summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-exynos/headsmp.S2
-rw-r--r--arch/arm/mach-exynos/hotplug.c7
-rw-r--r--arch/arm/mach-exynos/platsmp.c32
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));
}
}