bcm2835_spi...fer_prologue(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’– NAME πŸ’–

okay bestie, welcome to bcm2835_spi_transfer_prologue(9) in the Kernel API Manual β€” this page is literally about how to transfer first few bytes without DMA. tiny prologue, big main-character energy ✨

✨ SYNOPSIS ✨

void bcm2835_spi_transfer_prologue (struct spi_controller *ctlr , struct
       spi_transfer *tfr , struct bcm2835_spi *bs , u32 cs );

πŸŽ€ ARGUMENTS πŸŽ€

  • ctlr β€” SPI host controller. the host with the most, basically.
  • tfr β€” SPI transfer. the actual transfer being served.
  • bs β€” BCM2835 SPI controller. our specific controller bestie.
  • cs β€” CS register. yes, the register. iconic.

πŸ’… DESCRIPTION πŸ’…

so here’s the DMA-mode limitation, and it’s giving strict 4 byte chunk energy: the FIFO must be accessed in 4 byte chunks. Only the final write access is permitted to transmit less than 4 bytes, and the SPI controller deduces its intended size from the DLEN register. slay, but also constraint.

okay so picture a TX or RX sglist with multiple entries, one per page, and the first entry starts in the middle of a page. that first entry’s length may not be a multiple of 4. subsequent entries are fine because they span an entire page, hence they do have a length that’s a multiple of 4. periodt.

this cannot happen with kmalloc'ed buffers (which is what most clients use) because they are contiguous in physical memory and therefore not split on page boundaries by spi_map_buf. but it can happen with vmalloc'ed buffers. not the vmalloc plot twist 😭

the DMA engine is incapable of combining sglist entries into a continuous stream of 4 byte chunks β€” it treats every entry separately: a TX entry is rounded up to a multiple of 4 bytes by transmitting surplus bytes, and an RX entry is rounded up by throwing away received bytes. the audacity, honestly.

overcome this limitation by transferring the first few bytes without DMA: E.g. if the first TX sglist entry’s length is 23 and the first RX’s is 42, write 3 bytes to the TX FIFO but read only 2 bytes from the RX FIFO. the residue of 1 byte in the RX FIFO is picked up by DMA. together with the rest of the first RX sglist entry it makes up a multiple of 4 bytes. math ate, truly.

should the RX prologue be larger β€” say, 3 vis-Γ -vis a TX prologue of 1 β€” write 1 + 4 = 5 bytes to the TX FIFO and read 3 bytes from the RX FIFO.

Caution bestie: the additional 4 bytes spill over to the second TX sglist entry if the length of the first is exactly 1. πŸ’€

at most 6 bytes are written and at most 3 bytes read. do we know the transfer has this many bytes? yes β€” see BCM2835_SPI_DMA_MIN_LENGTH. slay, it’s documented.

the FIFO is normally accessed with 8-bit width by the CPU and 32-bit width by the DMA engine. toggling the DMA Enable flag in the CS register switches the width but also garbles the FIFO’s contents. the prologue must therefore be transmitted in 32-bit width to ensure that the following DMA transfer can pick up the residue in the RX FIFO in ungarbled form. no cap, width matters.

πŸ¦‹ SEE ALSO πŸ¦‹

Kernel file ./drivers/spi/spi-bcm2835.c β€” and the whole friend group is:

mwah πŸ’‹ this page comes from ./drivers/spi, dated October 2026 β€” go forth and prologue responsibly, bestie 🫢✨

πŸ“¦ where this page comes from