[PATCH v4 01/16] rockchip: spi: rk_spi: do not write bytes when in read-only mode

Quentin Schulz foss+uboot at 0leil.net
Thu Mar 14 10:36:14 CET 2024


From: Quentin Schulz <quentin.schulz at theobroma-systems.com>

The read-only mode is currently supported but only for 16b-aligned
buffers. For unaligned buffers, the last byte will be read in RW mode
right now, which isn't what is desired. Instead, let's put the
controller back into RO mode for that last byte and skip any write in
the xfer loop.

This is required for 3-wire SPI mode where PICO/POCI lanes are shorted
on HW level. This incidentally the recommended design for RK806 PMIC for
RK3588 products.

Cc: Quentin Schulz <foss+uboot at 0leil.net>
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>
Signed-off-by: Quentin Schulz <quentin.schulz at theobroma-systems.com>
---
 drivers/spi/rk_spi.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 7de943356ad..c8694fdff95 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -453,8 +453,17 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	 * case of read-only transfers by using the full 16bits of each
 	 * FIFO element.
 	 */
-	if (!out)
+	if (!out) {
 		ret = rockchip_spi_16bit_reader(dev, &in, &len);
+		/*
+		 * If "in" isn't 16b-aligned, we need to send the last byte
+		 * ourselves. We however need to have the controller in RO mode
+		 * which differs from the default.
+		 */
+		clrsetbits_le32(&regs->ctrlr0,
+				TMOD_MASK << TMOD_SHIFT,
+				TMOD_RO << TMOD_SHIFT);
+	}
 
 	/* This is the original 8bit reader/writer code */
 	while (len > 0) {
@@ -465,12 +474,13 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		rkspi_enable_chip(regs, true);
 
 		toread = todo;
-		towrite = todo;
+		/* Only write if we have something to write */
+		towrite = out ? todo : 0;
 		while (toread || towrite) {
 			u32 status = readl(&regs->sr);
 
 			if (towrite && !(status & SR_TF_FULL)) {
-				writel(out ? *out++ : 0, regs->txdr);
+				writel(*out++, regs->txdr);
 				towrite--;
 			}
 			if (toread && !(status & SR_RF_EMPT)) {
@@ -501,6 +511,10 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		spi_cs_deactivate(dev, slave_plat->cs);
 
 	rkspi_enable_chip(regs, false);
+	if (!out)
+		clrsetbits_le32(&regs->ctrlr0,
+				TMOD_MASK << TMOD_SHIFT,
+				TMOD_TR << TMOD_SHIFT);
 
 	return ret;
 }

-- 
2.44.0



More information about the U-Boot mailing list