diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 534d910ad..d39b53769 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -25,6 +25,8 @@ #define LOADER_MODULE_ID 0x7U #define MODE 0x80000000U +#define MODULE_ID_MASK 0x0000ff00 + /* default shutdown/reboot scope is system(2) */ static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; @@ -73,38 +75,29 @@ unsigned int pm_get_shutdown_scope(void) /* PM API functions */ /** - * pm_get_api_version() - Get version number of PMC PM firmware - * @version Returns 32-bit version number of PMC Power Management Firmware + * 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 Returns status, either success or error+reason + * @return PM_RET_SUCCESS on success or error code */ -enum pm_ret_status pm_get_api_version(unsigned int *version, uint32_t flag) +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]; + uint32_t payload[PAYLOAD_ARG_CNT] = {0}; + uint32_t module_id; - /* Send request to the PMC */ - PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_API_VERSION); - return pm_ipi_send_sync(primary_proc, payload, version, 1); -} + module_id = (x0 & MODULE_ID_MASK) >> 8; -/** - * pm_init_finalize() - Call to notify PMC PM firmware that master has power - * management enabled and that it has finished its - * initialization - * @flag 0 - Call from secure source - * 1 - Call from non-secure source - * - * @return Status returned by the PMU firmware - */ -enum pm_ret_status pm_init_finalize(uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; + //default module id is for LIBPM + if (module_id == 0) + module_id = LIBPM_MODULE_ID; - /* Send request to the PMU */ - PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_INIT_FINALIZE); - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + 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); } /** @@ -234,134 +227,6 @@ enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address, return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } -/** - * pm_request_device() - Request a device - * @device_id Device ID - * @capabilities Requested capabilities for the device - * @qos Required Quality of Service - * @ack Flag to specify whether acknowledge 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_request_device(uint32_t device_id, uint32_t capabilities, - uint32_t qos, uint32_t ack, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQUEST_DEVICE, - device_id, capabilities, qos, ack); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_release_device() - Release a device - * @device_id Device ID - * @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_release_device(uint32_t device_id, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RELEASE_DEVICE, - device_id); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_set_requirement() - Set requirement for the device - * @device_id Device ID - * @capabilities Requested capabilities for the device - * @latency Requested maximum latency - * @qos Required Quality of Service - * @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_requirement(uint32_t device_id, uint32_t capabilities, - uint32_t latency, uint32_t qos, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_SET_REQUIREMENT, - device_id, capabilities, latency, qos); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_get_device_status() - Get device's status - * @device_id Device ID - * @response Buffer to store device status response - * @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_get_device_status(uint32_t device_id, uint32_t *response, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_GET_DEVICE_STATUS, - device_id); - - return pm_ipi_send_sync(primary_proc, payload, response, 3); -} - -/** - * pm_reset_assert() - Assert/De-assert reset - * @reset Reset ID - * @assert Assert (1) or de-assert (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_reset_assert(uint32_t reset, bool assert, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, 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 - * @status Returns current status of selected reset ID - * @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_reset_get_status(uint32_t reset, uint32_t *status, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RESET_ASSERT, - reset); - - return pm_ipi_send_sync(primary_proc, payload, status, 1); -} - /** * pm_get_callbackdata() - Read from IPI response buffer * @data - array of PAYLOAD_ARG_CNT elements @@ -381,295 +246,13 @@ void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag) pm_ipi_irq_clear(primary_proc); } -/** - * pm_pinctrl_request() - Request a pin - * @pin Pin ID - * @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_pinctrl_request(uint32_t pin, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_REQUEST, - pin); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_release() - Release a pin - * @pin Pin ID - * @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_pinctrl_release(uint32_t pin, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_RELEASE, - pin); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_set_function() - Set pin function - * @pin Pin ID - * @function Function ID - * @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_pinctrl_set_function(uint32_t pin, uint32_t function, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, - PM_PINCTRL_SET_FUNCTION, pin, function) - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_get_function() - Get function set on the pin - * @pin Pin ID - * @function Function set on the pin - * @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_pinctrl_get_function(uint32_t pin, uint32_t *function, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, - PM_PINCTRL_SET_FUNCTION, pin); - - return pm_ipi_send_sync(primary_proc, payload, function, 1); -} - -/** - * pm_pinctrl_set_pin_param() - Set configuration parameter for the pin - * @pin Pin ID - * @param Parameter ID - * @value 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_pinctrl_set_pin_param(uint32_t pin, 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_PINCTRL_CONFIG_PARAM_SET, pin, param, value); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_pinctrl_get_pin_param() - Get configuration parameter value for the pin - * @pin Pin ID - * @param Parameter ID - * @value Buffer to store 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_pinctrl_get_pin_param(uint32_t pin, 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_PINCTRL_CONFIG_PARAM_GET, pin, param); - - return pm_ipi_send_sync(primary_proc, payload, value, 1); -} - -/** - * pm_clock_enable() - Enable the clock - * @clk_id Clock ID - * @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_clock_enable(uint32_t clk_id, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_ENABLE, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_clock_disable() - Disable the clock - * @clk_id Clock ID - * @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_clock_disable(uint32_t clk_id, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_DISABLE, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_clock_get_state() - Get clock status - * @clk_id Clock ID - * @state: Buffer to store clock status (1: Enabled, 0:Disabled) - * @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_clock_get_state(uint32_t clk_id, uint32_t *state, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETSTATE, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, state, 1); -} - -/** - * pm_clock_set_divider() - Set divider for the clock - * @clk_id Clock ID - * @divider Divider 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_clock_set_divider(uint32_t clk_id, uint32_t divider, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETDIVIDER, - clk_id, divider); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_clock_get_divider() - Get divider value for the clock - * @clk_id Clock ID - * @divider: Buffer to store clock divider 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_clock_get_divider(uint32_t clk_id, uint32_t *divider, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETDIVIDER, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, divider, 1); -} - -/** - * pm_clock_set_parent() - Set parent for the clock - * @clk_id Clock ID - * @parent Parent ID - * @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_clock_set_parent(uint32_t clk_id, uint32_t parent, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETPARENT, - clk_id, parent); - - return pm_ipi_send_sync(primary_proc, payload, NULL, 0); -} - -/** - * pm_clock_get_parent() - Get parent value for the clock - * @clk_id Clock ID - * @parent: Buffer to store clock parent 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_clock_get_parent(uint32_t clk_id, uint32_t *parent, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETPARENT, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, parent, 1); -} -/** - * pm_clock_get_rate() - Get the rate value for the clock - * @clk_id Clock ID - * @rate: Buffer to store clock rate 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_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETRATE, - clk_id); - - return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2); -} - /** * 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 @@ -692,6 +275,11 @@ enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param, /** * 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 @@ -714,6 +302,11 @@ enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, /** * 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 @@ -735,6 +328,11 @@ enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode, /** * 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 @@ -808,22 +406,28 @@ enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype, } /** -* pm_query_data() - PM API for querying firmware data -* @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 -* -* This function returns requested data. -*/ + * 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; + uint32_t version[PAYLOAD_ARG_CNT] = {0}; uint32_t payload[PAYLOAD_ARG_CNT]; uint32_t fw_api_version; @@ -831,25 +435,32 @@ enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid, arg1, arg2, arg3); - ret = pm_feature_check(PM_QUERY_DATA, &version, flag); - if (PM_RET_SUCCESS == ret) { - fw_api_version = version & 0xFFFFU; - if ((2U == fw_api_version) && - ((XPM_QID_CLOCK_GET_NAME == qid) || - (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) { - ret = pm_ipi_send_sync(primary_proc, payload, data, 8); - ret = data[0]; - data[0] = data[1]; - data[1] = data[2]; - data[2] = data[3]; + ret = pm_feature_check(PM_QUERY_DATA, &version[0], flag); + if (ret == PM_RET_SUCCESS) { + fw_api_version = version[0] & 0xFFFF; + 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, 4); + 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 @@ -860,13 +471,13 @@ enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2, * * This function calls IOCTL to firmware for device control and configuration. * - * @return Returns status, either success or error+reason + * @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 *value, uint32_t flag) { - uint32_t payload[PAYLOAD_ARG_CNT]; enum pm_ret_status ret; switch (ioctl_id) { @@ -892,11 +503,7 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, ret = PM_RET_SUCCESS; break; default: - /* Send request to the PMC */ - PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL, - device_id, ioctl_id, arg1, arg2); - ret = pm_ipi_send_sync(primary_proc, payload, value, 1); - break; + return PM_RET_ERROR_NOTSUPPORTED; } return ret; @@ -922,25 +529,6 @@ enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device, return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } -/** - * pm_get_chipid() - Read silicon ID registers - * @value Buffer for return values. Must be large enough - * to hold 8 bytes. - * @flag 0 - Call from secure source - * 1 - Call from non-secure source - * - * @return Returns silicon ID registers - */ -enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_CHIPID); - - return pm_ipi_send_sync(primary_proc, payload, value, 2); -} - /** * pm_feature_check() - Returns the supported API version if supported * @api_id API ID to check @@ -954,71 +542,32 @@ enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version, uint32_t flag) { uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version; - enum pm_ret_status status = PM_RET_ERROR_NOFEATURE; + enum pm_ret_status status; + uint32_t module_id; + + module_id = (api_id & MODULE_ID_MASK) >> 8; + + /* 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; + } switch (api_id) { case PM_GET_CALLBACK_DATA: case PM_GET_TRUSTZONE_VERSION: case PM_LOAD_PDI: *version = (PM_API_BASE_VERSION << 16); - status = PM_RET_SUCCESS; - break; - case PM_GET_API_VERSION: - case PM_GET_DEVICE_STATUS: - case PM_GET_OP_CHARACTERISTIC: - case PM_REQ_SUSPEND: - case PM_SELF_SUSPEND: - case PM_FORCE_POWERDOWN: - case PM_ABORT_SUSPEND: - case PM_REQ_WAKEUP: - case PM_SET_WAKEUP_SOURCE: - case PM_SYSTEM_SHUTDOWN: - case PM_REQUEST_DEVICE: - case PM_RELEASE_DEVICE: - case PM_SET_REQUIREMENT: - case PM_RESET_ASSERT: - case PM_RESET_GET_STATUS: - case PM_GET_CHIPID: - case PM_PINCTRL_REQUEST: - case PM_PINCTRL_RELEASE: - case PM_PINCTRL_GET_FUNCTION: - case PM_PINCTRL_SET_FUNCTION: - case PM_PINCTRL_CONFIG_PARAM_GET: - case PM_PINCTRL_CONFIG_PARAM_SET: - case PM_IOCTL: - 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_CLOCK_GETRATE: - case PM_PLL_SET_PARAMETER: - case PM_PLL_GET_PARAMETER: - case PM_PLL_SET_MODE: - case PM_PLL_GET_MODE: - case PM_FEATURE_CHECK: - case PM_INIT_FINALIZE: - case PM_SET_MAX_LATENCY: - case PM_REGISTER_NOTIFIER: - *version = (PM_API_BASE_VERSION << 16); - status = PM_RET_SUCCESS; - break; + return PM_RET_SUCCESS; case PM_QUERY_DATA: *version = (PM_API_QUERY_DATA_VERSION << 16); - status = PM_RET_SUCCESS; break; default: - *version = 0U; - status = PM_RET_ERROR_NOFEATURE; + *version = (PM_API_BASE_VERSION << 16); break; } - if (status != PM_RET_SUCCESS) { - goto done; - } - PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_FEATURE_CHECK, api_id); @@ -1059,54 +608,6 @@ enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low, return pm_ipi_send_sync(primary_proc, payload, NULL, 0); } -/** - * pm_get_op_characteristic() - PM call to request operating characteristics - * of a device - * @device_id Device id - * @type Type of the operating characteristic - * (power, temperature and latency) - * @result Returns the operating characteristic for the requested device, - * specified by the type - * @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_get_op_characteristic(uint32_t device_id, - enum pm_opchar_type type, - uint32_t *result, uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, - PM_GET_OP_CHARACTERISTIC, device_id, type); - return pm_ipi_send_sync(primary_proc, payload, result, 1); -} - -/** - * pm_set_max_latency() - PM call to change in the maximum wake-up latency - * requirements for a specific device currently - * used by that CPU. - * @device_id Device ID - * @latency Latency 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_set_max_latency(uint32_t device_id, uint32_t latency, - uint32_t flag) -{ - uint32_t payload[PAYLOAD_ARG_CNT]; - - /* Send request to the PMC */ - PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SET_MAX_LATENCY, - device_id, latency); - - 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 diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 5a927043e..b44b59039 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -14,8 +14,9 @@ * PM API function declarations **********************************************************/ -enum pm_ret_status pm_get_api_version(unsigned int *version, uint32_t flag); -enum pm_ret_status pm_init_finalize(uint32_t flag); +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, unsigned int latency, unsigned int state, @@ -29,42 +30,7 @@ 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_request_device(uint32_t device_id, uint32_t capabilities, - uint32_t qos, uint32_t ack, uint32_t flag); -enum pm_ret_status pm_release_device(uint32_t device_id, uint32_t flag); -enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, - uint32_t latency, uint32_t qos, - uint32_t flag); -enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response, - uint32_t flag); -enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert, uint32_t flag); -enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status, - uint32_t flag); void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag); -enum pm_ret_status pm_pinctrl_request(uint32_t pin, uint32_t flag); -enum pm_ret_status pm_pinctrl_release(uint32_t pin, uint32_t flag); -enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function, - uint32_t flag); -enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function, - uint32_t flag); -enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, - uint32_t value, uint32_t flag); -enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, - uint32_t *value, uint32_t flag); -enum pm_ret_status pm_clock_enable(uint32_t clk_id, uint32_t flag); -enum pm_ret_status pm_clock_disable(uint32_t clk_id, uint32_t flag); -enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state, - uint32_t flag); -enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider, - uint32_t flag); -enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider, - uint32_t flag); -enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent, - uint32_t flag); -enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent, - uint32_t flag); -enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, - uint32_t flag); 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, @@ -83,16 +49,10 @@ enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, 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); unsigned int pm_get_shutdown_scope(void); -enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag); enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version, 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_get_op_characteristic(uint32_t device_id, - enum pm_opchar_type type, - uint32_t *result, uint32_t flag); -enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency, - 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); diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index 08b46e2d1..8b6286995 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -42,9 +42,6 @@ #define PM_API_QUERY_DATA_VERSION 2U /* PM API ids */ -#define PM_GET_API_VERSION 1U -#define PM_GET_DEVICE_STATUS 3U -#define PM_GET_OP_CHARACTERISTIC 4U #define PM_REGISTER_NOTIFIER 5U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U @@ -53,31 +50,8 @@ #define PM_REQ_WAKEUP 10U #define PM_SET_WAKEUP_SOURCE 11U #define PM_SYSTEM_SHUTDOWN 12U -#define PM_REQUEST_DEVICE 13U -#define PM_RELEASE_DEVICE 14U -#define PM_SET_REQUIREMENT 15U -#define PM_SET_MAX_LATENCY 16U -#define PM_RESET_ASSERT 17U -#define PM_RESET_GET_STATUS 18U -#define PM_INIT_FINALIZE 21U -#define PM_GET_CHIPID 24U -#define PM_PINCTRL_REQUEST 28U -#define PM_PINCTRL_RELEASE 29U -#define PM_PINCTRL_GET_FUNCTION 30U -#define PM_PINCTRL_SET_FUNCTION 31U -#define PM_PINCTRL_CONFIG_PARAM_GET 32U -#define PM_PINCTRL_CONFIG_PARAM_SET 33U #define PM_IOCTL 34U #define PM_QUERY_DATA 35U -#define PM_CLOCK_ENABLE 36U -#define PM_CLOCK_DISABLE 37U -#define PM_CLOCK_GETSTATE 38U -#define PM_CLOCK_SETDIVIDER 39U -#define PM_CLOCK_GETDIVIDER 40U -#define PM_CLOCK_SETRATE 41U -#define PM_CLOCK_GETRATE 42U -#define PM_CLOCK_SETPARENT 43U -#define PM_CLOCK_GETPARENT 44U #define PM_PLL_SET_PARAMETER 48U #define PM_PLL_GET_PARAMETER 49U #define PM_PLL_SET_MODE 50U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index b082acbd5..f1f3991c9 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -114,49 +114,82 @@ int pm_setup(void) } /** - * 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 + * eemi_for_compatibility() - EEMI calls handler for deprecated calls * - * @return - Unused + * @return - If EEMI API found then, uintptr_t type address, else 0 * - * 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 + * 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. */ -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) +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; - uint32_t pm_arg[4]; - uint32_t security_flag = SECURE_FLAG; + switch (api_id) { - /* Handle case where PM wasn't initialized properly */ - if (pm_up == false) { - SMC_RET1(handle, SMC_UNK); + case PM_IOCTL: + { + uint32_t value; + + ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value, security_flag); + if (ret == PM_RET_ERROR_NOTSUPPORTED) + return (uintptr_t)0; + + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } - 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); + case PM_QUERY_DATA: + { + uint32_t data[PAYLOAD_ARG_CNT] = { 0 }; - /* - * 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; + 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] << 32), + (uint64_t)data[1] | ((uint64_t)data[2] << 32)); } - switch (smc_fid & FUNCID_NUM_MASK) { - /* PM API Functions */ + case PM_FEATURE_CHECK: + { + uint32_t version; + + ret = pm_feature_check(pm_arg[0], &version, security_flag); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)version << 32)); + } + + 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); @@ -179,65 +212,22 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag); SMC_RET1(handle, (uint64_t)ret); - case PM_REQ_WAKEUP: - ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3], - security_flag); - 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], - security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_REQUEST_DEVICE: - ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_RELEASE_DEVICE: - ret = pm_release_device(pm_arg[0], security_flag); - 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], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_GET_API_VERSION: - { - uint32_t api_version; - - ret = pm_get_api_version(&api_version, security_flag); - SMC_RET1(handle, (u_register_t)PM_RET_SUCCESS | - ((u_register_t)api_version << 32)); + default: + return (uintptr_t)0; } +} - case PM_GET_DEVICE_STATUS: - { - uint32_t buff[3]; - - ret = pm_get_device_status(pm_arg[0], buff, security_flag); - SMC_RET2(handle, (u_register_t)ret | ((u_register_t)buff[0] << 32), - (u_register_t)buff[1] | ((u_register_t)buff[2] << 32)); - } - - case PM_RESET_ASSERT: - ret = pm_reset_assert(pm_arg[0], pm_arg[1], security_flag); - 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, - security_flag); - SMC_RET1(handle, (u_register_t)ret | - ((u_register_t)reset_status << 32)); - } - - case PM_INIT_FINALIZE: - ret = pm_init_finalize(security_flag); - SMC_RET1(handle, (uint64_t)ret); +/** + * 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 PM_GET_CALLBACK_DATA: { @@ -245,192 +235,115 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag); SMC_RET2(handle, - (u_register_t)result[0] | ((u_register_t)result[1] << 32), - (u_register_t)result[2] | ((u_register_t)result[3] << 32)); - } - - case PM_PINCTRL_REQUEST: - ret = pm_pinctrl_request(pm_arg[0], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_RELEASE: - ret = pm_pinctrl_release(pm_arg[0], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_GET_FUNCTION: - { - uint32_t value = 0; - - ret = pm_pinctrl_get_function(pm_arg[0], &value, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_PINCTRL_SET_FUNCTION: - ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1], - security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PINCTRL_CONFIG_PARAM_GET: - { - uint32_t value; - - ret = pm_pinctrl_get_pin_param(pm_arg[0], pm_arg[1], &value, - security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_PINCTRL_CONFIG_PARAM_SET: - ret = pm_pinctrl_set_pin_param(pm_arg[0], pm_arg[1], pm_arg[2], - security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_IOCTL: - { - uint32_t value; - - ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], &value, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_QUERY_DATA: - { - uint32_t data[8] = { 0 }; - - ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], data, security_flag); - - SMC_RET2(handle, (u_register_t)ret | ((u_register_t)data[0] << 32), - (u_register_t)data[1] | ((u_register_t)data[2] << 32)); - - } - case PM_CLOCK_ENABLE: - ret = pm_clock_enable(pm_arg[0], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_CLOCK_DISABLE: - ret = pm_clock_disable(pm_arg[0], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_CLOCK_GETSTATE: - { - uint32_t value; - - ret = pm_clock_get_state(pm_arg[0], &value, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_CLOCK_SETDIVIDER: - ret = pm_clock_set_divider(pm_arg[0], pm_arg[1], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_CLOCK_GETDIVIDER: - { - uint32_t value; - - ret = pm_clock_get_divider(pm_arg[0], &value, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_CLOCK_SETPARENT: - ret = pm_clock_set_parent(pm_arg[0], pm_arg[1], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_CLOCK_GETPARENT: - { - uint32_t value; - - ret = pm_clock_get_parent(pm_arg[0], &value, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); - } - - case PM_CLOCK_GETRATE: - { - uint32_t rate[2] = { 0 }; - - ret = pm_clock_get_rate(pm_arg[0], rate, security_flag); - SMC_RET2(handle, (u_register_t)ret | ((u_register_t)rate[0] << 32), - (u_register_t)rate[1] | ((u_register_t)0U << 32)); - } - - case PM_PLL_SET_PARAMETER: - ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2], - security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PLL_GET_PARAMETER: - { - uint32_t value; - - ret = pm_pll_get_param(pm_arg[0], pm_arg[1], &value, - security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value << 32)); - } - - case PM_PLL_SET_MODE: - ret = pm_pll_set_mode(pm_arg[0], pm_arg[1], security_flag); - SMC_RET1(handle, (uint64_t)ret); - - case PM_PLL_GET_MODE: - { - uint32_t mode; - - ret = pm_pll_get_mode(pm_arg[0], &mode, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)mode << 32)); + (uint64_t)result[0] | ((uint64_t)result[1] << 32), + (uint64_t)result[2] | ((uint64_t)result[3] << 32)); } case PM_GET_TRUSTZONE_VERSION: SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | ((uint64_t)VERSAL_TZ_VERSION << 32)); - case PM_GET_CHIPID: - { - uint32_t result[2]; - - ret = pm_get_chipid(result, security_flag); - SMC_RET2(handle, (u_register_t)ret | ((u_register_t)result[0] << 32), - (u_register_t)result[1] | ((u_register_t)0U << 32)); - } - - case PM_FEATURE_CHECK: - { - uint32_t version; - - ret = pm_feature_check(pm_arg[0], &version, security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)version << 32)); - } - - case PM_LOAD_PDI: - { - ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2], - security_flag); - SMC_RET1(handle, (u_register_t)ret); - } - - case PM_GET_OP_CHARACTERISTIC: - { - uint32_t result; - - ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result, - security_flag); - SMC_RET1(handle, (u_register_t)ret | ((u_register_t)result << 32)); - } - - case PM_SET_MAX_LATENCY: - { - ret = pm_set_max_latency(pm_arg[0], pm_arg[1], security_flag); - SMC_RET1(handle, (u_register_t)ret); - } - - case PM_REGISTER_NOTIFIER: - { - ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], security_flag); - SMC_RET1(handle, (u_register_t)ret); - } - default: - WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); - SMC_RET1(handle, SMC_UNK); + 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] << 32), + (uint64_t)buf[2] | ((uint64_t)buf[3] << 32)); + } + } + + SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buf[0] << 32), + (uint64_t)buf[1] | ((uint64_t)buf[2] << 32)); +} + +/** + * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2. + * @smc_fid - Function Identifier + * @x1 - x4 - SMC64 Arguments from kernel + * x3 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, 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) + 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)) { + security_flag = NON_SECURE_FLAG; + } + + 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); + (void)(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; +}