18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2019 Lubomir Rintel <lkundrak@v3.sk> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#include <linux/io.h> 68c2ecf20Sopenharmony_ci#include <asm/smp_scu.h> 78c2ecf20Sopenharmony_ci#include <asm/smp.h> 88c2ecf20Sopenharmony_ci#include "addr-map.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define SW_BRANCH_VIRT_ADDR CIU_REG(0x24) 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic int mmp3_boot_secondary(unsigned int cpu, struct task_struct *idle) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci /* 158c2ecf20Sopenharmony_ci * Apparently, the boot ROM on the second core spins on this 168c2ecf20Sopenharmony_ci * register becoming non-zero and then jumps to the address written 178c2ecf20Sopenharmony_ci * there. No IPIs involved. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci __raw_writel(__pa_symbol(secondary_startup), SW_BRANCH_VIRT_ADDR); 208c2ecf20Sopenharmony_ci return 0; 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic void mmp3_smp_prepare_cpus(unsigned int max_cpus) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci scu_enable(SCU_VIRT_BASE); 268c2ecf20Sopenharmony_ci} 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const struct smp_operations mmp3_smp_ops __initconst = { 298c2ecf20Sopenharmony_ci .smp_prepare_cpus = mmp3_smp_prepare_cpus, 308c2ecf20Sopenharmony_ci .smp_boot_secondary = mmp3_boot_secondary, 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ciCPU_METHOD_OF_DECLARE(mmp3_smp, "marvell,mmp3-smp", &mmp3_smp_ops); 33