aboutsummaryrefslogtreecommitdiffstats
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.c60
1 files changed, 21 insertions, 39 deletions
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index ec02422e8499..50b9aad5e27b 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -32,28 +32,6 @@
32 32
33extern void exynos4_secondary_startup(void); 33extern void exynos4_secondary_startup(void);
34 34
35void __iomem *sysram_base_addr;
36void __iomem *sysram_ns_base_addr;
37
38static void __init exynos_smp_prepare_sysram(void)
39{
40 struct device_node *node;
41
42 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram") {
43 if (!of_device_is_available(node))
44 continue;
45 sysram_base_addr = of_iomap(node, 0);
46 break;
47 }
48
49 for_each_compatible_node(node, NULL, "samsung,exynos4210-sysram-ns") {
50 if (!of_device_is_available(node))
51 continue;
52 sysram_ns_base_addr = of_iomap(node, 0);
53 break;
54 }
55}
56
57static inline void __iomem *cpu_boot_reg_base(void) 35static inline void __iomem *cpu_boot_reg_base(void)
58{ 36{
59 if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) 37 if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
@@ -112,7 +90,8 @@ static void exynos_secondary_init(unsigned int cpu)
112static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) 90static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
113{ 91{
114 unsigned long timeout; 92 unsigned long timeout;
115 unsigned long phys_cpu = cpu_logical_map(cpu); 93 u32 mpidr = cpu_logical_map(cpu);
94 u32 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
116 int ret = -ENOSYS; 95 int ret = -ENOSYS;
117 96
118 /* 97 /*
@@ -126,17 +105,18 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
126 * the holding pen - release it, then wait for it to flag 105 * the holding pen - release it, then wait for it to flag
127 * that it has been released by resetting pen_release. 106 * that it has been released by resetting pen_release.
128 * 107 *
129 * Note that "pen_release" is the hardware CPU ID, whereas 108 * Note that "pen_release" is the hardware CPU core ID, whereas
130 * "cpu" is Linux's internal ID. 109 * "cpu" is Linux's internal ID.
131 */ 110 */
132 write_pen_release(phys_cpu); 111 write_pen_release(core_id);
133 112
134 if (!exynos_cpu_power_state(cpu)) { 113 if (!exynos_cpu_power_state(core_id)) {
135 exynos_cpu_power_up(cpu); 114 exynos_cpu_power_up(core_id);
136 timeout = 10; 115 timeout = 10;
137 116
138 /* wait max 10 ms until cpu1 is on */ 117 /* wait max 10 ms until cpu1 is on */
139 while (exynos_cpu_power_state(cpu) != S5P_CORE_LOCAL_PWR_EN) { 118 while (exynos_cpu_power_state(core_id)
119 != S5P_CORE_LOCAL_PWR_EN) {
140 if (timeout-- == 0) 120 if (timeout-- == 0)
141 break; 121 break;
142 122
@@ -167,20 +147,20 @@ static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
167 * Try to set boot address using firmware first 147 * Try to set boot address using firmware first
168 * and fall back to boot register if it fails. 148 * and fall back to boot register if it fails.
169 */ 149 */
170 ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr); 150 ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
171 if (ret && ret != -ENOSYS) 151 if (ret && ret != -ENOSYS)
172 goto fail; 152 goto fail;
173 if (ret == -ENOSYS) { 153 if (ret == -ENOSYS) {
174 void __iomem *boot_reg = cpu_boot_reg(phys_cpu); 154 void __iomem *boot_reg = cpu_boot_reg(core_id);
175 155
176 if (IS_ERR(boot_reg)) { 156 if (IS_ERR(boot_reg)) {
177 ret = PTR_ERR(boot_reg); 157 ret = PTR_ERR(boot_reg);
178 goto fail; 158 goto fail;
179 } 159 }
180 __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); 160 __raw_writel(boot_addr, cpu_boot_reg(core_id));
181 } 161 }
182 162
183 call_firmware_op(cpu_boot, phys_cpu); 163 call_firmware_op(cpu_boot, core_id);
184 164
185 arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 165 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
186 166
@@ -234,11 +214,11 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
234{ 214{
235 int i; 215 int i;
236 216
217 exynos_sysram_init();
218
237 if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9) 219 if (read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9)
238 scu_enable(scu_base_addr()); 220 scu_enable(scu_base_addr());
239 221
240 exynos_smp_prepare_sysram();
241
242 /* 222 /*
243 * Write the address of secondary startup into the 223 * Write the address of secondary startup into the
244 * system-wide flags register. The boot monitor waits 224 * system-wide flags register. The boot monitor waits
@@ -249,22 +229,24 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
249 * boot register if it fails. 229 * boot register if it fails.
250 */ 230 */
251 for (i = 1; i < max_cpus; ++i) { 231 for (i = 1; i < max_cpus; ++i) {
252 unsigned long phys_cpu;
253 unsigned long boot_addr; 232 unsigned long boot_addr;
233 u32 mpidr;
234 u32 core_id;
254 int ret; 235 int ret;
255 236
256 phys_cpu = cpu_logical_map(i); 237 mpidr = cpu_logical_map(i);
238 core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
257 boot_addr = virt_to_phys(exynos4_secondary_startup); 239 boot_addr = virt_to_phys(exynos4_secondary_startup);
258 240
259 ret = call_firmware_op(set_cpu_boot_addr, phys_cpu, boot_addr); 241 ret = call_firmware_op(set_cpu_boot_addr, core_id, boot_addr);
260 if (ret && ret != -ENOSYS) 242 if (ret && ret != -ENOSYS)
261 break; 243 break;
262 if (ret == -ENOSYS) { 244 if (ret == -ENOSYS) {
263 void __iomem *boot_reg = cpu_boot_reg(phys_cpu); 245 void __iomem *boot_reg = cpu_boot_reg(core_id);
264 246
265 if (IS_ERR(boot_reg)) 247 if (IS_ERR(boot_reg))
266 break; 248 break;
267 __raw_writel(boot_addr, cpu_boot_reg(phys_cpu)); 249 __raw_writel(boot_addr, cpu_boot_reg(core_id));
268 } 250 }
269 } 251 }
270} 252}