diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2018-01-10 15:04:21 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-01-10 15:04:21 -0500 |
commit | 80023aea83532c59e5a75fcc54b4158e44216c4a (patch) | |
tree | c7d25cc0ba331631f9ef5b20fa6644bfbed3149d | |
parent | 6baf9e67c9c5d738188b8490893c7e079d3deb7e (diff) | |
parent | ebe2f8718007d5a1238bb3cb8141b5bb2b4d5773 (diff) |
Merge tag 'irqchip-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates for 4.16 from Marc Zyngier
- Fix a GICv3 issue when parsing ACPI entries for disabled CPUs
- Driver for the MIPS Goldfish virtual platform
- Small fixlet for the ompic driver
- Interrupt polarity support for the Raspberry Pi irqchip
-rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt | 4 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt | 30 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | arch/arm/boot/dts/bcm2836.dtsi | 14 | ||||
-rw-r--r-- | arch/arm/boot/dts/bcm2837.dtsi | 12 | ||||
-rw-r--r-- | arch/arm/boot/dts/bcm283x.dtsi | 1 | ||||
-rw-r--r-- | drivers/irqchip/Kconfig | 8 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-bcm2836.c | 46 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 11 | ||||
-rw-r--r-- | drivers/irqchip/irq-goldfish-pic.c | 139 | ||||
-rw-r--r-- | drivers/irqchip/irq-ompic.c | 4 |
12 files changed, 241 insertions, 35 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt index f320dcd6e69b..8ced1696c325 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt | |||
@@ -12,7 +12,7 @@ Required properties: | |||
12 | registers | 12 | registers |
13 | - interrupt-controller: Identifies the node as an interrupt controller | 13 | - interrupt-controller: Identifies the node as an interrupt controller |
14 | - #interrupt-cells: Specifies the number of cells needed to encode an | 14 | - #interrupt-cells: Specifies the number of cells needed to encode an |
15 | interrupt source. The value shall be 1 | 15 | interrupt source. The value shall be 2 |
16 | 16 | ||
17 | Please refer to interrupts.txt in this directory for details of the common | 17 | Please refer to interrupts.txt in this directory for details of the common |
18 | Interrupt Controllers bindings used by client devices. | 18 | Interrupt Controllers bindings used by client devices. |
@@ -32,6 +32,6 @@ local_intc: local_intc { | |||
32 | compatible = "brcm,bcm2836-l1-intc"; | 32 | compatible = "brcm,bcm2836-l1-intc"; |
33 | reg = <0x40000000 0x100>; | 33 | reg = <0x40000000 0x100>; |
34 | interrupt-controller; | 34 | interrupt-controller; |
35 | #interrupt-cells = <1>; | 35 | #interrupt-cells = <2>; |
36 | interrupt-parent = <&local_intc>; | 36 | interrupt-parent = <&local_intc>; |
37 | }; | 37 | }; |
diff --git a/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt b/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt new file mode 100644 index 000000000000..35f752706e7d --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | Android Goldfish PIC | ||
2 | |||
3 | Android Goldfish programmable interrupt device used by Android | ||
4 | emulator. | ||
5 | |||
6 | Required properties: | ||
7 | |||
8 | - compatible : should contain "google,goldfish-pic" | ||
9 | - reg : <registers mapping> | ||
10 | - interrupts : <interrupt mapping> | ||
11 | |||
12 | Example for mips when used in cascade mode: | ||
13 | |||
14 | cpuintc { | ||
15 | #interrupt-cells = <0x1>; | ||
16 | #address-cells = <0>; | ||
17 | interrupt-controller; | ||
18 | compatible = "mti,cpu-interrupt-controller"; | ||
19 | }; | ||
20 | |||
21 | interrupt-controller@1f000000 { | ||
22 | compatible = "google,goldfish-pic"; | ||
23 | reg = <0x1f000000 0x1000>; | ||
24 | |||
25 | interrupt-controller; | ||
26 | #interrupt-cells = <0x1>; | ||
27 | |||
28 | interrupt-parent = <&cpuintc>; | ||
29 | interrupts = <0x2>; | ||
30 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 95c3fa1f520f..729f80d45bdf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -867,6 +867,12 @@ S: Supported | |||
867 | F: drivers/android/ | 867 | F: drivers/android/ |
868 | F: drivers/staging/android/ | 868 | F: drivers/staging/android/ |
869 | 869 | ||
870 | ANDROID GOLDFISH PIC DRIVER | ||
871 | M: Miodrag Dinic <miodrag.dinic@mips.com> | ||
872 | S: Supported | ||
873 | F: Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt | ||
874 | F: drivers/irqchip/irq-goldfish-pic.c | ||
875 | |||
870 | ANDROID GOLDFISH RTC DRIVER | 876 | ANDROID GOLDFISH RTC DRIVER |
871 | M: Miodrag Dinic <miodrag.dinic@mips.com> | 877 | M: Miodrag Dinic <miodrag.dinic@mips.com> |
872 | S: Supported | 878 | S: Supported |
diff --git a/arch/arm/boot/dts/bcm2836.dtsi b/arch/arm/boot/dts/bcm2836.dtsi index 61e158003509..1dfd76442777 100644 --- a/arch/arm/boot/dts/bcm2836.dtsi +++ b/arch/arm/boot/dts/bcm2836.dtsi | |||
@@ -13,24 +13,24 @@ | |||
13 | compatible = "brcm,bcm2836-l1-intc"; | 13 | compatible = "brcm,bcm2836-l1-intc"; |
14 | reg = <0x40000000 0x100>; | 14 | reg = <0x40000000 0x100>; |
15 | interrupt-controller; | 15 | interrupt-controller; |
16 | #interrupt-cells = <1>; | 16 | #interrupt-cells = <2>; |
17 | interrupt-parent = <&local_intc>; | 17 | interrupt-parent = <&local_intc>; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | arm-pmu { | 20 | arm-pmu { |
21 | compatible = "arm,cortex-a7-pmu"; | 21 | compatible = "arm,cortex-a7-pmu"; |
22 | interrupt-parent = <&local_intc>; | 22 | interrupt-parent = <&local_intc>; |
23 | interrupts = <9>; | 23 | interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; |
24 | }; | 24 | }; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | timer { | 27 | timer { |
28 | compatible = "arm,armv7-timer"; | 28 | compatible = "arm,armv7-timer"; |
29 | interrupt-parent = <&local_intc>; | 29 | interrupt-parent = <&local_intc>; |
30 | interrupts = <0>, // PHYS_SECURE_PPI | 30 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI |
31 | <1>, // PHYS_NONSECURE_PPI | 31 | <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI |
32 | <3>, // VIRT_PPI | 32 | <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI |
33 | <2>; // HYP_PPI | 33 | <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI |
34 | always-on; | 34 | always-on; |
35 | }; | 35 | }; |
36 | 36 | ||
@@ -76,7 +76,7 @@ | |||
76 | compatible = "brcm,bcm2836-armctrl-ic"; | 76 | compatible = "brcm,bcm2836-armctrl-ic"; |
77 | reg = <0x7e00b200 0x200>; | 77 | reg = <0x7e00b200 0x200>; |
78 | interrupt-parent = <&local_intc>; | 78 | interrupt-parent = <&local_intc>; |
79 | interrupts = <8>; | 79 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | &cpu_thermal { | 82 | &cpu_thermal { |
diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi index bc1cca5cf43c..efa7d3387ab2 100644 --- a/arch/arm/boot/dts/bcm2837.dtsi +++ b/arch/arm/boot/dts/bcm2837.dtsi | |||
@@ -12,7 +12,7 @@ | |||
12 | compatible = "brcm,bcm2836-l1-intc"; | 12 | compatible = "brcm,bcm2836-l1-intc"; |
13 | reg = <0x40000000 0x100>; | 13 | reg = <0x40000000 0x100>; |
14 | interrupt-controller; | 14 | interrupt-controller; |
15 | #interrupt-cells = <1>; | 15 | #interrupt-cells = <2>; |
16 | interrupt-parent = <&local_intc>; | 16 | interrupt-parent = <&local_intc>; |
17 | }; | 17 | }; |
18 | }; | 18 | }; |
@@ -20,10 +20,10 @@ | |||
20 | timer { | 20 | timer { |
21 | compatible = "arm,armv7-timer"; | 21 | compatible = "arm,armv7-timer"; |
22 | interrupt-parent = <&local_intc>; | 22 | interrupt-parent = <&local_intc>; |
23 | interrupts = <0>, // PHYS_SECURE_PPI | 23 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI |
24 | <1>, // PHYS_NONSECURE_PPI | 24 | <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI |
25 | <3>, // VIRT_PPI | 25 | <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI |
26 | <2>; // HYP_PPI | 26 | <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI |
27 | always-on; | 27 | always-on; |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -73,7 +73,7 @@ | |||
73 | compatible = "brcm,bcm2836-armctrl-ic"; | 73 | compatible = "brcm,bcm2836-armctrl-ic"; |
74 | reg = <0x7e00b200 0x200>; | 74 | reg = <0x7e00b200 0x200>; |
75 | interrupt-parent = <&local_intc>; | 75 | interrupt-parent = <&local_intc>; |
76 | interrupts = <8>; | 76 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | &cpu_thermal { | 79 | &cpu_thermal { |
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index dcde93c85c2d..18db25a5a66e 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <dt-bindings/clock/bcm2835.h> | 2 | #include <dt-bindings/clock/bcm2835.h> |
3 | #include <dt-bindings/clock/bcm2835-aux.h> | 3 | #include <dt-bindings/clock/bcm2835-aux.h> |
4 | #include <dt-bindings/gpio/gpio.h> | 4 | #include <dt-bindings/gpio/gpio.h> |
5 | #include <dt-bindings/interrupt-controller/irq.h> | ||
5 | 6 | ||
6 | /* firmware-provided startup stubs live here, where the secondary CPUs are | 7 | /* firmware-provided startup stubs live here, where the secondary CPUs are |
7 | * spinning. | 8 | * spinning. |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index c70476b34a53..d913aec85109 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -343,4 +343,12 @@ config MESON_IRQ_GPIO | |||
343 | help | 343 | help |
344 | Support Meson SoC Family GPIO Interrupt Multiplexer | 344 | Support Meson SoC Family GPIO Interrupt Multiplexer |
345 | 345 | ||
346 | config GOLDFISH_PIC | ||
347 | bool "Goldfish programmable interrupt controller" | ||
348 | depends on MIPS && (GOLDFISH || COMPILE_TEST) | ||
349 | select IRQ_DOMAIN | ||
350 | help | ||
351 | Say yes here to enable Goldfish interrupt controller driver used | ||
352 | for Goldfish based virtual platforms. | ||
353 | |||
346 | endmenu | 354 | endmenu |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d2df34a54d38..d27e3e3619e0 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -84,3 +84,4 @@ obj-$(CONFIG_QCOM_IRQ_COMBINER) += qcom-irq-combiner.o | |||
84 | obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o | 84 | obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o |
85 | obj-$(CONFIG_ARCH_SYNQUACER) += irq-sni-exiu.o | 85 | obj-$(CONFIG_ARCH_SYNQUACER) += irq-sni-exiu.o |
86 | obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o | 86 | obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o |
87 | obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o | ||
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c index 667b9e14b032..dfe4a460340b 100644 --- a/drivers/irqchip/irq-bcm2836.c +++ b/drivers/irqchip/irq-bcm2836.c | |||
@@ -98,13 +98,35 @@ static struct irq_chip bcm2836_arm_irqchip_gpu = { | |||
98 | .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq, | 98 | .irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq, |
99 | }; | 99 | }; |
100 | 100 | ||
101 | static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip) | 101 | static int bcm2836_map(struct irq_domain *d, unsigned int irq, |
102 | { | 102 | irq_hw_number_t hw) |
103 | int irq = irq_create_mapping(intc.domain, hwirq); | 103 | { |
104 | struct irq_chip *chip; | ||
105 | |||
106 | switch (hw) { | ||
107 | case LOCAL_IRQ_CNTPSIRQ: | ||
108 | case LOCAL_IRQ_CNTPNSIRQ: | ||
109 | case LOCAL_IRQ_CNTHPIRQ: | ||
110 | case LOCAL_IRQ_CNTVIRQ: | ||
111 | chip = &bcm2836_arm_irqchip_timer; | ||
112 | break; | ||
113 | case LOCAL_IRQ_GPU_FAST: | ||
114 | chip = &bcm2836_arm_irqchip_gpu; | ||
115 | break; | ||
116 | case LOCAL_IRQ_PMU_FAST: | ||
117 | chip = &bcm2836_arm_irqchip_pmu; | ||
118 | break; | ||
119 | default: | ||
120 | pr_warn_once("Unexpected hw irq: %lu\n", hw); | ||
121 | return -EINVAL; | ||
122 | } | ||
104 | 123 | ||
105 | irq_set_percpu_devid(irq); | 124 | irq_set_percpu_devid(irq); |
106 | irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq); | 125 | irq_domain_set_info(d, irq, hw, chip, d->host_data, |
126 | handle_percpu_devid_irq, NULL, NULL); | ||
107 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | 127 | irq_set_status_flags(irq, IRQ_NOAUTOEN); |
128 | |||
129 | return 0; | ||
108 | } | 130 | } |
109 | 131 | ||
110 | static void | 132 | static void |
@@ -165,7 +187,8 @@ static int bcm2836_cpu_dying(unsigned int cpu) | |||
165 | #endif | 187 | #endif |
166 | 188 | ||
167 | static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { | 189 | static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = { |
168 | .xlate = irq_domain_xlate_onecell | 190 | .xlate = irq_domain_xlate_onetwocell, |
191 | .map = bcm2836_map, | ||
169 | }; | 192 | }; |
170 | 193 | ||
171 | static void | 194 | static void |
@@ -218,19 +241,6 @@ static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node, | |||
218 | if (!intc.domain) | 241 | if (!intc.domain) |
219 | panic("%pOF: unable to create IRQ domain\n", node); | 242 | panic("%pOF: unable to create IRQ domain\n", node); |
220 | 243 | ||
221 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ, | ||
222 | &bcm2836_arm_irqchip_timer); | ||
223 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ, | ||
224 | &bcm2836_arm_irqchip_timer); | ||
225 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ, | ||
226 | &bcm2836_arm_irqchip_timer); | ||
227 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ, | ||
228 | &bcm2836_arm_irqchip_timer); | ||
229 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST, | ||
230 | &bcm2836_arm_irqchip_gpu); | ||
231 | bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST, | ||
232 | &bcm2836_arm_irqchip_pmu); | ||
233 | |||
234 | bcm2836_arm_irqchip_smp_init(); | 244 | bcm2836_arm_irqchip_smp_init(); |
235 | 245 | ||
236 | set_handle_irq(bcm2836_arm_irqchip_handle_irq); | 246 | set_handle_irq(bcm2836_arm_irqchip_handle_irq); |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index b56c3e23f0af..a874777e9b9d 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -1331,6 +1331,10 @@ gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header, | |||
1331 | u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2; | 1331 | u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2; |
1332 | void __iomem *redist_base; | 1332 | void __iomem *redist_base; |
1333 | 1333 | ||
1334 | /* GICC entry which has !ACPI_MADT_ENABLED is not unusable so skip */ | ||
1335 | if (!(gicc->flags & ACPI_MADT_ENABLED)) | ||
1336 | return 0; | ||
1337 | |||
1334 | redist_base = ioremap(gicc->gicr_base_address, size); | 1338 | redist_base = ioremap(gicc->gicr_base_address, size); |
1335 | if (!redist_base) | 1339 | if (!redist_base) |
1336 | return -ENOMEM; | 1340 | return -ENOMEM; |
@@ -1380,6 +1384,13 @@ static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header, | |||
1380 | if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) | 1384 | if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) |
1381 | return 0; | 1385 | return 0; |
1382 | 1386 | ||
1387 | /* | ||
1388 | * It's perfectly valid firmware can pass disabled GICC entry, driver | ||
1389 | * should not treat as errors, skip the entry instead of probe fail. | ||
1390 | */ | ||
1391 | if (!(gicc->flags & ACPI_MADT_ENABLED)) | ||
1392 | return 0; | ||
1393 | |||
1383 | return -ENODEV; | 1394 | return -ENODEV; |
1384 | } | 1395 | } |
1385 | 1396 | ||
diff --git a/drivers/irqchip/irq-goldfish-pic.c b/drivers/irqchip/irq-goldfish-pic.c new file mode 100644 index 000000000000..2a92f03c73e4 --- /dev/null +++ b/drivers/irqchip/irq-goldfish-pic.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Driver for MIPS Goldfish Programmable Interrupt Controller. | ||
3 | * | ||
4 | * Author: Miodrag Dinic <miodrag.dinic@mips.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | |||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/irqchip.h> | ||
17 | #include <linux/irqchip/chained_irq.h> | ||
18 | #include <linux/irqdomain.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/of_irq.h> | ||
21 | |||
22 | #define GFPIC_NR_IRQS 32 | ||
23 | |||
24 | /* 8..39 Cascaded Goldfish PIC interrupts */ | ||
25 | #define GFPIC_IRQ_BASE 8 | ||
26 | |||
27 | #define GFPIC_REG_IRQ_PENDING 0x04 | ||
28 | #define GFPIC_REG_IRQ_DISABLE_ALL 0x08 | ||
29 | #define GFPIC_REG_IRQ_DISABLE 0x0c | ||
30 | #define GFPIC_REG_IRQ_ENABLE 0x10 | ||
31 | |||
32 | struct goldfish_pic_data { | ||
33 | void __iomem *base; | ||
34 | struct irq_domain *irq_domain; | ||
35 | }; | ||
36 | |||
37 | static void goldfish_pic_cascade(struct irq_desc *desc) | ||
38 | { | ||
39 | struct goldfish_pic_data *gfpic = irq_desc_get_handler_data(desc); | ||
40 | struct irq_chip *host_chip = irq_desc_get_chip(desc); | ||
41 | u32 pending, hwirq, virq; | ||
42 | |||
43 | chained_irq_enter(host_chip, desc); | ||
44 | |||
45 | pending = readl(gfpic->base + GFPIC_REG_IRQ_PENDING); | ||
46 | while (pending) { | ||
47 | hwirq = __fls(pending); | ||
48 | virq = irq_linear_revmap(gfpic->irq_domain, hwirq); | ||
49 | generic_handle_irq(virq); | ||
50 | pending &= ~(1 << hwirq); | ||
51 | } | ||
52 | |||
53 | chained_irq_exit(host_chip, desc); | ||
54 | } | ||
55 | |||
56 | static const struct irq_domain_ops goldfish_irq_domain_ops = { | ||
57 | .xlate = irq_domain_xlate_onecell, | ||
58 | }; | ||
59 | |||
60 | static int __init goldfish_pic_of_init(struct device_node *of_node, | ||
61 | struct device_node *parent) | ||
62 | { | ||
63 | struct goldfish_pic_data *gfpic; | ||
64 | struct irq_chip_generic *gc; | ||
65 | struct irq_chip_type *ct; | ||
66 | unsigned int parent_irq; | ||
67 | int ret = 0; | ||
68 | |||
69 | gfpic = kzalloc(sizeof(*gfpic), GFP_KERNEL); | ||
70 | if (!gfpic) { | ||
71 | ret = -ENOMEM; | ||
72 | goto out_err; | ||
73 | } | ||
74 | |||
75 | parent_irq = irq_of_parse_and_map(of_node, 0); | ||
76 | if (!parent_irq) { | ||
77 | pr_err("Failed to map parent IRQ!\n"); | ||
78 | ret = -EINVAL; | ||
79 | goto out_free; | ||
80 | } | ||
81 | |||
82 | gfpic->base = of_iomap(of_node, 0); | ||
83 | if (!gfpic->base) { | ||
84 | pr_err("Failed to map base address!\n"); | ||
85 | ret = -ENOMEM; | ||
86 | goto out_unmap_irq; | ||
87 | } | ||
88 | |||
89 | /* Mask interrupts. */ | ||
90 | writel(1, gfpic->base + GFPIC_REG_IRQ_DISABLE_ALL); | ||
91 | |||
92 | gc = irq_alloc_generic_chip("GFPIC", 1, GFPIC_IRQ_BASE, gfpic->base, | ||
93 | handle_level_irq); | ||
94 | if (!gc) { | ||
95 | pr_err("Failed to allocate chip structures!\n"); | ||
96 | ret = -ENOMEM; | ||
97 | goto out_iounmap; | ||
98 | } | ||
99 | |||
100 | ct = gc->chip_types; | ||
101 | ct->regs.enable = GFPIC_REG_IRQ_ENABLE; | ||
102 | ct->regs.disable = GFPIC_REG_IRQ_DISABLE; | ||
103 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | ||
104 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | ||
105 | |||
106 | irq_setup_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS), 0, | ||
107 | IRQ_NOPROBE | IRQ_LEVEL, 0); | ||
108 | |||
109 | gfpic->irq_domain = irq_domain_add_legacy(of_node, GFPIC_NR_IRQS, | ||
110 | GFPIC_IRQ_BASE, 0, | ||
111 | &goldfish_irq_domain_ops, | ||
112 | NULL); | ||
113 | if (!gfpic->irq_domain) { | ||
114 | pr_err("Failed to add irqdomain!\n"); | ||
115 | ret = -ENOMEM; | ||
116 | goto out_destroy_generic_chip; | ||
117 | } | ||
118 | |||
119 | irq_set_chained_handler_and_data(parent_irq, | ||
120 | goldfish_pic_cascade, gfpic); | ||
121 | |||
122 | pr_info("Successfully registered.\n"); | ||
123 | return 0; | ||
124 | |||
125 | out_destroy_generic_chip: | ||
126 | irq_destroy_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS), | ||
127 | IRQ_NOPROBE | IRQ_LEVEL, 0); | ||
128 | out_iounmap: | ||
129 | iounmap(gfpic->base); | ||
130 | out_unmap_irq: | ||
131 | irq_dispose_mapping(parent_irq); | ||
132 | out_free: | ||
133 | kfree(gfpic); | ||
134 | out_err: | ||
135 | pr_err("Failed to initialize! (errno = %d)\n", ret); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | IRQCHIP_DECLARE(google_gf_pic, "google,goldfish-pic", goldfish_pic_of_init); | ||
diff --git a/drivers/irqchip/irq-ompic.c b/drivers/irqchip/irq-ompic.c index cf6d0c455518..e66ef4373b1e 100644 --- a/drivers/irqchip/irq-ompic.c +++ b/drivers/irqchip/irq-ompic.c | |||
@@ -171,9 +171,9 @@ static int __init ompic_of_init(struct device_node *node, | |||
171 | 171 | ||
172 | /* Setup the device */ | 172 | /* Setup the device */ |
173 | ompic_base = ioremap(res.start, resource_size(&res)); | 173 | ompic_base = ioremap(res.start, resource_size(&res)); |
174 | if (IS_ERR(ompic_base)) { | 174 | if (!ompic_base) { |
175 | pr_err("ompic: unable to map registers"); | 175 | pr_err("ompic: unable to map registers"); |
176 | return PTR_ERR(ompic_base); | 176 | return -ENOMEM; |
177 | } | 177 | } |
178 | 178 | ||
179 | irq = irq_of_parse_and_map(node, 0); | 179 | irq = irq_of_parse_and_map(node, 0); |