diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.c b/plat/xilinx/versal/pm_service/pm_api_sys.c index 1b32e4bd9..be28a41ae 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.c +++ b/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -572,3 +572,43 @@ enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode) return pm_ipi_send_sync(primary_proc, payload, mode, 1); } + +/** + * pm_force_powerdown() - PM call to request for another PU or subsystem to + * be powered down forcefully + * @target Device ID of the PU node to be forced powered down. + * @ack Flag to specify whether acknowledge is requested + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_FORCE_POWERDOWN, target, + ack); + + if (ack == IPI_BLOCKING) + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); + else + return pm_ipi_send(primary_proc, payload); +} + +/** + * pm_system_shutdown() - PM call to request a system shutdown or restart + * @type Shutdown or restart? 0=shutdown, 1=restart + * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SYSTEM_SHUTDOWN, type, + subtype); + + return pm_ipi_send_non_blocking(primary_proc, payload); +} diff --git a/plat/xilinx/versal/pm_service/pm_api_sys.h b/plat/xilinx/versal/pm_service/pm_api_sys.h index 025255bda..375199549 100644 --- a/plat/xilinx/versal/pm_service/pm_api_sys.h +++ b/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -53,5 +53,7 @@ enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param, uint32_t *value); enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode); enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode); +enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack); +enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype); #endif /* PM_API_SYS_H */ diff --git a/plat/xilinx/versal/pm_service/pm_defs.h b/plat/xilinx/versal/pm_service/pm_defs.h index ce2605a14..248c7151f 100644 --- a/plat/xilinx/versal/pm_service/pm_defs.h +++ b/plat/xilinx/versal/pm_service/pm_defs.h @@ -27,7 +27,9 @@ #define PM_GET_DEVICE_STATUS 3U #define PM_REQ_SUSPEND 6U #define PM_SELF_SUSPEND 7U +#define PM_FORCE_POWERDOWN 8U #define PM_ABORT_SUSPEND 9U +#define PM_SYSTEM_SHUTDOWN 12U #define PM_REQUEST_DEVICE 13U #define PM_RELEASE_DEVICE 14U #define PM_SET_REQUIREMENT 15U diff --git a/plat/xilinx/versal/pm_service/pm_svc_main.c b/plat/xilinx/versal/pm_service/pm_svc_main.c index 5dd315799..aa008ac9b 100644 --- a/plat/xilinx/versal/pm_service/pm_svc_main.c +++ b/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -88,6 +88,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, pm_arg[3]); SMC_RET1(handle, (uint64_t)ret); + case PM_FORCE_POWERDOWN: + ret = pm_force_powerdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQ_SUSPEND: ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]); @@ -97,6 +101,10 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, ret = pm_abort_suspend(pm_arg[0]); SMC_RET1(handle, (uint64_t)ret); + case PM_SYSTEM_SHUTDOWN: + ret = pm_system_shutdown(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + case PM_REQUEST_DEVICE: ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);