Gaining low-level SPI access on the Raspberry Pi

We’ve seen a ton of projects that interface hardware with the Raspberry Pi. But they usually depend on bit-banging. That means they toggle the pins in software to match a specific protocol. The thing is that the beefy Broadcom SoC that anchors the board has a lot of built-in peripherals that are just waiting to be used instead of bit banging. In this case, it’s the hardware SPI peripheral which can be accessed via the bcm2835 library for RPi.

One of the things that would have really complicated this process is the pin mapping between the Broadcom chip and the RPi GPIO header. Since not all pins are broken out, it was either luck or good design forethought that made all of the SPI0 pins from the chip available on the RPi breakout header. The library page (linked above) explains this well. But if you’re looking for more of a working example check out [EngineerByNight’s] project with adds an accelerometer using hardware SPI.

@JC No doubt there are probably other ways to do this. If you find a way to successfully communicate with SPI accelerometer on the Raspberry Pi using “the linux input layer,” I’d like to know how you did it. I tried that route first, with little success… The linux drivers are out there, but little guidance (that I am capable of understanding) on how to use them.

Still not proper – uses ‘undocumented’ input events. But it at least goes through the linux event layer already.

Even this has advantages already – you don’t need to poll the accelerometer, a platform driver can tie an interrupt to the accelerometer for example.

For Freerunner (GP2X Caanoo – same problem): due to extremely common problem of ‘source page not up anymore and nothing related ever got upstream’, I’m sending a link to pastebin from my local git copy: http://pastebin.com/jr4ZzfAz

This is crucial – when you stick accelerometer on SPI bus, how is linux to know that it’s there? You’re basically ‘making your own board’. Don’t worry though – you can have both generic raspi platform data AND your own – and you can even compile it as a kernel module so that you don’t have to mess with replacing the kernel :)

That piece there tells that theres an accelerometer present, handled by the lis302dl driver (your platform code should depend on that in kconfig ;P) and passes to it a pointer to already statically filled platform specific data structure.

Lets look at that platform specific data that the accelerometer driver gets from your platform driver:

Well.. thanks to this, that accelerometer driver will have all it needs to know to register with the SPI bus driver and tell it how to prepare the SPI bus for it. And then the accel driver can work happily ever after, receiving interrupts and generating input event structures passed to the kernel and almost-proper magic happens :)

Also look that there’s platform-specific interrupt handler code there too – very common. You can have multiple devices on single interrupt line, things that require special handling, etc.

Basically, when you do an acceleromterer driver, only put functionality necessary for translating raw SPI data into xyz and other ‘logical’ things. Leave anything ‘not common to every platform that uses this accelerometer’ in the platform code.
On the other hand: DON’T ever implement whole drivers in platform code. If anything could be reused, it should be a separate driver.

You can see that the freerunner code is pretty ugly (bitbanging inside platform driver), the devs were on a tight schedule desperately trying to get it work right until the end. I haven’t seen a better one yey.

It presents a char device node for reading/writing or memory mapping, as well as ioctls for sending screen commands like on/off
I’ll get a video up when I find another SD card – the one for my camera is running my Pi