diff options
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r-- | arch/arm/mach-mvebu/platsmp.c | 75 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/pm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/pmsu.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-mvebu/system-controller.c | 2 |
4 files changed, 78 insertions, 3 deletions
diff --git a/arch/arm/mach-mvebu/platsmp.c b/arch/arm/mach-mvebu/platsmp.c index 46c742d3bd41..e62273aacb43 100644 --- a/arch/arm/mach-mvebu/platsmp.c +++ b/arch/arm/mach-mvebu/platsmp.c @@ -184,3 +184,78 @@ const struct smp_operations armada_xp_smp_ops __initconst = { CPU_METHOD_OF_DECLARE(armada_xp_smp, "marvell,armada-xp-smp", &armada_xp_smp_ops); + +#define MV98DX3236_CPU_RESUME_CTRL_REG 0x08 +#define MV98DX3236_CPU_RESUME_ADDR_REG 0x04 + +static const struct of_device_id of_mv98dx3236_resume_table[] = { + { + .compatible = "marvell,98dx3336-resume-ctrl", + }, + { /* end of list */ }, +}; + +static int mv98dx3236_resume_set_cpu_boot_addr(int hw_cpu, void *boot_addr) +{ + struct device_node *np; + void __iomem *base; + WARN_ON(hw_cpu != 1); + + np = of_find_matching_node(NULL, of_mv98dx3236_resume_table); + if (!np) + return -ENODEV; + + base = of_io_request_and_map(np, 0, of_node_full_name(np)); + of_node_put(np); + if (IS_ERR(base)) + return PTR_ERR(base); + + writel(0, base + MV98DX3236_CPU_RESUME_CTRL_REG); + writel(virt_to_phys(boot_addr), base + MV98DX3236_CPU_RESUME_ADDR_REG); + + iounmap(base); + + return 0; +} + +static int mv98dx3236_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + int ret, hw_cpu; + + hw_cpu = cpu_logical_map(cpu); + set_secondary_cpu_clock(hw_cpu); + mv98dx3236_resume_set_cpu_boot_addr(hw_cpu, + armada_xp_secondary_startup); + + /* + * This is needed to wake up CPUs in the offline state after + * using CPU hotplug. + */ + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + + /* + * This is needed to take secondary CPUs out of reset on the + * initial boot. + */ + ret = mvebu_cpu_reset_deassert(hw_cpu); + if (ret) { + pr_warn("unable to boot CPU: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct smp_operations mv98dx3236_smp_ops __initconst = { + .smp_init_cpus = armada_xp_smp_init_cpus, + .smp_prepare_cpus = armada_xp_smp_prepare_cpus, + .smp_boot_secondary = mv98dx3236_boot_secondary, + .smp_secondary_init = armada_xp_secondary_init, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = armada_xp_cpu_die, + .cpu_kill = armada_xp_cpu_kill, +#endif +}; + +CPU_METHOD_OF_DECLARE(mv98dx3236_smp, "marvell,98dx3236-smp", + &mv98dx3236_smp_ops); diff --git a/arch/arm/mach-mvebu/pm.c b/arch/arm/mach-mvebu/pm.c index 2990c5269b18..c487be61d6d8 100644 --- a/arch/arm/mach-mvebu/pm.c +++ b/arch/arm/mach-mvebu/pm.c @@ -110,7 +110,7 @@ static void mvebu_pm_store_armadaxp_bootinfo(u32 *store_addr) { phys_addr_t resume_pc; - resume_pc = virt_to_phys(armada_370_xp_cpu_resume); + resume_pc = __pa_symbol(armada_370_xp_cpu_resume); /* * The bootloader expects the first two words to be a magic diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c index f39bd51bce18..27a78c80e5b1 100644 --- a/arch/arm/mach-mvebu/pmsu.c +++ b/arch/arm/mach-mvebu/pmsu.c @@ -112,7 +112,7 @@ static const struct of_device_id of_pmsu_table[] = { void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr) { - writel(virt_to_phys(boot_addr), pmsu_mp_base + + writel(__pa_symbol(boot_addr), pmsu_mp_base + PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu)); } diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c index 76cbc82a7407..04d9ebe6a90a 100644 --- a/arch/arm/mach-mvebu/system-controller.c +++ b/arch/arm/mach-mvebu/system-controller.c @@ -153,7 +153,7 @@ void mvebu_system_controller_set_cpu_boot_addr(void *boot_addr) if (of_machine_is_compatible("marvell,armada375")) mvebu_armada375_smp_wa_init(); - writel(virt_to_phys(boot_addr), system_controller_base + + writel(__pa_symbol(boot_addr), system_controller_base + mvebu_sc->resume_boot_addr); } #endif |