[PATCH v3 3/6] spmi: apple: check transaction status
Sasha Finkelstein <[email protected]> Mon, 03 Aug 2026 15:02:45 +0200
| Newsgroups | dev.linux.lists.asahi,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Alba Mendez <[email protected]> Check for parity errors and missing command ACKs Signed-off-by: Alba Mendez <[email protected]> Signed-off-by: Sasha Finkelstein <[email protected]> --- drivers/spmi/spmi-apple-controller.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c index e037ef914b6c..db03081796d1 100644 --- a/drivers/spmi/spmi-apple-controller.c +++ b/drivers/spmi/spmi-apple-controller.c @@ -22,6 +22,12 @@ #define SPMI_CMD_REG 0x4 #define SPMI_RSP_REG 0x8 +/* SPMI_RSP_REG reply word */ +#define SPMI_REPLY_FRAME_PARITY_STATUS GENMASK(31, 16) +#define SPMI_REPLY_ACK BIT(15) +#define SPMI_REPLY_SLAVE_ID GENMASK(14, 8) +#define SPMI_REPLY_CMD GENMASK(7, 0) + #define SPMI_RX_FIFO_EMPTY BIT(24) #define REG_POLL_INTERVAL_US 10000 @@ -76,7 +82,7 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, { struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl); u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len); - u32 rsp; + u32 reply, rsp; size_t len_read = 0; u8 i; int ret; @@ -87,8 +93,7 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, if (ret) return ret; - /* Discard SPMI reply status */ - readl(spmi->regs + SPMI_RSP_REG); + reply = readl(spmi->regs + SPMI_RSP_REG); /* Read SPMI data reply */ while (len_read < len) { @@ -107,6 +112,10 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, flush_extra_data(ctrl); + if (~FIELD_GET(SPMI_REPLY_FRAME_PARITY_STATUS, reply) & ((1 << len) - 1)) { + dev_err(&ctrl->dev, "some frames failed parity check\n"); + return -EIO; + } return 0; } @@ -115,6 +124,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, { struct apple_spmi *spmi = spmi_controller_get_drvdata(ctrl); u32 spmi_cmd = apple_spmi_pack_cmd(opc, sid, saddr, len); + u32 reply; size_t i = 0, j; int ret; @@ -133,11 +143,14 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, if (ret) return ret; - /* Discard */ - readl(spmi->regs + SPMI_RSP_REG); + reply = readl(spmi->regs + SPMI_RSP_REG); flush_extra_data(ctrl); + if (!FIELD_GET(SPMI_REPLY_ACK, reply)) { + dev_err(&ctrl->dev, "command not acknowledged\n"); + return -EIO; + } return 0; } -- 2.55.0