aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Schulz <quentin.schulz@theobroma-systems.com>2024-03-14 10:36:14 +0100
committerKever Yang <kever.yang@rock-chips.com>2024-03-14 18:19:44 +0800
commit3de8f45e6f2f94f4cd11a9cbc78ba1828ce639da (patch)
tree0b7ae226269634ac2f4d572d44bb39617942fde0
parent3b95c03d5706255f39a8f1a0fa02045d4fd981df (diff)
downloadu-boot-3de8f45e6f2f94f4cd11a9cbc78ba1828ce639da.zip
u-boot-3de8f45e6f2f94f4cd11a9cbc78ba1828ce639da.tar.gz
u-boot-3de8f45e6f2f94f4cd11a9cbc78ba1828ce639da.tar.bz2
rockchip: spi: rk_spi: do not write bytes when in read-only mode
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@0leil.net> Reviewed-by: Kever Yang <kever.yang@rock-chips.com> Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
-rw-r--r--drivers/spi/rk_spi.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 7de9433..c8694fd 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;
}