[v3,1/9] spi: add support for bits-per-word setting

Message ID 20260225161851.2475274-2-dario.binacchi@amarulasolutions.com
State New
Headers show
Series
  • video: support Rocktech RK050HR345-CT106A panel
Related show

Commit Message

Dario Binacchi Feb. 25, 2026, 4:16 p.m. UTC
Allow dynamic configuration of the SPI word length. This is required
for controllers and slaves that need to operate with non-standard
word lengths, such as 9-bit wide transfers.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
Reviewed-by: Simon Glass <simon.glass@canonical.com>

---

Changes in v3:
- Add Reviewed-by tag of Simon Glass
- Store the default value in struct dm_spi_slave_plat and copy it
  in struct spi_slave

 drivers/spi/spi-uclass.c | 22 +++++++++++++++++++++-
 include/spi.h            | 14 ++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

Patch

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 49b584c648d6..f70c04994252 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -91,6 +91,20 @@  void dm_spi_release_bus(struct udevice *dev)
 		ops->release_bus(dev);
 }
 
+int dm_spi_set_wordlen(struct udevice *dev, unsigned int wordlen)
+{
+	struct udevice *bus = dev->parent;
+	struct dm_spi_ops *ops = spi_get_ops(bus);
+
+	if (bus->uclass->uc_drv->id != UCLASS_SPI)
+		return -EOPNOTSUPP;
+
+	if (!ops->set_wordlen)
+		return -ENOSYS;
+
+	return ops->set_wordlen(dev, wordlen);
+}
+
 int dm_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		const void *dout, void *din, unsigned long flags)
 {
@@ -144,6 +158,11 @@  int spi_set_speed(struct spi_slave *slave, uint hz)
 	return ret;
 }
 
+int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen)
+{
+	return dm_spi_set_wordlen(slave->dev, wordlen);
+}
+
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 	     const void *dout, void *din, unsigned long flags)
 {
@@ -215,7 +234,7 @@  static int spi_child_pre_probe(struct udevice *dev)
 
 	slave->max_hz = plat->max_hz;
 	slave->mode = plat->mode;
-	slave->wordlen = SPI_DEFAULT_WORDLEN;
+	slave->wordlen = plat->wordlen;
 
 	return 0;
 }
@@ -582,6 +601,7 @@  int spi_slave_of_to_plat(struct udevice *dev, struct dm_spi_slave_plat *plat)
 	}
 
 	plat->mode = mode;
+	plat->wordlen = SPI_DEFAULT_WORDLEN;
 
 	return 0;
 }
diff --git a/include/spi.h b/include/spi.h
index 2783200d663e..5a98b1cad65e 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -77,11 +77,13 @@  struct dm_spi_bus {
  * @cs:		Chip select number (0..n-1)
  * @max_hz:	Maximum bus speed that this slave can tolerate
  * @mode:	SPI mode to use for this device (see SPI mode flags)
+ * @wordlen:	Word length in bits to use for this device
  */
 struct dm_spi_slave_plat {
 	unsigned int cs[SPI_CS_CNT_MAX];
 	uint max_hz;
 	uint mode;
+	unsigned int wordlen;
 };
 
 /**
@@ -729,6 +731,18 @@  int dm_spi_claim_bus(struct udevice *dev);
  */
 void dm_spi_release_bus(struct udevice *dev);
 
+/**
+ * Set the word length for SPI transactions
+ *
+ * Set the word length (number of bits per word) for SPI transactions.
+ *
+ * @slave:	The SPI slave
+ * @wordlen:	The number of bits in a word
+ *
+ * Returns: 0 on success, -1 on failure.
+ */
+int dm_spi_set_wordlen(struct udevice *dev, unsigned int wordlen);
+
 /**
  * SPI transfer
  *