Date: Thu, 4 Nov 2021 16:02:53 GMT From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 960e65d23aaa - main - qcom: add initial SCM legacy API Message-ID: <202111041602.1A4G2rEo003703@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=960e65d23aaa55dd00255e95f14c2f6256a4fce3 commit 960e65d23aaa55dd00255e95f14c2f6256a4fce3 Author: Adrian Chadd <adrian@FreeBSD.org> AuthorDate: 2021-10-30 03:34:08 +0000 Commit: Adrian Chadd <adrian@FreeBSD.org> CommitDate: 2021-11-04 16:02:33 +0000 qcom: add initial SCM legacy API This is a very simple implementation of Qualcomm's SCM API. It is just the structure/field definitions and the atomic SCM call which doesn't use the structs yet - it uses the field definitions inside registers. I've tested that setting the cold boot address via the atomic API is fine - Linux does the same thing. But not all SCM calls can be done via the legacy API. This is a reimplementation based on the Linux qualcomm SCM legacy code and definitions. Tested: * Qualcomm IPQ4018 AP, as part of other changes for doing SMP bring-up Reviewed by: andrew, manu, imp Differential Revision: https://reviews.freebsd.org/D32723 --- sys/arm/conf/std.qca | 3 + sys/arm/qualcomm/qcom_scm_defs.h | 122 ++++++++++++++++++++++++++ sys/arm/qualcomm/qcom_scm_legacy.c | 88 +++++++++++++++++++ sys/arm/qualcomm/qcom_scm_legacy.h | 41 +++++++++ sys/arm/qualcomm/qcom_scm_legacy_defs.h | 149 ++++++++++++++++++++++++++++++++ sys/arm/qualcomm/std.ipq4018 | 1 + 6 files changed, 404 insertions(+) diff --git a/sys/arm/conf/std.qca b/sys/arm/conf/std.qca index 091de6178094..00d627b77b7b 100644 --- a/sys/arm/conf/std.qca +++ b/sys/arm/conf/std.qca @@ -25,6 +25,9 @@ device sdhci device generic_timer device mpcore_timer +# PSCI - SMC calls, needed for qualcomm SCM +device psci + options FDT # Disable CP14 work in DDB as TZ won't let us by default diff --git a/sys/arm/qualcomm/qcom_scm_defs.h b/sys/arm/qualcomm/qcom_scm_defs.h new file mode 100644 index 000000000000..f4fe0fd76b52 --- /dev/null +++ b/sys/arm/qualcomm/qcom_scm_defs.h @@ -0,0 +1,122 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd <adrian@FreeBSD.org> + * + * 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_SCM_DEFS_H__ +#define __QCOM_SCM_DEFS_H__ + +/* + * Maximum SCM arguments and return values. + */ +#define MAX_QCOM_SCM_ARGS 10 +#define MAX_QCOM_SCM_RETS 3 + +/* + * SCM argument type definitions. + */ +#define QCOM_SCM_ARGTYPE_VAL 0x00 +#define QCOM_SCM_ARGTYPE_RO 0x01 +#define QCOM_SCM_ARGTYPE_RW 0x02 +#define QCOM_SCM_ARGTYPE_BUFVAL 0x03 + +/* + * SCM calls + arguments. + */ +#define QCOM_SCM_SVC_BOOT 0x01 +#define QCOM_SCM_BOOT_SET_ADDR 0x01 +#define QCOM_SCM_BOOT_TERMINATE_PC 0x02 +#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10 +#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a +#define QCOM_SCM_FLUSH_FLAG_MASK 0x3 + +/* Flags for QCOM_SCM_BOOT_SET_ADDR argv[0] */ +/* Note: no COLDBOOT for CPU0, it's already booted */ +#define QCOM_SCM_FLAG_COLDBOOT_CPU1 0x01 +#define QCOM_SCM_FLAG_WARMBOOT_CPU1 0x02 +#define QCOM_SCM_FLAG_WARMBOOT_CPU0 0x04 +#define QCOM_SCM_FLAG_COLDBOOT_CPU2 0x08 +#define QCOM_SCM_FLAG_WARMBOOT_CPU2 0x10 +#define QCOM_SCM_FLAG_COLDBOOT_CPU3 0x20 +#define QCOM_SCM_FLAG_WARMBOOT_CPU3 0x40 + +#define QCOM_SCM_SVC_PIL 0x02 +#define QCOM_SCM_PIL_PAS_INIT_IMAGE 0x01 +#define QCOM_SCM_PIL_PAS_MEM_SETUP 0x02 +#define QCOM_SCM_PIL_PAS_AUTH_AND_RESET 0x05 +#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06 +#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07 +#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a + +#define QCOM_SCM_SVC_IO 0x05 +#define QCOM_SCM_IO_READ 0x01 +#define QCOM_SCM_IO_WRITE 0x02 + +/* + * Fetch SCM call availability information. + */ +#define QCOM_SCM_SVC_INFO 0x06 +#define QCOM_SCM_INFO_IS_CALL_AVAIL 0x01 + +#define QCOM_SCM_SVC_MP 0x0c +#define QCOM_SCM_MP_RESTORE_SEC_CFG 0x02 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_SIZE 0x03 +#define QCOM_SCM_MP_IOMMU_SECURE_PTBL_INIT 0x04 +#define QCOM_SCM_MP_VIDEO_VAR 0x08 +#define QCOM_SCM_MP_ASSIGN 0x16 + +#define QCOM_SCM_SVC_OCMEM 0x0f +#define QCOM_SCM_OCMEM_LOCK_CMD 0x01 +#define QCOM_SCM_OCMEM_UNLOCK_CMD 0x02 + +#define QCOM_SCM_SVC_ES 0x10 +#define QCOM_SCM_ES_INVALIDATE_ICE_KEY 0x03 +#define QCOM_SCM_ES_CONFIG_SET_ICE_KEY 0x04 + +#define QCOM_SCM_SVC_HDCP 0x11 +#define QCOM_SCM_HDCP_INVOKE 0x01 + +#define QCOM_SCM_SVC_LMH 0x13 +#define QCOM_SCM_LMH_LIMIT_PROFILE_CHANGE 0x01 +#define QCOM_SCM_LMH_LIMIT_DCVSH 0x10 + +#define QCOM_SCM_SVC_SMMU_PROGRAM 0x15 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03 +#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02 + +/* + * Return values from the SCM calls. + */ +#define QCOM_SCM_RETVAL_V2_EBUSY -12 +#define QCOM_SCM_RETVAL_ENOMEM -5 +#define QCOM_SCM_RETVAL_EOPNOTSUPP -4 +#define QCOM_SCM_RETVAL_EINVAL_ADDR -3 +#define QCOM_SCM_RETVAL_EINVAL_ARG -2 +#define QCOM_SCM_RETVAL_ERROR -1 +#define QCOM_SCM_RETVAL_INTERRUPTED 1 + +#endif /* __QCOM_SCM_DEFS_H__ */ diff --git a/sys/arm/qualcomm/qcom_scm_legacy.c b/sys/arm/qualcomm/qcom_scm_legacy.c new file mode 100644 index 000000000000..d773e095185b --- /dev/null +++ b/sys/arm/qualcomm/qcom_scm_legacy.c @@ -0,0 +1,88 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd <adrian@FreeBSD.org> + * + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/reboot.h> +#include <sys/devmap.h> +#include <sys/smp.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/cpu.h> +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/machdep.h> +#include <machine/smp.h> + +#include <arm/qualcomm/qcom_scm_defs.h> +#include <arm/qualcomm/qcom_scm_legacy_defs.h> +#include <arm/qualcomm/qcom_scm_legacy.h> + +#include <dev/psci/smccc.h> + +/* + * Set the cold boot address for (later) a mask of CPUs. + * + * Don't set it for CPU0, that CPU is the boot CPU and is already alive. + * + * For now it sets it on CPU1..3. + * + * This works on the IPQ4019 as tested; the retval is 0x0. + */ +uint32_t +qcom_scm_legacy_mp_set_cold_boot_address(vm_offset_t mp_entry_func) +{ + struct arm_smccc_res res; + int ret; + int context_id; + + uint32_t scm_arg0 = QCOM_SCM_LEGACY_ATOMIC_ID(QCOM_SCM_SVC_BOOT, + QCOM_SCM_BOOT_SET_ADDR, 2); + + uint32_t scm_arg1 = QCOM_SCM_FLAG_COLDBOOT_CPU1 + | QCOM_SCM_FLAG_COLDBOOT_CPU2 + | QCOM_SCM_FLAG_COLDBOOT_CPU3; + uint32_t scm_arg2 = pmap_kextract((vm_offset_t)mp_entry_func); + + ret = arm_smccc_smc(scm_arg0, (uint32_t) &context_id, scm_arg1, + scm_arg2, 0, 0, 0, 0, &res); + + if (ret == 0 && res.a0 == 0) + return (0); + printf("%s: called; error; ret=0x%08x; retval[0]=0x%08x\n", + __func__, ret, res.a0); + + return (0); +} diff --git a/sys/arm/qualcomm/qcom_scm_legacy.h b/sys/arm/qualcomm/qcom_scm_legacy.h new file mode 100644 index 000000000000..a0f9d44062cf --- /dev/null +++ b/sys/arm/qualcomm/qcom_scm_legacy.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd <adrian@FreeBSD.org> + * + * 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_SCM_LEGACY_H__ +#define __QCOM_SCM_LEGACY_H__ + +/* + * These functions are specific to the 32 bit legacy SCM interface + * used by the IPQ806x and IPQ401x SoCs. + */ + +extern uint32_t qcom_scm_legacy_mp_set_cold_boot_address( + vm_offset_t mp_entry_func); + +#endif /* __QCOM_SCM_LEGACY_H__ */ diff --git a/sys/arm/qualcomm/qcom_scm_legacy_defs.h b/sys/arm/qualcomm/qcom_scm_legacy_defs.h new file mode 100644 index 000000000000..d34a552d4b80 --- /dev/null +++ b/sys/arm/qualcomm/qcom_scm_legacy_defs.h @@ -0,0 +1,149 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2021 Adrian Chadd <adrian@FreeBSD.org> + * + * 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_SCM_LEGACY_DEFS_H__ +#define __QCOM_SCM_LEGACY_DEFS_H__ + +/* + * These definitions are specific to the 32 bit legacy SCM interface + * used by the IPQ806x and IPQ401x SoCs. + */ + +/* + * Mapping of the SCM service/command fields into the a0 argument + * in an SMC instruction call. + * + * This is particular to the legacy SCM interface, and is not the + * same as the non-legacy 32/64 bit FNID mapping layout. + */ +#define QCOM_SCM_LEGACY_SMC_FNID(s, c) (((s) << 10) | ((c) & 0x3ff)) + +/* + * There are two kinds of SCM calls in this legacy path. + * + * The first kind are the normal ones - up to a defined max of arguments, + * a defined max of responses and some identifiers for all of it. + * They can be issues in parallel on different cores, can be interrupted, + * etc. + * + * The second kind are what are termed "atomic" SCM calls - + * up to 5 argument DWORDs, up to 3 response DWORDs, done atomically, + * not interruptable/parallel. + * + * The former use the structures below to represent the request and response + * in memory. The latter use defines and a direct SMC call with the + * arguments in registers. + */ + +struct qcom_scm_legacy_smc_args { + uint32_t args[8]; +}; + +/* + * Atomic SCM call command/response buffer definitions. + */ +#define QCOM_SCM_LEGACY_ATOMIC_MAX_ARGCOUNT 5 +#define QCOM_SCM_LEGACY_CLASS_REGISTER (0x2 << 8) +#define QCOM_SCM_LEGACY_MASK_IRQS (1U << 5) + +/* + * Mapping an SCM service/command/argcount into the a0 register + * for an SMC instruction call. + */ +#define QCOM_SCM_LEGACY_ATOMIC_ID(svc, cmd, n) \ + ((QCOM_SCM_LEGACY_SMC_FNID((svc), cmd) << 12) | \ + QCOM_SCM_LEGACY_CLASS_REGISTER | \ + QCOM_SCM_LEGACY_MASK_IRQS | \ + ((n) & 0xf)) + +/* + * Legacy command/response buffer definitions. + * + * The legacy path contains up to the defined maximum arguments + * but only a single command/response pair per call. + * + * A command and response buffer is laid out in memory as such: + * + * | command header | + * | (buffer payload) | + * | response header | + * | (response payload) | + */ + +/* + * The command header. + * + * len - the length of the total command and response, including + * the headers. + * + * buf_offset - the offset inside the buffer, starting at the + * beginning of this command header, where the command buffer + * is found. The end is the byte before the response_header_offset. + * + * response_header_offset - the offset inside the buffer where + * the response header is found. + * + * id - the QCOM_SCM_LEGACY_SMC_FNID() - service/command ids + */ +struct qcom_scm_legacy_command_header { + uint32_t len; + uint32_t buf_offset; + uint32_t response_header_offset; + uint32_t id; +}; + +/* + * The response header. + * + * This is found immediately after the command header and command + * buffer payload. + * + * len - the total amount of memory available for the response. + * Linux doesn't set this; it always passes in a response + * buffer large enough to store MAX_QCOM_SCM_RETS * DWORD + * bytes. + * + * It's also possible this is set by the firmware. + * + * buf_offset - start of response buffer, relative to the beginning + * of the command header. This also isn't set in Linux before + * calling the SMC instruction, but it is checked afterwards + * to assemble a pointer to the response data. The firmware + * likely sets this. + * + * is_complete - true if complete. Linux loops over DMA sync to + * check if this is complete even after the SMC call returns. + */ +struct qcom_scm_legacy_response_header { + uint32_t len; + uint32_t buf_offset; + uint32_t is_complete; +}; + +#endif /* __QCOM_SCM_LEGACY_DEFS_H__ */ diff --git a/sys/arm/qualcomm/std.ipq4018 b/sys/arm/qualcomm/std.ipq4018 index 823d7e74cb50..6492dbd06b1b 100644 --- a/sys/arm/qualcomm/std.ipq4018 +++ b/sys/arm/qualcomm/std.ipq4018 @@ -1,4 +1,5 @@ arm/qualcomm/ipq4018_machdep.c standard arm/qualcomm/ipq4018_mp.c optional smp +arm/qualcomm/qcom_scm_legacy.c standard dev/qcom_rnd/qcom_rnd.c optional qcom_rnd
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202111041602.1A4G2rEo003703>