From 2f93e4331edd8915a739091bf01fe2acad0a54c9 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Thu, 19 Mar 2026 19:53:58 +0000 Subject: [PATCH] soc/qualcomm/common: Add spmi_read8_safe helper with retry logic Introduce `spmi_read8_safe` to handle transient SPMI bus errors that can occur during early power sequencing. This helper implements a retry mechanism (up to 6 attempts) with a 50ms delay between reads. Providing a "safe" read wrapper prevents the system from misinterpreting transient arbiter errors (ERROR_SPMI_READ_FAILED) as valid zero data, which is critical for preventing premature power-offs when reading input current . BUG=b:436391478 BRANCH=none TEST=Verified that SPMI read failures in the charging applet now trigger the retry loop and successfully recover on Bluey. Change-Id: Id1b770d2cd91ccb069933bd9b023b867a7507009 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/91766 Tested-by: build bot (Jenkins) Reviewed-by: Kapil Porwal --- .../qualcomm/common/include/soc/qcom_spmi.h | 1 + src/soc/qualcomm/common/spmi.c | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/soc/qualcomm/common/include/soc/qcom_spmi.h b/src/soc/qualcomm/common/include/soc/qcom_spmi.h index 65d2e17bba..ef22d22377 100644 --- a/src/soc/qualcomm/common/include/soc/qcom_spmi.h +++ b/src/soc/qualcomm/common/include/soc/qcom_spmi.h @@ -12,5 +12,6 @@ int spmi_read8(uint32_t addr); int spmi_write8(uint32_t addr, uint8_t data); int spmi_read_bytes(uint32_t addr, uint8_t *data, uint32_t num_bytes); +int spmi_read8_safe(uint32_t reg); #endif // __SOC_QCOM_SPMI_H__ diff --git a/src/soc/qualcomm/common/spmi.c b/src/soc/qualcomm/common/spmi.c index 2409cbbf23..295dbc1ecf 100644 --- a/src/soc/qualcomm/common/spmi.c +++ b/src/soc/qualcomm/common/spmi.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -19,9 +20,14 @@ #define ERROR_APID_NOT_FOUND (-(int)BIT(8)) #define ERROR_TIMEOUT (-(int)BIT(9)) +/* Add this for your specific SPMI read error (-9) */ +#define ERROR_SPMI_READ_FAILED (-9) #define ARB_COMMAND_TIMEOUT_MS 100 +#define MAX_SPMI_RETRIES 6 +#define SPMI_RETRY_DELAY_MS 50 + // Individual register block per APID struct qcom_spmi_regs { uint32_t cmd; @@ -101,7 +107,7 @@ int spmi_read8(uint32_t addr) int ret = wait_for_done(regs); if (ret != 0) { printk(BIOS_ERR, "ERROR: SPMI_ARB read error [0x%x]: 0x%x\n", addr, ret); - return ret; + return ERROR_SPMI_READ_FAILED; } return read32(®s->rdata0) & 0xff; @@ -141,3 +147,24 @@ int spmi_read_bytes(uint32_t addr, uint8_t *data, uint32_t num_bytes) } return 0; } + +/* Helper to handle transient SPMI bus errors with retries */ +int spmi_read8_safe(uint32_t reg) +{ + int val; + int retries = 0; + + do { + val = spmi_read8(reg); + if (val != ERROR_SPMI_READ_FAILED) + return val; + + printk(BIOS_WARNING, "SPMI read error at 0x%x. Retry %d/%d in %dms\n", + reg, retries + 1, MAX_SPMI_RETRIES, SPMI_RETRY_DELAY_MS); + + mdelay(SPMI_RETRY_DELAY_MS); + retries++; + } while (retries < MAX_SPMI_RETRIES); + + return ERROR_SPMI_READ_FAILED; +}