[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250819195453.1094520-1-k-willis@ti.com>
Date: Tue, 19 Aug 2025 14:54:53 -0500
From: Kendall Willis <k-willis@...com>
To: <nm@...com>, <kristo@...nel.org>, <ssantosh@...nel.org>,
<linux-arm-kernel@...ts.infradead.org>, <linux-kernel@...r.kernel.org>
CC: <ulf.hansson@...aro.org>, <d-gole@...com>, <vishalm@...com>,
<sebin.francis@...com>, <msp@...libre.com>, <khilman@...libre.com>,
<k-willis@...com>
Subject: [PATCH v4] 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@...com>
Reviewed-by: Ulf Hansson <ulf.hansson@...aro.org>
---
Series has been tested on an SK-AM62B-P1 board. Normal suspend/resume
has been verified. Abort was tested by adding an error into the TI SCI
suspend hook.
Link to v3:
https://lore.kernel.org/all/20250709221619.2237699-1-k-willis@ti.com/
Link to v2:
https://lore.kernel.org/all/20250709205332.2235072-1-k-willis@ti.com/
Link to v1:
https://lore.kernel.org/all/20250627204821.1150459-1-k-willis@ti.com/
Changes from v3 to v4:
- rebase on linux-next
- reword commit message
- change ti_sci_cmd_lpm_abort parameter to be the device pointer
- remove setting ret to 0 when checking for failure in
ti_sci_cmd_lpm_abort since ret is set to 0 by default
- change ti_sci_complete() to ti_sci_pm_complete()
- add firmware capability support for LPM abort
- update debug message of detected firmware capabilities with
LPM-Abort
- check if the firmware has the capability for LPM abort functionality
before calling ti_sci_cmd_lpm_abort
- remove updated year in the ti_sci.h license
Changes from v2 to v3:
- added links to previous series and the changes between them
Changes from v1 to v2:
- rebase on linux-next
- drop the following patch:
pmdomain: ti_sci: Add LPM abort sequence to suspend path
- remove lpm_abort from ti_sci_pm_ops
- add ->complete() hook with ti_sci_cmd_lpm_abort to be called
unconditionally within it
- remove ti_sci_cmd_lpm_abort from the ->suspend() and
->suspend_noirq() hooks
- reword commit message
---
drivers/firmware/ti_sci.c | 57 +++++++++++++++++++++++++++++++++++++--
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 ae5fd1936ad32..49fd2ae01055d 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2015,6 +2015,47 @@ static int ti_sci_cmd_set_latency_constraint(const struct ti_sci_handle *handle,
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 053387d7baa06..701c416b2e78f 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;
base-commit: 886e5e7b0432360842303d587bb4a65d10741ae8
--
2.34.1
Powered by blists - more mailing lists