| ==================================== | |
| SPI devices with multiple data lanes | |
| ==================================== | |
| Some specialized SPI controllers and peripherals support multiple data lanes | |
| that allow reading more than one word at a time in parallel. This is different | |
| from dual/quad/octal SPI where multiple bits of a single word are transferred | |
| simultaneously. | |
| For example, controllers that support parallel flash memories have this feature | |
| as do some simultaneous-sampling ADCs where each channel has its own data lane. | |
| --------------------- | |
| Describing the wiring | |
| --------------------- | |
| The ``spi-tx-bus-width`` and ``spi-rx-bus-width`` properties in the devicetree | |
| are used to describe how many data lanes are connected between the controller | |
| and how wide each lane is. The number of items in the array indicates how many | |
| lanes there are, and the value of each item indicates how many bits wide that | |
| lane is. | |
| For example, a dual-simultaneous-sampling ADC with two 4-bit lanes might be | |
| wired up like this:: | |
| +--------------+ +----------+ | |
| | SPI | | AD4630 | | |
| | Controller | | ADC | | |
| | | | | | |
| | CS0 |--->| CS | | |
| | SCK |--->| SCK | | |
| | SDO |--->| SDI | | |
| | | | | | |
| | SDIA0 |<---| SDOA0 | | |
| | SDIA1 |<---| SDOA1 | | |
| | SDIA2 |<---| SDOA2 | | |
| | SDIA3 |<---| SDOA3 | | |
| | | | | | |
| | SDIB0 |<---| SDOB0 | | |
| | SDIB1 |<---| SDOB1 | | |
| | SDIB2 |<---| SDOB2 | | |
| | SDIB3 |<---| SDOB3 | | |
| | | | | | |
| +--------------+ +----------+ | |
| It is described in a devicetree like this:: | |
| spi { | |
| compatible = "my,spi-controller"; | |
| ... | |
| adc@0 { | |
| compatible = "adi,ad4630"; | |
| reg = <0>; | |
| ... | |
| spi-rx-bus-width = <4>, <4>; /* 2 lanes of 4 bits each */ | |
| ... | |
| }; | |
| }; | |
| In most cases, lanes will be wired up symmetrically (A to A, B to B, etc). If | |
| this isn't the case, extra ``spi-rx-lane-map`` and ``spi-tx-lane-map`` | |
| properties are needed to provide a mapping between controller lanes and the | |
| physical lane wires. | |
| Here is an example where a multi-lane SPI controller has each lane wired to | |
| separate single-lane peripherals:: | |
| +--------------+ +----------+ | |
| | SPI | | Thing 1 | | |
| | Controller | | | | |
| | | | | | |
| | CS0 |--->| CS | | |
| | SDO0 |--->| SDI | | |
| | SDI0 |<---| SDO | | |
| | SCLK0 |--->| SCLK | | |
| | | | | | |
| | | +----------+ | |
| | | | |
| | | +----------+ | |
| | | | Thing 2 | | |
| | | | | | |
| | CS1 |--->| CS | | |
| | SDO1 |--->| SDI | | |
| | SDI1 |<---| SDO | | |
| | SCLK1 |--->| SCLK | | |
| | | | | | |
| +--------------+ +----------+ | |
| This is described in a devicetree like this:: | |
| spi { | |
| compatible = "my,spi-controller"; | |
| ... | |
| thing1@0 { | |
| compatible = "my,thing1"; | |
| reg = <0>; | |
| ... | |
| }; | |
| thing2@1 { | |
| compatible = "my,thing2"; | |
| reg = <1>; | |
| ... | |
| spi-tx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for tx wire */ | |
| spi-rx-lane-map = <1>; /* lane 0 is not used, lane 1 is used for rx wire */ | |
| ... | |
| }; | |
| }; | |
| The default values of ``spi-rx-bus-width`` and ``spi-tx-bus-width`` are ``<1>``, | |
| so these properties can still be omitted even when ``spi-rx-lane-map`` and | |
| ``spi-tx-lane-map`` are used. | |
| ---------------------------- | |
| Usage in a peripheral driver | |
| ---------------------------- | |
| These types of SPI controllers generally do not support arbitrary use of the | |
| multiple lanes. Instead, they operate in one of a few defined modes. Peripheral | |
| drivers should set the :c:type:`struct spi_transfer.multi_lane_mode <spi_transfer>` | |
| field to indicate which mode they want to use for a given transfer. | |
| The possible values for this field have the following semantics: | |
| - :c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are | |
| ignored. This means that it is operating just like a conventional SPI | |
| peripheral. This is the default, so it does not need to be explicitly set. | |
| Example:: | |
| tx_buf[0] = 0x88; | |
| struct spi_transfer xfer = { | |
| .tx_buf = tx_buf, | |
| .len = 1, | |
| }; | |
| spi_sync_transfer(spi, &xfer, 1); | |
| Assuming the controller is sending the MSB first, the sequence of bits | |
| sent over the tx wire would be (right-most bit is sent first):: | |
| controller > data bits > peripheral | |
| ---------- ---------------- ---------- | |
| SDO 0 0-0-0-1-0-0-0-1 SDI 0 | |
| - :c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the | |
| lanes at the same time. This only makes sense for writes and not | |
| for reads. | |
| Example:: | |
| tx_buf[0] = 0x88; | |
| struct spi_transfer xfer = { | |
| .tx_buf = tx_buf, | |
| .len = 1, | |
| .multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR, | |
| }; | |
| spi_sync_transfer(spi, &xfer, 1); | |
| The data is mirrored on each tx wire:: | |
| controller > data bits > peripheral | |
| ---------- ---------------- ---------- | |
| SDO 0 0-0-0-1-0-0-0-1 SDI 0 | |
| SDO 1 0-0-0-1-0-0-0-1 SDI 1 | |
| - :c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words | |
| at the same time, one on each lane. This means that the buffer needs to be | |
| sized to hold data for all lanes. Data is interleaved in the buffer, with | |
| the first word corresponding to lane 0, the second to lane 1, and so on. | |
| Once the last lane is used, the next word in the buffer corresponds to lane | |
| 0 again. Accordingly, the buffer size must be a multiple of the number of | |
| lanes. This mode works for both reads and writes. | |
| Example:: | |
| struct spi_transfer xfer = { | |
| .rx_buf = rx_buf, | |
| .len = 2, | |
| .multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE, | |
| }; | |
| spi_sync_transfer(spi, &xfer, 1); | |
| Each rx wire has a different data word sent simultaneously:: | |
| controller < data bits < peripheral | |
| ---------- ---------------- ---------- | |
| SDI 0 0-0-0-1-0-0-0-1 SDO 0 | |
| SDI 1 1-0-0-0-1-0-0-0 SDO 1 | |
| After the transfer, ``rx_buf[0] == 0x11`` (word from SDO 0) and | |
| ``rx_buf[1] == 0x88`` (word from SDO 1). | |
| ----------------------------- | |
| SPI controller driver support | |
| ----------------------------- | |
| To support multiple data lanes, SPI controller drivers need to set | |
| :c:type:`struct spi_controller.num_data_lanes <spi_controller>` to a value | |
| greater than 1. | |
| Then the part of the driver that handles SPI transfers needs to check the | |
| :c:type:`struct spi_transfer.multi_lane_mode <spi_transfer>` field and implement | |
| the appropriate behavior for each supported mode and return an error for | |
| unsupported modes. | |
| The core SPI code should handle the rest. |