summaryrefslogtreecommitdiff
path: root/arch/arm/mach-exynos/platsmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/platsmp.c')
-rw-r--r--arch/arm/mach-exynos/platsmp.c32
1 files changed, 20 insertions, 12 deletions
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));
}
}