From eLinux.org
Jump to: navigation, search

This document describes SPI Slave support, and how to test it on the Renesas Koelsch board.

SPI Slave Support

Due to the nature of SPI slave (simultaneous transmit and receive, while everything runs at the pace of the master), it has hard real-time requirements: once an SPI transfer is started by the SPI master, a software SPI slave must have prepared all data to be sent back to the SPI master. Hence without additional hardware support, an SPI slave response can never be a reply to a command being simultaneously transmitted, and SPI slave replies must be received by the SPI master in a subsequent SPI transfer.

Examples of possible use cases:

  • Receiving streams of data in fixed-size messages (e.g. from a tuner),
  • Receiving and transmitting fixed-size messages of data (e.g. network frames),
  • Sending commands, and querying for responses,
  • ...

SPI Core Software Support

Core software support for SPI slave controllers includes

  • DT binding updates for SPI slave support,
  • A new "spi_slave" class,
  • A mechanism to associate SPI slave handlers with an SPI slave controller (through DT or sysfs).

From the point of view of an SPI slave protocol handler, an SPI slave controller looks almost like an ordinary SPI master controller. The only exception is that a transfer request will block on the remote SPI master, and may be cancelled using spi_slave_abort().

Known Bugs and Limitations

  • Handshaking (5-pin SPI, RDY-signal) is optional. An RDY-signal may be used for one or both of:
    • The SPI slave asserts RDY when it has data available, and wants to be queried by the SPI master. -> This can be handled on top, in the SPI slave protocol handler, using a GPIO.
    • After the SPI master has asserted CS, the SPI slave asserts RDY when it is ready to accept the transfer. -> This may need hardware support in the SPI slave controller, or dynamic GPIO vs. CS pinmuxing.

SPI Slave Controller Hardware Support


SPI Slave Controller support has been implemented for the MSIOF module (which can be found in e.g. Renesas R-Car Gen2 SoCs), in the "spi-sh-msiof" SPI driver. It supports both PIO and DMA mode (the transfer length must be a multiple of 4 bytes to use DMA).

Known Bugs and Limitations

  • This has been tested on the Renesas R-Car Gen2-based Koelsch development board only, using external loopback between two MSIOF instances.
  • For now, the MSIOF SPI slave driver only supports the transmission of messages with a size that is known in advance (the hardware can provide an interrupt when CS is deasserted before, though). I.e. when the SPI master sends a shorter message, the slave won't receive it. When the SPI master sends a longer message, the slave will receive the first part, and the rest will remain in the FIFO.

SPI Slave Handlers

With this prototype, two examples SPI slave handlers are provided:

  • "spi-slave-time" responds with the system uptime at the time of reception of the last SPI message, which can be used by an external microcontroller as a dead man's switch,
  • "spi-slave-system-control" allows remote control of system reboot, power off, halt, and suspend.

In addition, "spidev" can be used to handle SPI slave from userspace.

Kernel Source Code

All code is available in the following Git repository:


Hardware Test Environment

All testing has been done on the Renesas Koelsch development board.

Test wiring between MSIOF1 and MSIOF2 on EXIO Connector A:

  • Connect pin 48 ("MSIOF1 CS#") to pin 63 ("MSIOF2 CS#"),
  • Connect pin 46 ("MSIOF1 SCK") to pin 61 ("MSIOF2 SCK"),
  • Connect pin 54 ("MSIOF1 TX/MOSI") to pin 70 ("MSIOF2 RX/MOSI"),
  • Connect pin 56 ("MSIOF1 RX/MISO") to pin 68 ("MSIOF2 TX/MISO").

To ease wiring, you can use Samtec-Breakout-Adapters.

Software Test Environment

Kernel Source Tree

Please use the following Git repository:

Kernel Configuration

  • Build and install a kernel using "shmobile_defconfig", with the following additional options enabled:

Test Utilities

Test Procedure

  • Load all needed DT overlays by typing:
overlay add a-msiof1-spidev a-msiof2-slave

Expected output in the kernel log:

spi_sh_msiof e6e10000.spi: DMA available
spidev spi2.0: buggy DT: spidev listed directly in DT
------------[ cut here ]------------
WARNING: ... spidev_probe ...
spi_sh_msiof e6e00000.spi: DMA available

Note that the warning is expected and harmless.

Example 1: spi-slave-time

  • Enable the "spi-slave-timer" handler:
echo spi-slave-time > /sys/class/spi_slave/spi3/slave
  • Send 8 dummy bytes and receive the responce from the slave handler:
spidev_test -D /dev/spidev2.0 -p dummy-8B
  • Expected output:
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
RX | 00 00 04 6D 00 09 5B BB __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  | ...m..[�

0x0000046D and 0x00095BBB (actual numbers may vary) are the system (boot up) time in seconds resp. microseconds when the previous SPI message was received (or the driver was initialized, for the first message).

Example 2: spi-slave-system-control

  • Enable the "spi-slave-system-control" handler:
echo spi-slave-system-control > /sys/class/spi_slave/spi3/slave
  • Send a command to the slave handler:
spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt
  • Expected result: The system suspends (reboots, powers down, or halts).

Example 3: spidev


echo spidev > /sys/class/spi_slave/spi3/slave
spidev_test -D /dev/spidev3.0 -p slave-hello-to-master &
spidev_test -D /dev/spidev2.0 -p master-hello-to-slave

Expected output:

RX | 6D 61 73 74 65 72 2D 68 65 6C 6C 6F 2D 74 6F 2D 73 6C 61 76 65 __ __ __ __ __ __ __ __ __ __ __  | master-hello-to-slave
RX | 73 6C 61 76 65 2D 68 65 6C 6C 6F 2D 74 6F 2D 6D 61 73 74 65 72 __ __ __ __ __ __ __ __ __ __ __  | slave-hello-to-master

Known Issues

  • As handlers write data to the FIFO prior to the master requesting the data, this data will still be in the FIFO when changing handlers, and be transmitted later.