diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c index 8b77050da..5c6ba6b35 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -1740,3 +1740,41 @@ int ti_sci_enter_sleep(uint8_t proc_id, return 0; } + +/** + * ti_sci_lpm_get_next_sys_mode() - Get next LPM system mode + * + * @next_mode: pointer to a variable that will store the next mode + * + * Return: 0 if all goes well, else appropriate error message + */ +int ti_sci_lpm_get_next_sys_mode(uint8_t *next_mode) +{ + struct ti_sci_msg_req_lpm_get_next_sys_mode req; + struct ti_sci_msg_resp_lpm_get_next_sys_mode resp; + struct ti_sci_xfer xfer; + int ret; + + if (next_mode == NULL) { + return -EINVAL; + } + + ret = ti_sci_setup_one_xfer(TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE, 0, + &req, sizeof(req), + &resp, sizeof(resp), + &xfer); + if (ret != 0) { + ERROR("Message alloc failed (%d)\n", ret); + return ret; + } + + ret = ti_sci_do_xfer(&xfer); + if (ret != 0) { + ERROR("Transfer send failed (%d)\n", ret); + return ret; + } + + *next_mode = resp.mode; + + return 0; +} diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h index acaca4d04..06d1f8d6c 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h @@ -252,6 +252,11 @@ int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, * @mode: Low power mode to enter. * @core_resume_addr: Address that core should be resumed from * after low power transition. + * - ti_sci_lpm_get_next_sys_mode - Get next LPM system mode + * + * @next_mode: pointer to a variable that will store the next mode + * + * Return: 0 if all goes well, else appropriate error message * * NOTE: for all these functions, the following are generic in nature: * Returns 0 for successful request, else returns corresponding error message. @@ -259,5 +264,6 @@ int ti_sci_proc_wait_boot_status_no_wait(uint8_t proc_id, int ti_sci_enter_sleep(uint8_t proc_id, uint8_t mode, uint64_t core_resume_addr); +int ti_sci_lpm_get_next_sys_mode(uint8_t *next_mode); #endif /* TI_SCI_H */ diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h index 7f1c3683a..cc71eac6f 100644 --- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -31,6 +31,7 @@ /* Low Power Mode Requests */ #define TI_SCI_MSG_ENTER_SLEEP 0x0301 +#define TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE 0x030d /* Clock requests */ #define TI_SCI_MSG_SET_CLOCK_STATE 0x0100 @@ -133,6 +134,7 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_LPM_MCU_ONLY: MCU only LPM * MSG_FLAG_CAPS_LPM_STANDBY: Standby LPM * MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM + * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -145,6 +147,7 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_LPM_MCU_ONLY TI_SCI_MSG_FLAG(2) #define MSG_FLAG_CAPS_LPM_STANDBY TI_SCI_MSG_FLAG(3) #define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4) +#define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) uint64_t fw_caps; } __packed; @@ -764,10 +767,35 @@ struct ti_sci_msg_req_wait_proc_boot_status { */ struct ti_sci_msg_req_enter_sleep { struct ti_sci_msg_hdr hdr; +#define MSG_VALUE_SLEEP_MODE_DEEP_SLEEP 0x0 uint8_t mode; uint8_t processor_id; uint32_t core_resume_lo; uint32_t core_resume_hi; } __packed; +/** + * struct ti_sci_msg_req_lpm_get_next_sys_mode - Request for TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE. + * + * @hdr Generic Header + * + * This message is used to enquire DM for selected system wide low power mode. + */ +struct ti_sci_msg_req_lpm_get_next_sys_mode { + struct ti_sci_msg_hdr hdr; +} __packed; + +/** + * struct ti_sci_msg_resp_lpm_get_next_sys_mode - Response for TI_SCI_MSG_LPM_GET_NEXT_SYS_MODE. + * + * @hdr Generic Header + * @mode The selected system wide low power mode. + * + * Note: If the mode selection is not yet locked, this API returns "not selected" mode. + */ +struct ti_sci_msg_resp_lpm_get_next_sys_mode { + struct ti_sci_msg_hdr hdr; + uint8_t mode; +} __packed; + #endif /* TI_SCI_PROTOCOL_H */ diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c index e8d73dbd5..df49f4894 100644 --- a/plat/ti/k3/common/k3_psci.c +++ b/plat/ti/k3/common/k3_psci.c @@ -234,7 +234,7 @@ static int k3_validate_power_state(unsigned int power_state, return PSCI_E_SUCCESS; } -static void k3_pwr_domain_suspend(const psci_power_state_t *target_state) +static void k3_pwr_domain_suspend_to_mode(const psci_power_state_t *target_state, uint8_t mode) { unsigned int core, proc_id; @@ -247,7 +247,25 @@ static void k3_pwr_domain_suspend(const psci_power_state_t *target_state) k3_pwr_domain_off(target_state); - ti_sci_enter_sleep(proc_id, 0, k3_sec_entrypoint); + ti_sci_enter_sleep(proc_id, mode, k3_sec_entrypoint); +} + +static void k3_pwr_domain_suspend_dm_managed(const psci_power_state_t *target_state) +{ + uint8_t mode = MSG_VALUE_SLEEP_MODE_DEEP_SLEEP; + int ret; + + ret = ti_sci_lpm_get_next_sys_mode(&mode); + if (ret != 0) { + ERROR("Failed to fetch next system mode\n"); + } + + k3_pwr_domain_suspend_to_mode(target_state, mode); +} + +static void k3_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + k3_pwr_domain_suspend_to_mode(target_state, MSG_VALUE_SLEEP_MODE_DEEP_SLEEP); } static void k3_pwr_domain_suspend_finish(const psci_power_state_t *target_state) @@ -301,6 +319,8 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, k3_plat_psci_ops.pwr_domain_suspend = NULL; k3_plat_psci_ops.pwr_domain_suspend_finish = NULL; k3_plat_psci_ops.get_sys_suspend_power_state = NULL; + } else if (fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { + k3_plat_psci_ops.pwr_domain_suspend = k3_pwr_domain_suspend_dm_managed; } *psci_ops = &k3_plat_psci_ops;