]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
refactor(xilinx): move versal files to common place
authorJay Buddhabhatti <jay.buddhabhatti@amd.com>
Thu, 22 Dec 2022 07:03:35 +0000 (23:03 -0800)
committerJay Buddhabhatti <jay.buddhabhatti@amd.com>
Tue, 28 Mar 2023 05:57:00 +0000 (22:57 -0700)
Moved necessary files to common place so that it can be used for
Versal NET.

Signed-off-by: Jay Buddhabhatti <jay.buddhabhatti@amd.com>
Change-Id: I611fa849207b082e6599acfb65c55d27b9c99435

28 files changed:
plat/xilinx/common/include/pm_api_sys.h [new file with mode: 0644]
plat/xilinx/common/include/pm_node.h [new file with mode: 0644]
plat/xilinx/common/include/pm_svc_main.h [new file with mode: 0644]
plat/xilinx/common/pm_service/pm_api_sys.c [new file with mode: 0644]
plat/xilinx/common/pm_service/pm_svc_main.c [new file with mode: 0644]
plat/xilinx/versal/platform.mk
plat/xilinx/versal/pm_service/pm_api_sys.c [deleted file]
plat/xilinx/versal/pm_service/pm_api_sys.h [deleted file]
plat/xilinx/versal/pm_service/pm_node.h [deleted file]
plat/xilinx/versal/pm_service/pm_svc_main.c [deleted file]
plat/xilinx/versal/pm_service/pm_svc_main.h [deleted file]
plat/xilinx/versal_net/platform.mk
plat/xilinx/zynqmp/aarch64/zynqmp_common.c
plat/xilinx/zynqmp/libpm.mk
plat/xilinx/zynqmp/plat_psci.c
plat/xilinx/zynqmp/pm_service/pm_api_clock.c
plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c
plat/xilinx/zynqmp/pm_service/pm_api_sys.c [deleted file]
plat/xilinx/zynqmp/pm_service/pm_api_sys.h [deleted file]
plat/xilinx/zynqmp/pm_service/pm_client.c
plat/xilinx/zynqmp/pm_service/pm_svc_main.c [deleted file]
plat/xilinx/zynqmp/pm_service/pm_svc_main.h [deleted file]
plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c [new file with mode: 0644]
plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.h [new file with mode: 0644]
plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c [new file with mode: 0644]
plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.h [new file with mode: 0644]
plat/xilinx/zynqmp/sip_svc_setup.c

diff --git a/plat/xilinx/common/include/pm_api_sys.h b/plat/xilinx/common/include/pm_api_sys.h
new file mode 100644 (file)
index 0000000..e7b1567
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_API_SYS_H
+#define PM_API_SYS_H
+
+#include <stdint.h>
+#include "pm_defs.h"
+
+/*********************************************************************
+ * Target module IDs macros
+ ********************************************************************/
+#define LIBPM_MODULE_ID                0x2U
+#define LOADER_MODULE_ID       0x7U
+
+#define MODULE_ID_MASK         0x0000ff00U
+/**********************************************************
+ * PM API function declarations
+ **********************************************************/
+
+enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
+                                      uint32_t x2, uint32_t x3, uint32_t x4,
+                                      uint32_t x5, uint64_t *result);
+enum pm_ret_status pm_self_suspend(uint32_t nid,
+                                  uint32_t latency,
+                                  uint32_t state,
+                                  uintptr_t address, uint32_t flag);
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag);
+enum pm_ret_status pm_req_suspend(uint32_t target,
+                                 uint8_t ack,
+                                 uint32_t latency,
+                                 uint32_t state, uint32_t flag);
+enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
+                                uintptr_t address, uint8_t ack, uint32_t flag);
+enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
+                                       uint8_t enable, uint32_t flag);
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
+                        uint32_t ack);
+enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
+                                   uint32_t value, uint32_t flag);
+enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
+                                   uint32_t *value, uint32_t flag);
+enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
+                                  uint32_t flag);
+enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
+                                  uint32_t flag);
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
+                                     uint32_t flag);
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
+                                     uint32_t flag);
+enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
+                               uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                               uint32_t *value, uint32_t flag);
+enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
+                                uint32_t arg3, uint32_t *data, uint32_t flag);
+uint32_t pm_get_shutdown_scope(void);
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
+                                   uint32_t flag);
+enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
+                              uint32_t address_high, uint32_t flag);
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+                                       uint32_t wake, uint32_t enable,
+                                       uint32_t flag);
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) {        \
+       pl[0] = (uint32_t)(((uint32_t)(arg0) & 0xFFU) | ((mid) << 8U) | ((flag) << 24U)); \
+}
+
+#define PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1) {          \
+       pl[1] = (uint32_t)(arg1);                               \
+       PM_PACK_PAYLOAD1(pl, (mid), (flag), (arg0));                    \
+}
+
+#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) {    \
+       pl[2] = (uint32_t)(arg2);                               \
+       PM_PACK_PAYLOAD2(pl, (mid), (flag), (arg0), (arg1));            \
+}
+
+#define PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3) {      \
+       pl[3] = (uint32_t)(arg3);                                       \
+       PM_PACK_PAYLOAD3(pl, (mid), (flag), (arg0), (arg1), (arg2));            \
+}
+
+#define PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4) {        \
+       pl[4] = (uint32_t)(arg4);                                       \
+       PM_PACK_PAYLOAD4(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3));    \
+}
+
+#define PM_PACK_PAYLOAD6(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5) {  \
+       pl[5] = (uint32_t)(arg5);                                               \
+       PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4));            \
+}
+
+#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/common/include/pm_node.h b/plat/xilinx/common/include/pm_node.h
new file mode 100644 (file)
index 0000000..371c72d
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Versal PM nodes enums and defines */
+
+#ifndef PM_NODE_H
+#define PM_NODE_H
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+#define NODE_CLASS_SHIFT       26U
+#define NODE_SUBCLASS_SHIFT    20U
+#define NODE_TYPE_SHIFT                14U
+#define NODE_INDEX_SHIFT       0U
+#define NODE_CLASS_MASK_BITS    0x3F
+#define NODE_SUBCLASS_MASK_BITS 0x3F
+#define NODE_TYPE_MASK_BITS     0x3F
+#define NODE_INDEX_MASK_BITS    0x3FFF
+#define NODE_CLASS_MASK         (NODE_CLASS_MASK_BITS << NODE_CLASS_SHIFT)
+#define NODE_SUBCLASS_MASK      (NODE_SUBCLASS_MASK_BITS << NODE_SUBCLASS_SHIFT)
+#define NODE_TYPE_MASK          (NODE_TYPE_MASK_BITS << NODE_TYPE_SHIFT)
+#define NODE_INDEX_MASK         (NODE_INDEX_MASK_BITS << NODE_INDEX_SHIFT)
+
+#define NODEID(CLASS, SUBCLASS, TYPE, INDEX)   \
+            ((((CLASS) & NODE_CLASS_MASK_BITS) << NODE_CLASS_SHIFT) | \
+            (((SUBCLASS) & NODE_SUBCLASS_MASK_BITS) << NODE_SUBCLASS_SHIFT) | \
+            (((TYPE) & NODE_TYPE_MASK_BITS) << NODE_TYPE_SHIFT) | \
+            (((INDEX) & NODE_INDEX_MASK_BITS) << NODE_INDEX_SHIFT))
+
+#define NODECLASS(ID)          (((ID) & NODE_CLASS_MASK) >> NODE_CLASS_SHIFT)
+#define NODESUBCLASS(ID)       (((ID) & NODE_SUBCLASS_MASK) >> \
+                               NODE_SUBCLASS_SHIFT)
+#define NODETYPE(ID)           (((ID) & NODE_TYPE_MASK) >> NODE_TYPE_SHIFT)
+#define NODEINDEX(ID)          (((ID) & NODE_INDEX_MASK) >> NODE_INDEX_SHIFT)
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+/* Node class types */
+enum pm_node_class {
+       XPM_NODECLASS_MIN,
+
+       XPM_NODECLASS_POWER,
+       XPM_NODECLASS_CLOCK,
+       XPM_NODECLASS_RESET,
+       XPM_NODECLASS_MEMIC,
+       XPM_NODECLASS_STMIC,
+       XPM_NODECLASS_DEVICE,
+
+       XPM_NODECLASS_MAX
+};
+
+enum pm_device_node_subclass {
+       /* Device types */
+       XPM_NODESUBCL_DEV_CORE = 1,
+       XPM_NODESUBCL_DEV_PERIPH,
+       XPM_NODESUBCL_DEV_MEM,
+       XPM_NODESUBCL_DEV_SOC,
+       XPM_NODESUBCL_DEV_MEM_CTRLR,
+       XPM_NODESUBCL_DEV_PHY,
+};
+
+enum pm_device_node_type {
+       /* Device types */
+       XPM_NODETYPE_DEV_CORE_PMC = 1,
+       XPM_NODETYPE_DEV_CORE_PSM,
+       XPM_NODETYPE_DEV_CORE_APU,
+       XPM_NODETYPE_DEV_CORE_RPU,
+       XPM_NODETYPE_DEV_OCM,
+       XPM_NODETYPE_DEV_TCM,
+       XPM_NODETYPE_DEV_L2CACHE,
+       XPM_NODETYPE_DEV_DDR,
+       XPM_NODETYPE_DEV_PERIPH,
+       XPM_NODETYPE_DEV_SOC,
+       XPM_NODETYPE_DEV_GT,
+};
+
+/* Device node Indexes */
+enum pm_device_node_idx {
+       /* Device nodes */
+       XPM_NODEIDX_DEV_MIN,
+
+       /* Processor devices */
+       XPM_NODEIDX_DEV_PMC_PROC,
+       XPM_NODEIDX_DEV_PSM_PROC,
+       XPM_NODEIDX_DEV_ACPU_0,
+       XPM_NODEIDX_DEV_ACPU_1,
+       XPM_NODEIDX_DEV_RPU0_0,
+       XPM_NODEIDX_DEV_RPU0_1,
+
+       /* Memory devices */
+       XPM_NODEIDX_DEV_OCM_0,
+       XPM_NODEIDX_DEV_OCM_1,
+       XPM_NODEIDX_DEV_OCM_2,
+       XPM_NODEIDX_DEV_OCM_3,
+       XPM_NODEIDX_DEV_TCM_0_A,
+       XPM_NODEIDX_DEV_TCM_0_B,
+       XPM_NODEIDX_DEV_TCM_1_A,
+       XPM_NODEIDX_DEV_TCM_1_B,
+       XPM_NODEIDX_DEV_L2_BANK_0,
+       XPM_NODEIDX_DEV_DDR_0,
+       XPM_NODEIDX_DEV_DDR_1,
+       XPM_NODEIDX_DEV_DDR_2,
+       XPM_NODEIDX_DEV_DDR_3,
+       XPM_NODEIDX_DEV_DDR_4,
+       XPM_NODEIDX_DEV_DDR_5,
+       XPM_NODEIDX_DEV_DDR_6,
+       XPM_NODEIDX_DEV_DDR_7,
+
+       /* LPD Peripheral devices */
+       XPM_NODEIDX_DEV_USB_0,
+       XPM_NODEIDX_DEV_GEM_0,
+       XPM_NODEIDX_DEV_GEM_1,
+       XPM_NODEIDX_DEV_SPI_0,
+       XPM_NODEIDX_DEV_SPI_1,
+       XPM_NODEIDX_DEV_I2C_0,
+       XPM_NODEIDX_DEV_I2C_1,
+       XPM_NODEIDX_DEV_CAN_FD_0,
+       XPM_NODEIDX_DEV_CAN_FD_1,
+       XPM_NODEIDX_DEV_UART_0,
+       XPM_NODEIDX_DEV_UART_1,
+       XPM_NODEIDX_DEV_GPIO,
+       XPM_NODEIDX_DEV_TTC_0,
+       XPM_NODEIDX_DEV_TTC_1,
+       XPM_NODEIDX_DEV_TTC_2,
+       XPM_NODEIDX_DEV_TTC_3,
+       XPM_NODEIDX_DEV_SWDT_LPD,
+
+       /* FPD Peripheral devices */
+       XPM_NODEIDX_DEV_SWDT_FPD,
+
+       /* PMC Peripheral devices */
+       XPM_NODEIDX_DEV_OSPI,
+       XPM_NODEIDX_DEV_QSPI,
+       XPM_NODEIDX_DEV_GPIO_PMC,
+       XPM_NODEIDX_DEV_I2C_PMC,
+       XPM_NODEIDX_DEV_SDIO_0,
+       XPM_NODEIDX_DEV_SDIO_1,
+
+       XPM_NODEIDX_DEV_PL_0,
+       XPM_NODEIDX_DEV_PL_1,
+       XPM_NODEIDX_DEV_PL_2,
+       XPM_NODEIDX_DEV_PL_3,
+       XPM_NODEIDX_DEV_RTC,
+       XPM_NODEIDX_DEV_ADMA_0,
+       XPM_NODEIDX_DEV_ADMA_1,
+       XPM_NODEIDX_DEV_ADMA_2,
+       XPM_NODEIDX_DEV_ADMA_3,
+       XPM_NODEIDX_DEV_ADMA_4,
+       XPM_NODEIDX_DEV_ADMA_5,
+       XPM_NODEIDX_DEV_ADMA_6,
+       XPM_NODEIDX_DEV_ADMA_7,
+       XPM_NODEIDX_DEV_IPI_0,
+       XPM_NODEIDX_DEV_IPI_1,
+       XPM_NODEIDX_DEV_IPI_2,
+       XPM_NODEIDX_DEV_IPI_3,
+       XPM_NODEIDX_DEV_IPI_4,
+       XPM_NODEIDX_DEV_IPI_5,
+       XPM_NODEIDX_DEV_IPI_6,
+
+       /* Entire SoC */
+       XPM_NODEIDX_DEV_SOC,
+
+       /* DDR memory controllers */
+       XPM_NODEIDX_DEV_DDRMC_0,
+       XPM_NODEIDX_DEV_DDRMC_1,
+       XPM_NODEIDX_DEV_DDRMC_2,
+       XPM_NODEIDX_DEV_DDRMC_3,
+
+       /* GT devices */
+       XPM_NODEIDX_DEV_GT_0,
+       XPM_NODEIDX_DEV_GT_1,
+       XPM_NODEIDX_DEV_GT_2,
+       XPM_NODEIDX_DEV_GT_3,
+       XPM_NODEIDX_DEV_GT_4,
+       XPM_NODEIDX_DEV_GT_5,
+       XPM_NODEIDX_DEV_GT_6,
+       XPM_NODEIDX_DEV_GT_7,
+       XPM_NODEIDX_DEV_GT_8,
+       XPM_NODEIDX_DEV_GT_9,
+       XPM_NODEIDX_DEV_GT_10,
+
+       XPM_NODEIDX_DEV_MAX
+};
+
+#endif /* PM_NODE_H */
diff --git a/plat/xilinx/common/include/pm_svc_main.h b/plat/xilinx/common/include/pm_svc_main.h
new file mode 100644 (file)
index 0000000..1a27bdf
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PM_SVC_MAIN_H
+#define PM_SVC_MAIN_H
+
+#include <pm_common.h>
+
+int32_t pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+                       uint64_t x4, const void *cookie, void *handle,
+                       uint64_t flags);
+
+int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset);
+#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/common/pm_service/pm_api_sys.c b/plat/xilinx/common/pm_service/pm_api_sys.c
new file mode 100644 (file)
index 0000000..6ff61af
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Versal system level PM-API functions and communication with PMC via
+ * IPI interrupts
+ */
+
+#include <pm_common.h>
+#include <pm_ipi.h>
+#include <plat/common/platform.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_defs.h"
+#include "pm_svc_main.h"
+
+/* default shutdown/reboot scope is system(2) */
+static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
+
+/**
+ * pm_get_shutdown_scope() - Get the currently set shutdown scope
+ *
+ * @return     Shutdown scope value
+ */
+uint32_t pm_get_shutdown_scope(void)
+{
+       return pm_shutdown_scope;
+}
+
+/* PM API functions */
+
+/**
+ * pm_handle_eemi_call() - PM call for processor to send eemi payload
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ * @x0 to x5   Arguments received per SMC64 standard
+ * @result     Payload received from firmware
+ *
+ * @return      PM_RET_SUCCESS on success or error code
+ */
+enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
+                                      uint32_t x2, uint32_t x3, uint32_t x4,
+                                      uint32_t x5, uint64_t *result)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT] = {0};
+       uint32_t module_id;
+
+       module_id = (x0 & MODULE_ID_MASK) >> 8U;
+
+       //default module id is for LIBPM
+       if (module_id == 0) {
+               module_id = LIBPM_MODULE_ID;
+       }
+
+       PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
+       return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
+}
+
+/**
+ * pm_self_suspend() - PM call for processor to suspend itself
+ * @nid                Node id of the processor or subsystem
+ * @latency    Requested maximum wakeup latency (not supported)
+ * @state      Requested state
+ * @address    Resume address
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(uint32_t nid,
+                                  uint32_t latency,
+                                  uint32_t state,
+                                  uintptr_t address, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint32_t cpuid = plat_my_core_pos();
+       const struct pm_proc *proc = pm_get_proc(cpuid);
+
+       if (proc == NULL) {
+               WARN("Failed to get proc %d\n", cpuid);
+               return PM_RET_ERROR_INTERNAL;
+       }
+
+       /*
+        * Do client specific suspend operations
+        * (e.g. set powerdown request bit)
+        */
+       pm_client_suspend(proc, state);
+
+       /* Send request to the PLM */
+       PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND,
+                        proc->node_id, latency, state, address,
+                        (address >> 32));
+       return pm_ipi_send_sync(proc, payload, NULL, 0);
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ *                     is to be aborted.
+ * @reason     Reason for the abort
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /*
+        * Do client specific abort suspend operations
+        * (e.g. enable interrupts and clear powerdown request bit)
+        */
+       pm_client_abort_suspend();
+
+       /* Send request to the PLM */
+       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND,
+                        reason, primary_proc->node_id);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ *                   be suspended gracefully.
+ * @target     Node id of the targeted PU or subsystem
+ * @ack                Flag to specify whether acknowledge is requested
+ * @latency    Requested wakeup latency (not supported)
+ * @state      Requested state (not supported)
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
+                                 uint32_t latency, uint32_t state,
+                                 uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
+                        latency, state);
+       if (ack == IPI_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ *                  or subsystem
+ * @target     Device ID of the processor or subsystem to wake up
+ * @set_address        Resume address presence indicator
+ *             1 - resume address specified, 0 - otherwise
+ * @address    Resume address
+ * @ack                Flag to specify whether acknowledge requested
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMC.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
+                                uintptr_t address, uint8_t ack, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC to perform the wake of the PU */
+       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target,
+                        set_address, address, ack);
+
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ * @flag - 0 - Call from secure source
+ *        1 - Call from non-secure source
+ * @ack - 0 - Do not ack IPI after reading payload
+ *        1 - Ack IPI after reading payload
+ *
+ * Read value from ipi buffer response buffer.
+ * @return     Returns status, either success or error
+ */
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
+{
+       enum pm_ret_status ret = PM_RET_SUCCESS;
+       /* Return if interrupt is not from PMU */
+       if (pm_ipi_irq_status(primary_proc) == 0) {
+               return ret;
+       }
+
+       ret = pm_ipi_buff_read_callb(data, count);
+
+       if (ack != 0U) {
+               pm_ipi_irq_clear(primary_proc);
+       }
+
+       return ret;
+}
+
+/**
+ * pm_pll_set_param() - Set PLL parameter
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id     PLL clock ID
+ * @param      PLL parameter ID
+ * @value      Value to set for PLL parameter
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
+                                   uint32_t value, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER,
+                        clk_id, param, value);
+
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_param() - Get PLL parameter value
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id     PLL clock ID
+ * @param      PLL parameter ID
+ * @value:     Buffer to store PLL parameter value
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
+                                   uint32_t *value, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER,
+                        clk_id, param);
+
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_pll_set_mode() - Set PLL mode
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id     PLL clock ID
+ * @mode       PLL mode
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
+                                  uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE,
+                        clk_id, mode);
+
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_mode() - Get PLL mode
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @clk_id     PLL clock ID
+ * @mode:      Buffer to store PLL mode
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
+                                  uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE,
+                        clk_id);
+
+       return pm_ipi_send_sync(primary_proc, payload, mode, 1);
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ *                       be powered down forcefully
+ * @target     Device ID of the PU node to be forced powered down.
+ * @ack                Flag to specify whether acknowledge is requested
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
+                                     uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
+                        target, ack);
+
+       if (ack == IPI_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @type       Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
+ * @subtype    Scope: 0=APU-subsystem, 1=PS, 2=system
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
+                                     uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
+               /* Setting scope for subsequent PSCI reboot or shutdown */
+               pm_shutdown_scope = subtype;
+               return PM_RET_SUCCESS;
+       }
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN,
+                        type, subtype);
+
+       return pm_ipi_send_non_blocking(primary_proc, payload);
+}
+
+/**
+ * pm_query_data() -  PM API for querying firmware data
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @qid        The type of data to query
+ * @arg1       Argument 1 to requested query data call
+ * @arg2       Argument 2 to requested query data call
+ * @arg3       Argument 3 to requested query data call
+ * @data       Returned output data
+ * @flag 0 - Call from secure source
+ *     1 - Call from non-secure source
+ *
+ * @retur - 0 if success else non-zero error code of type
+ * enum pm_ret_status
+ */
+enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
+                                uint32_t arg3, uint32_t *data, uint32_t flag)
+{
+       uint32_t ret;
+       uint32_t version[PAYLOAD_ARG_CNT] = {0};
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint32_t fw_api_version;
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid,
+                        arg1, arg2, arg3);
+
+       ret = pm_feature_check(PM_QUERY_DATA, &version[0], flag);
+       if (ret == PM_RET_SUCCESS) {
+               fw_api_version = version[0] & 0xFFFFU;
+               if ((fw_api_version == 2U) &&
+                   ((qid == XPM_QID_CLOCK_GET_NAME) ||
+                    (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) {
+                       ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
+                       if (ret == PM_RET_SUCCESS) {
+                               ret = data[0];
+                               data[0] = data[1];
+                               data[1] = data[2];
+                               data[2] = data[3];
+                       }
+               } else {
+                       ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
+               }
+       }
+       return ret;
+}
+/**
+ * pm_api_ioctl() -  PM IOCTL API for device control and configs
+ *
+ * This API is deprecated and maintained here for backward compatibility.
+ * New use of this API should be avoided for versal platform.
+ * This API and its use cases will be removed for versal platform.
+ *
+ * @device_id  Device ID
+ * @ioctl_id   ID of the requested IOCTL
+ * @arg1       Argument 1 to requested IOCTL call
+ * @arg2       Argument 2 to requested IOCTL call
+ * @arg3       Argument 3 to requested IOCTL call
+ * @value      Returned output value
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return     Returns status, either 0 on success or non-zero error code
+ * of type enum pm_ret_status
+ */
+enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
+                               uint32_t arg1, uint32_t arg2, uint32_t arg3,
+                               uint32_t *value, uint32_t flag)
+{
+       enum pm_ret_status ret;
+
+       switch (ioctl_id) {
+       case IOCTL_SET_PLL_FRAC_MODE:
+               ret =  pm_pll_set_mode(arg1, arg2, flag);
+               break;
+       case IOCTL_GET_PLL_FRAC_MODE:
+               ret =  pm_pll_get_mode(arg1, value, flag);
+               break;
+       case IOCTL_SET_PLL_FRAC_DATA:
+               ret =  pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
+               break;
+       case IOCTL_GET_PLL_FRAC_DATA:
+               ret =  pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
+               break;
+       case IOCTL_SET_SGI:
+               /* Get the sgi number */
+               ret = pm_register_sgi(arg1, arg2);
+               if (ret != 0) {
+                       return PM_RET_ERROR_ARGS;
+               }
+               ret = PM_RET_SUCCESS;
+               break;
+       default:
+               return PM_RET_ERROR_NOTSUPPORTED;
+       }
+
+       return ret;
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target     Device id of the targeted PU or subsystem
+ * @wkup_node  Device id of the wakeup peripheral
+ * @enable     Enable or disable the specified peripheral as wake source
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
+                                       uint8_t enable, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE,
+                        target, wkup_device, enable);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_feature_check() - Returns the supported API version if supported
+ * @api_id     API ID to check
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ * @ret_payload pointer to array of PAYLOAD_ARG_CNT number of
+ *             words Returned supported API version and bitmasks
+ *             for IOCTL and QUERY ID
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
+                                   uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint32_t module_id;
+
+       /* Return version of API which are implemented in ATF only */
+       switch (api_id) {
+       case PM_GET_CALLBACK_DATA:
+       case PM_GET_TRUSTZONE_VERSION:
+               ret_payload[0] = PM_API_VERSION_2;
+               return PM_RET_SUCCESS;
+       case TF_A_PM_REGISTER_SGI:
+               ret_payload[0] = PM_API_BASE_VERSION;
+               return PM_RET_SUCCESS;
+       default:
+               break;
+       }
+
+       module_id = (api_id & MODULE_ID_MASK) >> 8U;
+
+       /*
+        * feature check should be done only for LIBPM module
+        * If module_id is 0, then we consider it LIBPM module as default id
+        */
+       if ((module_id > 0) && (module_id != LIBPM_MODULE_ID)) {
+               return PM_RET_SUCCESS;
+       }
+
+       PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
+                        PM_FEATURE_CHECK, api_id);
+       return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
+}
+
+/**
+ * pm_load_pdi() - Load the PDI
+ *
+ * This function provides support to load PDI from linux
+ *
+ * src:        Source device of pdi(DDR, OCM, SD etc)
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
+                              uint32_t address_high, uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src,
+                        address_high, address_low);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_register_notifier() - PM call to register a subsystem to be notified
+ *                         about the device event
+ * @device_id  Device ID for the Node to which the event is related
+ * @event      Event in question
+ * @wake       Wake subsystem upon capturing the event if value 1
+ * @enable     Enable the registration for value 1, disable for value 0
+ * @flag       0 - Call from secure source
+ *             1 - Call from non-secure source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
+                                       uint32_t wake, uint32_t enable,
+                                       uint32_t flag)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMC */
+       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER,
+                        device_id, event, wake, enable);
+
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c
new file mode 100644 (file)
index 0000000..6fd7f0d
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for Versal power management calls and
+ * IPI setup functions for communication with PMC.
+ */
+
+#include <errno.h>
+#include <plat_private.h>
+#include <stdbool.h>
+#include <common/runtime_svc.h>
+#include <plat/common/platform.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include <drivers/arm/gicv3.h>
+#include "../drivers/arm/gic/v3/gicv3_private.h"
+
+#define MODE                           0x80000000U
+
+#define XSCUGIC_SGIR_EL1_INITID_SHIFT    24U
+#define INVALID_SGI    0xFFU
+#define PM_INIT_SUSPEND_CB     (30U)
+#define PM_NOTIFY_CB           (32U)
+DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
+
+/* pm_up = true - UP, pm_up = false - DOWN */
+static bool pm_up;
+static uint32_t sgi = (uint32_t)INVALID_SGI;
+
+static void notify_os(void)
+{
+       int32_t cpu;
+       uint32_t reg;
+
+       cpu = plat_my_core_pos() + 1U;
+
+       reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
+       write_icc_asgi1r_el1(reg);
+}
+
+static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+                               void *cookie)
+{
+       uint32_t payload[4] = {0};
+       enum pm_ret_status ret;
+
+       VERBOSE("Received IPI FIQ from firmware\n");
+
+       (void)plat_ic_acknowledge_interrupt();
+
+       ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
+       if (ret != PM_RET_SUCCESS) {
+               payload[0] = ret;
+       }
+
+       switch (payload[0]) {
+       case PM_INIT_SUSPEND_CB:
+       case PM_NOTIFY_CB:
+               if (sgi != INVALID_SGI) {
+                       notify_os();
+               }
+               break;
+       case PM_RET_ERROR_INVALID_CRC:
+               pm_ipi_irq_clear(primary_proc);
+               WARN("Invalid CRC in the payload\n");
+               break;
+
+       default:
+               pm_ipi_irq_clear(primary_proc);
+               WARN("Invalid IPI payload\n");
+               break;
+       }
+
+       /* Clear FIQ */
+       plat_ic_end_of_interrupt(id);
+
+       return 0;
+}
+
+/**
+ * pm_register_sgi() - PM register the IPI interrupt
+ *
+ * @sgi -  SGI number to be used for communication.
+ * @reset -  Reset to invalid SGI when reset=1.
+ * @return     On success, the initialization function must return 0.
+ *             Any other return value will cause the framework to ignore
+ *             the service
+ *
+ * Update the SGI number to be used.
+ *
+ */
+int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset)
+{
+       if (reset == 1U) {
+               sgi = INVALID_SGI;
+               return 0;
+       }
+
+       if (sgi != INVALID_SGI) {
+               return -EBUSY;
+       }
+
+       if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
+               return -EINVAL;
+       }
+
+       sgi = (uint32_t)sgi_num;
+       return 0;
+}
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return     On success, the initialization function must return 0.
+ *             Any other return value will cause the framework to ignore
+ *             the service
+ *
+ * Initialization functions for Versal power management for
+ * communicaton with PMC.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ */
+int32_t pm_setup(void)
+{
+       int32_t ret = 0;
+
+       pm_ipi_init(primary_proc);
+       pm_up = true;
+
+       /*
+        * Enable IPI IRQ
+        * assume the rich OS is OK to handle callback IRQs now.
+        * Even if we were wrong, it would not enable the IRQ in
+        * the GIC.
+        */
+       pm_ipi_irq_enable(primary_proc);
+
+       ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
+       if (ret != 0) {
+               WARN("BL31: registering IPI interrupt failed\n");
+       }
+
+       gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
+       return ret;
+}
+
+/**
+ * eemi_for_compatibility() - EEMI calls handler for deprecated calls
+ *
+ * @return - If EEMI API found then, uintptr_t type address, else 0
+ *
+ * Some EEMI API's use case needs to be changed in Linux driver, so they
+ * can take advantage of common EEMI handler in TF-A. As of now the old
+ * implementation of these APIs are required to maintain backward compatibility
+ * until their use case in linux driver changes.
+ */
+static uintptr_t eemi_for_compatibility(uint32_t api_id, uint32_t *pm_arg,
+                                       void *handle, uint32_t security_flag)
+{
+       enum pm_ret_status ret;
+
+       switch (api_id) {
+
+       case PM_IOCTL:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+                                  pm_arg[3], pm_arg[4],
+                                  &value, security_flag);
+               if (ret == PM_RET_ERROR_NOTSUPPORTED)
+                       return (uintptr_t)0;
+
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_QUERY_DATA:
+       {
+               uint32_t data[PAYLOAD_ARG_CNT] = { 0 };
+
+               ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+                                   pm_arg[3], data, security_flag);
+
+               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)data[0] << 32U),
+                        (uint64_t)data[1] | ((uint64_t)data[2] << 32U));
+       }
+
+       case PM_FEATURE_CHECK:
+       {
+               uint32_t result[PAYLOAD_ARG_CNT] = {0U};
+
+               ret = pm_feature_check(pm_arg[0], result, security_flag);
+               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+                        (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
+       }
+
+       case PM_LOAD_PDI:
+       {
+               ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2],
+                                 security_flag);
+               SMC_RET1(handle, (uint64_t)ret);
+       }
+
+       default:
+               return (uintptr_t)0;
+       }
+}
+
+/**
+ * eemi_psci_debugfs_handler() - EEMI API invoked from PSCI
+ *
+ * These EEMI APIs performs CPU specific power management tasks.
+ * These EEMI APIs are invoked either from PSCI or from debugfs in kernel.
+ * These calls require CPU specific processing before sending IPI request to
+ * Platform Management Controller. For example enable/disable CPU specific
+ * interrupts. This requires separate handler for these calls and may not be
+ * handled using common eemi handler
+ */
+static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, uint32_t *pm_arg,
+                                          void *handle, uint32_t security_flag)
+{
+       enum pm_ret_status ret;
+
+       switch (api_id) {
+
+       case PM_SELF_SUSPEND:
+               ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+                                     pm_arg[3], security_flag);
+               SMC_RET1(handle, (u_register_t)ret);
+
+       case PM_FORCE_POWERDOWN:
+               ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag);
+               SMC_RET1(handle, (u_register_t)ret);
+
+       case PM_REQ_SUSPEND:
+               ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+                                    pm_arg[3], security_flag);
+               SMC_RET1(handle, (u_register_t)ret);
+
+       case PM_ABORT_SUSPEND:
+               ret = pm_abort_suspend(pm_arg[0], security_flag);
+               SMC_RET1(handle, (u_register_t)ret);
+
+       case PM_SYSTEM_SHUTDOWN:
+               ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag);
+               SMC_RET1(handle, (u_register_t)ret);
+
+       default:
+               return (uintptr_t)0;
+       }
+}
+
+/**
+ * TF_A_specific_handler() - SMC handler for TF-A specific functionality
+ *
+ * These EEMI calls performs functionality that does not require
+ * IPI transaction. The handler ends in TF-A and returns requested data to
+ * kernel from TF-A.
+ */
+static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
+                                      void *handle, uint32_t security_flag)
+{
+       switch (api_id) {
+
+       case TF_A_PM_REGISTER_SGI:
+       {
+               int32_t ret;
+
+               ret = pm_register_sgi(pm_arg[0], pm_arg[1]);
+               if (ret != 0) {
+                       SMC_RET1(handle, (uint32_t)PM_RET_ERROR_ARGS);
+               }
+
+               SMC_RET1(handle, (uint32_t)PM_RET_SUCCESS);
+       }
+
+       case PM_GET_CALLBACK_DATA:
+       {
+               uint32_t result[4] = {0};
+               enum pm_ret_status ret;
+
+               ret = pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
+               if (ret != 0) {
+                       result[0] = ret;
+               }
+
+               SMC_RET2(handle,
+                       (uint64_t)result[0] | ((uint64_t)result[1] << 32U),
+                       (uint64_t)result[2] | ((uint64_t)result[3] << 32U));
+       }
+
+       case PM_GET_TRUSTZONE_VERSION:
+               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+                        ((uint64_t)TZ_VERSION << 32U));
+
+       default:
+               return (uintptr_t)0;
+       }
+}
+
+/**
+ * eemi_handler() - Prepare EEMI payload and perform IPI transaction
+ *
+ * EEMI - Embedded Energy Management Interface is Xilinx proprietary protocol
+ * to allow communication between power management controller and different
+ * processing clusters.
+ *
+ * This handler prepares EEMI protocol payload received from kernel and performs
+ * IPI transaction.
+ */
+static uintptr_t eemi_handler(uint32_t api_id, uint32_t *pm_arg,
+                             void *handle, uint32_t security_flag)
+{
+       enum pm_ret_status ret;
+       uint32_t buf[PAYLOAD_ARG_CNT] = {0};
+
+       ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
+                                 pm_arg[2], pm_arg[3], pm_arg[4],
+                                 (uint64_t *)buf);
+       /*
+        * Two IOCTLs, to get clock name and pinctrl name of pm_query_data API
+        * receives 5 words of respoonse from firmware. Currently linux driver can
+        * receive only 4 words from TF-A. So, this needs to be handled separately
+        * than other eemi calls.
+        */
+       if (api_id == PM_QUERY_DATA) {
+               if ((pm_arg[0] == XPM_QID_CLOCK_GET_NAME ||
+                   pm_arg[0] == XPM_QID_PINCTRL_GET_FUNCTION_NAME) &&
+                   ret == PM_RET_SUCCESS) {
+                       SMC_RET2(handle, (uint64_t)buf[0] | ((uint64_t)buf[1] << 32U),
+                               (uint64_t)buf[2] | ((uint64_t)buf[3] << 32U));
+               }
+       }
+
+       SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
+                (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U));
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - SMC64 Arguments from kernel
+ *           x3 (upper 32-bits) and x4 are Unused
+ * @cookie  - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return  - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+                       uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+       uintptr_t ret;
+       uint32_t pm_arg[PAYLOAD_ARG_CNT] = {0};
+       uint32_t security_flag = SECURE_FLAG;
+       uint32_t api_id;
+
+       /* Handle case where PM wasn't initialized properly */
+       if (pm_up == false) {
+               SMC_RET1(handle, SMC_UNK);
+       }
+
+       /*
+        * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
+        * if smc called is non secure
+        */
+       if (is_caller_non_secure(flags) != 0) {
+               security_flag = NON_SECURE_FLAG;
+       }
+
+       pm_arg[0] = (uint32_t)x1;
+       pm_arg[1] = (uint32_t)(x1 >> 32U);
+       pm_arg[2] = (uint32_t)x2;
+       pm_arg[3] = (uint32_t)(x2 >> 32U);
+       pm_arg[4] = (uint32_t)x3;
+       (void)(x4);
+       api_id = smc_fid & FUNCID_NUM_MASK;
+
+       ret = eemi_for_compatibility(api_id, pm_arg, handle, security_flag);
+       if (ret != (uintptr_t)0) {
+               return ret;
+       }
+
+       ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle, flags);
+       if (ret !=  (uintptr_t)0) {
+               return ret;
+       }
+
+       ret = TF_A_specific_handler(api_id, pm_arg, handle, security_flag);
+       if (ret !=  (uintptr_t)0) {
+               return ret;
+       }
+
+       ret = eemi_handler(api_id, pm_arg, handle, security_flag);
+
+       return ret;
+}
index 8087297a22c94df808beead2c3560c53d15ccb0e..71f680261bc394e3aa36cbb03940591cfd6633b5 100644 (file)
@@ -1,4 +1,5 @@
 # Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 
@@ -82,6 +83,8 @@ BL31_SOURCES          +=      drivers/arm/cci/cci.c                           \
                                plat/xilinx/common/plat_startup.c               \
                                plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c \
                                plat/xilinx/common/pm_service/pm_ipi.c          \
+                               plat/xilinx/common/pm_service/pm_api_sys.c      \
+                               plat/xilinx/common/pm_service/pm_svc_main.c     \
                                plat/xilinx/versal/bl31_versal_setup.c          \
                                plat/xilinx/versal/plat_psci.c                  \
                                plat/xilinx/versal/plat_versal.c                \
@@ -89,8 +92,6 @@ BL31_SOURCES          +=      drivers/arm/cci/cci.c                           \
                                plat/xilinx/versal/sip_svc_setup.c              \
                                plat/xilinx/versal/versal_gicv3.c               \
                                plat/xilinx/versal/versal_ipi.c                 \
-                               plat/xilinx/versal/pm_service/pm_svc_main.c     \
-                               plat/xilinx/versal/pm_service/pm_api_sys.c      \
                                plat/xilinx/versal/pm_service/pm_client.c
 
 ifeq ($(HARDEN_SLS_ALL), 1)
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c
deleted file mode 100644 (file)
index cc99f11..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * Versal system level PM-API functions and communication with PMC via
- * IPI interrupts
- */
-
-#include <pm_common.h>
-#include <pm_ipi.h>
-#include <plat/common/platform.h>
-#include "pm_api_sys.h"
-#include "pm_client.h"
-#include "pm_defs.h"
-#include "pm_svc_main.h"
-
-/* default shutdown/reboot scope is system(2) */
-static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
-
-/**
- * pm_get_shutdown_scope() - Get the currently set shutdown scope
- *
- * @return     Shutdown scope value
- */
-uint32_t pm_get_shutdown_scope(void)
-{
-       return pm_shutdown_scope;
-}
-
-/* PM API functions */
-
-/**
- * pm_handle_eemi_call() - PM call for processor to send eemi payload
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- * @x0 to x5   Arguments received per SMC64 standard
- * @result     Payload received from firmware
- *
- * @return      PM_RET_SUCCESS on success or error code
- */
-enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
-                                      uint32_t x2, uint32_t x3, uint32_t x4,
-                                      uint32_t x5, uint64_t *result)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT] = {0};
-       uint32_t module_id;
-
-       module_id = (x0 & MODULE_ID_MASK) >> 8U;
-
-       //default module id is for LIBPM
-       if (module_id == 0) {
-               module_id = LIBPM_MODULE_ID;
-       }
-
-       PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
-       return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
-}
-
-/**
- * pm_self_suspend() - PM call for processor to suspend itself
- * @nid                Node id of the processor or subsystem
- * @latency    Requested maximum wakeup latency (not supported)
- * @state      Requested state
- * @address    Resume address
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * This is a blocking call, it will return only once PMU has responded.
- * On a wakeup, resume address will be automatically set by PMU.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_self_suspend(uint32_t nid,
-                                  uint32_t latency,
-                                  uint32_t state,
-                                  uintptr_t address, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint32_t cpuid = plat_my_core_pos();
-       const struct pm_proc *proc = pm_get_proc(cpuid);
-
-       if (proc == NULL) {
-               WARN("Failed to get proc %d\n", cpuid);
-               return PM_RET_ERROR_INTERNAL;
-       }
-
-       /*
-        * Do client specific suspend operations
-        * (e.g. set powerdown request bit)
-        */
-       pm_client_suspend(proc, state);
-
-       /* Send request to the PLM */
-       PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND,
-                        proc->node_id, latency, state, address,
-                        (address >> 32));
-       return pm_ipi_send_sync(proc, payload, NULL, 0);
-}
-
-/**
- * pm_abort_suspend() - PM call to announce that a prior suspend request
- *                     is to be aborted.
- * @reason     Reason for the abort
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * Calling PU expects the PMU to abort the initiated suspend procedure.
- * This is a non-blocking call without any acknowledge.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /*
-        * Do client specific abort suspend operations
-        * (e.g. enable interrupts and clear powerdown request bit)
-        */
-       pm_client_abort_suspend();
-
-       /* Send request to the PLM */
-       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND,
-                        reason, primary_proc->node_id);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_req_suspend() - PM call to request for another PU or subsystem to
- *                   be suspended gracefully.
- * @target     Node id of the targeted PU or subsystem
- * @ack                Flag to specify whether acknowledge is requested
- * @latency    Requested wakeup latency (not supported)
- * @state      Requested state (not supported)
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
-                                 uint32_t latency, uint32_t state,
-                                 uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
-                        latency, state);
-       if (ack == IPI_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_req_wakeup() - PM call for processor to wake up selected processor
- *                  or subsystem
- * @target     Device ID of the processor or subsystem to wake up
- * @set_address        Resume address presence indicator
- *             1 - resume address specified, 0 - otherwise
- * @address    Resume address
- * @ack                Flag to specify whether acknowledge requested
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * This API function is either used to power up another APU core for SMP
- * (by PSCI) or to power up an entirely different PU or subsystem, such
- * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
- * automatically set by PMC.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
-                                uintptr_t address, uint8_t ack, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC to perform the wake of the PU */
-       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target,
-                        set_address, address, ack);
-
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_get_callbackdata() - Read from IPI response buffer
- * @data - array of PAYLOAD_ARG_CNT elements
- * @flag - 0 - Call from secure source
- *        1 - Call from non-secure source
- * @ack - 0 - Do not ack IPI after reading payload
- *        1 - Ack IPI after reading payload
- *
- * Read value from ipi buffer response buffer.
- * @return     Returns status, either success or error
- */
-enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
-{
-       enum pm_ret_status ret = PM_RET_SUCCESS;
-       /* Return if interrupt is not from PMU */
-       if (pm_ipi_irq_status(primary_proc) == 0) {
-               return ret;
-       }
-
-       ret = pm_ipi_buff_read_callb(data, count);
-
-       if (ack != 0U) {
-               pm_ipi_irq_clear(primary_proc);
-       }
-
-       return ret;
-}
-
-/**
- * pm_pll_set_param() - Set PLL parameter
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @clk_id     PLL clock ID
- * @param      PLL parameter ID
- * @value      Value to set for PLL parameter
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
-                                   uint32_t value, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER,
-                        clk_id, param, value);
-
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_pll_get_param() - Get PLL parameter value
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @clk_id     PLL clock ID
- * @param      PLL parameter ID
- * @value:     Buffer to store PLL parameter value
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
-                                   uint32_t *value, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER,
-                        clk_id, param);
-
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/**
- * pm_pll_set_mode() - Set PLL mode
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @clk_id     PLL clock ID
- * @mode       PLL mode
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
-                                  uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE,
-                        clk_id, mode);
-
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_pll_get_mode() - Get PLL mode
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @clk_id     PLL clock ID
- * @mode:      Buffer to store PLL mode
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
-                                  uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE,
-                        clk_id);
-
-       return pm_ipi_send_sync(primary_proc, payload, mode, 1);
-}
-
-/**
- * pm_force_powerdown() - PM call to request for another PU or subsystem to
- *                       be powered down forcefully
- * @target     Device ID of the PU node to be forced powered down.
- * @ack                Flag to specify whether acknowledge is requested
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
-                                     uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
-                        target, ack);
-
-       if (ack == IPI_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_system_shutdown() - PM call to request a system shutdown or restart
- * @type       Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
- * @subtype    Scope: 0=APU-subsystem, 1=PS, 2=system
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
-                                     uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
-               /* Setting scope for subsequent PSCI reboot or shutdown */
-               pm_shutdown_scope = subtype;
-               return PM_RET_SUCCESS;
-       }
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN,
-                        type, subtype);
-
-       return pm_ipi_send_non_blocking(primary_proc, payload);
-}
-
-/**
- * pm_query_data() -  PM API for querying firmware data
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @qid        The type of data to query
- * @arg1       Argument 1 to requested query data call
- * @arg2       Argument 2 to requested query data call
- * @arg3       Argument 3 to requested query data call
- * @data       Returned output data
- * @flag 0 - Call from secure source
- *     1 - Call from non-secure source
- *
- * @retur - 0 if success else non-zero error code of type
- * enum pm_ret_status
- */
-enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
-                                uint32_t arg3, uint32_t *data, uint32_t flag)
-{
-       uint32_t ret;
-       uint32_t version[PAYLOAD_ARG_CNT] = {0};
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint32_t fw_api_version;
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid,
-                        arg1, arg2, arg3);
-
-       ret = pm_feature_check(PM_QUERY_DATA, &version[0], flag);
-       if (ret == PM_RET_SUCCESS) {
-               fw_api_version = version[0] & 0xFFFFU;
-               if ((fw_api_version == 2U) &&
-                   ((qid == XPM_QID_CLOCK_GET_NAME) ||
-                    (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) {
-                       ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
-                       if (ret == PM_RET_SUCCESS) {
-                               ret = data[0];
-                               data[0] = data[1];
-                               data[1] = data[2];
-                               data[2] = data[3];
-                       }
-               } else {
-                       ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
-               }
-       }
-       return ret;
-}
-/**
- * pm_api_ioctl() -  PM IOCTL API for device control and configs
- *
- * This API is deprecated and maintained here for backward compatibility.
- * New use of this API should be avoided for versal platform.
- * This API and its use cases will be removed for versal platform.
- *
- * @device_id  Device ID
- * @ioctl_id   ID of the requested IOCTL
- * @arg1       Argument 1 to requested IOCTL call
- * @arg2       Argument 2 to requested IOCTL call
- * @arg3       Argument 3 to requested IOCTL call
- * @value      Returned output value
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * This function calls IOCTL to firmware for device control and configuration.
- *
- * @return     Returns status, either 0 on success or non-zero error code
- * of type enum pm_ret_status
- */
-enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
-                               uint32_t arg1, uint32_t arg2, uint32_t arg3,
-                               uint32_t *value, uint32_t flag)
-{
-       enum pm_ret_status ret;
-
-       switch (ioctl_id) {
-       case IOCTL_SET_PLL_FRAC_MODE:
-               ret =  pm_pll_set_mode(arg1, arg2, flag);
-               break;
-       case IOCTL_GET_PLL_FRAC_MODE:
-               ret =  pm_pll_get_mode(arg1, value, flag);
-               break;
-       case IOCTL_SET_PLL_FRAC_DATA:
-               ret =  pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2, flag);
-               break;
-       case IOCTL_GET_PLL_FRAC_DATA:
-               ret =  pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value, flag);
-               break;
-       case IOCTL_SET_SGI:
-               /* Get the sgi number */
-               ret = pm_register_sgi(arg1, arg2);
-               if (ret != 0) {
-                       return PM_RET_ERROR_ARGS;
-               }
-               ret = PM_RET_SUCCESS;
-               break;
-       default:
-               return PM_RET_ERROR_NOTSUPPORTED;
-       }
-
-       return ret;
-}
-
-/**
- * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
- * @target     Device id of the targeted PU or subsystem
- * @wkup_node  Device id of the wakeup peripheral
- * @enable     Enable or disable the specified peripheral as wake source
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
-                                       uint8_t enable, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE,
-                        target, wkup_device, enable);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_feature_check() - Returns the supported API version if supported
- * @api_id     API ID to check
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- * @ret_payload pointer to array of PAYLOAD_ARG_CNT number of
- *             words Returned supported API version and bitmasks
- *             for IOCTL and QUERY ID
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
-                                   uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint32_t module_id;
-
-       /* Return version of API which are implemented in ATF only */
-       switch (api_id) {
-       case PM_GET_CALLBACK_DATA:
-       case PM_GET_TRUSTZONE_VERSION:
-               ret_payload[0] = PM_API_VERSION_2;
-               return PM_RET_SUCCESS;
-       case TF_A_PM_REGISTER_SGI:
-               ret_payload[0] = PM_API_BASE_VERSION;
-               return PM_RET_SUCCESS;
-       default:
-               break;
-       }
-
-       module_id = (api_id & MODULE_ID_MASK) >> 8U;
-
-       /*
-        * feature check should be done only for LIBPM module
-        * If module_id is 0, then we consider it LIBPM module as default id
-        */
-       if ((module_id > 0) && (module_id != LIBPM_MODULE_ID)) {
-               return PM_RET_SUCCESS;
-       }
-
-       PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
-                        PM_FEATURE_CHECK, api_id);
-       return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
-}
-
-/**
- * pm_load_pdi() - Load the PDI
- *
- * This function provides support to load PDI from linux
- *
- * src:        Source device of pdi(DDR, OCM, SD etc)
- * address_low: lower 32-bit Linear memory space address
- * address_high: higher 32-bit Linear memory space address
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return      Returns status, either success or error+reason
- */
-enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
-                              uint32_t address_high, uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src,
-                        address_high, address_low);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_register_notifier() - PM call to register a subsystem to be notified
- *                         about the device event
- * @device_id  Device ID for the Node to which the event is related
- * @event      Event in question
- * @wake       Wake subsystem upon capturing the event if value 1
- * @enable     Enable the registration for value 1, disable for value 0
- * @flag       0 - Call from secure source
- *             1 - Call from non-secure source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
-                                       uint32_t wake, uint32_t enable,
-                                       uint32_t flag)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMC */
-       PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER,
-                        device_id, event, wake, enable);
-
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h
deleted file mode 100644 (file)
index 8625e95..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PM_API_SYS_H
-#define PM_API_SYS_H
-
-#include <stdint.h>
-#include "pm_defs.h"
-
-/*********************************************************************
- * Target module IDs macros
- ********************************************************************/
-#define LIBPM_MODULE_ID                0x2U
-#define LOADER_MODULE_ID       0x7U
-
-#define MODULE_ID_MASK         0x0000ff00U
-/**********************************************************
- * PM API function declarations
- **********************************************************/
-
-enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
-                                      uint32_t x2, uint32_t x3, uint32_t x4,
-                                      uint32_t x5, uint64_t *result);
-enum pm_ret_status pm_self_suspend(uint32_t nid,
-                                  uint32_t latency,
-                                  uint32_t state,
-                                  uintptr_t address, uint32_t flag);
-enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag);
-enum pm_ret_status pm_req_suspend(uint32_t target,
-                                 uint8_t ack,
-                                 uint32_t latency,
-                                 uint32_t state, uint32_t flag);
-enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
-                                uintptr_t address, uint8_t ack, uint32_t flag);
-enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t device_id,
-                                       uint8_t enable, uint32_t flag);
-enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag,
-                        uint32_t ack);
-enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
-                                   uint32_t value, uint32_t flag);
-enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
-                                   uint32_t *value, uint32_t flag);
-enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
-                                  uint32_t flag);
-enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
-                                  uint32_t flag);
-enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
-                                     uint32_t flag);
-enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
-                                     uint32_t flag);
-enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
-                               uint32_t arg1, uint32_t arg2, uint32_t arg3,
-                               uint32_t *value, uint32_t flag);
-enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
-                                uint32_t arg3, uint32_t *data, uint32_t flag);
-uint32_t pm_get_shutdown_scope(void);
-enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
-                                   uint32_t flag);
-enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
-                              uint32_t address_high, uint32_t flag);
-enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
-                                       uint32_t wake, uint32_t enable,
-                                       uint32_t flag);
-
-/**
- * Assigning of argument values into array elements.
- */
-#define PM_PACK_PAYLOAD1(pl, mid, flag, arg0) {        \
-       pl[0] = (uint32_t)(((uint32_t)(arg0) & 0xFFU) | ((mid) << 8U) | ((flag) << 24U)); \
-}
-
-#define PM_PACK_PAYLOAD2(pl, mid, flag, arg0, arg1) {          \
-       pl[1] = (uint32_t)(arg1);                               \
-       PM_PACK_PAYLOAD1(pl, (mid), (flag), (arg0));                    \
-}
-
-#define PM_PACK_PAYLOAD3(pl, mid, flag, arg0, arg1, arg2) {    \
-       pl[2] = (uint32_t)(arg2);                               \
-       PM_PACK_PAYLOAD2(pl, (mid), (flag), (arg0), (arg1));            \
-}
-
-#define PM_PACK_PAYLOAD4(pl, mid, flag, arg0, arg1, arg2, arg3) {      \
-       pl[3] = (uint32_t)(arg3);                                       \
-       PM_PACK_PAYLOAD3(pl, (mid), (flag), (arg0), (arg1), (arg2));            \
-}
-
-#define PM_PACK_PAYLOAD5(pl, mid, flag, arg0, arg1, arg2, arg3, arg4) {        \
-       pl[4] = (uint32_t)(arg4);                                       \
-       PM_PACK_PAYLOAD4(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3));    \
-}
-
-#define PM_PACK_PAYLOAD6(pl, mid, flag, arg0, arg1, arg2, arg3, arg4, arg5) {  \
-       pl[5] = (uint32_t)(arg5);                                               \
-       PM_PACK_PAYLOAD5(pl, (mid), (flag), (arg0), (arg1), (arg2), (arg3), (arg4));            \
-}
-
-#endif /* PM_API_SYS_H */
diff --git a/plat/xilinx/versal/pm_service/pm_node.h b/plat/xilinx/versal/pm_service/pm_node.h
deleted file mode 100644 (file)
index 1b82ec7..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2019, Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/* Versal PM nodes enums and defines */
-
-#ifndef PM_NODE_H
-#define PM_NODE_H
-
-/*********************************************************************
- * Macro definitions
- ********************************************************************/
-
-#define NODE_CLASS_SHIFT       26U
-#define NODE_SUBCLASS_SHIFT    20U
-#define NODE_TYPE_SHIFT                14U
-#define NODE_INDEX_SHIFT       0U
-#define NODE_CLASS_MASK_BITS    0x3F
-#define NODE_SUBCLASS_MASK_BITS 0x3F
-#define NODE_TYPE_MASK_BITS     0x3F
-#define NODE_INDEX_MASK_BITS    0x3FFF
-#define NODE_CLASS_MASK         (NODE_CLASS_MASK_BITS << NODE_CLASS_SHIFT)
-#define NODE_SUBCLASS_MASK      (NODE_SUBCLASS_MASK_BITS << NODE_SUBCLASS_SHIFT)
-#define NODE_TYPE_MASK          (NODE_TYPE_MASK_BITS << NODE_TYPE_SHIFT)
-#define NODE_INDEX_MASK         (NODE_INDEX_MASK_BITS << NODE_INDEX_SHIFT)
-
-#define NODEID(CLASS, SUBCLASS, TYPE, INDEX)   \
-            ((((CLASS) & NODE_CLASS_MASK_BITS) << NODE_CLASS_SHIFT) | \
-            (((SUBCLASS) & NODE_SUBCLASS_MASK_BITS) << NODE_SUBCLASS_SHIFT) | \
-            (((TYPE) & NODE_TYPE_MASK_BITS) << NODE_TYPE_SHIFT) | \
-            (((INDEX) & NODE_INDEX_MASK_BITS) << NODE_INDEX_SHIFT))
-
-#define NODECLASS(ID)          (((ID) & NODE_CLASS_MASK) >> NODE_CLASS_SHIFT)
-#define NODESUBCLASS(ID)       (((ID) & NODE_SUBCLASS_MASK) >> \
-                               NODE_SUBCLASS_SHIFT)
-#define NODETYPE(ID)           (((ID) & NODE_TYPE_MASK) >> NODE_TYPE_SHIFT)
-#define NODEINDEX(ID)          (((ID) & NODE_INDEX_MASK) >> NODE_INDEX_SHIFT)
-
-/*********************************************************************
- * Enum definitions
- ********************************************************************/
-
-/* Node class types */
-enum pm_node_class {
-       XPM_NODECLASS_MIN,
-
-       XPM_NODECLASS_POWER,
-       XPM_NODECLASS_CLOCK,
-       XPM_NODECLASS_RESET,
-       XPM_NODECLASS_MEMIC,
-       XPM_NODECLASS_STMIC,
-       XPM_NODECLASS_DEVICE,
-
-       XPM_NODECLASS_MAX
-};
-
-enum pm_device_node_subclass {
-       /* Device types */
-       XPM_NODESUBCL_DEV_CORE = 1,
-       XPM_NODESUBCL_DEV_PERIPH,
-       XPM_NODESUBCL_DEV_MEM,
-       XPM_NODESUBCL_DEV_SOC,
-       XPM_NODESUBCL_DEV_MEM_CTRLR,
-       XPM_NODESUBCL_DEV_PHY,
-};
-
-enum pm_device_node_type {
-       /* Device types */
-       XPM_NODETYPE_DEV_CORE_PMC = 1,
-       XPM_NODETYPE_DEV_CORE_PSM,
-       XPM_NODETYPE_DEV_CORE_APU,
-       XPM_NODETYPE_DEV_CORE_RPU,
-       XPM_NODETYPE_DEV_OCM,
-       XPM_NODETYPE_DEV_TCM,
-       XPM_NODETYPE_DEV_L2CACHE,
-       XPM_NODETYPE_DEV_DDR,
-       XPM_NODETYPE_DEV_PERIPH,
-       XPM_NODETYPE_DEV_SOC,
-       XPM_NODETYPE_DEV_GT,
-};
-
-/* Device node Indexes */
-enum pm_device_node_idx {
-       /* Device nodes */
-       XPM_NODEIDX_DEV_MIN,
-
-       /* Processor devices */
-       XPM_NODEIDX_DEV_PMC_PROC,
-       XPM_NODEIDX_DEV_PSM_PROC,
-       XPM_NODEIDX_DEV_ACPU_0,
-       XPM_NODEIDX_DEV_ACPU_1,
-       XPM_NODEIDX_DEV_RPU0_0,
-       XPM_NODEIDX_DEV_RPU0_1,
-
-       /* Memory devices */
-       XPM_NODEIDX_DEV_OCM_0,
-       XPM_NODEIDX_DEV_OCM_1,
-       XPM_NODEIDX_DEV_OCM_2,
-       XPM_NODEIDX_DEV_OCM_3,
-       XPM_NODEIDX_DEV_TCM_0_A,
-       XPM_NODEIDX_DEV_TCM_0_B,
-       XPM_NODEIDX_DEV_TCM_1_A,
-       XPM_NODEIDX_DEV_TCM_1_B,
-       XPM_NODEIDX_DEV_L2_BANK_0,
-       XPM_NODEIDX_DEV_DDR_0,
-       XPM_NODEIDX_DEV_DDR_1,
-       XPM_NODEIDX_DEV_DDR_2,
-       XPM_NODEIDX_DEV_DDR_3,
-       XPM_NODEIDX_DEV_DDR_4,
-       XPM_NODEIDX_DEV_DDR_5,
-       XPM_NODEIDX_DEV_DDR_6,
-       XPM_NODEIDX_DEV_DDR_7,
-
-       /* LPD Peripheral devices */
-       XPM_NODEIDX_DEV_USB_0,
-       XPM_NODEIDX_DEV_GEM_0,
-       XPM_NODEIDX_DEV_GEM_1,
-       XPM_NODEIDX_DEV_SPI_0,
-       XPM_NODEIDX_DEV_SPI_1,
-       XPM_NODEIDX_DEV_I2C_0,
-       XPM_NODEIDX_DEV_I2C_1,
-       XPM_NODEIDX_DEV_CAN_FD_0,
-       XPM_NODEIDX_DEV_CAN_FD_1,
-       XPM_NODEIDX_DEV_UART_0,
-       XPM_NODEIDX_DEV_UART_1,
-       XPM_NODEIDX_DEV_GPIO,
-       XPM_NODEIDX_DEV_TTC_0,
-       XPM_NODEIDX_DEV_TTC_1,
-       XPM_NODEIDX_DEV_TTC_2,
-       XPM_NODEIDX_DEV_TTC_3,
-       XPM_NODEIDX_DEV_SWDT_LPD,
-
-       /* FPD Peripheral devices */
-       XPM_NODEIDX_DEV_SWDT_FPD,
-
-       /* PMC Peripheral devices */
-       XPM_NODEIDX_DEV_OSPI,
-       XPM_NODEIDX_DEV_QSPI,
-       XPM_NODEIDX_DEV_GPIO_PMC,
-       XPM_NODEIDX_DEV_I2C_PMC,
-       XPM_NODEIDX_DEV_SDIO_0,
-       XPM_NODEIDX_DEV_SDIO_1,
-
-       XPM_NODEIDX_DEV_PL_0,
-       XPM_NODEIDX_DEV_PL_1,
-       XPM_NODEIDX_DEV_PL_2,
-       XPM_NODEIDX_DEV_PL_3,
-       XPM_NODEIDX_DEV_RTC,
-       XPM_NODEIDX_DEV_ADMA_0,
-       XPM_NODEIDX_DEV_ADMA_1,
-       XPM_NODEIDX_DEV_ADMA_2,
-       XPM_NODEIDX_DEV_ADMA_3,
-       XPM_NODEIDX_DEV_ADMA_4,
-       XPM_NODEIDX_DEV_ADMA_5,
-       XPM_NODEIDX_DEV_ADMA_6,
-       XPM_NODEIDX_DEV_ADMA_7,
-       XPM_NODEIDX_DEV_IPI_0,
-       XPM_NODEIDX_DEV_IPI_1,
-       XPM_NODEIDX_DEV_IPI_2,
-       XPM_NODEIDX_DEV_IPI_3,
-       XPM_NODEIDX_DEV_IPI_4,
-       XPM_NODEIDX_DEV_IPI_5,
-       XPM_NODEIDX_DEV_IPI_6,
-
-       /* Entire SoC */
-       XPM_NODEIDX_DEV_SOC,
-
-       /* DDR memory controllers */
-       XPM_NODEIDX_DEV_DDRMC_0,
-       XPM_NODEIDX_DEV_DDRMC_1,
-       XPM_NODEIDX_DEV_DDRMC_2,
-       XPM_NODEIDX_DEV_DDRMC_3,
-
-       /* GT devices */
-       XPM_NODEIDX_DEV_GT_0,
-       XPM_NODEIDX_DEV_GT_1,
-       XPM_NODEIDX_DEV_GT_2,
-       XPM_NODEIDX_DEV_GT_3,
-       XPM_NODEIDX_DEV_GT_4,
-       XPM_NODEIDX_DEV_GT_5,
-       XPM_NODEIDX_DEV_GT_6,
-       XPM_NODEIDX_DEV_GT_7,
-       XPM_NODEIDX_DEV_GT_8,
-       XPM_NODEIDX_DEV_GT_9,
-       XPM_NODEIDX_DEV_GT_10,
-
-       XPM_NODEIDX_DEV_MAX
-};
-
-#endif /* PM_NODE_H */
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c
deleted file mode 100644 (file)
index 185bfdb..0000000
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- * Copyright (c) 2022, Advanced Micro Devices, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * Top-level SMC handler for Versal power management calls and
- * IPI setup functions for communication with PMC.
- */
-
-#include <errno.h>
-#include <plat_private.h>
-#include <stdbool.h>
-#include <common/runtime_svc.h>
-#include <plat/common/platform.h>
-#include "pm_api_sys.h"
-#include "pm_client.h"
-#include "pm_ipi.h"
-#include <drivers/arm/gicv3.h>
-#include "../drivers/arm/gic/v3/gicv3_private.h"
-
-#define MODE                           0x80000000U
-
-#define XSCUGIC_SGIR_EL1_INITID_SHIFT    24U
-#define INVALID_SGI    0xFFU
-#define PM_INIT_SUSPEND_CB     (30U)
-#define PM_NOTIFY_CB           (32U)
-DEFINE_RENAME_SYSREG_RW_FUNCS(icc_asgi1r_el1, S3_0_C12_C11_6)
-
-/* pm_up = true - UP, pm_up = false - DOWN */
-static bool pm_up;
-static uint32_t sgi = (uint32_t)INVALID_SGI;
-
-static void notify_os(void)
-{
-       int32_t cpu;
-       uint32_t reg;
-
-       cpu = plat_my_core_pos() + 1U;
-
-       reg = (cpu | (sgi << XSCUGIC_SGIR_EL1_INITID_SHIFT));
-       write_icc_asgi1r_el1(reg);
-}
-
-static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle,
-                               void *cookie)
-{
-       uint32_t payload[4] = {0};
-       enum pm_ret_status ret;
-
-       VERBOSE("Received IPI FIQ from firmware\n");
-
-       (void)plat_ic_acknowledge_interrupt();
-
-       ret = pm_get_callbackdata(payload, ARRAY_SIZE(payload), 0, 0);
-       if (ret != PM_RET_SUCCESS) {
-               payload[0] = ret;
-       }
-
-       switch (payload[0]) {
-       case PM_INIT_SUSPEND_CB:
-       case PM_NOTIFY_CB:
-               if (sgi != INVALID_SGI) {
-                       notify_os();
-               }
-               break;
-       case PM_RET_ERROR_INVALID_CRC:
-               pm_ipi_irq_clear(primary_proc);
-               WARN("Invalid CRC in the payload\n");
-               break;
-
-       default:
-               pm_ipi_irq_clear(primary_proc);
-               WARN("Invalid IPI payload\n");
-               break;
-       }
-
-       /* Clear FIQ */
-       plat_ic_end_of_interrupt(id);
-
-       return 0;
-}
-
-/**
- * pm_register_sgi() - PM register the IPI interrupt
- *
- * @sgi -  SGI number to be used for communication.
- * @reset -  Reset to invalid SGI when reset=1.
- * @return     On success, the initialization function must return 0.
- *             Any other return value will cause the framework to ignore
- *             the service
- *
- * Update the SGI number to be used.
- *
- */
-int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset)
-{
-       if (reset == 1U) {
-               sgi = INVALID_SGI;
-               return 0;
-       }
-
-       if (sgi != INVALID_SGI) {
-               return -EBUSY;
-       }
-
-       if (sgi_num >= GICV3_MAX_SGI_TARGETS) {
-               return -EINVAL;
-       }
-
-       sgi = (uint32_t)sgi_num;
-       return 0;
-}
-
-/**
- * pm_setup() - PM service setup
- *
- * @return     On success, the initialization function must return 0.
- *             Any other return value will cause the framework to ignore
- *             the service
- *
- * Initialization functions for Versal power management for
- * communicaton with PMC.
- *
- * Called from sip_svc_setup initialization function with the
- * rt_svc_init signature.
- */
-int32_t pm_setup(void)
-{
-       int32_t ret = 0;
-
-       pm_ipi_init(primary_proc);
-       pm_up = true;
-
-       /*
-        * Enable IPI IRQ
-        * assume the rich OS is OK to handle callback IRQs now.
-        * Even if we were wrong, it would not enable the IRQ in
-        * the GIC.
-        */
-       pm_ipi_irq_enable(primary_proc);
-
-       ret = request_intr_type_el3(PLAT_VERSAL_IPI_IRQ, ipi_fiq_handler);
-       if (ret != 0) {
-               WARN("BL31: registering IPI interrupt failed\n");
-       }
-
-       gicd_write_irouter(gicv3_driver_data->gicd_base, PLAT_VERSAL_IPI_IRQ, MODE);
-       return ret;
-}
-
-/**
- * eemi_for_compatibility() - EEMI calls handler for deprecated calls
- *
- * @return - If EEMI API found then, uintptr_t type address, else 0
- *
- * Some EEMI API's use case needs to be changed in Linux driver, so they
- * can take advantage of common EEMI handler in TF-A. As of now the old
- * implementation of these APIs are required to maintain backward compatibility
- * until their use case in linux driver changes.
- */
-static uintptr_t eemi_for_compatibility(uint32_t api_id, uint32_t *pm_arg,
-                                       void *handle, uint32_t security_flag)
-{
-       enum pm_ret_status ret;
-
-       switch (api_id) {
-
-       case PM_IOCTL:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
-                                  pm_arg[3], pm_arg[4],
-                                  &value, security_flag);
-               if (ret == PM_RET_ERROR_NOTSUPPORTED)
-                       return (uintptr_t)0;
-
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_QUERY_DATA:
-       {
-               uint32_t data[PAYLOAD_ARG_CNT] = { 0 };
-
-               ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
-                                   pm_arg[3], data, security_flag);
-
-               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)data[0] << 32U),
-                        (uint64_t)data[1] | ((uint64_t)data[2] << 32U));
-       }
-
-       case PM_FEATURE_CHECK:
-       {
-               uint32_t result[PAYLOAD_ARG_CNT] = {0U};
-
-               ret = pm_feature_check(pm_arg[0], result, security_flag);
-               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
-                        (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
-       }
-
-       case PM_LOAD_PDI:
-       {
-               ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2],
-                                 security_flag);
-               SMC_RET1(handle, (uint64_t)ret);
-       }
-
-       default:
-               return (uintptr_t)0;
-       }
-}
-
-/**
- * eemi_psci_debugfs_handler() - EEMI API invoked from PSCI
- *
- * These EEMI APIs performs CPU specific power management tasks.
- * These EEMI APIs are invoked either from PSCI or from debugfs in kernel.
- * These calls require CPU specific processing before sending IPI request to
- * Platform Management Controller. For example enable/disable CPU specific
- * interrupts. This requires separate handler for these calls and may not be
- * handled using common eemi handler
- */
-static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, uint32_t *pm_arg,
-                                          void *handle, uint32_t security_flag)
-{
-       enum pm_ret_status ret;
-
-       switch (api_id) {
-
-       case PM_SELF_SUSPEND:
-               ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
-                                     pm_arg[3], security_flag);
-               SMC_RET1(handle, (u_register_t)ret);
-
-       case PM_FORCE_POWERDOWN:
-               ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag);
-               SMC_RET1(handle, (u_register_t)ret);
-
-       case PM_REQ_SUSPEND:
-               ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
-                                    pm_arg[3], security_flag);
-               SMC_RET1(handle, (u_register_t)ret);
-
-       case PM_ABORT_SUSPEND:
-               ret = pm_abort_suspend(pm_arg[0], security_flag);
-               SMC_RET1(handle, (u_register_t)ret);
-
-       case PM_SYSTEM_SHUTDOWN:
-               ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag);
-               SMC_RET1(handle, (u_register_t)ret);
-
-       default:
-               return (uintptr_t)0;
-       }
-}
-
-/**
- * TF_A_specific_handler() - SMC handler for TF-A specific functionality
- *
- * These EEMI calls performs functionality that does not require
- * IPI transaction. The handler ends in TF-A and returns requested data to
- * kernel from TF-A.
- */
-static uintptr_t TF_A_specific_handler(uint32_t api_id, uint32_t *pm_arg,
-                                      void *handle, uint32_t security_flag)
-{
-       switch (api_id) {
-
-       case TF_A_PM_REGISTER_SGI:
-       {
-               int32_t ret;
-
-               ret = pm_register_sgi(pm_arg[0], pm_arg[1]);
-               if (ret != 0) {
-                       SMC_RET1(handle, (uint32_t)PM_RET_ERROR_ARGS);
-               }
-
-               SMC_RET1(handle, (uint32_t)PM_RET_SUCCESS);
-       }
-
-       case PM_GET_CALLBACK_DATA:
-       {
-               uint32_t result[4] = {0};
-               enum pm_ret_status ret;
-
-               ret = pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag, 1U);
-               if (ret != 0) {
-                       result[0] = ret;
-               }
-
-               SMC_RET2(handle,
-                       (uint64_t)result[0] | ((uint64_t)result[1] << 32U),
-                       (uint64_t)result[2] | ((uint64_t)result[3] << 32U));
-       }
-
-       case PM_GET_TRUSTZONE_VERSION:
-               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
-                        ((uint64_t)TZ_VERSION << 32U));
-
-       default:
-               return (uintptr_t)0;
-       }
-}
-
-/**
- * eemi_handler() - Prepare EEMI payload and perform IPI transaction
- *
- * EEMI - Embedded Energy Management Interface is Xilinx proprietary protocol
- * to allow communication between power management controller and different
- * processing clusters.
- *
- * This handler prepares EEMI protocol payload received from kernel and performs
- * IPI transaction.
- */
-static uintptr_t eemi_handler(uint32_t api_id, uint32_t *pm_arg,
-                             void *handle, uint32_t security_flag)
-{
-       enum pm_ret_status ret;
-       uint32_t buf[PAYLOAD_ARG_CNT] = {0};
-
-       ret = pm_handle_eemi_call(security_flag, api_id, pm_arg[0], pm_arg[1],
-                                 pm_arg[2], pm_arg[3], pm_arg[4],
-                                 (uint64_t *)buf);
-       /*
-        * Two IOCTLs, to get clock name and pinctrl name of pm_query_data API
-        * receives 5 words of respoonse from firmware. Currently linux driver can
-        * receive only 4 words from TF-A. So, this needs to be handled separately
-        * than other eemi calls.
-        */
-       if (api_id == PM_QUERY_DATA) {
-               if ((pm_arg[0] == XPM_QID_CLOCK_GET_NAME ||
-                   pm_arg[0] == XPM_QID_PINCTRL_GET_FUNCTION_NAME) &&
-                   ret == PM_RET_SUCCESS) {
-                       SMC_RET2(handle, (uint64_t)buf[0] | ((uint64_t)buf[1] << 32U),
-                               (uint64_t)buf[2] | ((uint64_t)buf[3] << 32U));
-               }
-       }
-
-       SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32U),
-                (uint64_t)buf[1] | ((uint64_t)buf[2] << 32U));
-}
-
-/**
- * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
- * @smc_fid - Function Identifier
- * @x1 - x4 - SMC64 Arguments from kernel
- *           x3 (upper 32-bits) and x4 are Unused
- * @cookie  - Unused
- * @handler - Pointer to caller's context structure
- *
- * @return  - Unused
- *
- * Determines that smc_fid is valid and supported PM SMC Function ID from the
- * list of pm_api_ids, otherwise completes the request with
- * the unknown SMC Function ID
- *
- * The SMC calls for PM service are forwarded from SIP Service SMC handler
- * function with rt_svc_handle signature
- */
-uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
-                       uint64_t x4, const void *cookie, void *handle, uint64_t flags)
-{
-       uintptr_t ret;
-       uint32_t pm_arg[PAYLOAD_ARG_CNT] = {0};
-       uint32_t security_flag = SECURE_FLAG;
-       uint32_t api_id;
-
-       /* Handle case where PM wasn't initialized properly */
-       if (pm_up == false) {
-               SMC_RET1(handle, SMC_UNK);
-       }
-
-       /*
-        * Mark BIT24 payload (i.e 1st bit of pm_arg[3] ) as non-secure (1)
-        * if smc called is non secure
-        */
-       if (is_caller_non_secure(flags) != 0) {
-               security_flag = NON_SECURE_FLAG;
-       }
-
-       pm_arg[0] = (uint32_t)x1;
-       pm_arg[1] = (uint32_t)(x1 >> 32U);
-       pm_arg[2] = (uint32_t)x2;
-       pm_arg[3] = (uint32_t)(x2 >> 32U);
-       pm_arg[4] = (uint32_t)x3;
-       (void)(x4);
-       api_id = smc_fid & FUNCID_NUM_MASK;
-
-       ret = eemi_for_compatibility(api_id, pm_arg, handle, security_flag);
-       if (ret != (uintptr_t)0) {
-               return ret;
-       }
-
-       ret = eemi_psci_debugfs_handler(api_id, pm_arg, handle, flags);
-       if (ret !=  (uintptr_t)0) {
-               return ret;
-       }
-
-       ret = TF_A_specific_handler(api_id, pm_arg, handle, security_flag);
-       if (ret !=  (uintptr_t)0) {
-               return ret;
-       }
-
-       ret = eemi_handler(api_id, pm_arg, handle, security_flag);
-
-       return ret;
-}
diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.h b/plat/xilinx/versal/pm_service/pm_svc_main.h
deleted file mode 100644 (file)
index b6e764f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PM_SVC_MAIN_H
-#define PM_SVC_MAIN_H
-
-#include <pm_common.h>
-
-int32_t pm_setup(void);
-uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
-                       uint64_t x4, const void *cookie, void *handle,
-                       uint64_t flags);
-
-int32_t pm_register_sgi(uint32_t sgi_num, uint32_t reset);
-#endif /* PM_SVC_MAIN_H */
index 28e329519e7395a7d81b3af7f54e8081aa9e4553..0bc5925b1465ddccb3f13899f91c525aaa3c2071 100644 (file)
@@ -1,6 +1,6 @@
 # Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
 # Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved.
-# Copyright (C) 2022, Advanced Micro Devices, Inc. All rights reserved.
+# Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 
@@ -87,10 +87,10 @@ BL31_SOURCES                +=      drivers/arm/cci/cci.c                           \
                                lib/cpus/aarch64/cortex_a78.S                   \
                                plat/common/plat_psci_common.c
 ifeq ($(TFA_NO_PM), 0)
-BL31_SOURCES           +=      plat/xilinx/versal/pm_service/pm_api_sys.c      \
+BL31_SOURCES           +=      plat/xilinx/common/pm_service/pm_api_sys.c      \
                                plat/xilinx/common/pm_service/pm_ipi.c          \
                                ${PLAT_PATH}/plat_psci_pm.c                     \
-                               plat/xilinx/versal/pm_service/pm_svc_main.c     \
+                               plat/xilinx/common/pm_service/pm_svc_main.c     \
                                ${PLAT_PATH}/pm_service/pm_client.c             \
                                ${PLAT_PATH}/versal_net_ipi.c
 else
index 95a266e743c8cecac941256a082612ff360f3462..8f2863615475572485dc463aa6a128126281fa46 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
- * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -19,7 +19,7 @@
 #include <plat/common/platform.h>
 #include <services/arm_arch_svc.h>
 
-#include "pm_api_sys.h"
+#include "zynqmp_pm_api_sys.h"
 
 /*
  * Table of regions to map using the MMU.
index 4ceb5765afe8b30bfd2e18a14f251c8446ed669c..db3c74260ee79b0821afe451f6829400cb33e081 100644 (file)
@@ -8,8 +8,8 @@ LIBPM_SRCS      :=      $(addprefix plat/xilinx/common/pm_service/,     \
                        pm_ipi.c)
 
 LIBPM_SRCS      +=      $(addprefix plat/xilinx/zynqmp/pm_service/,  \
-                        pm_svc_main.c                                  \
-                       pm_api_sys.c                                    \
+                        zynqmp_pm_svc_main.c                           \
+                       zynqmp_pm_api_sys.c                             \
                        pm_api_pinctrl.c                                \
                        pm_api_ioctl.c                                  \
                        pm_api_clock.c                                  \
index b7408b1dae7e7142dc0b08622bc7dcf9563bdbcc..5211ace82f5d54370eacb3308427f26c60fdadf4 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -16,8 +17,8 @@
 #include <plat/common/platform.h>
 
 #include <plat_private.h>
-#include "pm_api_sys.h"
 #include "pm_client.h"
+#include "zynqmp_pm_api_sys.h"
 
 static uintptr_t zynqmp_sec_entry;
 
index e61310aad45149bf7b7fe055356615d9678344fa..9f4278d6d33861bbbe2f0d8e779c68382f690026 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <plat/common/platform.h>
 
 #include "pm_api_clock.h"
-#include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_common.h"
 #include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
 
 #define CLK_NODE_MAX                   (6U)
 
index c0bfd51e78c1a02f7f46068f67d370955ae77409..45038b063fd8ed167fe87320c7554ebeba0979df 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
 #include "pm_api_clock.h"
 #include "pm_api_ioctl.h"
-#include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_common.h"
 #include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
 
 /**
  * pm_ioctl_get_rpu_oper_mode () - Get current RPU operation mode
index 8f373418c73ff07095c4032965abd56c427da087..847ec2c5dc087f9329d2bb570fa2e0cfab9413cb 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
 #include <plat/common/platform.h>
 
 #include "pm_api_pinctrl.h"
-#include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_common.h"
 #include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
 
 struct pinctrl_function {
        char name[FUNCTION_NAME_LEN];
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
deleted file mode 100644 (file)
index 58491a0..0000000
+++ /dev/null
@@ -1,1811 +0,0 @@
-/*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2022-2023, Advanced Micro Devices Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * ZynqMP system level PM-API functions and communication with PMU via
- * IPI interrupts
- */
-
-#include <arch_helpers.h>
-#include <plat/common/platform.h>
-
-#include "pm_api_clock.h"
-#include "pm_api_ioctl.h"
-#include "pm_api_pinctrl.h"
-#include "pm_api_sys.h"
-#include "pm_client.h"
-#include "pm_common.h"
-#include "pm_ipi.h"
-
-#define PM_QUERY_FEATURE_BITMASK ( \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
-       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
-       (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
-
-/**
- * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
- * on both the ATF and firmware
- *
- * @id:                EEMI API id or IOCTL id to be checked
- * @api_id:    Dependent EEMI API
- */
-typedef struct __attribute__((packed)) {
-       uint8_t id;
-       uint8_t api_id;
-} eemi_api_dependency;
-
-/* Dependent APIs for ATF to check their version from firmware */
-static const eemi_api_dependency api_dep_table[] = {
-       {
-               .id = PM_SELF_SUSPEND,
-               .api_id = PM_SELF_SUSPEND,
-       },
-       {
-               .id = PM_REQ_WAKEUP,
-               .api_id = PM_REQ_WAKEUP,
-       },
-       {
-               .id = PM_ABORT_SUSPEND,
-               .api_id = PM_ABORT_SUSPEND,
-       },
-       {
-               .id = PM_SET_WAKEUP_SOURCE,
-               .api_id = PM_SET_WAKEUP_SOURCE,
-       },
-       {
-               .id = PM_SYSTEM_SHUTDOWN,
-               .api_id = PM_SYSTEM_SHUTDOWN,
-       },
-       {
-               .id = PM_GET_API_VERSION,
-               .api_id = PM_GET_API_VERSION,
-       },
-       {
-               .id = PM_CLOCK_ENABLE,
-               .api_id = PM_PLL_SET_MODE,
-       },
-       {
-               .id = PM_CLOCK_ENABLE,
-               .api_id = PM_CLOCK_ENABLE,
-       },
-       {
-               .id = PM_CLOCK_DISABLE,
-               .api_id = PM_PLL_SET_MODE,
-       },
-       {
-               .id = PM_CLOCK_DISABLE,
-               .api_id = PM_CLOCK_DISABLE,
-       },
-       {
-               .id = PM_CLOCK_GETSTATE,
-               .api_id = PM_PLL_GET_MODE,
-       },
-       {
-               .id = PM_CLOCK_GETSTATE,
-               .api_id = PM_CLOCK_GETSTATE,
-       },
-       {
-               .id = PM_CLOCK_SETDIVIDER,
-               .api_id = PM_PLL_SET_PARAMETER,
-       },
-       {
-               .id = PM_CLOCK_SETDIVIDER,
-               .api_id = PM_CLOCK_SETDIVIDER,
-       },
-       {
-               .id = PM_CLOCK_GETDIVIDER,
-               .api_id = PM_PLL_GET_PARAMETER,
-       },
-       {
-               .id = PM_CLOCK_GETDIVIDER,
-               .api_id = PM_CLOCK_GETDIVIDER,
-       },
-       {
-               .id = PM_CLOCK_SETPARENT,
-               .api_id = PM_PLL_SET_PARAMETER,
-       },
-       {
-               .id = PM_CLOCK_SETPARENT,
-               .api_id = PM_CLOCK_SETPARENT,
-       },
-       {
-               .id = PM_CLOCK_GETPARENT,
-               .api_id = PM_PLL_GET_PARAMETER,
-       },
-       {
-               .id = PM_CLOCK_GETPARENT,
-               .api_id = PM_CLOCK_GETPARENT,
-       },
-       {
-               .id = PM_PLL_SET_PARAMETER,
-               .api_id = PM_PLL_SET_PARAMETER,
-       },
-       {
-               .id = PM_PLL_GET_PARAMETER,
-               .api_id = PM_PLL_GET_PARAMETER,
-       },
-       {
-               .id = PM_PLL_SET_MODE,
-               .api_id = PM_PLL_SET_MODE,
-       },
-       {
-               .id = PM_PLL_GET_MODE,
-               .api_id = PM_PLL_GET_MODE,
-       },
-       {
-               .id = PM_REGISTER_ACCESS,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = PM_REGISTER_ACCESS,
-               .api_id = PM_MMIO_READ,
-       },
-       {
-               .id = PM_FEATURE_CHECK,
-               .api_id = PM_FEATURE_CHECK,
-       },
-       {
-               .id = IOCTL_SET_TAPDELAY_BYPASS,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_SET_SGMII_MODE,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_SD_DLL_RESET,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_SET_SD_TAPDELAY,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_SET_SD_TAPDELAY,
-               .api_id = PM_MMIO_READ,
-       },
-       {
-               .id = IOCTL_SET_PLL_FRAC_DATA,
-               .api_id = PM_PLL_SET_PARAMETER,
-       },
-       {
-               .id = IOCTL_GET_PLL_FRAC_DATA,
-               .api_id = PM_PLL_GET_PARAMETER,
-       },
-       {
-               .id = IOCTL_WRITE_GGS,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_READ_GGS,
-               .api_id = PM_MMIO_READ,
-       },
-       {
-               .id = IOCTL_WRITE_PGGS,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_READ_PGGS,
-               .api_id = PM_MMIO_READ,
-       },
-       {
-               .id = IOCTL_ULPI_RESET,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_SET_BOOT_HEALTH_STATUS,
-               .api_id = PM_MMIO_WRITE,
-       },
-       {
-               .id = IOCTL_AFI,
-               .api_id = PM_MMIO_WRITE,
-       },
-};
-
-/* Expected firmware API version to ATF */
-static const uint8_t atf_expected_ver_id[] = {
-       [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
-       [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
-       [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
-       [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
-       [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
-       [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
-       [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
-       [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
-       [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
-       [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
-       [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
-       [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
-       [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
-       [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
-       [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
-       [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
-       [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
-       [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
-       [PM_MMIO_READ] = FW_API_BASE_VERSION,
-       [PM_FEATURE_CHECK] = FW_API_VERSION_2,
-};
-
-/* default shutdown/reboot scope is system(2) */
-static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
-
-/**
- * pm_get_shutdown_scope() - Get the currently set shutdown scope
- *
- * @return     Shutdown scope value
- */
-uint32_t pm_get_shutdown_scope(void)
-{
-       return pm_shutdown_scope;
-}
-
-/**
- * pm_self_suspend() - PM call for processor to suspend itself
- * @nid                Node id of the processor or subsystem
- * @latency    Requested maximum wakeup latency (not supported)
- * @state      Requested state
- * @address    Resume address
- *
- * This is a blocking call, it will return only once PMU has responded.
- * On a wakeup, resume address will be automatically set by PMU.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
-                                  uint32_t latency,
-                                  uint32_t state,
-                                  uintptr_t address)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint32_t cpuid = plat_my_core_pos();
-       const struct pm_proc *proc = pm_get_proc(cpuid);
-
-       /*
-        * Do client specific suspend operations
-        * (e.g. set powerdown request bit)
-        */
-       pm_client_suspend(proc, state);
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
-                        state, address, (address >> 32));
-       return pm_ipi_send_sync(proc, payload, NULL, 0);
-}
-
-/**
- * pm_req_suspend() - PM call to request for another PU or subsystem to
- *                   be suspended gracefully.
- * @target     Node id of the targeted PU or subsystem
- * @ack                Flag to specify whether acknowledge is requested
- * @latency    Requested wakeup latency (not supported)
- * @state      Requested state (not supported)
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_req_suspend(enum pm_node_id target,
-                                 enum pm_request_ack ack,
-                                 uint32_t latency, uint32_t state)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
-       if (ack == REQ_ACK_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_req_wakeup() - PM call for processor to wake up selected processor
- *                  or subsystem
- * @target     Node id of the processor or subsystem to wake up
- * @ack                Flag to specify whether acknowledge requested
- * @set_address        Resume address presence indicator
- *                             1 resume address specified, 0 otherwise
- * @address    Resume address
- *
- * This API function is either used to power up another APU core for SMP
- * (by PSCI) or to power up an entirely different PU or subsystem, such
- * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
- * automatically set by PMU.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
-                                uint32_t set_address,
-                                uintptr_t address,
-                                enum pm_request_ack ack)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint64_t encoded_address;
-
-
-       /* encode set Address into 1st bit of address */
-       encoded_address = address;
-       encoded_address |= !!set_address;
-
-       /* Send request to the PMU to perform the wake of the PU */
-       PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
-                        encoded_address >> 32, ack);
-
-       if (ack == REQ_ACK_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_force_powerdown() - PM call to request for another PU or subsystem to
- *                       be powered down forcefully
- * @target     Node id of the targeted PU or subsystem
- * @ack                Flag to specify whether acknowledge is requested
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
-                                     enum pm_request_ack ack)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
-
-       if (ack == REQ_ACK_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_abort_suspend() - PM call to announce that a prior suspend request
- *                     is to be aborted.
- * @reason     Reason for the abort
- *
- * Calling PU expects the PMU to abort the initiated suspend procedure.
- * This is a non-blocking call without any acknowledge.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /*
-        * Do client specific abort suspend operations
-        * (e.g. enable interrupts and clear powerdown request bit)
-        */
-       pm_client_abort_suspend();
-       /* Send request to the PMU */
-       /* TODO: allow passing the node ID of the affected CPU */
-       PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
-                        primary_proc->node_id);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
- * @target     Node id of the targeted PU or subsystem
- * @wkup_node  Node id of the wakeup peripheral
- * @enable     Enable or disable the specified peripheral as wake source
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
-                                       enum pm_node_id wkup_node,
-                                       uint32_t enable)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
-                        enable);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_system_shutdown() - PM call to request a system shutdown or restart
- * @type       Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
- * @subtype    Scope: 0=APU-subsystem, 1=PS, 2=system
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
-               /* Setting scope for subsequent PSCI reboot or shutdown */
-               pm_shutdown_scope = subtype;
-               return PM_RET_SUCCESS;
-       }
-
-       PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
-       return pm_ipi_send_non_blocking(primary_proc, payload);
-}
-
-/* APIs for managing PM slaves: */
-
-/**
- * pm_req_node() - PM call to request a node with specific capabilities
- * @nid                Node id of the slave
- * @capabilities Requested capabilities of the slave
- * @qos                Quality of service (not supported)
- * @ack                Flag to specify whether acknowledge is requested
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_req_node(enum pm_node_id nid,
-                              uint32_t capabilities,
-                              uint32_t qos,
-                              enum pm_request_ack ack)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
-
-       if (ack == REQ_ACK_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/**
- * pm_set_requirement() - PM call to set requirement for PM slaves
- * @nid                Node id of the slave
- * @capabilities Requested capabilities of the slave
- * @qos                Quality of service (not supported)
- * @ack                Flag to specify whether acknowledge is requested
- *
- * This API function is to be used for slaves a PU already has requested
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
-                                     uint32_t capabilities,
-                                     uint32_t qos,
-                                     enum pm_request_ack ack)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
-                        ack);
-
-       if (ack == REQ_ACK_BLOCKING) {
-               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-       } else {
-               return pm_ipi_send(primary_proc, payload);
-       }
-}
-
-/* Miscellaneous API functions */
-
-/**
- * pm_get_api_version() - Get version number of PMU PM firmware
- * @version    Returns 32-bit version number of PMU Power Management Firmware
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_get_api_version(uint32_t *version)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
-       return pm_ipi_send_sync(primary_proc, payload, version, 1);
-}
-
-/**
- * pm_get_node_status() - PM call to request a node's current status
- * @nid                Node id
- * @ret_buff   Buffer for the return values:
- *             [0] - Current power state of the node
- *             [1] - Current requirements for the node (slave nodes only)
- *             [2] - Current usage status for the node (slave nodes only)
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
-                                     uint32_t *ret_buff)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
-       return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
-}
-
-/**
- * pm_mmio_write() - Perform write to protected mmio
- * @address    Address to write to
- * @mask       Mask to apply
- * @value      Value to write
- *
- * This function provides access to PM-related control registers
- * that may not be directly accessible by a particular PU.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_mmio_write(uintptr_t address,
-                                uint32_t mask,
-                                uint32_t value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_mmio_read() - Read value from protected mmio
- * @address    Address to write to
- * @value      Value to write
- *
- * This function provides access to PM-related control registers
- * that may not be directly accessible by a particular PU.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/**
- * pm_fpga_load() - Load the bitstream into the PL.
- *
- * This function provides access to the xilfpga library to load
- * the Bit-stream into PL.
- *
- * address_low: lower 32-bit Linear memory space address
- *
- * address_high: higher 32-bit Linear memory space address
- *
- * size:       Number of 32bit words
- *
- * @return      Returns status, either success or error+reason
- */
-enum pm_ret_status pm_fpga_load(uint32_t address_low,
-                               uint32_t address_high,
-                               uint32_t size,
-                               uint32_t flags)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
-                                               size, flags);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_fpga_get_status() - Read value from fpga status register
- * @value       Value to read
- *
- * This function provides access to the xilfpga library to get
- * the fpga status
- * @return      Returns status, either success or error+reason
- */
-enum pm_ret_status pm_fpga_get_status(uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/**
- * pm_get_chipid() - Read silicon ID registers
- * @value       Buffer for return values. Must be large enough
- *             to hold 8 bytes.
- *
- * @return      Returns silicon ID registers
- */
-enum pm_ret_status pm_get_chipid(uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
-       return pm_ipi_send_sync(primary_proc, payload, value, 2);
-}
-
-/**
- * pm_secure_rsaaes() - Load the secure images.
- *
- * This function provides access to the xilsecure library to load
- * the authenticated, encrypted, and authenicated/encrypted images.
- *
- * address_low: lower 32-bit Linear memory space address
- *
- * address_high: higher 32-bit Linear memory space address
- *
- * size:       Number of 32bit words
- *
- * @return      Returns status, either success or error+reason
- */
-enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
-                               uint32_t address_high,
-                               uint32_t size,
-                               uint32_t flags)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
-                        size, flags);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_aes_engine() - Aes data blob encryption/decryption
- * This function provides access to the xilsecure library to
- * encrypt/decrypt data blobs.
- *
- * address_low: lower 32-bit address of the AesParams structure
- *
- * address_high: higher 32-bit address of the AesParams structure
- *
- * value:        Returned output value
- *
- * @return       Returns status, either success or error+reason
- */
-enum pm_ret_status pm_aes_engine(uint32_t address_high,
-                                uint32_t address_low,
-                                uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/**
- * pm_get_callbackdata() - Read from IPI response buffer
- * @data - array of PAYLOAD_ARG_CNT elements
- *
- * Read value from ipi buffer response buffer.
- * @return      Returns status, either success or error
- */
-enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count)
-{
-       enum pm_ret_status ret = PM_RET_SUCCESS;
-       /* Return if interrupt is not from PMU */
-       if (!pm_ipi_irq_status(primary_proc)) {
-               return ret;
-       }
-
-       ret = pm_ipi_buff_read_callb(data, count);
-       pm_ipi_irq_clear(primary_proc);
-       return ret;
-}
-
-/**
- * pm_ioctl() -  PM IOCTL API for device control and configs
- * @node_id    Node ID of the device
- * @ioctl_id   ID of the requested IOCTL
- * @arg1       Argument 1 to requested IOCTL call
- * @arg2       Argument 2 to requested IOCTL call
- * @out                Returned output value
- *
- * This function calls IOCTL to firmware for device control and configuration.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_ioctl(enum pm_node_id nid,
-                           uint32_t ioctl_id,
-                           uint32_t arg1,
-                           uint32_t arg2,
-                           uint32_t *value)
-{
-       return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
-}
-
-/**
- * fw_api_version() - Returns API version implemented in firmware
- * @api_id     API ID to check
- * @version    Returned supported API version
- * @len                Number of words to be returned
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
-                                        uint32_t len)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
-       return pm_ipi_send_sync(primary_proc, payload, version, len);
-}
-
-/**
- * check_api_dependency() -  API to check dependent EEMI API version
- * @id         EEMI API ID to check
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status check_api_dependency(uint8_t id)
-{
-       uint8_t i;
-       uint32_t version;
-       int ret;
-
-       for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
-               if (api_dep_table[i].id == id) {
-                       if (api_dep_table[i].api_id == 0U) {
-                               break;
-                       }
-
-                       ret = fw_api_version(api_dep_table[i].api_id,
-                                            &version, 1);
-                       if (ret != PM_RET_SUCCESS) {
-                               return ret;
-                       }
-
-                       /* Check if fw version matches ATF expected version */
-                       if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
-                               return PM_RET_ERROR_NOTSUPPORTED;
-                       }
-               }
-       }
-
-       return PM_RET_SUCCESS;
-}
-
-/**
- * feature_check_atf() - These are API's completely implemented in ATF
- * @api_id     API ID to check
- * @version    Returned supported API version
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
-                                           uint32_t *bit_mask)
-{
-       switch (api_id) {
-       case PM_QUERY_DATA:
-               *version = TFA_API_QUERY_DATA_VERSION;
-               bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
-               bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
-               return PM_RET_SUCCESS;
-       case PM_GET_CALLBACK_DATA:
-       case PM_GET_TRUSTZONE_VERSION:
-       case PM_SET_SUSPEND_MODE:
-               *version = ATF_API_BASE_VERSION;
-               return PM_RET_SUCCESS;
-       default:
-               return PM_RET_ERROR_NO_FEATURE;
-       }
-}
-
-/**
- * get_atf_version_for_partial_apis() - Return ATF version for partially
- * implemented APIs
- * @api_id     API ID to check
- * @version    Returned supported API version
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
-                                                          uint32_t *version)
-{
-       switch (api_id) {
-       case PM_SELF_SUSPEND:
-       case PM_REQ_WAKEUP:
-       case PM_ABORT_SUSPEND:
-       case PM_SET_WAKEUP_SOURCE:
-       case PM_SYSTEM_SHUTDOWN:
-       case PM_GET_API_VERSION:
-       case PM_CLOCK_ENABLE:
-       case PM_CLOCK_DISABLE:
-       case PM_CLOCK_GETSTATE:
-       case PM_CLOCK_SETDIVIDER:
-       case PM_CLOCK_GETDIVIDER:
-       case PM_CLOCK_SETPARENT:
-       case PM_CLOCK_GETPARENT:
-       case PM_PLL_SET_PARAMETER:
-       case PM_PLL_GET_PARAMETER:
-       case PM_PLL_SET_MODE:
-       case PM_PLL_GET_MODE:
-       case PM_REGISTER_ACCESS:
-               *version = ATF_API_BASE_VERSION;
-               return PM_RET_SUCCESS;
-       case PM_FEATURE_CHECK:
-               *version = FW_API_VERSION_2;
-               return PM_RET_SUCCESS;
-       default:
-               return PM_RET_ERROR_ARGS;
-       }
-}
-
-/**
- * feature_check_partial() - These are API's partially implemented in
- * ATF and firmware both
- * @api_id     API ID to check
- * @version    Returned supported API version
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status feature_check_partial(uint32_t api_id,
-                                               uint32_t *version)
-{
-       uint32_t status;
-
-       switch (api_id) {
-       case PM_SELF_SUSPEND:
-       case PM_REQ_WAKEUP:
-       case PM_ABORT_SUSPEND:
-       case PM_SET_WAKEUP_SOURCE:
-       case PM_SYSTEM_SHUTDOWN:
-       case PM_GET_API_VERSION:
-       case PM_CLOCK_ENABLE:
-       case PM_CLOCK_DISABLE:
-       case PM_CLOCK_GETSTATE:
-       case PM_CLOCK_SETDIVIDER:
-       case PM_CLOCK_GETDIVIDER:
-       case PM_CLOCK_SETPARENT:
-       case PM_CLOCK_GETPARENT:
-       case PM_PLL_SET_PARAMETER:
-       case PM_PLL_GET_PARAMETER:
-       case PM_PLL_SET_MODE:
-       case PM_PLL_GET_MODE:
-       case PM_REGISTER_ACCESS:
-       case PM_FEATURE_CHECK:
-               status = check_api_dependency(api_id);
-               if (status != PM_RET_SUCCESS) {
-                       return status;
-               }
-               return get_atf_version_for_partial_apis(api_id, version);
-       default:
-               return PM_RET_ERROR_NO_FEATURE;
-       }
-}
-
-/**
- * pm_feature_check() - Returns the supported API version if supported
- * @api_id     API ID to check
- * @version    Returned supported API version
- * @bit_mask   Returned supported IOCTL id version
- * @len                Number of bytes to be returned in bit_mask variable
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
-                                   uint32_t *bit_mask, uint8_t len)
-{
-       uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
-       uint32_t status;
-
-       /* Get API version implemented in ATF */
-       status = feature_check_atf(api_id, version, bit_mask);
-       if (status != PM_RET_ERROR_NO_FEATURE) {
-               return status;
-       }
-
-       /* Get API version implemented by firmware and ATF both */
-       status = feature_check_partial(api_id, version);
-       if (status != PM_RET_ERROR_NO_FEATURE) {
-               return status;
-       }
-
-       /* Get API version implemented by firmware */
-       status = fw_api_version(api_id, ret_payload, 3);
-       /* IOCTL call may return failure whose ID is not implemented in
-        * firmware but implemented in ATF
-        */
-       if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
-               return status;
-       }
-
-       *version = ret_payload[0];
-
-       /* Update IOCTL bit mask which are implemented in ATF */
-       if ((api_id == PM_IOCTL) || (api_id == PM_GET_OP_CHARACTERISTIC)) {
-               if (len < 2) {
-                       return PM_RET_ERROR_ARGS;
-               }
-               bit_mask[0] = ret_payload[1];
-               bit_mask[1] = ret_payload[2];
-               if (api_id == PM_IOCTL) {
-                       /* Get IOCTL's implemented by ATF */
-                       status = atf_ioctl_bitmask(bit_mask);
-               }
-       } else {
-               /* Requires for MISRA */
-       }
-
-       return status;
-}
-
-/**
- * pm_clock_get_max_divisor - PM call to get max divisor
- * @clock_id   Clock ID
- * @div_type   Divisor ID (TYPE_DIV1 or TYPE_DIV2)
- * @max_div    Maximum supported divisor
- *
- * This function is used by master to get maximum supported value.
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
-                                                  uint8_t div_type,
-                                                  uint32_t *max_div)
-{
-       return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
-}
-
-/**
- * pm_clock_get_num_clocks - PM call to request number of clocks
- * @nclockss: Number of clocks
- *
- * This function is used by master to get number of clocks.
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
-{
-       return pm_api_clock_get_num_clocks(nclocks);
-}
-
-/**
- * pm_clock_get_name() - PM call to request a clock's name
- * @clock_id   Clock ID
- * @name       Name of clock (max 16 bytes)
- *
- * This function is used by master to get nmae of clock specified
- * by given clock ID.
- */
-static void pm_clock_get_name(uint32_t clock_id, char *name)
-{
-       pm_api_clock_get_name(clock_id, name);
-}
-
-/**
- * pm_clock_get_topology() - PM call to request a clock's topology
- * @clock_id   Clock ID
- * @index      Topology index for next toplogy node
- * @topology   Buffer to store nodes in topology and flags
- *
- * This function is used by master to get topology information for the
- * clock specified by given clock ID. Each response would return 3
- * topology nodes. To get next nodes, caller needs to call this API with
- * index of next node. Index starts from 0.
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
-                                               uint32_t index,
-                                               uint32_t *topology)
-{
-       return pm_api_clock_get_topology(clock_id, index, topology);
-}
-
-/**
- * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
- *                              parameters for fixed clock
- * @clock_id   Clock ID
- * @mul                Multiplication value
- * @div                Divisor value
- *
- * This function is used by master to get fixed factor parameers for the
- * fixed clock. This API is application only for the fixed clock.
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
-                                                         uint32_t *mul,
-                                                         uint32_t *div)
-{
-       return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
-}
-
-/**
- * pm_clock_get_parents() - PM call to request a clock's first 3 parents
- * @clock_id   Clock ID
- * @index      Index of next parent
- * @parents    Parents of the given clock
- *
- * This function is used by master to get clock's parents information.
- * This API will return 3 parents with a single response. To get other
- * parents, master should call same API in loop with new parent index
- * till error is returned.
- *
- * E.g First call should have index 0 which will return parents 0, 1 and
- * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
- * so on.
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
-                                              uint32_t index,
-                                              uint32_t *parents)
-{
-       return pm_api_clock_get_parents(clock_id, index, parents);
-}
-
-/**
- * pm_clock_get_attributes() - PM call to request a clock's attributes
- * @clock_id   Clock ID
- * @attr       Clock attributes
- *
- * This function is used by master to get clock's attributes
- * (e.g. valid, clock type, etc).
- *
- * @return     Returns status, either success or error+reason
- */
-static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
-                                                 uint32_t *attr)
-{
-       return pm_api_clock_get_attributes(clock_id, attr);
-}
-
-/**
- * pm_clock_gate() - Configure clock gate
- * @clock_id   Id of the clock to be configured
- * @enable     Flag 0=disable (gate the clock), !0=enable (activate the clock)
- *
- * @return     Error if an argument is not valid or status as returned by the
- *             PM controller (PMU)
- */
-static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
-                                       uint8_t enable)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       enum pm_ret_status status;
-       enum pm_api_id api_id;
-
-       /* Check if clock ID is valid and return an error if it is not */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       if (enable) {
-               api_id = PM_CLOCK_ENABLE;
-       } else {
-               api_id = PM_CLOCK_DISABLE;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD2(payload, api_id, clock_id);
-       status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-
-       /* If action fails due to the lack of permissions filter the error */
-       if (status == PM_RET_ERROR_ACCESS) {
-               status = PM_RET_SUCCESS;
-       }
-
-       return status;
-}
-
-/**
- * pm_clock_enable() - Enable the clock for given id
- * @clock_id: Id of the clock to be enabled
- *
- * This function is used by master to enable the clock
- * including peripherals and PLL clocks.
- *
- * @return:    Error if an argument is not valid or status as returned by the
- *             pm_clock_gate
- */
-enum pm_ret_status pm_clock_enable(uint32_t clock_id)
-{
-       struct pm_pll *pll;
-
-       /* First try to handle it as a PLL */
-       pll = pm_clock_get_pll(clock_id);
-       if (pll) {
-               return pm_clock_pll_enable(pll);
-       }
-
-       /* It's an on-chip clock, PMU should configure clock's gate */
-       return pm_clock_gate(clock_id, 1);
-}
-
-/**
- * pm_clock_disable - Disable the clock for given id
- * @clock_id: Id of the clock to be disable
- *
- * This function is used by master to disable the clock
- * including peripherals and PLL clocks.
- *
- * @return:    Error if an argument is not valid or status as returned by the
- *             pm_clock_gate
- */
-enum pm_ret_status pm_clock_disable(uint32_t clock_id)
-{
-       struct pm_pll *pll;
-
-       /* First try to handle it as a PLL */
-       pll = pm_clock_get_pll(clock_id);
-       if (pll) {
-               return pm_clock_pll_disable(pll);
-       }
-
-       /* It's an on-chip clock, PMU should configure clock's gate */
-       return pm_clock_gate(clock_id, 0);
-}
-
-/**
- * pm_clock_getstate - Get the clock state for given id
- * @clock_id: Id of the clock to be queried
- * @state: 1/0 (Enabled/Disabled)
- *
- * This function is used by master to get the state of clock
- * including peripherals and PLL clocks.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
-                                    uint32_t *state)
-{
-       struct pm_pll *pll;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       enum pm_ret_status status;
-
-       /* First try to handle it as a PLL */
-       pll = pm_clock_get_pll(clock_id);
-       if (pll)
-               return pm_clock_pll_get_state(pll, state);
-
-       /* Check if clock ID is a valid on-chip clock */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
-       return pm_ipi_send_sync(primary_proc, payload, state, 1);
-}
-
-/**
- * pm_clock_setdivider - Set the clock divider for given id
- * @clock_id: Id of the clock
- * @divider: divider value
- *
- * This function is used by master to set divider for any clock
- * to achieve desired rate.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
-                                      uint32_t divider)
-{
-       enum pm_ret_status status;
-       enum pm_node_id nid;
-       enum pm_clock_div_id div_id;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       const uint32_t div0 = 0xFFFF0000;
-       const uint32_t div1 = 0x0000FFFF;
-       uint32_t val;
-
-       /* Get PLL node ID using PLL clock ID */
-       status = pm_clock_get_pll_node_id(clock_id, &nid);
-       if (status == PM_RET_SUCCESS) {
-               return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
-       }
-
-       /* Check if clock ID is a valid on-chip clock */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       if (div0 == (divider & div0)) {
-               div_id = PM_CLOCK_DIV0_ID;
-               val = divider & ~div0;
-       } else if (div1 == (divider & div1)) {
-               div_id = PM_CLOCK_DIV1_ID;
-               val = (divider & ~div1) >> 16;
-       } else {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_clock_getdivider - Get the clock divider for given id
- * @clock_id: Id of the clock
- * @divider: divider value
- *
- * This function is used by master to get divider values
- * for any clock.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
-                                      uint32_t *divider)
-{
-       enum pm_ret_status status;
-       enum pm_node_id nid;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       uint32_t val;
-
-       /* Get PLL node ID using PLL clock ID */
-       status = pm_clock_get_pll_node_id(clock_id, &nid);
-       if (status == PM_RET_SUCCESS) {
-               return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
-       }
-
-       /* Check if clock ID is a valid on-chip clock */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
-               /* Send request to the PMU to get div0 */
-               PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
-                                PM_CLOCK_DIV0_ID);
-               status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
-               if (status != PM_RET_SUCCESS) {
-                       return status;
-               }
-               *divider = val;
-       }
-
-       if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
-               /* Send request to the PMU to get div1 */
-               PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
-                                PM_CLOCK_DIV1_ID);
-               status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
-               if (status != PM_RET_SUCCESS) {
-                       return status;
-               }
-               *divider |= val << 16;
-       }
-
-       return status;
-}
-
-/**
- * pm_clock_setrate - Set the clock rate for given id
- * @clock_id: Id of the clock
- * @rate: rate value in hz
- *
- * This function is used by master to set rate for any clock.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
-                                   uint64_t rate)
-{
-       return PM_RET_ERROR_NOTSUPPORTED;
-}
-
-/**
- * pm_clock_getrate - Get the clock rate for given id
- * @clock_id: Id of the clock
- * @rate: rate value in hz
- *
- * This function is used by master to get rate
- * for any clock.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
-                                   uint64_t *rate)
-{
-       return PM_RET_ERROR_NOTSUPPORTED;
-}
-
-/**
- * pm_clock_setparent - Set the clock parent for given id
- * @clock_id: Id of the clock
- * @parent_index: Index of the parent clock into clock's parents array
- *
- * This function is used by master to set parent for any clock.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
-                                     uint32_t parent_index)
-{
-       struct pm_pll *pll;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       enum pm_ret_status status;
-
-       /* First try to handle it as a PLL */
-       pll = pm_clock_get_pll_by_related_clk(clock_id);
-       if (pll) {
-               return pm_clock_pll_set_parent(pll, clock_id, parent_index);
-       }
-
-       /* Check if clock ID is a valid on-chip clock */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_clock_getparent - Get the clock parent for given id
- * @clock_id: Id of the clock
- * @parent_index: parent index
- *
- * This function is used by master to get parent index
- * for any clock.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
-                                     uint32_t *parent_index)
-{
-       struct pm_pll *pll;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-       enum pm_ret_status status;
-
-       /* First try to handle it as a PLL */
-       pll = pm_clock_get_pll_by_related_clk(clock_id);
-       if (pll) {
-               return pm_clock_pll_get_parent(pll, clock_id, parent_index);
-       }
-
-       /* Check if clock ID is a valid on-chip clock */
-       status = pm_clock_id_is_valid(clock_id);
-       if (status != PM_RET_SUCCESS) {
-               return status;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
-       return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
-}
-
-/**
- * pm_pinctrl_get_num_pins - PM call to request number of pins
- * @npins: Number of pins
- *
- * This function is used by master to get number of pins
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
-{
-       return pm_api_pinctrl_get_num_pins(npins);
-}
-
-/**
- * pm_pinctrl_get_num_functions - PM call to request number of functions
- * @nfuncs: Number of functions
- *
- * This function is used by master to get number of functions
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
-{
-       return pm_api_pinctrl_get_num_functions(nfuncs);
-}
-
-/**
- * pm_pinctrl_get_num_function_groups - PM call to request number of
- *                                     function groups
- * @fid: Id of function
- * @ngroups: Number of function groups
- *
- * This function is used by master to get number of function groups specified
- * by given function Id
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
-                                                            uint32_t *ngroups)
-{
-       return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
-}
-
-/**
- * pm_pinctrl_get_function_name - PM call to request function name
- * @fid: Id of function
- * @name: Name of function
- *
- * This function is used by master to get name of function specified
- * by given function Id
- */
-static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
-{
-       pm_api_pinctrl_get_function_name(fid, name);
-}
-
-/**
- * pm_pinctrl_get_function_groups - PM call to request function groups
- * @fid: Id of function
- * @index: Index of next function groups
- * @groups: Function groups
- *
- * This function is used by master to get function groups specified
- * by given function Id. This API will return 6 function groups with
- * a single response. To get other function groups, master should call
- * same API in loop with new function groups index till error is returned.
- *
- * E.g First call should have index 0 which will return function groups
- * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
- * function groups 6, 7, 8, 9, 10 and 11 and so on.
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
-                                                        uint32_t index,
-                                                        uint16_t *groups)
-{
-       return pm_api_pinctrl_get_function_groups(fid, index, groups);
-}
-
-/**
- * pm_pinctrl_get_pin_groups - PM call to request pin groups
- * @pin_id: Id of pin
- * @index: Index of next pin groups
- * @groups: pin groups
- *
- * This function is used by master to get pin groups specified
- * by given pin Id. This API will return 6 pin groups with
- * a single response. To get other pin groups, master should call
- * same API in loop with new pin groups index till error is returned.
- *
- * E.g First call should have index 0 which will return pin groups
- * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
- * pin groups 6, 7, 8, 9, 10 and 11 and so on.
- *
- * Return: Returns status, either success or error+reason.
- */
-static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
-                                                   uint32_t index,
-                                                   uint16_t *groups)
-{
-       return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
-}
-
-/**
- * pm_query_data() -  PM API for querying firmware data
- * @arg1       Argument 1 to requested IOCTL call
- * @arg2       Argument 2 to requested IOCTL call
- * @arg3       Argument 3 to requested IOCTL call
- * @arg4       Argument 4 to requested IOCTL call
- * @data       Returned output data
- *
- * This function returns requested data.
- */
-void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
-                  uint32_t arg3, uint32_t *data)
-{
-       switch (qid) {
-       case PM_QID_CLOCK_GET_NAME:
-               pm_clock_get_name(arg1, (char *)data);
-               break;
-       case PM_QID_CLOCK_GET_TOPOLOGY:
-               data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
-               break;
-       case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
-               data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
-                                                         &data[2]);
-               break;
-       case PM_QID_CLOCK_GET_PARENTS:
-               data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
-               break;
-       case PM_QID_CLOCK_GET_ATTRIBUTES:
-               data[0] = pm_clock_get_attributes(arg1, &data[1]);
-               break;
-       case PM_QID_PINCTRL_GET_NUM_PINS:
-               data[0] = pm_pinctrl_get_num_pins(&data[1]);
-               break;
-       case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
-               data[0] = pm_pinctrl_get_num_functions(&data[1]);
-               break;
-       case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
-               data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
-               break;
-       case PM_QID_PINCTRL_GET_FUNCTION_NAME:
-               pm_pinctrl_get_function_name(arg1, (char *)data);
-               break;
-       case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
-               data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
-                                                        (uint16_t *)&data[1]);
-               break;
-       case PM_QID_PINCTRL_GET_PIN_GROUPS:
-               data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
-                                                   (uint16_t *)&data[1]);
-               break;
-       case PM_QID_CLOCK_GET_NUM_CLOCKS:
-               data[0] = pm_clock_get_num_clocks(&data[1]);
-               break;
-
-       case PM_QID_CLOCK_GET_MAX_DIVISOR:
-               data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
-               break;
-       default:
-               data[0] = PM_RET_ERROR_ARGS;
-               WARN("Unimplemented query service call: 0x%x\n", qid);
-               break;
-       }
-}
-
-enum pm_ret_status pm_sha_hash(uint32_t address_high,
-                                   uint32_t address_low,
-                                   uint32_t size,
-                                   uint32_t flags)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
-                                size, flags);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-enum pm_ret_status pm_rsa_core(uint32_t address_high,
-                                   uint32_t address_low,
-                                   uint32_t size,
-                                   uint32_t flags)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
-                                size, flags);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-enum pm_ret_status pm_secure_image(uint32_t address_low,
-                                  uint32_t address_high,
-                                  uint32_t key_lo,
-                                  uint32_t key_hi,
-                                  uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
-                        key_hi, key_lo);
-       return pm_ipi_send_sync(primary_proc, payload, value, 2);
-}
-
-/**
- * pm_fpga_read - Perform the fpga configuration readback
- *
- * @reg_numframes: Configuration register offset (or) Number of frames to read
- * @address_low: lower 32-bit Linear memory space address
- * @address_high: higher 32-bit Linear memory space address
- * @readback_type: Type of fpga readback operation
- *                0 -- Configuration Register readback
- *                1 -- Configuration Data readback
- * @value:     Value to read
- *
- * This function provides access to the xilfpga library to read
- * the PL configuration.
- *
- * Return: Returns status, either success or error+reason.
- */
-enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
-                               uint32_t address_low,
-                               uint32_t address_high,
-                               uint32_t readback_type,
-                               uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
-                        address_high, readback_type);
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/*
- * pm_pll_set_parameter() - Set the PLL parameter value
- * @nid                Node id of the target PLL
- * @param_id   ID of the PLL parameter
- * @value      Parameter value to be set
- *
- * Setting the parameter will have physical effect once the PLL mode is set to
- * integer or fractional.
- *
- * @return     Error if an argument is not valid or status as returned by the
- *             PM controller (PMU)
- */
-enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
-                                       enum pm_pll_param param_id,
-                                       uint32_t value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Check if given node ID is a PLL node */
-       if (nid < NODE_APLL || nid > NODE_IOPLL) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Check if parameter ID is valid and return an error if it's not */
-       if (param_id >= PM_PLL_PARAM_MAX) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_pll_get_parameter() - Get the PLL parameter value
- * @nid                Node id of the target PLL
- * @param_id   ID of the PLL parameter
- * @value      Location to store the parameter value
- *
- * @return     Error if an argument is not valid or status as returned by the
- *             PM controller (PMU)
- */
-enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
-                                       enum pm_pll_param param_id,
-                                       uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Check if given node ID is a PLL node */
-       if (nid < NODE_APLL || nid > NODE_IOPLL) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Check if parameter ID is valid and return an error if it's not */
-       if (param_id >= PM_PLL_PARAM_MAX) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
-
-/**
- * pm_pll_set_mode() - Set the PLL mode
- * @nid                Node id of the target PLL
- * @mode       PLL mode to be set
- *
- * If reset mode is set the PM controller will first bypass the PLL and then
- * assert the reset. If integer or fractional mode is set the PM controller will
- * ensure that the complete PLL programming sequence is satisfied. After this
- * function returns success the PLL is locked and its bypass is deasserted.
- *
- * @return     Error if an argument is not valid or status as returned by the
- *             PM controller (PMU)
- */
-enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Check if given node ID is a PLL node */
-       if (nid < NODE_APLL || nid > NODE_IOPLL) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Check if PLL mode is valid */
-       if (mode >= PM_PLL_MODE_MAX) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
-       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
-}
-
-/**
- * pm_pll_get_mode() - Get the PLL mode
- * @nid                Node id of the target PLL
- * @mode       Location to store the mode of the PLL
- *
- * @return     Error if an argument is not valid or status as returned by the
- *             PM controller (PMU)
- */
-enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Check if given node ID is a PLL node */
-       if (nid < NODE_APLL || nid > NODE_IOPLL) {
-               return PM_RET_ERROR_ARGS;
-       }
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
-       return pm_ipi_send_sync(primary_proc, payload, mode, 1);
-}
-
-/**
- * pm_register_access() -  PM API for register read/write access data
- *
- * @register_access_id Register_access_id which says register read/write
- *
- * @address            Address of the register to be accessed
- *
- * @mask               Mask value to be used while writing value
- *
- * @value              Value to be written to register
- *
- * @out                        Returned output data
- *
- * This function returns requested data.
- *
- * @return     Returns status, either success or error+reason
- */
-enum pm_ret_status pm_register_access(uint32_t register_access_id,
-                                     uint32_t address,
-                                     uint32_t mask,
-                                     uint32_t value,
-                                     uint32_t *out)
-{
-       enum pm_ret_status ret;
-
-       if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
-                       ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
-                       ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
-                       ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
-               return PM_RET_ERROR_ACCESS;
-       }
-
-       switch (register_access_id) {
-       case CONFIG_REG_WRITE:
-               ret = pm_mmio_write(address, mask, value);
-               break;
-       case CONFIG_REG_READ:
-               ret = pm_mmio_read(address, out);
-               break;
-       default:
-               ret = PM_RET_ERROR_ARGS;
-               WARN("Unimplemented register_access call\n\r");
-               break;
-       }
-       return ret;
-}
-
-/**
- * pm_efuse_access() - To program or read efuse bits.
- *
- * This function provides access to the xilskey library to program/read
- * efuse bits.
- *
- * address_low: lower 32-bit Linear memory space address
- * address_high: higher 32-bit Linear memory space address
- *
- * value: Returned output value
- *
- * @return  Returns status, either success or error+reason
- *
- */
-enum pm_ret_status pm_efuse_access(uint32_t address_high,
-                                  uint32_t address_low,
-                                  uint32_t *value)
-{
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       /* Send request to the PMU */
-       PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
-
-       return pm_ipi_send_sync(primary_proc, payload, value, 1);
-}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
deleted file mode 100644 (file)
index 1341e7b..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PM_API_SYS_H
-#define PM_API_SYS_H
-
-#include <stdint.h>
-
-#include "pm_defs.h"
-
-enum pm_query_id {
-       PM_QID_INVALID,
-       PM_QID_CLOCK_GET_NAME,
-       PM_QID_CLOCK_GET_TOPOLOGY,
-       PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
-       PM_QID_CLOCK_GET_PARENTS,
-       PM_QID_CLOCK_GET_ATTRIBUTES,
-       PM_QID_PINCTRL_GET_NUM_PINS,
-       PM_QID_PINCTRL_GET_NUM_FUNCTIONS,
-       PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
-       PM_QID_PINCTRL_GET_FUNCTION_NAME,
-       PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
-       PM_QID_PINCTRL_GET_PIN_GROUPS,
-       PM_QID_CLOCK_GET_NUM_CLOCKS,
-       PM_QID_CLOCK_GET_MAX_DIVISOR,
-};
-
-enum pm_register_access_id {
-       CONFIG_REG_WRITE,
-       CONFIG_REG_READ,
-};
-
-/**
- * Assigning of argument values into array elements.
- */
-#define PM_PACK_PAYLOAD1(pl, arg0) {   \
-       pl[0] = (uint32_t)(arg0);       \
-}
-
-#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {     \
-       pl[1] = (uint32_t)(arg1);               \
-       PM_PACK_PAYLOAD1(pl, arg0);             \
-}
-
-#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {       \
-       pl[2] = (uint32_t)(arg2);                       \
-       PM_PACK_PAYLOAD2(pl, arg0, arg1);               \
-}
-
-#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \
-       pl[3] = (uint32_t)(arg3);                       \
-       PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);         \
-}
-
-#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {   \
-       pl[4] = (uint32_t)(arg4);                               \
-       PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);           \
-}
-
-#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {     \
-       pl[5] = (uint32_t)(arg5);                                       \
-       PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);             \
-}
-
-/**********************************************************
- * System-level API function declarations
- **********************************************************/
-enum pm_ret_status pm_req_suspend(enum pm_node_id target,
-                                 enum pm_request_ack ack,
-                                 uint32_t latency,
-                                 uint32_t state);
-
-enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
-                                  uint32_t latency,
-                                  uint32_t state,
-                                  uintptr_t address);
-
-enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
-                                     enum pm_request_ack ack);
-
-enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
-
-enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
-                                uint32_t set_address,
-                                uintptr_t address,
-                                enum pm_request_ack ack);
-
-enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
-                                       enum pm_node_id wkup_node,
-                                       uint32_t enable);
-
-enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype);
-
-/* API functions for managing PM Slaves */
-enum pm_ret_status pm_req_node(enum pm_node_id nid,
-                              uint32_t capabilities,
-                              uint32_t qos,
-                              enum pm_request_ack ack);
-
-enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
-                                     uint32_t capabilities,
-                                     uint32_t qos,
-                                     enum pm_request_ack ack);
-
-/* Miscellaneous API functions */
-enum pm_ret_status pm_get_api_version(uint32_t *version);
-enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
-                                     uint32_t *ret_buff);
-
-/* Direct-Control API functions */
-enum pm_ret_status pm_mmio_write(uintptr_t address,
-                                uint32_t mask,
-                                uint32_t value);
-enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value);
-enum pm_ret_status pm_fpga_load(uint32_t address_low,
-                               uint32_t address_high,
-                               uint32_t size,
-                               uint32_t flags);
-enum pm_ret_status pm_fpga_get_status(uint32_t *value);
-
-enum pm_ret_status pm_get_chipid(uint32_t *value);
-enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
-                                   uint32_t address_high,
-                                   uint32_t size,
-                                   uint32_t flags);
-uint32_t pm_get_shutdown_scope(void);
-enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count);
-enum pm_ret_status pm_ioctl(enum pm_node_id nid,
-                           uint32_t ioctl_id,
-                           uint32_t arg1,
-                           uint32_t arg2,
-                           uint32_t *value);
-enum pm_ret_status pm_clock_enable(uint32_t clock_id);
-enum pm_ret_status pm_clock_disable(uint32_t clock_id);
-enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
-                                    uint32_t *state);
-enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
-                                      uint32_t divider);
-enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
-                                      uint32_t *divider);
-enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
-                                   uint64_t rate);
-enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
-                                   uint64_t *rate);
-enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
-                                     uint32_t parent_index);
-enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
-                                     uint32_t *parent_index);
-void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
-                  uint32_t arg3, uint32_t *data);
-enum pm_ret_status pm_sha_hash(uint32_t address_high,
-                                   uint32_t address_low,
-                                   uint32_t size,
-                                   uint32_t flags);
-enum pm_ret_status pm_rsa_core(uint32_t address_high,
-                                   uint32_t address_low,
-                                   uint32_t size,
-                                   uint32_t flags);
-enum pm_ret_status pm_secure_image(uint32_t address_low,
-                                  uint32_t address_high,
-                                  uint32_t key_lo,
-                                  uint32_t key_hi,
-                                  uint32_t *value);
-enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
-                               uint32_t address_low,
-                               uint32_t address_high,
-                               uint32_t readback_type,
-                               uint32_t *value);
-enum pm_ret_status pm_aes_engine(uint32_t address_high,
-                                uint32_t address_low,
-                                uint32_t  *value);
-enum pm_ret_status pm_register_access(uint32_t register_access_id,
-                                     uint32_t address,
-                                     uint32_t mask,
-                                     uint32_t value,
-                                     uint32_t *out);
-enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
-                                       enum pm_pll_param param_id,
-                                       uint32_t value);
-enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
-                                       enum pm_pll_param param_id,
-                                       uint32_t *value);
-enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
-enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
-enum pm_ret_status pm_efuse_access(uint32_t address_high,
-                                  uint32_t address_low, uint32_t *value);
-enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
-                                   uint32_t *bit_mask, uint8_t len);
-enum pm_ret_status check_api_dependency(uint8_t id);
-
-#endif /* PM_API_SYS_H */
index 7217fa145975d658c10dd1e42f4b2c8699837559..f752525a281253e95bf64452766dead9cbce8cae 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -21,9 +22,9 @@
 
 #include <plat_ipi.h>
 #include <zynqmp_def.h>
-#include "pm_api_sys.h"
 #include "pm_client.h"
 #include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
 
 #define IRQ_MAX                84U
 #define NUM_GICD_ISENABLER     ((IRQ_MAX >> 5U) + 1U)
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
deleted file mode 100644 (file)
index b35859d..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-/*
- * Top-level SMC handler for ZynqMP power management calls and
- * IPI setup functions for communication with PMU.
- */
-
-#include <errno.h>
-
-#include <common/runtime_svc.h>
-#if ZYNQMP_WDT_RESTART
-#include <arch_helpers.h>
-#include <drivers/arm/gicv2.h>
-#include <lib/mmio.h>
-#include <lib/spinlock.h>
-#include <plat/common/platform.h>
-#endif
-
-#include <plat_private.h>
-#include "pm_api_sys.h"
-#include "pm_client.h"
-#include "pm_defs.h"
-#include "pm_ipi.h"
-
-/* pm_up = !0 - UP, pm_up = 0 - DOWN */
-static int32_t pm_up, ipi_irq_flag;
-
-#if ZYNQMP_WDT_RESTART
-static spinlock_t inc_lock;
-static int active_cores = 0;
-#endif
-
-/**
- * pm_context - Structure which contains data for power management
- * @api_version                version of PM API, must match with one on PMU side
- * @payload            payload array used to store received
- *                     data from ipi buffer registers
- */
-static struct {
-       uint32_t api_version;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-} pm_ctx;
-
-#if ZYNQMP_WDT_RESTART
-/**
- * trigger_wdt_restart() - Trigger warm restart event to APU cores
- *
- * This function triggers SGI for all active APU CPUs. SGI handler then
- * power down CPU and call system reset.
- */
-static void trigger_wdt_restart(void)
-{
-       uint32_t core_count = 0;
-       uint32_t core_status[3];
-       uint32_t target_cpu_list = 0;
-       int i;
-
-       for (i = 0; i < 4; i++) {
-               pm_get_node_status(NODE_APU_0 + i, core_status);
-               if (core_status[0] == 1) {
-                       core_count++;
-                       target_cpu_list |= (1 << i);
-               }
-       }
-
-       spin_lock(&inc_lock);
-       active_cores = core_count;
-       spin_unlock(&inc_lock);
-
-       INFO("Active Cores: %d\n", active_cores);
-
-       for (i = PLATFORM_CORE_COUNT - 1; i >= 0; i--) {
-               if (target_cpu_list & (1 << i)) {
-                       /* trigger SGI to active cores */
-                       plat_ic_raise_el3_sgi(ARM_IRQ_SEC_SGI_7, i);
-               }
-       }
-}
-
-/**
- * ttc_fiq_handler() - TTC Handler for timer event
- * @id         number of the highest priority pending interrupt of the type
- *             that this handler was registered for
- * @flags      security state, bit[0]
- * @handler    pointer to 'cpu_context' structure of the current CPU for the
- *             security state specified in the 'flags' parameter
- * @cookie     unused
- *
- * Function registered as INTR_TYPE_EL3 interrupt handler
- *
- * When WDT event is received in PMU, PMU needs to notify master to do cleanup
- * if required. PMU sets up timer and starts timer to overflow in zero time upon
- * WDT event. ATF handles this timer event and takes necessary action required
- * for warm restart.
- *
- * In presence of non-secure software layers (EL1/2) sets the interrupt
- * at registered entrance in GIC and informs that PMU responsed or demands
- * action.
- */
-static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
-                               void *cookie)
-{
-       INFO("BL31: Got TTC FIQ\n");
-
-       plat_ic_end_of_interrupt(id);
-
-       /* Clear TTC interrupt by reading interrupt register */
-       mmio_read_32(TTC3_INTR_REGISTER_1);
-
-       /* Disable the timer interrupts */
-       mmio_write_32(TTC3_INTR_ENABLE_1, 0);
-
-       trigger_wdt_restart();
-
-       return 0;
-}
-
-/**
- * zynqmp_sgi7_irq() - Handler for SGI7 IRQ
- * @id         number of the highest priority pending interrupt of the type
- *             that this handler was registered for
- * @flags      security state, bit[0]
- * @handler    pointer to 'cpu_context' structure of the current CPU for the
- *             security state specified in the 'flags' parameter
- * @cookie     unused
- *
- * Function registered as INTR_TYPE_EL3 interrupt handler
- *
- * On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs.
- * In response to SGI7 interrupt, each CPUs do clean up if required and last
- * running CPU calls system restart.
- */
-static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
-                                                void *handle, void *cookie)
-{
-       int i;
-       uint32_t value;
-
-       /* enter wfi and stay there */
-       INFO("Entering wfi\n");
-
-       spin_lock(&inc_lock);
-       active_cores--;
-
-       for (i = 0; i < 4; i++) {
-               mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i,
-                               0xffffffff);
-       }
-
-       dsb();
-
-       spin_unlock(&inc_lock);
-
-       if (active_cores == 0) {
-               pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value);
-               value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT;
-               pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value);
-       }
-
-       /* enter wfi and stay there */
-       while (1)
-               wfi();
-}
-
-/**
- * pm_wdt_restart_setup() - Setup warm restart interrupts
- *
- * This function sets up handler for SGI7 and TTC interrupts
- * used for warm restart.
- */
-static int pm_wdt_restart_setup(void)
-{
-       int ret;
-
-       /* register IRQ handler for SGI7 */
-       ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq);
-       if (ret) {
-               WARN("BL31: registering SGI7 interrupt failed\n");
-               goto err;
-       }
-
-       ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler);
-       if (ret)
-               WARN("BL31: registering TTC3 interrupt failed\n");
-
-err:
-       return ret;
-}
-#endif
-
-/**
- * pm_setup() - PM service setup
- *
- * @return     On success, the initialization function must return 0.
- *             Any other return value will cause the framework to ignore
- *             the service
- *
- * Initialization functions for ZynqMP power management for
- * communicaton with PMU.
- *
- * Called from sip_svc_setup initialization function with the
- * rt_svc_init signature.
- */
-int32_t pm_setup(void)
-{
-       enum pm_ret_status err;
-
-       pm_ipi_init(primary_proc);
-
-       err = pm_get_api_version(&pm_ctx.api_version);
-       if (err != PM_RET_SUCCESS) {
-               ERROR("BL31: Failed to read Platform Management API version. "
-                     "Return: %d\n", err);
-               return -EINVAL;
-       }
-       if (pm_ctx.api_version < PM_VERSION) {
-               ERROR("BL31: Platform Management API version error. Expected: "
-                     "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
-                     PM_VERSION_MINOR, pm_ctx.api_version >> 16,
-                     pm_ctx.api_version & 0xFFFFU);
-               return -EINVAL;
-       }
-
-       int32_t status = 0, ret = 0;
-#if ZYNQMP_WDT_RESTART
-       status = pm_wdt_restart_setup();
-       if (status)
-               WARN("BL31: warm-restart setup failed\n");
-#endif
-
-       if (status >= 0) {
-               INFO("BL31: PM Service Init Complete: API v%d.%d\n",
-                    PM_VERSION_MAJOR, PM_VERSION_MINOR);
-               ret = 0;
-       } else {
-               INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
-               ret = status;
-       }
-
-       pm_up = !status;
-
-       return ret;
-}
-
-/**
- * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
- * @smc_fid - Function Identifier
- * @x1 - x4 - Arguments
- * @cookie  - Unused
- * @handler - Pointer to caller's context structure
- *
- * @return  - Unused
- *
- * Determines that smc_fid is valid and supported PM SMC Function ID from the
- * list of pm_api_ids, otherwise completes the request with
- * the unknown SMC Function ID
- *
- * The SMC calls for PM service are forwarded from SIP Service SMC handler
- * function with rt_svc_handle signature
- */
-uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
-                       uint64_t x4, const void *cookie, void *handle, uint64_t flags)
-{
-       enum pm_ret_status ret;
-       uint32_t payload[PAYLOAD_ARG_CNT];
-
-       uint32_t pm_arg[5];
-       uint32_t result[PAYLOAD_ARG_CNT] = {0};
-       uint32_t api_id;
-
-       /* Handle case where PM wasn't initialized properly */
-       if (pm_up == 0)
-               SMC_RET1(handle, SMC_UNK);
-
-       pm_arg[0] = (uint32_t)x1;
-       pm_arg[1] = (uint32_t)(x1 >> 32);
-       pm_arg[2] = (uint32_t)x2;
-       pm_arg[3] = (uint32_t)(x2 >> 32);
-       pm_arg[4] = (uint32_t)x3;
-
-       api_id = smc_fid & FUNCID_NUM_MASK;
-
-       switch (api_id) {
-       /* PM API Functions */
-       case PM_SELF_SUSPEND:
-               ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
-                                     pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_REQ_SUSPEND:
-               ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
-                                    pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_REQ_WAKEUP:
-       {
-               /* Use address flag is encoded in the 1st bit of the low-word */
-               uint32_t set_addr = pm_arg[1] & 0x1U;
-               uint64_t address = (uint64_t)pm_arg[2] << 32U;
-
-               address |= pm_arg[1] & (~0x1U);
-               ret = pm_req_wakeup(pm_arg[0], set_addr, address,
-                                   pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-       }
-
-       case PM_FORCE_POWERDOWN:
-               ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_ABORT_SUSPEND:
-               ret = pm_abort_suspend(pm_arg[0]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SET_WAKEUP_SOURCE:
-               ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SYSTEM_SHUTDOWN:
-               ret = pm_system_shutdown(pm_arg[0], pm_arg[1]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_REQ_NODE:
-               ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SET_REQUIREMENT:
-               ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
-                                        pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_GET_API_VERSION:
-               if (ipi_irq_flag == 0U) {
-                       /*
-                        * Enable IPI IRQ
-                        * assume the rich OS is OK to handle callback IRQs now.
-                        * Even if we were wrong, it would not enable the IRQ in
-                        * the GIC.
-                        */
-                       pm_ipi_irq_enable(primary_proc);
-                       ipi_irq_flag = 1U;
-               }
-               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
-                        ((uint64_t)pm_ctx.api_version << 32));
-       case PM_FPGA_LOAD:
-               ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_FPGA_GET_STATUS:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_fpga_get_status(&value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-       }
-
-       case PM_SECURE_RSA_AES:
-               ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
-                                      pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_GET_CALLBACK_DATA:
-               ret = pm_get_callbackdata(result, ARRAY_SIZE(result));
-               if (ret != PM_RET_SUCCESS) {
-                       result[0] = ret;
-               }
-
-               SMC_RET2(handle,
-                        (uint64_t)result[0] | ((uint64_t)result[1] << 32),
-                        (uint64_t)result[2] | ((uint64_t)result[3] << 32));
-       case PM_IOCTL:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
-                              pm_arg[3], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-       }
-
-       case PM_QUERY_DATA:
-       {
-               uint32_t data[4] = { 0 };
-
-               pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
-                             pm_arg[3], data);
-               SMC_RET2(handle, (uint64_t)data[0]  | ((uint64_t)data[1] << 32),
-                        (uint64_t)data[2] | ((uint64_t)data[3] << 32));
-       }
-
-       case PM_CLOCK_ENABLE:
-               ret = pm_clock_enable(pm_arg[0]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_CLOCK_DISABLE:
-               ret = pm_clock_disable(pm_arg[0]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_CLOCK_GETSTATE:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_clock_getstate(pm_arg[0], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-       }
-
-       case PM_CLOCK_SETDIVIDER:
-               ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_CLOCK_GETDIVIDER:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_clock_getdivider(pm_arg[0], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
-       }
-
-       case PM_CLOCK_SETRATE:
-               ret = pm_clock_setrate(pm_arg[0],
-                      ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
-
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_CLOCK_GETRATE:
-       {
-               uint64_t value = 0;
-
-               ret = pm_clock_getrate(pm_arg[0], &value);
-               SMC_RET2(handle, (uint64_t)ret |
-                                 (((uint64_t)value & 0xFFFFFFFFU) << 32U),
-                        (value >> 32U) & 0xFFFFFFFFU);
-
-       }
-
-       case PM_CLOCK_SETPARENT:
-               ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_CLOCK_GETPARENT:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_clock_getparent(pm_arg[0], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_GET_TRUSTZONE_VERSION:
-               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
-                        ((uint64_t)ZYNQMP_TZ_VERSION << 32U));
-
-       case PM_SET_SUSPEND_MODE:
-               ret = pm_set_suspend_mode(pm_arg[0]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SECURE_SHA:
-               ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2],
-                               pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SECURE_RSA:
-               ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2],
-                                      pm_arg[3]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_SECURE_IMAGE:
-       {
-               ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
-                                     pm_arg[3], &result[0]);
-               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
-                        result[1]);
-       }
-
-       case PM_FPGA_READ:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
-                                  &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_SECURE_AES:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_PLL_SET_PARAMETER:
-               ret = pm_pll_set_parameter(pm_arg[0], pm_arg[1], pm_arg[2]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_PLL_GET_PARAMETER:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32U));
-       }
-
-       case PM_PLL_SET_MODE:
-               ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]);
-               SMC_RET1(handle, (uint64_t)ret);
-
-       case PM_PLL_GET_MODE:
-       {
-               uint32_t mode = 0U;
-
-               ret = pm_pll_get_mode(pm_arg[0], &mode);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32U));
-       }
-
-       case PM_REGISTER_ACCESS:
-       {
-               uint32_t value = 0U;
-
-               ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
-                                        pm_arg[3], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_EFUSE_ACCESS:
-       {
-               uint32_t value = 0U;
-
-#if defined(ZYNQMP_SECURE_EFUSES)
-               if (is_caller_non_secure(flags)) {
-                       SMC_RET1(handle,
-                                (((uint64_t)PM_RET_ERROR_NOT_ENABLED) << 32U) |
-                                (uint64_t)PM_RET_ERROR_ACCESS);
-               }
-#endif
-               ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
-               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
-       }
-
-       case PM_FPGA_GET_VERSION:
-       case PM_FPGA_GET_FEATURE_LIST:
-       {
-               uint32_t ret_payload[PAYLOAD_ARG_CNT];
-
-               PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK,
-                                pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
-               ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, 3U);
-               SMC_RET2(handle, (uint64_t)ret | (uint64_t)ret_payload[0] << 32U,
-                        (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32U);
-       }
-
-       case PM_FEATURE_CHECK:
-       {
-               uint32_t version = 0;
-               uint32_t bit_mask[2] = {0};
-
-               ret = pm_feature_check(pm_arg[0], &version, bit_mask,
-                                      ARRAY_SIZE(bit_mask));
-               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)version << 32U),
-                        (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32U));
-       }
-
-       default:
-               /* Send request to the PMU */
-               PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
-                                pm_arg[2], pm_arg[3], pm_arg[4]);
-               ret = pm_ipi_send_sync(primary_proc, payload, result,
-                                      PAYLOAD_ARG_CNT);
-               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
-                        (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
-       }
-}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
deleted file mode 100644 (file)
index 3c3082f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef PM_SVC_MAIN_H
-#define PM_SVC_MAIN_H
-
-#include "pm_common.h"
-
-int32_t pm_setup(void);
-uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
-                       uint64_t x4, const void *cookie, void *handle,
-                       uint64_t flags);
-#endif /* PM_SVC_MAIN_H */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.c
new file mode 100644 (file)
index 0000000..d11d6ff
--- /dev/null
@@ -0,0 +1,1811 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2023, Advanced Micro Devices Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions and communication with PMU via
+ * IPI interrupts
+ */
+
+#include <arch_helpers.h>
+#include <plat/common/platform.h>
+
+#include "pm_api_clock.h"
+#include "pm_api_ioctl.h"
+#include "pm_api_pinctrl.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
+
+#define PM_QUERY_FEATURE_BITMASK ( \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
+       (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
+       (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
+
+/**
+ * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
+ * on both the ATF and firmware
+ *
+ * @id:                EEMI API id or IOCTL id to be checked
+ * @api_id:    Dependent EEMI API
+ */
+typedef struct __attribute__((packed)) {
+       uint8_t id;
+       uint8_t api_id;
+} eemi_api_dependency;
+
+/* Dependent APIs for ATF to check their version from firmware */
+static const eemi_api_dependency api_dep_table[] = {
+       {
+               .id = PM_SELF_SUSPEND,
+               .api_id = PM_SELF_SUSPEND,
+       },
+       {
+               .id = PM_REQ_WAKEUP,
+               .api_id = PM_REQ_WAKEUP,
+       },
+       {
+               .id = PM_ABORT_SUSPEND,
+               .api_id = PM_ABORT_SUSPEND,
+       },
+       {
+               .id = PM_SET_WAKEUP_SOURCE,
+               .api_id = PM_SET_WAKEUP_SOURCE,
+       },
+       {
+               .id = PM_SYSTEM_SHUTDOWN,
+               .api_id = PM_SYSTEM_SHUTDOWN,
+       },
+       {
+               .id = PM_GET_API_VERSION,
+               .api_id = PM_GET_API_VERSION,
+       },
+       {
+               .id = PM_CLOCK_ENABLE,
+               .api_id = PM_PLL_SET_MODE,
+       },
+       {
+               .id = PM_CLOCK_ENABLE,
+               .api_id = PM_CLOCK_ENABLE,
+       },
+       {
+               .id = PM_CLOCK_DISABLE,
+               .api_id = PM_PLL_SET_MODE,
+       },
+       {
+               .id = PM_CLOCK_DISABLE,
+               .api_id = PM_CLOCK_DISABLE,
+       },
+       {
+               .id = PM_CLOCK_GETSTATE,
+               .api_id = PM_PLL_GET_MODE,
+       },
+       {
+               .id = PM_CLOCK_GETSTATE,
+               .api_id = PM_CLOCK_GETSTATE,
+       },
+       {
+               .id = PM_CLOCK_SETDIVIDER,
+               .api_id = PM_PLL_SET_PARAMETER,
+       },
+       {
+               .id = PM_CLOCK_SETDIVIDER,
+               .api_id = PM_CLOCK_SETDIVIDER,
+       },
+       {
+               .id = PM_CLOCK_GETDIVIDER,
+               .api_id = PM_PLL_GET_PARAMETER,
+       },
+       {
+               .id = PM_CLOCK_GETDIVIDER,
+               .api_id = PM_CLOCK_GETDIVIDER,
+       },
+       {
+               .id = PM_CLOCK_SETPARENT,
+               .api_id = PM_PLL_SET_PARAMETER,
+       },
+       {
+               .id = PM_CLOCK_SETPARENT,
+               .api_id = PM_CLOCK_SETPARENT,
+       },
+       {
+               .id = PM_CLOCK_GETPARENT,
+               .api_id = PM_PLL_GET_PARAMETER,
+       },
+       {
+               .id = PM_CLOCK_GETPARENT,
+               .api_id = PM_CLOCK_GETPARENT,
+       },
+       {
+               .id = PM_PLL_SET_PARAMETER,
+               .api_id = PM_PLL_SET_PARAMETER,
+       },
+       {
+               .id = PM_PLL_GET_PARAMETER,
+               .api_id = PM_PLL_GET_PARAMETER,
+       },
+       {
+               .id = PM_PLL_SET_MODE,
+               .api_id = PM_PLL_SET_MODE,
+       },
+       {
+               .id = PM_PLL_GET_MODE,
+               .api_id = PM_PLL_GET_MODE,
+       },
+       {
+               .id = PM_REGISTER_ACCESS,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = PM_REGISTER_ACCESS,
+               .api_id = PM_MMIO_READ,
+       },
+       {
+               .id = PM_FEATURE_CHECK,
+               .api_id = PM_FEATURE_CHECK,
+       },
+       {
+               .id = IOCTL_SET_TAPDELAY_BYPASS,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_SET_SGMII_MODE,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_SD_DLL_RESET,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_SET_SD_TAPDELAY,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_SET_SD_TAPDELAY,
+               .api_id = PM_MMIO_READ,
+       },
+       {
+               .id = IOCTL_SET_PLL_FRAC_DATA,
+               .api_id = PM_PLL_SET_PARAMETER,
+       },
+       {
+               .id = IOCTL_GET_PLL_FRAC_DATA,
+               .api_id = PM_PLL_GET_PARAMETER,
+       },
+       {
+               .id = IOCTL_WRITE_GGS,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_READ_GGS,
+               .api_id = PM_MMIO_READ,
+       },
+       {
+               .id = IOCTL_WRITE_PGGS,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_READ_PGGS,
+               .api_id = PM_MMIO_READ,
+       },
+       {
+               .id = IOCTL_ULPI_RESET,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_SET_BOOT_HEALTH_STATUS,
+               .api_id = PM_MMIO_WRITE,
+       },
+       {
+               .id = IOCTL_AFI,
+               .api_id = PM_MMIO_WRITE,
+       },
+};
+
+/* Expected firmware API version to ATF */
+static const uint8_t atf_expected_ver_id[] = {
+       [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
+       [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
+       [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
+       [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
+       [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
+       [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
+       [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
+       [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
+       [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
+       [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
+       [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
+       [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
+       [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
+       [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
+       [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
+       [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
+       [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
+       [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
+       [PM_MMIO_READ] = FW_API_BASE_VERSION,
+       [PM_FEATURE_CHECK] = FW_API_VERSION_2,
+};
+
+/* default shutdown/reboot scope is system(2) */
+static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
+
+/**
+ * pm_get_shutdown_scope() - Get the currently set shutdown scope
+ *
+ * @return     Shutdown scope value
+ */
+uint32_t pm_get_shutdown_scope(void)
+{
+       return pm_shutdown_scope;
+}
+
+/**
+ * pm_self_suspend() - PM call for processor to suspend itself
+ * @nid                Node id of the processor or subsystem
+ * @latency    Requested maximum wakeup latency (not supported)
+ * @state      Requested state
+ * @address    Resume address
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+                                  uint32_t latency,
+                                  uint32_t state,
+                                  uintptr_t address)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint32_t cpuid = plat_my_core_pos();
+       const struct pm_proc *proc = pm_get_proc(cpuid);
+
+       /*
+        * Do client specific suspend operations
+        * (e.g. set powerdown request bit)
+        */
+       pm_client_suspend(proc, state);
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
+                        state, address, (address >> 32));
+       return pm_ipi_send_sync(proc, payload, NULL, 0);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ *                   be suspended gracefully.
+ * @target     Node id of the targeted PU or subsystem
+ * @ack                Flag to specify whether acknowledge is requested
+ * @latency    Requested wakeup latency (not supported)
+ * @state      Requested state (not supported)
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+                                 enum pm_request_ack ack,
+                                 uint32_t latency, uint32_t state)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
+       if (ack == REQ_ACK_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ *                  or subsystem
+ * @target     Node id of the processor or subsystem to wake up
+ * @ack                Flag to specify whether acknowledge requested
+ * @set_address        Resume address presence indicator
+ *                             1 resume address specified, 0 otherwise
+ * @address    Resume address
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMU.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+                                uint32_t set_address,
+                                uintptr_t address,
+                                enum pm_request_ack ack)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint64_t encoded_address;
+
+
+       /* encode set Address into 1st bit of address */
+       encoded_address = address;
+       encoded_address |= !!set_address;
+
+       /* Send request to the PMU to perform the wake of the PU */
+       PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
+                        encoded_address >> 32, ack);
+
+       if (ack == REQ_ACK_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ *                       be powered down forcefully
+ * @target     Node id of the targeted PU or subsystem
+ * @ack                Flag to specify whether acknowledge is requested
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+                                     enum pm_request_ack ack)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
+
+       if (ack == REQ_ACK_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ *                     is to be aborted.
+ * @reason     Reason for the abort
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /*
+        * Do client specific abort suspend operations
+        * (e.g. enable interrupts and clear powerdown request bit)
+        */
+       pm_client_abort_suspend();
+       /* Send request to the PMU */
+       /* TODO: allow passing the node ID of the affected CPU */
+       PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
+                        primary_proc->node_id);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target     Node id of the targeted PU or subsystem
+ * @wkup_node  Node id of the wakeup peripheral
+ * @enable     Enable or disable the specified peripheral as wake source
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+                                       enum pm_node_id wkup_node,
+                                       uint32_t enable)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
+                        enable);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @type       Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
+ * @subtype    Scope: 0=APU-subsystem, 1=PS, 2=system
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
+               /* Setting scope for subsequent PSCI reboot or shutdown */
+               pm_shutdown_scope = subtype;
+               return PM_RET_SUCCESS;
+       }
+
+       PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
+       return pm_ipi_send_non_blocking(primary_proc, payload);
+}
+
+/* APIs for managing PM slaves: */
+
+/**
+ * pm_req_node() - PM call to request a node with specific capabilities
+ * @nid                Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos                Quality of service (not supported)
+ * @ack                Flag to specify whether acknowledge is requested
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+                              uint32_t capabilities,
+                              uint32_t qos,
+                              enum pm_request_ack ack)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
+
+       if (ack == REQ_ACK_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/**
+ * pm_set_requirement() - PM call to set requirement for PM slaves
+ * @nid                Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos                Quality of service (not supported)
+ * @ack                Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+                                     uint32_t capabilities,
+                                     uint32_t qos,
+                                     enum pm_request_ack ack)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
+                        ack);
+
+       if (ack == REQ_ACK_BLOCKING) {
+               return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+       } else {
+               return pm_ipi_send(primary_proc, payload);
+       }
+}
+
+/* Miscellaneous API functions */
+
+/**
+ * pm_get_api_version() - Get version number of PMU PM firmware
+ * @version    Returns 32-bit version number of PMU Power Management Firmware
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_api_version(uint32_t *version)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
+       return pm_ipi_send_sync(primary_proc, payload, version, 1);
+}
+
+/**
+ * pm_get_node_status() - PM call to request a node's current status
+ * @nid                Node id
+ * @ret_buff   Buffer for the return values:
+ *             [0] - Current power state of the node
+ *             [1] - Current requirements for the node (slave nodes only)
+ *             [2] - Current usage status for the node (slave nodes only)
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
+                                     uint32_t *ret_buff)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
+       return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
+}
+
+/**
+ * pm_mmio_write() - Perform write to protected mmio
+ * @address    Address to write to
+ * @mask       Mask to apply
+ * @value      Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+                                uint32_t mask,
+                                uint32_t value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_mmio_read() - Read value from protected mmio
+ * @address    Address to write to
+ * @value      Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_fpga_load() - Load the bitstream into the PL.
+ *
+ * This function provides access to the xilfpga library to load
+ * the Bit-stream into PL.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ *
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * size:       Number of 32bit words
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+                               uint32_t address_high,
+                               uint32_t size,
+                               uint32_t flags)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
+                                               size, flags);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_fpga_get_status() - Read value from fpga status register
+ * @value       Value to read
+ *
+ * This function provides access to the xilfpga library to get
+ * the fpga status
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_get_status(uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_get_chipid() - Read silicon ID registers
+ * @value       Buffer for return values. Must be large enough
+ *             to hold 8 bytes.
+ *
+ * @return      Returns silicon ID registers
+ */
+enum pm_ret_status pm_get_chipid(uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
+       return pm_ipi_send_sync(primary_proc, payload, value, 2);
+}
+
+/**
+ * pm_secure_rsaaes() - Load the secure images.
+ *
+ * This function provides access to the xilsecure library to load
+ * the authenticated, encrypted, and authenicated/encrypted images.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ *
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * size:       Number of 32bit words
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
+                               uint32_t address_high,
+                               uint32_t size,
+                               uint32_t flags)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
+                        size, flags);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_aes_engine() - Aes data blob encryption/decryption
+ * This function provides access to the xilsecure library to
+ * encrypt/decrypt data blobs.
+ *
+ * address_low: lower 32-bit address of the AesParams structure
+ *
+ * address_high: higher 32-bit address of the AesParams structure
+ *
+ * value:        Returned output value
+ *
+ * @return       Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_aes_engine(uint32_t address_high,
+                                uint32_t address_low,
+                                uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_get_callbackdata() - Read from IPI response buffer
+ * @data - array of PAYLOAD_ARG_CNT elements
+ *
+ * Read value from ipi buffer response buffer.
+ * @return      Returns status, either success or error
+ */
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count)
+{
+       enum pm_ret_status ret = PM_RET_SUCCESS;
+       /* Return if interrupt is not from PMU */
+       if (!pm_ipi_irq_status(primary_proc)) {
+               return ret;
+       }
+
+       ret = pm_ipi_buff_read_callb(data, count);
+       pm_ipi_irq_clear(primary_proc);
+       return ret;
+}
+
+/**
+ * pm_ioctl() -  PM IOCTL API for device control and configs
+ * @node_id    Node ID of the device
+ * @ioctl_id   ID of the requested IOCTL
+ * @arg1       Argument 1 to requested IOCTL call
+ * @arg2       Argument 2 to requested IOCTL call
+ * @out                Returned output value
+ *
+ * This function calls IOCTL to firmware for device control and configuration.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+                           uint32_t ioctl_id,
+                           uint32_t arg1,
+                           uint32_t arg2,
+                           uint32_t *value)
+{
+       return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
+}
+
+/**
+ * fw_api_version() - Returns API version implemented in firmware
+ * @api_id     API ID to check
+ * @version    Returned supported API version
+ * @len                Number of words to be returned
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
+                                        uint32_t len)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
+       return pm_ipi_send_sync(primary_proc, payload, version, len);
+}
+
+/**
+ * check_api_dependency() -  API to check dependent EEMI API version
+ * @id         EEMI API ID to check
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status check_api_dependency(uint8_t id)
+{
+       uint8_t i;
+       uint32_t version;
+       int ret;
+
+       for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
+               if (api_dep_table[i].id == id) {
+                       if (api_dep_table[i].api_id == 0U) {
+                               break;
+                       }
+
+                       ret = fw_api_version(api_dep_table[i].api_id,
+                                            &version, 1);
+                       if (ret != PM_RET_SUCCESS) {
+                               return ret;
+                       }
+
+                       /* Check if fw version matches ATF expected version */
+                       if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
+                               return PM_RET_ERROR_NOTSUPPORTED;
+                       }
+               }
+       }
+
+       return PM_RET_SUCCESS;
+}
+
+/**
+ * feature_check_atf() - These are API's completely implemented in ATF
+ * @api_id     API ID to check
+ * @version    Returned supported API version
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
+                                           uint32_t *bit_mask)
+{
+       switch (api_id) {
+       case PM_QUERY_DATA:
+               *version = TFA_API_QUERY_DATA_VERSION;
+               bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
+               bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
+               return PM_RET_SUCCESS;
+       case PM_GET_CALLBACK_DATA:
+       case PM_GET_TRUSTZONE_VERSION:
+       case PM_SET_SUSPEND_MODE:
+               *version = ATF_API_BASE_VERSION;
+               return PM_RET_SUCCESS;
+       default:
+               return PM_RET_ERROR_NO_FEATURE;
+       }
+}
+
+/**
+ * get_atf_version_for_partial_apis() - Return ATF version for partially
+ * implemented APIs
+ * @api_id     API ID to check
+ * @version    Returned supported API version
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
+                                                          uint32_t *version)
+{
+       switch (api_id) {
+       case PM_SELF_SUSPEND:
+       case PM_REQ_WAKEUP:
+       case PM_ABORT_SUSPEND:
+       case PM_SET_WAKEUP_SOURCE:
+       case PM_SYSTEM_SHUTDOWN:
+       case PM_GET_API_VERSION:
+       case PM_CLOCK_ENABLE:
+       case PM_CLOCK_DISABLE:
+       case PM_CLOCK_GETSTATE:
+       case PM_CLOCK_SETDIVIDER:
+       case PM_CLOCK_GETDIVIDER:
+       case PM_CLOCK_SETPARENT:
+       case PM_CLOCK_GETPARENT:
+       case PM_PLL_SET_PARAMETER:
+       case PM_PLL_GET_PARAMETER:
+       case PM_PLL_SET_MODE:
+       case PM_PLL_GET_MODE:
+       case PM_REGISTER_ACCESS:
+               *version = ATF_API_BASE_VERSION;
+               return PM_RET_SUCCESS;
+       case PM_FEATURE_CHECK:
+               *version = FW_API_VERSION_2;
+               return PM_RET_SUCCESS;
+       default:
+               return PM_RET_ERROR_ARGS;
+       }
+}
+
+/**
+ * feature_check_partial() - These are API's partially implemented in
+ * ATF and firmware both
+ * @api_id     API ID to check
+ * @version    Returned supported API version
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status feature_check_partial(uint32_t api_id,
+                                               uint32_t *version)
+{
+       uint32_t status;
+
+       switch (api_id) {
+       case PM_SELF_SUSPEND:
+       case PM_REQ_WAKEUP:
+       case PM_ABORT_SUSPEND:
+       case PM_SET_WAKEUP_SOURCE:
+       case PM_SYSTEM_SHUTDOWN:
+       case PM_GET_API_VERSION:
+       case PM_CLOCK_ENABLE:
+       case PM_CLOCK_DISABLE:
+       case PM_CLOCK_GETSTATE:
+       case PM_CLOCK_SETDIVIDER:
+       case PM_CLOCK_GETDIVIDER:
+       case PM_CLOCK_SETPARENT:
+       case PM_CLOCK_GETPARENT:
+       case PM_PLL_SET_PARAMETER:
+       case PM_PLL_GET_PARAMETER:
+       case PM_PLL_SET_MODE:
+       case PM_PLL_GET_MODE:
+       case PM_REGISTER_ACCESS:
+       case PM_FEATURE_CHECK:
+               status = check_api_dependency(api_id);
+               if (status != PM_RET_SUCCESS) {
+                       return status;
+               }
+               return get_atf_version_for_partial_apis(api_id, version);
+       default:
+               return PM_RET_ERROR_NO_FEATURE;
+       }
+}
+
+/**
+ * pm_feature_check() - Returns the supported API version if supported
+ * @api_id     API ID to check
+ * @version    Returned supported API version
+ * @bit_mask   Returned supported IOCTL id version
+ * @len                Number of bytes to be returned in bit_mask variable
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+                                   uint32_t *bit_mask, uint8_t len)
+{
+       uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
+       uint32_t status;
+
+       /* Get API version implemented in ATF */
+       status = feature_check_atf(api_id, version, bit_mask);
+       if (status != PM_RET_ERROR_NO_FEATURE) {
+               return status;
+       }
+
+       /* Get API version implemented by firmware and ATF both */
+       status = feature_check_partial(api_id, version);
+       if (status != PM_RET_ERROR_NO_FEATURE) {
+               return status;
+       }
+
+       /* Get API version implemented by firmware */
+       status = fw_api_version(api_id, ret_payload, 3);
+       /* IOCTL call may return failure whose ID is not implemented in
+        * firmware but implemented in ATF
+        */
+       if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
+               return status;
+       }
+
+       *version = ret_payload[0];
+
+       /* Update IOCTL bit mask which are implemented in ATF */
+       if ((api_id == PM_IOCTL) || (api_id == PM_GET_OP_CHARACTERISTIC)) {
+               if (len < 2) {
+                       return PM_RET_ERROR_ARGS;
+               }
+               bit_mask[0] = ret_payload[1];
+               bit_mask[1] = ret_payload[2];
+               if (api_id == PM_IOCTL) {
+                       /* Get IOCTL's implemented by ATF */
+                       status = atf_ioctl_bitmask(bit_mask);
+               }
+       } else {
+               /* Requires for MISRA */
+       }
+
+       return status;
+}
+
+/**
+ * pm_clock_get_max_divisor - PM call to get max divisor
+ * @clock_id   Clock ID
+ * @div_type   Divisor ID (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div    Maximum supported divisor
+ *
+ * This function is used by master to get maximum supported value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
+                                                  uint8_t div_type,
+                                                  uint32_t *max_div)
+{
+       return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
+}
+
+/**
+ * pm_clock_get_num_clocks - PM call to request number of clocks
+ * @nclockss: Number of clocks
+ *
+ * This function is used by master to get number of clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
+{
+       return pm_api_clock_get_num_clocks(nclocks);
+}
+
+/**
+ * pm_clock_get_name() - PM call to request a clock's name
+ * @clock_id   Clock ID
+ * @name       Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ */
+static void pm_clock_get_name(uint32_t clock_id, char *name)
+{
+       pm_api_clock_get_name(clock_id, name);
+}
+
+/**
+ * pm_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id   Clock ID
+ * @index      Topology index for next toplogy node
+ * @topology   Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
+                                               uint32_t index,
+                                               uint32_t *topology)
+{
+       return pm_api_clock_get_topology(clock_id, index, topology);
+}
+
+/**
+ * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
+ *                              parameters for fixed clock
+ * @clock_id   Clock ID
+ * @mul                Multiplication value
+ * @div                Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
+                                                         uint32_t *mul,
+                                                         uint32_t *div)
+{
+       return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
+}
+
+/**
+ * pm_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id   Clock ID
+ * @index      Index of next parent
+ * @parents    Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
+                                              uint32_t index,
+                                              uint32_t *parents)
+{
+       return pm_api_clock_get_parents(clock_id, index, parents);
+}
+
+/**
+ * pm_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id   Clock ID
+ * @attr       Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return     Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
+                                                 uint32_t *attr)
+{
+       return pm_api_clock_get_attributes(clock_id, attr);
+}
+
+/**
+ * pm_clock_gate() - Configure clock gate
+ * @clock_id   Id of the clock to be configured
+ * @enable     Flag 0=disable (gate the clock), !0=enable (activate the clock)
+ *
+ * @return     Error if an argument is not valid or status as returned by the
+ *             PM controller (PMU)
+ */
+static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
+                                       uint8_t enable)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       enum pm_ret_status status;
+       enum pm_api_id api_id;
+
+       /* Check if clock ID is valid and return an error if it is not */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       if (enable) {
+               api_id = PM_CLOCK_ENABLE;
+       } else {
+               api_id = PM_CLOCK_DISABLE;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD2(payload, api_id, clock_id);
+       status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+
+       /* If action fails due to the lack of permissions filter the error */
+       if (status == PM_RET_ERROR_ACCESS) {
+               status = PM_RET_SUCCESS;
+       }
+
+       return status;
+}
+
+/**
+ * pm_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * @return:    Error if an argument is not valid or status as returned by the
+ *             pm_clock_gate
+ */
+enum pm_ret_status pm_clock_enable(uint32_t clock_id)
+{
+       struct pm_pll *pll;
+
+       /* First try to handle it as a PLL */
+       pll = pm_clock_get_pll(clock_id);
+       if (pll) {
+               return pm_clock_pll_enable(pll);
+       }
+
+       /* It's an on-chip clock, PMU should configure clock's gate */
+       return pm_clock_gate(clock_id, 1);
+}
+
+/**
+ * pm_clock_disable - Disable the clock for given id
+ * @clock_id: Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * @return:    Error if an argument is not valid or status as returned by the
+ *             pm_clock_gate
+ */
+enum pm_ret_status pm_clock_disable(uint32_t clock_id)
+{
+       struct pm_pll *pll;
+
+       /* First try to handle it as a PLL */
+       pll = pm_clock_get_pll(clock_id);
+       if (pll) {
+               return pm_clock_pll_disable(pll);
+       }
+
+       /* It's an on-chip clock, PMU should configure clock's gate */
+       return pm_clock_gate(clock_id, 0);
+}
+
+/**
+ * pm_clock_getstate - Get the clock state for given id
+ * @clock_id: Id of the clock to be queried
+ * @state: 1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
+                                    uint32_t *state)
+{
+       struct pm_pll *pll;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       enum pm_ret_status status;
+
+       /* First try to handle it as a PLL */
+       pll = pm_clock_get_pll(clock_id);
+       if (pll)
+               return pm_clock_pll_get_state(pll, state);
+
+       /* Check if clock ID is a valid on-chip clock */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
+       return pm_ipi_send_sync(primary_proc, payload, state, 1);
+}
+
+/**
+ * pm_clock_setdivider - Set the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
+                                      uint32_t divider)
+{
+       enum pm_ret_status status;
+       enum pm_node_id nid;
+       enum pm_clock_div_id div_id;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       const uint32_t div0 = 0xFFFF0000;
+       const uint32_t div1 = 0x0000FFFF;
+       uint32_t val;
+
+       /* Get PLL node ID using PLL clock ID */
+       status = pm_clock_get_pll_node_id(clock_id, &nid);
+       if (status == PM_RET_SUCCESS) {
+               return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+       }
+
+       /* Check if clock ID is a valid on-chip clock */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       if (div0 == (divider & div0)) {
+               div_id = PM_CLOCK_DIV0_ID;
+               val = divider & ~div0;
+       } else if (div1 == (divider & div1)) {
+               div_id = PM_CLOCK_DIV1_ID;
+               val = (divider & ~div1) >> 16;
+       } else {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_clock_getdivider - Get the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
+                                      uint32_t *divider)
+{
+       enum pm_ret_status status;
+       enum pm_node_id nid;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       uint32_t val;
+
+       /* Get PLL node ID using PLL clock ID */
+       status = pm_clock_get_pll_node_id(clock_id, &nid);
+       if (status == PM_RET_SUCCESS) {
+               return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
+       }
+
+       /* Check if clock ID is a valid on-chip clock */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
+               /* Send request to the PMU to get div0 */
+               PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
+                                PM_CLOCK_DIV0_ID);
+               status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
+               if (status != PM_RET_SUCCESS) {
+                       return status;
+               }
+               *divider = val;
+       }
+
+       if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
+               /* Send request to the PMU to get div1 */
+               PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
+                                PM_CLOCK_DIV1_ID);
+               status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
+               if (status != PM_RET_SUCCESS) {
+                       return status;
+               }
+               *divider |= val << 16;
+       }
+
+       return status;
+}
+
+/**
+ * pm_clock_setrate - Set the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
+                                   uint64_t rate)
+{
+       return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_clock_getrate - Get the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
+                                   uint64_t *rate)
+{
+       return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_clock_setparent - Set the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_index: Index of the parent clock into clock's parents array
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
+                                     uint32_t parent_index)
+{
+       struct pm_pll *pll;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       enum pm_ret_status status;
+
+       /* First try to handle it as a PLL */
+       pll = pm_clock_get_pll_by_related_clk(clock_id);
+       if (pll) {
+               return pm_clock_pll_set_parent(pll, clock_id, parent_index);
+       }
+
+       /* Check if clock ID is a valid on-chip clock */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_clock_getparent - Get the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_index: parent index
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
+                                     uint32_t *parent_index)
+{
+       struct pm_pll *pll;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+       enum pm_ret_status status;
+
+       /* First try to handle it as a PLL */
+       pll = pm_clock_get_pll_by_related_clk(clock_id);
+       if (pll) {
+               return pm_clock_pll_get_parent(pll, clock_id, parent_index);
+       }
+
+       /* Check if clock ID is a valid on-chip clock */
+       status = pm_clock_id_is_valid(clock_id);
+       if (status != PM_RET_SUCCESS) {
+               return status;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
+       return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
+}
+
+/**
+ * pm_pinctrl_get_num_pins - PM call to request number of pins
+ * @npins: Number of pins
+ *
+ * This function is used by master to get number of pins
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
+{
+       return pm_api_pinctrl_get_num_pins(npins);
+}
+
+/**
+ * pm_pinctrl_get_num_functions - PM call to request number of functions
+ * @nfuncs: Number of functions
+ *
+ * This function is used by master to get number of functions
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
+{
+       return pm_api_pinctrl_get_num_functions(nfuncs);
+}
+
+/**
+ * pm_pinctrl_get_num_function_groups - PM call to request number of
+ *                                     function groups
+ * @fid: Id of function
+ * @ngroups: Number of function groups
+ *
+ * This function is used by master to get number of function groups specified
+ * by given function Id
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
+                                                            uint32_t *ngroups)
+{
+       return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
+}
+
+/**
+ * pm_pinctrl_get_function_name - PM call to request function name
+ * @fid: Id of function
+ * @name: Name of function
+ *
+ * This function is used by master to get name of function specified
+ * by given function Id
+ */
+static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
+{
+       pm_api_pinctrl_get_function_name(fid, name);
+}
+
+/**
+ * pm_pinctrl_get_function_groups - PM call to request function groups
+ * @fid: Id of function
+ * @index: Index of next function groups
+ * @groups: Function groups
+ *
+ * This function is used by master to get function groups specified
+ * by given function Id. This API will return 6 function groups with
+ * a single response. To get other function groups, master should call
+ * same API in loop with new function groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return function groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * function groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
+                                                        uint32_t index,
+                                                        uint16_t *groups)
+{
+       return pm_api_pinctrl_get_function_groups(fid, index, groups);
+}
+
+/**
+ * pm_pinctrl_get_pin_groups - PM call to request pin groups
+ * @pin_id: Id of pin
+ * @index: Index of next pin groups
+ * @groups: pin groups
+ *
+ * This function is used by master to get pin groups specified
+ * by given pin Id. This API will return 6 pin groups with
+ * a single response. To get other pin groups, master should call
+ * same API in loop with new pin groups index till error is returned.
+ *
+ * E.g First call should have index 0 which will return pin groups
+ * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
+ * pin groups 6, 7, 8, 9, 10 and 11 and so on.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
+                                                   uint32_t index,
+                                                   uint16_t *groups)
+{
+       return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
+}
+
+/**
+ * pm_query_data() -  PM API for querying firmware data
+ * @arg1       Argument 1 to requested IOCTL call
+ * @arg2       Argument 2 to requested IOCTL call
+ * @arg3       Argument 3 to requested IOCTL call
+ * @arg4       Argument 4 to requested IOCTL call
+ * @data       Returned output data
+ *
+ * This function returns requested data.
+ */
+void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
+                  uint32_t arg3, uint32_t *data)
+{
+       switch (qid) {
+       case PM_QID_CLOCK_GET_NAME:
+               pm_clock_get_name(arg1, (char *)data);
+               break;
+       case PM_QID_CLOCK_GET_TOPOLOGY:
+               data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
+               break;
+       case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
+               data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
+                                                         &data[2]);
+               break;
+       case PM_QID_CLOCK_GET_PARENTS:
+               data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
+               break;
+       case PM_QID_CLOCK_GET_ATTRIBUTES:
+               data[0] = pm_clock_get_attributes(arg1, &data[1]);
+               break;
+       case PM_QID_PINCTRL_GET_NUM_PINS:
+               data[0] = pm_pinctrl_get_num_pins(&data[1]);
+               break;
+       case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
+               data[0] = pm_pinctrl_get_num_functions(&data[1]);
+               break;
+       case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
+               data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
+               break;
+       case PM_QID_PINCTRL_GET_FUNCTION_NAME:
+               pm_pinctrl_get_function_name(arg1, (char *)data);
+               break;
+       case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
+               data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
+                                                        (uint16_t *)&data[1]);
+               break;
+       case PM_QID_PINCTRL_GET_PIN_GROUPS:
+               data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
+                                                   (uint16_t *)&data[1]);
+               break;
+       case PM_QID_CLOCK_GET_NUM_CLOCKS:
+               data[0] = pm_clock_get_num_clocks(&data[1]);
+               break;
+
+       case PM_QID_CLOCK_GET_MAX_DIVISOR:
+               data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
+               break;
+       default:
+               data[0] = PM_RET_ERROR_ARGS;
+               WARN("Unimplemented query service call: 0x%x\n", qid);
+               break;
+       }
+}
+
+enum pm_ret_status pm_sha_hash(uint32_t address_high,
+                                   uint32_t address_low,
+                                   uint32_t size,
+                                   uint32_t flags)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
+                                size, flags);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+enum pm_ret_status pm_rsa_core(uint32_t address_high,
+                                   uint32_t address_low,
+                                   uint32_t size,
+                                   uint32_t flags)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
+                                size, flags);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+enum pm_ret_status pm_secure_image(uint32_t address_low,
+                                  uint32_t address_high,
+                                  uint32_t key_lo,
+                                  uint32_t key_hi,
+                                  uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
+                        key_hi, key_lo);
+       return pm_ipi_send_sync(primary_proc, payload, value, 2);
+}
+
+/**
+ * pm_fpga_read - Perform the fpga configuration readback
+ *
+ * @reg_numframes: Configuration register offset (or) Number of frames to read
+ * @address_low: lower 32-bit Linear memory space address
+ * @address_high: higher 32-bit Linear memory space address
+ * @readback_type: Type of fpga readback operation
+ *                0 -- Configuration Register readback
+ *                1 -- Configuration Data readback
+ * @value:     Value to read
+ *
+ * This function provides access to the xilfpga library to read
+ * the PL configuration.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
+                               uint32_t address_low,
+                               uint32_t address_high,
+                               uint32_t readback_type,
+                               uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
+                        address_high, readback_type);
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/*
+ * pm_pll_set_parameter() - Set the PLL parameter value
+ * @nid                Node id of the target PLL
+ * @param_id   ID of the PLL parameter
+ * @value      Parameter value to be set
+ *
+ * Setting the parameter will have physical effect once the PLL mode is set to
+ * integer or fractional.
+ *
+ * @return     Error if an argument is not valid or status as returned by the
+ *             PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
+                                       enum pm_pll_param param_id,
+                                       uint32_t value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Check if given node ID is a PLL node */
+       if (nid < NODE_APLL || nid > NODE_IOPLL) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Check if parameter ID is valid and return an error if it's not */
+       if (param_id >= PM_PLL_PARAM_MAX) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_parameter() - Get the PLL parameter value
+ * @nid                Node id of the target PLL
+ * @param_id   ID of the PLL parameter
+ * @value      Location to store the parameter value
+ *
+ * @return     Error if an argument is not valid or status as returned by the
+ *             PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
+                                       enum pm_pll_param param_id,
+                                       uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Check if given node ID is a PLL node */
+       if (nid < NODE_APLL || nid > NODE_IOPLL) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Check if parameter ID is valid and return an error if it's not */
+       if (param_id >= PM_PLL_PARAM_MAX) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
+
+/**
+ * pm_pll_set_mode() - Set the PLL mode
+ * @nid                Node id of the target PLL
+ * @mode       PLL mode to be set
+ *
+ * If reset mode is set the PM controller will first bypass the PLL and then
+ * assert the reset. If integer or fractional mode is set the PM controller will
+ * ensure that the complete PLL programming sequence is satisfied. After this
+ * function returns success the PLL is locked and its bypass is deasserted.
+ *
+ * @return     Error if an argument is not valid or status as returned by the
+ *             PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Check if given node ID is a PLL node */
+       if (nid < NODE_APLL || nid > NODE_IOPLL) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Check if PLL mode is valid */
+       if (mode >= PM_PLL_MODE_MAX) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
+       return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
+/**
+ * pm_pll_get_mode() - Get the PLL mode
+ * @nid                Node id of the target PLL
+ * @mode       Location to store the mode of the PLL
+ *
+ * @return     Error if an argument is not valid or status as returned by the
+ *             PM controller (PMU)
+ */
+enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Check if given node ID is a PLL node */
+       if (nid < NODE_APLL || nid > NODE_IOPLL) {
+               return PM_RET_ERROR_ARGS;
+       }
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
+       return pm_ipi_send_sync(primary_proc, payload, mode, 1);
+}
+
+/**
+ * pm_register_access() -  PM API for register read/write access data
+ *
+ * @register_access_id Register_access_id which says register read/write
+ *
+ * @address            Address of the register to be accessed
+ *
+ * @mask               Mask value to be used while writing value
+ *
+ * @value              Value to be written to register
+ *
+ * @out                        Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return     Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_access(uint32_t register_access_id,
+                                     uint32_t address,
+                                     uint32_t mask,
+                                     uint32_t value,
+                                     uint32_t *out)
+{
+       enum pm_ret_status ret;
+
+       if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
+                       ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
+                       ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
+                       ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
+               return PM_RET_ERROR_ACCESS;
+       }
+
+       switch (register_access_id) {
+       case CONFIG_REG_WRITE:
+               ret = pm_mmio_write(address, mask, value);
+               break;
+       case CONFIG_REG_READ:
+               ret = pm_mmio_read(address, out);
+               break;
+       default:
+               ret = PM_RET_ERROR_ARGS;
+               WARN("Unimplemented register_access call\n\r");
+               break;
+       }
+       return ret;
+}
+
+/**
+ * pm_efuse_access() - To program or read efuse bits.
+ *
+ * This function provides access to the xilskey library to program/read
+ * efuse bits.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * value: Returned output value
+ *
+ * @return  Returns status, either success or error+reason
+ *
+ */
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+                                  uint32_t address_low,
+                                  uint32_t *value)
+{
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       /* Send request to the PMU */
+       PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
+
+       return pm_ipi_send_sync(primary_proc, payload, value, 1);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_api_sys.h
new file mode 100644 (file)
index 0000000..7d26554
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ZYNQMP_PM_API_SYS_H
+#define ZYNQMP_PM_API_SYS_H
+
+#include <stdint.h>
+
+#include "pm_defs.h"
+
+enum pm_query_id {
+       PM_QID_INVALID,
+       PM_QID_CLOCK_GET_NAME,
+       PM_QID_CLOCK_GET_TOPOLOGY,
+       PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+       PM_QID_CLOCK_GET_PARENTS,
+       PM_QID_CLOCK_GET_ATTRIBUTES,
+       PM_QID_PINCTRL_GET_NUM_PINS,
+       PM_QID_PINCTRL_GET_NUM_FUNCTIONS,
+       PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS,
+       PM_QID_PINCTRL_GET_FUNCTION_NAME,
+       PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
+       PM_QID_PINCTRL_GET_PIN_GROUPS,
+       PM_QID_CLOCK_GET_NUM_CLOCKS,
+       PM_QID_CLOCK_GET_MAX_DIVISOR,
+};
+
+enum pm_register_access_id {
+       CONFIG_REG_WRITE,
+       CONFIG_REG_READ,
+};
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, arg0) {   \
+       pl[0] = (uint32_t)(arg0);       \
+}
+
+#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {     \
+       pl[1] = (uint32_t)(arg1);               \
+       PM_PACK_PAYLOAD1(pl, arg0);             \
+}
+
+#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {       \
+       pl[2] = (uint32_t)(arg2);                       \
+       PM_PACK_PAYLOAD2(pl, arg0, arg1);               \
+}
+
+#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \
+       pl[3] = (uint32_t)(arg3);                       \
+       PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);         \
+}
+
+#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {   \
+       pl[4] = (uint32_t)(arg4);                               \
+       PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);           \
+}
+
+#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {     \
+       pl[5] = (uint32_t)(arg5);                                       \
+       PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);             \
+}
+
+/**********************************************************
+ * System-level API function declarations
+ **********************************************************/
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+                                 enum pm_request_ack ack,
+                                 uint32_t latency,
+                                 uint32_t state);
+
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+                                  uint32_t latency,
+                                  uint32_t state,
+                                  uintptr_t address);
+
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+                                     enum pm_request_ack ack);
+
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
+
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+                                uint32_t set_address,
+                                uintptr_t address,
+                                enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+                                       enum pm_node_id wkup_node,
+                                       uint32_t enable);
+
+enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype);
+
+/* API functions for managing PM Slaves */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+                              uint32_t capabilities,
+                              uint32_t qos,
+                              enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+                                     uint32_t capabilities,
+                                     uint32_t qos,
+                                     enum pm_request_ack ack);
+
+/* Miscellaneous API functions */
+enum pm_ret_status pm_get_api_version(uint32_t *version);
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
+                                     uint32_t *ret_buff);
+
+/* Direct-Control API functions */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+                                uint32_t mask,
+                                uint32_t value);
+enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value);
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+                               uint32_t address_high,
+                               uint32_t size,
+                               uint32_t flags);
+enum pm_ret_status pm_fpga_get_status(uint32_t *value);
+
+enum pm_ret_status pm_get_chipid(uint32_t *value);
+enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
+                                   uint32_t address_high,
+                                   uint32_t size,
+                                   uint32_t flags);
+uint32_t pm_get_shutdown_scope(void);
+enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count);
+enum pm_ret_status pm_ioctl(enum pm_node_id nid,
+                           uint32_t ioctl_id,
+                           uint32_t arg1,
+                           uint32_t arg2,
+                           uint32_t *value);
+enum pm_ret_status pm_clock_enable(uint32_t clock_id);
+enum pm_ret_status pm_clock_disable(uint32_t clock_id);
+enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
+                                    uint32_t *state);
+enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
+                                      uint32_t divider);
+enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
+                                      uint32_t *divider);
+enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
+                                   uint64_t rate);
+enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
+                                   uint64_t *rate);
+enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
+                                     uint32_t parent_index);
+enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
+                                     uint32_t *parent_index);
+void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
+                  uint32_t arg3, uint32_t *data);
+enum pm_ret_status pm_sha_hash(uint32_t address_high,
+                                   uint32_t address_low,
+                                   uint32_t size,
+                                   uint32_t flags);
+enum pm_ret_status pm_rsa_core(uint32_t address_high,
+                                   uint32_t address_low,
+                                   uint32_t size,
+                                   uint32_t flags);
+enum pm_ret_status pm_secure_image(uint32_t address_low,
+                                  uint32_t address_high,
+                                  uint32_t key_lo,
+                                  uint32_t key_hi,
+                                  uint32_t *value);
+enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
+                               uint32_t address_low,
+                               uint32_t address_high,
+                               uint32_t readback_type,
+                               uint32_t *value);
+enum pm_ret_status pm_aes_engine(uint32_t address_high,
+                                uint32_t address_low,
+                                uint32_t  *value);
+enum pm_ret_status pm_register_access(uint32_t register_access_id,
+                                     uint32_t address,
+                                     uint32_t mask,
+                                     uint32_t value,
+                                     uint32_t *out);
+enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
+                                       enum pm_pll_param param_id,
+                                       uint32_t value);
+enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
+                                       enum pm_pll_param param_id,
+                                       uint32_t *value);
+enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
+enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode);
+enum pm_ret_status pm_efuse_access(uint32_t address_high,
+                                  uint32_t address_low, uint32_t *value);
+enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
+                                   uint32_t *bit_mask, uint8_t len);
+enum pm_ret_status check_api_dependency(uint8_t id);
+
+#endif /* ZYNQMP_PM_API_SYS_H */
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.c
new file mode 100644 (file)
index 0000000..b54936e
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * Top-level SMC handler for ZynqMP power management calls and
+ * IPI setup functions for communication with PMU.
+ */
+
+#include <errno.h>
+
+#include <common/runtime_svc.h>
+#if ZYNQMP_WDT_RESTART
+#include <arch_helpers.h>
+#include <drivers/arm/gicv2.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+#include <plat/common/platform.h>
+#endif
+
+#include <plat_private.h>
+#include "pm_client.h"
+#include "pm_defs.h"
+#include "pm_ipi.h"
+#include "zynqmp_pm_api_sys.h"
+
+/* pm_up = !0 - UP, pm_up = 0 - DOWN */
+static int32_t pm_up, ipi_irq_flag;
+
+#if ZYNQMP_WDT_RESTART
+static spinlock_t inc_lock;
+static int active_cores = 0;
+#endif
+
+/**
+ * pm_context - Structure which contains data for power management
+ * @api_version                version of PM API, must match with one on PMU side
+ * @payload            payload array used to store received
+ *                     data from ipi buffer registers
+ */
+static struct {
+       uint32_t api_version;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+} pm_ctx;
+
+#if ZYNQMP_WDT_RESTART
+/**
+ * trigger_wdt_restart() - Trigger warm restart event to APU cores
+ *
+ * This function triggers SGI for all active APU CPUs. SGI handler then
+ * power down CPU and call system reset.
+ */
+static void trigger_wdt_restart(void)
+{
+       uint32_t core_count = 0;
+       uint32_t core_status[3];
+       uint32_t target_cpu_list = 0;
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               pm_get_node_status(NODE_APU_0 + i, core_status);
+               if (core_status[0] == 1) {
+                       core_count++;
+                       target_cpu_list |= (1 << i);
+               }
+       }
+
+       spin_lock(&inc_lock);
+       active_cores = core_count;
+       spin_unlock(&inc_lock);
+
+       INFO("Active Cores: %d\n", active_cores);
+
+       for (i = PLATFORM_CORE_COUNT - 1; i >= 0; i--) {
+               if (target_cpu_list & (1 << i)) {
+                       /* trigger SGI to active cores */
+                       plat_ic_raise_el3_sgi(ARM_IRQ_SEC_SGI_7, i);
+               }
+       }
+}
+
+/**
+ * ttc_fiq_handler() - TTC Handler for timer event
+ * @id         number of the highest priority pending interrupt of the type
+ *             that this handler was registered for
+ * @flags      security state, bit[0]
+ * @handler    pointer to 'cpu_context' structure of the current CPU for the
+ *             security state specified in the 'flags' parameter
+ * @cookie     unused
+ *
+ * Function registered as INTR_TYPE_EL3 interrupt handler
+ *
+ * When WDT event is received in PMU, PMU needs to notify master to do cleanup
+ * if required. PMU sets up timer and starts timer to overflow in zero time upon
+ * WDT event. ATF handles this timer event and takes necessary action required
+ * for warm restart.
+ *
+ * In presence of non-secure software layers (EL1/2) sets the interrupt
+ * at registered entrance in GIC and informs that PMU responsed or demands
+ * action.
+ */
+static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
+                               void *cookie)
+{
+       INFO("BL31: Got TTC FIQ\n");
+
+       plat_ic_end_of_interrupt(id);
+
+       /* Clear TTC interrupt by reading interrupt register */
+       mmio_read_32(TTC3_INTR_REGISTER_1);
+
+       /* Disable the timer interrupts */
+       mmio_write_32(TTC3_INTR_ENABLE_1, 0);
+
+       trigger_wdt_restart();
+
+       return 0;
+}
+
+/**
+ * zynqmp_sgi7_irq() - Handler for SGI7 IRQ
+ * @id         number of the highest priority pending interrupt of the type
+ *             that this handler was registered for
+ * @flags      security state, bit[0]
+ * @handler    pointer to 'cpu_context' structure of the current CPU for the
+ *             security state specified in the 'flags' parameter
+ * @cookie     unused
+ *
+ * Function registered as INTR_TYPE_EL3 interrupt handler
+ *
+ * On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs.
+ * In response to SGI7 interrupt, each CPUs do clean up if required and last
+ * running CPU calls system restart.
+ */
+static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
+                                                void *handle, void *cookie)
+{
+       int i;
+       uint32_t value;
+
+       /* enter wfi and stay there */
+       INFO("Entering wfi\n");
+
+       spin_lock(&inc_lock);
+       active_cores--;
+
+       for (i = 0; i < 4; i++) {
+               mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i,
+                               0xffffffff);
+       }
+
+       dsb();
+
+       spin_unlock(&inc_lock);
+
+       if (active_cores == 0) {
+               pm_mmio_read(PMU_GLOBAL_GEN_STORAGE4, &value);
+               value = (value & RESTART_SCOPE_MASK) >> RESTART_SCOPE_SHIFT;
+               pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET, value);
+       }
+
+       /* enter wfi and stay there */
+       while (1)
+               wfi();
+}
+
+/**
+ * pm_wdt_restart_setup() - Setup warm restart interrupts
+ *
+ * This function sets up handler for SGI7 and TTC interrupts
+ * used for warm restart.
+ */
+static int pm_wdt_restart_setup(void)
+{
+       int ret;
+
+       /* register IRQ handler for SGI7 */
+       ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq);
+       if (ret) {
+               WARN("BL31: registering SGI7 interrupt failed\n");
+               goto err;
+       }
+
+       ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler);
+       if (ret)
+               WARN("BL31: registering TTC3 interrupt failed\n");
+
+err:
+       return ret;
+}
+#endif
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return     On success, the initialization function must return 0.
+ *             Any other return value will cause the framework to ignore
+ *             the service
+ *
+ * Initialization functions for ZynqMP power management for
+ * communicaton with PMU.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ */
+int32_t pm_setup(void)
+{
+       enum pm_ret_status err;
+
+       pm_ipi_init(primary_proc);
+
+       err = pm_get_api_version(&pm_ctx.api_version);
+       if (err != PM_RET_SUCCESS) {
+               ERROR("BL31: Failed to read Platform Management API version. "
+                     "Return: %d\n", err);
+               return -EINVAL;
+       }
+       if (pm_ctx.api_version < PM_VERSION) {
+               ERROR("BL31: Platform Management API version error. Expected: "
+                     "v%d.%d - Found: v%d.%d\n", PM_VERSION_MAJOR,
+                     PM_VERSION_MINOR, pm_ctx.api_version >> 16,
+                     pm_ctx.api_version & 0xFFFFU);
+               return -EINVAL;
+       }
+
+       int32_t status = 0, ret = 0;
+#if ZYNQMP_WDT_RESTART
+       status = pm_wdt_restart_setup();
+       if (status)
+               WARN("BL31: warm-restart setup failed\n");
+#endif
+
+       if (status >= 0) {
+               INFO("BL31: PM Service Init Complete: API v%d.%d\n",
+                    PM_VERSION_MAJOR, PM_VERSION_MINOR);
+               ret = 0;
+       } else {
+               INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
+               ret = status;
+       }
+
+       pm_up = !status;
+
+       return ret;
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie  - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return  - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+                       uint64_t x4, const void *cookie, void *handle, uint64_t flags)
+{
+       enum pm_ret_status ret;
+       uint32_t payload[PAYLOAD_ARG_CNT];
+
+       uint32_t pm_arg[5];
+       uint32_t result[PAYLOAD_ARG_CNT] = {0};
+       uint32_t api_id;
+
+       /* Handle case where PM wasn't initialized properly */
+       if (pm_up == 0)
+               SMC_RET1(handle, SMC_UNK);
+
+       pm_arg[0] = (uint32_t)x1;
+       pm_arg[1] = (uint32_t)(x1 >> 32);
+       pm_arg[2] = (uint32_t)x2;
+       pm_arg[3] = (uint32_t)(x2 >> 32);
+       pm_arg[4] = (uint32_t)x3;
+
+       api_id = smc_fid & FUNCID_NUM_MASK;
+
+       switch (api_id) {
+       /* PM API Functions */
+       case PM_SELF_SUSPEND:
+               ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+                                     pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_REQ_SUSPEND:
+               ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+                                    pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_REQ_WAKEUP:
+       {
+               /* Use address flag is encoded in the 1st bit of the low-word */
+               uint32_t set_addr = pm_arg[1] & 0x1U;
+               uint64_t address = (uint64_t)pm_arg[2] << 32U;
+
+               address |= pm_arg[1] & (~0x1U);
+               ret = pm_req_wakeup(pm_arg[0], set_addr, address,
+                                   pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+       }
+
+       case PM_FORCE_POWERDOWN:
+               ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_ABORT_SUSPEND:
+               ret = pm_abort_suspend(pm_arg[0]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SET_WAKEUP_SOURCE:
+               ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SYSTEM_SHUTDOWN:
+               ret = pm_system_shutdown(pm_arg[0], pm_arg[1]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_REQ_NODE:
+               ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SET_REQUIREMENT:
+               ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
+                                        pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_GET_API_VERSION:
+               if (ipi_irq_flag == 0U) {
+                       /*
+                        * Enable IPI IRQ
+                        * assume the rich OS is OK to handle callback IRQs now.
+                        * Even if we were wrong, it would not enable the IRQ in
+                        * the GIC.
+                        */
+                       pm_ipi_irq_enable(primary_proc);
+                       ipi_irq_flag = 1U;
+               }
+               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+                        ((uint64_t)pm_ctx.api_version << 32));
+       case PM_FPGA_LOAD:
+               ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_FPGA_GET_STATUS:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_fpga_get_status(&value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+       }
+
+       case PM_SECURE_RSA_AES:
+               ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
+                                      pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_GET_CALLBACK_DATA:
+               ret = pm_get_callbackdata(result, ARRAY_SIZE(result));
+               if (ret != PM_RET_SUCCESS) {
+                       result[0] = ret;
+               }
+
+               SMC_RET2(handle,
+                        (uint64_t)result[0] | ((uint64_t)result[1] << 32),
+                        (uint64_t)result[2] | ((uint64_t)result[3] << 32));
+       case PM_IOCTL:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
+                              pm_arg[3], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+       }
+
+       case PM_QUERY_DATA:
+       {
+               uint32_t data[4] = { 0 };
+
+               pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+                             pm_arg[3], data);
+               SMC_RET2(handle, (uint64_t)data[0]  | ((uint64_t)data[1] << 32),
+                        (uint64_t)data[2] | ((uint64_t)data[3] << 32));
+       }
+
+       case PM_CLOCK_ENABLE:
+               ret = pm_clock_enable(pm_arg[0]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_CLOCK_DISABLE:
+               ret = pm_clock_disable(pm_arg[0]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_CLOCK_GETSTATE:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_clock_getstate(pm_arg[0], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+       }
+
+       case PM_CLOCK_SETDIVIDER:
+               ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_CLOCK_GETDIVIDER:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_clock_getdivider(pm_arg[0], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+       }
+
+       case PM_CLOCK_SETRATE:
+               ret = pm_clock_setrate(pm_arg[0],
+                      ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
+
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_CLOCK_GETRATE:
+       {
+               uint64_t value = 0;
+
+               ret = pm_clock_getrate(pm_arg[0], &value);
+               SMC_RET2(handle, (uint64_t)ret |
+                                 (((uint64_t)value & 0xFFFFFFFFU) << 32U),
+                        (value >> 32U) & 0xFFFFFFFFU);
+
+       }
+
+       case PM_CLOCK_SETPARENT:
+               ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_CLOCK_GETPARENT:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_clock_getparent(pm_arg[0], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_GET_TRUSTZONE_VERSION:
+               SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+                        ((uint64_t)ZYNQMP_TZ_VERSION << 32U));
+
+       case PM_SET_SUSPEND_MODE:
+               ret = pm_set_suspend_mode(pm_arg[0]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SECURE_SHA:
+               ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2],
+                               pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SECURE_RSA:
+               ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2],
+                                      pm_arg[3]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_SECURE_IMAGE:
+       {
+               ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
+                                     pm_arg[3], &result[0]);
+               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+                        result[1]);
+       }
+
+       case PM_FPGA_READ:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
+                                  &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_SECURE_AES:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_PLL_SET_PARAMETER:
+               ret = pm_pll_set_parameter(pm_arg[0], pm_arg[1], pm_arg[2]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_PLL_GET_PARAMETER:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32U));
+       }
+
+       case PM_PLL_SET_MODE:
+               ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]);
+               SMC_RET1(handle, (uint64_t)ret);
+
+       case PM_PLL_GET_MODE:
+       {
+               uint32_t mode = 0U;
+
+               ret = pm_pll_get_mode(pm_arg[0], &mode);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32U));
+       }
+
+       case PM_REGISTER_ACCESS:
+       {
+               uint32_t value = 0U;
+
+               ret = pm_register_access(pm_arg[0], pm_arg[1], pm_arg[2],
+                                        pm_arg[3], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_EFUSE_ACCESS:
+       {
+               uint32_t value = 0U;
+
+#if defined(ZYNQMP_SECURE_EFUSES)
+               if (is_caller_non_secure(flags)) {
+                       SMC_RET1(handle,
+                                (((uint64_t)PM_RET_ERROR_NOT_ENABLED) << 32U) |
+                                (uint64_t)PM_RET_ERROR_ACCESS);
+               }
+#endif
+               ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value);
+               SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32U);
+       }
+
+       case PM_FPGA_GET_VERSION:
+       case PM_FPGA_GET_FEATURE_LIST:
+       {
+               uint32_t ret_payload[PAYLOAD_ARG_CNT];
+
+               PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK,
+                                pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+               ret = pm_ipi_send_sync(primary_proc, payload, ret_payload, 3U);
+               SMC_RET2(handle, (uint64_t)ret | (uint64_t)ret_payload[0] << 32U,
+                        (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32U);
+       }
+
+       case PM_FEATURE_CHECK:
+       {
+               uint32_t version = 0;
+               uint32_t bit_mask[2] = {0};
+
+               ret = pm_feature_check(pm_arg[0], &version, bit_mask,
+                                      ARRAY_SIZE(bit_mask));
+               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)version << 32U),
+                        (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32U));
+       }
+
+       default:
+               /* Send request to the PMU */
+               PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1],
+                                pm_arg[2], pm_arg[3], pm_arg[4]);
+               ret = pm_ipi_send_sync(primary_proc, payload, result,
+                                      PAYLOAD_ARG_CNT);
+               SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32U),
+                        (uint64_t)result[1] | ((uint64_t)result[2] << 32U));
+       }
+}
diff --git a/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/zynqmp_pm_svc_main.h
new file mode 100644 (file)
index 0000000..03ff6d3
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023, Advanced Micro Devices Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ZYNQMP_PM_SVC_MAIN_H
+#define ZYNQMP_PM_SVC_MAIN_H
+
+#include "pm_common.h"
+
+int32_t pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+                       uint64_t x4, const void *cookie, void *handle,
+                       uint64_t flags);
+#endif /* ZYNQMP_PM_SVC_MAIN_H */
index c55784e3ff3bfc33530ecd576cdad7b56b146449..6ec7ed492ef1620c8a09885098c22874ad7652e2 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <custom_svc.h>
 #include "ipi_mailbox_svc.h"
-#include "pm_svc_main.h"
+#include "zynqmp_pm_svc_main.h"
 
 /* SMC function IDs for SiP Service queries */
 #define ZYNQMP_SIP_SVC_CALL_COUNT      U(0x8200ff00)