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.

roliver-rpi and others added 30 commits November 10, 2025 11:09
The Raspberry Pi RP2040 GPIO bridge is an I2C-attached device exposing
both a Tx-only SPI controller, and a GPIO controller.

Due to the relative difference in transfer rates between standard-mode
I2C and SPI, the GPIO bridge makes use of 12 MiB of non-volatile storage
to cache repeated transfers. This cache is arranged in ~8 KiB blocks and
is addressed by the MD5 digest of the data contained therein.

Optionally, this driver is able to take advantage of Raspberry Pi RP1
GPIOs to achieve faster than I2C data transfer rates.

Signed-off-by: Richard Oliver <[email protected]>

spi: rp2040-gpio-bridge: Add debugfs progress indicator

Useful for tracking upload progress via userspace.

Signed-off-by: Naushir Patuck <[email protected]>

spi: rp2040-gpio-bridge: add missing MD5 dependency

rp2040-gpio-bridge relies on the md5 crypto driver. This dependency
cannot be determined automatically as rp2040-gpio-bridge does not
use any of md5's symbols directly.

Declare a soft 'pre' dependency on md5 to ensure that it is included and
loaded before rp2040-gpio-bridge.

Signed-off-by: Richard Oliver <[email protected]>

spi: rp2040-gpio-bridge: fix gpiod error handling

In some circumstances, devm_gpiod_get_array_optional() can return
PTR_ERR rather than NULL to indicate failure. Handle these cases.

Signed-off-by: Richard Oliver <[email protected]>

spi: rp2040-gpio-bridge: probe: Cfg fast_xfer clk

Fast transfer mode requires that the first bit of data is clocked with a
rising edge. This can cause extra bits of data to be clocked on hardware
where the clock signal uses a pull-up. This change ensures that clk is
driven low before fast data transfer mode is entered.

Signed-off-by: Richard Oliver <[email protected]>
The snps,block-size DT property declares the maximum block size for each
channel of the dw-axi-dmac. However, the driver ignores these when
setting max_seg_size and uses MAX_BLOCK_SIZE (4096) instead.

To take advantage of the efficiencies of larger blocks, calculate the
minimum block size across all channels and use that instead.

See: raspberrypi#6256

Signed-off-by: Phil Elwell <[email protected]>
The firmware advertises its features as a string of words separated by
spaces. Ensure that feature names are only matched in their entirety.

Signed-off-by: Phil Elwell <[email protected]>
The Cypress firmwares use "extsae" to indicate wpa_supplicant-hosted
SAE/WPA3.

Signed-off-by: Phil Elwell <[email protected]>
support sae executed in wpa_supplicant and offload 4-way handshake offload.

Signed-off-by: Chien-Chia Chen <[email protected]>

JIRA: SWWLAN-142424
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]>
There's no real need to constrain MEM access widths to 32-bit (or
narrower), as the DMAC is intelligent enough to size memory accesses
appropriately. Wider accesses are more efficient.

Similarly, MEM burst lengths don't need to be a function of DEV burst
lengths - the DMAC packs/unpacks data into/from its internal channel
FIFOs appropriately. Longer accesses are more efficient.

However, the DMAC doesn't have complete support for unaligned accesses,
and blocks are always defined in integer multiples of SRC_WIDTH, so odd
source lengths or buffer alignments will prevent wide accesses being
used, as before.

There is an implicit requirement to limit requested DEV read burst
lengths to less than the hardware's maximum configured MSIZE - otherwise
RX data will be left over at the end of a block. There is no config
register that reports this value, so the AXI burst length parameter is
used to produce a facsimile of it. Warn if such a request arrives that
doesn't respect this.

Signed-off-by: Jonathan Bell <[email protected]>
Do an end-run around ASoC in lieu of not being able to easily find the
associated DMA controller capabilities.

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]>
In the same way that other subsystems support the setting of device
id numbers from Device Tree aliases, allow gpiochip numbers to be
derived from "gpiochip<n>" aliases.

Signed-off-by: Phil Elwell <[email protected]>
Although later functions can handle a NULL fwnode, fwnode can't handle
being passed a NULL pointer.

See: raspberrypi#6305

Signed-off-by: Phil Elwell <[email protected]>
The check if the oscillator stop bit is set was reading from Control_1
register instead of the Seconds register.
This caused the Seconds register to be incorrectly changed if bit 7 of
Control_1 happens to be set.

Signed-off-by: Axel Hammarberg <[email protected]>
Add YAML device tree binding for the Sony IMX500 CMOS image sensor /
CNN inference engine.  Also, add a MAINTAINERS entry.

Signed-off-by: Richard Oliver <[email protected]>
The Sony IMX500 is a stacked 1/2.3-inch CMOS digital image sensor and
inbuilt AI processor with an active array CNN (Convolutional Neural
Network) inference engine.  The native sensor size is 4056H x 3040V, and
the module also contains an in-built ISP for the CNN. The module is
programmable through an I2C interface with firmware and neural network
uploads being made over SPI. This driver supports imaging only.

Signed-off-by: Richard Oliver <[email protected]>

media: i2c: imx500: Inbuilt AI processor support

Add support for the IMX500's inbuilt AI processor. The IMX500 program
loader, AI processor firmware, DNN weights are accessed via the kernel's
firmware interface on 'open' and are transferred to the IMX500 over SPI.

Signed-off-by: Richard Oliver <[email protected]>

media: i2c: imx500: Enable LED during SPI transfers

The Raspberry Pi 'AI Camera' is equipped with an LED. Enable this LED
during SPI transfers to indicate to the end-user that progress is being
made during large tramsfers.

Signed-off-by: Richard Oliver <[email protected]>

drivers: media: imx500: Fixes for vblank control

Reduce the default/max framerate of the 2x2 binned mode to 30fps.
The current limit of 50fps can cause the sensor to produce corrupt
frames and cause missing framing events.

Also fixup the vblank control min/max/default/step paramters when
setting up.

Signed-off-by: Naushir Patuck <[email protected]>

drivers: media: imx500: Simplify the vblank control init

Set the VBLANK control minimum and default values to IMX500_VBLANK_MIN
unconditionally everywhere.

Remove the mode specific framerate_default parameter, it is now unused.

Signed-off-by: Naushir Patuck <[email protected]>

drivers: media: imx500: Enable LS correction

This correction is calibrated to approx 5000K.

Signed-off-by: Naushir Patuck <[email protected]>

imx500: Fix for long exposure setup

The IMX500 (unlike the IMX477/IMX708) requires two regsiters to be set
for the exposure shift value to work correctly. The additional register
write (which was missing) is for the integration time shift.

Signed-off-by: Naushir Patuck <[email protected]>

drivers: media: imx500: Enable sensor temperature monitoring

The register needs to be disabled before loading any firmware, otherwise
the upload fails for unknown reasons. Re-enable before starting the
sensor streaming.

Signed-off-by: Naushir Patuck <[email protected]>

drivers: media: imx500: Add device id readback control

Add a new custom control V4L2_CID_USER_GET_IMX500_DEVICE_ID to allow
userland to query the device id from the IMX500 sensor eeprom.

Note that this device id can only be accessed when a network firmware
has been upoloaded to the device, so cannot be cached on probe.

Signed-off-by: Naushir Patuck <[email protected]>

media: i2c: imx500: pm_runtime error paths

This change amends various error-paths in imx500_start_streaming() to
ensure that pm_runtime refcounts do not remain erroneously incremented
on failure.

Signed-off-by: Richard Oliver <[email protected]>

media: i2c: imx500: GPIO acquire/release semantics

When the imx500 driver is used as part of the 'AI Camera', the poweroff
state is never reached as the camera and gpio driver share a regulator.
By releasing the GPIOs when they are not in use, 'AI Camera' is able to
achieve a powered-down state.

Signed-off-by: Richard Oliver <[email protected]>

media: i2c: imx500: input tensor injection

Input tensor injection is a debug feature that allows a user-controlled
input to be passed directly to IMX500's inference engine (bypassing the
in-built ISP).

Three new custom controls are added to ENABLE_INJECTION before streaming
begins, to provide appropriate input tensors via an INPUT_TENSOR_FD, and
to provide notification of DNN results in the sensor output via
INJECTION_CMP_FRM.

Signed-off-by: Richard Oliver <[email protected]>
Add EXPORT_SYMBOL_GPL() for find_cpio_data() so that loadable modules
may also parse uncompressed cpio.

Signed-off-by: Richard Oliver <[email protected]>
The i.MX8MP makes calls on it's source device to determine
the link-frequency that should be configured on the CSI2 receiver.

When the source is behind a video mux, we need to pass this call through
to the connected device.

Map the control handler of the source device to the video-mux,
essentially proxying all controls on the mux to the device which has
it's link enabled.

Signed-off-by: Kieran Bingham <[email protected]>
system_heap.max_order=<uint>

Signed-off-by: Tvrtko Ursulin <[email protected]>
Add numa_policy kernel argument to allow overriding the kernel's default
NUMA policy at boot time.

Syntax identical to what tmpfs accepts as it's mpol argument is accepted.

Some examples:

 numa_policy=interleave
 numa_policy=interleave=skip-interleave
 numa_policy=bind:0-3,5,7,9-15
 numa_policy=bind=static:1-2

Signed-off-by: Tvrtko Ursulin <[email protected]>
... Make sure CMA zones do not straddle the emulated NUMA nodes ...

Signed-off-by: Tvrtko Ursulin <[email protected]>
…ed allocations

Add iommu_dma_numa_policy= kernel parameter which can be used to modify
the NUMA allocation policy of remapped buffer allocations.

Policy is only used for devices which are not associated with a NUMA node.

Syntax identical to what tmpfs accepts as it's mpol argument is accepted.

Some examples:

 iommu_dma_numa_policy=interleave
 iommu_dma_numa_policy=interleave=skip-interleave
 iommu_dma_numa_policy=bind:0-3,5,7,9-15
 iommu_dma_numa_policy=bind=static:1-2

Signed-off-by: Tvrtko Ursulin <[email protected]>
To help work around certain memory controller limitations or similar, a
random NUMA allocation memory policy is added.

Signed-off-by: Tvrtko Ursulin <[email protected]>
Some apps like linpack use numa_setpolicy to disable numa,
but that tends to have a significant performance hit for us.

If you have a cmdline.txt setting of numa_policy (to something other
than default), then lets ignore runtime changes and stick with
the cmdline.txt setting.

Not specifying numa_setpolicy in cmdline, or setting
numa_setpolicy=default(*) will allow runtime settings to work.

(*) easier to do when numa_setpolicy=interleave is set in DT.

Ignore logging for the first 40 seconds as there are some
expected switches during boot.

Signed-off-by: Dom Cobley <[email protected]>

Show process name in set_mempolicy() ignored message

Signed-off-by: Trevor Man <[email protected]>
As a workaround (and possibly a fix) for CPU spins observed on BCM2837,
use ptep_clear_flush_young instead of ptep_test_and_clear_young inside
lru_gen_look_around in order to expose PTE changes to the MMU. Note that
on architectures that don't require an explicit flush,
ptep_clear_flush_young just calls ptep_test_and_clear_young.

Signed-off-by: Phil Elwell <[email protected]>
A user has reported that a card of this model from late 2021 doesn't
work, so extend the date range and make it match on all card sizes.

Signed-off-by: Jonathan Bell <[email protected]>
Add two quirk properties that control whether or not the controller
issues many more handshakes to FS/HS Async endpoints in a single
(micro)frame. Enabling these can significantly increase throughput for
endpoints that frequently respond with NAKs.

Signed-off-by: Jonathan Bell <[email protected]>
If a device frequently NAKs, it can exhaust the scheduled handshakes in
a frame. It will then not get polled by the controller until the next
frame interval. This is most noticeable on FS devices as the controller
schedules a small set of transactions only once per full-speed frame.

Setting the ENH_PER_NAK_FS/LS bits in the GUCTL1 register increases the
number of transactions that can be scheduled to Async (Control/Bulk)
endpoints in the respective frame time. In the FS case, this only
applies to FS devices directly connected to root ports.

Signed-off-by: Jonathan Bell <[email protected]>
6by9 and others added 25 commits November 10, 2025 11:10
The regulator compatible string changed, and implements the PWM
API instead of the backlight one, therefore requiring pwm-backlight
to sit inbetween.

Signed-off-by: Dave Stevenson <[email protected]>
Add an overlay to allow composite video to be output on GPIOs 4-11
on Raspberry Pi 5, 500, 500+ or CM5 only, with an optional 108 MHz
clock on GPIO 0 and duplicate MSB on GPIO 27.

Requires composite video to be enabled and DPI to be disabled.

Signed-off-by: Nick Hollinghurst <[email protected]>
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

@popcornmix popcornmix force-pushed the rpi-6.18.y branch 4 times, most recently from d003d86 to dff72a6 Compare December 1, 2025 12:35
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.