diff options
-rw-r--r-- | drivers/firmware/ti_sci.c | 57 | ||||
-rw-r--r-- | drivers/firmware/ti_sci.h | 3 |
2 files changed, 58 insertions, 2 deletions
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index ae5fd1936ad3..49fd2ae01055 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -2015,6 +2015,47 @@ fail: return ret; } +/** + * ti_sci_cmd_lpm_abort() - Abort entry to LPM by clearing selection of LPM to enter + * @dev: Device pointer corresponding to the SCI entity + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_lpm_abort(struct device *dev) +{ + struct ti_sci_info *info = dev_get_drvdata(dev); + struct ti_sci_msg_hdr *req; + struct ti_sci_msg_hdr *resp; + struct ti_sci_xfer *xfer; + int ret = 0; + + xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_ABORT, + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, + sizeof(*req), sizeof(*resp)); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) { + dev_err(dev, "Mbox send fail %d\n", ret); + goto fail; + } + + resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; + + if (!ti_sci_is_response_ack(resp)) + ret = -ENODEV; + +fail: + ti_sci_put_one_xfer(&info->minfo, xfer); + + return ret; +} + static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle) { struct ti_sci_info *info; @@ -3739,11 +3780,22 @@ static int __maybe_unused ti_sci_resume_noirq(struct device *dev) return 0; } +static void __maybe_unused ti_sci_pm_complete(struct device *dev) +{ + struct ti_sci_info *info = dev_get_drvdata(dev); + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT) { + if (ti_sci_cmd_lpm_abort(dev)) + dev_err(dev, "LPM clear selection failed.\n"); + } +} + static const struct dev_pm_ops ti_sci_pm_ops = { #ifdef CONFIG_PM_SLEEP .suspend = ti_sci_suspend, .suspend_noirq = ti_sci_suspend_noirq, .resume_noirq = ti_sci_resume_noirq, + .complete = ti_sci_pm_complete, #endif }; @@ -3876,10 +3928,11 @@ static int ti_sci_probe(struct platform_device *pdev) } ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); - dev_dbg(dev, "Detected firmware capabilities: %s%s%s\n", + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s\n", info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", - info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "" + info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "" ); ti_sci_setup_ops(info); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 053387d7baa0..701c416b2e78 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -42,6 +42,7 @@ #define TI_SCI_MSG_SET_IO_ISOLATION 0x0307 #define TI_SCI_MSG_LPM_SET_DEVICE_CONSTRAINT 0x0309 #define TI_SCI_MSG_LPM_SET_LATENCY_CONSTRAINT 0x030A +#define TI_SCI_MSG_LPM_ABORT 0x0311 /* Resource Management Requests */ #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 @@ -147,6 +148,7 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported) * MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM + * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -157,6 +159,7 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_GENERIC TI_SCI_MSG_FLAG(0) #define MSG_FLAG_CAPS_LPM_PARTIAL_IO TI_SCI_MSG_FLAG(4) #define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) +#define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) u64 fw_caps; } __packed; |