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