--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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;
+}
# 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
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 \
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)
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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 */
# 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
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
/*
* 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
*/
#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.
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 \
/*
* 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
*/
#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;
/*
* 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)
/*
* 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
/*
* 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];
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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 */
/*
* 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
*/
#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)
+++ /dev/null
-/*
- * 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));
- }
-}
+++ /dev/null
-/*
- * 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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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));
+ }
+}
--- /dev/null
+/*
+ * 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 */
#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)