diff mbox

[v3,15/21] ARM: exynos4/5: convert pmu wakeup to stacked domains

Message ID 1421087187-26988-16-git-send-email-marc.zyngier@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marc Zyngier Jan. 12, 2015, 6:26 p.m. UTC
Exynos 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 fact that the PMU block is actually the first
interrupt controller in the chain for RTC, kernels with this patch
applied wont have any suspend-resume facility when booted
with old DTs, and old kernels with updated DTs may not even boot.

Also, I stronly suspect that there is more than two wake-up
interrupts on these platforms, but I leave it to the maintainers
to fix their mess.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/boot/dts/exynos4.dtsi    |   3 +
 arch/arm/boot/dts/exynos5250.dtsi |   3 +
 arch/arm/boot/dts/exynos5420.dtsi |   3 +
 arch/arm/mach-exynos/exynos.c     |  14 ++---
 arch/arm/mach-exynos/suspend.c    | 122 ++++++++++++++++++++++++++++++++++----
 5 files changed, 126 insertions(+), 19 deletions(-)

Comments

Pankaj Dubey Jan. 15, 2015, 6:41 a.m. UTC | #1
+CC: Thomas Abraham <thomas.ab@samsung.com>

Hi Mark,

On Monday 12 January 2015 11:56 PM, Marc Zyngier wrote:
> Exynos 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 fact that the PMU block is actually the first
> interrupt controller in the chain for RTC, kernels with this patch
> applied wont have any suspend-resume facility when booted
> with old DTs, and old kernels with updated DTs may not even boot.
>
> Also, I stronly suspect that there is more than two wake-up
> interrupts on these platforms, but I leave it to the maintainers
> to fix their mess.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>

I tested this series on Exynos5250, using kgene/for-next and 
linux-next/next-20150114, but S2R failed on Exynos5250 based SMDK board.

Following is the log I got on SMDK5250 board, (note I have added some 
debugging log to know what is happening)

I can see is S3C-RTC's "enable_irq_wake" is failing with error -6.
I also observed that even though we are adding pmu_domain_ops using 
irq_domain_add_hierarchy, but none of pmu_domain_ops are getting called.

Please let me know if I am missing anything or do I need to modify 
anything to test S2R on Exynos SoC.

---------------------
echo +10 > /sys/class/rtc/rtc1/wakealarm; sleep 1; echo mem > /sys/power/sta
te
[  257.428163] PM: Syncing filesystems ... done.
[  257.431786] Freezing user space processes ... (elapsed 0.003 seconds) 
done.
[  257.439680] Freezing remaining freezable tasks ... (elapsed 0.001 
seconds) done.
[  257.544451] wake enabled for irq 116
[  257.546916] CPU: 0 PID: 1311 Comm: ash Not tainted 
3.19.0-rc4-next-20150114-00023-g492ff37 #15
[  257.555141] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[  257.561231] [<c0014430>] (unwind_backtrace) from [<c0011594>] 
(show_stack+0x10/0x14)
[  257.568948] [<c0011594>] (show_stack) from [<c0418b00>] 
(dump_stack+0x84/0xc4)
[  257.576151] [<c0418b00>] (dump_stack) from [<c005ce30>] 
(set_irq_wake_real+0x58/0x8c)
[  257.583961] [<c005ce30>] (set_irq_wake_real) from [<c005cef0>] 
(irq_set_irq_wake+0x8c/0xf0)
[  257.592295] [<c005cef0>] (irq_set_irq_wake) from [<c02e9d94>] 
(s3c_rtc_suspend+0xb8/0xdc)
[  257.600456] [<c02e9d94>] (s3c_rtc_suspend) from [<c0298c80>] 
(dpm_run_callback.isra.13+0x1c/0x60)
[  257.609308] [<c0298c80>] (dpm_run_callback.isra.13) from [<c02996a0>] 
(__device_suspend+0x128/0x2d0)
[  257.618422] [<c02996a0>] (__device_suspend) from [<c029a850>] 
(dpm_suspend+0x64/0x22c)
[  257.626320] [<c029a850>] (dpm_suspend) from [<c0058488>] 
(suspend_devices_and_enter+0x88/0x3dc)
[  257.634999] [<c0058488>] (suspend_devices_and_enter) from 
[<c00589c8>] (pm_suspend+0x1ec/0x24c)
[  257.643680] [<c00589c8>] (pm_suspend) from [<c00576e0>] 
(state_store+0x68/0xb8)
[  257.650972] [<c00576e0>] (state_store) from [<c012835c>] 
(kernfs_fop_write+0xb8/0x19c)
[  257.658870] [<c012835c>] (kernfs_fop_write) from [<c00cf620>] 
(vfs_write+0xa0/0x1ac)
[  257.666595] [<c00cf620>] (vfs_write) from [<c00cfc78>] 
(SyS_write+0x44/0x9c)
[  257.673625] [<c00cfc78>] (SyS_write) from [<c000e6e0>] 
(ret_fast_syscall+0x0/0x30)
[  257.681176] genirq: PKD: irq_desc->name: (null): irq: 60
[  257.686469] genirq: PKD: set_irq_wake_real: ret: -6
[  257.691349] s3c-rtc 101e0000.rtc: enable_irq_wake failed: -6
[  257.708926] PM: suspend of devices complete after 260.482 msecs
[  257.713362] BUCK9: No configuration
[  257.716840] BUCK8: No configuration
[  257.720309] BUCK7: No configuration
[  257.723776] BUCK6: No configuration
[  257.727254] P1.8V_BUCK_OUT5: No configuration
[  257.731597] LDO26: No configuration
[  257.735066] LDO25: No configuration
[  257.738532] LDO24: No configuration
[  257.742009] LDO23: No configuration
[  257.745481] LDO22: No configuration
[  257.748954] LDO21: No configuration
[  257.752419] LDO20: No configuration
[  257.755897] LDO19: No configuration
[  257.759370] LDO18: No configuration
[  257.762835] LDO17: No configuration
[  257.766314] P1.8V_LDO_OUT16: No configuration
[  257.770653] P1.0V_LDO_OUT15: No configuration
[  257.774994] P1.8V_LDO_OUT14: No configuration
[  257.779334] P1.8V_LDO_OUT13: No configuration
[  257.783668] P3.0V_LDO_OUT12: No configuration
[  257.788013] P1.8V_LDO_OUT11: No configuration
[  257.792353] P1.8V_LDO_OUT10: No configuration
[  257.796693] LDO9: No configuration
[  257.800079] P1.0V_LDO_OUT8: No configuration
[  257.804332] P1.1V_LDO_OUT7: No configuration
[  257.808579] P1.1V_LDO_OUT6: No configuration
[  257.812838] P1.8V_LDO_OUT5: No configuration
[  257.817091] P2.8V_LDO_OUT4: No configuration
[  257.821345] P1.8V_LDO_OUT3: No configuration
[  257.825599] P1.2V_LDO_OUT2: No configuration
[  257.829851] P1.0V_LDO_OUT1: No configuration
[  257.835786] PM: late suspend of devices complete after 1.676 msecs
[  257.841913] PM: noirq suspend of devices complete after 1.420 msecs
[  257.846737] Disabling non-boot CPUs ...
[  257.850810] IRQ54 no longer affine to CPU1
[  257.850922] CPU1: shutdown

------------------------------------

Thanks,
Pankaj Dubey
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Marc Zyngier Jan. 16, 2015, 7:22 p.m. UTC | #2
Hi Pankaj,

On 15/01/15 06:41, Pankaj Dubey wrote:
> +CC: Thomas Abraham <thomas.ab@samsung.com>
> 
> Hi Mark,
> 
> On Monday 12 January 2015 11:56 PM, Marc Zyngier wrote:
>> Exynos 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 fact that the PMU block is actually the first
>> interrupt controller in the chain for RTC, kernels with this patch
>> applied wont have any suspend-resume facility when booted
>> with old DTs, and old kernels with updated DTs may not even boot.
>>
>> Also, I stronly suspect that there is more than two wake-up
>> interrupts on these platforms, but I leave it to the maintainers
>> to fix their mess.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>
> 
> I tested this series on Exynos5250, using kgene/for-next and 
> linux-next/next-20150114, but S2R failed on Exynos5250 based SMDK board.
> 
> Following is the log I got on SMDK5250 board, (note I have added some 
> debugging log to know what is happening)
> 
> I can see is S3C-RTC's "enable_irq_wake" is failing with error -6.
> I also observed that even though we are adding pmu_domain_ops using 
> irq_domain_add_hierarchy, but none of pmu_domain_ops are getting called.
> 
> Please let me know if I am missing anything or do I need to modify 
> anything to test S2R on Exynos SoC.

Thanks for giving it a go. One think I noticed is that I forgot to add a
"#interrupt-cells = <3>;" to the pmu_system_controller node.

Also, it would be interesting to know what is the hwirq associated with
the irq_desc you've printed below.

Thanks,

	M.

> ---------------------
> echo +10 > /sys/class/rtc/rtc1/wakealarm; sleep 1; echo mem > /sys/power/sta
> te
> [  257.428163] PM: Syncing filesystems ... done.
> [  257.431786] Freezing user space processes ... (elapsed 0.003 seconds) 
> done.
> [  257.439680] Freezing remaining freezable tasks ... (elapsed 0.001 
> seconds) done.
> [  257.544451] wake enabled for irq 116
> [  257.546916] CPU: 0 PID: 1311 Comm: ash Not tainted 
> 3.19.0-rc4-next-20150114-00023-g492ff37 #15
> [  257.555141] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [  257.561231] [<c0014430>] (unwind_backtrace) from [<c0011594>] 
> (show_stack+0x10/0x14)
> [  257.568948] [<c0011594>] (show_stack) from [<c0418b00>] 
> (dump_stack+0x84/0xc4)
> [  257.576151] [<c0418b00>] (dump_stack) from [<c005ce30>] 
> (set_irq_wake_real+0x58/0x8c)
> [  257.583961] [<c005ce30>] (set_irq_wake_real) from [<c005cef0>] 
> (irq_set_irq_wake+0x8c/0xf0)
> [  257.592295] [<c005cef0>] (irq_set_irq_wake) from [<c02e9d94>] 
> (s3c_rtc_suspend+0xb8/0xdc)
> [  257.600456] [<c02e9d94>] (s3c_rtc_suspend) from [<c0298c80>] 
> (dpm_run_callback.isra.13+0x1c/0x60)
> [  257.609308] [<c0298c80>] (dpm_run_callback.isra.13) from [<c02996a0>] 
> (__device_suspend+0x128/0x2d0)
> [  257.618422] [<c02996a0>] (__device_suspend) from [<c029a850>] 
> (dpm_suspend+0x64/0x22c)
> [  257.626320] [<c029a850>] (dpm_suspend) from [<c0058488>] 
> (suspend_devices_and_enter+0x88/0x3dc)
> [  257.634999] [<c0058488>] (suspend_devices_and_enter) from 
> [<c00589c8>] (pm_suspend+0x1ec/0x24c)
> [  257.643680] [<c00589c8>] (pm_suspend) from [<c00576e0>] 
> (state_store+0x68/0xb8)
> [  257.650972] [<c00576e0>] (state_store) from [<c012835c>] 
> (kernfs_fop_write+0xb8/0x19c)
> [  257.658870] [<c012835c>] (kernfs_fop_write) from [<c00cf620>] 
> (vfs_write+0xa0/0x1ac)
> [  257.666595] [<c00cf620>] (vfs_write) from [<c00cfc78>] 
> (SyS_write+0x44/0x9c)
> [  257.673625] [<c00cfc78>] (SyS_write) from [<c000e6e0>] 
> (ret_fast_syscall+0x0/0x30)
> [  257.681176] genirq: PKD: irq_desc->name: (null): irq: 60
> [  257.686469] genirq: PKD: set_irq_wake_real: ret: -6
> [  257.691349] s3c-rtc 101e0000.rtc: enable_irq_wake failed: -6
> [  257.708926] PM: suspend of devices complete after 260.482 msecs
> [  257.713362] BUCK9: No configuration
> [  257.716840] BUCK8: No configuration
> [  257.720309] BUCK7: No configuration
> [  257.723776] BUCK6: No configuration
> [  257.727254] P1.8V_BUCK_OUT5: No configuration
> [  257.731597] LDO26: No configuration
> [  257.735066] LDO25: No configuration
> [  257.738532] LDO24: No configuration
> [  257.742009] LDO23: No configuration
> [  257.745481] LDO22: No configuration
> [  257.748954] LDO21: No configuration
> [  257.752419] LDO20: No configuration
> [  257.755897] LDO19: No configuration
> [  257.759370] LDO18: No configuration
> [  257.762835] LDO17: No configuration
> [  257.766314] P1.8V_LDO_OUT16: No configuration
> [  257.770653] P1.0V_LDO_OUT15: No configuration
> [  257.774994] P1.8V_LDO_OUT14: No configuration
> [  257.779334] P1.8V_LDO_OUT13: No configuration
> [  257.783668] P3.0V_LDO_OUT12: No configuration
> [  257.788013] P1.8V_LDO_OUT11: No configuration
> [  257.792353] P1.8V_LDO_OUT10: No configuration
> [  257.796693] LDO9: No configuration
> [  257.800079] P1.0V_LDO_OUT8: No configuration
> [  257.804332] P1.1V_LDO_OUT7: No configuration
> [  257.808579] P1.1V_LDO_OUT6: No configuration
> [  257.812838] P1.8V_LDO_OUT5: No configuration
> [  257.817091] P2.8V_LDO_OUT4: No configuration
> [  257.821345] P1.8V_LDO_OUT3: No configuration
> [  257.825599] P1.2V_LDO_OUT2: No configuration
> [  257.829851] P1.0V_LDO_OUT1: No configuration
> [  257.835786] PM: late suspend of devices complete after 1.676 msecs
> [  257.841913] PM: noirq suspend of devices complete after 1.420 msecs
> [  257.846737] Disabling non-boot CPUs ...
> [  257.850810] IRQ54 no longer affine to CPU1
> [  257.850922] CPU1: shutdown
> 
> ------------------------------------
> 
> Thanks,
> Pankaj Dubey
>
diff mbox

Patch

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index b8168f1..adc189f 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -141,6 +141,8 @@ 
 	pmu_system_controller: system-controller@10020000 {
 		compatible = "samsung,exynos4210-pmu", "syscon";
 		reg = <0x10020000 0x4000>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	dsi_0: dsi@11C80000 {
@@ -253,6 +255,7 @@ 
 	rtc@10070000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x10070000 0x100>;
+		interrupt-parent = <&pmu_system_controller>;
 		interrupts = <0 44 0>, <0 45 0>;
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 0a229fc..c31007c 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -194,6 +194,8 @@ 
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
@@ -230,6 +232,7 @@ 
 	rtc: rtc@101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 517e50f..1946c76c 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -309,6 +309,7 @@ 
 	rtc: rtc@101E0000 {
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
+		interrupt-parent = <&pmu_system_controller>;
 		status = "disabled";
 	};
 
@@ -748,6 +749,8 @@ 
 		clock-names = "clkout16";
 		clocks = <&clock CLK_FIN_PLL>;
 		#clock-cells = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic>;
 	};
 
 	sysreg_system_controller: syscon@10050000 {
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index c13d083..e417fdc 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -175,16 +175,15 @@  static void __init exynos_init_io(void)
 	exynos_map_io();
 }
 
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to suspend.c.
+ */
 static const struct of_device_id exynos_dt_pmu_match[] = {
 	{ .compatible = "samsung,exynos3250-pmu" },
-	{ .compatible = "samsung,exynos4210-pmu" },
-	{ .compatible = "samsung,exynos4212-pmu" },
-	{ .compatible = "samsung,exynos4412-pmu" },
-	{ .compatible = "samsung,exynos4415-pmu" },
-	{ .compatible = "samsung,exynos5250-pmu" },
 	{ .compatible = "samsung,exynos5260-pmu" },
 	{ .compatible = "samsung,exynos5410-pmu" },
-	{ .compatible = "samsung,exynos5420-pmu" },
 	{ /*sentinel*/ },
 };
 
@@ -195,9 +194,6 @@  static void exynos_map_pmu(void)
 	np = of_find_matching_node(NULL, exynos_dt_pmu_match);
 	if (np)
 		pmu_base_addr = of_iomap(np, 0);
-
-	if (!pmu_base_addr)
-		panic("failed to find exynos pmu register\n");
 }
 
 static void __init exynos_init_irq(void)
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index f8e7dcd..b325ecd 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -18,7 +18,9 @@ 
 #include <linux/syscore_ops.h>
 #include <linux/cpu_pm.h>
 #include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
 #include <linux/err.h>
 #include <linux/regulator/machine.h>
 
@@ -44,8 +46,8 @@ 
 #define EXYNOS5420_CPU_STATE	0x28
 
 /**
- * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
- * @hwirq: Hardware IRQ signal of the GIC
+ * struct exynos_wkup_irq - PMU IRQ to mask mapping
+ * @hwirq: Hardware IRQ signal of the PMU
  * @mask: Mask in PMU wake-up mask register
  */
 struct exynos_wkup_irq {
@@ -92,14 +94,14 @@  static unsigned int exynos_pmu_spare3;
 static u32 exynos_irqwake_intmask = 0xffffffff;
 
 static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
-	{ 76, BIT(1) }, /* RTC alarm */
-	{ 77, BIT(2) }, /* RTC tick */
+	{ 44, BIT(1) }, /* RTC alarm */
+	{ 45, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
 static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
-	{ 75, BIT(1) }, /* RTC alarm */
-	{ 76, BIT(2) }, /* RTC tick */
+	{ 43, BIT(1) }, /* RTC alarm */
+	{ 44, BIT(2) }, /* RTC tick */
 	{ /* sentinel */ },
 };
 
@@ -153,6 +155,109 @@  static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
 	return -ENOENT;
 }
 
+static struct irq_chip exynos_pmu_chip = {
+	.name		= "PMU",
+	.irq_eoi	= irq_chip_eoi_parent,
+	.irq_mask	= irq_chip_mask_parent,
+	.irq_unmask	= irq_chip_unmask_parent,
+	.irq_retrigger	= irq_chip_retrigger_hierarchy,
+	.irq_set_wake	= exynos_irq_set_wake,
+};
+
+static int exynos_pmu_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 exynos_pmu_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];
+
+	for (i = 0; i < nr_irqs; i++)
+		irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+					      &exynos_pmu_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 exynos_pmu_domain_ops = {
+	.xlate	= exynos_pmu_domain_xlate,
+	.alloc	= exynos_pmu_domain_alloc,
+	.free	= irq_domain_free_irqs_common,
+};
+
+static int __init exynos_pmu_irq_init(struct device_node *node,
+				      struct device_node *parent)
+{
+	struct irq_domain *parent_domain, *domain;
+
+	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;
+	}
+
+	pmu_base_addr = of_iomap(node, 0);
+
+	if (!pmu_base_addr) {
+		pr_err("%s: failed to find exynos pmu register\n",
+		       node->full_name);
+		return -ENOMEM;
+	}
+
+	domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
+					  node, &exynos_pmu_domain_ops,
+					  NULL);
+	if (!domain) {
+		iounmap(pmu_base_addr);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+#define EXYNOS_PMU_IRQ(symbol, name)	OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+
+EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
+EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
+EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
+EXYNOS_PMU_IRQ(exynos4415_pmu_irq, "samsung,exynos4415-pmu");
+EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
+EXYNOS_PMU_IRQ(exynos5420_pmu_irq, "samsung,exynos5420-pmu");
+
 static int exynos_cpu_do_idle(void)
 {
 	/* issue the standby signal into the pm unit. */
@@ -550,9 +655,6 @@  void __init exynos_pm_init(void)
 	}
 	pm_data = (struct exynos_pm_data *) match->data;
 
-	/* Platform-specific GIC callback */
-	gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
-
 	/* All wakeup disable */
 	tmp = pmu_raw_readl(S5P_WAKEUP_MASK);
 	tmp |= pm_data->wake_disable_mask;