/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2021 Adrian Chadd <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include "opt_platform.h"2829#include <sys/param.h>30#include <sys/systm.h>31#include <sys/bus.h>32#include <sys/reboot.h>33#include <sys/smp.h>3435#include <vm/vm.h>3637#include <machine/cpu.h>38#include <machine/bus.h>39#include <machine/intr.h>40#include <machine/machdep.h>41#include <machine/platformvar.h>42#include <machine/smp.h>4344#include <dev/fdt/fdt_common.h>45#include <dev/ofw/openfirm.h>46#include <dev/ofw/ofw_cpu.h>4748#include <arm/qualcomm/ipq4018_machdep.h>49#include <arm/qualcomm/qcom_scm_legacy.h>50#include <arm/qualcomm/qcom_cpu_kpssv2.h>5152#include "platform_if.h"5354void55ipq4018_mp_setmaxid(platform_t plat)56{57int ncpu;5859/* If we've already set the global vars don't bother to do it again. */60if (mp_ncpus != 0)61return;6263/* Read current CP15 Cache Size ID Register */64ncpu = cp15_l2ctlr_get();65ncpu = CPUV7_L2CTLR_NPROC(ncpu);6667mp_ncpus = ncpu;68mp_maxid = ncpu - 1;6970printf("SMP: ncpu=%d\n", ncpu);71}7273static bool74ipq4018_start_ap(u_int id, phandle_t node, u_int addr_cells, pcell_t *arg)75{7677/*78* For the IPQ401x we assume the enable method is79* "qcom,kpss-acc-v2". If this path gets turned into80* something more generic for other 32 bit qualcomm81* SoCs then we'll likely want to turn this into a82* switch based on "enable-method".83*/84return qcom_cpu_kpssv2_regulator_start(id, node);85}8687void88ipq4018_mp_start_ap(platform_t plat)89{90int ret;9192/*93* First step - SCM call to set the cold boot address to mpentry, so94* CPUs hopefully start in the MP path.95*/96ret = qcom_scm_legacy_mp_set_cold_boot_address((vm_offset_t) mpentry);97if (ret != 0)98panic("%s: Couldn't set cold boot address via SCM "99"(error 0x%08x)", __func__, ret);100101/*102* Next step - loop over the CPU nodes and do the per-CPU setup103* required to power on the CPUs themselves.104*/105ofw_cpu_early_foreach(ipq4018_start_ap, true);106107/*108* The next set of IPIs to the CPUs will wake them up and enter109* mpentry.110*/111}112113114