diff options
| author | Tomasz Figa <t.figa@samsung.com> | 2012-11-23 21:13:48 -0500 |
|---|---|---|
| committer | Kukjin Kim <kgene.kim@samsung.com> | 2012-11-27 18:04:29 -0500 |
| commit | 1f054f52ee7c4f62b4ea352e95943f032d19cc15 (patch) | |
| tree | 67dbf606cbda25ce2c9fe3b462d5537617077819 | |
| parent | 5fa23dde6e9a20a9c4bb3ff280ed84478829540d (diff) | |
ARM: EXYNOS: Add support for secondary CPU bring-up on Exynos4412
Exynos4412 uses different information register for each core. This
patch adjusts the bring-up code to take that into account.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
| -rw-r--r-- | arch/arm/mach-exynos/platsmp.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index f93d820ecab5..4ca8ff14a5bf 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c | |||
| @@ -36,8 +36,22 @@ | |||
| 36 | 36 | ||
| 37 | extern void exynos4_secondary_startup(void); | 37 | extern void exynos4_secondary_startup(void); |
| 38 | 38 | ||
| 39 | #define CPU1_BOOT_REG (samsung_rev() == EXYNOS4210_REV_1_1 ? \ | 39 | static inline void __iomem *cpu_boot_reg_base(void) |
| 40 | S5P_INFORM5 : S5P_VA_SYSRAM) | 40 | { |
| 41 | if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) | ||
| 42 | return S5P_INFORM5; | ||
| 43 | return S5P_VA_SYSRAM; | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline void __iomem *cpu_boot_reg(int cpu) | ||
| 47 | { | ||
| 48 | void __iomem *boot_reg; | ||
| 49 | |||
| 50 | boot_reg = cpu_boot_reg_base(); | ||
| 51 | if (soc_is_exynos4412()) | ||
| 52 | boot_reg += 4*cpu; | ||
| 53 | return boot_reg; | ||
| 54 | } | ||
| 41 | 55 | ||
| 42 | /* | 56 | /* |
| 43 | * Write pen_release in a way that is guaranteed to be visible to all | 57 | * Write pen_release in a way that is guaranteed to be visible to all |
| @@ -84,6 +98,7 @@ static void __cpuinit exynos_secondary_init(unsigned int cpu) | |||
| 84 | static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) | 98 | static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) |
| 85 | { | 99 | { |
| 86 | unsigned long timeout; | 100 | unsigned long timeout; |
| 101 | unsigned long phys_cpu = cpu_logical_map(cpu); | ||
| 87 | 102 | ||
| 88 | /* | 103 | /* |
| 89 | * Set synchronisation state between this boot processor | 104 | * Set synchronisation state between this boot processor |
| @@ -99,7 +114,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct | |||
| 99 | * Note that "pen_release" is the hardware CPU ID, whereas | 114 | * Note that "pen_release" is the hardware CPU ID, whereas |
| 100 | * "cpu" is Linux's internal ID. | 115 | * "cpu" is Linux's internal ID. |
| 101 | */ | 116 | */ |
| 102 | write_pen_release(cpu_logical_map(cpu)); | 117 | write_pen_release(phys_cpu); |
| 103 | 118 | ||
| 104 | if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { | 119 | if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) { |
| 105 | __raw_writel(S5P_CORE_LOCAL_PWR_EN, | 120 | __raw_writel(S5P_CORE_LOCAL_PWR_EN, |
| @@ -133,7 +148,7 @@ static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct | |||
| 133 | smp_rmb(); | 148 | smp_rmb(); |
| 134 | 149 | ||
| 135 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 150 | __raw_writel(virt_to_phys(exynos4_secondary_startup), |
| 136 | CPU1_BOOT_REG); | 151 | cpu_boot_reg(phys_cpu)); |
| 137 | gic_raise_softirq(cpumask_of(cpu), 0); | 152 | gic_raise_softirq(cpumask_of(cpu), 0); |
| 138 | 153 | ||
| 139 | if (pen_release == -1) | 154 | if (pen_release == -1) |
| @@ -181,6 +196,8 @@ static void __init exynos_smp_init_cpus(void) | |||
| 181 | 196 | ||
| 182 | static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | 197 | static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) |
| 183 | { | 198 | { |
| 199 | int i; | ||
| 200 | |||
| 184 | if (!soc_is_exynos5250()) | 201 | if (!soc_is_exynos5250()) |
| 185 | scu_enable(scu_base_addr()); | 202 | scu_enable(scu_base_addr()); |
| 186 | 203 | ||
| @@ -190,8 +207,9 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) | |||
| 190 | * until it receives a soft interrupt, and then the | 207 | * until it receives a soft interrupt, and then the |
| 191 | * secondary CPU branches to this address. | 208 | * secondary CPU branches to this address. |
| 192 | */ | 209 | */ |
| 193 | __raw_writel(virt_to_phys(exynos4_secondary_startup), | 210 | for (i = 1; i < max_cpus; ++i) |
| 194 | CPU1_BOOT_REG); | 211 | __raw_writel(virt_to_phys(exynos4_secondary_startup), |
| 212 | cpu_boot_reg(cpu_logical_map(i))); | ||
| 195 | } | 213 | } |
| 196 | 214 | ||
| 197 | struct smp_operations exynos_smp_ops __initdata = { | 215 | struct smp_operations exynos_smp_ops __initdata = { |
