Skip to content

Conversation

@pelwell
Copy link
Contributor

@pelwell pelwell commented Nov 11, 2025

RP1 has two SPI target (slave) interfaces - SPI4 on GPIOs 8-11 and SPI7 with a number of positions from GPIO45 upwards. Until recently, the Linux driver for the Synopsys SPI block did not support target mode, but a patch has just appeared in the next branch that does just that.

This patch set adds the two required patches, rebasing the downstream patches on top of them. Currently there is no spi4-pi5 overlay (the only one we are likely to require), but getting the driver changes in now should shake out any major breakage with the SPI controller instances.

pelwell and others added 20 commits November 11, 2025 14:02
commit b926b15547d29a88932de3c24a05c12826fc1dbc upstream.

Since the designware SPI controller can act as both a target and a host,
rename spi_controller member of the dw_spi struct to ctlr instead of host.
Similarly, rename the functions handling the controller, using controller
instead of host as the suffix.

No functional changes intended.

Signed-off-by: Benoît Monin <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Mark Brown <[email protected]>
commit fe8cc44dd173cde5788ab4e3730ac61f3d316d9c upstream.

Implement target mode for the DesignWare controller with the following
changes:

Allocate an SPI controller of the correct type based on the spi-slave
property in dw_spi_add_controller() and set the controller properties
depending on its type. Since they are only relevant when acting as a host
controller, settings related to chip-select control and the set_cs()
callback are only set in host mode, as are the loopback support, the
memory operations and the maximum frequency. The target_abort() callback
is set only when configured in target mode.

The number of chip-select is set to 1 in dw_spi_hw_init() since the
controller only has one CS input in target mode.

In dw_spi_update_config(), return after setting the CTRLR0 register as
the other registers are only relevant in host mode and are read-only
in target mode. This function is called as part of the transfer_one()
callback, which is identical in both the host and target mode.

Move the code implementing the handle_err() callback to a new function
named dw_spi_abort(), and use it to implement both the handle_err()
and the target_abort() callbacks.

Finally, drop the error path on the spi-slave property in
dw_spi_mmio_probe(), as it is now a valid configuration.

Signed-off-by: Benoît Monin <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Mark Brown <[email protected]>
Even when configured to use only gpiod CS lines, the DW SPI controller
still expects a bit to be set in the SER register, otherwise transfers
stall. For the csgpiod case, nominate bit 0 for the job.

See: raspberrypi#6159

Signed-off-by: Phil Elwell <[email protected]>
TMOD_TO is the transmit-only mode that doesn't put data into the receive
FIFO. Using TMOD_TO when the user doesn't want the received data saves
CPU time and memory bandwidth.

Signed-off-by: Phil Elwell <[email protected]>
TMOD_RO is the receive-only mode that doesn't require data in the
transmit FIFO in order to generate clock cycles. Using TMOD_RO when the
device doesn't care about the data sent to it saves CPU time and memory
bandwidth.

Signed-off-by: Phil Elwell <[email protected]>
Disabling the peripheral resets controller state which has a dangerous
side-effect of disabling the DMA handshake interface while it is active.
This can cause DMA channels to hang.

The error recovery pathway will wait for DMA to stop and reset the chip
anyway, so mask further FIFO interrupts and let the transfer finish
gracefully.

Signed-off-by: Jonathan Bell <[email protected]>
Ensure the transmit FIFO has emptied before ending the transfer by
dropping the TX threshold to 0 when the last byte has been pushed into
the FIFO. Include a similar fix for the non-IRQ paths.

See: raspberrypi#6285
Fixes: 6014649 ("spi: dw: Save bandwidth with the TMOD_TO feature")
Signed-off-by: Phil Elwell <[email protected]>
The DW SPI interface has a 16-bit clock divider, where the bottom bit
of the divisor must be 0. Limit how low the clock speed can go to
prevent the clock divider from being truncated, as that could lead to
a much higher clock rate than requested.

Signed-off-by: Phil Elwell <[email protected]>
SPI transfers are of defined length, unlike some UART traffic, so it is
safe to let the DMA controller choose a suitable memory width.

Signed-off-by: Phil Elwell <[email protected]>
If this is a DMA transfer, and if there is no simultaneous RX transfer,
wait for the interface to go idle before reporting that TX is done.

Link: https://forums.raspberrypi.com/viewtopic.php?t=383027

Signed-off-by: Phil Elwell <[email protected]>
@pelwell
Copy link
Contributor Author

pelwell commented Nov 11, 2025

The Forums thread asking about SPI target mode on Pi 5 is here: https://forums.raspberrypi.com/viewtopic.php?t=393684

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants