Skip to content
notro edited this page Sep 13, 2015 · 11 revisions

Note: Mainline spi-bcm2835 has DMA support now, so this project is discontinued.

This is a fork of the DMA capable SPI master driver by Martin Sperl.

In addition to adding DMA it also silences this message

bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated

Note: DMA can not be used from userspace. spidev does not support it.

Module arguments

  • mode
    2 - dma (default)
    1 - interrupt
    0 - polled
  • realtime
    Run with realtime priority
  • debug
    1: Print info from bcm2708_setup_state() about clock divisor etc.

Technical details

SPI Clock divider

Excerpt from BCM2835 ARM Peripherals datasheet page 156:

  CLK Register
---------------------------------------------------------------------------------------
Synopsis: This register allows the SPI clock rate to be set. 

Bit(s)  Field Name   Description                                         Type   Reset
15:0     CDIV         Clock Divider                                       RW     0x0
                      SCLK = Core Clock / CDIV 
                      If CDIV is set to 0, the divisor is 65536. The 
                      divisor must be a power of 2. Odd numbers 
                      rounded down. The maximum SPI clock rate is 
                      of the APB clock.

This limitation has been expressed with this statement in the driver:

static int bcm2708_setup_state()
[...]
		/* CDIV must be a power of 2, so round up */
		cdiv = roundup_pow_of_two(cdiv);

Testing has shown that this limitation is not needed (forum post).
The FBTFT prebuilt kernel has had this limitation lifted since the end of May 2013 without any reports of malfunction.

FIFO size

Excerpt from BCM2835 ARM Peripherals datasheet page 158:

10.6.2 Interrupt 
e) Set INTR and INTD. These can be left set over multiple operations. 
f) Set CS, CPOL, CPHA as required and set TA = 1. This will immediately trigger a 
first interrupt with DONE == 1. 
g) On interrupt: 
h) If DONE is set and data to write (this means it is the first interrupt), write up to 16 
bytes to SPI_FIFO. If DONE is set and no more data, set TA = 0. Read trailing data 
from SPI_FIFO until RXD is 0. 
i) If RXR is set read 12 bytes data from SPI_FIFO and if more data to write, write up to 
12 bytes to SPIFIFO.

The vanilla driver follows this to the letter. Martin Sperl in his version fills the FIFO until it is full.
I added printk statements to bcm2708_transfer_one_message_irqdriven() and bcm2708_transfer_one_message_irqdriven_irqhandler() printing out how many bytes was written to the FIFO. This showed that the buffer can be filled with 110-120 bytes. This gives a tenth the number of interrupts per transfer.

Bidirectional mode

In bidirectional SPI master mode the same SPI standard is implemented except that a single wire is used for the data (MIMO) instead of the two as in standard mode (MISO and MOSI).
This is not implemented (SPI_3WIRE).

LoSSI mode

The SPI hardware has support for something called Low Speed Serial Interface. This is 9-bit SPI in bidirectional mode. There is one caveat however, certain values (commands) triggers the SPI controller to do a 8 or 24-bit SPI read. This makes this mode only useful for LoSSI slaves like certain LCD Controllers.
The Linux SPI subsystem has no support for LoSSI, so it's not implemented.

References

Clone this wiki locally
You can’t perform that action at this time.