diff --git a/sys/arm/qualcomm/ipq4018_mp.c b/sys/arm/qualcomm/ipq4018_mp.c index 37b7cc3e097d..a7ebb7d7d6c8 100644 --- a/sys/arm/qualcomm/ipq4018_mp.c +++ b/sys/arm/qualcomm/ipq4018_mp.c @@ -35,27 +35,82 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include #include +#include #include #include +#include #include +#include +#include #include "platform_if.h" void ipq4018_mp_setmaxid(platform_t plat) { + int ncpu; + + /* If we've already set the global vars don't bother to do it again. */ + if (mp_ncpus != 0) + return; + + /* Read current CP15 Cache Size ID Register */ + ncpu = cp15_l2ctlr_get(); + ncpu = CPUV7_L2CTLR_NPROC(ncpu); + + mp_ncpus = ncpu; + mp_maxid = ncpu - 1; + + printf("SMP: ncpu=%d\n", ncpu); +} + +static boolean_t +ipq4018_start_ap(u_int id, phandle_t node, u_int addr_cells, pcell_t *arg) +{ + + /* + * For the IPQ401x we assume the enable method is + * "qcom,kpss-acc-v2". If this path gets turned into + * something more generic for other 32 bit qualcomm + * SoCs then we'll likely want to turn this into a + * switch based on "enable-method". + */ + return qcom_cpu_kpssv2_regulator_start(id, node); } void ipq4018_mp_start_ap(platform_t plat) { + int ret; + + /* + * First step - SCM call to set the cold boot address to mpentry, so + * CPUs hopefully start in the MP path. + */ + ret = qcom_scm_legacy_mp_set_cold_boot_address((vm_offset_t) mpentry); + if (ret != 0) + panic("%s: Couldn't set cold boot address via SCM " + "(error 0x%08x)", __func__, ret); + + /* + * Next step - loop over the CPU nodes and do the per-CPU setup + * required to power on the CPUs themselves. + */ + ofw_cpu_early_foreach(ipq4018_start_ap, true); + + /* + * The next set of IPIs to the CPUs will wake them up and enter + * mpentry. + */ } diff --git a/sys/arm/qualcomm/qcom_cpu_kpssv2.c b/sys/arm/qualcomm/qcom_cpu_kpssv2.c new file mode 100644 index 000000000000..4193f952549b --- /dev/null +++ b/sys/arm/qualcomm/qcom_cpu_kpssv2.c @@ -0,0 +1,211 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_platform.h" + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "platform_if.h" + +/* + * Since DELAY() hangs this early, we need some way to + * delay things to settle. + */ +static inline void +loop_delay(int usec) +{ + int lcount = usec * 100000; + + for (volatile int i = 0; i < lcount; i++) + ; +} + +/* + * This is the KPSSv2 (eg IPQ4018) regulator path for CPU + * and shared L2 cache power-on. + */ +boolean_t +qcom_cpu_kpssv2_regulator_start(u_int id, phandle_t node) +{ + phandle_t acc_phandle, l2_phandle, saw_phandle; + bus_space_tag_t acc_tag, saw_tag; + bus_space_handle_t acc_handle, saw_handle; + bus_size_t acc_sz, saw_sz; + ssize_t sret; + int ret; + uint32_t reg_val; + + /* + * We don't need to power up CPU 0! This will power it + * down first and ... then everything hangs. + */ + if (id == 0) + return true; + + /* + * Walk the qcom,acc and next-level-cache entries to find their + * child phandles and thus regulators. + * + * The qcom,acc is a phandle to a node. + * + * The next-level-cache actually is a phandle through to a qcom,saw + * entry. + */ + sret = OF_getencprop(node, "qcom,acc", (void *) &acc_phandle, + sizeof(acc_phandle)); + if (sret != sizeof(acc_phandle)) + panic("***couldn't get phandle for qcom,acc"); + acc_phandle = OF_node_from_xref(acc_phandle); + + sret = OF_getencprop(node, "next-level-cache", (void *) &l2_phandle, + sizeof(l2_phandle)); + if (sret != sizeof(l2_phandle)) + panic("***couldn't get phandle for next-level-cache"); + l2_phandle = OF_node_from_xref(l2_phandle); + + sret = OF_getencprop(l2_phandle, "qcom,saw", (void *) &saw_phandle, + sizeof(saw_phandle)); + if (sret != sizeof(saw_phandle)) + panic("***couldn't get phandle for qcom,saw"); + l2_phandle = OF_node_from_xref(l2_phandle); + + /* + * Now that we have the phandles referencing the correct locations, + * do some KVA mappings so we can go access the registers. + */ + ret = OF_decode_addr(acc_phandle, 0, &acc_tag, &acc_handle, &acc_sz); + if (ret != 0) + panic("*** couldn't map qcom,acc space (%d)", ret); + ret = OF_decode_addr(saw_phandle, 0, &saw_tag, &saw_handle, &saw_sz); + if (ret != 0) + panic("*** couldn't map next-level-cache -> " + "qcom,saw space (%d)", ret); + + /* + * Power sequencing to ensure the cores are off, then power them on + * and bring them out of reset. + */ + + /* + * BHS: off + * LDO: bypassed, powered off + */ + reg_val = (64 << QCOM_APC_PWR_GATE_CTL_BHS_CNT_SHIFT) + | (0x3f << QCOM_APC_PWR_GATE_CTL_LDO_PWR_DWN_SHIFT) + | QCOM_APC_PWR_GATE_CTL_BHS_EN; + bus_space_write_4(acc_tag, acc_handle, QCOM_APC_PWR_GATE_CTL, reg_val); + mb(); + /* Settle time */ + loop_delay(1); + + /* + * Start up BHS segments. + */ + reg_val |= 0x3f << QCOM_APC_PWR_GATE_CTL_BHS_SEG_SHIFT; + bus_space_write_4(acc_tag, acc_handle, QCOM_APC_PWR_GATE_CTL, reg_val); + mb(); + /* Settle time */ + loop_delay(1); + + /* + * Switch on the LDO bypass; BHS will now supply power. + */ + reg_val |= 0x3f << QCOM_APC_PWR_GATE_CTL_LDO_BYP_SHIFT; + bus_space_write_4(acc_tag, acc_handle, QCOM_APC_PWR_GATE_CTL, reg_val); + + /* + * Shared L2 regulator control. + */ + bus_space_write_4(saw_tag, saw_handle, QCOM_APCS_SAW2_2_VCTL, 0x10003); + mb(); + /* Settle time */ + loop_delay(50); + + /* + * Put the core in reset. + */ + reg_val = QCOM_APCS_CPU_PWR_CTL_COREPOR_RST + | QCOM_APCS_CPU_PWR_CTL_CLAMP; + bus_space_write_4(acc_tag, acc_handle, QCOM_APCS_CPU_PWR_CTL, reg_val); + mb(); + loop_delay(2); + + /* + * Remove power-down clamp. + */ + reg_val &= ~QCOM_APCS_CPU_PWR_CTL_CLAMP; + bus_space_write_4(acc_tag, acc_handle, QCOM_APCS_CPU_PWR_CTL, reg_val); + mb(); + loop_delay(2); + + /* + * Clear core power reset. + */ + reg_val &= ~QCOM_APCS_CPU_PWR_CTL_COREPOR_RST; + bus_space_write_4(acc_tag, acc_handle, QCOM_APCS_CPU_PWR_CTL, reg_val); + mb(); + + /* + * The power is ready, the core is out of reset, signal the core + * to power up. + */ + reg_val |= QCOM_APCS_CPU_PWR_CTL_CORE_PWRD_UP; + bus_space_write_4(acc_tag, acc_handle, QCOM_APCS_CPU_PWR_CTL, reg_val); + mb(); + + /* + * Finished with these KVA mappings, so release them. + */ + bus_space_unmap(acc_tag, acc_handle, acc_sz); + bus_space_unmap(saw_tag, saw_handle, saw_sz); + + return true; +} diff --git a/sys/arm/qualcomm/qcom_cpu_kpssv2.h b/sys/arm/qualcomm/qcom_cpu_kpssv2.h new file mode 100644 index 000000000000..18e4affc208e --- /dev/null +++ b/sys/arm/qualcomm/qcom_cpu_kpssv2.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __QCOM_CPU_KPSSV2_H__ +#define __QCOM_CPU_KPSSV2_H__ + +extern boolean_t qcom_cpu_kpssv2_regulator_start(u_int id, phandle_t node); + +#endif /* __QCOM_CPU_KPSSV2_H__ */ diff --git a/sys/arm/qualcomm/qcom_cpu_kpssv2_reg.h b/sys/arm/qualcomm/qcom_cpu_kpssv2_reg.h new file mode 100644 index 000000000000..b966571e9fdd --- /dev/null +++ b/sys/arm/qualcomm/qcom_cpu_kpssv2_reg.h @@ -0,0 +1,58 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef __QCOM_CPU_KPSSV2_REG_H__ +#define __QCOM_CPU_KPSSV2_REG_H__ + + +/* + * APCS CPU core regulator registers. + */ +#define QCOM_APCS_CPU_PWR_CTL 0x04 +#define QCOM_APCS_CPU_PWR_CTL_PLL_CLAMP (1U << 8) +#define QCOM_APCS_CPU_PWR_CTL_CORE_PWRD_UP (1U << 7) +#define QCOM_APCS_CPU_PWR_CTL_COREPOR_RST (1U << 5) +#define QCOM_APCS_CPU_PWR_CTL_CORE_RST (1U << 4) +#define QCOM_APCS_CPU_PWR_CTL_L2DT_SLP (1U << 3) +#define QCOM_APCS_CPU_PWR_CTL_CLAMP (1U << 0) + +#define QCOM_APC_PWR_GATE_CTL 0x14 +#define QCOM_APC_PWR_GATE_CTL_BHS_CNT_SHIFT 24 +#define QCOM_APC_PWR_GATE_CTL_LDO_PWR_DWN_SHIFT 16 +#define QCOM_APC_PWR_GATE_CTL_LDO_BYP_SHIFT 8 +#define QCOM_APC_PWR_GATE_CTL_BHS_SEG_SHIFT 1 +#define QCOM_APC_PWR_GATE_CTL_BHS_EN (1U << 0) + + +/* + * L2 cache regulator registers. + */ +#define QCOM_APCS_SAW2_2_VCTL 0x1c + +#endif /* __QCOM_CPU_KPSSV2_REG_H__ */ diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 index 6492dbd06b1b..099fd81b5171 100644 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -1,5 +1,6 @@ arm/qualcomm/ipq4018_machdep.c standard arm/qualcomm/ipq4018_mp.c optional smp arm/qualcomm/qcom_scm_legacy.c standard +arm/qualcomm/qcom_cpu_kpssv2.c optional smp dev/qcom_rnd/qcom_rnd.c optional qcom_rnd