This patch enables CPU cores on Exynos4, on Exynos4412 secondary CPU cores
are power-gated, therefore we must turn on the CPU cores on the system boot.

Shows below log message on boot.
[    0.045000] CPU: Testing write buffer coherency: ok
[    0.045000] CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00
[    0.045000] hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7
counters e
[    0.045000] Setting up static identity map for 0x40370790 - 0x403707e8
[    0.045000] L310 cache controller enabled
[    0.045000] l2x0: 16 ways, CACHE_ID 0x4100c4c8, AUX_CTRL 0x7e470001, Cache
sizeB
[    0.070000] CPU1: Booted secondary processor
[    0.090000] CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01
[    0.090000] CPU1: Unknown IPI message 0x1
[    0.100000] CPU2: Booted secondary processor
[    0.120000] CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02
[    0.120000] CPU2: Unknown IPI message 0x1
[    0.130000] CPU3: Booted secondary processor
[    0.150000] CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03
[    0.150000] CPU3: Unknown IPI message 0x1
[    0.150000] Brought up 4 CPUs
[    0.150000] SMP: Total of 4 processors activated (7969.17 BogoMIPS).

Change-Id: I61615c5b719d3646698f114fc3777eb304694099
Signed-off-by: Dongjin Kim <dongjin....@agreeyamobility.net>
---
 arch/arm/mach-exynos/hotplug.c               |    4 +-
 arch/arm/mach-exynos/include/mach/regs-pmu.h |   11 ++-
 arch/arm/mach-exynos/platsmp.c               |  100 +++++++++++++++++---------
 3 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index 9c17a0a..cd53497 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -66,8 +66,8 @@ static inline void platform_do_lowpower(unsigned int cpu, int 
*spurious)
        for (;;) {
 
                /* make cpu1 to be turned off at next WFI command */
-               if (cpu == 1)
-                       __raw_writel(0, S5P_ARM_CORE1_CONFIGURATION);
+               if ((cpu >= 1) && (cpu < num_possible_cpus()))
+                       __raw_writel(0, S5P_ARM_CORE_CONFIGURATION(cpu));
 
                /*
                 * here's the WFI
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h 
b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index d4e392b..0bb21e2 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -123,10 +123,15 @@
 #define S5P_GPS_ALIVE_LOWPWR                   S5P_PMUREG(0x13A0)
 
 #define S5P_ARM_CORE0_CONFIGURATION            S5P_PMUREG(0x2000)
+#define S5P_ARM_CORE0_STATUS                   S5P_PMUREG(0x2004)
 #define S5P_ARM_CORE0_OPTION                   S5P_PMUREG(0x2008)
-#define S5P_ARM_CORE1_CONFIGURATION            S5P_PMUREG(0x2080)
-#define S5P_ARM_CORE1_STATUS                   S5P_PMUREG(0x2084)
-#define S5P_ARM_CORE1_OPTION                   S5P_PMUREG(0x2088)
+
+#define S5P_ARM_CORE_OPTION(_nr)       (S5P_ARM_CORE0_OPTION + ((_nr) * 0x80))
+#define S5P_ARM_CORE_STATUS(_nr)       (S5P_ARM_CORE0_STATUS + ((_nr) * 0x80))
+#define S5P_ARM_CORE_CONFIGURATION(_nr)        \
+                               (S5P_ARM_CORE0_CONFIGURATION + ((_nr) * 0x80))
+
+#define S5P_CORE_OPTION_DIS                     (1 << 8)
 
 #define S5P_ARM_COMMON_OPTION                  S5P_PMUREG(0x2408)
 #define S5P_TOP_PWR_OPTION                     S5P_PMUREG(0x2C48)
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 36c3984..68ca26f 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -34,9 +34,6 @@
 
 extern void exynos4_secondary_startup(void);
 
-#define CPU1_BOOT_REG          (samsung_rev() == EXYNOS4210_REV_1_1 ? \
-                               S5P_INFORM5 : S5P_VA_SYSRAM)
-
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
@@ -59,6 +56,9 @@ static void write_pen_release(int val)
 
 static void __iomem *scu_base_addr(void)
 {
+       if (soc_is_exynos5250())
+               return 0;
+
        return (void __iomem *)(S5P_VA_SCU);
 }
 
@@ -86,9 +86,41 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
        spin_unlock(&boot_lock);
 }
 
+static int exynos_power_up_cpu(unsigned int cpu)
+{
+       unsigned long timeout;
+       unsigned int val;
+       void __iomem *power_base = S5P_ARM_CORE_CONFIGURATION(cpu);
+
+       val = __raw_readl(power_base);
+       if (!(val & S5P_CORE_LOCAL_PWR_EN)) {
+               __raw_writel(S5P_CORE_LOCAL_PWR_EN, power_base);
+
+               timeout = 10;
+
+               /* wait max 10 ms until cpu is on */
+               while ((__raw_readl(power_base + 0x4)
+                       & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
+                       if (timeout-- == 0)
+                               break;
+
+                       mdelay(1);
+               }
+
+               if (timeout == 0) {
+                       pr_err("cpu%d power enable failed", cpu);
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        unsigned long timeout;
+       void __iomem *boot_base;
+       int ret;
 
        /*
         * Set synchronisation state between this boot processor
@@ -96,6 +128,12 @@ int __cpuinit boot_secondary(unsigned int cpu, struct 
task_struct *idle)
         */
        spin_lock(&boot_lock);
 
+       ret = exynos_power_up_cpu(cpu);
+       if (ret) {
+               spin_unlock(&boot_lock);
+               return ret;
+       }
+
        /*
         * The secondary processor is waiting to be released from
         * the holding pen - release it, then wait for it to flag
@@ -106,39 +144,33 @@ int __cpuinit boot_secondary(unsigned int cpu, struct 
task_struct *idle)
         */
        write_pen_release(cpu_logical_map(cpu));
 
-       if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
-               __raw_writel(S5P_CORE_LOCAL_PWR_EN,
-                            S5P_ARM_CORE1_CONFIGURATION);
-
-               timeout = 10;
-
-               /* wait max 10 ms until cpu1 is on */
-               while ((__raw_readl(S5P_ARM_CORE1_STATUS)
-                       & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
-                       if (timeout-- == 0)
-                               break;
-
-                       mdelay(1);
-               }
-
-               if (timeout == 0) {
-                       printk(KERN_ERR "cpu1 power enable failed");
-                       spin_unlock(&boot_lock);
-                       return -ETIMEDOUT;
-               }
-       }
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
                smp_rmb();
 
+               if (soc_is_exynos4210() &&
+                               (samsung_rev() == EXYNOS4210_REV_1_1))
+                       boot_base = S5P_INFORM5;
+               else
+                       boot_base = S5P_VA_SYSRAM;
+
+               if (soc_is_exynos4412())
+                       boot_base += (0x4 * cpu);
+
+               /*
+                * Write the address of secondary startup into the
+                * system-wide flags register. The boot monitor waits
+                * until it receives a soft interrupt, and then the
+                * secondary CPU branches to this address.
+                */
                __raw_writel(virt_to_phys(exynos4_secondary_startup),
-                       CPU1_BOOT_REG);
+                               boot_base);
+
                gic_raise_softirq(cpumask_of(cpu), 1);
 
                if (pen_release == -1)
@@ -186,15 +218,15 @@ void __init smp_init_cpus(void)
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       if (!soc_is_exynos5250())
-               scu_enable(scu_base_addr());
+       int i;
 
        /*
-        * Write the address of secondary startup into the
-        * system-wide flags register. The boot monitor waits
-        * until it receives a soft interrupt, and then the
-        * secondary CPU branches to this address.
+        * Initialise the present map, which describes the set of CPUs
+        * actually populated at the present time.
         */
-       __raw_writel(virt_to_phys(exynos4_secondary_startup),
-                       CPU1_BOOT_REG);
+       for (i = 0; i < max_cpus; i++)
+               set_cpu_present(i, true);
+
+       if (!soc_is_exynos5250())
+               scu_enable(scu_base_addr());
 }
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to