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 <subratabanik@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91766
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
This commit is contained in:
Subrata Banik 2026-03-19 19:53:58 +00:00
commit 2f93e4331e
2 changed files with 29 additions and 1 deletions

View file

@ -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__

View file

@ -2,6 +2,7 @@
#include <arch/mmio.h>
#include <commonlib/bsd/stdlib.h>
#include <delay.h>
#include <soc/addressmap.h>
#include <soc/qcom_spmi.h>
#include <timer.h>
@ -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(&regs->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;
}