.. | .. |
---|
22 | 22 | #include <asm/smp_scu.h> |
---|
23 | 23 | #include <asm/firmware.h> |
---|
24 | 24 | |
---|
25 | | -#include <mach/map.h> |
---|
26 | | - |
---|
27 | 25 | #include "common.h" |
---|
28 | 26 | |
---|
29 | 27 | extern void exynos4_secondary_startup(void); |
---|
| 28 | + |
---|
| 29 | +/* XXX exynos_pen_release is cargo culted code - DO NOT COPY XXX */ |
---|
| 30 | +volatile int exynos_pen_release = -1; |
---|
30 | 31 | |
---|
31 | 32 | #ifdef CONFIG_HOTPLUG_CPU |
---|
32 | 33 | static inline void cpu_leave_lowpower(u32 core_id) |
---|
.. | .. |
---|
57 | 58 | |
---|
58 | 59 | wfi(); |
---|
59 | 60 | |
---|
60 | | - if (pen_release == core_id) { |
---|
| 61 | + if (exynos_pen_release == core_id) { |
---|
61 | 62 | /* |
---|
62 | 63 | * OK, proper wakeup, we're done |
---|
63 | 64 | */ |
---|
.. | .. |
---|
185 | 186 | |
---|
186 | 187 | static void __iomem *cpu_boot_reg_base(void) |
---|
187 | 188 | { |
---|
188 | | - if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) |
---|
| 189 | + if (soc_is_exynos4210() && exynos_rev() == EXYNOS4210_REV_1_1) |
---|
189 | 190 | return pmu_base_addr + S5P_INFORM5; |
---|
190 | 191 | return sysram_base_addr; |
---|
191 | 192 | } |
---|
.. | .. |
---|
211 | 212 | */ |
---|
212 | 213 | void exynos_core_restart(u32 core_id) |
---|
213 | 214 | { |
---|
| 215 | + unsigned int timeout = 16; |
---|
214 | 216 | u32 val; |
---|
215 | 217 | |
---|
216 | 218 | if (!of_machine_is_compatible("samsung,exynos3250")) |
---|
217 | 219 | return; |
---|
218 | 220 | |
---|
219 | | - while (!pmu_raw_readl(S5P_PMU_SPARE2)) |
---|
| 221 | + while (timeout && !pmu_raw_readl(S5P_PMU_SPARE2)) { |
---|
| 222 | + timeout--; |
---|
220 | 223 | udelay(10); |
---|
| 224 | + } |
---|
| 225 | + if (timeout == 0) { |
---|
| 226 | + pr_err("cpu core %u restart failed\n", core_id); |
---|
| 227 | + return; |
---|
| 228 | + } |
---|
221 | 229 | udelay(10); |
---|
222 | 230 | |
---|
223 | 231 | val = pmu_raw_readl(EXYNOS_ARM_CORE_STATUS(core_id)); |
---|
.. | .. |
---|
228 | 236 | } |
---|
229 | 237 | |
---|
230 | 238 | /* |
---|
231 | | - * Write pen_release in a way that is guaranteed to be visible to all |
---|
232 | | - * observers, irrespective of whether they're taking part in coherency |
---|
| 239 | + * XXX CARGO CULTED CODE - DO NOT COPY XXX |
---|
| 240 | + * |
---|
| 241 | + * Write exynos_pen_release in a way that is guaranteed to be visible to |
---|
| 242 | + * all observers, irrespective of whether they're taking part in coherency |
---|
233 | 243 | * or not. This is necessary for the hotplug code to work reliably. |
---|
234 | 244 | */ |
---|
235 | | -static void write_pen_release(int val) |
---|
| 245 | +static void exynos_write_pen_release(int val) |
---|
236 | 246 | { |
---|
237 | | - pen_release = val; |
---|
| 247 | + exynos_pen_release = val; |
---|
238 | 248 | smp_wmb(); |
---|
239 | | - sync_cache_w(&pen_release); |
---|
| 249 | + sync_cache_w(&exynos_pen_release); |
---|
240 | 250 | } |
---|
241 | 251 | |
---|
242 | | -static DEFINE_RAW_SPINLOCK(boot_lock); |
---|
| 252 | +static DEFINE_SPINLOCK(boot_lock); |
---|
243 | 253 | |
---|
244 | 254 | static void exynos_secondary_init(unsigned int cpu) |
---|
245 | 255 | { |
---|
.. | .. |
---|
247 | 257 | * let the primary processor know we're out of the |
---|
248 | 258 | * pen, then head off into the C entry point |
---|
249 | 259 | */ |
---|
250 | | - write_pen_release(-1); |
---|
| 260 | + exynos_write_pen_release(-1); |
---|
251 | 261 | |
---|
252 | 262 | /* |
---|
253 | 263 | * Synchronise with the boot thread. |
---|
254 | 264 | */ |
---|
255 | | - raw_spin_lock(&boot_lock); |
---|
256 | | - raw_spin_unlock(&boot_lock); |
---|
| 265 | + spin_lock(&boot_lock); |
---|
| 266 | + spin_unlock(&boot_lock); |
---|
257 | 267 | } |
---|
258 | 268 | |
---|
259 | 269 | int exynos_set_boot_addr(u32 core_id, unsigned long boot_addr) |
---|
.. | .. |
---|
317 | 327 | * Set synchronisation state between this boot processor |
---|
318 | 328 | * and the secondary one |
---|
319 | 329 | */ |
---|
320 | | - raw_spin_lock(&boot_lock); |
---|
| 330 | + spin_lock(&boot_lock); |
---|
321 | 331 | |
---|
322 | 332 | /* |
---|
323 | 333 | * The secondary processor is waiting to be released from |
---|
324 | 334 | * the holding pen - release it, then wait for it to flag |
---|
325 | | - * that it has been released by resetting pen_release. |
---|
| 335 | + * that it has been released by resetting exynos_pen_release. |
---|
326 | 336 | * |
---|
327 | | - * Note that "pen_release" is the hardware CPU core ID, whereas |
---|
| 337 | + * Note that "exynos_pen_release" is the hardware CPU core ID, whereas |
---|
328 | 338 | * "cpu" is Linux's internal ID. |
---|
329 | 339 | */ |
---|
330 | | - write_pen_release(core_id); |
---|
| 340 | + exynos_write_pen_release(core_id); |
---|
331 | 341 | |
---|
332 | 342 | if (!exynos_cpu_power_state(core_id)) { |
---|
333 | 343 | exynos_cpu_power_up(core_id); |
---|
.. | .. |
---|
336 | 346 | /* wait max 10 ms until cpu1 is on */ |
---|
337 | 347 | while (exynos_cpu_power_state(core_id) |
---|
338 | 348 | != S5P_CORE_LOCAL_PWR_EN) { |
---|
339 | | - if (timeout-- == 0) |
---|
| 349 | + if (timeout == 0) |
---|
340 | 350 | break; |
---|
341 | | - |
---|
| 351 | + timeout--; |
---|
342 | 352 | mdelay(1); |
---|
343 | 353 | } |
---|
344 | 354 | |
---|
345 | 355 | if (timeout == 0) { |
---|
346 | 356 | printk(KERN_ERR "cpu1 power enable failed"); |
---|
347 | | - raw_spin_unlock(&boot_lock); |
---|
| 357 | + spin_unlock(&boot_lock); |
---|
348 | 358 | return -ETIMEDOUT; |
---|
349 | 359 | } |
---|
350 | 360 | } |
---|
.. | .. |
---|
376 | 386 | else |
---|
377 | 387 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
---|
378 | 388 | |
---|
379 | | - if (pen_release == -1) |
---|
| 389 | + if (exynos_pen_release == -1) |
---|
380 | 390 | break; |
---|
381 | 391 | |
---|
382 | 392 | udelay(10); |
---|
383 | 393 | } |
---|
384 | 394 | |
---|
385 | | - if (pen_release != -1) |
---|
| 395 | + if (exynos_pen_release != -1) |
---|
386 | 396 | ret = -ETIMEDOUT; |
---|
387 | 397 | |
---|
388 | 398 | /* |
---|
.. | .. |
---|
390 | 400 | * calibrations, then wait for it to finish |
---|
391 | 401 | */ |
---|
392 | 402 | fail: |
---|
393 | | - raw_spin_unlock(&boot_lock); |
---|
| 403 | + spin_unlock(&boot_lock); |
---|
394 | 404 | |
---|
395 | | - return pen_release != -1 ? ret : 0; |
---|
| 405 | + return exynos_pen_release != -1 ? ret : 0; |
---|
396 | 406 | } |
---|
397 | 407 | |
---|
398 | 408 | static void __init exynos_smp_prepare_cpus(unsigned int max_cpus) |
---|
399 | 409 | { |
---|
400 | | - int i; |
---|
401 | | - |
---|
402 | 410 | exynos_sysram_init(); |
---|
403 | 411 | |
---|
404 | 412 | exynos_set_delayed_reset_assertion(true); |
---|
405 | 413 | |
---|
406 | 414 | if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) |
---|
407 | 415 | exynos_scu_enable(); |
---|
408 | | - |
---|
409 | | - /* |
---|
410 | | - * Write the address of secondary startup into the |
---|
411 | | - * system-wide flags register. The boot monitor waits |
---|
412 | | - * until it receives a soft interrupt, and then the |
---|
413 | | - * secondary CPU branches to this address. |
---|
414 | | - * |
---|
415 | | - * Try using firmware operation first and fall back to |
---|
416 | | - * boot register if it fails. |
---|
417 | | - */ |
---|
418 | | - for (i = 1; i < max_cpus; ++i) { |
---|
419 | | - unsigned long boot_addr; |
---|
420 | | - u32 mpidr; |
---|
421 | | - u32 core_id; |
---|
422 | | - int ret; |
---|
423 | | - |
---|
424 | | - mpidr = cpu_logical_map(i); |
---|
425 | | - core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); |
---|
426 | | - boot_addr = __pa_symbol(exynos4_secondary_startup); |
---|
427 | | - |
---|
428 | | - ret = exynos_set_boot_addr(core_id, boot_addr); |
---|
429 | | - if (ret) |
---|
430 | | - break; |
---|
431 | | - } |
---|
432 | 416 | } |
---|
433 | 417 | |
---|
434 | 418 | #ifdef CONFIG_HOTPLUG_CPU |
---|