[PATCH 0/2] spi: soft_spi: Add support for SPI_3WIRE

Add support for SPI_3WIRE on soft_spi driver.
Hironori KIKUCHI (2): spi: spi-uclass: Fix dm_spi_claim_bus() spi: soft_spi: Add support for SPI_3WIRE
drivers/spi/soft_spi.c | 19 ++++++++++++++++--- drivers/spi/spi-uclass.c | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-)

When dm_spi_claim_bus() claims a bus, sometimes plat->mode and/or plat->max_hz have not been copied to the priv object yet. This can lead to an SPI bus malfunction.
To fix this, use the object returned by dev_get_parent_plat() instead, which is set by spi_slave_of_to_plat() on spi_child_post_bind().
Signed-off-by: Hironori KIKUCHI kikuchan98@gmail.com --- drivers/spi/spi-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index d604975374..0b3f29b6d8 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -54,7 +54,7 @@ int dm_spi_claim_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct dm_spi_ops *ops = spi_get_ops(bus); struct dm_spi_bus *spi = dev_get_uclass_priv(bus); - struct spi_slave *slave = dev_get_parent_priv(dev); + struct dm_spi_slave_plat *slave = dev_get_parent_plat(dev); uint speed, mode;
speed = slave->max_hz;

When 3-wire mode is claimed on the bus, use the MOSI (output) pin to receive data. In this mode, since the transfer can only be either TX or RX, return -EINVAL if both are required at the same time.
Signed-off-by: Hironori KIKUCHI kikuchan98@gmail.com --- drivers/spi/soft_spi.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c index a8ec2f4f7b..ae444dad8a 100644 --- a/drivers/spi/soft_spi.c +++ b/drivers/spi/soft_spi.c @@ -124,8 +124,19 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, u8 *rxd = din; int cpha = !!(priv->mode & SPI_CPHA); int cidle = !!(priv->mode & SPI_CPOL); + int txrx = plat->flags; unsigned int j;
+ if (priv->mode & SPI_3WIRE) { + if (txd && rxd) + return -EINVAL; + + txrx = txd ? SPI_MASTER_NO_RX : SPI_MASTER_NO_TX; + dm_gpio_set_dir_flags(&plat->mosi, + txd ? GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE : + GPIOD_IS_IN); + } + debug("spi_xfer: slave %s:%s dout %08X din %08X bitlen %u\n", dev->parent->name, dev->name, *(uint *)txd, *(uint *)rxd, bitlen); @@ -160,7 +171,7 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, */ if (cpha) soft_spi_scl(dev, !cidle); - if ((plat->flags & SPI_MASTER_NO_TX) == 0) + if ((txrx & SPI_MASTER_NO_TX) == 0) soft_spi_sda(dev, !!(tmpdout & 0x80)); udelay(plat->spi_delay_us);
@@ -174,8 +185,10 @@ static int soft_spi_xfer(struct udevice *dev, unsigned int bitlen, else soft_spi_scl(dev, cidle); tmpdin <<= 1; - if ((plat->flags & SPI_MASTER_NO_RX) == 0) - tmpdin |= dm_gpio_get_value(&plat->miso); + if ((txrx & SPI_MASTER_NO_RX) == 0) + tmpdin |= dm_gpio_get_value((priv->mode & SPI_3WIRE) ? + &plat->mosi : + &plat->miso); tmpdout <<= 1; udelay(plat->spi_delay_us);
participants (1)
-
Hironori KIKUCHI