From 76ff8c459e9e6d105e614d68648bd6680806f93e Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Tue, 12 Oct 2021 03:30:09 -0700 Subject: [PATCH 1/6] feat(zynqmp): pass ioctl calls to firmware Firmware supports new IOCTL for different purposes. To avoid maintaining new IOCTL IDs in ATF, pass IOCTL call to firmware for IOCTL IDs implemented in firmware. Signed-off-by: Rajan Vaja Signed-off-by: Ronak Jain Change-Id: Ie14697c8da9581b0f695f4d33f05161ece558385 --- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 10 +-- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 3 - plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 65 -------------------- plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 32 ++++++++++ 4 files changed, 37 insertions(+), 73 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index 9c5af88bb..11068696f 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -618,6 +618,7 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, unsigned int *value) { enum pm_ret_status ret; + uint32_t payload[PAYLOAD_ARG_CNT]; switch (ioctl_id) { case IOCTL_GET_RPU_OPER_MODE: @@ -677,12 +678,11 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, case IOCTL_AFI: ret = pm_ioctl_afi(arg1, arg2); break; - case IOCTL_SET_FEATURE_CONFIG: - case IOCTL_GET_FEATURE_CONFIG: - ret = pm_feature_config(ioctl_id, arg1, arg2, value); - break; default: - ret = PM_RET_ERROR_NOTSUPPORTED; + /* Send request to the PMU */ + PM_PACK_PAYLOAD5(payload, PM_IOCTL, nid, ioctl_id, arg1, arg2); + + ret = pm_ipi_send_sync(primary_proc, payload, value, 1); break; } diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index f18dc00a2..7f9686184 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -49,9 +49,6 @@ enum { IOCTL_AIE_ISR_CLEAR = 24, /* Register SGI to ATF */ IOCTL_REGISTER_SGI = 25, - /* Runtime feature configuration */ - IOCTL_SET_FEATURE_CONFIG = 26, - IOCTL_GET_FEATURE_CONFIG = 27, }; //RPU operation mode diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 5d9408cd5..2aaebac8b 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -33,38 +33,6 @@ unsigned int pm_get_shutdown_scope(void) return pm_shutdown_scope; } -/** - * 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); \ -} - #define EM_PACK_PAYLOAD1(pl, arg0) { \ pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \ } @@ -1648,36 +1616,3 @@ enum pm_ret_status em_send_errors(unsigned int *value) EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS); return pm_ipi_send_sync(primary_proc, payload, value, 1); } - -/** - * pm_feature_config() - feature configuration at runtime - * - * This function is used to send IPI request to PMUFW to configure feature - * at runtime. The feature can be enable or disable as well as the feature - * can be configure at runtime using an IOCTL call. - * - * @ioctl_id The ioctl id for the feature configuration - * @config_id The config id of the feature to be configured - * @value The value to be configured - * @response Return to reference pointer - * - * @return Returns 0 on success or error value on failure - */ -enum pm_ret_status pm_feature_config(unsigned int ioctl_id, - unsigned int config_id, - unsigned int value, - unsigned int *response) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value); - - if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) { - return pm_ipi_send_sync(primary_proc, payload, response, 1); - } else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) { - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); - } else { - return PM_RET_ERROR_ARGS; - } -} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index ca07cef75..d6ad84fb6 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -33,6 +33,38 @@ enum pm_register_access_id { 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 **********************************************************/ From cc077c22273075db328bd30fa12c28abf9eef052 Mon Sep 17 00:00:00 2001 From: Nava kishore Manne Date: Thu, 13 Jan 2022 13:29:36 +0530 Subject: [PATCH 2/6] feat(zynqmp): add support to get info of xilfpga Adds support to get the xilfpga library version and feature list info. Signed-off-by: Nava kishore Manne Signed-off-by: Ronak Jain Change-Id: Iff10ad2628a6a90230c18dc3aebf9dde89f53ecd --- plat/xilinx/zynqmp/pm_service/pm_defs.h | 2 ++ plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 3324431dd..bfd5e8b5d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -101,6 +101,8 @@ enum pm_api_id { /* PM Register Access API */ PM_REGISTER_ACCESS, PM_EFUSE_ACCESS, + PM_FPGA_GET_VERSION, + PM_FPGA_GET_FEATURE_LIST, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index a49bda8d2..f7ce5a243 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -634,6 +634,19 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_FPGA_GET_VERSION: + case PM_FPGA_GET_FEATURE_LIST: + { + uint32_t payload[PAYLOAD_ARG_CNT]; + 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] << 32, + (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK); From a469c1e1f4c1cd69f98ce45d6e0709de091b8cb3 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Thu, 20 Jan 2022 23:11:18 -0800 Subject: [PATCH 3/6] fix(zynqmp): use common interface for eemi apis Currently all EEMI API has its own implementation in TF-A which is redundant. Most EEMI API implementation in TF-A does same work. It prepares payload received from kernel, sends payload to firmware, receives response from firmware and send response back to kernel. So use common interface for EEMI APIs which has similar functionality. This will optimize TF-A code. Signed-off-by: Ronak Jain Change-Id: I07325644a1fae80211f2588d5807c21973f6d48f --- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 249 +------------------- plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 30 +-- plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 130 ++-------- 3 files changed, 16 insertions(+), 393 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index 2aaebac8b..faaff1b08 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -273,36 +273,6 @@ enum pm_ret_status pm_set_requirement(enum pm_node_id nid, return pm_ipi_send(primary_proc, payload); } -/** - * pm_release_node() - PM call to release a node - * @nid Node id of the slave - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_release_node(enum pm_node_id nid) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_set_max_latency() - PM call to set wakeup latency requirements - * @nid Node id of the slave - * @latency Requested maximum wakeup latency - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_set_max_latency(enum pm_node_id nid, - unsigned int latency) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - /* Miscellaneous API functions */ /** @@ -320,36 +290,6 @@ enum pm_ret_status pm_get_api_version(unsigned int *version) return pm_ipi_send_sync(primary_proc, payload, version, 1); } -/** - * pm_set_configuration() - PM call to set system configuration - * @phys_addr Physical 32-bit address of data structure in memory - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_set_configuration(unsigned int phys_addr) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_init_finalize() - Call to notify PMU firmware that master has power - * management enabled and that it has finished its - * initialization - * - * @return Status returned by the PMU firmware - */ -enum pm_ret_status pm_init_finalize(void) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - /** * pm_get_node_status() - PM call to request a node's current status * @nid Node id @@ -369,86 +309,6 @@ enum pm_ret_status pm_get_node_status(enum pm_node_id nid, return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3); } -/** - * pm_register_notifier() - Register the PU to be notified of PM events - * @nid Node id of the slave - * @event The event to be notified about - * @wake Wake up on event - * @enable Enable or disable the notifier - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_register_notifier(enum pm_node_id nid, - unsigned int event, - unsigned int wake, - unsigned int enable) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER, - nid, event, wake, enable); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_get_op_characteristic() - PM call to request operating characteristics - * of a node - * @nid Node id of the slave - * @type Type of the operating characteristic - * (power, temperature and latency) - * @result Returns the operating characteristic for the requested node, - * specified by the type - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, - enum pm_opchar_type type, - uint32_t *result) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type); - return pm_ipi_send_sync(primary_proc, payload, result, 1); -} - -/* Direct-Control API functions */ - -/** - * pm_reset_assert() - Assert reset - * @reset Reset ID - * @assert Assert (1) or de-assert (0) - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_reset_assert(unsigned int reset, - unsigned int assert) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_reset_get_status() - Get current status of a reset line - * @reset Reset ID - * @reset_status Returns current status of selected reset line - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_reset_get_status(unsigned int reset, - unsigned int *reset_status) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset); - return pm_ipi_send_sync(primary_proc, payload, reset_status, 1); -} - /** * pm_mmio_write() - Perform write to protected mmio * @address Address to write to @@ -617,113 +477,6 @@ void pm_get_callbackdata(uint32_t *data, size_t count) pm_ipi_irq_clear(primary_proc); } -/** - * pm_pinctrl_request() - Request Pin from firmware - * @pin Pin number to request - * - * This function requests pin from firmware. - * - * @return Returns status, either success or error+reason. - */ -enum pm_ret_status pm_pinctrl_request(unsigned int pin) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_release() - Release Pin from firmware - * @pin Pin number to release - * - * This function releases pin from firmware. - * - * @return Returns status, either success or error+reason. - */ -enum pm_ret_status pm_pinctrl_release(unsigned int pin) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_get_function() - Read function id set for the given pin - * @pin Pin number - * @fid ID of function currently set for given pin - * - * This function provides the function currently set for the given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin); - return pm_ipi_send_sync(primary_proc, payload, fid, 1); -} - -/** - * pm_pinctrl_set_function() - Set function id set for the given pin - * @pin Pin number - * @fid ID of function to set for given pin - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_get_config() - Read value of requested config param for given pin - * @pin Pin number - * @param Parameter values to be read - * @value Buffer for configuration Parameter value - * - * This function provides the configuration parameter value for the given pin. - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_pinctrl_get_config(unsigned int pin, - unsigned int param, - unsigned int *value) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param); - return pm_ipi_send_sync(primary_proc, payload, value, 1); -} - -/** - * pm_pinctrl_set_config() - Set value of requested config param for given pin - * @pin Pin number - * @param Parameter to set - * @value Parameter value to set - * - * @return Returns status, either success or error+reason - */ -enum pm_ret_status pm_pinctrl_set_config(unsigned int pin, - unsigned int param, - unsigned int value) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMU */ - PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param, - value); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - /** * pm_ioctl() - PM IOCTL API for device control and configs * @node_id Node ID of the device diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index d6ad84fb6..c0dae3e80 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -104,28 +104,16 @@ enum pm_ret_status pm_req_node(enum pm_node_id nid, unsigned int capabilities, unsigned int qos, enum pm_request_ack ack); -enum pm_ret_status pm_release_node(enum pm_node_id nid); enum pm_ret_status pm_set_requirement(enum pm_node_id nid, unsigned int capabilities, unsigned int qos, enum pm_request_ack ack); -enum pm_ret_status pm_set_max_latency(enum pm_node_id nid, - unsigned int latency); /* Miscellaneous API functions */ enum pm_ret_status pm_get_api_version(unsigned int *version); -enum pm_ret_status pm_set_configuration(unsigned int phys_addr); -enum pm_ret_status pm_init_finalize(void); enum pm_ret_status pm_get_node_status(enum pm_node_id node, uint32_t *ret_buff); -enum pm_ret_status pm_register_notifier(enum pm_node_id nid, - unsigned int event, - unsigned int wake, - unsigned int enable); -enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid, - enum pm_opchar_type type, - uint32_t *result); enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid, enum pm_ret_status status, unsigned int oppoint); @@ -134,10 +122,6 @@ enum pm_ret_status pm_notify_cb(enum pm_node_id nid, unsigned int oppoint); /* Direct-Control API functions */ -enum pm_ret_status pm_reset_assert(unsigned int reset_id, - unsigned int assert); -enum pm_ret_status pm_reset_get_status(unsigned int reset_id, - unsigned int *reset_status); enum pm_ret_status pm_mmio_write(uintptr_t address, unsigned int mask, unsigned int value); @@ -155,18 +139,6 @@ enum pm_ret_status pm_secure_rsaaes(uint32_t address_high, uint32_t flags); unsigned int pm_get_shutdown_scope(void); void pm_get_callbackdata(uint32_t *data, size_t count); -enum pm_ret_status pm_pinctrl_request(unsigned int pin); -enum pm_ret_status pm_pinctrl_release(unsigned int pin); -enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, - enum pm_node_id *nid); -enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, - enum pm_node_id nid); -enum pm_ret_status pm_pinctrl_get_config(unsigned int pin, - unsigned int param, - unsigned int *value); -enum pm_ret_status pm_pinctrl_set_config(unsigned int pin, - unsigned int param, - unsigned int value); enum pm_ret_status pm_ioctl(enum pm_node_id nid, unsigned int ioctl_id, unsigned int arg1, diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index f7ce5a243..f15686fd8 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -262,8 +262,11 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *cookie, void *handle, uint64_t flags) { enum pm_ret_status ret; + uint32_t payload[PAYLOAD_ARG_CNT]; uint32_t pm_arg[4]; + uint32_t result[PAYLOAD_ARG_CNT]; + uint32_t api_id; /* Handle case where PM wasn't initialized properly */ if (!pm_up) @@ -273,8 +276,11 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, 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; - switch (smc_fid & FUNCID_NUM_MASK) { + 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], @@ -318,19 +324,11 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); SMC_RET1(handle, (uint64_t)ret); - case PM_RELEASE_NODE: - ret = pm_release_node(pm_arg[0]); - 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_SET_MAX_LATENCY: - ret = pm_set_max_latency(pm_arg[0], pm_arg[1]); - SMC_RET1(handle, (uint64_t)ret); - case PM_GET_API_VERSION: /* Check is PM API version already verified */ if (pm_ctx.api_version >= PM_VERSION) { @@ -348,62 +346,6 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ((uint64_t)pm_ctx.api_version << 32)); } - case PM_SET_CONFIGURATION: - ret = pm_set_configuration(pm_arg[0]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_INIT_FINALIZE: - ret = pm_init_finalize(); - SMC_RET1(handle, (uint64_t)ret); - - case PM_GET_NODE_STATUS: - { - uint32_t buff[3]; - - ret = pm_get_node_status(pm_arg[0], buff); - SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32), - (uint64_t)buff[1] | ((uint64_t)buff[2] << 32)); - } - - case PM_GET_OP_CHARACTERISTIC: - { - uint32_t result; - - ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result); - SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32)); - } - - case PM_REGISTER_NOTIFIER: - ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_RESET_ASSERT: - ret = pm_reset_assert(pm_arg[0], pm_arg[1]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_RESET_GET_STATUS: - { - uint32_t reset_status; - - ret = pm_reset_get_status(pm_arg[0], &reset_status); - SMC_RET1(handle, (uint64_t)ret | - ((uint64_t)reset_status << 32)); - } - - /* PM memory access functions */ - case PM_MMIO_WRITE: - ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_MMIO_READ: - { - uint32_t value; - - ret = pm_mmio_read(pm_arg[0], &value); - SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 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); @@ -416,62 +358,16 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } - case PM_GET_CHIPID: - { - uint32_t result[2]; - - ret = pm_get_chipid(result); - SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32), - result[1]); - } - 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: - { - uint32_t result[4] = {0}; - pm_get_callbackdata(result, ARRAY_SIZE(result)); SMC_RET2(handle, (uint64_t)result[0] | ((uint64_t)result[1] << 32), (uint64_t)result[2] | ((uint64_t)result[3] << 32)); - } - - case PM_PINCTRL_REQUEST: - ret = pm_pinctrl_request(pm_arg[0]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_RELEASE: - ret = pm_pinctrl_release(pm_arg[0]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_GET_FUNCTION: - { - uint32_t value = 0; - - ret = pm_pinctrl_get_function(pm_arg[0], &value); - SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); - } - - case PM_PINCTRL_SET_FUNCTION: - ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1]); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_CONFIG_PARAM_GET: - { - uint32_t value; - - ret = pm_pinctrl_get_config(pm_arg[0], pm_arg[1], &value); - SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); - } - - case PM_PINCTRL_CONFIG_PARAM_SET: - ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]); - SMC_RET1(handle, (uint64_t)ret); - case PM_IOCTL: { uint32_t value; @@ -568,8 +464,6 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, case PM_SECURE_IMAGE: { - uint32_t result[2]; - 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] << 32), @@ -637,7 +531,6 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, case PM_FPGA_GET_VERSION: case PM_FPGA_GET_FEATURE_LIST: { - uint32_t payload[PAYLOAD_ARG_CNT]; uint32_t ret_payload[PAYLOAD_ARG_CNT]; PM_PACK_PAYLOAD5(payload, smc_fid & FUNCID_NUM_MASK, @@ -648,8 +541,13 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, } default: - WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); - SMC_RET1(handle, SMC_UNK); + /* 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] << 32), + (uint64_t)result[1] | ((uint64_t)result[2] << 32)); } } From 223a6284b8a0a3ead884a7f0cf333a464d32e319 Mon Sep 17 00:00:00 2001 From: Ronak Jain Date: Tue, 21 Dec 2021 01:39:59 -0800 Subject: [PATCH 4/6] feat(zynqmp): add feature check support This API returns version of supported APIs. Here, there are three cases to check API version by using feature check implementation. 1. Completely implemented in TF-A: I mean the EEMI APIs which are completely implemented in the TF-A only. So check those IDs and return appropriate version for the same. Right now, it is base version. 2. Completely implemented in firmware: I mean the EEMI APIs which are completely implemented in the firmware only. Here, TF-A only passes Linux request to the firmware to get the version of supported API. So check those IDs and send request to firmware to get the version and return to Linux if the version is supported or return the error code if the feature is not supported. 3. Partially implemented (Implemented in TF-A and firmware both): First check dependent EEMI API version with the expected version in the TF-A. If the dependent EEMI API is supported in firmware then return its version and check with the expected version in the TF-A. If the version matches then check for the actual requested EEMI API version. If the version is supported then return version of API implemented in TF-A. Signed-off-by: Ronak Jain Change-Id: I73f20d8222c518df1cda7879548b408b130b5b2e --- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c | 46 +- plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h | 3 +- plat/xilinx/zynqmp/pm_service/pm_api_sys.c | 433 +++++++++++++++++++ plat/xilinx/zynqmp/pm_service/pm_api_sys.h | 3 + plat/xilinx/zynqmp/pm_service/pm_defs.h | 19 +- plat/xilinx/zynqmp/pm_service/pm_svc_main.c | 18 +- 6 files changed, 514 insertions(+), 8 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index 11068696f..a87681b45 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -688,3 +688,47 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, return ret; } + +/** + * pm_update_ioctl_bitmask() - API to get supported IOCTL ID mask + * @bit_mask Returned bit mask of supported IOCTL IDs + */ +enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask) +{ + uint8_t supported_ids[] = { + IOCTL_GET_RPU_OPER_MODE, + IOCTL_SET_RPU_OPER_MODE, + IOCTL_RPU_BOOT_ADDR_CONFIG, + IOCTL_TCM_COMB_CONFIG, + IOCTL_SET_TAPDELAY_BYPASS, + IOCTL_SET_SGMII_MODE, + IOCTL_SD_DLL_RESET, + IOCTL_SET_SD_TAPDELAY, + IOCTL_SET_PLL_FRAC_MODE, + IOCTL_GET_PLL_FRAC_MODE, + IOCTL_SET_PLL_FRAC_DATA, + IOCTL_GET_PLL_FRAC_DATA, + IOCTL_WRITE_GGS, + IOCTL_READ_GGS, + IOCTL_WRITE_PGGS, + IOCTL_READ_PGGS, + IOCTL_ULPI_RESET, + IOCTL_SET_BOOT_HEALTH_STATUS, + IOCTL_AFI, + }; + uint8_t i, ioctl_id; + int ret; + + for (i = 0U; i < ARRAY_SIZE(supported_ids); i++) { + ioctl_id = supported_ids[i]; + if (ioctl_id >= 64U) { + return PM_RET_ERROR_NOTSUPPORTED; + } + ret = check_api_dependency(ioctl_id); + if (ret == PM_RET_SUCCESS) { + bit_mask[ioctl_id / 32] |= BIT(ioctl_id % 32); + } + } + + return PM_RET_SUCCESS; +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index 7f9686184..0c5f33fa6 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -92,4 +92,5 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, unsigned int arg1, unsigned int arg2, unsigned int *value); +enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask); #endif /* PM_API_IOCTL_H */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index faaff1b08..f9af451c0 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -20,6 +20,225 @@ #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 unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM; @@ -498,6 +717,220 @@ enum pm_ret_status pm_ioctl(enum pm_node_id nid, 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 = ATF_API_BASE_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) { + if (len < 2) { + return PM_RET_ERROR_ARGS; + } + bit_mask[0] = ret_payload[1]; + bit_mask[1] = ret_payload[2]; + /* 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 diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index c0dae3e80..4e38c42b4 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -210,5 +210,8 @@ enum pm_ret_status pm_feature_config(unsigned int ioctl_id, unsigned int config_id, unsigned int value, unsigned int *response); +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 */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index bfd5e8b5d..1933b8704 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -22,6 +22,16 @@ #define PM_VERSION ((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR) +/** + * PM API versions + */ +/* Expected version of firmware APIs */ +#define FW_API_BASE_VERSION (1U) +/* Expected version of firmware API for feature check */ +#define FW_API_VERSION_2 (2U) +/* Version of APIs implemented in ATF */ +#define ATF_API_BASE_VERSION (1U) + /* Capabilities for RAM */ #define PM_CAP_ACCESS 0x1U #define PM_CAP_CONTEXT 0x2U @@ -34,6 +44,11 @@ #define PM_STATE_SUSPEND_TO_RAM 0xFU #define EM_FUNID_NUM_MASK 0xF0000U + +#define PM_GET_CALLBACK_DATA 0xa01 +#define PM_SET_SUSPEND_MODE 0xa02 +#define PM_GET_TRUSTZONE_VERSION 0xa03 + /********************************************************************* * Enum definitions ********************************************************************/ @@ -103,6 +118,7 @@ enum pm_api_id { PM_EFUSE_ACCESS, PM_FPGA_GET_VERSION, PM_FPGA_GET_FEATURE_LIST, + PM_FEATURE_CHECK = 63, PM_API_MAX }; @@ -243,7 +259,8 @@ enum pm_ret_status { PM_RET_ERROR_DOUBLE_REQ = 2004, PM_RET_ERROR_ABORT_SUSPEND = 2005, PM_RET_ERROR_TIMEOUT = 2006, - PM_RET_ERROR_NODE_USED = 2007 + PM_RET_ERROR_NODE_USED = 2007, + PM_RET_ERROR_NO_FEATURE = 2008 }; /** diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index f15686fd8..b789da14c 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -23,12 +23,9 @@ #include #include "pm_api_sys.h" #include "pm_client.h" +#include "pm_defs.h" #include "pm_ipi.h" -#define PM_GET_CALLBACK_DATA 0xa01 -#define PM_SET_SUSPEND_MODE 0xa02 -#define PM_GET_TRUSTZONE_VERSION 0xa03 - /* pm_up = !0 - UP, pm_up = 0 - DOWN */ static int32_t pm_up, ipi_irq_flag; @@ -540,6 +537,17 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32); } + case PM_FEATURE_CHECK: + { + uint32_t version; + 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 << 32), + (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32)); + } + default: /* Send request to the PMU */ PM_PACK_PAYLOAD6(payload, api_id, pm_arg[0], pm_arg[1], From e682d38b56854e1586b25d929dbc83543b4c66e4 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 2 Feb 2022 09:15:31 +0100 Subject: [PATCH 5/6] feat(zynqmp): pm_api_clock_get_num_clocks cleanup There is no reason to have even one additional useless line that's why remove it. Signed-off-by: Michal Simek Signed-off-by: Ronak Jain Change-Id: Icc3c74249dfe64173aa5c88fb0f9ffe7576fc2aa --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index 0cc517ec9..410983022 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -2443,8 +2443,6 @@ enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks) * * This function is used by master to get nmae of clock specified * by given clock ID. - * - * @return Returns success. In case of error, name data is 0. */ void pm_api_clock_get_name(unsigned int clock_id, char *name) { From b35b556718b60b78cb5d96b0c137e2fe82eb0086 Mon Sep 17 00:00:00 2001 From: Ravi Patel Date: Thu, 15 Apr 2021 05:55:19 -0700 Subject: [PATCH 6/6] fix(zynqmp): query node status to power up APU If APU is in suspending state and if wakeup request comes then PMUFW returns error which is not handled at ATF side. To fix this, get the APU node status before calling wakeup and return error if found in suspending state. Here, we can not handle the error code of pm_req_wakeup() from PMUFW because ATF is already calling pm_client_wakeup() before calling pm_req_wakeup(). Signed-off-by: Ravi Patel Signed-off-by: Ronak Jain Change-Id: I18d47384e46e22ae49e804093ad0641b7a6349e2 --- plat/xilinx/zynqmp/plat_psci.c | 11 ++++++++++- plat/xilinx/zynqmp/pm_service/pm_defs.h | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c index f78b88cdf..b2b473a48 100644 --- a/plat/xilinx/zynqmp/plat_psci.c +++ b/plat/xilinx/zynqmp/plat_psci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -33,6 +33,8 @@ static int zynqmp_pwr_domain_on(u_register_t mpidr) { unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); const struct pm_proc *proc; + uint32_t buff[3]; + enum pm_ret_status ret; VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); @@ -40,6 +42,13 @@ static int zynqmp_pwr_domain_on(u_register_t mpidr) return PSCI_E_INTERN_FAIL; proc = pm_get_proc(cpu_id); + + /* Check the APU proc status before wakeup */ + ret = pm_get_node_status(proc->node_id, buff); + if ((ret != PM_RET_SUCCESS) || (buff[0] == PM_PROC_STATE_SUSPENDING)) { + return PSCI_E_INTERN_FAIL; + } + /* Clear power down request */ pm_client_wakeup(proc); diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index 1933b8704..2baf9607d 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -43,6 +43,12 @@ #define PM_STATE_CPU_IDLE 0x0U #define PM_STATE_SUSPEND_TO_RAM 0xFU +/* APU processor states */ +#define PM_PROC_STATE_FORCEDOFF 0U +#define PM_PROC_STATE_ACTIVE 1U +#define PM_PROC_STATE_SLEEP 2U +#define PM_PROC_STATE_SUSPENDING 3U + #define EM_FUNID_NUM_MASK 0xF0000U #define PM_GET_CALLBACK_DATA 0xa01