diff options
| author | Boon Khai Ng <[email protected]> | 2026-03-12 12:46:33 +0800 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-07-20 13:16:10 -0600 |
| commit | 5a83cae32d9a1f29209d4f171a8de18bf82fd630 (patch) | |
| tree | e75334f69681a203f722531c789922c5e5069548 | |
| parent | 042e45e026c77227319a426940577856ffe62e7b (diff) | |
spi: dw: Allow bits_per_word to be configured by device drivers
The DesignWare SPI controller supports configurable bits_per_word
(typically 4-32 bits), but this was previously hardcoded to 8 bits
in the driver initialization.
This patch enables bits_per_word to be set dynamically by upper-level
device drivers, matching the approach used in Linux. The controller
reads the bits_per_word value from the spi_slave structure during
each transfer, allowing different SPI devices on the same bus to use
different word sizes.
Implementation details:
- Read slave->bits_per_word in dw_spi_xfer() before each transfer
- Validate requested value against controller capabilities (4 to max_xfer)
- Default to 8 bits if not set (maintains backward compatibility)
This follows the Linux model where spi_device drivers set bits_per_word,
and the controller driver reads it in the transfer function. Device
drivers can now set slave->bits_per_word before calling spi_xfer().
Example usage in device driver:
slave->bits_per_word = 16;
spi_xfer(slave, ...);
Backward compatible: Existing drivers that don't set bits_per_word
will continue to work with the default 8-bit transfers.
Signed-off-by: Boon Khai Ng <[email protected]>
| -rw-r--r-- | drivers/spi/designware_spi.c | 12 | ||||
| -rw-r--r-- | include/spi.h | 1 |
2 files changed, 13 insertions, 0 deletions
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index b520c727900..0df9a4f5abd 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -497,6 +497,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, { struct udevice *bus = dev->parent; struct dw_spi_priv *priv = dev_get_priv(bus); + struct spi_slave *slave = dev_get_parent_priv(dev); const u8 *tx = dout; u8 *rx = din; int ret = 0; @@ -504,6 +505,17 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, u32 val; u32 cs; + /* Get bits_per_word from slave (set by device driver) */ + if (slave->bits_per_word >= 4 && slave->bits_per_word <= priv->max_xfer) { + priv->bits_per_word = slave->bits_per_word; + } else if (slave->bits_per_word == 0) { + priv->bits_per_word = 8; /* Default if not set */ + } else { + dev_warn(dev, "Invalid bits_per_word %u, using 8\n", + slave->bits_per_word); + priv->bits_per_word = 8; + } + /* spi core configured to do 8 bit transfers */ if (bitlen % 8) { dev_err(dev, "Non byte aligned SPI transfer.\n"); diff --git a/include/spi.h b/include/spi.h index 7eaf0aa69b8..97096a77526 100644 --- a/include/spi.h +++ b/include/spi.h @@ -161,6 +161,7 @@ struct spi_slave { unsigned int max_write_size; void *memory_map; + u8 bits_per_word; u8 flags; #define SPI_XFER_BEGIN BIT(0) /* Assert CS before transfer */ #define SPI_XFER_END BIT(1) /* Deassert CS after transfer */ |
