8d technologies

spi-char: Bi-directional communication with an SPI device using a character device

About | Download | Usage | Contact
< Back to main page

This kernel modules implements a character device which allows to communicate with an SPI device via a character device. I developped this module for use in our products, but made the code available under the GPL license.

There are pitfalls:

When communicating using SPI, for each byte sent by the master, the slave sends one too. In our case, when the salve has data to send, it interrupts the master. To read the byte, the master must send a byte too. If the master has no data to transmit, this module sends NUL (0x00) bytes. This behaviour must be taken into account when designing the communication protocol. (eg: Use a header and transmit data inside packets).

When writing a packet to the character device, use only one write. If you split the packet in multiple consecutive writes and the slave wants to send you data between two pieces (at a moment where the master has nothing to send), the slave may receive some NULs between your pieces of data. (Your checksum should detect this, but the data is lost).

Here is a patch, which I use with 2.6.18-rc2:

This patch adds a config option named "SPI character device" in drivers->char. SPI must be enabled.

To use this module, enable it in menuconfig. You'll also need to enable an SPI Master controller driver for your board/architecture.

This module is a regular SPI protocol driver. You must declare it's association with a specific bus and chip id using struct spi_board_info, typically in your arch/.../mach-*/board-*.c file. See Documenation/spi/spi-summary for more info.

Here is an example, from my compulab cm-x255 kernel patch (cm-x255.c):
static void spichar_cs_control(u32 command)
    if (command & PXA2XX_CS_ASSERT)
        GPCR(17) = GPIO_bit(17);
        GPSR(17) = GPIO_bit(17);

static struct pxa2xx_spi_chip spichar_chip_info = {
    .tx_threshold = 2,
    .rx_threshold = 1,
    .dma_burst_size = 8,
    .timeout_microsecs = 1000,
    .cs_control = spichar_cs_control,

static struct spi_board_info spi_board_info[] __initdata = {
    [0] = {
        .modalias   = "max6902",
        .max_speed_hz   =   1000000,
        .bus_num    = 1,
        .chip_select    = 0,
    [1] = {
        .modalias       = "spi-char",
        .max_speed_hz   = 20000,
        .bus_num        = 2,
        .chip_select    = 0,
        .irq            = IRQ_GPIO(2),
        .controller_data= &spichar_chip_info,

You may contact me by email if you have suggestions, improvements, patches or questions:

Raphael Assenat <raph.armcore@8d.com>