diff mbox series

spmi: msm: bound the CMD_DONE poll with a timeout

Message ID 20261002-b4-qcom-spmi-v1-1-33fbd16ee559@protonmail.com
State New
Delegated to: Casey Connolly
Headers show
Series spmi: msm: bound the CMD_DONE poll with a timeout | expand

Commit Message

Petr Hodina via B4 Relay Oct. 2, 2026, 9:36 p.m. UTC
From: Petr Hodina <petr.hodina@protonmail.com>

msm_spmi_write()/msm_spmi_read() busy-wait in inifinte loop.
Bound the wait with readl_poll_timeout() and return -ETIMEDOUT on
failure when the PMIC peripheral does not respond.

Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
---
Tested on Xiaomi Pad 5 (nabu) hardware: pm8150l's WLED node
on usid 5 never returns CMD_DONE.

msm_spmi_write()/msm_spmi_read() busy-wait on CMD_DONE with no
timeout. Therefore one unresponsive PMIC peripheral hangs boot
indefinitely.

Bound the wait with readl_poll_timeout() so DM can fail that one
device's probe instead of halting the whole boot.
---
 drivers/spmi/spmi-msm.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)


---
base-commit: ece349ade2973e220f524ce59e59711cc919263f
change-id: 20261002-b4-qcom-spmi-a3c44ca5d952

Best regards,
--  
Petr Hodina <petr.hodina@protonmail.com>

Comments

Abel Vesa Oct. 9, 2026, 12:10 p.m. UTC | #1
On 26-10-02 23:36:12, Petr Hodina via B4 Relay wrote:
> From: Petr Hodina <petr.hodina@protonmail.com>
> 
> msm_spmi_write()/msm_spmi_read() busy-wait in inifinte loop.
> Bound the wait with readl_poll_timeout() and return -ETIMEDOUT on
> failure when the PMIC peripheral does not respond.
> 
> Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>

Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
Aswin Murugan Oct. 9, 2026, 4:02 p.m. UTC | #2
On 10/3/2026 3:06 AM, Petr Hodina via B4 Relay wrote:
> From: Petr Hodina <petr.hodina@protonmail.com>
>
> msm_spmi_write()/msm_spmi_read() busy-wait in inifinte loop.
> Bound the wait with readl_poll_timeout() and return -ETIMEDOUT on
> failure when the PMIC peripheral does not respond.
>
> Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Reviewed-by: Aswin Murugan <aswin.murugan@oss.qualcomm.com>
diff mbox series

Patch

diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c
index b89dd0b406b..92cd42d8627 100644
--- a/drivers/spmi/spmi-msm.c
+++ b/drivers/spmi/spmi-msm.c
@@ -12,8 +12,11 @@ 
 #include <fdtdec.h>
 #include <asm/io.h>
 #include <dm/device_compat.h>
+#include <linux/iopoll.h>
 #include <spmi/spmi.h>
 
+#define SPMI_CMD_DONE_TIMEOUT_US 100000
+
 /* PMIC Arbiter configuration registers */
 #define PMIC_ARB_VERSION 0x0000
 #define PMIC_ARB_VERSION_V2_MIN 0x20010000
@@ -161,10 +164,10 @@  static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off,
 	writel(reg, priv->spmi_chnls + ch_offset + SPMI_REG_CMD0);
 
 	/* Wait till CMD DONE status */
-	reg = 0;
-	while (!reg) {
-		reg = readl(priv->spmi_chnls + ch_offset +
-			    SPMI_REG_STATUS);
+	if (readl_poll_timeout(priv->spmi_chnls + ch_offset + SPMI_REG_STATUS,
+			       reg, reg, SPMI_CMD_DONE_TIMEOUT_US)) {
+		printf("SPMI write timeout (channel %#x).\n", ch_offset);
+		return -ETIMEDOUT;
 	}
 
 	if (reg ^ SPMI_STATUS_DONE) {
@@ -231,9 +234,10 @@  static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off)
 	writel(reg, priv->spmi_obs + ch_offset + SPMI_REG_CMD0);
 
 	/* Wait till CMD DONE status */
-	reg = 0;
-	while (!reg) {
-		reg = readl(priv->spmi_obs + ch_offset + SPMI_REG_STATUS);
+	if (readl_poll_timeout(priv->spmi_obs + ch_offset + SPMI_REG_STATUS,
+			       reg, reg, SPMI_CMD_DONE_TIMEOUT_US)) {
+		printf("SPMI read timeout (channel %#x).\n", ch_offset);
+		return -ETIMEDOUT;
 	}
 
 	if (reg ^ SPMI_STATUS_DONE) {