Pull irq updates from Thomas Gleixner: "The usual boring updates from the interrupt subsystem: - Infrastructure to allow building irqchip drivers as modules - Consolidation of irqchip ACPI probing - Removal of the EOI-preflow interrupt handler which was required for SPARC support and became obsolete after SPARC was converted to use sparse interrupts. - Cleanups, fixes and improvements all over the place" * tag 'irq-core-2020-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (51 commits) irqchip/loongson-pch-pic: Fix the misused irq flow handler irqchip/loongson-htvec: Support 8 groups of HT vectors irqchip/loongson-liointc: Fix misuse of gc->mask_cache dt-bindings: interrupt-controller: Update Loongson HTVEC description irqchip/imx-intmux: Fix irqdata regs save in imx_intmux_runtime_suspend() irqchip/imx-intmux: Implement intmux runtime power management irqchip/gic-v4.1: Use GFP_ATOMIC flag in allocate_vpe_l1_table() irqchip: Fix IRQCHIP_PLATFORM_DRIVER_* compilation by including module.h irqchip/stm32-exti: Map direct event to irq parent irqchip/mtk-cirq: Convert to a platform driver irqchip/mtk-sysirq: Convert to a platform driver irqchip/qcom-pdc: Switch to using IRQCHIP_PLATFORM_DRIVER helper macros irqchip: Add IRQCHIP_PLATFORM_DRIVER_BEGIN/END and IRQCHIP_MATCH helper macros irqchip: irq-bcm2836.h: drop a duplicated word irqchip/gic-v4.1: Ensure accessing the correct RD when writing INVALLR irqchip/irq-bcm7038-l1: Guard uses of cpu_logical_map irqchip/gic-v3: Remove unused register definition irqchip/qcom-pdc: Allow QCOM_PDC to be loadable as a permanent module genirq: Export irq_chip_retrigger_hierarchy and irq_chip_set_vcpu_affinity_parent irqdomain: Export irq_domain_update_bus_token ...
Unified · Split
| @@ -2,7 +2,10 @@ Broadcom Generic Level 2 Interrupt Controller · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | Required properties: | 3 | Required properties: |
| 4 | 4 | ||
| 5 | - compatible: should be "brcm,l2-intc" for latched interrupt controllers | 5 | - compatible: should be one of: |
| 6 | "brcm,hif-spi-l2-intc" or | ||
| 7 | "brcm,upg-aux-aon-l2-intc" or | ||
| 8 | "brcm,l2-intc" for latched interrupt controllers | ||
| 6 | should be "brcm,bcm7271-l2-intc" for level interrupt controllers | 9 | should be "brcm,bcm7271-l2-intc" for level interrupt controllers |
| 7 | - reg: specifies the base physical address and size of the registers | 10 | - reg: specifies the base physical address and size of the registers |
| 8 | - interrupt-controller: identifies the node as an interrupt controller | 11 | - interrupt-controller: identifies the node as an interrupt controller |
| @@ -22,8 +22,8 @@ properties: · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | interrupts: | 23 | interrupts: |
| 24 | minItems: 1 | 24 | minItems: 1 |
| 25 | maxItems: 4 | 25 | maxItems: 8 |
| 26 | description: Four parent interrupts that receive chained interrupts. | 26 | description: Eight parent interrupts that receive chained interrupts. |
| 27 | 27 | ||
| 28 | interrupt-controller: true | 28 | interrupt-controller: true |
| 29 | 29 | ||
| @@ -81,7 +81,6 @@ config SPARC64 · 80 unmodified lines | |||
| 81 | select RTC_DRV_STARFIRE | 81 | select RTC_DRV_STARFIRE |
| 82 | select HAVE_PERF_EVENTS | 82 | select HAVE_PERF_EVENTS |
| 83 | select PERF_USE_VMALLOC | 83 | select PERF_USE_VMALLOC |
| 84 | select IRQ_PREFLOW_FASTEOI | ||
| 85 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 84 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
| 86 | select HAVE_C_RECORDMCOUNT | 85 | select HAVE_C_RECORDMCOUNT |
| 87 | select HAVE_ARCH_AUDITSYSCALL | 86 | select HAVE_ARCH_AUDITSYSCALL |
| @@ -425,7 +425,7 @@ config GOLDFISH_PIC · 424 unmodified lines | |||
| 425 | for Goldfish based virtual platforms. | 425 | for Goldfish based virtual platforms. |
| 426 | 426 | ||
| 427 | config QCOM_PDC | 427 | config QCOM_PDC |
| 428 | bool "QCOM PDC" | 428 | tristate "QCOM PDC" |
| 429 | depends on ARCH_QCOM | 429 | depends on ARCH_QCOM |
| 430 | select IRQ_DOMAIN_HIERARCHY | 430 | select IRQ_DOMAIN_HIERARCHY |
| 431 | help | 431 | help |
| @@ -541,7 +541,6 @@ config LOONGSON_HTPIC · 109 unmodified lines | |||
| 541 | default y | 541 | default y |
| 542 | select IRQ_DOMAIN | 542 | select IRQ_DOMAIN |
| 543 | select GENERIC_IRQ_CHIP | 543 | select GENERIC_IRQ_CHIP |
| 544 | select I8259 | ||
| 545 | help | 544 | help |
| 546 | Support for the Loongson-3 HyperTransport PIC Controller. | 545 | Support for the Loongson-3 HyperTransport PIC Controller. |
| 547 | 546 | ||
| @@ -92,7 +92,7 @@ static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq, · 91 unmodified lines | |||
| 92 | return 0; | 92 | return 0; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | static struct irq_domain_ops ativic32_ops = { | 95 | static const struct irq_domain_ops ativic32_ops = { |
| 96 | .map = ativic32_irq_domain_map, | 96 | .map = ativic32_irq_domain_map, |
| 97 | .xlate = irq_domain_xlate_onecell | 97 | .xlate = irq_domain_xlate_onecell |
| 98 | }; | 98 | }; |
| @@ -310,10 +310,16 @@ static void __init sama5d3_aic_irq_fixup(void) · 309 unmodified lines | |||
| 310 | aic_common_rtc_irq_fixup(); | 310 | aic_common_rtc_irq_fixup(); |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static void __init sam9x60_aic_irq_fixup(void) | ||
| 314 | { | ||
| 315 | aic_common_rtc_irq_fixup(); | ||
| 316 | aic_common_rtt_irq_fixup(); | ||
| 317 | } | ||
| 318 | |||
| 313 | static const struct of_device_id aic5_irq_fixups[] __initconst = { | 319 | static const struct of_device_id aic5_irq_fixups[] __initconst = { |
| 314 | { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup }, | 320 | { .compatible = "atmel,sama5d3", .data = sama5d3_aic_irq_fixup }, |
| 315 | { .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup }, | 321 | { .compatible = "atmel,sama5d4", .data = sama5d3_aic_irq_fixup }, |
| 316 | { .compatible = "microchip,sam9x60", .data = sama5d3_aic_irq_fixup }, | 322 | { .compatible = "microchip,sam9x60", .data = sam9x60_aic_irq_fixup }, |
| 317 | { /* sentinel */ }, | 323 | { /* sentinel */ }, |
| 318 | }; | 324 | }; |
| 319 | 325 | ||
| @@ -28,6 +28,9 @@ · 27 unmodified lines | |||
| 28 | #include <linux/irqchip.h> | 28 | #include <linux/irqchip.h> |
| 29 | #include <linux/irqchip/chained_irq.h> | 29 | #include <linux/irqchip/chained_irq.h> |
| 30 | #include <linux/syscore_ops.h> | 30 | #include <linux/syscore_ops.h> |
| 31 | #ifdef CONFIG_ARM | ||
| 32 | #include <asm/smp_plat.h> | ||
| 33 | #endif | ||
| 31 | 34 | ||
| 32 | #define IRQS_PER_WORD 32 | 35 | #define IRQS_PER_WORD 32 |
| 33 | #define REG_BYTES_PER_IRQ_WORD (sizeof(u32) * 4) | 36 | #define REG_BYTES_PER_IRQ_WORD (sizeof(u32) * 4) |
| @@ -327,7 +330,11 @@ static int bcm7038_l1_suspend(void) · 293 unmodified lines | |||
| 327 | u32 val; | 330 | u32 val; |
| 328 | 331 | ||
| 329 | /* Wakeup interrupt should only come from the boot cpu */ | 332 | /* Wakeup interrupt should only come from the boot cpu */ |
| 333 | #ifdef CONFIG_SMP | ||
| 330 | boot_cpu = cpu_logical_map(0); | 334 | boot_cpu = cpu_logical_map(0); |
| 335 | #else | ||
| 336 | boot_cpu = 0; | ||
| 337 | #endif | ||
| 331 | 338 | ||
| 332 | list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) { | 339 | list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) { |
| 333 | for (word = 0; word < intc->n_words; word++) { | 340 | for (word = 0; word < intc->n_words; word++) { |
| @@ -347,7 +354,11 @@ static void bcm7038_l1_resume(void) · 13 unmodified lines | |||
| 347 | struct bcm7038_l1_chip *intc; | 354 | struct bcm7038_l1_chip *intc; |
| 348 | int boot_cpu, word; | 355 | int boot_cpu, word; |
| 349 | 356 | ||
| 357 | #ifdef CONFIG_SMP | ||
| 350 | boot_cpu = cpu_logical_map(0); | 358 | boot_cpu = cpu_logical_map(0); |
| 359 | #else | ||
| 360 | boot_cpu = 0; | ||
| 361 | #endif | ||
| 351 | 362 | ||
| 352 | list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) { | 363 | list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) { |
| 353 | for (word = 0; word < intc->n_words; word++) { | 364 | for (word = 0; word < intc->n_words; word++) { |
| @@ -143,6 +143,9 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn, · 142 unmodified lines | |||
| 143 | 143 | ||
| 144 | irq_set_chained_handler_and_data(parent_irq, | 144 | irq_set_chained_handler_and_data(parent_irq, |
| 145 | bcm7120_l2_intc_irq_handle, l1_data); | 145 | bcm7120_l2_intc_irq_handle, l1_data); |
| 146 | if (data->can_wake) | ||
| 147 | enable_irq_wake(parent_irq); | ||
| 148 | |||
| 146 | return 0; | 149 | return 0; |
| 147 | } | 150 | } |
| 148 | 151 | ||
| @@ -247,6 +250,8 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, · 98 unmodified lines | |||
| 247 | if (ret < 0) | 250 | if (ret < 0) |
| 248 | goto out_free_l1_data; | 251 | goto out_free_l1_data; |
| 249 | 252 | ||
| 253 | data->can_wake = of_property_read_bool(dn, "brcm,irq-can-wake"); | ||
| 254 | |||
| 250 | for (irq = 0; irq < data->num_parent_irqs; irq++) { | 255 | for (irq = 0; irq < data->num_parent_irqs; irq++) { |
| 251 | ret = bcm7120_l2_intc_init_one(dn, data, irq, valid_mask); | 256 | ret = bcm7120_l2_intc_init_one(dn, data, irq, valid_mask); |
| 252 | if (ret) | 257 | if (ret) |
| @@ -274,9 +279,6 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, · 21 unmodified lines | |||
| 274 | goto out_free_domain; | 279 | goto out_free_domain; |
| 275 | } | 280 | } |
| 276 | 281 | ||
| 277 | if (of_property_read_bool(dn, "brcm,irq-can-wake")) | ||
| 278 | data->can_wake = true; | ||
| 279 | |||
| 280 | for (idx = 0; idx < data->n_words; idx++) { | 282 | for (idx = 0; idx < data->n_words; idx++) { |
| 281 | irq = idx * IRQS_PER_WORD; | 283 | irq = idx * IRQS_PER_WORD; |
| 282 | gc = irq_get_domain_generic_chip(data->domain, irq); | 284 | gc = irq_get_domain_generic_chip(data->domain, irq); |
| @@ -254,6 +254,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, · 253 unmodified lines | |||
| 254 | */ | 254 | */ |
| 255 | data->gc->wake_enabled = 0xffffffff; | 255 | data->gc->wake_enabled = 0xffffffff; |
| 256 | ct->chip.irq_set_wake = irq_gc_set_wake; | 256 | ct->chip.irq_set_wake = irq_gc_set_wake; |
| 257 | enable_irq_wake(parent_irq); | ||
| 257 | } | 258 | } |
| 258 | 259 | ||
| 259 | pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq); | 260 | pr_info("registered L2 intc (%pOF, parent irq: %d)\n", np, parent_irq); |
| @@ -275,6 +276,10 @@ static int __init brcmstb_l2_edge_intc_of_init(struct device_node *np, · 15 unmodified lines | |||
| 275 | return brcmstb_l2_intc_of_init(np, parent, &l2_edge_intc_init); | 276 | return brcmstb_l2_intc_of_init(np, parent, &l2_edge_intc_init); |
| 276 | } | 277 | } |
| 277 | IRQCHIP_DECLARE(brcmstb_l2_intc, "brcm,l2-intc", brcmstb_l2_edge_intc_of_init); | 278 | IRQCHIP_DECLARE(brcmstb_l2_intc, "brcm,l2-intc", brcmstb_l2_edge_intc_of_init); |
| 279 | IRQCHIP_DECLARE(brcmstb_hif_spi_l2_intc, "brcm,hif-spi-l2-intc", | ||
| 280 | brcmstb_l2_edge_intc_of_init); | ||
| 281 | IRQCHIP_DECLARE(brcmstb_upg_aux_aon_l2_intc, "brcm,upg-aux-aon-l2-intc", | ||
| 282 | brcmstb_l2_edge_intc_of_init); | ||
| 278 | 283 | ||
| 279 | static int __init brcmstb_l2_lvl_intc_of_init(struct device_node *np, | 284 | static int __init brcmstb_l2_lvl_intc_of_init(struct device_node *np, |
| 280 | struct device_node *parent) | 285 | struct device_node *parent) |
| @@ -2814,7 +2814,7 @@ static int allocate_vpe_l1_table(void) · 2813 unmodified lines | |||
| 2814 | if (val & GICR_VPROPBASER_4_1_VALID) | 2814 | if (val & GICR_VPROPBASER_4_1_VALID) |
| 2815 | goto out; | 2815 | goto out; |
| 2816 | 2816 | ||
| 2817 | gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_KERNEL); | 2817 | gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_ATOMIC); |
| 2818 | if (!gic_data_rdist()->vpe_table_mask) | 2818 | if (!gic_data_rdist()->vpe_table_mask) |
| 2819 | return -ENOMEM; | 2819 | return -ENOMEM; |
| 2820 | 2820 | ||
| @@ -2881,7 +2881,7 @@ static int allocate_vpe_l1_table(void) · 60 unmodified lines | |||
| 2881 | 2881 | ||
| 2882 | pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n", | 2882 | pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n", |
| 2883 | np, npg, psz, epp, esz); | 2883 | np, npg, psz, epp, esz); |
| 2884 | page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(np * PAGE_SIZE)); | 2884 | page = alloc_pages(GFP_ATOMIC | __GFP_ZERO, get_order(np * PAGE_SIZE)); |
| 2885 | if (!page) | 2885 | if (!page) |
| 2886 | return -ENOMEM; | 2886 | return -ENOMEM; |
| 2887 | 2887 | ||
| @@ -4090,18 +4090,22 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe, · 1202 unmodified lines | |||
| 4090 | static void its_vpe_4_1_invall(struct its_vpe *vpe) | 4090 | static void its_vpe_4_1_invall(struct its_vpe *vpe) |
| 4091 | { | 4091 | { |
| 4092 | void __iomem *rdbase; | 4092 | void __iomem *rdbase; |
| 4093 | unsigned long flags; | ||
| 4093 | u64 val; | 4094 | u64 val; |
| 4095 | int cpu; | ||
| 4094 | 4096 | ||
| 4095 | val = GICR_INVALLR_V; | 4097 | val = GICR_INVALLR_V; |
| 4096 | val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id); | 4098 | val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id); |
| 4097 | 4099 | ||
| 4098 | /* Target the redistributor this vPE is currently known on */ | 4100 | /* Target the redistributor this vPE is currently known on */ |
| 4099 | raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock); | 4101 | cpu = vpe_to_cpuid_lock(vpe, &flags); |
| 4100 | rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base; | 4102 | raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock); |
| 4103 | rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base; | ||
| 4101 | gic_write_lpir(val, rdbase + GICR_INVALLR); | 4104 | gic_write_lpir(val, rdbase + GICR_INVALLR); |
| 4102 | 4105 | ||
| 4103 | wait_for_syncr(rdbase); | 4106 | wait_for_syncr(rdbase); |
| 4104 | raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock); | 4107 | raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock); |
| 4108 | vpe_to_cpuid_unlock(vpe, flags); | ||
| 4105 | } | 4109 | } |
| 4106 | 4110 | ||
| 4107 | static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) | 4111 | static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info) |
| @@ -2116,7 +2116,7 @@ static void __init gic_acpi_setup_kvm_info(void) · 2115 unmodified lines | |||
| 2116 | } | 2116 | } |
| 2117 | 2117 | ||
| 2118 | static int __init | 2118 | static int __init |
| 2119 | gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end) | 2119 | gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end) |
| 2120 | { | 2120 | { |
| 2121 | struct acpi_madt_generic_distributor *dist; | 2121 | struct acpi_madt_generic_distributor *dist; |
| 2122 | struct fwnode_handle *domain_handle; | 2122 | struct fwnode_handle *domain_handle; |
| @@ -1584,7 +1584,7 @@ static void __init gic_acpi_setup_kvm_info(void) · 1583 unmodified lines | |||
| 1584 | gic_set_kvm_info(&gic_v2_kvm_info); | 1584 | gic_set_kvm_info(&gic_v2_kvm_info); |
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | static int __init gic_v2_acpi_init(struct acpi_subtable_header *header, | 1587 | static int __init gic_v2_acpi_init(union acpi_subtable_headers *header, |
| 1588 | const unsigned long end) | 1588 | const unsigned long end) |
| 1589 | { | 1589 | { |
| 1590 | struct acpi_madt_generic_distributor *dist; | 1590 | struct acpi_madt_generic_distributor *dist; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | |||
| 53 | #include <linux/of_irq.h> | 53 | #include <linux/of_irq.h> |
| 54 | #include <linux/of_platform.h> | 54 | #include <linux/of_platform.h> |
| 55 | #include <linux/spinlock.h> | 55 | #include <linux/spinlock.h> |
| 56 | #include <linux/pm_runtime.h> | ||
| 56 | 57 | ||
| 57 | #define CHANIER(n) (0x10 + (0x40 * n)) | 58 | #define CHANIER(n) (0x10 + (0x40 * n)) |
| 58 | #define CHANIPR(n) (0x20 + (0x40 * n)) | 59 | #define CHANIPR(n) (0x20 + (0x40 * n)) |
| @@ -60,6 +61,8 @@ · 1 unmodified line | |||
| 60 | #define CHAN_MAX_NUM 0x8 | 61 | #define CHAN_MAX_NUM 0x8 |
| 61 | 62 | ||
| 62 | struct intmux_irqchip_data { | 63 | struct intmux_irqchip_data { |
| 64 | struct irq_chip chip; | ||
| 65 | u32 saved_reg; | ||
| 63 | int chanidx; | 66 | int chanidx; |
| 64 | int irq; | 67 | int irq; |
| 65 | struct irq_domain *domain; | 68 | struct irq_domain *domain; |
| @@ -120,8 +123,10 @@ static struct irq_chip imx_intmux_irq_chip = { · 54 unmodified lines | |||
| 120 | static int imx_intmux_irq_map(struct irq_domain *h, unsigned int irq, | 123 | static int imx_intmux_irq_map(struct irq_domain *h, unsigned int irq, |
| 121 | irq_hw_number_t hwirq) | 124 | irq_hw_number_t hwirq) |
| 122 | { | 125 | { |
| 123 | irq_set_chip_data(irq, h->host_data); | 126 | struct intmux_irqchip_data *data = h->host_data; |
| 124 | irq_set_chip_and_handler(irq, &imx_intmux_irq_chip, handle_level_irq); | 127 | |
| 128 | irq_set_chip_data(irq, data); | ||
| 129 | irq_set_chip_and_handler(irq, &data->chip, handle_level_irq); | ||
| 125 | 130 | ||
| 126 | return 0; | 131 | return 0; |
| 127 | } | 132 | } |
| @@ -210,8 +215,7 @@ static int imx_intmux_probe(struct platform_device *pdev) · 82 unmodified lines | |||
| 210 | return -EINVAL; | 215 | return -EINVAL; |
| 211 | } | 216 | } |
| 212 | 217 | ||
| 213 | data = devm_kzalloc(&pdev->dev, sizeof(*data) + | 218 | data = devm_kzalloc(&pdev->dev, struct_size(data, irqchip_data, channum), GFP_KERNEL); |
| 214 | channum * sizeof(data->irqchip_data[0]), GFP_KERNEL); | ||
| 215 | if (!data) | 219 | if (!data) |
| 216 | return -ENOMEM; | 220 | return -ENOMEM; |
| 217 | 221 | ||
| @@ -232,6 +236,10 @@ static int imx_intmux_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 232 | data->channum = channum; | 236 | data->channum = channum; |
| 233 | raw_spin_lock_init(&data->lock); | 237 | raw_spin_lock_init(&data->lock); |
| 234 | 238 | ||
| 239 | pm_runtime_get_noresume(&pdev->dev); | ||
| 240 | pm_runtime_set_active(&pdev->dev); | ||
| 241 | pm_runtime_enable(&pdev->dev); | ||
| 242 | |||
| 235 | ret = clk_prepare_enable(data->ipg_clk); | 243 | ret = clk_prepare_enable(data->ipg_clk); |
| 236 | if (ret) { | 244 | if (ret) { |
| 237 | dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret); | 245 | dev_err(&pdev->dev, "failed to enable ipg clk: %d\n", ret); |
| @@ -239,6 +247,8 @@ static int imx_intmux_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 239 | } | 247 | } |
| 240 | 248 | ||
| 241 | for (i = 0; i < channum; i++) { | 249 | for (i = 0; i < channum; i++) { |
| 250 | data->irqchip_data[i].chip = imx_intmux_irq_chip; | ||
| 251 | data->irqchip_data[i].chip.parent_device = &pdev->dev; | ||
| 242 | data->irqchip_data[i].chanidx = i; | 252 | data->irqchip_data[i].chanidx = i; |
| 243 | 253 | ||
| 244 | data->irqchip_data[i].irq = irq_of_parse_and_map(np, i); | 254 | data->irqchip_data[i].irq = irq_of_parse_and_map(np, i); |
| @@ -267,6 +277,12 @@ static int imx_intmux_probe(struct platform_device *pdev) · 22 unmodified lines | |||
| 267 | 277 | ||
| 268 | platform_set_drvdata(pdev, data); | 278 | platform_set_drvdata(pdev, data); |
| 269 | 279 | ||
| 280 | /* | ||
| 281 | * Let pm_runtime_put() disable clock. | ||
| 282 | * If CONFIG_PM is not enabled, the clock will stay powered. | ||
| 283 | */ | ||
| 284 | pm_runtime_put(&pdev->dev); | ||
| 285 | |||
| 270 | return 0; | 286 | return 0; |
| 271 | out: | 287 | out: |
| 272 | clk_disable_unprepare(data->ipg_clk); | 288 | clk_disable_unprepare(data->ipg_clk); |
| @@ -288,11 +304,56 @@ static int imx_intmux_remove(struct platform_device *pdev) · 15 unmodified lines | |||
| 288 | irq_domain_remove(data->irqchip_data[i].domain); | 304 | irq_domain_remove(data->irqchip_data[i].domain); |
| 289 | } | 305 | } |
| 290 | 306 | ||
| 307 | pm_runtime_disable(&pdev->dev); | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | #ifdef CONFIG_PM | ||
| 313 | static int imx_intmux_runtime_suspend(struct device *dev) | ||
| 314 | { | ||
| 315 | struct intmux_data *data = dev_get_drvdata(dev); | ||
| 316 | struct intmux_irqchip_data *irqchip_data; | ||
| 317 | int i; | ||
| 318 | |||
| 319 | for (i = 0; i < data->channum; i++) { | ||
| 320 | irqchip_data = &data->irqchip_data[i]; | ||
| 321 | irqchip_data->saved_reg = readl_relaxed(data->regs + CHANIER(i)); | ||
| 322 | } | ||
| 323 | |||
| 291 | clk_disable_unprepare(data->ipg_clk); | 324 | clk_disable_unprepare(data->ipg_clk); |
| 292 | 325 | ||
| 293 | return 0; | 326 | return 0; |
| 294 | } | 327 | } |
| 295 | 328 | ||
| 329 | static int imx_intmux_runtime_resume(struct device *dev) | ||
| 330 | { | ||
| 331 | struct intmux_data *data = dev_get_drvdata(dev); | ||
| 332 | struct intmux_irqchip_data *irqchip_data; | ||
| 333 | int ret, i; | ||
| 334 | |||
| 335 | ret = clk_prepare_enable(data->ipg_clk); | ||
| 336 | if (ret) { | ||
| 337 | dev_err(dev, "failed to enable ipg clk: %d\n", ret); | ||
| 338 | return ret; | ||
| 339 | } | ||
| 340 | |||
| 341 | for (i = 0; i < data->channum; i++) { | ||
| 342 | irqchip_data = &data->irqchip_data[i]; | ||
| 343 | writel_relaxed(irqchip_data->saved_reg, data->regs + CHANIER(i)); | ||
| 344 | } | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | #endif | ||
| 349 | |||
| 350 | static const struct dev_pm_ops imx_intmux_pm_ops = { | ||
| 351 | SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | ||
| 352 | pm_runtime_force_resume) | ||
| 353 | SET_RUNTIME_PM_OPS(imx_intmux_runtime_suspend, | ||
| 354 | imx_intmux_runtime_resume, NULL) | ||
| 355 | }; | ||
| 356 | |||
| 296 | static const struct of_device_id imx_intmux_id[] = { | 357 | static const struct of_device_id imx_intmux_id[] = { |
| 297 | { .compatible = "fsl,imx-intmux", }, | 358 | { .compatible = "fsl,imx-intmux", }, |
| 298 | { /* sentinel */ }, | 359 | { /* sentinel */ }, |
| @@ -302,6 +363,7 @@ static struct platform_driver imx_intmux_driver = { · 3 unmodified lines | |||
| 302 | .driver = { | 363 | .driver = { |
| 303 | .name = "imx-intmux", | 364 | .name = "imx-intmux", |
| 304 | .of_match_table = imx_intmux_id, | 365 | .of_match_table = imx_intmux_id, |
| 366 | .pm = &imx_intmux_pm_ops, | ||
| 305 | }, | 367 | }, |
| 306 | .probe = imx_intmux_probe, | 368 | .probe = imx_intmux_probe, |
| 307 | .remove = imx_intmux_remove, | 369 | .remove = imx_intmux_remove, |
| @@ -93,10 +93,8 @@ int __init htpic_of_init(struct device_node *node, struct device_node *parent) · 92 unmodified lines | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | htpic = kzalloc(sizeof(*htpic), GFP_KERNEL); | 95 | htpic = kzalloc(sizeof(*htpic), GFP_KERNEL); |
| 96 | if (!htpic) { | 96 | if (!htpic) |
| 97 | err = -ENOMEM; | 97 | return -ENOMEM; |
| 98 | goto out_free; | ||
| 99 | } | ||
| 100 | 98 | ||
| 101 | htpic->base = of_iomap(node, 0); | 99 | htpic->base = of_iomap(node, 0); |
| 102 | if (!htpic->base) { | 100 | if (!htpic->base) { |
| @@ -19,15 +19,14 @@ · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | /* Registers */ | 20 | /* Registers */ |
| 21 | #define HTVEC_EN_OFF 0x20 | 21 | #define HTVEC_EN_OFF 0x20 |
| 22 | #define HTVEC_MAX_PARENT_IRQ 4 | 22 | #define HTVEC_MAX_PARENT_IRQ 8 |
| 23 | 23 | ||
| 24 | #define VEC_COUNT_PER_REG 32 | 24 | #define VEC_COUNT_PER_REG 32 |
| 25 | #define VEC_REG_COUNT 4 | ||
| 26 | #define VEC_COUNT (VEC_COUNT_PER_REG * VEC_REG_COUNT) | ||
| 27 | #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) | 25 | #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) |
| 28 | #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) | 26 | #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) |
| 29 | 27 | ||
| 30 | struct htvec { | 28 | struct htvec { |
| 29 | int num_parents; | ||
| 31 | void __iomem *base; | 30 | void __iomem *base; |
| 32 | struct irq_domain *htvec_domain; | 31 | struct irq_domain *htvec_domain; |
| 33 | raw_spinlock_t htvec_lock; | 32 | raw_spinlock_t htvec_lock; |
| @@ -43,7 +42,7 @@ static void htvec_irq_dispatch(struct irq_desc *desc) · 9 unmodified lines | |||
| 43 | 42 | ||
| 44 | chained_irq_enter(chip, desc); | 43 | chained_irq_enter(chip, desc); |
| 45 | 44 | ||
| 46 | for (i = 0; i < VEC_REG_COUNT; i++) { | 45 | for (i = 0; i < priv->num_parents; i++) { |
| 47 | pending = readl(priv->base + 4 * i); | 46 | pending = readl(priv->base + 4 * i); |
| 48 | while (pending) { | 47 | while (pending) { |
| 49 | int bit = __ffs(pending); | 48 | int bit = __ffs(pending); |
| @@ -109,11 +108,14 @@ static struct irq_chip htvec_irq_chip = { · 59 unmodified lines | |||
| 109 | static int htvec_domain_alloc(struct irq_domain *domain, unsigned int virq, | 108 | static int htvec_domain_alloc(struct irq_domain *domain, unsigned int virq, |
| 110 | unsigned int nr_irqs, void *arg) | 109 | unsigned int nr_irqs, void *arg) |
| 111 | { | 110 | { |
| 111 | int ret; | ||
| 112 | unsigned long hwirq; | 112 | unsigned long hwirq; |
| 113 | unsigned int type, i; | 113 | unsigned int type, i; |
| 114 | struct htvec *priv = domain->host_data; | 114 | struct htvec *priv = domain->host_data; |
| 115 | 115 | ||
| 116 | irq_domain_translate_onecell(domain, arg, &hwirq, &type); | 116 | ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type); |
| 117 | if (ret) | ||
| 118 | return ret; | ||
| 117 | 119 | ||
| 118 | for (i = 0; i < nr_irqs; i++) { | 120 | for (i = 0; i < nr_irqs; i++) { |
| 119 | irq_domain_set_info(domain, virq + i, hwirq + i, &htvec_irq_chip, | 121 | irq_domain_set_info(domain, virq + i, hwirq + i, &htvec_irq_chip, |
| @@ -147,7 +149,7 @@ static void htvec_reset(struct htvec *priv) · 27 unmodified lines | |||
| 147 | u32 idx; | 149 | u32 idx; |
| 148 | 150 | ||
| 149 | /* Clear IRQ cause registers, mask all interrupts */ | 151 | /* Clear IRQ cause registers, mask all interrupts */ |
| 150 | for (idx = 0; idx < VEC_REG_COUNT; idx++) { | 152 | for (idx = 0; idx < priv->num_parents; idx++) { |
| 151 | writel_relaxed(0x0, priv->base + HTVEC_EN_OFF + 4 * idx); | 153 | writel_relaxed(0x0, priv->base + HTVEC_EN_OFF + 4 * idx); |
| 152 | writel_relaxed(0xFFFFFFFF, priv->base); | 154 | writel_relaxed(0xFFFFFFFF, priv->base); |
| 153 | } | 155 | } |
| @@ -157,7 +159,7 @@ static int htvec_of_init(struct device_node *node, · 3 unmodified lines | |||
| 157 | struct device_node *parent) | 159 | struct device_node *parent) |
| 158 | { | 160 | { |
| 159 | struct htvec *priv; | 161 | struct htvec *priv; |
| 160 | int err, parent_irq[4], num_parents = 0, i; | 162 | int err, parent_irq[8], i; |
| 161 | 163 | ||
| 162 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 164 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 163 | if (!priv) | 165 | if (!priv) |
| @@ -176,33 +178,35 @@ static int htvec_of_init(struct device_node *node, · 12 unmodified lines | |||
| 176 | if (parent_irq[i] <= 0) | 178 | if (parent_irq[i] <= 0) |
| 177 | break; | 179 | break; |
| 178 | 180 | ||
| 179 | num_parents++; | 181 | priv->num_parents++; |
| 180 | } | 182 | } |
| 181 | 183 | ||
| 182 | if (!num_parents) { | 184 | if (!priv->num_parents) { |
| 183 | pr_err("Failed to get parent irqs\n"); | 185 | pr_err("Failed to get parent irqs\n"); |
| 184 | err = -ENODEV; | 186 | err = -ENODEV; |
| 185 | goto iounmap_base; | 187 | goto iounmap_base; |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 188 | priv->htvec_domain = irq_domain_create_linear(of_node_to_fwnode(node), | 190 | priv->htvec_domain = irq_domain_create_linear(of_node_to_fwnode(node), |
| 189 | VEC_COUNT, | 191 | (VEC_COUNT_PER_REG * priv->num_parents), |
| 190 | &htvec_domain_ops, | 192 | &htvec_domain_ops, priv); |
| 191 | priv); | ||
| 192 | if (!priv->htvec_domain) { | 193 | if (!priv->htvec_domain) { |
| 193 | pr_err("Failed to create IRQ domain\n"); | 194 | pr_err("Failed to create IRQ domain\n"); |
| 194 | err = -ENOMEM; | 195 | err = -ENOMEM; |
| 195 | goto iounmap_base; | 196 | goto irq_dispose; |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | htvec_reset(priv); | 199 | htvec_reset(priv); |
| 199 | 200 | ||
| 200 | for (i = 0; i < num_parents; i++) | 201 | for (i = 0; i < priv->num_parents; i++) |
| 201 | irq_set_chained_handler_and_data(parent_irq[i], | 202 | irq_set_chained_handler_and_data(parent_irq[i], |
| 202 | htvec_irq_dispatch, priv); | 203 | htvec_irq_dispatch, priv); |
| 203 | 204 | ||
| 204 | return 0; | 205 | return 0; |
| 205 | 206 | ||
| 207 | irq_dispose: | ||
| 208 | for (; i > 0; i--) | ||
| 209 | irq_dispose_mapping(parent_irq[i - 1]); | ||
| 206 | iounmap_base: | 210 | iounmap_base: |
| 207 | iounmap(priv->base); | 211 | iounmap(priv->base); |
| 208 | free_priv: | 212 | free_priv: |
| @@ -60,7 +60,7 @@ static void liointc_chained_handle_irq(struct irq_desc *desc) · 59 unmodified lines | |||
| 60 | if (!pending) { | 60 | if (!pending) { |
| 61 | /* Always blame LPC IRQ if we have that bug */ | 61 | /* Always blame LPC IRQ if we have that bug */ |
| 62 | if (handler->priv->has_lpc_irq_errata && | 62 | if (handler->priv->has_lpc_irq_errata && |
| 63 | (handler->parent_int_map & ~gc->mask_cache & | 63 | (handler->parent_int_map & gc->mask_cache & |
| 64 | BIT(LIOINTC_ERRATA_IRQ))) | 64 | BIT(LIOINTC_ERRATA_IRQ))) |
| 65 | pending = BIT(LIOINTC_ERRATA_IRQ); | 65 | pending = BIT(LIOINTC_ERRATA_IRQ); |
| 66 | else | 66 | else |
| @@ -114,6 +114,7 @@ static int liointc_set_type(struct irq_data *data, unsigned int type) · 47 unmodified lines | |||
| 114 | liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); | 114 | liointc_set_bit(gc, LIOINTC_REG_INTC_POL, mask, false); |
| 115 | break; | 115 | break; |
| 116 | default: | 116 | default: |
| 117 | irq_gc_unlock_irqrestore(gc, flags); | ||
| 117 | return -EINVAL; | 118 | return -EINVAL; |
| 118 | } | 119 | } |
| 119 | irq_gc_unlock_irqrestore(gc, flags); | 120 | irq_gc_unlock_irqrestore(gc, flags); |
| @@ -131,11 +132,11 @@ static void liointc_resume(struct irq_chip_generic *gc) · 11 unmodified lines | |||
| 131 | irq_gc_lock_irqsave(gc, flags); | 132 | irq_gc_lock_irqsave(gc, flags); |
| 132 | /* Disable all at first */ | 133 | /* Disable all at first */ |
| 133 | writel(0xffffffff, gc->reg_base + LIOINTC_REG_INTC_DISABLE); | 134 | writel(0xffffffff, gc->reg_base + LIOINTC_REG_INTC_DISABLE); |
| 134 | /* Revert map cache */ | 135 | /* Restore map cache */ |
| 135 | for (i = 0; i < LIOINTC_CHIP_IRQ; i++) | 136 | for (i = 0; i < LIOINTC_CHIP_IRQ; i++) |
| 136 | writeb(priv->map_cache[i], gc->reg_base + i); | 137 | writeb(priv->map_cache[i], gc->reg_base + i); |
| 137 | /* Revert mask cache */ | 138 | /* Restore mask cache */ |
| 138 | writel(~gc->mask_cache, gc->reg_base + LIOINTC_REG_INTC_ENABLE); | 139 | writel(gc->mask_cache, gc->reg_base + LIOINTC_REG_INTC_ENABLE); |
| 139 | irq_gc_unlock_irqrestore(gc, flags); | 140 | irq_gc_unlock_irqrestore(gc, flags); |
| 140 | } | 141 | } |
| 141 | 142 | ||
| @@ -243,7 +244,7 @@ int __init liointc_of_init(struct device_node *node, · 101 unmodified lines | |||
| 243 | ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; | 244 | ct->chip.irq_mask_ack = irq_gc_mask_disable_reg; |
| 244 | ct->chip.irq_set_type = liointc_set_type; | 245 | ct->chip.irq_set_type = liointc_set_type; |
| 245 | 246 | ||
| 246 | gc->mask_cache = 0xffffffff; | 247 | gc->mask_cache = 0; |
| 247 | priv->gc = gc; | 248 | priv->gc = gc; |
| 248 | 249 | ||
| 249 | for (i = 0; i < LIOINTC_NUM_PARENT; i++) { | 250 | for (i = 0; i < LIOINTC_NUM_PARENT; i++) { |
| @@ -100,17 +100,12 @@ static int pch_msi_parent_domain_alloc(struct irq_domain *domain, · 99 unmodified lines | |||
| 100 | unsigned int virq, int hwirq) | 100 | unsigned int virq, int hwirq) |
| 101 | { | 101 | { |
| 102 | struct irq_fwspec fwspec; | 102 | struct irq_fwspec fwspec; |
| 103 | int ret; | ||
| 104 | 103 | ||
| 105 | fwspec.fwnode = domain->parent->fwnode; | 104 | fwspec.fwnode = domain->parent->fwnode; |
| 106 | fwspec.param_count = 1; | 105 | fwspec.param_count = 1; |
| 107 | fwspec.param[0] = hwirq; | 106 | fwspec.param[0] = hwirq; |
| 108 | 107 | ||
| 109 | ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); | 108 | return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); |
| 110 | if (ret) | ||
| 111 | return ret; | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | 109 | } |
| 115 | 110 | ||
| 116 | static int pch_msi_middle_domain_alloc(struct irq_domain *domain, | 111 | static int pch_msi_middle_domain_alloc(struct irq_domain *domain, |
| @@ -64,15 +64,6 @@ static void pch_pic_bitclr(struct pch_pic *priv, int offset, int bit) · 63 unmodified lines | |||
| 64 | raw_spin_unlock(&priv->pic_lock); | 64 | raw_spin_unlock(&priv->pic_lock); |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static void pch_pic_eoi_irq(struct irq_data *d) | ||
| 68 | { | ||
| 69 | u32 idx = PIC_REG_IDX(d->hwirq); | ||
| 70 | struct pch_pic *priv = irq_data_get_irq_chip_data(d); | ||
| 71 | |||
| 72 | writel(BIT(PIC_REG_BIT(d->hwirq)), | ||
| 73 | priv->base + PCH_PIC_CLR + idx * 4); | ||
| 74 | } | ||
| 75 | |||
| 76 | static void pch_pic_mask_irq(struct irq_data *d) | 67 | static void pch_pic_mask_irq(struct irq_data *d) |
| 77 | { | 68 | { |
| 78 | struct pch_pic *priv = irq_data_get_irq_chip_data(d); | 69 | struct pch_pic *priv = irq_data_get_irq_chip_data(d); |
| @@ -85,6 +76,9 @@ static void pch_pic_unmask_irq(struct irq_data *d) · 6 unmodified lines | |||
| 85 | { | 76 | { |
| 86 | struct pch_pic *priv = irq_data_get_irq_chip_data(d); | 77 | struct pch_pic *priv = irq_data_get_irq_chip_data(d); |
| 87 | 78 | ||
| 79 | writel(BIT(PIC_REG_BIT(d->hwirq)), | ||
| 80 | priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4); | ||
| 81 | |||
| 88 | irq_chip_unmask_parent(d); | 82 | irq_chip_unmask_parent(d); |
| 89 | pch_pic_bitclr(priv, PCH_PIC_MASK, d->hwirq); | 83 | pch_pic_bitclr(priv, PCH_PIC_MASK, d->hwirq); |
| 90 | } | 84 | } |
| @@ -124,7 +118,6 @@ static struct irq_chip pch_pic_irq_chip = { · 33 unmodified lines | |||
| 124 | .irq_mask = pch_pic_mask_irq, | 118 | .irq_mask = pch_pic_mask_irq, |
| 125 | .irq_unmask = pch_pic_unmask_irq, | 119 | .irq_unmask = pch_pic_unmask_irq, |
| 126 | .irq_ack = irq_chip_ack_parent, | 120 | .irq_ack = irq_chip_ack_parent, |
| 127 | .irq_eoi = pch_pic_eoi_irq, | ||
| 128 | .irq_set_affinity = irq_chip_set_affinity_parent, | 121 | .irq_set_affinity = irq_chip_set_affinity_parent, |
| 129 | .irq_set_type = pch_pic_set_type, | 122 | .irq_set_type = pch_pic_set_type, |
| 130 | }; | 123 | }; |
| @@ -135,22 +128,25 @@ static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq, · 4 unmodified lines | |||
| 135 | int err; | 128 | int err; |
| 136 | unsigned int type; | 129 | unsigned int type; |
| 137 | unsigned long hwirq; | 130 | unsigned long hwirq; |
| 138 | struct irq_fwspec fwspec; | 131 | struct irq_fwspec *fwspec = arg; |
| 132 | struct irq_fwspec parent_fwspec; | ||
| 139 | struct pch_pic *priv = domain->host_data; | 133 | struct pch_pic *priv = domain->host_data; |
| 140 | 134 | ||
| 141 | irq_domain_translate_twocell(domain, arg, &hwirq, &type); | 135 | err = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type); |
| 136 | if (err) | ||
| 137 | return err; | ||
| 142 | 138 | ||
| 143 | fwspec.fwnode = domain->parent->fwnode; | 139 | parent_fwspec.fwnode = domain->parent->fwnode; |
| 144 | fwspec.param_count = 1; | 140 | parent_fwspec.param_count = 1; |
| 145 | fwspec.param[0] = hwirq + priv->ht_vec_base; | 141 | parent_fwspec.param[0] = hwirq + priv->ht_vec_base; |
| 146 | 142 | ||
| 147 | err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); | 143 | err = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); |
| 148 | if (err) | 144 | if (err) |
| 149 | return err; | 145 | return err; |
| 150 | 146 | ||
| 151 | irq_domain_set_info(domain, virq, hwirq, | 147 | irq_domain_set_info(domain, virq, hwirq, |
| 152 | &pch_pic_irq_chip, priv, | 148 | &pch_pic_irq_chip, priv, |
| 153 | handle_fasteoi_ack_irq, NULL, NULL); | 149 | handle_level_irq, NULL, NULL); |
| 154 | irq_set_probe(virq); | 150 | irq_set_probe(virq); |
| 155 | 151 | ||
| 156 | return 0; | 152 | return 0; |
| @@ -46,7 +46,7 @@ · 45 unmodified lines | |||
| 46 | 46 | ||
| 47 | void __iomem *mips_gic_base; | 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 | static DEFINE_SPINLOCK(gic_lock); | 51 | static DEFINE_SPINLOCK(gic_lock); |
| 52 | static struct irq_domain *gic_irq_domain; | 52 | static struct irq_domain *gic_irq_domain; |
| @@ -617,8 +617,8 @@ error: · 564 unmodified lines | |||
| 617 | return ret; | 617 | return ret; |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, | 620 | static void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, |
| 621 | unsigned int nr_irqs) | 621 | unsigned int nr_irqs) |
| 622 | { | 622 | { |
| 623 | irq_hw_number_t base_hwirq; | 623 | irq_hw_number_t base_hwirq; |
| 624 | struct irq_data *data; | 624 | struct irq_data *data; |
| @@ -631,8 +631,8 @@ void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, · 6 unmodified lines | |||
| 631 | bitmap_set(ipi_available, base_hwirq, nr_irqs); | 631 | bitmap_set(ipi_available, base_hwirq, nr_irqs); |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, | 634 | static int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, |
| 635 | enum irq_domain_bus_token bus_token) | 635 | enum irq_domain_bus_token bus_token) |
| 636 | { | 636 | { |
| 637 | bool is_ipi; | 637 | bool is_ipi; |
| 638 | 638 | ||
| @@ -295,4 +295,6 @@ out_free: · 294 unmodified lines | |||
| 295 | return ret; | 295 | return ret; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | IRQCHIP_DECLARE(mtk_cirq, "mediatek,mtk-cirq", mtk_cirq_of_init); | 298 | IRQCHIP_PLATFORM_DRIVER_BEGIN(mtk_cirq) |
| 299 | IRQCHIP_MATCH("mediatek,mtk-cirq", mtk_cirq_of_init) | ||
| 300 | IRQCHIP_PLATFORM_DRIVER_END(mtk_cirq) | ||
| @@ -15,7 +15,7 @@ · 14 unmodified lines | |||
| 15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
| 16 | 16 | ||
| 17 | struct mtk_sysirq_chip_data { | 17 | struct mtk_sysirq_chip_data { |
| 18 | spinlock_t lock; | 18 | raw_spinlock_t lock; |
| 19 | u32 nr_intpol_bases; | 19 | u32 nr_intpol_bases; |
| 20 | void __iomem **intpol_bases; | 20 | void __iomem **intpol_bases; |
| 21 | u32 *intpol_words; | 21 | u32 *intpol_words; |
| @@ -37,7 +37,7 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) · 15 unmodified lines | |||
| 37 | reg_index = chip_data->which_word[hwirq]; | 37 | reg_index = chip_data->which_word[hwirq]; |
| 38 | offset = hwirq & 0x1f; | 38 | offset = hwirq & 0x1f; |
| 39 | 39 | ||
| 40 | spin_lock_irqsave(&chip_data->lock, flags); | 40 | raw_spin_lock_irqsave(&chip_data->lock, flags); |
| 41 | value = readl_relaxed(base + reg_index * 4); | 41 | value = readl_relaxed(base + reg_index * 4); |
| 42 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) { | 42 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) { |
| 43 | if (type == IRQ_TYPE_LEVEL_LOW) | 43 | if (type == IRQ_TYPE_LEVEL_LOW) |
| @@ -53,7 +53,7 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) · 9 unmodified lines | |||
| 53 | 53 | ||
| 54 | data = data->parent_data; | 54 | data = data->parent_data; |
| 55 | ret = data->chip->irq_set_type(data, type); | 55 | ret = data->chip->irq_set_type(data, type); |
| 56 | spin_unlock_irqrestore(&chip_data->lock, flags); | 56 | raw_spin_unlock_irqrestore(&chip_data->lock, flags); |
| 57 | return ret; | 57 | return ret; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| @@ -212,7 +212,7 @@ static int __init mtk_sysirq_of_init(struct device_node *node, · 152 unmodified lines | |||
| 212 | ret = -ENOMEM; | 212 | ret = -ENOMEM; |
| 213 | goto out_free_which_word; | 213 | goto out_free_which_word; |
| 214 | } | 214 | } |
| 215 | spin_lock_init(&chip_data->lock); | 215 | raw_spin_lock_init(&chip_data->lock); |
| 216 | 216 | ||
| 217 | return 0; | 217 | return 0; |
| 218 | 218 | ||
| @@ -231,4 +231,6 @@ out_free_chip: · 12 unmodified lines | |||
| 231 | kfree(chip_data); | 231 | kfree(chip_data); |
| 232 | return ret; | 232 | return ret; |
| 233 | } | 233 | } |
| 234 | IRQCHIP_DECLARE(mtk_sysirq, "mediatek,mt6577-sysirq", mtk_sysirq_of_init); | 234 | IRQCHIP_PLATFORM_DRIVER_BEGIN(mtk_sysirq) |
| 235 | IRQCHIP_MATCH("mediatek,mt6577-sysirq", mtk_sysirq_of_init) | ||
| 236 | IRQCHIP_PLATFORM_DRIVER_END(mtk_sysirq) | ||
| @@ -25,7 +25,6 @@ · 24 unmodified lines | |||
| 25 | #define IRQS_PER_BANK 32 | 25 | #define IRQS_PER_BANK 32 |
| 26 | 26 | ||
| 27 | #define HWSPNLCK_TIMEOUT 1000 /* usec */ | 27 | #define HWSPNLCK_TIMEOUT 1000 /* usec */ |
| 28 | #define HWSPNLCK_RETRY_DELAY 100 /* usec */ | ||
| 29 | 28 | ||
| 30 | struct stm32_exti_bank { | 29 | struct stm32_exti_bank { |
| 31 | u32 imr_ofst; | 30 | u32 imr_ofst; |
| @@ -42,6 +41,7 @@ struct stm32_exti_bank { · 10 unmodified lines | |||
| 42 | struct stm32_desc_irq { | 41 | struct stm32_desc_irq { |
| 43 | u32 exti; | 42 | u32 exti; |
| 44 | u32 irq_parent; | 43 | u32 irq_parent; |
| 44 | struct irq_chip *chip; | ||
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | struct stm32_exti_drv_data { | 47 | struct stm32_exti_drv_data { |
| @@ -166,27 +166,41 @@ static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { · 118 unmodified lines | |||
| 166 | &stm32mp1_exti_b3, | 166 | &stm32mp1_exti_b3, |
| 167 | }; | 167 | }; |
| 168 | 168 | ||
| 169 | static struct irq_chip stm32_exti_h_chip; | ||
| 170 | static struct irq_chip stm32_exti_h_chip_direct; | ||
| 171 | |||
| 169 | static const struct stm32_desc_irq stm32mp1_desc_irq[] = { | 172 | static const struct stm32_desc_irq stm32mp1_desc_irq[] = { |
| 170 | { .exti = 0, .irq_parent = 6 }, | 173 | { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, |
| 171 | { .exti = 1, .irq_parent = 7 }, | 174 | { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, |
| 172 | { .exti = 2, .irq_parent = 8 }, | 175 | { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, |
| 173 | { .exti = 3, .irq_parent = 9 }, | 176 | { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, |
| 174 | { .exti = 4, .irq_parent = 10 }, | 177 | { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, |
| 175 | { .exti = 5, .irq_parent = 23 }, | 178 | { .exti = 5, .irq_parent = 23, .chip = &stm32_exti_h_chip }, |
| 176 | { .exti = 6, .irq_parent = 64 }, | 179 | { .exti = 6, .irq_parent = 64, .chip = &stm32_exti_h_chip }, |
| 177 | { .exti = 7, .irq_parent = 65 }, | 180 | { .exti = 7, .irq_parent = 65, .chip = &stm32_exti_h_chip }, |
| 178 | { .exti = 8, .irq_parent = 66 }, | 181 | { .exti = 8, .irq_parent = 66, .chip = &stm32_exti_h_chip }, |
| 179 | { .exti = 9, .irq_parent = 67 }, | 182 | { .exti = 9, .irq_parent = 67, .chip = &stm32_exti_h_chip }, |
| 180 | { .exti = 10, .irq_parent = 40 }, | 183 | { .exti = 10, .irq_parent = 40, .chip = &stm32_exti_h_chip }, |
| 181 | { .exti = 11, .irq_parent = 42 }, | 184 | { .exti = 11, .irq_parent = 42, .chip = &stm32_exti_h_chip }, |
| 182 | { .exti = 12, .irq_parent = 76 }, | 185 | { .exti = 12, .irq_parent = 76, .chip = &stm32_exti_h_chip }, |
| 183 | { .exti = 13, .irq_parent = 77 }, | 186 | { .exti = 13, .irq_parent = 77, .chip = &stm32_exti_h_chip }, |
| 184 | { .exti = 14, .irq_parent = 121 }, | 187 | { .exti = 14, .irq_parent = 121, .chip = &stm32_exti_h_chip }, |
| 185 | { .exti = 15, .irq_parent = 127 }, | 188 | { .exti = 15, .irq_parent = 127, .chip = &stm32_exti_h_chip }, |
| 186 | { .exti = 16, .irq_parent = 1 }, | 189 | { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, |
| 187 | { .exti = 65, .irq_parent = 144 }, | 190 | { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, |
| 188 | { .exti = 68, .irq_parent = 143 }, | 191 | { .exti = 21, .irq_parent = 31, .chip = &stm32_exti_h_chip_direct }, |
| 189 | { .exti = 73, .irq_parent = 129 }, | 192 | { .exti = 22, .irq_parent = 33, .chip = &stm32_exti_h_chip_direct }, |
| 193 | { .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, | ||
| 194 | { .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct }, | ||
| 195 | { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct }, | ||
| 196 | { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct }, | ||
| 197 | { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, | ||
| 198 | { .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct }, | ||
| 199 | { .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct }, | ||
| 200 | { .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip }, | ||
| 201 | { .exti = 68, .irq_parent = 143, .chip = &stm32_exti_h_chip }, | ||
| 202 | { .exti = 70, .irq_parent = 62, .chip = &stm32_exti_h_chip_direct }, | ||
| 203 | { .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip }, | ||
| 190 | }; | 204 | }; |
| 191 | 205 | ||
| 192 | static const struct stm32_exti_drv_data stm32mp1_drv_data = { | 206 | static const struct stm32_exti_drv_data stm32mp1_drv_data = { |
| @@ -196,22 +210,23 @@ static const struct stm32_exti_drv_data stm32mp1_drv_data = { · 3 unmodified lines | |||
| 196 | .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), | 210 | .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), |
| 197 | }; | 211 | }; |
| 198 | 212 | ||
| 199 | static int stm32_exti_to_irq(const struct stm32_exti_drv_data *drv_data, | 213 | static const struct |
| 200 | irq_hw_number_t hwirq) | 214 | stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data, |
| 215 | irq_hw_number_t hwirq) | ||
| 201 | { | 216 | { |
| 202 | const struct stm32_desc_irq *desc_irq; | 217 | const struct stm32_desc_irq *desc = NULL; |
| 203 | int i; | 218 | int i; |
| 204 | 219 | ||
| 205 | if (!drv_data->desc_irqs) | 220 | if (!drv_data->desc_irqs) |
| 206 | return -EINVAL; | 221 | return NULL; |
| 207 | 222 | ||
| 208 | for (i = 0; i < drv_data->irq_nr; i++) { | 223 | for (i = 0; i < drv_data->irq_nr; i++) { |
| 209 | desc_irq = &drv_data->desc_irqs[i]; | 224 | desc = &drv_data->desc_irqs[i]; |
| 210 | if (desc_irq->exti == hwirq) | 225 | if (desc->exti == hwirq) |
| 211 | return desc_irq->irq_parent; | 226 | break; |
| 212 | } | 227 | } |
| 213 | 228 | ||
| 214 | return -EINVAL; | 229 | return desc; |
| 215 | } | 230 | } |
| 216 | 231 | ||
| 217 | static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) | 232 | static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) |
| @@ -277,55 +292,24 @@ static int stm32_exti_set_type(struct irq_data *d, · 59 unmodified lines | |||
| 277 | return 0; | 292 | return 0; |
| 278 | } | 293 | } |
| 279 | 294 | ||
| 280 | static int stm32_exti_hwspin_lock(struct stm32_exti_chip_data *chip_data) | ||
| 281 | { | ||
| 282 | int ret, timeout = 0; | ||
| 283 | |||
| 284 | if (!chip_data->host_data->hwlock) | ||
| 285 | return 0; | ||
| 286 | |||
| 287 | /* | ||
| 288 | * Use the x_raw API since we are under spin_lock protection. | ||
| 289 | * Do not use the x_timeout API because we are under irq_disable | ||
| 290 | * mode (see __setup_irq()) | ||
| 291 | */ | ||
| 292 | do { | ||
| 293 | ret = hwspin_trylock_raw(chip_data->host_data->hwlock); | ||
| 294 | if (!ret) | ||
| 295 | return 0; | ||
| 296 | |||
| 297 | udelay(HWSPNLCK_RETRY_DELAY); | ||
| 298 | timeout += HWSPNLCK_RETRY_DELAY; | ||
| 299 | } while (timeout < HWSPNLCK_TIMEOUT); | ||
| 300 | |||
| 301 | if (ret == -EBUSY) | ||
| 302 | ret = -ETIMEDOUT; | ||
| 303 | |||
| 304 | if (ret) | ||
| 305 | pr_err("%s can't get hwspinlock (%d)\n", __func__, ret); | ||
| 306 | |||
| 307 | return ret; | ||
| 308 | } | ||
| 309 | |||
| 310 | static void stm32_exti_hwspin_unlock(struct stm32_exti_chip_data *chip_data) | ||
| 311 | { | ||
| 312 | if (chip_data->host_data->hwlock) | ||
| 313 | hwspin_unlock_raw(chip_data->host_data->hwlock); | ||
| 314 | } | ||
| 315 | |||
| 316 | static int stm32_irq_set_type(struct irq_data *d, unsigned int type) | 295 | static int stm32_irq_set_type(struct irq_data *d, unsigned int type) |
| 317 | { | 296 | { |
| 318 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 297 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 319 | struct stm32_exti_chip_data *chip_data = gc->private; | 298 | struct stm32_exti_chip_data *chip_data = gc->private; |
| 320 | const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; | 299 | const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; |
| 300 | struct hwspinlock *hwlock = chip_data->host_data->hwlock; | ||
| 321 | u32 rtsr, ftsr; | 301 | u32 rtsr, ftsr; |
| 322 | int err; | 302 | int err; |
| 323 | 303 | ||
| 324 | irq_gc_lock(gc); | 304 | irq_gc_lock(gc); |
| 325 | 305 | ||
| 326 | err = stm32_exti_hwspin_lock(chip_data); | 306 | if (hwlock) { |
| 327 | if (err) | 307 | err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); |
| 328 | goto unlock; | 308 | if (err) { |
| 309 | pr_err("%s can't get hwspinlock (%d)\n", __func__, err); | ||
| 310 | goto unlock; | ||
| 311 | } | ||
| 312 | } | ||
| 329 | 313 | ||
| 330 | rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst); | 314 | rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst); |
| 331 | ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst); | 315 | ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst); |
| @@ -338,7 +322,8 @@ static int stm32_irq_set_type(struct irq_data *d, unsigned int type) · 6 unmodified lines | |||
| 338 | irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst); | 322 | irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst); |
| 339 | 323 | ||
| 340 | unspinlock: | 324 | unspinlock: |
| 341 | stm32_exti_hwspin_unlock(chip_data); | 325 | if (hwlock) |
| 326 | hwspin_unlock_in_atomic(hwlock); | ||
| 342 | unlock: | 327 | unlock: |
| 343 | irq_gc_unlock(gc); | 328 | irq_gc_unlock(gc); |
| 344 | 329 | ||
| @@ -504,15 +489,20 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) · 159 unmodified lines | |||
| 504 | { | 489 | { |
| 505 | struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); | 490 | struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d); |
| 506 | const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; | 491 | const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank; |
| 492 | struct hwspinlock *hwlock = chip_data->host_data->hwlock; | ||
| 507 | void __iomem *base = chip_data->host_data->base; | 493 | void __iomem *base = chip_data->host_data->base; |
| 508 | u32 rtsr, ftsr; | 494 | u32 rtsr, ftsr; |
| 509 | int err; | 495 | int err; |
| 510 | 496 | ||
| 511 | raw_spin_lock(&chip_data->rlock); | 497 | raw_spin_lock(&chip_data->rlock); |
| 512 | 498 | ||
| 513 | err = stm32_exti_hwspin_lock(chip_data); | 499 | if (hwlock) { |
| 514 | if (err) | 500 | err = hwspin_lock_timeout_in_atomic(hwlock, HWSPNLCK_TIMEOUT); |
| 515 | goto unlock; | 501 | if (err) { |
| 502 | pr_err("%s can't get hwspinlock (%d)\n", __func__, err); | ||
| 503 | goto unlock; | ||
| 504 | } | ||
| 505 | } | ||
| 516 | 506 | ||
| 517 | rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst); | 507 | rtsr = readl_relaxed(base + stm32_bank->rtsr_ofst); |
| 518 | ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst); | 508 | ftsr = readl_relaxed(base + stm32_bank->ftsr_ofst); |
| @@ -525,7 +515,8 @@ static int stm32_exti_h_set_type(struct irq_data *d, unsigned int type) · 6 unmodified lines | |||
| 525 | writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); | 515 | writel_relaxed(ftsr, base + stm32_bank->ftsr_ofst); |
| 526 | 516 | ||
| 527 | unspinlock: | 517 | unspinlock: |
| 528 | stm32_exti_hwspin_unlock(chip_data); | 518 | if (hwlock) |
| 519 | hwspin_unlock_in_atomic(hwlock); | ||
| 529 | unlock: | 520 | unlock: |
| 530 | raw_spin_unlock(&chip_data->rlock); | 521 | raw_spin_unlock(&chip_data->rlock); |
| 531 | 522 | ||
| @@ -628,30 +619,47 @@ static struct irq_chip stm32_exti_h_chip = { · 96 unmodified lines | |||
| 628 | .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL, | 619 | .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? stm32_exti_h_set_affinity : NULL, |
| 629 | }; | 620 | }; |
| 630 | 621 | ||
| 622 | static struct irq_chip stm32_exti_h_chip_direct = { | ||
| 623 | .name = "stm32-exti-h-direct", | ||
| 624 | .irq_eoi = irq_chip_eoi_parent, | ||
| 625 | .irq_ack = irq_chip_ack_parent, | ||
| 626 | .irq_mask = irq_chip_mask_parent, | ||
| 627 | .irq_unmask = irq_chip_unmask_parent, | ||
| 628 | .irq_retrigger = irq_chip_retrigger_hierarchy, | ||
| 629 | .irq_set_type = irq_chip_set_type_parent, | ||
| 630 | .irq_set_wake = stm32_exti_h_set_wake, | ||
| 631 | .flags = IRQCHIP_MASK_ON_SUSPEND, | ||
| 632 | .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, | ||
| 633 | }; | ||
| 634 | |||
| 631 | static int stm32_exti_h_domain_alloc(struct irq_domain *dm, | 635 | static int stm32_exti_h_domain_alloc(struct irq_domain *dm, |
| 632 | unsigned int virq, | 636 | unsigned int virq, |
| 633 | unsigned int nr_irqs, void *data) | 637 | unsigned int nr_irqs, void *data) |
| 634 | { | 638 | { |
| 635 | struct stm32_exti_host_data *host_data = dm->host_data; | 639 | struct stm32_exti_host_data *host_data = dm->host_data; |
| 636 | struct stm32_exti_chip_data *chip_data; | 640 | struct stm32_exti_chip_data *chip_data; |
| 641 | const struct stm32_desc_irq *desc; | ||
| 637 | struct irq_fwspec *fwspec = data; | 642 | struct irq_fwspec *fwspec = data; |
| 638 | struct irq_fwspec p_fwspec; | 643 | struct irq_fwspec p_fwspec; |
| 639 | irq_hw_number_t hwirq; | 644 | irq_hw_number_t hwirq; |
| 640 | int p_irq, bank; | 645 | int bank; |
| 641 | 646 | ||
| 642 | hwirq = fwspec->param[0]; | 647 | hwirq = fwspec->param[0]; |
| 643 | bank = hwirq / IRQS_PER_BANK; | 648 | bank = hwirq / IRQS_PER_BANK; |
| 644 | chip_data = &host_data->chips_data[bank]; | 649 | chip_data = &host_data->chips_data[bank]; |
| 645 | 650 | ||
| 646 | irq_domain_set_hwirq_and_chip(dm, virq, hwirq, | ||
| 647 | &stm32_exti_h_chip, chip_data); | ||
| 648 | 651 | ||
| 649 | p_irq = stm32_exti_to_irq(host_data->drv_data, hwirq); | 652 | desc = stm32_exti_get_desc(host_data->drv_data, hwirq); |
| 650 | if (p_irq >= 0) { | 653 | if (!desc) |
| 654 | return -EINVAL; | ||
| 655 | |||
| 656 | irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, | ||
| 657 | chip_data); | ||
| 658 | if (desc->irq_parent) { | ||
| 651 | p_fwspec.fwnode = dm->parent->fwnode; | 659 | p_fwspec.fwnode = dm->parent->fwnode; |
| 652 | p_fwspec.param_count = 3; | 660 | p_fwspec.param_count = 3; |
| 653 | p_fwspec.param[0] = GIC_SPI; | 661 | p_fwspec.param[0] = GIC_SPI; |
| 654 | p_fwspec.param[1] = p_irq; | 662 | p_fwspec.param[1] = desc->irq_parent; |
| 655 | p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; | 663 | p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; |
| 656 | 664 | ||
| 657 | return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); | 665 | return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); |
| @@ -433,8 +433,6 @@ static int ti_sci_inta_set_type(struct irq_data *data, unsigned int type) · 432 unmodified lines | |||
| 433 | default: | 433 | default: |
| 434 | return -EINVAL; | 434 | return -EINVAL; |
| 435 | } | 435 | } |
| 436 | |||
| 437 | return -EINVAL; | ||
| 438 | } | 436 | } |
| 439 | 437 | ||
| 440 | static struct irq_chip ti_sci_inta_irq_chip = { | 438 | static struct irq_chip ti_sci_inta_irq_chip = { |
| @@ -572,7 +570,7 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) · 131 unmodified lines | |||
| 572 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 570 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 573 | inta->base = devm_ioremap_resource(dev, res); | 571 | inta->base = devm_ioremap_resource(dev, res); |
| 574 | if (IS_ERR(inta->base)) | 572 | if (IS_ERR(inta->base)) |
| 575 | return -ENODEV; | 573 | return PTR_ERR(inta->base); |
| 576 | 574 | ||
| 577 | domain = irq_domain_add_linear(dev_of_node(dev), | 575 | domain = irq_domain_add_linear(dev_of_node(dev), |
| 578 | ti_sci_get_num_resources(inta->vint), | 576 | ti_sci_get_num_resources(inta->vint), |
| @@ -612,6 +610,6 @@ static struct platform_driver ti_sci_inta_irq_domain_driver = { · 33 unmodified lines | |||
| 612 | }; | 610 | }; |
| 613 | module_platform_driver(ti_sci_inta_irq_domain_driver); | 611 | module_platform_driver(ti_sci_inta_irq_domain_driver); |
| 614 | 612 | ||
| 615 | MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ticom>"); | 613 | MODULE_AUTHOR("Lokesh Vutla <lokeshvutla@ti.com>"); |
| 616 | MODULE_DESCRIPTION("K3 Interrupt Aggregator driver over TI SCI protocol"); | 614 | MODULE_DESCRIPTION("K3 Interrupt Aggregator driver over TI SCI protocol"); |
| 617 | MODULE_LICENSE("GPL v2"); | 615 | MODULE_LICENSE("GPL v2"); |
| @@ -27,7 +27,10 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #define VIC_IRQ_STATUS 0x00 | 28 | #define VIC_IRQ_STATUS 0x00 |
| 29 | #define VIC_FIQ_STATUS 0x04 | 29 | #define VIC_FIQ_STATUS 0x04 |
| 30 | #define VIC_RAW_STATUS 0x08 | ||
| 30 | #define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ | 31 | #define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */ |
| 32 | #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ | ||
| 33 | #define VIC_INT_ENABLE_CLEAR 0x14 | ||
| 31 | #define VIC_INT_SOFT 0x18 | 34 | #define VIC_INT_SOFT 0x18 |
| 32 | #define VIC_INT_SOFT_CLEAR 0x1c | 35 | #define VIC_INT_SOFT_CLEAR 0x1c |
| 33 | #define VIC_PROTECT 0x20 | 36 | #define VIC_PROTECT 0x20 |
| @@ -428,7 +431,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, · 394 unmodified lines | |||
| 428 | vic_register(base, 0, irq_start, vic_sources, 0, node); | 431 | vic_register(base, 0, irq_start, vic_sources, 0, node); |
| 429 | } | 432 | } |
| 430 | 433 | ||
| 431 | void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, | 434 | static void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, |
| 432 | u32 vic_sources, u32 resume_sources, | 435 | u32 vic_sources, u32 resume_sources, |
| 433 | struct device_node *node) | 436 | struct device_node *node) |
| 434 | { | 437 | { |
| @@ -481,27 +484,6 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, · 46 unmodified lines | |||
| 481 | __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); | 484 | __vic_init(base, 0, irq_start, vic_sources, resume_sources, NULL); |
| 482 | } | 485 | } |
| 483 | 486 | ||
| 484 | /** | ||
| 485 | * vic_init_cascaded() - initialise a cascaded vectored interrupt controller | ||
| 486 | * @base: iomem base address | ||
| 487 | * @parent_irq: the parent IRQ we're cascaded off | ||
| 488 | * @vic_sources: bitmask of interrupt sources to allow | ||
| 489 | * @resume_sources: bitmask of interrupt sources to allow for resume | ||
| 490 | * | ||
| 491 | * This returns the base for the new interrupts or negative on error. | ||
| 492 | */ | ||
| 493 | int __init vic_init_cascaded(void __iomem *base, unsigned int parent_irq, | ||
| 494 | u32 vic_sources, u32 resume_sources) | ||
| 495 | { | ||
| 496 | struct vic_device *v; | ||
| 497 | |||
| 498 | v = &vic_devices[vic_id]; | ||
| 499 | __vic_init(base, parent_irq, 0, vic_sources, resume_sources, NULL); | ||
| 500 | /* Return out acquired base */ | ||
| 501 | return v->irq; | ||
| 502 | } | ||
| 503 | EXPORT_SYMBOL_GPL(vic_init_cascaded); | ||
| 504 | |||
| 505 | #ifdef CONFIG_OF | 487 | #ifdef CONFIG_OF |
| 506 | static int __init vic_of_init(struct device_node *node, | 488 | static int __init vic_of_init(struct device_node *node, |
| 507 | struct device_node *parent) | 489 | struct device_node *parent) |
| @@ -10,8 +10,10 @@ · 9 unmodified lines | |||
| 10 | 10 | ||
| 11 | #include <linux/acpi.h> | 11 | #include <linux/acpi.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/of_device.h> | ||
| 13 | #include <linux/of_irq.h> | 14 | #include <linux/of_irq.h> |
| 14 | #include <linux/irqchip.h> | 15 | #include <linux/irqchip.h> |
| 16 | #include <linux/platform_device.h> | ||
| 15 | 17 | ||
| 16 | /* | 18 | /* |
| 17 | * This special of_device_id is the sentinel at the end of the | 19 | * This special of_device_id is the sentinel at the end of the |
| @@ -29,3 +31,30 @@ void __init irqchip_init(void) · 11 unmodified lines | |||
| 29 | of_irq_init(__irqchip_of_table); | 31 | of_irq_init(__irqchip_of_table); |
| 30 | acpi_probe_device_table(irqchip); | 32 | acpi_probe_device_table(irqchip); |
| 31 | } | 33 | } |
| 34 | |||
| 35 | int platform_irqchip_probe(struct platform_device *pdev) | ||
| 36 | { | ||
| 37 | struct device_node *np = pdev->dev.of_node; | ||
| 38 | struct device_node *par_np = of_irq_find_parent(np); | ||
| 39 | of_irq_init_cb_t irq_init_cb = of_device_get_match_data(&pdev->dev); | ||
| 40 | |||
| 41 | if (!irq_init_cb) | ||
| 42 | return -EINVAL; | ||
| 43 | |||
| 44 | if (par_np == np) | ||
| 45 | par_np = NULL; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * If there's a parent interrupt controller and none of the parent irq | ||
| 49 | * domains have been registered, that means the parent interrupt | ||
| 50 | * controller has not been initialized yet. it's not time for this | ||
| 51 | * interrupt controller to initialize. So, defer probe of this | ||
| 52 | * interrupt controller. The actual initialization callback of this | ||
| 53 | * interrupt controller can check for specific domains as necessary. | ||
| 54 | */ | ||
| 55 | if (par_np && !irq_find_matching_host(np, DOMAIN_BUS_ANY)) | ||
| 56 | return -EPROBE_DEFER; | ||
| 57 | |||
| 58 | return irq_init_cb(np, par_np); | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL_GPL(platform_irqchip_probe); | ||
| @@ -11,9 +11,11 @@ · 10 unmodified lines | |||
| 11 | #include <linux/irqdomain.h> | 11 | #include <linux/irqdomain.h> |
| 12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | #include <linux/module.h> | ||
| 14 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 15 | #include <linux/of_address.h> | 16 | #include <linux/of_address.h> |
| 16 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
| 18 | #include <linux/of_irq.h> | ||
| 17 | #include <linux/soc/qcom/irq.h> | 19 | #include <linux/soc/qcom/irq.h> |
| 18 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| 19 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| @@ -430,4 +432,8 @@ fail: · 410 unmodified lines | |||
| 430 | return ret; | 432 | return ret; |
| 431 | } | 433 | } |
| 432 | 434 | ||
| 433 | IRQCHIP_DECLARE(qcom_pdc, "qcom,pdc", qcom_pdc_init); | 435 | IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_pdc) |
| 436 | IRQCHIP_MATCH("qcom,pdc", qcom_pdc_init) | ||
| 437 | IRQCHIP_PLATFORM_DRIVER_END(qcom_pdc) | ||
| 438 | MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Power Domain Controller"); | ||
| 439 | MODULE_LICENSE("GPL v2"); | ||
| @@ -1150,16 +1150,27 @@ struct acpi_probe_entry { · 1149 unmodified lines | |||
| 1150 | kernel_ulong_t driver_data; | 1150 | kernel_ulong_t driver_data; |
| 1151 | }; | 1151 | }; |
| 1152 | 1152 | ||
| 1153 | #define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, valid, data, fn) \ | 1153 | #define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable, \ |
| 1154 | valid, data, fn) \ | ||
| 1154 | static const struct acpi_probe_entry __acpi_probe_##name \ | 1155 | static const struct acpi_probe_entry __acpi_probe_##name \ |
| 1155 | __used __section(__##table##_acpi_probe_table) \ | 1156 | __used __section(__##table##_acpi_probe_table) = { \ |
| 1156 | = { \ | ||
| 1157 | .id = table_id, \ | 1157 | .id = table_id, \ |
| 1158 | .type = subtable, \ | 1158 | .type = subtable, \ |
| 1159 | .subtable_valid = valid, \ | 1159 | .subtable_valid = valid, \ |
| 1160 | .probe_table = (acpi_tbl_table_handler)fn, \ | 1160 | .probe_table = fn, \ |
| 1161 | .driver_data = data, \ | 1161 | .driver_data = data, \ |
| 1162 | } | 1162 | } |
| 1163 | |||
| 1164 | #define ACPI_DECLARE_SUBTABLE_PROBE_ENTRY(table, name, table_id, \ | ||
| 1165 | subtable, valid, data, fn) \ | ||
| 1166 | static const struct acpi_probe_entry __acpi_probe_##name \ | ||
| 1167 | __used __section(__##table##_acpi_probe_table) = { \ | ||
| 1168 | .id = table_id, \ | ||
| 1169 | .type = subtable, \ | ||
| 1170 | .subtable_valid = valid, \ | ||
| 1171 | .probe_subtbl = fn, \ | ||
| 1172 | .driver_data = data, \ | ||
| 1173 | } | ||
| 1163 | 1174 | ||
| 1164 | #define ACPI_PROBE_TABLE(name) __##name##_acpi_probe_table | 1175 | #define ACPI_PROBE_TABLE(name) __##name##_acpi_probe_table |
| 1165 | #define ACPI_PROBE_TABLE_END(name) __##name##_acpi_probe_table_end | 1176 | #define ACPI_PROBE_TABLE_END(name) __##name##_acpi_probe_table_end |
| @@ -12,7 +12,9 @@ · 11 unmodified lines | |||
| 12 | #define _LINUX_IRQCHIP_H | 12 | #define _LINUX_IRQCHIP_H |
| 13 | 13 | ||
| 14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
| 15 | #include <linux/module.h> | ||
| 15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
| 17 | #include <linux/platform_device.h> | ||
| 16 | 18 | ||
| 17 | /* | 19 | /* |
| 18 | * This macro must be used by the different irqchip drivers to declare | 20 | * This macro must be used by the different irqchip drivers to declare |
| @@ -26,6 +28,28 @@ · 7 unmodified lines | |||
| 26 | */ | 28 | */ |
| 27 | #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn) | 29 | #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn) |
| 28 | 30 | ||
| 31 | extern int platform_irqchip_probe(struct platform_device *pdev); | ||
| 32 | |||
| 33 | #define IRQCHIP_PLATFORM_DRIVER_BEGIN(drv_name) \ | ||
| 34 | static const struct of_device_id drv_name##_irqchip_match_table[] = { | ||
| 35 | |||
| 36 | #define IRQCHIP_MATCH(compat, fn) { .compatible = compat, .data = fn }, | ||
| 37 | |||
| 38 | #define IRQCHIP_PLATFORM_DRIVER_END(drv_name) \ | ||
| 39 | {}, \ | ||
| 40 | }; \ | ||
| 41 | MODULE_DEVICE_TABLE(of, drv_name##_irqchip_match_table); \ | ||
| 42 | static struct platform_driver drv_name##_driver = { \ | ||
| 43 | .probe = platform_irqchip_probe, \ | ||
| 44 | .driver = { \ | ||
| 45 | .name = #drv_name, \ | ||
| 46 | .owner = THIS_MODULE, \ | ||
| 47 | .of_match_table = drv_name##_irqchip_match_table, \ | ||
| 48 | .suppress_bind_attrs = true, \ | ||
| 49 | }, \ | ||
| 50 | }; \ | ||
| 51 | builtin_platform_driver(drv_name##_driver) | ||
| 52 | |||
| 29 | /* | 53 | /* |
| 30 | * This macro must be used by the different irqchip drivers to declare | 54 | * This macro must be used by the different irqchip drivers to declare |
| 31 | * the association between their version and their initialization function. | 55 | * the association between their version and their initialization function. |
| @@ -39,8 +63,9 @@ · 7 unmodified lines | |||
| 39 | * @fn: initialization function | 63 | * @fn: initialization function |
| 40 | */ | 64 | */ |
| 41 | #define IRQCHIP_ACPI_DECLARE(name, subtable, validate, data, fn) \ | 65 | #define IRQCHIP_ACPI_DECLARE(name, subtable, validate, data, fn) \ |
| 42 | ACPI_DECLARE_PROBE_ENTRY(irqchip, name, ACPI_SIG_MADT, \ | 66 | ACPI_DECLARE_SUBTABLE_PROBE_ENTRY(irqchip, name, \ |
| 43 | subtable, validate, data, fn) | 67 | ACPI_SIG_MADT, subtable, \ |
| 68 | validate, data, fn) | ||
| 44 | 69 | ||
| 45 | #ifdef CONFIG_IRQCHIP | 70 | #ifdef CONFIG_IRQCHIP |
| 46 | void irqchip_init(void); | 71 | void irqchip_init(void); |
| @@ -19,7 +19,6 @@ · 18 unmodified lines | |||
| 19 | #define GICD_CLRSPI_NSR 0x0048 | 19 | #define GICD_CLRSPI_NSR 0x0048 |
| 20 | #define GICD_SETSPI_SR 0x0050 | 20 | #define GICD_SETSPI_SR 0x0050 |
| 21 | #define GICD_CLRSPI_SR 0x0058 | 21 | #define GICD_CLRSPI_SR 0x0058 |
| 22 | #define GICD_SEIR 0x0068 | ||
| 23 | #define GICD_IGROUPR 0x0080 | 22 | #define GICD_IGROUPR 0x0080 |
| 24 | #define GICD_ISENABLER 0x0100 | 23 | #define GICD_ISENABLER 0x0100 |
| 25 | #define GICD_ICENABLER 0x0180 | 24 | #define GICD_ICENABLER 0x0180 |
| @@ -119,14 +118,11 @@ · 93 unmodified lines | |||
| 119 | #define GICR_WAKER 0x0014 | 118 | #define GICR_WAKER 0x0014 |
| 120 | #define GICR_SETLPIR 0x0040 | 119 | #define GICR_SETLPIR 0x0040 |
| 121 | #define GICR_CLRLPIR 0x0048 | 120 | #define GICR_CLRLPIR 0x0048 |
| 122 | #define GICR_SEIR GICD_SEIR | ||
| 123 | #define GICR_PROPBASER 0x0070 | 121 | #define GICR_PROPBASER 0x0070 |
| 124 | #define GICR_PENDBASER 0x0078 | 122 | #define GICR_PENDBASER 0x0078 |
| 125 | #define GICR_INVLPIR 0x00A0 | 123 | #define GICR_INVLPIR 0x00A0 |
| 126 | #define GICR_INVALLR 0x00B0 | 124 | #define GICR_INVALLR 0x00B0 |
| 127 | #define GICR_SYNCR 0x00C0 | 125 | #define GICR_SYNCR 0x00C0 |
| 128 | #define GICR_MOVLPIR 0x0100 | ||
| 129 | #define GICR_MOVALLR 0x0110 | ||
| 130 | #define GICR_IDREGS GICD_IDREGS | 126 | #define GICR_IDREGS GICD_IDREGS |
| 131 | #define GICR_PIDR2 GICD_PIDR2 | 127 | #define GICR_PIDR2 GICD_PIDR2 |
| 132 | 128 | ||
| @@ -9,17 +9,6 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
| 11 | 11 | ||
| 12 | #define VIC_RAW_STATUS 0x08 | ||
| 13 | #define VIC_INT_ENABLE 0x10 /* 1 = enable, 0 = disable */ | ||
| 14 | #define VIC_INT_ENABLE_CLEAR 0x14 | ||
| 15 | |||
| 16 | struct device_node; | ||
| 17 | struct pt_regs; | ||
| 18 | |||
| 19 | void __vic_init(void __iomem *base, int parent_irq, int irq_start, | ||
| 20 | u32 vic_sources, u32 resume_sources, struct device_node *node); | ||
| 21 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); | 12 | void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); |
| 22 | int vic_init_cascaded(void __iomem *base, unsigned int parent_irq, | ||
| 23 | u32 vic_sources, u32 resume_sources); | ||
| 24 | 13 | ||
| 25 | #endif | 14 | #endif |
| @@ -30,7 +30,7 @@ · 29 unmodified lines | |||
| 30 | */ | 30 | */ |
| 31 | #define LOCAL_MAILBOX_INT_CONTROL0 0x050 | 31 | #define LOCAL_MAILBOX_INT_CONTROL0 0x050 |
| 32 | /* | 32 | /* |
| 33 | * The CPU's interrupt status register. Bits are defined by the the | 33 | * The CPU's interrupt status register. Bits are defined by the |
| 34 | * LOCAL_IRQ_* bits below. | 34 | * LOCAL_IRQ_* bits below. |
| 35 | */ | 35 | */ |
| 36 | #define LOCAL_IRQ_PENDING0 0x060 | 36 | #define LOCAL_IRQ_PENDING0 0x060 |
| @@ -22,7 +22,6 @@ struct pt_regs; · 21 unmodified lines | |||
| 22 | * @irq_common_data: per irq and chip data passed down to chip functions | 22 | * @irq_common_data: per irq and chip data passed down to chip functions |
| 23 | * @kstat_irqs: irq stats per cpu | 23 | * @kstat_irqs: irq stats per cpu |
| 24 | * @handle_irq: highlevel irq-events handler | 24 | * @handle_irq: highlevel irq-events handler |
| 25 | * @preflow_handler: handler called before the flow handler (currently used by sparc) | ||
| 26 | * @action: the irq action chain | 25 | * @action: the irq action chain |
| 27 | * @status_use_accessors: status information | 26 | * @status_use_accessors: status information |
| 28 | * @core_internal_state__do_not_mess_with_it: core internal status information | 27 | * @core_internal_state__do_not_mess_with_it: core internal status information |
| @@ -58,9 +57,6 @@ struct irq_desc { · 29 unmodified lines | |||
| 58 | struct irq_data irq_data; | 57 | struct irq_data irq_data; |
| 59 | unsigned int __percpu *kstat_irqs; | 58 | unsigned int __percpu *kstat_irqs; |
| 60 | irq_flow_handler_t handle_irq; | 59 | irq_flow_handler_t handle_irq; |
| 61 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
| 62 | irq_preflow_handler_t preflow_handler; | ||
| 63 | #endif | ||
| 64 | struct irqaction *action; /* IRQ action list */ | 60 | struct irqaction *action; /* IRQ action list */ |
| 65 | unsigned int status_use_accessors; | 61 | unsigned int status_use_accessors; |
| 66 | unsigned int core_internal_state__do_not_mess_with_it; | 62 | unsigned int core_internal_state__do_not_mess_with_it; |
| @@ -268,15 +264,4 @@ irq_set_lockdep_class(unsigned int irq, struct lock_class_key *lock_class, · 201 unmodified lines | |||
| 268 | } | 264 | } |
| 269 | } | 265 | } |
| 270 | 266 | ||
| 271 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
| 272 | static inline void | ||
| 273 | __irq_set_preflow_handler(unsigned int irq, irq_preflow_handler_t handler) | ||
| 274 | { | ||
| 275 | struct irq_desc *desc; | ||
| 276 | |||
| 277 | desc = irq_to_desc(irq); | ||
| 278 | desc->preflow_handler = handler; | ||
| 279 | } | ||
| 280 | #endif | ||
| 281 | |||
| 282 | #endif | 267 | #endif |
| @@ -10,6 +10,5 @@ · 9 unmodified lines | |||
| 10 | struct irq_desc; | 10 | struct irq_desc; |
| 11 | struct irq_data; | 11 | struct irq_data; |
| 12 | typedef void (*irq_flow_handler_t)(struct irq_desc *desc); | 12 | typedef void (*irq_flow_handler_t)(struct irq_desc *desc); |
| 13 | typedef void (*irq_preflow_handler_t)(struct irq_data *data); | ||
| 14 | 13 | ||
| 15 | #endif | 14 | #endif |
| @@ -51,10 +51,6 @@ config GENERIC_IRQ_INJECTION · 50 unmodified lines | |||
| 51 | config HARDIRQS_SW_RESEND | 51 | config HARDIRQS_SW_RESEND |
| 52 | bool | 52 | bool |
| 53 | 53 | ||
| 54 | # Preflow handler support for fasteoi (sparc64) | ||
| 55 | config IRQ_PREFLOW_FASTEOI | ||
| 56 | bool | ||
| 57 | |||
| 58 | # Edge style eoi based handler (cell) | 54 | # Edge style eoi based handler (cell) |
| 59 | config IRQ_EDGE_EOI_HANDLER | 55 | config IRQ_EDGE_EOI_HANDLER |
| 60 | bool | 56 | bool |
| @@ -656,16 +656,6 @@ out_unlock: · 655 unmodified lines | |||
| 656 | } | 656 | } |
| 657 | EXPORT_SYMBOL_GPL(handle_level_irq); | 657 | EXPORT_SYMBOL_GPL(handle_level_irq); |
| 658 | 658 | ||
| 659 | #ifdef CONFIG_IRQ_PREFLOW_FASTEOI | ||
| 660 | static inline void preflow_handler(struct irq_desc *desc) | ||
| 661 | { | ||
| 662 | if (desc->preflow_handler) | ||
| 663 | desc->preflow_handler(&desc->irq_data); | ||
| 664 | } | ||
| 665 | #else | ||
| 666 | static inline void preflow_handler(struct irq_desc *desc) { } | ||
| 667 | #endif | ||
| 668 | |||
| 669 | static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip) | 659 | static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip) |
| 670 | { | 660 | { |
| 671 | if (!(desc->istate & IRQS_ONESHOT)) { | 661 | if (!(desc->istate & IRQS_ONESHOT)) { |
| @@ -721,7 +711,6 @@ void handle_fasteoi_irq(struct irq_desc *desc) · 49 unmodified lines | |||
| 721 | if (desc->istate & IRQS_ONESHOT) | 711 | if (desc->istate & IRQS_ONESHOT) |
| 722 | mask_irq(desc); | 712 | mask_irq(desc); |
| 723 | 713 | ||
| 724 | preflow_handler(desc); | ||
| 725 | handle_irq_event(desc); | 714 | handle_irq_event(desc); |
| 726 | 715 | ||
| 727 | cond_unmask_eoi_irq(desc, chip); | 716 | cond_unmask_eoi_irq(desc, chip); |
| @@ -1231,7 +1220,6 @@ void handle_fasteoi_ack_irq(struct irq_desc *desc) · 503 unmodified lines | |||
| 1231 | /* Start handling the irq */ | 1220 | /* Start handling the irq */ |
| 1232 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 1221 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
| 1233 | 1222 | ||
| 1234 | preflow_handler(desc); | ||
| 1235 | handle_irq_event(desc); | 1223 | handle_irq_event(desc); |
| 1236 | 1224 | ||
| 1237 | cond_unmask_eoi_irq(desc, chip); | 1225 | cond_unmask_eoi_irq(desc, chip); |
| @@ -1281,7 +1269,6 @@ void handle_fasteoi_mask_irq(struct irq_desc *desc) · 43 unmodified lines | |||
| 1281 | if (desc->istate & IRQS_ONESHOT) | 1269 | if (desc->istate & IRQS_ONESHOT) |
| 1282 | mask_irq(desc); | 1270 | mask_irq(desc); |
| 1283 | 1271 | ||
| 1284 | preflow_handler(desc); | ||
| 1285 | handle_irq_event(desc); | 1272 | handle_irq_event(desc); |
| 1286 | 1273 | ||
| 1287 | cond_unmask_eoi_irq(desc, chip); | 1274 | cond_unmask_eoi_irq(desc, chip); |
| @@ -1478,6 +1465,7 @@ int irq_chip_retrigger_hierarchy(struct irq_data *data) · 190 unmodified lines | |||
| 1478 | 1465 | ||
| 1479 | return 0; | 1466 | return 0; |
| 1480 | } | 1467 | } |
| 1468 | EXPORT_SYMBOL_GPL(irq_chip_retrigger_hierarchy); | ||
| 1481 | 1469 | ||
| 1482 | /** | 1470 | /** |
| 1483 | * irq_chip_set_vcpu_affinity_parent - Set vcpu affinity on the parent interrupt | 1471 | * irq_chip_set_vcpu_affinity_parent - Set vcpu affinity on the parent interrupt |
| @@ -1492,7 +1480,7 @@ int irq_chip_set_vcpu_affinity_parent(struct irq_data *data, void *vcpu_info) · 8 unmodified lines | |||
| 1492 | 1480 | ||
| 1493 | return -ENOSYS; | 1481 | return -ENOSYS; |
| 1494 | } | 1482 | } |
| 1495 | 1483 | EXPORT_SYMBOL_GPL(irq_chip_set_vcpu_affinity_parent); | |
| 1496 | /** | 1484 | /** |
| 1497 | * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt | 1485 | * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt |
| 1498 | * @data: Pointer to interrupt specific data | 1486 | * @data: Pointer to interrupt specific data |
| @@ -142,7 +142,7 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size, · 141 unmodified lines | |||
| 142 | if (!domain) | 142 | if (!domain) |
| 143 | return NULL; | 143 | return NULL; |
| 144 | 144 | ||
| 145 | if (fwnode && is_fwnode_irqchip(fwnode)) { | 145 | if (is_fwnode_irqchip(fwnode)) { |
| 146 | fwid = container_of(fwnode, struct irqchip_fwid, fwnode); | 146 | fwid = container_of(fwnode, struct irqchip_fwid, fwnode); |
| 147 | 147 | ||
| 148 | switch (fwid->type) { | 148 | switch (fwid->type) { |
| @@ -281,6 +281,7 @@ void irq_domain_update_bus_token(struct irq_domain *domain, · 132 unmodified lines | |||
| 281 | 281 | ||
| 282 | mutex_unlock(&irq_domain_mutex); | 282 | mutex_unlock(&irq_domain_mutex); |
| 283 | } | 283 | } |
| 284 | EXPORT_SYMBOL_GPL(irq_domain_update_bus_token); | ||
| 284 | 285 | ||
| 285 | /** | 286 | /** |
| 286 | * irq_domain_add_simple() - Register an irq_domain and optionally map a range of irqs | 287 | * irq_domain_add_simple() - Register an irq_domain and optionally map a range of irqs |