| From 6a2e0b505985a089d209920251a95201abacfa31 Mon Sep 17 00:00:00 2001 |
| From: "Kao.Benson" <kao.benson@inventec.corp-partner.google.com> |
| Date: Mon, 5 Aug 2024 17:22:18 +0800 |
| Subject: [PATCH] AMD apml through i3c interface process |
| |
| AMD recommends applying a provided patch. Through studying this patch, |
| we have achieved the ability to retry in case of NACK by modifying the |
| software in i3c driver. |
| |
| Reference patch: |
| https://github.com/AMDESE/OpenBMC/blob/master/meta-amd/meta-common/recipes-kernel/linux/linux-aspeed/0002-drivers-i3c-Modify-I3C-driver.patch#L3008 |
| |
| Tested: |
| Before modify, It saw the error by using i3c tool |
| ~# i3ctransfer -d i3c-0-22400000002 -w 0x73 -r 0x0a |
| Error: transfer failed: Input/output error |
| ~# i3ctransfer -d i3c-0-22400000002 -w 0x73 -r 0x0a |
| Success on message 0 |
| Success on message 1 |
| received data: |
| 0x09 |
| 0x00 |
| 0x10 |
| 0x00 |
| 0x00 |
| 0x00 |
| 0x41 |
| 0x75 |
| 0x74 |
| 0x6 |
| |
| [After we modify] |
| ~# i3ctransfer -d i3c-0-22400000002 -w |
| 0x73,0x08,0x08,0x91,0x00,0x00,0x00,0x00,0x00,0x00 |
| Success on message 0 |
| ~# i3ctransfer -d i3c-0-22400000002 -w 0x02 -r 1 |
| Success on message 0 |
| Success on message 1 |
| received data: |
| 0x80 |
| ~# i3ctransfer -d i3c-0-22400000002 -w 0x73 -r 0x0a |
| Success on message 0 |
| Success on message 1 |
| received data: |
| 0x09 |
| 0x00 |
| 0x10 |
| 0x00 |
| 0x00 |
| 0x00 |
| 0x41 |
| 0x75 |
| 0x74 |
| 0x68 |
| ~# i3ctransfer -d i3c-0-22400000002 -w 0x73 -r 0x0a |
| Success on message 0 |
| Success on message 1 |
| received data: |
| 0x09 |
| 0x00 |
| 0x10 |
| 0x00 |
| 0x00 |
| 0x00 |
| 0x41 |
| 0x75 |
| 0x74 |
| 0x68 |
| |
| Signed-off-by: Kao.Benson <kao.benson@inventec.corp-partner.google.com> |
| --- |
| drivers/i3c/master/svc-i3c-master.c | 13 ++++++++++--- |
| 1 file changed, 10 insertions(+), 3 deletions(-) |
| |
| diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c |
| index 6fdaa8b9de5d..ec9d4be0d8dc 100644 |
| --- a/drivers/i3c/master/svc-i3c-master.c |
| +++ b/drivers/i3c/master/svc-i3c-master.c |
| @@ -196,6 +196,7 @@ |
| #define SVC_I3C_MAX_I2CBAUD 15 |
| #define I3C_SCL_PP_PERIOD_NS_MIN 40 |
| #define I3C_SCL_OD_LOW_PERIOD_NS_MIN 200 |
| +#define I3C_RETRY 3 |
| |
| /* DMA definitions */ |
| #define MAX_DMA_COUNT 1024 |
| @@ -1449,11 +1450,12 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, |
| bool use_dma) |
| { |
| u32 reg, rdterm = *read_len, mstatus; |
| - int ret, i, count, space; |
| + int ret, i, count, space, retry_times = 0; |
| unsigned long flags; |
| unsigned long start; |
| u32 ibiresp; |
| |
| +retry_count: |
| if (rdterm > SVC_I3C_MAX_RDTERM) |
| rdterm = SVC_I3C_MAX_RDTERM; |
| |
| @@ -1566,8 +1568,13 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master, |
| reg = readl(master->regs + SVC_I3C_MSTATUS); |
| if (SVC_I3C_MSTATUS_NACKED(reg)) { |
| dev_dbg(master->dev, "addr 0x%x NACK\n", addr); |
| - ret = -EIO; |
| - goto emit_stop; |
| + if (retry_times >= I3C_RETRY) |
| + { |
| + ret = -EIO; |
| + goto emit_stop; |
| + } |
| + retry_times++; |
| + goto retry_count; |
| } |
| |
| if (use_dma) |
| -- |
| 2.34.1 |
| |