| .. | .. |
|---|
| 46 | 46 | |
|---|
| 47 | 47 | void __iomem *mips_gic_base; |
|---|
| 48 | 48 | |
|---|
| 49 | | -DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks); |
|---|
| 49 | +static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks); |
|---|
| 50 | 50 | |
|---|
| 51 | 51 | static DEFINE_SPINLOCK(gic_lock); |
|---|
| 52 | 52 | static struct irq_domain *gic_irq_domain; |
|---|
| 53 | | -static struct irq_domain *gic_ipi_domain; |
|---|
| 54 | 53 | static int gic_shared_intrs; |
|---|
| 55 | 54 | static unsigned int gic_cpu_pin; |
|---|
| 56 | 55 | static unsigned int timer_cpu_pin; |
|---|
| 57 | 56 | static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; |
|---|
| 57 | + |
|---|
| 58 | +#ifdef CONFIG_GENERIC_IRQ_IPI |
|---|
| 58 | 59 | static DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS); |
|---|
| 59 | 60 | static DECLARE_BITMAP(ipi_available, GIC_MAX_INTRS); |
|---|
| 61 | +#endif /* CONFIG_GENERIC_IRQ_IPI */ |
|---|
| 60 | 62 | |
|---|
| 61 | 63 | static struct gic_all_vpes_chip_data { |
|---|
| 62 | 64 | u32 map; |
|---|
| .. | .. |
|---|
| 459 | 461 | u32 map; |
|---|
| 460 | 462 | |
|---|
| 461 | 463 | if (hwirq >= GIC_SHARED_HWIRQ_BASE) { |
|---|
| 464 | +#ifdef CONFIG_GENERIC_IRQ_IPI |
|---|
| 462 | 465 | /* verify that shared irqs don't conflict with an IPI irq */ |
|---|
| 463 | 466 | if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) |
|---|
| 464 | 467 | return -EBUSY; |
|---|
| 468 | +#endif /* CONFIG_GENERIC_IRQ_IPI */ |
|---|
| 465 | 469 | |
|---|
| 466 | 470 | err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, |
|---|
| 467 | 471 | &gic_level_irq_controller, |
|---|
| .. | .. |
|---|
| 480 | 484 | case GIC_LOCAL_INT_TIMER: |
|---|
| 481 | 485 | /* CONFIG_MIPS_CMP workaround (see __gic_init) */ |
|---|
| 482 | 486 | map = GIC_MAP_PIN_MAP_TO_PIN | timer_cpu_pin; |
|---|
| 483 | | - /* fall-through */ |
|---|
| 487 | + fallthrough; |
|---|
| 484 | 488 | case GIC_LOCAL_INT_PERFCTR: |
|---|
| 485 | 489 | case GIC_LOCAL_INT_FDC: |
|---|
| 486 | 490 | /* |
|---|
| .. | .. |
|---|
| 550 | 554 | .map = gic_irq_domain_map, |
|---|
| 551 | 555 | }; |
|---|
| 552 | 556 | |
|---|
| 557 | +#ifdef CONFIG_GENERIC_IRQ_IPI |
|---|
| 558 | + |
|---|
| 553 | 559 | static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, |
|---|
| 554 | 560 | const u32 *intspec, unsigned int intsize, |
|---|
| 555 | 561 | irq_hw_number_t *out_hwirq, |
|---|
| .. | .. |
|---|
| 617 | 623 | return ret; |
|---|
| 618 | 624 | } |
|---|
| 619 | 625 | |
|---|
| 620 | | -void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, |
|---|
| 621 | | - unsigned int nr_irqs) |
|---|
| 626 | +static void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, |
|---|
| 627 | + unsigned int nr_irqs) |
|---|
| 622 | 628 | { |
|---|
| 623 | 629 | irq_hw_number_t base_hwirq; |
|---|
| 624 | 630 | struct irq_data *data; |
|---|
| .. | .. |
|---|
| 631 | 637 | bitmap_set(ipi_available, base_hwirq, nr_irqs); |
|---|
| 632 | 638 | } |
|---|
| 633 | 639 | |
|---|
| 634 | | -int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, |
|---|
| 635 | | - enum irq_domain_bus_token bus_token) |
|---|
| 640 | +static int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, |
|---|
| 641 | + enum irq_domain_bus_token bus_token) |
|---|
| 636 | 642 | { |
|---|
| 637 | 643 | bool is_ipi; |
|---|
| 638 | 644 | |
|---|
| .. | .. |
|---|
| 653 | 659 | .match = gic_ipi_domain_match, |
|---|
| 654 | 660 | }; |
|---|
| 655 | 661 | |
|---|
| 662 | +static int gic_register_ipi_domain(struct device_node *node) |
|---|
| 663 | +{ |
|---|
| 664 | + struct irq_domain *gic_ipi_domain; |
|---|
| 665 | + unsigned int v[2], num_ipis; |
|---|
| 666 | + |
|---|
| 667 | + gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, |
|---|
| 668 | + IRQ_DOMAIN_FLAG_IPI_PER_CPU, |
|---|
| 669 | + GIC_NUM_LOCAL_INTRS + gic_shared_intrs, |
|---|
| 670 | + node, &gic_ipi_domain_ops, NULL); |
|---|
| 671 | + if (!gic_ipi_domain) { |
|---|
| 672 | + pr_err("Failed to add IPI domain"); |
|---|
| 673 | + return -ENXIO; |
|---|
| 674 | + } |
|---|
| 675 | + |
|---|
| 676 | + irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); |
|---|
| 677 | + |
|---|
| 678 | + if (node && |
|---|
| 679 | + !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { |
|---|
| 680 | + bitmap_set(ipi_resrv, v[0], v[1]); |
|---|
| 681 | + } else { |
|---|
| 682 | + /* |
|---|
| 683 | + * Reserve 2 interrupts per possible CPU/VP for use as IPIs, |
|---|
| 684 | + * meeting the requirements of arch/mips SMP. |
|---|
| 685 | + */ |
|---|
| 686 | + num_ipis = 2 * num_possible_cpus(); |
|---|
| 687 | + bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); |
|---|
| 688 | + } |
|---|
| 689 | + |
|---|
| 690 | + bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); |
|---|
| 691 | + |
|---|
| 692 | + return 0; |
|---|
| 693 | +} |
|---|
| 694 | + |
|---|
| 695 | +#else /* !CONFIG_GENERIC_IRQ_IPI */ |
|---|
| 696 | + |
|---|
| 697 | +static inline int gic_register_ipi_domain(struct device_node *node) |
|---|
| 698 | +{ |
|---|
| 699 | + return 0; |
|---|
| 700 | +} |
|---|
| 701 | + |
|---|
| 702 | +#endif /* !CONFIG_GENERIC_IRQ_IPI */ |
|---|
| 703 | + |
|---|
| 656 | 704 | static int gic_cpu_startup(unsigned int cpu) |
|---|
| 657 | 705 | { |
|---|
| 658 | 706 | /* Enable or disable EIC */ |
|---|
| .. | .. |
|---|
| 671 | 719 | static int __init gic_of_init(struct device_node *node, |
|---|
| 672 | 720 | struct device_node *parent) |
|---|
| 673 | 721 | { |
|---|
| 674 | | - unsigned int cpu_vec, i, gicconfig, v[2], num_ipis; |
|---|
| 722 | + unsigned int cpu_vec, i, gicconfig; |
|---|
| 675 | 723 | unsigned long reserved; |
|---|
| 676 | 724 | phys_addr_t gic_base; |
|---|
| 677 | 725 | struct resource res; |
|---|
| 678 | 726 | size_t gic_len; |
|---|
| 727 | + int ret; |
|---|
| 679 | 728 | |
|---|
| 680 | 729 | /* Find the first available CPU vector. */ |
|---|
| 681 | 730 | i = 0; |
|---|
| .. | .. |
|---|
| 716 | 765 | __sync(); |
|---|
| 717 | 766 | } |
|---|
| 718 | 767 | |
|---|
| 719 | | - mips_gic_base = ioremap_nocache(gic_base, gic_len); |
|---|
| 768 | + mips_gic_base = ioremap(gic_base, gic_len); |
|---|
| 769 | + if (!mips_gic_base) { |
|---|
| 770 | + pr_err("Failed to ioremap gic_base\n"); |
|---|
| 771 | + return -ENOMEM; |
|---|
| 772 | + } |
|---|
| 720 | 773 | |
|---|
| 721 | 774 | gicconfig = read_gic_config(); |
|---|
| 722 | 775 | gic_shared_intrs = gicconfig & GIC_CONFIG_NUMINTERRUPTS; |
|---|
| .. | .. |
|---|
| 764 | 817 | return -ENXIO; |
|---|
| 765 | 818 | } |
|---|
| 766 | 819 | |
|---|
| 767 | | - gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, |
|---|
| 768 | | - IRQ_DOMAIN_FLAG_IPI_PER_CPU, |
|---|
| 769 | | - GIC_NUM_LOCAL_INTRS + gic_shared_intrs, |
|---|
| 770 | | - node, &gic_ipi_domain_ops, NULL); |
|---|
| 771 | | - if (!gic_ipi_domain) { |
|---|
| 772 | | - pr_err("Failed to add IPI domain"); |
|---|
| 773 | | - return -ENXIO; |
|---|
| 774 | | - } |
|---|
| 775 | | - |
|---|
| 776 | | - irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); |
|---|
| 777 | | - |
|---|
| 778 | | - if (node && |
|---|
| 779 | | - !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { |
|---|
| 780 | | - bitmap_set(ipi_resrv, v[0], v[1]); |
|---|
| 781 | | - } else { |
|---|
| 782 | | - /* |
|---|
| 783 | | - * Reserve 2 interrupts per possible CPU/VP for use as IPIs, |
|---|
| 784 | | - * meeting the requirements of arch/mips SMP. |
|---|
| 785 | | - */ |
|---|
| 786 | | - num_ipis = 2 * num_possible_cpus(); |
|---|
| 787 | | - bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); |
|---|
| 788 | | - } |
|---|
| 789 | | - |
|---|
| 790 | | - bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); |
|---|
| 820 | + ret = gic_register_ipi_domain(node); |
|---|
| 821 | + if (ret) |
|---|
| 822 | + return ret; |
|---|
| 791 | 823 | |
|---|
| 792 | 824 | board_bind_eic_interrupt = &gic_bind_eic_interrupt; |
|---|
| 793 | 825 | |
|---|