Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: ti_sci: Enable abort handling of entry to LPM

The PM co-processor (device manager or DM) adds the ability to abort
entry to a low power mode by clearing the mode selection in the
latest version of its firmware (11.01.09) [1].

Enable the ti_sci driver to support the LPM abort call which clears the
low power mode selection of the DM. This fixes an issue where failed
system suspend attempts would cause subsequent suspends to fail.

After system suspend completes, regardless of if system suspend succeeds
or fails, the ->complete() hook in TI SCI will be called. In the
->complete() hook, a message will be sent to the DM to clear the current
low power mode selection. Clearing the low power mode selection
unconditionally will not cause any error in the DM.

[1] https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html

Signed-off-by: Kendall Willis <k-willis@ti.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://patch.msgid.link/20250819195453.1094520-1-k-willis@ti.com
Signed-off-by: Nishanth Menon <nm@ti.com>

authored by

Kendall Willis and committed by
Nishanth Menon
0fdd3240 a5039648

+58 -2
+55 -2
drivers/firmware/ti_sci.c
··· 2015 2015 return ret; 2016 2016 } 2017 2017 2018 + /** 2019 + * ti_sci_cmd_lpm_abort() - Abort entry to LPM by clearing selection of LPM to enter 2020 + * @dev: Device pointer corresponding to the SCI entity 2021 + * 2022 + * Return: 0 if all went well, else returns appropriate error value. 2023 + */ 2024 + static int ti_sci_cmd_lpm_abort(struct device *dev) 2025 + { 2026 + struct ti_sci_info *info = dev_get_drvdata(dev); 2027 + struct ti_sci_msg_hdr *req; 2028 + struct ti_sci_msg_hdr *resp; 2029 + struct ti_sci_xfer *xfer; 2030 + int ret = 0; 2031 + 2032 + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_ABORT, 2033 + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, 2034 + sizeof(*req), sizeof(*resp)); 2035 + if (IS_ERR(xfer)) { 2036 + ret = PTR_ERR(xfer); 2037 + dev_err(dev, "Message alloc failed(%d)\n", ret); 2038 + return ret; 2039 + } 2040 + req = (struct ti_sci_msg_hdr *)xfer->xfer_buf; 2041 + 2042 + ret = ti_sci_do_xfer(info, xfer); 2043 + if (ret) { 2044 + dev_err(dev, "Mbox send fail %d\n", ret); 2045 + goto fail; 2046 + } 2047 + 2048 + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; 2049 + 2050 + if (!ti_sci_is_response_ack(resp)) 2051 + ret = -ENODEV; 2052 + 2053 + fail: 2054 + ti_sci_put_one_xfer(&info->minfo, xfer); 2055 + 2056 + return ret; 2057 + } 2058 + 2018 2059 static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) 2019 2060 { 2020 2061 struct ti_sci_info *info; ··· 3780 3739 return 0; 3781 3740 } 3782 3741 3742 + static void __maybe_unused ti_sci_pm_complete(struct device *dev) 3743 + { 3744 + struct ti_sci_info *info = dev_get_drvdata(dev); 3745 + 3746 + if (info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT) { 3747 + if (ti_sci_cmd_lpm_abort(dev)) 3748 + dev_err(dev, "LPM clear selection failed.\n"); 3749 + } 3750 + } 3751 + 3783 3752 static const struct dev_pm_ops ti_sci_pm_ops = { 3784 3753 #ifdef CONFIG_PM_SLEEP 3785 3754 .suspend = ti_sci_suspend, 3786 3755 .suspend_noirq = ti_sci_suspend_noirq, 3787 3756 .resume_noirq = ti_sci_resume_noirq, 3757 + .complete = ti_sci_pm_complete, 3788 3758 #endif 3789 3759 }; 3790 3760 ··· 3928 3876 } 3929 3877 3930 3878 ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); 3931 - dev_dbg(dev, "Detected firmware capabilities: %s%s%s\n", 3879 + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s\n", 3932 3880 info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", 3933 3881 info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", 3934 - info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "" 3882 + info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", 3883 + info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "" 3935 3884 ); 3936 3885 3937 3886 ti_sci_setup_ops(info);
+3
drivers/firmware/ti_sci.h
··· 42 42 #define TI_SCI_MSG_SET_IO_ISOLATION 0x0307 43 43 #define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309 44 44 #define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A 45 + #define TI_SCI_MSG_LPM_ABORT 0x0311 45 46 46 47 /* Resource Management Requests */ 47 48 #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 ··· 148 147 * MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported) 149 148 * MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM 150 149 * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM 150 + * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM 151 151 * 152 152 * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS 153 153 * providing currently available SOC/firmware capabilities. SoC that don't ··· 159 157 #define MSG_FLAG_CAPS_GENERIC TI_SCI_MSG_FLAG(0) 160 158 #define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4) 161 159 #define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) 160 + #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) 162 161 #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) 163 162 u64 fw_caps; 164 163 } __packed;