1*d093bc03SLubomir Rintel // SPDX-License-Identifier: GPL-2.0-or-later 2*d093bc03SLubomir Rintel /* 3*d093bc03SLubomir Rintel * Copyright (C) 2019 Lubomir Rintel <lkundrak@v3.sk> 4*d093bc03SLubomir Rintel */ 5*d093bc03SLubomir Rintel #include <linux/io.h> 6*d093bc03SLubomir Rintel #include <asm/smp_scu.h> 7*d093bc03SLubomir Rintel #include <asm/smp.h> 8*d093bc03SLubomir Rintel #include "addr-map.h" 9*d093bc03SLubomir Rintel 10*d093bc03SLubomir Rintel #define SW_BRANCH_VIRT_ADDR CIU_REG(0x24) 11*d093bc03SLubomir Rintel mmp3_boot_secondary(unsigned int cpu,struct task_struct * idle)12*d093bc03SLubomir Rintelstatic int mmp3_boot_secondary(unsigned int cpu, struct task_struct *idle) 13*d093bc03SLubomir Rintel { 14*d093bc03SLubomir Rintel /* 15*d093bc03SLubomir Rintel * Apparently, the boot ROM on the second core spins on this 16*d093bc03SLubomir Rintel * register becoming non-zero and then jumps to the address written 17*d093bc03SLubomir Rintel * there. No IPIs involved. 18*d093bc03SLubomir Rintel */ 19*d093bc03SLubomir Rintel __raw_writel(__pa_symbol(secondary_startup), SW_BRANCH_VIRT_ADDR); 20*d093bc03SLubomir Rintel return 0; 21*d093bc03SLubomir Rintel } 22*d093bc03SLubomir Rintel mmp3_smp_prepare_cpus(unsigned int max_cpus)23*d093bc03SLubomir Rintelstatic void mmp3_smp_prepare_cpus(unsigned int max_cpus) 24*d093bc03SLubomir Rintel { 25*d093bc03SLubomir Rintel scu_enable(SCU_VIRT_BASE); 26*d093bc03SLubomir Rintel } 27*d093bc03SLubomir Rintel 28*d093bc03SLubomir Rintel static const struct smp_operations mmp3_smp_ops __initconst = { 29*d093bc03SLubomir Rintel .smp_prepare_cpus = mmp3_smp_prepare_cpus, 30*d093bc03SLubomir Rintel .smp_boot_secondary = mmp3_boot_secondary, 31*d093bc03SLubomir Rintel }; 32*d093bc03SLubomir Rintel CPU_METHOD_OF_DECLARE(mmp3_smp, "marvell,mmp3-smp", &mmp3_smp_ops); 33