ARM: omap: convert wakeupgen to stacked domains
authorMarc Zyngier <marc.zyngier@arm.com>
Wed, 11 Mar 2015 15:43:49 +0000 (15:43 +0000)
committerJason Cooper <jason@lakedaemon.net>
Sun, 15 Mar 2015 00:56:13 +0000 (00:56 +0000)
OMAP4/5 has been (ab)using the gic_arch_extn to provide
wakeup from suspend, and it makes a lot of sense to convert
this code to use stacked domains instead.

This patch does just this, updating the DT files to actually
reflect what the HW provides.

BIG FAT WARNING: because the DTs were so far lying by not
exposing the WUGEN HW block, kernels with this patch applied
won't have any suspend-resume facility when booted with old DTs,
and old kernels with updated DTs won't even boot.

On a platform with this patch applied, the system looks like
this:

root@bacon-fat:~# cat /proc/interrupts
            CPU0       CPU1
 16:          0          0     WUGEN  37  gp_timer
 19:     233799     155916       GIC  27  arch_timer
 23:          0          0     WUGEN   9  l3-dbg-irq
 24:          1          0     WUGEN  10  l3-app-irq
 27:        282          0     WUGEN  13  omap-dma-engine
 44:          0          0  4ae10000.gpio  13  DMA
294:          0          0     WUGEN  20  gpmc
297:        506          0     WUGEN  56  48070000.i2c
298:          0          0     WUGEN  57  48072000.i2c
299:          0          0     WUGEN  61  48060000.i2c
300:          0          0     WUGEN  62  4807a000.i2c
301:          8          0     WUGEN  60  4807c000.i2c
308:       2439          0     WUGEN  74  OMAP UART2
312:        362          0     WUGEN  83  mmc2
313:        502          0     WUGEN  86  mmc0
314:         13          0     WUGEN  94  mmc1
350:          0          0      PRCM  pinctrl, pinctrl
406:   35155709          0       GIC 109  ehci_hcd:usb1
407:          0          0     WUGEN   7  palmas
409:          0          0     WUGEN 119  twl6040
410:          0          0   twl6040   5  twl6040_irq_ready
411:          0          0   twl6040   0  twl6040_irq_th
IPI0:          0          1  CPU wakeup interrupts
IPI1:          0          0  Timer broadcast interrupts
IPI2:      95334     902334  Rescheduling interrupts
IPI3:          0          0  Function call interrupts
IPI4:        479        648  Single function call interrupts
IPI5:          0          0  CPU stop interrupts
IPI6:          0          0  IRQ work interrupts
IPI7:          0          0  completion interrupts
Err:          0

Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/1426088629-15377-8-git-send-email-marc.zyngier@arm.com
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
18 files changed:
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am437x-sk-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra72x.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/omap4-duovero.dtsi
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var-som-om44.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-cm-t54.dts
arch/arm/boot/dts/omap5-uevm.dts
arch/arm/boot/dts/omap5.dtsi
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap-wakeupgen.h
arch/arm/mach-omap2/omap4-common.c

index 1943fc333e7c34c8ce13648000e94d233e7a733f..8a099bc10c1e4579e765819d2f87bd92bec8e4a5 100644 (file)
@@ -15,7 +15,7 @@
 
 / {
        compatible = "ti,am4372", "ti,am43";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
 
        aliases {
                #interrupt-cells = <3>;
                reg = <0x48241000 0x1000>,
                      <0x48240100 0x0100>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        l2-cache-controller@48242000 {
index f84d9715a4a9fc286dbfca7af4e9d5963cda6549..26956cb50835d660d4a853e52e913eca9190e4e5 100644 (file)
                reg = <0x24>;
                compatible = "ti,tps65218";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-               interrupt-parent = <&gic>;
                interrupt-controller;
                #interrupt-cells = <2>;
 
index 832d24318f62b538da305b4939f71b31e7ca1d86..8ae29c955c11d7f83f4423184a8ed61412b515dd 100644 (file)
        tps@24 {
                compatible = "ti,tps65218";
                reg = <0x24>;
-               interrupt-parent = <&gic>;
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-controller;
                #interrupt-cells = <2>;
index 257c099c347e422b9dcde514355172958f14fb3f..1d7109196872299464ccfb5f3a1938b76e4f68ef 100644 (file)
                reg = <0x24>;
                compatible = "ti,tps65218";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
-               interrupt-parent = <&gic>;
                interrupt-controller;
                #interrupt-cells = <2>;
 
index 850f949d409a5d878a24917ca85c74de6493b2d7..c65eea095afa24d38c500ad6ea0f130651f6aa0e 100644 (file)
                interrupt-parent = <&gic>;
        };
 
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
+       };
+
        /*
         * The soc node represents the soc top level view. It is used for IPs
         * that are not memory mapped in the MPU view or for the MPU itself.
                reg = <0x44000000 0x1000000>,
                      <0x45000000 0x1000>;
                interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
-                                     <&gic GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+                                     <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
                prm: prm@4ae06000 {
                        compatible = "ti,dra7-prm";
                        compatible = "ti,irq-crossbar";
                        reg = <0x4a002a48 0x130>;
                        interrupt-controller;
-                       interrupt-parent = <&gic>;
+                       interrupt-parent = <&wakeupgen>;
                        #interrupt-cells = <3>;
                        ti,max-irqs = <160>;
                        ti,max-crossbar-sources = <MAX_SOURCES>;
index e782bf1dd863df0e8332c739a998dd89de5089f4..f7fb0d0ef25a5400b5738ba8b8afad955cded5f5 100644 (file)
@@ -25,7 +25,7 @@
 
        pmu {
                compatible = "arm,cortex-a15-pmu";
-               interrupt-parent = <&gic>;
+               interrupt-parent = <&wakeupgen>;
                interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
        };
 };
index 0fc758db55f54a4b3231d3bf36a3fe986e5e0503..00eeed789b4b74a306137f82d6fb70ebea831fe7 100644 (file)
@@ -41,7 +41,7 @@
 
        pmu {
                compatible = "arm,cortex-a15-pmu";
-               interrupt-parent = <&gic>;
+               interrupt-parent = <&wakeupgen>;
                interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
        };
index e860ccd9d09c073aa57a9f599b54e038ee70f0c7..f2a94fa625527661e19b4983f27372be0119f7e0 100644 (file)
        twl: twl@48 {
                reg = <0x48>;
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;           /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
                compatible = "ti,twl6040";
                reg = <0x4b>;
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;         /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio6 0 GPIO_ACTIVE_HIGH>;         /* gpio_160 */
 
                vio-supply = <&v1v8>;
index 150513506c19f9764f63cd5828b79d4b7b1417f5..7c15fb2e2fe4098a7393bb7fa1239e37a4ebab3d 100644 (file)
                reg = <0x48>;
                /* IRQ# = 7 */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* IRQ# = 119 */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio4 31 GPIO_ACTIVE_HIGH>;  /* gpio line 127 */
 
                vio-supply = <&v1v8>;
 };
 
 &uart2 {
-       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART2_RX>;
 };
 
 &uart3 {
-       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART3_RX>;
 };
 
 &uart4 {
-       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART4_RX>;
 };
 
index 3e1da43068f68e67f7578d5eda64c12ea33501ca..8aca8dae968ad276f193a3b3c969082a23dcc7e7 100644 (file)
                reg = <0x48>;
                /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
 
                vio-supply = <&v1v8>;
 };
 
 &uart2 {
-       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART2_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart2_pins>;
 };
 
 &uart3 {
-       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART3_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins>;
 };
 
 &uart4 {
-       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+       interrupts-extended = <&wakeupgen GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
                               &omap4_pmx_core OMAP4_UART4_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart4_pins>;
index 062701e1a8981cc800ebbcc8b2edcfc0f80e3e30..a4f1ba2e1903baead6b8be5f59ae8a87a157a109 100644 (file)
                reg = <0x48>;
                /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
-               interrupt-parent = <&gic>;
        };
 
        twl6040: twl@4b {
 
                /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
                interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio6 22 0>; /* gpio 182 */
 
                vio-supply = <&v1v8>;
index 074147cebae49f965b254915240b667bffcf9d21..7cb5236f751d9e2d2ef29a3f05fc707b6565b636 100644 (file)
@@ -14,7 +14,7 @@
 
 / {
        compatible = "ti,omap4430", "ti,omap4";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
        aliases {
                i2c0 = &i2c1;
@@ -56,6 +56,7 @@
                #interrupt-cells = <3>;
                reg = <0x48241000 0x1000>,
                      <0x48240100 0x0100>;
+               interrupt-parent = <&gic>;
        };
 
        L2: l2-cache-controller@48242000 {
                clocks = <&mpu_periphclk>;
                reg = <0x48240600 0x20>;
                interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        /*
                uart2: serial@4806c000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                };
                uart3: serial@48020000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                };
                uart4: serial@4806e000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                };
index b54b271e153b65ccc709af6a2e298ef907fb63c3..61ad2ea347204bc9154b120ec861a7658f67f61b 100644 (file)
        palmas: palmas@48 {
                compatible = "ti,palmas";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-               interrupt-parent = <&gic>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
index 159720d6c9569aa6b13c65ee3674ca64d335a21e..74777a6e200a68bb7cda9257d70aee78549bc8bd 100644 (file)
        palmas: palmas@48 {
                compatible = "ti,palmas";
                interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
-               interrupt-parent = <&gic>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
                pinctrl-0 = <&twl6040_pins>;
 
                interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-               interrupt-parent = <&gic>;
                ti,audpwron-gpio = <&gpio5 13 0>;  /* gpio line 141 */
 
                vio-supply = <&smps7_reg>;
index b321fdf42c9f3c51e3a59d4b51b27a08f4fcaba4..b056156e2a7a2ce6395e77cbd45de40eab075e7a 100644 (file)
@@ -18,7 +18,7 @@
        #size-cells = <1>;
 
        compatible = "ti,omap5";
-       interrupt-parent = <&gic>;
+       interrupt-parent = <&wakeupgen>;
 
        aliases {
                i2c0 = &i2c1;
@@ -79,6 +79,7 @@
                             <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 11 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 10 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupt-parent = <&gic>;
        };
 
        pmu {
                      <0x48212000 0x1000>,
                      <0x48214000 0x2000>,
                      <0x48216000 0x2000>;
+               interrupt-parent = <&gic>;
+       };
+
+       wakeupgen: interrupt-controller@48281000 {
+               compatible = "ti,omap5-wugen-mpu", "ti,omap4-wugen-mpu";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               reg = <0x48281000 0x1000>;
+               interrupt-parent = <&gic>;
        };
 
        /*
                uart1: serial@4806a000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806a000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart1";
                        clock-frequency = <48000000>;
                };
                uart2: serial@4806c000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806c000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart2";
                        clock-frequency = <48000000>;
                };
                uart3: serial@48020000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48020000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart3";
                        clock-frequency = <48000000>;
                };
                uart4: serial@4806e000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x4806e000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart4";
                        clock-frequency = <48000000>;
                };
                uart5: serial@48066000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48066000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart5";
                        clock-frequency = <48000000>;
                };
                uart6: serial@48068000 {
                        compatible = "ti,omap4-uart";
                        reg = <0x48068000 0x100>;
-                       interrupts-extended = <&gic GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
                        ti,hwmods = "uart6";
                        clock-frequency = <48000000>;
                };
                        usbhsohci: ohci@4a064800 {
                                compatible = "ti,ohci-omap3";
                                reg = <0x4a064800 0x400>;
-                               interrupt-parent = <&gic>;
                                interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
                        usbhsehci: ehci@4a064c00 {
                                compatible = "ti,ehci-omap";
                                reg = <0x4a064c00 0x400>;
-                               interrupt-parent = <&gic>;
                                interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
                        };
                };
index f961c46453b97c3ba7aa636af837e4cc66801260..3b56722dfd8a975c77da8e1599207c8b447e290c 100644 (file)
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu_pm.h>
-#include <linux/irqchip/arm-gic.h>
 
 #include "omap-wakeupgen.h"
 #include "omap-secure.h"
@@ -78,29 +79,12 @@ static inline void sar_writel(u32 val, u32 offset, u8 idx)
 
 static inline int _wakeupgen_get_irq_info(u32 irq, u32 *bit_posn, u8 *reg_index)
 {
-       unsigned int spi_irq;
-
-       /*
-        * PPIs and SGIs are not supported.
-        */
-       if (irq < OMAP44XX_IRQ_GIC_START)
-               return -EINVAL;
-
-       /*
-        * Subtract the GIC offset.
-        */
-       spi_irq = irq - OMAP44XX_IRQ_GIC_START;
-       if (spi_irq > MAX_IRQS) {
-               pr_err("omap wakeupGen: Invalid IRQ%d\n", irq);
-               return -EINVAL;
-       }
-
        /*
         * Each WakeupGen register controls 32 interrupt.
         * i.e. 1 bit per SPI IRQ
         */
-       *reg_index = spi_irq >> 5;
-       *bit_posn = spi_irq %= 32;
+       *reg_index = irq >> 5;
+       *bit_posn = irq %= 32;
 
        return 0;
 }
@@ -141,6 +125,7 @@ static void wakeupgen_mask(struct irq_data *d)
        raw_spin_lock_irqsave(&wakeupgen_lock, flags);
        _wakeupgen_clear(d->hwirq, irq_target_cpu[d->hwirq]);
        raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+       irq_chip_mask_parent(d);
 }
 
 /*
@@ -153,6 +138,7 @@ static void wakeupgen_unmask(struct irq_data *d)
        raw_spin_lock_irqsave(&wakeupgen_lock, flags);
        _wakeupgen_set(d->hwirq, irq_target_cpu[d->hwirq]);
        raw_spin_unlock_irqrestore(&wakeupgen_lock, flags);
+       irq_chip_unmask_parent(d);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -400,15 +386,91 @@ int omap_secure_apis_support(void)
        return omap_secure_apis;
 }
 
+static struct irq_chip wakeupgen_chip = {
+       .name                   = "WUGEN",
+       .irq_eoi                = irq_chip_eoi_parent,
+       .irq_mask               = wakeupgen_mask,
+       .irq_unmask             = wakeupgen_unmask,
+       .irq_retrigger          = irq_chip_retrigger_hierarchy,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int wakeupgen_domain_xlate(struct irq_domain *domain,
+                                 struct device_node *controller,
+                                 const u32 *intspec,
+                                 unsigned int intsize,
+                                 unsigned long *out_hwirq,
+                                 unsigned int *out_type)
+{
+       if (domain->of_node != controller)
+               return -EINVAL; /* Shouldn't happen, really... */
+       if (intsize != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (intspec[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       *out_hwirq = intspec[1];
+       *out_type = intspec[2];
+       return 0;
+}
+
+static int wakeupgen_domain_alloc(struct irq_domain *domain,
+                                 unsigned int virq,
+                                 unsigned int nr_irqs, void *data)
+{
+       struct of_phandle_args *args = data;
+       struct of_phandle_args parent_args;
+       irq_hw_number_t hwirq;
+       int i;
+
+       if (args->args_count != 3)
+               return -EINVAL; /* Not GIC compliant */
+       if (args->args[0] != 0)
+               return -EINVAL; /* No PPI should point to this domain */
+
+       hwirq = args->args[1];
+       if (hwirq >= MAX_IRQS)
+               return -EINVAL; /* Can't deal with this */
+
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+                                             &wakeupgen_chip, NULL);
+
+       parent_args = *args;
+       parent_args.np = domain->parent->of_node;
+       return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops wakeupgen_domain_ops = {
+       .xlate  = wakeupgen_domain_xlate,
+       .alloc  = wakeupgen_domain_alloc,
+       .free   = irq_domain_free_irqs_common,
+};
+
 /*
  * Initialise the wakeupgen module.
  */
-int __init omap_wakeupgen_init(void)
+static int __init wakeupgen_init(struct device_node *node,
+                                struct device_node *parent)
 {
+       struct irq_domain *parent_domain, *domain;
        int i;
        unsigned int boot_cpu = smp_processor_id();
        u32 val;
 
+       if (!parent) {
+               pr_err("%s: no parent, giving up\n", node->full_name);
+               return -ENODEV;
+       }
+
+       parent_domain = irq_find_host(parent);
+       if (!parent_domain) {
+               pr_err("%s: unable to obtain parent domain\n", node->full_name);
+               return -ENXIO;
+       }
        /* Not supported on OMAP4 ES1.0 silicon */
        if (omap_rev() == OMAP4430_REV_ES1_0) {
                WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n");
@@ -416,7 +478,7 @@ int __init omap_wakeupgen_init(void)
        }
 
        /* Static mapping, never released */
-       wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
+       wakeupgen_base = of_iomap(node, 0);
        if (WARN_ON(!wakeupgen_base))
                return -ENOMEM;
 
@@ -429,6 +491,14 @@ int __init omap_wakeupgen_init(void)
                max_irqs = AM43XX_IRQS;
        }
 
+       domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs,
+                                         node, &wakeupgen_domain_ops,
+                                         NULL);
+       if (!domain) {
+               iounmap(wakeupgen_base);
+               return -ENOMEM;
+       }
+
        /* Clear all IRQ bitmasks at wakeupGen level */
        for (i = 0; i < irq_banks; i++) {
                wakeupgen_writel(0, i, CPU0_ID);
@@ -436,14 +506,6 @@ int __init omap_wakeupgen_init(void)
                        wakeupgen_writel(0, i, CPU1_ID);
        }
 
-       /*
-        * Override GIC architecture specific functions to add
-        * OMAP WakeupGen interrupt controller along with GIC
-        */
-       gic_arch_extn.irq_mask = wakeupgen_mask;
-       gic_arch_extn.irq_unmask = wakeupgen_unmask;
-       gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
-
        /*
         * FIXME: Add support to set_smp_affinity() once the core
         * GIC code has necessary hooks in place.
@@ -474,3 +536,9 @@ int __init omap_wakeupgen_init(void)
 
        return 0;
 }
+
+/*
+ * We cannot use the IRQCHIP_DECLARE macro that lives in
+ * drivers/irqchip, so we're forced to roll our own. Not very nice.
+ */
+OF_DECLARE_2(irqchip, ti_wakeupgen, "ti,omap4-wugen-mpu", wakeupgen_init);
index b3c8eccfae790de050f853d7528662a3a5c33aa2..a3491ad12368f9fd8e7f03dd12799634d76f3a7e 100644 (file)
@@ -33,7 +33,6 @@
 #define OMAP_TIMESTAMPCYCLELO                  0xc08
 #define OMAP_TIMESTAMPCYCLEHI                  0xc0c
 
-extern int __init omap_wakeupgen_init(void);
 extern void __iomem *omap_get_wakeupgen_base(void);
 extern int omap_secure_apis_support(void);
 #endif
index cf7aafb27fd11cb76567083a76c4ad5f74c06634..7bb116a6f86f5b88c35830c2e2b78fd291b43499 100644 (file)
@@ -241,26 +241,26 @@ static int __init omap4_sar_ram_init(void)
 }
 omap_early_initcall(omap4_sar_ram_init);
 
-static const struct of_device_id gic_match[] = {
-       { .compatible = "arm,cortex-a9-gic", },
-       { .compatible = "arm,cortex-a15-gic", },
+static const struct of_device_id intc_match[] = {
+       { .compatible = "ti,omap4-wugen-mpu", },
+       { .compatible = "ti,omap5-wugen-mpu", },
        { },
 };
 
-static struct device_node *gic_node;
+static struct device_node *intc_node;
 
 unsigned int omap4_xlate_irq(unsigned int hwirq)
 {
        struct of_phandle_args irq_data;
        unsigned int irq;
 
-       if (!gic_node)
-               gic_node = of_find_matching_node(NULL, gic_match);
+       if (!intc_node)
+               intc_node = of_find_matching_node(NULL, intc_match);
 
-       if (WARN_ON(!gic_node))
+       if (WARN_ON(!intc_node))
                return hwirq;
 
-       irq_data.np = gic_node;
+       irq_data.np = intc_node;
        irq_data.args_count = 3;
        irq_data.args[0] = 0;
        irq_data.args[1] = hwirq - OMAP44XX_IRQ_GIC_START;
@@ -277,6 +277,12 @@ void __init omap_gic_of_init(void)
 {
        struct device_node *np;
 
+       intc_node = of_find_matching_node(NULL, intc_match);
+       if (WARN_ON(!intc_node)) {
+               pr_err("No WUGEN found in DT, system will misbehave.\n");
+               pr_err("UPDATE YOUR DEVICE TREE!\n");
+       }
+
        /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */
        if (!cpu_is_omap446x())
                goto skip_errata_init;
@@ -290,6 +296,5 @@ void __init omap_gic_of_init(void)
        WARN_ON(!twd_base);
 
 skip_errata_init:
-       omap_wakeupgen_init();
        irqchip_init();
 }