| .. | .. |
|---|
| 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 |
|---|