The branch main has been updated by adrian:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=960e65d23aaa55dd00255e95f14c2f6256a4fce3

commit 960e65d23aaa55dd00255e95f14c2f6256a4fce3
Author:     Adrian Chadd <adr...@freebsd.org>
AuthorDate: 2021-10-30 03:34:08 +0000
Commit:     Adrian Chadd <adr...@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 <adr...@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 <adr...@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 <adr...@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 <adr...@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

Reply via email to