11ee89e22SGregory CLEMENT /* 21ee89e22SGregory CLEMENT * Symmetric Multi Processing (SMP) support for Marvell EBU Cortex-A9 31ee89e22SGregory CLEMENT * based SOCs (Armada 375/38x). 41ee89e22SGregory CLEMENT * 51ee89e22SGregory CLEMENT * Copyright (C) 2014 Marvell 61ee89e22SGregory CLEMENT * 71ee89e22SGregory CLEMENT * Gregory CLEMENT <gregory.clement@free-electrons.com> 81ee89e22SGregory CLEMENT * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 91ee89e22SGregory CLEMENT * 101ee89e22SGregory CLEMENT * This file is licensed under the terms of the GNU General Public 111ee89e22SGregory CLEMENT * License version 2. This program is licensed "as is" without any 121ee89e22SGregory CLEMENT * warranty of any kind, whether express or implied. 131ee89e22SGregory CLEMENT */ 141ee89e22SGregory CLEMENT 151ee89e22SGregory CLEMENT #include <linux/init.h> 161ee89e22SGregory CLEMENT #include <linux/io.h> 171ee89e22SGregory CLEMENT #include <linux/of.h> 181ee89e22SGregory CLEMENT #include <linux/smp.h> 1987384cc0SGregory CLEMENT #include <linux/mbus.h> 201ee89e22SGregory CLEMENT #include <asm/smp_scu.h> 211ee89e22SGregory CLEMENT #include <asm/smp_plat.h> 221ee89e22SGregory CLEMENT #include "common.h" 231ee89e22SGregory CLEMENT #include "pmsu.h" 241ee89e22SGregory CLEMENT 251ee89e22SGregory CLEMENT extern void mvebu_cortex_a9_secondary_startup(void); 261ee89e22SGregory CLEMENT 271ee89e22SGregory CLEMENT static int __cpuinit mvebu_cortex_a9_boot_secondary(unsigned int cpu, 281ee89e22SGregory CLEMENT struct task_struct *idle) 291ee89e22SGregory CLEMENT { 301ee89e22SGregory CLEMENT int ret, hw_cpu; 311ee89e22SGregory CLEMENT 321ee89e22SGregory CLEMENT pr_info("Booting CPU %d\n", cpu); 331ee89e22SGregory CLEMENT 341ee89e22SGregory CLEMENT /* 351ee89e22SGregory CLEMENT * Write the address of secondary startup into the system-wide 361ee89e22SGregory CLEMENT * flags register. The boot monitor waits until it receives a 371ee89e22SGregory CLEMENT * soft interrupt, and then the secondary CPU branches to this 381ee89e22SGregory CLEMENT * address. 391ee89e22SGregory CLEMENT */ 401ee89e22SGregory CLEMENT hw_cpu = cpu_logical_map(cpu); 41*305969fbSGregory CLEMENT if (of_machine_is_compatible("marvell,armada375")) 421ee89e22SGregory CLEMENT mvebu_system_controller_set_cpu_boot_addr(mvebu_cortex_a9_secondary_startup); 43*305969fbSGregory CLEMENT else 44*305969fbSGregory CLEMENT mvebu_pmsu_set_cpu_boot_addr(hw_cpu, mvebu_cortex_a9_secondary_startup); 451ee89e22SGregory CLEMENT smp_wmb(); 461ee89e22SGregory CLEMENT ret = mvebu_cpu_reset_deassert(hw_cpu); 471ee89e22SGregory CLEMENT if (ret) { 481ee89e22SGregory CLEMENT pr_err("Could not start the secondary CPU: %d\n", ret); 491ee89e22SGregory CLEMENT return ret; 501ee89e22SGregory CLEMENT } 511ee89e22SGregory CLEMENT arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 521ee89e22SGregory CLEMENT 531ee89e22SGregory CLEMENT return 0; 541ee89e22SGregory CLEMENT } 551ee89e22SGregory CLEMENT 561ee89e22SGregory CLEMENT static struct smp_operations mvebu_cortex_a9_smp_ops __initdata = { 571ee89e22SGregory CLEMENT .smp_boot_secondary = mvebu_cortex_a9_boot_secondary, 581ee89e22SGregory CLEMENT }; 591ee89e22SGregory CLEMENT 601ee89e22SGregory CLEMENT CPU_METHOD_OF_DECLARE(mvebu_armada_375_smp, "marvell,armada-375-smp", 611ee89e22SGregory CLEMENT &mvebu_cortex_a9_smp_ops); 621ee89e22SGregory CLEMENT CPU_METHOD_OF_DECLARE(mvebu_armada_380_smp, "marvell,armada-380-smp", 631ee89e22SGregory CLEMENT &mvebu_cortex_a9_smp_ops); 64