xref: /openbmc/linux/arch/arm/mach-mvebu/platsmp-a9.c (revision 1ee89e2231a1b04dc34765edd195725ddf4ba998)
1*1ee89e22SGregory CLEMENT /*
2*1ee89e22SGregory CLEMENT  * Symmetric Multi Processing (SMP) support for Marvell EBU Cortex-A9
3*1ee89e22SGregory CLEMENT  * based SOCs (Armada 375/38x).
4*1ee89e22SGregory CLEMENT  *
5*1ee89e22SGregory CLEMENT  * Copyright (C) 2014 Marvell
6*1ee89e22SGregory CLEMENT  *
7*1ee89e22SGregory CLEMENT  * Gregory CLEMENT <gregory.clement@free-electrons.com>
8*1ee89e22SGregory CLEMENT  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
9*1ee89e22SGregory CLEMENT  *
10*1ee89e22SGregory CLEMENT  * This file is licensed under the terms of the GNU General Public
11*1ee89e22SGregory CLEMENT  * License version 2.  This program is licensed "as is" without any
12*1ee89e22SGregory CLEMENT  * warranty of any kind, whether express or implied.
13*1ee89e22SGregory CLEMENT  */
14*1ee89e22SGregory CLEMENT 
15*1ee89e22SGregory CLEMENT #include <linux/init.h>
16*1ee89e22SGregory CLEMENT #include <linux/io.h>
17*1ee89e22SGregory CLEMENT #include <linux/of.h>
18*1ee89e22SGregory CLEMENT #include <linux/smp.h>
19*1ee89e22SGregory CLEMENT #include <asm/smp_scu.h>
20*1ee89e22SGregory CLEMENT #include <asm/smp_plat.h>
21*1ee89e22SGregory CLEMENT #include "common.h"
22*1ee89e22SGregory CLEMENT #include "pmsu.h"
23*1ee89e22SGregory CLEMENT 
24*1ee89e22SGregory CLEMENT extern void mvebu_cortex_a9_secondary_startup(void);
25*1ee89e22SGregory CLEMENT 
26*1ee89e22SGregory CLEMENT static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu,
27*1ee89e22SGregory CLEMENT 						    struct task_struct *idle)
28*1ee89e22SGregory CLEMENT {
29*1ee89e22SGregory CLEMENT 	int ret, hw_cpu;
30*1ee89e22SGregory CLEMENT 
31*1ee89e22SGregory CLEMENT 	pr_info("Booting CPU %d\n", cpu);
32*1ee89e22SGregory CLEMENT 
33*1ee89e22SGregory CLEMENT 	/*
34*1ee89e22SGregory CLEMENT 	 * Write the address of secondary startup into the system-wide
35*1ee89e22SGregory CLEMENT 	 * flags register. The boot monitor waits until it receives a
36*1ee89e22SGregory CLEMENT 	 * soft interrupt, and then the secondary CPU branches to this
37*1ee89e22SGregory CLEMENT 	 * address.
38*1ee89e22SGregory CLEMENT 	 */
39*1ee89e22SGregory CLEMENT 	hw_cpu = cpu_logical_map(cpu);
40*1ee89e22SGregory CLEMENT 
41*1ee89e22SGregory CLEMENT 	if (of_machine_is_compatible("marvell,armada375"))
42*1ee89e22SGregory CLEMENT 		mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup);
43*1ee89e22SGregory CLEMENT 	else
44*1ee89e22SGregory CLEMENT 		mvebu_pmsu_set_cpu_boot_addr(hw_cpu,
45*1ee89e22SGregory CLEMENT 					     mvebu_cortex_a9_secondary_startup);
46*1ee89e22SGregory CLEMENT 
47*1ee89e22SGregory CLEMENT 	smp_wmb();
48*1ee89e22SGregory CLEMENT 	ret = mvebu_cpu_reset_deassert(hw_cpu);
49*1ee89e22SGregory CLEMENT 	if (ret) {
50*1ee89e22SGregory CLEMENT 		pr_err("Could not start the secondary CPU: %d\n", ret);
51*1ee89e22SGregory CLEMENT 		return ret;
52*1ee89e22SGregory CLEMENT 	}
53*1ee89e22SGregory CLEMENT 	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
54*1ee89e22SGregory CLEMENT 
55*1ee89e22SGregory CLEMENT 	return 0;
56*1ee89e22SGregory CLEMENT }
57*1ee89e22SGregory CLEMENT 
58*1ee89e22SGregory CLEMENT static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = {
59*1ee89e22SGregory CLEMENT 	.smp_boot_secondary	= mvebu_cortex_a9_boot_secondary,
60*1ee89e22SGregory CLEMENT #ifdef CONFIG_HOTPLUG_CPU
61*1ee89e22SGregory CLEMENT 	.cpu_die		= armada_xp_cpu_die,
62*1ee89e22SGregory CLEMENT #endif
63*1ee89e22SGregory CLEMENT };
64*1ee89e22SGregory CLEMENT 
65*1ee89e22SGregory CLEMENT CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp",
66*1ee89e22SGregory CLEMENT 		      &mvebu_cortex_a9_smp_ops);
67*1ee89e22SGregory CLEMENT CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp",
68*1ee89e22SGregory CLEMENT 		      &mvebu_cortex_a9_smp_ops);
69