ARM: EXYNOS: Map SYSRAM through generic DT bindings
authorSachin Kamat <sachin.kamat@linaro.org>
Mon, 12 May 2014 22:13:44 +0000 (07:13 +0900)
committerKukjin Kim <kgene.kim@samsung.com>
Wed, 14 May 2014 18:30:05 +0000 (03:30 +0900)
Instead of hardcoding the SYSRAM details for each SoC,
pass this information through device tree (DT) and make
the code SoC agnostic. Generic DT SRAM bindings are
used for achieving this.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
arch/arm/Kconfig
arch/arm/boot/dts/exynos4210-universal_c210.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4x12.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/firmware.c
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/platsmp.c

index ab438cb5af5570f5aae9b3215b9c73586ce80427..19ffaaed971ec3c48df88987a925d4b200c1e583 100644 (file)
@@ -843,6 +843,7 @@ config ARCH_EXYNOS
        select HAVE_S3C_RTC if RTC_CLASS
        select NEED_MACH_MEMORY_H
        select SPARSE_IRQ
+       select SRAM
        select USE_OF
        help
          Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
index 63e34b24b04f7fbf35b4f78e7e17ee8b4a314d05..9296dee10e264035e774c6a21b0a5d782eb4c52b 100644 (file)
                bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rw rootwait earlyprintk panic=5 maxcpus=1";
        };
 
+       sysram@02020000 {
+               smp-sysram@0 {
+                       status = "disabled";
+               };
+
+               smp-sysram@5000 {
+                       compatible = "samsung,exynos4210-sysram";
+                       reg = <0x5000 0x1000>;
+               };
+
+               smp-sysram@1f000 {
+                       status = "disabled";
+               };
+       };
+
        mct@10050000 {
                compatible = "none";
        };
index cacf6140dd2f58be5351f797d889d8b0563e461c..ee3001f38821a7d9ad32b93be4ad414a4f3070e6 100644 (file)
                pinctrl2 = &pinctrl_2;
        };
 
+       sysram@02020000 {
+               compatible = "mmio-sram";
+               reg = <0x02020000 0x20000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x02020000 0x20000>;
+
+               smp-sysram@0 {
+                       compatible = "samsung,exynos4210-sysram";
+                       reg = <0x0 0x1000>;
+               };
+
+               smp-sysram@1f000 {
+                       compatible = "samsung,exynos4210-sysram-ns";
+                       reg = <0x1f000 0x1000>;
+               };
+       };
+
        pd_lcd1: lcd1-power-domain@10023CA0 {
                compatible = "samsung,exynos4210-pd";
                reg = <0x10023CA0 0x20>;
index c4a9306f8529ab84ce3836781d1795b83c735e15..70e3765b51eee263bd921f35c57dafcb1936ca9f 100644 (file)
                interrupts = <2 2>, <3 2>, <18 2>, <19 2>;
        };
 
+       sysram@02020000 {
+               compatible = "mmio-sram";
+               reg = <0x02020000 0x40000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x02020000 0x40000>;
+
+               smp-sysram@0 {
+                       compatible = "samsung,exynos4210-sysram";
+                       reg = <0x0 0x1000>;
+               };
+
+               smp-sysram@2f000 {
+                       compatible = "samsung,exynos4210-sysram-ns";
+                       reg = <0x2f000 0x1000>;
+               };
+       };
+
        pd_isp: isp-power-domain@10023CA0 {
                compatible = "samsung,exynos4210-pd";
                reg = <0x10023CA0 0x20>;
index 37423314a02826a66670776c03109f1526449bc7..e44693e2cfdaa9ae7a79e5b6f5e2476e6570a8d7 100644 (file)
                };
        };
 
+       sysram@02020000 {
+               compatible = "mmio-sram";
+               reg = <0x02020000 0x30000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x02020000 0x30000>;
+
+               smp-sysram@0 {
+                       compatible = "samsung,exynos4210-sysram";
+                       reg = <0x0 0x1000>;
+               };
+
+               smp-sysram@2f000 {
+                       compatible = "samsung,exynos4210-sysram-ns";
+                       reg = <0x2f000 0x1000>;
+               };
+       };
+
        pd_gsc: gsc-power-domain@10044000 {
                compatible = "samsung,exynos4210-pd";
                reg = <0x10044000 0x20>;
index 0d1dea81af0c671a8eb5df2d32f5e7b7ff9b5b69..3f34196d394e9301c2e9f18ef0cf32007a6a26d7 100644 (file)
                };
        };
 
+       sysram@02020000 {
+               compatible = "mmio-sram";
+               reg = <0x02020000 0x54000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x02020000 0x54000>;
+
+               smp-sysram@0 {
+                       compatible = "samsung,exynos4210-sysram";
+                       reg = <0x0 0x1000>;
+               };
+
+               smp-sysram@53000 {
+                       compatible = "samsung,exynos4210-sysram-ns";
+                       reg = <0x53000 0x1000>;
+               };
+       };
+
        clock: clock-controller@10010000 {
                compatible = "samsung,exynos5420-clock";
                reg = <0x10010000 0x30000>;
index 9ef3f83efaffa642c9bbe26d68aa71750072c28e..963c51fb606c520a17df85b75621b5d6b2e15ea0 100644 (file)
@@ -18,6 +18,7 @@
 void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
 
 struct map_desc;
+extern void __iomem *sysram_ns_base_addr;
 void exynos_init_io(void);
 void exynos_restart(enum reboot_mode mode, const char *cmd);
 void exynos_cpuidle_init(void);
index b32a907d021d4a2b5a809a22899cb237464d0d57..e973ff5de7b394fdb11e5dd7962992c32485827c 100644 (file)
@@ -114,51 +114,6 @@ static struct map_desc exynos4_iodesc[] __initdata = {
        },
 };
 
-static struct map_desc exynos4_iodesc0[] __initdata = {
-       {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc exynos4_iodesc1[] __initdata = {
-       {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM,
-               .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc exynos4210_iodesc[] __initdata = {
-       {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
-               .pfn            = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc exynos4x12_iodesc[] __initdata = {
-       {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
-               .pfn            = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       },
-};
-
-static struct map_desc exynos5250_iodesc[] __initdata = {
-       {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
-               .pfn            = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       },
-};
-
 static struct map_desc exynos5_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S3C_VA_SYS,
@@ -180,11 +135,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_SROMC),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_SYSRAM,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_CMU,
                .pfn            = __phys_to_pfn(EXYNOS5_PA_CMU),
@@ -280,20 +230,6 @@ static void __init exynos_map_io(void)
 
        if (soc_is_exynos5())
                iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
-
-       if (soc_is_exynos4210()) {
-               if (samsung_rev() == EXYNOS4210_REV_0)
-                       iotable_init(exynos4_iodesc0,
-                                               ARRAY_SIZE(exynos4_iodesc0));
-               else
-                       iotable_init(exynos4_iodesc1,
-                                               ARRAY_SIZE(exynos4_iodesc1));
-               iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
-       }
-       if (soc_is_exynos4212() || soc_is_exynos4412())
-               iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
-       if (soc_is_exynos5250())
-               iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
 }
 
 void __init exynos_init_io(void)
index 932129ef26c66054a2bdeecaef9c0af1a9bba788..483dfcd690650c54674584169b99ef00967964d0 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <mach/map.h>
 
+#include "common.h"
 #include "smc.h"
 
 static int exynos_do_idle(void)
@@ -34,7 +35,12 @@ static int exynos_cpu_boot(int cpu)
 
 static int exynos_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
 {
-       void __iomem *boot_reg = S5P_VA_SYSRAM_NS + 0x1c + 4*cpu;
+       void __iomem *boot_reg;
+
+       if (!sysram_ns_base_addr)
+               return -ENODEV;
+
+       boot_reg = sysram_ns_base_addr + 0x1c + 4*cpu;
 
        __raw_writel(boot_addr, boot_reg);
        return 0;
index 7b046b59d9ecc8829a98699ed84a6ffcbad4a8f5..548269a606340aad4bd275684b4b9d98fc5e7f68 100644 (file)
 
 #include <plat/map-s5p.h>
 
-#define EXYNOS4_PA_SYSRAM0             0x02025000
-#define EXYNOS4_PA_SYSRAM1             0x02020000
-#define EXYNOS5_PA_SYSRAM              0x02020000
-#define EXYNOS4210_PA_SYSRAM_NS                0x0203F000
-#define EXYNOS4x12_PA_SYSRAM_NS                0x0204F000
-#define EXYNOS5250_PA_SYSRAM_NS                0x0204F000
-
 #define EXYNOS_PA_CHIPID               0x10000000
 
 #define EXYNOS4_PA_SYSCON              0x10010000
index 03e5e9f9470536c01180963261dabf0c0c0eca08..c11c5418e0fc9ee80fd857b5a5fa15065a633df0 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/of_address.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
 extern void exynos4_secondary_startup(void);
 
+static void __iomem *sysram_base_addr;
+void __iomem *sysram_ns_base_addr;
+
+static void __init exynos_smp_prepare_sysram(void)
+{
+       struct device_node *node;
+
+       for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
+               if (!of_device_is_available(node))
+                       continue;
+               sysram_base_addr = of_iomap(node, 0);
+               break;
+       }
+
+       for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
+               if (!of_device_is_available(node))
+                       continue;
+               sysram_ns_base_addr = of_iomap(node, 0);
+               break;
+       }
+}
+
 static inline void __iomem *cpu_boot_reg_base(void)
 {
        if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
                return S5P_INFORM5;
-       return S5P_VA_SYSRAM;
+       return sysram_base_addr;
 }
 
 static inline void __iomem *cpu_boot_reg(int cpu)
@@ -45,6 +68,8 @@ static inline void __iomem *cpu_boot_reg(int cpu)
        void __iomem *boot_reg;
 
        boot_reg = cpu_boot_reg_base();
+       if (!boot_reg)
+               return ERR_PTR(-ENODEV);
        if (soc_is_exynos4412())
                boot_reg += 4*cpu;
        else if (soc_is_exynos5420())
@@ -90,6 +115,7 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        unsigned long timeout;
        unsigned long phys_cpu = cpu_logical_map(cpu);
+       int ret = -ENOSYS;
 
        /*
         * Set synchronisation state between this boot processor
@@ -146,8 +172,18 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
                 * Try to set boot address using firmware first
                 * and fall back to boot register if it fails.
                 */
-               if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+               ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr);
+               if (ret && ret != -ENOSYS)
+                       goto fail;
+               if (ret == -ENOSYS) {
+                       void __iomem *boot_reg = cpu_boot_reg(phys_cpu);
+
+                       if (IS_ERR(boot_reg)) {
+                               ret = PTR_ERR(boot_reg);
+                               goto fail;
+                       }
                        __raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
+               }
 
                call_firmware_op(cpu_boot, phys_cpu);
 
@@ -163,9 +199,10 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
         * now the secondary core is starting up let it run its
         * calibrations, then wait for it to finish
         */
+fail:
        spin_unlock(&boot_lock);
 
-       return pen_release != -1 ? -ENOSYS : 0;
+       return pen_release != -1 ? ret : 0;
 }
 
 /*
@@ -205,6 +242,8 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
        if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
                scu_enable(scu_base_addr());
 
+       exynos_smp_prepare_sysram();
+
        /*
         * Write the address of secondary startup into the
         * system-wide flags register. The boot monitor waits
@@ -217,12 +256,21 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
        for (i = 1; i < max_cpus; ++i) {
                unsigned long phys_cpu;
                unsigned long boot_addr;
+               int ret;
 
                phys_cpu = cpu_logical_map(i);
                boot_addr = virt_to_phys(exynos4_secondary_startup);
 
-               if (call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr))
+               ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr);
+               if (ret && ret != -ENOSYS)
+                       break;
+               if (ret == -ENOSYS) {
+                       void __iomem *boot_reg = cpu_boot_reg(phys_cpu);
+
+                       if (IS_ERR(boot_reg))
+                               break;
                        __raw_writel(boot_addr, cpu_boot_reg(phys_cpu));
+               }
        }
 }