bcm2835_spi_...sfer_one_dma(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

okay so this is the bcm2835_spi_...sfer_one_dma(9) page from the Kernel API Manual, and bestie, we're getting into SPI transfer via DMA engine energy πŸ’…βœ¨

πŸ’– NAME πŸ’–

bcm2835_spi_transfer_one_dma β€” perform SPI transfer using DMA engine. that's it, that's the name πŸŽ€

✨ SYNOPSIS ✨

int bcm2835_spi_transfer_one_dma (struct spi_controller *ctlr , struct
       spi_transfer *tfr , struct bcm2835_spidev *target , u32 cs );

no cap, that's the whole signature 🫢

πŸŽ€ ARGUMENTS πŸŽ€

okay who's who in this cast:

  • ctlr β€” SPI host controller
  • tfr β€” SPI transfer
  • target β€” BCM2835 SPI target
  • cs β€” CS register

all four are main characters, no skips πŸ’œ

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so the tea is: this function handles different transfer modes, and each one has its own little routine. here's the breakdown πŸ‘‡

Bidirectional transfers β€” when both tx_buf and rx_buf are non-NULL β€” are the setup where it sets up the TX and RX DMA channel to copy between memory and the FIFO register. slay.

TX-only transfers (rx_buf is NULL): copying the RX FIFO's contents to memory is pointless. but not reading the RX FIFO isn't an option either, because transmission is halted once it's full. so the workaround is to cyclically clear the RX FIFO by setting the CLEAR_RX bit in the CS register. iconic.

the CS register value is precalculated in bcm2835_spi_setup. normally this is called only once, on target registration. a DMA descriptor to write this value is preallocated in bcm2835_dma_init. all that's left to do when performing a TX-only transfer is to submit this descriptor to the RX DMA channel. latency is thereby minimized. the descriptor does not generate any interrupts while running. it must be terminated once the TX DMA channel is done. periodt.

clearing the RX FIFO is paced by the DREQ signal. the signal is asserted when the RX FIFO becomes half full, i.e. 32 bytes. (tuneable with the DC register.) reading 32 bytes from the RX FIFO would normally require 8 bus accesses, whereas clearing it requires only 1 bus access. so you get an 8-fold reduction in bus traffic and thus energy consumption. ate that up πŸ”₯

RX-only transfers (tx_buf is NULL): fill the TX FIFO by cyclically copying from the zero page. the DMA descriptor to do this is preallocated in bcm2835_dma_init. it must be terminated once the RX DMA channel is done and can then be reused. iykyk.

the BCM2835 DMA driver autodetects when a transaction copies from the zero page and utilizes the DMA controller's ability to synthesize zeroes instead of copying them from memory. this reduces traffic on the memory bus. the feature is not available on so-called "lite" channels, but normally TX DMA is backed by a full-featured channel. not me being obsessed with zero-page autodetection ✨

zero-filling the TX FIFO is paced by the DREQ signal. unfortunately the BCM2835 SPI controller continues to assert DREQ even after the DLEN register has been counted down to zero (hardware erratum). thus, when the transfer has finished, the DMA engine zero-fills the TX FIFO until it is half full. (tuneable with the DC register.) so up to 9 gratuitous bus accesses are performed at the end of an RX-only transfer. 😭 that's the hardware erratum tea, bestie.

🌈 SEE ALSO 🌈

Kernel file ./drivers/spi/spi-bcm2835.c is the source spot, and these are the related cuties:

go read those if you want the full lore 🫢


okay that's the whole page β€” source/version spot: ./drivers/spi; date: October 2026; page: bcm2835_spi_...sfer_one_dma(9). bye bestie, go make that SPI DMA transfer slay πŸ’–βœ¨

πŸ“¦ where this page comes from