[PATCH v4 3/6] spmi: apple: check transaction status
Sasha Finkelstein <[email protected]> Wed, 05 Aug 2026 12:11:13 +0200
| Newsgroups | gmane.linux.kernel,gmane.linux.ports.arm.kernel,gmane.linux.drivers.devicetree |
|---|---|
| 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 | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/spmi/spmi-apple-controller.c b/drivers/spmi/spmi-apple-controller.c index 4d5356bf9bbf..7ebf899edf17 100644 --- a/drivers/spmi/spmi-apple-controller.c +++ b/drivers/spmi/spmi-apple-controller.c @@ -11,6 +11,8 @@ * spmi-pmic-arb.c Copyright (c) 2021, The Linux Foundation. */ +#include <linux/bitfield.h> +#include <linux/bits.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> @@ -23,6 +25,12 @@ #define SPMI_RSP_REG 0x8 #define SPMI_ACT_REG 0xa4 +/* 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_ACT_FIFO_FLUSH BIT(0) #define SPMI_RX_FIFO_EMPTY BIT(24) @@ -66,7 +74,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; @@ -82,12 +90,12 @@ 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) { if (readl(spmi->regs + SPMI_STATUS_REG) & SPMI_RX_FIFO_EMPTY) { + spmi->prev_fail = true; dev_err_ratelimited(&ctrl->dev, "FIFO lacks reply data, controller stuck?\n"); return -EIO; @@ -105,6 +113,10 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, u8 opc, u8 sid, spmi->prev_fail = true; } + 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; } @@ -113,6 +125,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; @@ -136,14 +149,17 @@ 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); if (!(readl(spmi->regs + SPMI_STATUS_REG) & SPMI_RX_FIFO_EMPTY)) { dev_warn(&ctrl->dev, "FIFO has extra data\n"); spmi->prev_fail = true; } + if (!FIELD_GET(SPMI_REPLY_ACK, reply)) { + dev_err(&ctrl->dev, "command not acknowledged\n"); + return -EIO; + } return 0; } -- 2.55.0