Re: [PATCH] spi: Handle spi-{tx,rx}-bus-width 0 as SPI_NO_TX/SPI_NO_RX

Quentin Schulz <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
Hi Cole,

On 8/18/26 3:15 AM, Cole Munz wrote:
> The spi-peripheral-props binding shipped in dts/upstream allows a bus
> width of 0, meaning no RX or TX is possible on this device. The
> switches in spi_slave_of_to_plat() only handle 1/2/4/8, so a width of
> 0 falls through to the default case and warns "spi-rx-bus-width 0 not
> supported" on every boot, even though the devicetree is valid per the
> binding. The fact that the wire is missing is then dropped from
> plat->mode.
> 
> Map 0 to new SPI_NO_TX/SPI_NO_RX mode bits, as Linux has done since
> v5.12 ("spi: Add SPI_NO_TX/RX support", mainline d962608ce218).
> Bits 16 and 17 are the first free mode bits.
> 
> This comes up on devices with no MISO line at all, such as a
> write-only SPI display described with spi-rx-bus-width = <0>.
> 
> Signed-off-by: Cole Munz <[email protected]>
> ---
> Raised as a boot-log warning on Flipper One, whose display has no MISO
> line at all: that pin is reused as the end-of-frame GPIO. Reported at
> flipperdevices/u-boot#33, and sent here rather than to the fork as

Please provide a full link next time, not everything is hosted on GitHub 
so we wouldn't necessarily know where to look. I knew because I had at a 
look at Flipper One's repos a few weeks ago and remembered. For 
reference: https://github.com/flipperdevices/u-boot/issues/33

> suggested on that issue.
> 
> Verified on sandbox at 527115ef6783, with spi-rx-bus-width = <0> added
> to spi.bin@0 in arch/sandbox/dts/test.dts and CONFIG_LOG disabled, so
> warn_non_xpl() reaches the console the way it does on the board.
> 
> Before:
>   $ ./u-boot -T -c "sf probe"
>   spi-rx-bus-width 0 not supported
>   spi-rx-bus-width 0 not supported
>   SF: Detected m25p16 with page size 256 Bytes, erase size 64 KiB, 2 MiB
> 
> After:
>   $ ./u-boot -T -c "sf probe"
>   SF: Detected m25p16 with page size 256 Bytes, erase size 64 KiB, 2 MiB
> 
> It warns twice in sandbox because both the pre- and post-reloc DM scans
> run there; the board logs it once.
> 
> ut dm spi_flash, spi_xfer, spi_find, spi_claim_bus, spi_set_wordlen and
> spi_flash_func all pass with the property in place. Nothing consumes the
> new bits yet, matching d962608ce218 in Linux, where the consumers landed
> later.
> 
>   drivers/spi/spi-uclass.c | 6 ++++++
>   include/spi.h            | 2 ++
>   2 files changed, 8 insertions(+)
> 
> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> index 120565df1497..0f0d4b1384f2 100644
> --- a/drivers/spi/spi-uclass.c
> +++ b/drivers/spi/spi-uclass.c
> @@ -229,6 +229,9 @@ static int spi_child_post_bind(struct udevice *dev)
>   	/* Device DUAL/QUAD mode */
>   	value = dev_read_u32_default(dev, "spi-tx-bus-width", 1);
>   	switch (value) {
> +	case 0:
> +		mode |= SPI_NO_TX;
> +		break;
>   	case 1:
>   		break;
>   	case 2:
> @@ -247,6 +250,9 @@ static int spi_child_post_bind(struct udevice *dev)
>   
>   	value = dev_read_u32_default(dev, "spi-rx-bus-width", 1);
>   	switch (value) {
> +	case 0:
> +		mode |= SPI_NO_RX;
> +		break;
>   	case 1:
>   		break;
>   	case 2:
> diff --git a/include/spi.h b/include/spi.h
> index 97096a775262..f477763bdc60 100644
> --- a/include/spi.h
> +++ b/include/spi.h
> @@ -34,6 +34,8 @@ struct spinand_info;
>   #define SPI_RX_QUAD	BIT(13)			/* receive with 4 wires */
>   #define SPI_TX_OCTAL	BIT(14)			/* transmit with 8 wires */
>   #define SPI_RX_OCTAL	BIT(15)			/* receive with 8 wires */
> +#define SPI_NO_TX	BIT(16)			/* no transmit wire */
> +#define SPI_NO_RX	BIT(17)			/* no receive wire */
>   
>   /* Header byte that marks the start of the message */
>   #define SPI_PREAMBLE_END_BYTE	0xec

So this is fine, but incomplete. We should really do:

[...]
struct dm_spi_slave_plat *plat = dev_get_parent_plat(dev);

if (din && (plat->mode & SPI_NO_RX))
     return -EINVAL;
if (dout && (plat->mode & SPI_NO_TX))
     return -EINVAL;

return ops->xfer(dev, bitlen, dout, din, flags);

in dm_spi_xfer(). To avoid calling xfer() with an invalid configuration. 
This would then match the Linux kernel behavior (c.f. __spi_validate) 
and avoid all SPI controller drivers having to implement logic to avoid 
reading/writing on NO_RX/NO_TX devices.

It'd be nice to add tests to make sure this is handled properly (the 
function returns -EINAL on invalid configuration).

Please send the spi-uclass.c and rk_spi.c in the same series (in 
separate commits still, like you've done here), with a joined 
cover-letter (the info you added to this patch and the Rockchip one is 
good enough IMO).

Cheers,
Quentin
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.