1. Article purpose[edit source]
The purpose of this article is to explain how to configure the MDF internal peripheral using the device tree mechanism, relying on the bindings documentation, that is the description of the required and optional device-tree properties.
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]
Linux® OS: STM32 MDF device tree bindings: Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml .
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 organization.
The 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/SoC level)[edit source]
The MDF node is located in the device tree file for the software components, supporting the peripheral and listed in the above DT bindings documentation paragraph.
The MDF node is declared in stm32mp251.dtsi[1].
- DT root node ('mdf') describes the MDF hardware block common parameters such as registers area, reset, clocks, power domain and pins.
- DT child nodes ('sitf0', 'sitf1', ...) describe each serial interface independently: compatible string, registers area, pins, ...
- DT child nodes ('filter0', 'filter1', ...) describe each filter path independently: compatible string, registers area, interrupts, DMAs, ...
mdf: mdf@404d0000 { compatible = "st,stm32mp25-mdf"; ... /* common resources in 'mdf' root node. */ sitf0: sitf@80 { compatible = "st,stm32mp25-sitf-mdf"; reg = <0x80 0x4>; ... /* private resources in serial interface 0 child node. */ }; filter0: filter@84 { compatible = "st,stm32mp25-mdf-dmic"; /* Compatible for audio driver */ reg = <0x84 0x70>; ... /* private resources in filter 0 child node. */ } };
3.2. DT configuration (board level)[edit source]
The objective of this chapter is to explain how to enable and configure the MDF DT nodes for a board. The peripheral configuration must be done in specific board device tree files (board dts file and pinctrl dtsi file).
3.2.1. Common resources for all MDF filters[edit source]
Configure the 'mdf1' DT root node:
- Enable the DT root node for the MDF, by setting status = "okay".
- Optionally configure the MDF as a clock provider (for example, to feed external MEMS microphones), as shown in MDF audio example.
&mdf1 { status = "okay"; };
3.2.2. Private resources for each MDF serial interface[edit source]
Configure the sitf(s) DT child node(s):
- Enable the SITF child node for the MDF, by setting status = "okay".
- Configure the pin for input bitstream, via pinctrl, by setting pinctrl-0, pinctrl-1 and pinctrl-names. Also used to configure a pin for optional input clock.
- Configure serial interface protocol, by setting st,sitf-mode property.
- Optionally configure the serial interface as a clock consumer, as shown in MDF audio example.
&mdf1 { ... sitf6: sitf@380 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&mdf_sdi6_pins_a>; pinctrl-1 = <&mdf_sdi6_sleep_pins_a>; st,sitf-mode = "spi"; status = "okay"; }; };
3.2.3. Private resources for each MDF filter[edit source]
Configure the filter(s) DT child node(s):
- Enable the filter child node for the MDF, by setting status = "okay".
- Configure the input bitstream serial interface source, by setting st,sitf property.
- Configure CIC filter order, by setting st,cic-mode property.
- Optionally configure more filter parameters according to DT bindings documentation.
- Optionally configure more filter parameters according to DT bindings documentation.
&mdf1 {
...
filter0: filter@84 {
st,cic-mode = <5>;
st,sitf = <&sitf6 0>; /* Parameter sets the clock active edge for SPI modes. 0/1 for rising/falling edge*/
status = "okay";
};
};
3.2.4. Additional configuration for MDF audio[edit source]
If the MDF peripheral is used for audio capture, then additional child nodes must be added for audio soundcard configuration.
3.3. DT configuration examples[edit source]
3.3.1. MDF audio example[edit source]
The following example demonstrates how to capture data from two digital microphones and asynchronously retrieve the data on two ALSA audio devices. The MDF provides a clock on the CCK0 output to the two digital microphones. The CCK0 frequency is set to 1536 kHz, which is an effective compromise to support 8, 16, 32, and 48 kHz audio sampling rates, as it is both a power of 2 and a multiple of 3 (1536 equal 3 x 2^9). The signals from the two microphones are multiplexed onto a single data line connected to the serial interface 6 (alternatively, two independent data lines connected to two serial interfaces may be used). This example can serve as a foundation for subsequent audio examples.
&mdf1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&mdf_cck0_pins_a>; /* Configure output pin for CCK0 clock */ pinctrl-1 = <&mdf_cck0_sleep_pins_a>; #clock-cells = <1>; /* Set MDF as clock provider */ clock-output-names = "cck0"; /* Enable CCK0 output clock to feed the digital microphones */ clock-frequency = <1536000>; /* Set CCK0 output clock to 1536 kHz. */ status = "okay"; sitf6: sitf@380 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&mdf_sdi6_pins_a>; pinctrl-1 = <&mdf_sdi6_sleep_pins_a>; st,sitf-mode = "spi"; /* Set SPI protocol on serial interface 6 */ clocks = <&mdf1 0>; /* Set CCK0 as input clock for serial interface 6 */ status = "okay"; }; filter0: filter@84 { compatible = "st,stm32mp25-mdf-dmic"; st,cic-mode = <4>; /* Set CIC filter sync 4 mode */ st,sitf = <&sitf6 0>; /* Feed filter0 with input data from serial interface 6 on clock rising edge */ st,hpf-filter-cutoff-bp = <625>; status = "okay"; asoc_pdm0: mdf-dai { compatible = "st,stm32mp25-mdf-dai"; #sound-dai-cells = <0>; io-channels = <&filter0 0>; power-domains = <&RET_PD>; status = "okay"; mdf1_port0: port { mdf_endpoint0: endpoint { remote-endpoint = <&dmic0_endpoint>; }; }; }; filter1: filter@104 { compatible = "st,stm32mp25-mdf-dmic"; st,cic-mode = <4>; st,sitf = <&sitf6 1>; /* Feed filter1 with input data from serial interface 6 on clock falling edge */ st,hpf-filter-cutoff-bp = <625>; status = "okay"; asoc_pdm1: mdf-dai { compatible = "st,stm32mp25-mdf-dai"; #sound-dai-cells = <0>; io-channels = <&filter1 0>; power-domains = <&RET_PD>; status = "okay"; mdf1_port1: port { mdf_endpoint1: endpoint { remote-endpoint = <&dmic1_endpoint>; }; }; }; };
3.3.2. MDF audio interleaved channels configuration example[edit source]
This example shows how to configure the MDF to capture data from two digital microphones, and retrieve the data synchronously on a single ALSA audio device. The channel data are interleaved.
Information |
Only the update of the MDF audio example is described and highlighted in this chapter. |
Information |
This example can be expanded to capture samples from N microphones, but with the condition that the first filter must be filter0 and the subsequent filters must have consecutive indexes up to N-1. |
&mdf1 { st,interleave = <&filter0 &filter1>; /* Configure filter0 and filter1 as interleaved */ ... filter0: filter@84 { ... asoc_pdm0: mdf-dai { io-channels = <&filter0 0>; /* Filter0 provides interleaved stereo data to the ALSA audio device */ mdf1_port0: port {}; }; }; filter1: filter@104 { st,sitf = <&sitf6 1>; /* Specify data source and inherit other configurations from filter0 */ }; }; dmic0: dmic-0 { num-channels = <2>; /* Stereo dmic codec */ ... };
3.3.3. MDF audio synchronous channels configuration example[edit source]
This example shows how to configure the MDF to capture data from two digital microphones, and retrieve the data synchronously on two ALSA audio devices. The typical use is to launch filter3 first, waiting from acquisition on filter2 to start.
Information |
Only the update of the MDF audio example is described and highlighted in this chapter. |
Information |
This example can be expanded to capture samples from N microphones. Any filter can be set as the synchronization provider and any other filters may be synchronized to it. |
&mdf1 {
...
filter0: filter@84 {
...
asoc_pdm0: mdf-dai {
io-channels = <&filter0 0>;
mdf1_port0: port {};
};
};
filter1: filter@104 {
st,sync = <&filter0>; /* Synchronize filter1 with filter0 */
asoc_pdm1: mdf-dai {
io-channels = <&filter1 0>;
mdf1_port1: port {};
};
};
3.3.4. MDF IIO example[edit source]
This example demonstrates how to configure the MDF to capture data from a Sigma-Delta modulator ADC and retrieve the data on two IIO devices. In this example, it is assumed that the MDF provides a clock to the Sigma-Delta modulator and the serial interface via the CCK0 output. However, this clock can also be provided by another system clock.
&mdf1: mdf@504d0000 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&mdf_cck0_pins_a>; /* Configure output pin for CCK0 clock */ pinctrl-1 = <&mdf_cck0_sleep_pins_a>; #clock-cells = <1>; /* Set MDF as a clock provider */ clock-output-names = "cck0"; clock-frequency = <1024000>; /* Set CCK0 output clock to 1024 kHz */ status = "okay"; sitf6: sitf@380 { compatible = "st,stm32mp25-sitf-mdf"; reg = <0x380 0x4>; st,sitf-mode = "spi"; /* Configure the serial interface in SPI mode. */ clocks = <&mdf1 0>; /* Set CCK0 as input clock for serial interface 6 */ status = "okay"; }; filter0: filter@84 { compatible = "st,stm32mp25-mdf-adc"; st,cic-mode = <2>; st,sitf = <&sitf6 0>; #address-cells = <1>; #size-cells = <0>; status = "okay"; channel@0 { reg = <0>; }; }; filter1: filter@104 { compatible = "st,stm32mp25-mdf-adc"; st,cic-mode = <2>; st,sitf = <&sitf6 1>; #address-cells = <1>; #size-cells = <0>; status = "okay"; channel@1 { reg = <1>; }; }; };
3.3.5. MDF IIO scan mode example[edit source]
This example demonstrates how to configure the MDF to capture data from a Sigma Delta modulator ADC, and retrieve the data from one or several channels on a single IIO device.
Information |
Only the update of the MDF IIO example is described and highlighted in this chapter. |
&mdf1: mdf@504d0000 { st,interleave = <&filter0 &filter1>; /* Configure filter0 and filter1 as interleaved */ ... sitf6: sitf@380 { ... }; filter0: filter@84 { compatible = "st,stm32mp25-mdf-adc"; st,cic-mode = <2>; st,sitf = <&sitf6 0>; #address-cells = <1>; #size-cells = <0>; channel@0 { reg = <0>; /* Channel0 connected to serial interface associated to filter0 */ }; channel@1 { reg = <1>; /* Channel1 connected to serial interface associated to filter1 */ }; }; filter1: filter@104 { compatible = "st,stm32mp25-mdf-adc"; st,cic-mode = <2>; st,sitf = <&sitf6 1>; }; };
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.
STM32CubeMX may not support all the properties described in DT binding files listed 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]
Refer to the following links for additional information: