Tests:MSIOF-SPI-Slave

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,

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

 * "spi_master" is now used for both master and slave support, which is a misnomer.
 * 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.

Features
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.
 * The "slave_abort" callback does cancel the current ongoing transfer, but all new transfers are immediately cancelled, too.

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:
 * Repository: git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git
 * Branch: "topic/spi-slave-v2"

= Testing =

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.

Kernel Source Tree
Please use the following Git repository:
 * Repository: git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git
 * Branch: "topic/spi-slave-v2-integration" (This is a merge of "topic/spi-slave-v2" and "topic/renesas-overlays", meant for testing).

Kernel Configuration
CONFIG_OF_OVERLAY=y CONFIG_OF_CONFIGFS=y CONFIG_SPI_SPIDEV=y CONFIG_SPI_SLAVE=y CONFIG_SPI_SLAVE_TIME=y CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y
 * Build and install a kernel using "shmobile_defconfig", with the following additional options enabled:


 * Install the built DT overlays on the target board, cfr. R-Car/DT-Overlays.

Test Utilities

 * , from R-Car/DT-Overlays,
 * , from http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/tools/spi.

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

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
echo spi-slave-time > /sys/class/spi_slave/spi3/slave
 * Enable the "spi-slave-timer" handler:

spidev_test -D /dev/spidev2.0 -p dummy-8B
 * Send 8 dummy bytes and receive the responce from the slave handler:

spi mode: 0x0 bits per word: 8 max speed: 500000 Hz (500 KHz) RX | 00 00 04 6D 00 09 5B BB __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ | ...m..[�
 * Expected output:

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
echo spi-slave-system-control > /sys/class/spi_slave/spi3/slave
 * Enable the "spi-slave-system-control" handler:

reboot='\x7c\x50' poweroff='\x71\x3f' halt='\x38\x76' suspend='\x1b\x1b' spidev_test -D /dev/spidev2.0 -p $suspend # or $reboot, $poweroff, $halt
 * Send a command to the slave handler:


 * Expected result: The system suspends (reboots, powers down, or halts).

Example 3: spidev
Type: 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 ...

Bugs and Known Issues

 * Due to an issue with the "slave_abort" callback, switching to an "spi-slave-*" handler after another "spi-slave-*" handler has been used requires a reboot. Switching to/from the "spidev" handler works fine.
 * 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.