diff options
Diffstat (limited to 'arch/arm/mach-zynq/platsmp.c')
| -rw-r--r-- | arch/arm/mach-zynq/platsmp.c | 83 |
1 files changed, 39 insertions, 44 deletions
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c index 5fc167e0761..abc82ef085c 100644 --- a/arch/arm/mach-zynq/platsmp.c +++ b/arch/arm/mach-zynq/platsmp.c @@ -30,20 +30,15 @@ /* * Store number of cores in the system * Because of scu_get_core_count() must be in __init section and can't - * be called from zynq_cpun_start() because it is in __cpuinit section. + * be called from zynq_cpun_start() because it is not in __init section. */ static int ncores; -int __cpuinit zynq_cpun_start(u32 address, int cpu) +int zynq_cpun_start(u32 address, int cpu) { u32 trampoline_code_size = &zynq_secondary_trampoline_end - &zynq_secondary_trampoline; - if (cpu > ncores) { - pr_warn("CPU No. is not available in the system\n"); - return -1; - } - /* MS: Expectation that SLCR are directly map and accessible */ /* Not possible to jump to non aligned address */ if (!(address & 3) && (!address || (address >= trampoline_code_size))) { @@ -53,34 +48,34 @@ int __cpuinit zynq_cpun_start(u32 address, int cpu) &zynq_secondary_trampoline; zynq_slcr_cpu_stop(cpu); - - if (__pa(PAGE_OFFSET)) { - zero = ioremap(0, trampoline_code_size); - if (!zero) { - pr_warn("BOOTUP jump vectors not accessible\n"); - return -1; + if (address) { + if (__pa(PAGE_OFFSET)) { + zero = ioremap(0, trampoline_code_size); + if (!zero) { + pr_warn("BOOTUP jump vectors not accessible\n"); + return -1; + } + } else { + zero = (__force u8 __iomem *)PAGE_OFFSET; } - } else { - zero = (__force u8 __iomem *)PAGE_OFFSET; - } - - /* - * This is elegant way how to jump to any address - * 0x0: Load address at 0x8 to r0 - * 0x4: Jump by mov instruction - * 0x8: Jumping address - */ - memcpy((__force void *)zero, &zynq_secondary_trampoline, - trampoline_size); - writel(address, zero + trampoline_size); - - flush_cache_all(); - outer_flush_range(0, trampoline_code_size); - smp_wmb(); - - if (__pa(PAGE_OFFSET)) - iounmap(zero); + /* + * This is elegant way how to jump to any address + * 0x0: Load address at 0x8 to r0 + * 0x4: Jump by mov instruction + * 0x8: Jumping address + */ + memcpy((__force void *)zero, &zynq_secondary_trampoline, + trampoline_size); + writel(address, zero + trampoline_size); + + flush_cache_all(); + outer_flush_range(0, trampoline_code_size); + smp_wmb(); + + if (__pa(PAGE_OFFSET)) + iounmap(zero); + } zynq_slcr_cpu_start(cpu); return 0; @@ -92,10 +87,10 @@ int __cpuinit zynq_cpun_start(u32 address, int cpu) } EXPORT_SYMBOL(zynq_cpun_start); -static int __cpuinit zynq_boot_secondary(unsigned int cpu, +static int zynq_boot_secondary(unsigned int cpu, struct task_struct *idle) { - return zynq_cpun_start(virt_to_phys(secondary_startup), cpu); + return zynq_cpun_start(virt_to_phys(zynq_secondary_startup), cpu); } /* @@ -114,23 +109,23 @@ static void __init zynq_smp_init_cpus(void) static void __init zynq_smp_prepare_cpus(unsigned int max_cpus) { - int i; - - /* - * Initialise the present map, which describes the set of CPUs - * actually populated at the present time. - */ - for (i = 0; i < max_cpus; i++) - set_cpu_present(i, true); - scu_enable(zynq_scu_base); } +#ifdef CONFIG_HOTPLUG_CPU +static int zynq_cpu_kill(unsigned cpu) +{ + zynq_slcr_cpu_stop(cpu); + return 1; +} +#endif + struct smp_operations zynq_smp_ops __initdata = { .smp_init_cpus = zynq_smp_init_cpus, .smp_prepare_cpus = zynq_smp_prepare_cpus, .smp_boot_secondary = zynq_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = zynq_platform_cpu_die, + .cpu_kill = zynq_cpu_kill, #endif }; |
