summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoon Khai Ng <[email protected]>2026-03-12 12:46:33 +0800
committerTom Rini <[email protected]>2026-07-20 13:16:10 -0600
commit5a83cae32d9a1f29209d4f171a8de18bf82fd630 (patch)
treee75334f69681a203f722531c789922c5e5069548
parent042e45e026c77227319a426940577856ffe62e7b (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.c12
-rw-r--r--include/spi.h1
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 */