]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(versal-net): add SMP support for Versal NET
authorMichal Simek <michal.simek@amd.com>
Mon, 19 Sep 2022 11:52:54 +0000 (13:52 +0200)
committerMichal Simek <michal.simek@amd.com>
Tue, 20 Sep 2022 07:25:32 +0000 (09:25 +0200)
Add SMP support for Versal NET via register access.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Signed-off-by: Akshay Belsare <Akshay.Belsare@amd.com>
Change-Id: I46d73e2cd678ae720b5255722b6b0611c22659e8

plat/xilinx/versal_net/include/plat_pm_common.h [new file with mode: 0644]
plat/xilinx/versal_net/include/versal_net_def.h
plat/xilinx/versal_net/plat_psci.c
plat/xilinx/versal_net/platform.mk
plat/xilinx/versal_net/sip_svc_setup.c

diff --git a/plat/xilinx/versal_net/include/plat_pm_common.h b/plat/xilinx/versal_net/include/plat_pm_common.h
new file mode 100644 (file)
index 0000000..ad7b40f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
+ * Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Contains platform specific definitions of commonly used macros data types
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef PLAT_PM_COMMON_H
+#define PLAT_PM_COMMON_H
+
+#include <stdint.h>
+
+#include <common/debug.h>
+
+#include "pm_defs.h"
+
+#define NON_SECURE_FLAG                1U
+#define SECURE_FLAG            0U
+
+#endif /* PLAT_PM_COMMON_H */
index 826a8239e32a9e6e7be58baffe499a795fb9f3b3..c2dab923456560d2775225ce97dcb13d42ac1993 100644 (file)
 
 /* Global timer reset */
 #define PSX_CRF                        U(0xEC200000)
+#define ACPU0_CLK_CTRL         U(0x10C)
+#define ACPU_CLK_CTRL_CLKACT   BIT(25)
+
+#define RST_APU0_OFFSET                U(0x300)
+#define RST_APU_COLD_RESET     BIT(0)
+#define RST_APU_WARN_RESET     BIT(4)
+#define RST_APU_CLUSTER_COLD_RESET     BIT(8)
+#define RST_APU_CLUSTER_WARM_RESET     BIT(9)
+
 #define PSX_CRF_RST_TIMESTAMP_OFFSET   U(0x33C)
 
+#define APU_PCLI                       U(0xECB10000)
+#define APU_PCLI_CPU_STEP              U(0x30)
+#define APU_PCLI_CLUSTER_CPU_STEP      (4U * APU_PCLI_CPU_STEP)
+#define APU_PCLI_CLUSTER_OFFSET                U(0x8000)
+#define APU_PCLI_CLUSTER_STEP          U(0x1000)
+#define PCLI_PREQ_OFFSET               U(0x4)
+#define PREQ_CHANGE_REQUEST            BIT(0)
+#define PCLI_PSTATE_OFFSET             U(0x8)
+#define PCLI_PSTATE_VAL_SET            U(0x48)
+#define PCLI_PSTATE_VAL_CLEAR          U(0x38)
+
 /* Firmware Image Package */
 #define VERSAL_NET_PRIMARY_CPU         U(0)
 
 
 #define VERSAL_NET_IOU_SCNTRS_CONTROL_EN       U(1)
 
+#define APU_CLUSTER0           U(0xECC00000)
+#define APU_RVBAR_L_0          U(0x40)
+#define APU_RVBAR_H_0          U(0x44)
+#define APU_CLUSTER_STEP       U(0x100000)
+
+#define SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL U(0xF1060504)
+
 /*******************************************************************************
  * IRQ constants
  ******************************************************************************/
index 8acc8b5ee1de30fbcf1932dae3fef7c6a29ee1df..299eca406aff8a4b6cf14f3550cdc4c0d78826c4 100644 (file)
@@ -9,6 +9,7 @@
 #include <assert.h>
 
 #include <common/debug.h>
+#include <common/runtime_svc.h>
 #include <lib/mmio.h>
 #include <lib/psci/psci.h>
 #include <plat/arm/common/plat_arm.h>
 
 #include <plat_private.h>
 
+#define FUNCID_MASK    U(0xffff)
+#define PM_RET_ERROR_NOFEATURE U(19)
+
+#define PM_IOCTL       34U
+
 static uintptr_t versal_net_sec_entry;
 
+static void zynqmp_cpu_standby(plat_local_state_t cpu_state)
+{
+       dsb();
+       wfi();
+}
+
+static int32_t zynqmp_nopmu_pwr_domain_on(u_register_t mpidr)
+{
+       uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
+       uint32_t cpu = cpu_id % PLATFORM_CORE_COUNT_PER_CLUSTER;
+       uint32_t cluster = cpu_id / PLATFORM_CORE_COUNT_PER_CLUSTER;
+       uintptr_t apu_cluster_base = 0, apu_pcli_base, apu_pcli_cluster = 0;
+       uintptr_t rst_apu_cluster = PSX_CRF + RST_APU0_OFFSET + (cluster * 0x4);
+
+       VERBOSE("%s: mpidr: 0x%lx, cpuid: %x, cpu: %x, cluster: %x\n",
+               __func__, mpidr, cpu_id, cpu, cluster);
+
+       if (cpu_id == -1) {
+               return PSCI_E_INTERN_FAIL;
+       }
+
+       if (platform_id == VERSAL_NET_SPP && cluster > 1) {
+               panic();
+       }
+
+       if (cluster > 3) {
+               panic();
+       }
+
+       apu_pcli_cluster = APU_PCLI + APU_PCLI_CLUSTER_OFFSET + (cluster * APU_PCLI_CLUSTER_STEP);
+       apu_cluster_base = APU_CLUSTER0 + (cluster * APU_CLUSTER_STEP);
+
+       /* Enable clock */
+       mmio_setbits_32(PSX_CRF + ACPU0_CLK_CTRL + (cluster * 0x4), ACPU_CLK_CTRL_CLKACT);
+
+       /* Enable cluster states */
+       mmio_setbits_32(apu_pcli_cluster + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_SET);
+       mmio_setbits_32(apu_pcli_cluster + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
+
+       /* assert core reset */
+       mmio_setbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
+
+       /* program RVBAR */
+       mmio_write_32(apu_cluster_base + APU_RVBAR_L_0 + (cpu << 3),
+                     (uint32_t)versal_net_sec_entry);
+       mmio_write_32(apu_cluster_base + APU_RVBAR_H_0 + (cpu << 3),
+                     versal_net_sec_entry >> 32);
+
+       /* de-assert core reset */
+       mmio_clrbits_32(rst_apu_cluster, ((RST_APU_COLD_RESET|RST_APU_WARN_RESET) << cpu));
+
+       /* clear cluster resets */
+       mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_WARM_RESET);
+       mmio_clrbits_32(rst_apu_cluster, RST_APU_CLUSTER_COLD_RESET);
+
+       apu_pcli_base = APU_PCLI + (APU_PCLI_CPU_STEP * cpu) +
+                       (APU_PCLI_CLUSTER_CPU_STEP * cluster);
+
+       mmio_write_32(apu_pcli_base + PCLI_PSTATE_OFFSET, PCLI_PSTATE_VAL_CLEAR);
+       mmio_write_32(apu_pcli_base + PCLI_PREQ_OFFSET, PREQ_CHANGE_REQUEST);
+
+       return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_nopmu_pwr_domain_off(const psci_power_state_t *target_state)
+{
+}
+
+static void __dead2 zynqmp_nopmu_system_reset(void)
+{
+       while (1)
+               wfi();
+}
+
+static int32_t zynqmp_validate_ns_entrypoint(uint64_t ns_entrypoint)
+{
+       return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
+{
+}
+
+static void zynqmp_pwr_domain_on_finish(const psci_power_state_t *target_state)
+{
+       plat_versal_net_gic_pcpu_init();
+       plat_versal_net_gic_cpuif_enable();
+}
+
+static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+}
+
+static void __dead2 zynqmp_system_off(void)
+{
+       while (1)
+               wfi();
+}
+
+static int32_t zynqmp_validate_power_state(uint32_t power_state, psci_power_state_t *req_state)
+{
+       return PSCI_E_SUCCESS;
+}
+
+static void zynqmp_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+       req_state->pwr_domain_state[PSCI_CPU_PWR_LVL] = PLAT_MAX_OFF_STATE;
+       req_state->pwr_domain_state[1] = PLAT_MAX_OFF_STATE;
+}
+
 static const struct plat_psci_ops versal_net_nopmc_psci_ops = {
+       .cpu_standby                    = zynqmp_cpu_standby,
+       .pwr_domain_on                  = zynqmp_nopmu_pwr_domain_on,
+       .pwr_domain_off                 = zynqmp_nopmu_pwr_domain_off,
+       .system_reset                   = zynqmp_nopmu_system_reset,
+       .validate_ns_entrypoint         = zynqmp_validate_ns_entrypoint,
+       .pwr_domain_suspend             = zynqmp_pwr_domain_suspend,
+       .pwr_domain_on_finish           = zynqmp_pwr_domain_on_finish,
+       .pwr_domain_suspend_finish      = zynqmp_pwr_domain_suspend_finish,
+       .system_off                     = zynqmp_system_off,
+       .validate_power_state           = zynqmp_validate_power_state,
+       .get_sys_suspend_power_state    = zynqmp_get_sys_suspend_power_state,
 };
 
 /*******************************************************************************
@@ -36,3 +163,59 @@ int32_t plat_setup_psci_ops(uintptr_t sec_entrypoint,
 
        return 0;
 }
+
+int sip_svc_setup_init(void)
+{
+       return 0;
+}
+
+static int32_t no_pm_ioctl(uint32_t device_id, uint32_t ioctl_id,
+                          uint32_t arg1, uint32_t arg2)
+{
+       VERBOSE("%s: ioctl_id: %x, arg1: %x\n", __func__, ioctl_id, arg1);
+       if (ioctl_id == IOCTL_OSPI_MUX_SELECT) {
+               mmio_write_32(SLCR_OSPI_QSPI_IOU_AXI_MUX_SEL, arg1);
+               return 0;
+       }
+       return PM_RET_ERROR_NOFEATURE;
+}
+
+static uint64_t no_pm_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+                             uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+       int32_t ret;
+       uint32_t arg[4], api_id;
+
+       arg[0] = (uint32_t)x1;
+       arg[1] = (uint32_t)(x1 >> 32);
+       arg[2] = (uint32_t)x2;
+       arg[3] = (uint32_t)(x2 >> 32);
+
+       api_id = smc_fid & FUNCID_NUM_MASK;
+       VERBOSE("%s: smc_fid: %x, api_id=0x%x\n", __func__, smc_fid, api_id);
+
+       switch (smc_fid & FUNCID_MASK) {
+       case PM_IOCTL:
+       {
+               ret = no_pm_ioctl(arg[0], arg[1], arg[2], arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+       }
+       case PM_GET_CHIPID:
+       {
+               uint32_t idcode, version;
+
+               idcode  = mmio_read_32(PMC_TAP);
+               version = mmio_read_32(PMC_TAP_VERSION);
+               SMC_RET2(handle, ((uint64_t)idcode << 32), version);
+       }
+       default:
+               WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
+               SMC_RET1(handle, SMC_UNK);
+       }
+}
+
+uint64_t smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4,
+                    void *cookie, void *handle, uint64_t flags)
+{
+       return no_pm_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+}
index 5ff5b6259e564b57119237ab3f344ff5241c0751..32594c73dcd236205cc255ef50152e02f0c4688b 100644 (file)
@@ -46,7 +46,8 @@ $(eval $(call add_define_val,VERSAL_NET_CONSOLE,VERSAL_NET_CONSOLE_ID_${VERSAL_N
 
 PLAT_INCLUDES          :=      -Iinclude/plat/arm/common/                      \
                                -Iplat/xilinx/common/include/                   \
-                               -I${PLAT_PATH}/include/
+                               -I${PLAT_PATH}/include/                         \
+                               -Iplat/xilinx/versal/pm_service/
 
 # Include GICv3 driver files
 include drivers/arm/gic/v3/gicv3.mk
index 6a94b22004ebd13a32a8c3f0136847fc7e22b1c9..9a8d519a4a00c56df4e0bd47c93182e59fbf418b 100644 (file)
@@ -8,10 +8,15 @@
 
 /* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */
 
+#include <errno.h>
+
 #include <common/debug.h>
 #include <common/runtime_svc.h>
 #include <tools_share/uuid.h>
 
+#include "plat_private.h"
+#include "pm_svc_main.h"
+
 /* SMC function IDs for SiP Service queries */
 #define VERSAL_NET_SIP_SVC_CALL_COUNT  (0x8200ff00U)
 #define VERSAL_NET_SIP_SVC_UID         (0x8200ff01U)
@@ -31,7 +36,7 @@ DEFINE_SVC_UUID2(versal_net_sip_uuid,
  */
 static int32_t sip_svc_setup(void)
 {
-       return 0;
+       return sip_svc_setup_init();
 }
 
 /*