The Flipper One's display is SPI with no MISO line at all. The controller only ever gets written to, so the board never routes a receive wire, and the pin that would have carried it is doing something else: it is the end-of-frame GPIO instead. This is a normal thing for a write-only display to do. It is not a normal thing for U-Boot's SPI stack to expect.
The devicetree binding for SPI peripherals already has a way to say this: spi-rx-bus-width = <0>, zero meaning no wire in that direction. Linux has understood zero since 5.12. U-Boot's copy of the same binding parses the property and then has nowhere to put a zero. spi_slave_of_to_plat() switches on 1, 2, 4, 8 and falls through to a default case for anything else, which prints a warning on every boot and quietly drops the fact that the wire is missing.
Giving zero a place to go
Linux's answer was two new mode bits, SPI_NO_TX and SPI_NO_RX, added in d962608ce218. U-Boot didn't have them. The first patch adds the same two bits at the first free positions in include/spi.h and maps a bus width of 0 onto them in the DT parsing switch, so the case that used to fall through to a warning now records what the board actually says.
Recording the bit is not the same as enforcing it, and Quentin Schulz caught that in review: nothing stops a caller from asking for a transfer in a direction that has no wire, and if the check only lives in one driver, every other controller driver needs to reinvent it. Linux enforces this centrally in __spi_validate(), so the patch does the same in dm_spi_xfer():
if (din && (slave_plat->mode & SPI_NO_RX))
return -EINVAL;
if (dout && (slave_plat->mode & SPI_NO_TX))
return -EINVAL;
A din on a no-RX device or a dout on a no-TX device now fails before it reaches any driver, instead of each driver having to know to check. A sandbox test exercises both rejections directly, flipping the mode bits on a bound device and asserting the transfer comes back -EINVAL.
The FIFO that was still running
The mode bit reaching the core is only half the board's problem, because the Rockchip SPI controller itself was still running full duplex no matter what the device asked for. rockchip_spi_claim_bus() hardcoded TMOD_TR, transmit and receive together, and the transfer loop always set toread = todo, so it clocked and waited on receive bytes that nobody was ever going to read because there was no wire to read them on.
The controller already has a transfer-mode field built for exactly this: TMOD_TR for both directions, TMOD_TO for transmit-only, TMOD_RO for receive-only, each one leaving the unused FIFO out of the transfer instead of just ignoring what comes back from it. The second patch picks the mode from the same bits the first patch set:
static u32 rkspi_base_tmod(struct rockchip_spi_priv *priv)
{
if (priv->mode & SPI_NO_RX)
return TMOD_TO;
if (priv->mode & SPI_NO_TX)
return TMOD_RO;
return TMOD_TR;
}
Switching the transfer mode alone would have hung the board. The 8-bit transfer loop paces itself on the receive FIFO filling up, and with no receive wire that FIFO never fills, so a loop that still waited on it would wait forever. The fix is to leave toread at zero when SPI_NO_RX is set and let the existing wait_till_not_busy() at the end of the chunk carry the completion, the same call that already covers a transmit-only tail today. One more spot restored a hardcoded TMOD_TR after a read-only transfer, which would have quietly undone the device's own mode on the next claim; that now restores from rkspi_base_tmod() too.
Landing it
The series went through a few rounds before Quentin was happy with it, mostly the central-validation point above. Alexey Charkov tested the Rockchip half on actual Flipper One hardware. Quentin, custodian for u-boot-rockchip, applied v4 on 2026-08-29 with the usual b4-ty automated notice, no reply needed on a message that just says applied, thanks:
- spi: Handle spi-{tx,rx}-bus-width 0 as SPI_NO_TX/SPI_NO_RX
- spi: rockchip: skip the unused FIFO direction on a one-wire device
Both land in the 2027.01 release. The board still has to actually boot and show a frame on real hardware for the fix to prove itself the rest of the way, and that half of the deal was Alexey's already.