diff options
Diffstat (limited to 'drivers/spi/rk_spi.c')
-rw-r--r-- | drivers/spi/rk_spi.c | 20 |
1 files 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(®s->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(®s->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(®s->ctrlr0, + TMOD_MASK << TMOD_SHIFT, + TMOD_TR << TMOD_SHIFT); return ret; } |