ARM: OMAP5: Add hook in SoC initcalls to enable pm initialization
[cascardo/linux.git] / arch / arm / mach-exynos / exynos.c
index 66c9b96..6a24e11 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/irqchip.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -29,6 +30,9 @@
 #include "common.h"
 #include "mfc.h"
 #include "regs-pmu.h"
+#include "regs-sys.h"
+
+void __iomem *pmu_base_addr;
 
 static struct map_desc exynos4_iodesc[] __initdata = {
        {
@@ -56,11 +60,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_PMU,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_PMU),
-               .length         = SZ_64K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
                .pfn            = __phys_to_pfn(EXYNOS4_PA_COMBINER),
@@ -135,19 +134,14 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_CMU),
                .length         = 144 * SZ_1K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_PMU,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_PMU),
-               .length         = SZ_64K,
-               .type           = MT_DEVICE,
        },
 };
 
-void exynos_restart(enum reboot_mode mode, const char *cmd)
+static void exynos_restart(enum reboot_mode mode, const char *cmd)
 {
        struct device_node *np;
        u32 val = 0x1;
-       void __iomem *addr = EXYNOS_SWRESET;
+       void __iomem *addr = pmu_base_addr + EXYNOS_SWRESET;
 
        if (of_machine_is_compatible("samsung,exynos5440")) {
                u32 status;
@@ -171,17 +165,6 @@ static struct platform_device exynos_cpuidle = {
        .id                = -1,
 };
 
-void __init exynos_cpuidle_init(void)
-{
-       if (soc_is_exynos4210() || soc_is_exynos5250())
-               platform_device_register(&exynos_cpuidle);
-}
-
-void __init exynos_cpufreq_init(void)
-{
-       platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-}
-
 void __iomem *sysram_base_addr;
 void __iomem *sysram_ns_base_addr;
 
@@ -204,7 +187,7 @@ void __init exynos_sysram_init(void)
        }
 }
 
-void __init exynos_init_late(void)
+static void __init exynos_init_late(void)
 {
        if (of_machine_is_compatible("samsung,exynos5440"))
                /* to be supported later */
@@ -251,7 +234,7 @@ static void __init exynos_map_io(void)
                iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
 }
 
-void __init exynos_init_io(void)
+static void __init exynos_init_io(void)
 {
        debug_ll_io_init();
 
@@ -263,6 +246,41 @@ void __init exynos_init_io(void)
        exynos_map_io();
 }
 
+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,exynos5250-pmu" },
+       { .compatible = "samsung,exynos5260-pmu" },
+       { .compatible = "samsung,exynos5410-pmu" },
+       { .compatible = "samsung,exynos5420-pmu" },
+       { /*sentinel*/ },
+};
+
+static void exynos_map_pmu(void)
+{
+       struct device_node *np;
+
+       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)
+{
+       irqchip_init();
+       /*
+        * Since platsmp.c needs pmu base address by the time
+        * DT is not unflatten so we can't use DT APIs before
+        * init_irq
+        */
+       exynos_map_pmu();
+}
+
 static void __init exynos_dt_machine_init(void)
 {
        struct device_node *i2c_np;
@@ -298,8 +316,11 @@ static void __init exynos_dt_machine_init(void)
        if (!IS_ENABLED(CONFIG_SMP))
                exynos_sysram_init();
 
-       exynos_cpuidle_init();
-       exynos_cpufreq_init();
+       if (of_machine_is_compatible("samsung,exynos4210") ||
+                       of_machine_is_compatible("samsung,exynos5250"))
+               platform_device_register(&exynos_cpuidle);
+
+       platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
 
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
@@ -352,6 +373,7 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
        .smp            = smp_ops(exynos_smp_ops),
        .map_io         = exynos_init_io,
        .init_early     = exynos_firmware_init,
+       .init_irq       = exynos_init_irq,
        .init_machine   = exynos_dt_machine_init,
        .init_late      = exynos_init_late,
        .dt_compat      = exynos_dt_compat,