diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-exynos/headsmp.S | 2 | ||||
-rw-r--r-- | arch/arm/mach-exynos/hotplug.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 32 |
3 files changed, 26 insertions, 15 deletions
diff --git a/arch/arm/mach-exynos/headsmp.S b/arch/arm/mach-exynos/headsmp.S index 5364d4bfa8b..b1243664999 100644 --- a/arch/arm/mach-exynos/headsmp.S +++ b/arch/arm/mach-exynos/headsmp.S @@ -22,7 +22,7 @@ */ ENTRY(exynos4_secondary_startup) mrc p15, 0, r0, c0, c0, 5 - and r0, r0, #15 + and r0, r0, #0xFFFFFF adr r4, 1f ldmia r4, {r5, r6} sub r4, r4, r5 diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c index 4c974267852..44932a8ae7b 100644 --- a/arch/arm/mach-exynos/hotplug.c +++ b/arch/arm/mach-exynos/hotplug.c @@ -94,10 +94,13 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) { u32 mpidr = cpu_logical_map(cpu); u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); + u32 cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); + cluster_id = cluster_id > 1 ? 0 : cluster_id; + u32 cpu_idx = (cluster_id * 4) + core_id; for (;;) { /* Turn the CPU off on next WFI instruction. */ - exynos_cpu_power_down(core_id); + exynos_cpu_power_down(cpu_idx); /* * here's the WFI @@ -107,7 +110,7 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious) : : "memory", "cc"); - if (pen_release == core_id) { + if (pen_release == cpu_idx) { /* * OK, proper wakeup, we're done */ diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 9a8d557054c..8deffebd3f5 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -95,6 +95,9 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct unsigned long timeout; u32 mpidr = cpu_logical_map(cpu); u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); + u32 cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); + cluster_id = cluster_id > 1 ? 0 : cluster_id; + u32 cpu_idx = (cluster_id * 4) + core_id; /* * Set synchronisation state between this boot processor @@ -110,21 +113,21 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct * Note that "pen_release" is the hardware CPU core ID, whereas * "cpu" is Linux's internal ID. */ - write_pen_release(core_id); + write_pen_release(mpidr); - if (!(__raw_readl(S5P_ARM_CORE_STATUS(core_id)) + if (!(__raw_readl(S5P_ARM_CORE_STATUS(cpu_idx)) & S5P_CORE_LOCAL_PWR_EN)) { u32 core_conf = 0; core_conf |= S5P_CORE_LOCAL_PWR_EN; if (soc_is_exynos3250()) core_conf |= S5P_CORE_AUTOWAKEUP_EN; - __raw_writel(core_conf, S5P_ARM_CORE_CONFIGURATION(core_id)); + __raw_writel(core_conf, S5P_ARM_CORE_CONFIGURATION(cpu_idx)); timeout = 10; /* wait max 10 ms until cpu1 is on */ - while ((__raw_readl(S5P_ARM_CORE_STATUS(core_id)) + while ((__raw_readl(S5P_ARM_CORE_STATUS(cpu_idx)) & S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) { if (timeout-- == 0) break; @@ -148,13 +151,13 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct udelay(10); udelay(10); - tmp = __raw_readl(S5P_ARM_CORE_STATUS(core_id)); + tmp = __raw_readl(S5P_ARM_CORE_STATUS(cpu_idx)); tmp |= (S5P_CORE_LOCAL_PWR_EN << 8); - __raw_writel(tmp, S5P_ARM_CORE_STATUS(core_id)); + __raw_writel(tmp, S5P_ARM_CORE_STATUS(cpu_idx)); } if (soc_is_exynos3250()) - __raw_writel(EXYNOS3_COREPORESET(core_id), EXYNOS_SWRESET); + __raw_writel(EXYNOS3_COREPORESET(cpu_idx), EXYNOS_SWRESET); /* * Send the secondary CPU a soft interrupt, thereby causing @@ -174,10 +177,10 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct * 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, core_id, boot_addr)) - __raw_writel(boot_addr, cpu_boot_reg(core_id)); + if (call_firmware_op(set_cpu_boot_addr, cpu_idx, boot_addr)) + __raw_writel(boot_addr, cpu_boot_reg(cpu_idx)); - call_firmware_op(cpu_boot, core_id); + call_firmware_op(cpu_boot, cpu_idx); if (soc_is_exynos3250()) dsb_sev(); @@ -245,13 +248,18 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) unsigned long boot_addr; u32 mpidr; u32 core_id; + u32 cluster_id; + u32 cpu_idx; mpidr = cpu_logical_map(i); core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); + cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); + cluster_id = cluster_id > 1 ? 0 : cluster_id; + cpu_idx = (cluster_id * 4) + core_id; boot_addr = virt_to_phys(exynos4_secondary_startup); - if (call_firmware_op(set_cpu_boot_addr, core_id, boot_addr)) - __raw_writel(boot_addr, cpu_boot_reg(core_id)); + if (call_firmware_op(set_cpu_boot_addr, cpu_idx, boot_addr)) + __raw_writel(boot_addr, cpu_boot_reg(cpu_idx)); } } |