1. Article purpose[edit source]
This article explains how to configure the SPI internal peripheral[1] when the peripheral is assigned to Linux® OS, and in particular:
- how to configure the STM32 SPI peripheral
- how to configure the STM32 external SPI devices present either on the board or on a hardware extension.
The configuration is performed using the device tree mechanism[2].
It is used by the STM32 SPI Linux® driver that registers relevant information in the SPI framework.
If the peripheral is assigned to another execution context, refer to How to assign an internal peripheral to an execution context article for guidelines on peripheral assignment and configuration.
2. DT bindings documentation[edit source]
The SPI bus and its associated device are represented by:
3. DT configuration[edit source]
This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device tree file split.
STM32CubeMX can be used to generate the board device tree. Refer to How to configure the DT using STM32CubeMX for more details.
3.1. DT configuration (STM32 level)[edit source]
At device level, each SPI controller is declared as follows:
- for STM32MP13x lines , refer to DTS file stm32mp131.dtsi[5]
- for STM32MP15x lines , refer to DTS file stm32mp151.dtsi[6]
spi1: spi@44004000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x44004000 0x400>; interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc SPI1_K>; resets = <&rcc SPI1_R>; dmas = <&dmamux1 37 0x400 0x05>, <&dmamux1 38 0x400 0x05>; dma-names = "rx", "tx"; power-domains = <&pd_core>; status = "disabled"; };
- for STM32MP25x lines , refer to DTS file stm32mp251.dtsi[7]
spi1: spi@40230000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32mp25-spi"; reg = <0x40230000 0x400>; interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc CK_KER_SPI1>; resets = <&rcc SPI1_R>; dmas = <&hpdma 49 0x20 0x00003012 0>, <&hpdma 50 0x20 0x00003021 0>; dma-names = "rx", "tx"; feature-domains = <&rifsc STM32MP25_RIFSC_SPI1_ID>; power-domains = <&RET_PD>; status = "disabled"; };
3.2. DT configuration (board level)[edit source]
Master: stm32mpu is used as a SPI master device
&spi1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi1_pins_a>; pinctrl-1 = <&spi1_sleep_pins_a>; status = "okay"; foo@0 { compatible = "spi-foo"; reg = <0>; /* CS #0 */ spi-max-frequency = <10000000>; }; };
Slave: stm32mpu is used as a SPI slave device
&spi1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi5_slave_pins_a>; pinctrl-1 = <&spi5_slave_sleep_pins_a>; status = "okay"; #address-cells = <0>; cs-gpios = <0>; spi-slave; slave { compatible = "spi-slave-foo"; spi-max-frequency = <10000000>; }; };
There are two levels of configuration:
- Configuration of the SPI bus properties:
- pinctrl-0&1 configuration depends on hardware board configuration and on how the SPI devices are connected to MOSI, MISO and Clk pins. In slave mode, NSS pin should also be configured here.
More details about pin configuration are available here: Pinctrl device tree configuration - cs-gpios represents the list of GPIOs used as chip selects. This property is optional. More details about GPIO configuration are available here: GPIO device tree configuration
- dmas: by default, DMAs are specified for all SPI instances. This is up to the user to remove them if they are not needed. /delete-property/ is used to remove DMA usage for SPI. Both /delete-property/dma-names and /delete-property/dmas have to be inserted to get rid of DMAs.
- spi-slave have to be inserted to use STM32MPU as SPI slave device.
- pinctrl-0&1 configuration depends on hardware board configuration and on how the SPI devices are connected to MOSI, MISO and Clk pins. In slave mode, NSS pin should also be configured here.
- Configuration of the properties of the SPI device connected on the bus:
- compatible represents the name of the SPI device driver.
- reg represents the index of the gpio chip select associated to this SPI device.
- spi-max-frequency represents the maximum SPI clocking speed for the device (in Hz).
For more information about SPI bus and SPI device bindings, please refer to spi-controller.yaml[3]
3.3. DT configuration example[edit source]
3.3.1. Example of an external TPM device[edit source]
&spi1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi1_pins_a>; pinctrl-1 = <&spi1_sleep_pins_a>; cs-gpios = <&gpioz 3 0>; status = "okay"; st33zp24@0 { compatible = "st,st33htpm-spi"; reg = <0>; /* CS #0 */ spi-max-frequency = <10000000>; }; };
The above example registers a TPM device on spi1 bus, selected by chip select 0 also known as GPIO-Z3. This instance is compatible with the driver registered with the same compatible property (st,st33htpm-spi).
3.3.2. Example of SPI master/slave communication on STM32MP157F-DK2 board[edit source]
Configuration on board device tree stm32mp157f-dk2.dts[8]
/* SPI4 configured as master */
&spi4 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&spi4_pins_b>;
pinctrl-1 = <&spi4_sleep_pins_b>;
status = "okay";
cs-gpios= <&gpioe 11 0>;
master@0 {
compatible = "rohm,dh2228fv";
reg = <0>; /* CS #0 */
spi-max-frequency = <10000000>;
};
};
/* SPI5 configured as slave */
&spi5 {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&spi5_pins_a>;
pinctrl-1 = <&spi5_sleep_pins_a>;
status = "okay";
#address-cells = <0>;
cs-gpios = <0>;
spi-slave;
slave {
compatible = "lwn,bk4";
spi-max-frequency = <10000000>;
};
};
On master side, the chip-select is managed by the software itself, allowing it to control the corresponding cs gpio depending on the slave it wants to talk to. This is the reason why you can observe the NSS pin declared as above in the cs-gpio property, in SPI4 node. However, for the slave (SPI5), this is purely an hardware configuration, so the NSS is declared directly in the pinctrl DT as you can see below.
Configuration of the pinctrl device tree stm32mp15-pinctrl.dtsi[9]
spi4_pins_b: spi4-1 { pins1 { pinmux = <STM32_PINMUX('E', 12, AF5)>, /* SPI4_SCK */ <STM32_PINMUX('E', 14, AF5)>; /* SPI4_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = <STM32_PINMUX('E', 13, AF5)>; /* SPI4_MISO */ bias-disable; }; }; spi4_sleep_pins_b: spi4-sleep-1 { pins { pinmux = <STM32_PINMUX('E', 12, ANALOG)>, /* SPI4_SCK */ <STM32_PINMUX('E', 13, ANALOG)>, /* SPI4_MISO */ <STM32_PINMUX('E', 14, ANALOG)>; /* SPI4_MOSI */ }; }; spi5_pins_a: spi5-0 { pins1 { pinmux = <STM32_PINMUX('F', 7, AF5)>, /* SPI5_SCK */ <STM32_PINMUX('F', 9, AF5)>; /* SPI5_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = <STM32_PINMUX('F', 8, AF5)>, /* SPI5_MISO */ <STM32_PINMUX('F', 6, AF5)>; /* SPI5_NSS */ bias-disable; }; }; spi5_sleep_pins_a: spi5-sleep-0 { pins { pinmux = <STM32_PINMUX('F', 7, ANALOG)>, /* SPI5_SCK */ <STM32_PINMUX('F', 8, ANALOG)>, /* SPI5_MISO */ <STM32_PINMUX('F', 9, ANALOG)>, /* SPI5_MOSI */ <STM32_PINMUX('F', 6, ANALOG)>; /* SPI5_NSS */ }; };
The example above show how to configure DT and pins to setup a master/slave communication on STM32MP157F-DK2 board. Indeed, both SPI4 and SPI5 have GPIOs available directly on the disco board, that let us connect the good pins together in order to make our test.
Wires to add:
CN13 Connector | CN2 Connector |
---|---|
Pin 3 - SPI4_NSS (PE11) | Pin 24 - SPI5_NSS (PF6) |
Pin 4 - SPI4_MOSI (PE14) | Pin 19 - SPI5_MOSI (PF9) |
Pin 5 - SPI4_MISO (PE13) | Pin 21 - SPI5_MISO (PF8) |
Pin 6 - SPI4_SCK (PE12) | Pin 23 - SPI5_SCK (PF7) |
Now we can enter the following commands on the board to test the communication. In our FULL_DUPLEX configuration, we first prepare a message to send on our slave SPI device, then when the master will send its own one, both will send and receive messages from each other:
board$> spidev_test -D /dev/spidev1.0 -p slave-hello-to-master -v & board$> spidev_test -D /dev/spidev0.0 -p master-hello-to-slave -v output: TX | 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| TX | 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| 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|
4. How to configure the DT using STM32CubeMX[edit source]
The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.
The STM32CubeMX may not support all the properties described in the above DT bindings documentation paragraph. If so, the tool inserts user sections in the generated device tree. These sections can then be edited to add some properties and they are preserved from one generation to another. Refer to STM32CubeMX user manual for further information.
5. References[edit source]
Please refer to the following links for additional information:
- ↑ SPI internal peripheral
- ↑ Device tree
- ↑ 3.0 3.1 Documentation/devicetree/bindings/spi/spi-controller.yaml , Generic device tree bindings for SPI buses
- ↑ Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
- ↑ arch/arm/boot/dts/stm32mp131.dtsi
- ↑ arch/arm/boot/dts/stm32mp151.dtsi
- ↑ arch/arm64/boot/dts/st/stm32mp251.dtsi
- ↑ arch/arm/boot/dts/stm32mp157f-dk2.dts
- ↑ arch/arm/boot/dts/stm32mp15-pinctrl.dtsi