[v2,1/8] spi: add support for bits-per-word setting

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

Commit Message

Dario Binacchi Feb. 21, 2026, 9:42 a.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>
---

(no changes since v1)

 drivers/spi/spi-uclass.c | 19 +++++++++++++++++++
 include/spi.h            | 12 ++++++++++++
 2 files changed, 31 insertions(+)

Comments

Simon Glass Feb. 23, 2026, 5:51 p.m. UTC | #1
Hi Dario,

On Sat, 21 Feb 2026 at 02:43, Dario Binacchi
<dario.binacchi@amarulasolutions.com> wrote:
>
> 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>
> ---
>
> (no changes since v1)
>
>  drivers/spi/spi-uclass.c | 19 +++++++++++++++++++
>  include/spi.h            | 12 ++++++++++++
>  2 files changed, 31 insertions(+)
>

Reviewed-by: Simon Glass <simon.glass@canonical.com>

Thoughts below

> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> index 49b584c648d6..a4a3b6c25b7d 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;

This should not happen, right? We don't normally include these kinds
of checks in U-Boot, to avoid code-size costs.

I have long thought about adding 'CONFIG_SAFE' option behind which we
could hide checks, which people could then enable if they with:

if (CONFIG_IS_ENABLED(SAFE) && bus && bus->uclass &&
bus->uclass->uc_drv && bus->uclass->uc_drv->id != UCLASS_SPI)
              return -[error number to use for all of these checks];

(would need to check dev->parent and ops too)

> +
> +       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)
>  {
> diff --git a/include/spi.h b/include/spi.h
> index 2783200d663e..a92f54a7404b 100644
> --- a/include/spi.h
> +++ b/include/spi.h
> @@ -729,6 +729,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
>   *
> --
> 2.43.0
>

We should probably store the the wordlen in struct dm_spi_slave_plat

We could even avoid a new operation, but then your driver would need
to set the word on an xfer() call. Plis your new operation lines up
with the existing ones. So this seems OK to me.

Regards,
Simon

To unsubscribe from this group and stop receiving emails from it, send an email to linux-amarula+unsubscribe@amarulasolutions.com.

Patch

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 49b584c648d6..a4a3b6c25b7d 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)
 {
diff --git a/include/spi.h b/include/spi.h
index 2783200d663e..a92f54a7404b 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -729,6 +729,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
  *