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/