[[PageOutline]] = Serial Peripheral Interface Bus (SPI) = The Serial Peripheral Interface bus is a synchronous serial communication interface specification used for short distance communication primary in embedded systems. The interface was originally developed by Motorola and can be used in a master or slave configuration. It is typically used as a 3-wire bus containing the following signals (other than power and ground and chip-selects): * SCLK * MISO * MOSI * SS# (Optional Slave Select) SPI can be a multi-slave bus if chip selects are used which are asserted by the host controller to enable one device at a time. References: * http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus == On-Board SPI controllers == [=#spitable] === Newport / Ventana === Various Gateworks boards support 3.3V TTL SPI to an off-board expansion connector with a single CS#: ||= Family =||= Board =||= Device Tree Node =||= Connector =|| || Newport || GW630x || spi_7_0 || J8 || || || GW640x || spi_7_0 || J8 || || || || Ventana || GW522x || ecspi3 || J24 || || || GW54xx-E+ || ecspi2 || J32 || Pinout (all signals are 3.3V TTL): * 1 - MOSI * 2 - MISO * 3 - SCLK * 4 - SS0# (This is chip select 0) * 5 - 3.3V * GND === Laguna === While SPI is used for on-board FLASH storage for many Laguna boards, it also is brought out to the J9 expansion connector available on the Laguna GW2388: * J9.2 - CS# * J9.4 - SCLK * J9.6 - MISO * J9.8 - MOSI * J9.10 - GND [[Image(spi2388.png,800px)]] For details on adding kernel devices to the Laguna kernel see [#laguna below] [=#usb] == USB SPI controllers == A SPI master can also be added via USB expansion. For example: * [http://trac.gateworks.com/wiki/expansion/gw16113 GW16113 firmware-flexible USB 2.0 FS expansion] * [http://www.commell.com.tw/product/Peripheral/PCI%20Express%20mini%20card/MPX-24794S.HTM Commell MPX-24794S USB 2.0 FS SPI/I2C/GPIO expansion] [=#linux] == Using a Linux SPI kernel driver == [=#devicetree] === device-tree: Newport / Ventana === Linux kernels that utilize the device-tree need to add a device-tree node to the SPI controller to use a kernel driver. Note that you can also access SPI from userspace using {{{spidev}}} (see [#spidev below]) An example device-tree child node for a m25p32-vme6g nor flash device would be: {{{#!c flash: m25p80@0 { /* "m25p32" is your device ID string */ compatible = "m25p32"; /* device frequency (in MHz) */ spi-max-frequency = <30000000>; /* Chip Select */ reg = <0>; /* see dts documentation for your device */ #device-width = <1>; #address-cells = <1>; #size-cells = <1>; partition@0 { /* The name of this partition */ label = "data"; /* starting address and length */ reg = <0x0 0x2000000>; }; }; }}} Note that this node must appear within the SPI host controller. For a list of device-tree nodes [#spitable see above]. Note that the values shown in the above node are specific to the m25p32-vme6g, and can vary greatly from the actual device you are using. Replace attribute values as necessary. When searching for your device ID string or its controlling driver, searching via a Linux LXR site like the one at [https://lxr.missinglinkelectronics.com/linux missing link electronics] for your device name can be helpful. [=#laguna] === non-device-tree: Laguna === Linux kernels that do not utilize device-tree need to register a {{{spi_board_info}}} struct with the kernel via {{{spi_register_board_info()}}}. To add a SPI device to Laguna you would add it to the spi_board_info array in {{{laguna.c}}}. Be sure to specify chip_select=1 to use CS1 as CS0 is used for the on-board SPI FLASH device. References: * [https://github.com/Gateworks/openwrt/blob/16.02/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/laguna.c#L188 spi_board_info struct] * [https://github.com/Gateworks/openwrt/blob/16.02/target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/laguna.c#L1097 call to spi_register_board_info()] [=#spidev] == Linux spidev userspace API == SPI devices have a limited userspace API, supporting basic half-duplex read() and write() access to SPI slave devices referred to as {{{spidev}}}. Using ioctl() requests, full duplex transfers and device I/O configuration are also available. Some reasons you might want to use this programming interface include: * Prototyping in an environment that's not crash-prone; stray pointers in userspace won't normally bring down any Linux system. * Developing simple protocols used to talk to micro-controllers acting as SPI slaves, which you may need to change quite often. Of course there are drivers that can never be written in userspace, because they need to access kernel interfaces (such as IRQ handlers or other layers of the driver stack) that are not accessible to userspace. Userspace access to SPI devices is done through the /dev/spidev. device interface. In order to use this you must have spidev enabled in the kernel (CONFIG_SPI_SPIDEV) and have a spidev node defined under the SPI controller in the device-tree. In order to support {{{spidev}}} a spidev child node needs to be present in the device-tree under the SPI host controller. For example, a GW54xx which brings out the ecspi2 host interface: {{{#!c &ecspi2 { cs-gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_ecspi2>; status = "okay"; spidev0: spidev@0 { compatible = "rohm,dh2228fv"; reg = <0>; spi-max-frequency = <60000000>; }; }; }}} For instructions on compiling and updating a device-tree see [wiki:linux/devicetree linux/devicetree] An application using {{{spidev}}} would include the {{{}}} header file. For more info see: * [https://www.kernel.org/doc/Documentation/spi/spidev Kernel Documentation]