[PATCH linux dev-5.3 4/4] fsi: aspeed: Implement byte and half world transfers

Joel Stanley joel at jms.id.au
Wed Oct 23 17:18:48 AEDT 2019


The driver did not previously support non-word size transfers. The
fsi-i2c driver attempts accesses of this size, so we require it now.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
 drivers/fsi/fsi-master-aspeed.c | 37 +++++++++++++++++++++++----------
 1 file changed, 26 insertions(+), 11 deletions(-)

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index 8c5eb2bb1994..a99f9172ffa7 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -164,24 +164,38 @@ static const u32 fsi_base = 0xa0000000;
 #define CMD_WRITE	0
 
 /* OPBx_XFER_SIZE */
-#define XFER_WORD	(BIT(1) | BIT(0))
-#define XFER_NIBBLE	(BIT(0))
+#define XFER_FULLWORD	(BIT(1) | BIT(0))
+#define XFER_HALFWORD	(BIT(0))
 #define XFER_BYTE	(0)
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/fsi_master_aspeed.h>
 
+static u32 get_xfer_size(size_t size) {
+	switch (size) {
+	case 1:
+		return XFER_BYTE;
+	case 2:
+		return XFER_HALFWORD;
+	case 4:
+		return XFER_FULLWORD;
+	default:
+		return -EINVAL;
+	}
+}
+
 static u32 opb_write(void __iomem *base, uint32_t addr, uint32_t val,
 		     size_t size)
 {
-	u32 reg, ret, status;
+	u32 reg, ret, status, xfer_size;
 
-	/* TODO: implement other sizes, see 0x18 */
-	WARN_ON(size != 4);
+	xfer_size = get_xfer_size(size);
+	if (xfer_size < 0)
+		return xfer_size;
 
 	writel(0x1, base + OPB0_SELECT);
 	writel(CMD_WRITE, base + OPB0_RW);
-	writel(XFER_WORD, base + OPB0_XFER_SIZE);
+	writel(xfer_size, base + OPB0_XFER_SIZE);
 	writel(addr, base + OPB0_FSI_ADDR);
 	writel(val, base + OPB0_FSI_DATA_W);
 	writel(0x1, base + OPB_IRQ_CLEAR);
@@ -208,15 +222,16 @@ static u32 opb_write(void __iomem *base, uint32_t addr, uint32_t val,
 
 static int opb_read(void __iomem *base, uint32_t addr, size_t size, u32 *out)
 {
-	u32 result, reg;
+	u32 result, reg, xfer_size;
 	int status, ret;
 
-	/* TODO: implement other sizes, see 0x18 */
-	WARN_ON(size != 4);
+	xfer_size = get_xfer_size(size);
+	if (xfer_size < 0)
+		return xfer_size;
 
 	writel(0x1, base + OPB0_SELECT);
 	writel(CMD_READ, base + OPB0_RW);
-	writel(XFER_WORD, base + OPB0_XFER_SIZE);
+	writel(xfer_size, base + OPB0_XFER_SIZE);
 	writel(addr, base + OPB0_FSI_ADDR);
 	writel(0x1, base + OPB_IRQ_CLEAR);
 	writel(0x1, base + OPB_TRIGGER);
@@ -242,7 +257,7 @@ static int opb_read(void __iomem *base, uint32_t addr, size_t size, u32 *out)
 		return -EIO;
 
 	if (out)
-		*out = result;
+		memcpy(out, &result, size);
 
 	return 0;
 }
-- 
2.23.0



More information about the openbmc mailing list