* [PATCH 0/3] iio: adc: stm32: add mdf support for stm32mp2
@ 2026-10-01 14:56 Olivier Moysan
2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan
` (2 more replies)
0 siblings, 3 replies; 31+ messages in thread
From: Olivier Moysan @ 2026-10-01 14:56 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin,
Alexandre Torgue, Olivier Moysan, Arnaud Pouliquen, Liam Girdwood,
Mark Brown, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
Sumit Semwal, Christian König
Cc: linux-iio, devicetree, linux-stm32, linux-arm-kernel,
linux-kernel, linux-sound, linux-media, dri-devel, linaro-mm-sig
This series adds support for the STM32 Multi-function Digital Filter (MDF)
found on STM32MP2 SoCs. MDF filters bitstreams from external sigma-delta
modulators and PDM microphones into samples for IIO and ASoC consumers.
The first patch documents the MDF core, serial interfaces, filters and
their connections in the devicetree binding.
The second patch adds the core, serial interface and filter drivers.
It supports IIO voltage channels for external sigma-delta modulators,
with direct reads or DMA buffering, and PDM microphone capture through
a cyclic DMA buffer. It also provides CIC filter configuration,
synchronization and filter interleaving.
The lastest patches add an ASoC DAI for PDM microphone capture.
Olivier Moysan (3):
dt-bindings: iio: adc: add bindings for stm32 mdf filter
iio: adc: add stm32 mdf support
ASoC: stm32: add mdf dai support
.../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 +++
drivers/iio/adc/Kconfig | 27 +
drivers/iio/adc/Makefile | 3 +
drivers/iio/adc/stm32-mdf-adc.c | 2078 +++++++++++++++++
drivers/iio/adc/stm32-mdf-core.c | 857 +++++++
drivers/iio/adc/stm32-mdf-serial.c | 309 +++
drivers/iio/adc/stm32-mdf.h | 312 +++
include/linux/iio/adc/stm32-mdf-adc.h | 19 +
sound/soc/stm/Kconfig | 15 +
sound/soc/stm/Makefile | 3 +
sound/soc/stm/stm32_amdf.c | 376 +++
11 files changed, 4382 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml
create mode 100644 drivers/iio/adc/stm32-mdf-adc.c
create mode 100644 drivers/iio/adc/stm32-mdf-core.c
create mode 100644 drivers/iio/adc/stm32-mdf-serial.c
create mode 100644 drivers/iio/adc/stm32-mdf.h
create mode 100644 include/linux/iio/adc/stm32-mdf-adc.h
create mode 100644 sound/soc/stm/stm32_amdf.c
base-commit: 9ee8306121495d2a25aa5d1bfd519f2748786b83
--
2.43.0
^ permalink raw reply [flat|nested] 31+ messages in thread* [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 14:56 [PATCH 0/3] iio: adc: stm32: add mdf support for stm32mp2 Olivier Moysan @ 2026-10-01 14:56 ` Olivier Moysan 2026-10-01 16:25 ` Rob Herring (Arm) ` (3 more replies) 2026-10-01 14:56 ` [PATCH 3/3] ASoC: stm32: add mdf dai support Olivier Moysan [not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com> 2 siblings, 4 replies; 31+ messages in thread From: Olivier Moysan @ 2026-10-01 14:56 UTC (permalink / raw) To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, Olivier Moysan Cc: linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Add bindings that describes STM32 MDF settings to support digital filtering for Pulse Density Modulation (PDM) microphones and analog sigma delta modulators. Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> --- .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml new file mode 100644 index 000000000000..f2fbc3e150e8 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml @@ -0,0 +1,383 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC + +maintainers: + - Olivier Moysan <olivier.moysan@foss.st.com> + +description: | + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to + interface external sigma delta modulators to STM32 micro controllers. + +properties: + compatible: + enum: + - st,stm32mp25-mdf + - st,stm32mp23-mdf + + reg: + minItems: 1 + maxItems: 2 + + clocks: + maxItems: 1 + + clock-names: + description: Internal clock used for MDF digital processing. + items: + - const: ker_ck + + "#clock-cells": + enum: [0, 1] + + clock-output-names: + description: | + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, + but can be gated independently to save power. + minItems: 1 + maxItems: 2 + oneOf: + - items: + - const: cck0 + - items: + - const: cck1 + - items: + - const: cck0 + - const: cck1 + + clock-frequency: + description: | + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. + The frequency must be a multiple of the "ker_ck" clock frequency. + maximum: 25000000 + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + ranges: true + + clock-ranges: true + + resets: + maxItems: 1 + + reset-names: + items: + - const: mdf + + access-controllers: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + Phandle to the rifsc device to check access right. + + power-domains: + maxItems: 1 + + st,interleave: + description: | + List of phandles of interleaved filters. The indexes of interleaved filters must be + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters + are muxed in a single channel and retrieved through the device associated to the filter 0. + The filters 1..N have to be enabled, but inherit their configuration from filter 0. + $ref: /schemas/types.yaml#/definitions/phandle-array + +required: + - compatible + - reg + - ranges + - clocks + - clock-names + - clock-ranges + - "#address-cells" + - "#size-cells" + +additionalProperties: false + +patternProperties: + "^sitf@[0-9]+$": + type: object + description: Serial interface child node + + properties: + compatible: + enum: + - st,stm32mp25-sitf-mdf + + reg: + description: Specify the SITF serial interface instance + maxItems: 1 + + clocks: + description: | + Serial interface clock (optional depending on interface mode) + maxItems: 1 + + st,sitf-mode: + description: | + Select serial interface protocol + - spi: SPI mode + - lf_spi: low frequency SPI mode for low power applications + $ref: /schemas/types.yaml#/definitions/string + enum: + - spi + - lf_spi + + required: + - reg + - st,sitf-mode + + additionalProperties: false + + "^filter@[0-9]+$": + type: object + description: Digital filter path child node + + properties: + compatible: + enum: + - st,stm32mp25-mdf-dmic + - st,stm32mp25-mdf-adc + + reg: + description: Specify the MDF filter instance + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 1 + description: Internal clock used for MDF digital processing and control blocks. + + clock-names: + items: + - const: ker_ck + + dmas: + maxItems: 1 + + dma-names: + items: + - const: rx + + "#io-channel-cells": + const: 1 + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + st,cic-mode: + description: | + Cascaded-integrator-comb (CIC) filter configuration + - 0: MCIC & ACIC filters in FastSinc mode + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 + This property is mandatory for filter 0 or filters not used in interleave mode. + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 5 + + st,delay: + description: Filter delay in samples + $ref: /schemas/types.yaml#/definitions/uint32 + maximum: 127 + + st,rs-filter-bypass: + description: Bypass RSFLT reshaping filter. + $ref: /schemas/types.yaml#/definitions/flag + + st,hpf-filter-cutoff-bp: + description: | + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. + If this property is not defined the HPF is disabled. + enum: [625, 1250, 2500, 9500] + + st,sync: + description: + Synchronize to another filter. + Must contain the phandle of the filter providing the synchronization. + allOf: + - $ref: /schemas/types.yaml#/definitions/phandle-array + - maxItems: 1 + + st,sitf: + $ref: /schemas/types.yaml#/definitions/phandle-array + items: + - items: + - description: Phandle of the serial interface connected to the digital filter + - description: | + The phandle's argument selects the bitstream on the falling or rising edge + of the serial interface clock: + - 0: rising edge + - 1: falling edge + enum: [0, 1] + default: 0 + description: + Should be phandle/bitstream pair. + + required: + - compatible + - reg + - interrupts + - dmas + - dma-names + - "#io-channel-cells" + - "#address-cells" + - "#size-cells" + - st,sitf + + unevaluatedProperties: false + + patternProperties: + "^channel@([0-7])$": + type: object + $ref: adc.yaml + description: Represents the external channel which is connected to the MDF. + + properties: + reg: + maximum: 7 + + io-backends: + description: + Used to pipe external sigma delta modulator or internal ADC backend to MDF + channel. + maxItems: 1 + + required: + - reg + + unevaluatedProperties: false + + allOf: + - if: + properties: + compatible: + contains: + const: st,stm32mp25-mdf-adc + + then: + patternProperties: + "^channel@[0-7]$": + required: + - io-backends + + - if: + properties: + compatible: + contains: + const: st,stm32mp25-mdf-dmic + + then: + patternProperties: + "^mdf-dai+$": + type: object + description: child node + + properties: + compatible: + enum: + - st,stm32mp25-mdf-dai + + "#sound-dai-cells": + const: 0 + + io-channels: + description: + From common IIO binding. Used to pipe external sigma delta + modulator or internal ADC output to MDF channel. + + power-domains: + maxItems: 1 + + port: + $ref: /schemas/sound/audio-graph-port.yaml# + unevaluatedProperties: false + + required: + - compatible + - "#sound-dai-cells" + - io-channels + + additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/st,stm32mp25-rcc.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + mdf1: mdf@504d0000 { + compatible = "st,stm32mp25-mdf"; + ranges = <0 0x504d0000 0x1000>; + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&rcc CK_KER_MDF1>; + clock-names = "ker_ck"; + clock-ranges; + #clock-cells = <1>; + clock-output-names = "cck0", "cck1"; + clock-frequency = <2048000>; + + sitf5: sitf@300 { + compatible = "st,stm32mp25-sitf-mdf"; + reg = <0x300 0x4>; + st,sitf-mode = "spi"; + clocks = <&mdf1 0>; + }; + + filter0: filter@84 { + compatible = "st,stm32mp25-mdf-dmic"; + reg = <0x84 0x70>; + #io-channel-cells = <1>; + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&hpdma 63 0x63 0x12 0>; + dma-names = "rx"; + st,cic-mode = <5>; + st,sitf = <&sitf5 0>; + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + }; + + asoc_pdm0: mdf-dai { + compatible = "st,stm32mp25-mdf-dai"; + #sound-dai-cells = <0>; + io-channels = <&filter0 0>; + }; + }; + + filter1: filter@104 { + compatible = "st,stm32mp25-mdf-adc"; + reg = <0x104 0x70>; + #io-channel-cells = <1>; + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&hpdma 64 0x63 0x12 0>; + dma-names = "rx"; + st,cic-mode = <2>; + st,sitf = <&sitf5 1>; + #address-cells = <1>; + #size-cells = <0>; + + channel@1 { + reg = <1>; + settling-time-us = <1000>; + io-backends = <&sd_adc1>; + }; + }; + }; + +... -- 2.43.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan @ 2026-10-01 16:25 ` Rob Herring (Arm) 2026-10-01 18:32 ` Conor Dooley ` (2 subsequent siblings) 3 siblings, 0 replies; 31+ messages in thread From: Rob Herring (Arm) @ 2026-10-01 16:25 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, Conor Dooley, linux-kernel, Krzysztof Kozlowski, Andy Shevchenko, David Lechner, Maxime Coquelin, devicetree, linux-stm32, Nuno Sá, Alexandre Torgue, linux-arm-kernel, linux-iio On Thu, 01 Oct 2026 16:56:45 +0200, Olivier Moysan wrote: > Add bindings that describes STM32 MDF settings to support > digital filtering for Pulse Density Modulation (PDM) microphones > and analog sigma delta modulators. > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > --- > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > 1 file changed, 383 insertions(+) > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: ./Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml:363: example 0 [redundant-whitespace] extra whitespace before { doc reference errors (make refcheckdocs): See https://patchwork.kernel.org/project/devicetree/patch/20261001145702.2628429-2-olivier.moysan@foss.st.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan 2026-10-01 16:25 ` Rob Herring (Arm) @ 2026-10-01 18:32 ` Conor Dooley 2026-10-07 9:01 ` Olivier MOYSAN 2026-10-02 9:22 ` Krzysztof Kozlowski 2026-10-02 9:34 ` Krzysztof Kozlowski 3 siblings, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-01 18:32 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 12687 bytes --] On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > Add bindings that describes STM32 MDF settings to support > digital filtering for Pulse Density Modulation (PDM) microphones > and analog sigma delta modulators. > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > --- > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > 1 file changed, 383 insertions(+) > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > new file mode 100644 > index 000000000000..f2fbc3e150e8 > --- /dev/null > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > @@ -0,0 +1,383 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > + > +maintainers: > + - Olivier Moysan <olivier.moysan@foss.st.com> > + > +description: | > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > + interface external sigma delta modulators to STM32 micro controllers. > + > +properties: > + compatible: > + enum: > + - st,stm32mp25-mdf > + - st,stm32mp23-mdf > + > + reg: > + minItems: 1 > + maxItems: 2 This needs an items list here. The size of the regions seems like crap to begin with... > + > + clocks: > + maxItems: 1 > + > + clock-names: > + description: Internal clock used for MDF digital processing. > + items: > + - const: ker_ck This is pointless when you only have one. > + > + "#clock-cells": > + enum: [0, 1] Why is this not fixed? Also why are parts of your own device consuming the clocks? > + > + clock-output-names: > + description: | > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > + but can be gated independently to save power. > + minItems: 1 > + maxItems: 2 > + oneOf: > + - items: > + - const: cck0 > + - items: > + - const: cck1 > + - items: > + - const: cck0 > + - const: cck1 > + > + clock-frequency: > + description: | > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > + The frequency must be a multiple of the "ker_ck" clock frequency. > + maximum: 25000000 Should not be needed, the consumers request what they need. > + > + "#address-cells": > + const: 1 > + > + "#size-cells": > + const: 1 > + > + ranges: true > + > + clock-ranges: true > + > + resets: > + maxItems: 1 > + > + reset-names: > + items: > + - const: mdf > + > + access-controllers: > + $ref: /schemas/types.yaml#/definitions/phandle-array > + description: | > + Phandle to the rifsc device to check access right. > + > + power-domains: > + maxItems: 1 > + > + st,interleave: > + description: | > + List of phandles of interleaved filters. The indexes of interleaved filters must be > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > + are muxed in a single channel and retrieved through the device associated to the filter 0. > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > + $ref: /schemas/types.yaml#/definitions/phandle-array No idea what these even are, but this is probably not the right way to represent the relationship between devices. They're apparently ADCs, but this is also an ADC so I'm not sure what's going on here at all. > + > +required: > + - compatible > + - reg > + - ranges > + - clocks > + - clock-names > + - clock-ranges > + - "#address-cells" > + - "#size-cells" > + > +additionalProperties: false > + > +patternProperties: > + "^sitf@[0-9]+$": > + type: object > + description: Serial interface child node Why is this a child node at all? Probably not worth reviewing more without a link to the docs for this device so I can figure out what on earth is going on! Thanks, Conor. > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-sitf-mdf > + > + reg: > + description: Specify the SITF serial interface instance > + maxItems: 1 > + > + clocks: > + description: | > + Serial interface clock (optional depending on interface mode) > + maxItems: 1 > + > + st,sitf-mode: > + description: | > + Select serial interface protocol > + - spi: SPI mode > + - lf_spi: low frequency SPI mode for low power applications > + $ref: /schemas/types.yaml#/definitions/string > + enum: > + - spi > + - lf_spi > + > + required: > + - reg > + - st,sitf-mode > + > + additionalProperties: false > + > + "^filter@[0-9]+$": > + type: object > + description: Digital filter path child node > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-mdf-dmic > + - st,stm32mp25-mdf-adc > + > + reg: > + description: Specify the MDF filter instance > + maxItems: 1 > + > + interrupts: > + maxItems: 1 > + > + clocks: > + minItems: 1 > + description: Internal clock used for MDF digital processing and control blocks. > + > + clock-names: > + items: > + - const: ker_ck > + > + dmas: > + maxItems: 1 > + > + dma-names: > + items: > + - const: rx > + > + "#io-channel-cells": > + const: 1 > + > + '#address-cells': > + const: 1 > + > + '#size-cells': > + const: 0 > + > + st,cic-mode: > + description: | > + Cascaded-integrator-comb (CIC) filter configuration > + - 0: MCIC & ACIC filters in FastSinc mode > + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 > + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 > + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 > + This property is mandatory for filter 0 or filters not used in interleave mode. > + $ref: /schemas/types.yaml#/definitions/uint32 > + minimum: 0 > + maximum: 5 > + > + st,delay: > + description: Filter delay in samples > + $ref: /schemas/types.yaml#/definitions/uint32 > + maximum: 127 > + > + st,rs-filter-bypass: > + description: Bypass RSFLT reshaping filter. > + $ref: /schemas/types.yaml#/definitions/flag > + > + st,hpf-filter-cutoff-bp: > + description: | > + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. > + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. > + If this property is not defined the HPF is disabled. > + enum: [625, 1250, 2500, 9500] > + > + st,sync: > + description: > + Synchronize to another filter. > + Must contain the phandle of the filter providing the synchronization. > + allOf: > + - $ref: /schemas/types.yaml#/definitions/phandle-array > + - maxItems: 1 > + > + st,sitf: > + $ref: /schemas/types.yaml#/definitions/phandle-array > + items: > + - items: > + - description: Phandle of the serial interface connected to the digital filter > + - description: | > + The phandle's argument selects the bitstream on the falling or rising edge > + of the serial interface clock: > + - 0: rising edge > + - 1: falling edge > + enum: [0, 1] > + default: 0 > + description: > + Should be phandle/bitstream pair. > + > + required: > + - compatible > + - reg > + - interrupts > + - dmas > + - dma-names > + - "#io-channel-cells" > + - "#address-cells" > + - "#size-cells" > + - st,sitf > + > + unevaluatedProperties: false > + > + patternProperties: > + "^channel@([0-7])$": > + type: object > + $ref: adc.yaml > + description: Represents the external channel which is connected to the MDF. > + > + properties: > + reg: > + maximum: 7 > + > + io-backends: > + description: > + Used to pipe external sigma delta modulator or internal ADC backend to MDF > + channel. > + maxItems: 1 > + > + required: > + - reg > + > + unevaluatedProperties: false > + > + allOf: > + - if: > + properties: > + compatible: > + contains: > + const: st,stm32mp25-mdf-adc > + > + then: > + patternProperties: > + "^channel@[0-7]$": > + required: > + - io-backends > + > + - if: > + properties: > + compatible: > + contains: > + const: st,stm32mp25-mdf-dmic > + > + then: > + patternProperties: > + "^mdf-dai+$": > + type: object > + description: child node > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-mdf-dai > + > + "#sound-dai-cells": > + const: 0 > + > + io-channels: > + description: > + From common IIO binding. Used to pipe external sigma delta > + modulator or internal ADC output to MDF channel. > + > + power-domains: > + maxItems: 1 > + > + port: > + $ref: /schemas/sound/audio-graph-port.yaml# > + unevaluatedProperties: false > + > + required: > + - compatible > + - "#sound-dai-cells" > + - io-channels > + > + additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/st,stm32mp25-rcc.h> > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + mdf1: mdf@504d0000 { > + compatible = "st,stm32mp25-mdf"; > + ranges = <0 0x504d0000 0x1000>; > + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; > + #address-cells = <1>; > + #size-cells = <1>; > + clocks = <&rcc CK_KER_MDF1>; > + clock-names = "ker_ck"; > + clock-ranges; > + #clock-cells = <1>; > + clock-output-names = "cck0", "cck1"; > + clock-frequency = <2048000>; > + > + sitf5: sitf@300 { > + compatible = "st,stm32mp25-sitf-mdf"; > + reg = <0x300 0x4>; > + st,sitf-mode = "spi"; > + clocks = <&mdf1 0>; > + }; > + > + filter0: filter@84 { > + compatible = "st,stm32mp25-mdf-dmic"; > + reg = <0x84 0x70>; > + #io-channel-cells = <1>; > + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; > + dmas = <&hpdma 63 0x63 0x12 0>; > + dma-names = "rx"; > + st,cic-mode = <5>; > + st,sitf = <&sitf5 0>; > + #address-cells = <1>; > + #size-cells = <0>; > + > + channel@0 { > + reg = <0>; > + }; > + > + asoc_pdm0: mdf-dai { > + compatible = "st,stm32mp25-mdf-dai"; > + #sound-dai-cells = <0>; > + io-channels = <&filter0 0>; > + }; > + }; > + > + filter1: filter@104 { > + compatible = "st,stm32mp25-mdf-adc"; > + reg = <0x104 0x70>; > + #io-channel-cells = <1>; > + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; > + dmas = <&hpdma 64 0x63 0x12 0>; > + dma-names = "rx"; > + st,cic-mode = <2>; > + st,sitf = <&sitf5 1>; > + #address-cells = <1>; > + #size-cells = <0>; > + > + channel@1 { > + reg = <1>; > + settling-time-us = <1000>; > + io-backends = <&sd_adc1>; > + }; > + }; > + }; > + > +... > -- > 2.43.0 > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 18:32 ` Conor Dooley @ 2026-10-07 9:01 ` Olivier MOYSAN 2026-10-07 13:47 ` Rob Herring 2026-10-08 10:11 ` Conor Dooley 0 siblings, 2 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-07 9:01 UTC (permalink / raw) To: Conor Dooley Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Conor, Thanks for the review On 10/1/26 20:32, Conor Dooley wrote: > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >> Add bindings that describes STM32 MDF settings to support >> digital filtering for Pulse Density Modulation (PDM) microphones >> and analog sigma delta modulators. >> >> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >> --- >> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >> 1 file changed, 383 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> >> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> new file mode 100644 >> index 000000000000..f2fbc3e150e8 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> @@ -0,0 +1,383 @@ >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >> + >> +maintainers: >> + - Olivier Moysan <olivier.moysan@foss.st.com> >> + >> +description: | >> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >> + interface external sigma delta modulators to STM32 micro controllers. >> + >> +properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf >> + - st,stm32mp23-mdf >> + >> + reg: >> + minItems: 1 >> + maxItems: 2 > > This needs an items list here. The size of the regions seems like crap > to begin with... > >> + >> + clocks: >> + maxItems: 1 >> + >> + clock-names: >> + description: Internal clock used for MDF digital processing. >> + items: >> + - const: ker_ck > > This is pointless when you only have one. > I agree that it could be dropped. However, it is useful for using devm_regmap_init_mmio_clk. >> + >> + "#clock-cells": >> + enum: [0, 1] > > Why is this not fixed? Also why are parts of your own device consuming > the clocks? > >> + >> + clock-output-names: >> + description: | >> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >> + but can be gated independently to save power. >> + minItems: 1 >> + maxItems: 2 >> + oneOf: >> + - items: >> + - const: cck0 >> + - items: >> + - const: cck1 >> + - items: >> + - const: cck0 >> + - const: cck1 >> + >> + clock-frequency: >> + description: | >> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >> + The frequency must be a multiple of the "ker_ck" clock frequency. >> + maximum: 25000000 > > Should not be needed, the consumers request what they need. > The CCKx clock frequency depends on the maximum rate supported by the sigma delta converters (for instance a digital mic) and the expected decimation ratio on the bitstream. Typically this determines the frequency on the SPI bus. This rate is defined statically and shared by the CCKx clocks. So IMHO, as this rate is unique, it can look strange to let the consumer define it. Moreover, it seems to me that clock-frequency is already used to configure the frequency of a provider in some other bindings. For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml So, it's not clear for me, what is the restriction on clock-frequency property. >> + >> + ranges: true >> + >> + clock-ranges: true >> + >> + resets: >> + maxItems: 1 >> + >> + reset-names: >> + items: >> + - const: mdf >> + >> + access-controllers: >> + $ref: /schemas/types.yaml#/definitions/phandle-array >> + description: | >> + Phandle to the rifsc device to check access right. >> + >> + power-domains: >> + maxItems: 1 >> + >> + st,interleave: >> + description: | >> + List of phandles of interleaved filters. The indexes of interleaved filters must be >> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >> + are muxed in a single channel and retrieved through the device associated to the filter 0. >> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >> + $ref: /schemas/types.yaml#/definitions/phandle-array > > No idea what these even are, but this is probably not the right way to > represent the relationship between devices. They're apparently ADCs, but > this is also an ADC so I'm not sure what's going on here at all. > >> + >> +required: >> + - compatible >> + - reg >> + - ranges >> + - clocks >> + - clock-names >> + - clock-ranges >> + - "#address-cells" >> + - "#size-cells" >> + >> +additionalProperties: false >> + >> +patternProperties: >> + "^sitf@[0-9]+$": >> + type: object >> + description: Serial interface child node > > Why is this a child node at all? > > Probably not worth reviewing more without a link to the docs for this > device so I can figure out what on earth is going on! > The MDF is a digital filter for sigma-delta bitstreams, rather than the analog-to-digital converter itself. Here is the link to STM32MP25 reference manuel https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf Chapter 45: Multi-function digital filter (MDF) On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital filters (DFLT) which can be connected through a multiplexer. Below is a schematic view of typical applications targeted by this peripheral Audio use case: mdf +-------------------------------------+ +------+ | +------+ +------+ +------+ | | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device +------+ | +------+ +------+ +------+ | +-------------------------------------+ For instance, in an audio use case the serial interface can be configured to provide the clock to the digital microphone (cck0, cck1 or both) at a common predefined rate, and to retrieve the PDM samples. The serial interface provides this samples to a digital filter, which delivers PCM samples on its output. Analog use case: mdf +-------------------------------------+ +--------+ | +------+ +------+ +------+ | | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device +--------+ | +------+ +------+ +------+ | +-------------------------------------+ Best regards Olivier > Thanks, > Conor. > >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-sitf-mdf >> + >> + reg: >> + description: Specify the SITF serial interface instance >> + maxItems: 1 >> + >> + clocks: >> + description: | >> + Serial interface clock (optional depending on interface mode) >> + maxItems: 1 >> + >> + st,sitf-mode: >> + description: | >> + Select serial interface protocol >> + - spi: SPI mode >> + - lf_spi: low frequency SPI mode for low power applications >> + $ref: /schemas/types.yaml#/definitions/string >> + enum: >> + - spi >> + - lf_spi >> + >> + required: >> + - reg >> + - st,sitf-mode >> + >> + additionalProperties: false >> + >> + "^filter@[0-9]+$": >> + type: object >> + description: Digital filter path child node >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf-dmic >> + - st,stm32mp25-mdf-adc >> + >> + reg: >> + description: Specify the MDF filter instance >> + maxItems: 1 >> + >> + interrupts: >> + maxItems: 1 >> + >> + clocks: >> + minItems: 1 >> + description: Internal clock used for MDF digital processing and control blocks. >> + >> + clock-names: >> + items: >> + - const: ker_ck >> + >> + dmas: >> + maxItems: 1 >> + >> + dma-names: >> + items: >> + - const: rx >> + >> + "#io-channel-cells": >> + const: 1 >> + >> + '#address-cells': >> + const: 1 >> + >> + '#size-cells': >> + const: 0 >> + >> + st,cic-mode: >> + description: | >> + Cascaded-integrator-comb (CIC) filter configuration >> + - 0: MCIC & ACIC filters in FastSinc mode >> + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 >> + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 >> + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 >> + This property is mandatory for filter 0 or filters not used in interleave mode. >> + $ref: /schemas/types.yaml#/definitions/uint32 >> + minimum: 0 >> + maximum: 5 >> + >> + st,delay: >> + description: Filter delay in samples >> + $ref: /schemas/types.yaml#/definitions/uint32 >> + maximum: 127 >> + >> + st,rs-filter-bypass: >> + description: Bypass RSFLT reshaping filter. >> + $ref: /schemas/types.yaml#/definitions/flag >> + >> + st,hpf-filter-cutoff-bp: >> + description: | >> + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. >> + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. >> + If this property is not defined the HPF is disabled. >> + enum: [625, 1250, 2500, 9500] >> + >> + st,sync: >> + description: >> + Synchronize to another filter. >> + Must contain the phandle of the filter providing the synchronization. >> + allOf: >> + - $ref: /schemas/types.yaml#/definitions/phandle-array >> + - maxItems: 1 >> + >> + st,sitf: >> + $ref: /schemas/types.yaml#/definitions/phandle-array >> + items: >> + - items: >> + - description: Phandle of the serial interface connected to the digital filter >> + - description: | >> + The phandle's argument selects the bitstream on the falling or rising edge >> + of the serial interface clock: >> + - 0: rising edge >> + - 1: falling edge >> + enum: [0, 1] >> + default: 0 >> + description: >> + Should be phandle/bitstream pair. >> + >> + required: >> + - compatible >> + - reg >> + - interrupts >> + - dmas >> + - dma-names >> + - "#io-channel-cells" >> + - "#address-cells" >> + - "#size-cells" >> + - st,sitf >> + >> + unevaluatedProperties: false >> + >> + patternProperties: >> + "^channel@([0-7])$": >> + type: object >> + $ref: adc.yaml >> + description: Represents the external channel which is connected to the MDF. >> + >> + properties: >> + reg: >> + maximum: 7 >> + >> + io-backends: >> + description: >> + Used to pipe external sigma delta modulator or internal ADC backend to MDF >> + channel. >> + maxItems: 1 >> + >> + required: >> + - reg >> + >> + unevaluatedProperties: false >> + >> + allOf: >> + - if: >> + properties: >> + compatible: >> + contains: >> + const: st,stm32mp25-mdf-adc >> + >> + then: >> + patternProperties: >> + "^channel@[0-7]$": >> + required: >> + - io-backends >> + >> + - if: >> + properties: >> + compatible: >> + contains: >> + const: st,stm32mp25-mdf-dmic >> + >> + then: >> + patternProperties: >> + "^mdf-dai+$": >> + type: object >> + description: child node >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf-dai >> + >> + "#sound-dai-cells": >> + const: 0 >> + >> + io-channels: >> + description: >> + From common IIO binding. Used to pipe external sigma delta >> + modulator or internal ADC output to MDF channel. >> + >> + power-domains: >> + maxItems: 1 >> + >> + port: >> + $ref: /schemas/sound/audio-graph-port.yaml# >> + unevaluatedProperties: false >> + >> + required: >> + - compatible >> + - "#sound-dai-cells" >> + - io-channels >> + >> + additionalProperties: false >> + >> +examples: >> + - | >> + #include <dt-bindings/clock/st,stm32mp25-rcc.h> >> + #include <dt-bindings/interrupt-controller/arm-gic.h> >> + mdf1: mdf@504d0000 { >> + compatible = "st,stm32mp25-mdf"; >> + ranges = <0 0x504d0000 0x1000>; >> + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; >> + #address-cells = <1>; >> + #size-cells = <1>; >> + clocks = <&rcc CK_KER_MDF1>; >> + clock-names = "ker_ck"; >> + clock-ranges; >> + #clock-cells = <1>; >> + clock-output-names = "cck0", "cck1"; >> + clock-frequency = <2048000>; >> + >> + sitf5: sitf@300 { >> + compatible = "st,stm32mp25-sitf-mdf"; >> + reg = <0x300 0x4>; >> + st,sitf-mode = "spi"; >> + clocks = <&mdf1 0>; >> + }; >> + >> + filter0: filter@84 { >> + compatible = "st,stm32mp25-mdf-dmic"; >> + reg = <0x84 0x70>; >> + #io-channel-cells = <1>; >> + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; >> + dmas = <&hpdma 63 0x63 0x12 0>; >> + dma-names = "rx"; >> + st,cic-mode = <5>; >> + st,sitf = <&sitf5 0>; >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + channel@0 { >> + reg = <0>; >> + }; >> + >> + asoc_pdm0: mdf-dai { >> + compatible = "st,stm32mp25-mdf-dai"; >> + #sound-dai-cells = <0>; >> + io-channels = <&filter0 0>; >> + }; >> + }; >> + >> + filter1: filter@104 { >> + compatible = "st,stm32mp25-mdf-adc"; >> + reg = <0x104 0x70>; >> + #io-channel-cells = <1>; >> + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; >> + dmas = <&hpdma 64 0x63 0x12 0>; >> + dma-names = "rx"; >> + st,cic-mode = <2>; >> + st,sitf = <&sitf5 1>; >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + channel@1 { >> + reg = <1>; >> + settling-time-us = <1000>; >> + io-backends = <&sd_adc1>; >> + }; >> + }; >> + }; >> + >> +... >> -- >> 2.43.0 >> ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-07 9:01 ` Olivier MOYSAN @ 2026-10-07 13:47 ` Rob Herring 2026-10-07 16:02 ` Olivier MOYSAN 2026-10-08 10:11 ` Conor Dooley 1 sibling, 1 reply; 31+ messages in thread From: Rob Herring @ 2026-10-07 13:47 UTC (permalink / raw) To: Olivier MOYSAN Cc: Conor Dooley, Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > Hi Conor, > > Thanks for the review > > On 10/1/26 20:32, Conor Dooley wrote: > > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > > > Add bindings that describes STM32 MDF settings to support > > > digital filtering for Pulse Density Modulation (PDM) microphones > > > and analog sigma delta modulators. > > > > > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > > > --- > > > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > > > 1 file changed, 383 insertions(+) > > > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > new file mode 100644 > > > index 000000000000..f2fbc3e150e8 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > @@ -0,0 +1,383 @@ > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > +%YAML 1.2 > > > +--- > > > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > + > > > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > > > + > > > +maintainers: > > > + - Olivier Moysan <olivier.moysan@foss.st.com> > > > + > > > +description: | > > > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > > > + interface external sigma delta modulators to STM32 micro controllers. > > > + > > > +properties: > > > + compatible: > > > + enum: > > > + - st,stm32mp25-mdf > > > + - st,stm32mp23-mdf > > > + > > > + reg: > > > + minItems: 1 > > > + maxItems: 2 > > > > This needs an items list here. The size of the regions seems like crap > > to begin with... > > > > > + > > > + clocks: > > > + maxItems: 1 > > > + > > > + clock-names: > > > + description: Internal clock used for MDF digital processing. > > > + items: > > > + - const: ker_ck > > > > This is pointless when you only have one. > > > > I agree that it could be dropped. However, it is useful for using > devm_regmap_init_mmio_clk. I don't know what that function is/does, but that's not justification for bindings. Maybe you need a helper that handles a single clock. Or that function could take a NULL string for single clock? > > > > + > > > + "#clock-cells": > > > + enum: [0, 1] > > > > Why is this not fixed? Also why are parts of your own device consuming > > the clocks? > > > > > + > > > + clock-output-names: > > > + description: | > > > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > > > + but can be gated independently to save power. > > > + minItems: 1 > > > + maxItems: 2 > > > + oneOf: > > > + - items: > > > + - const: cck0 > > > + - items: > > > + - const: cck1 > > > + - items: > > > + - const: cck0 > > > + - const: cck1 > > > + > > > + clock-frequency: > > > + description: | > > > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > > > + The frequency must be a multiple of the "ker_ck" clock frequency. > > > + maximum: 25000000 > > > > Should not be needed, the consumers request what they need. > > > > The CCKx clock frequency depends on the maximum rate supported by the sigma > delta converters (for instance a digital mic) and the expected decimation > ratio on the bitstream. Typically this determines the frequency on the SPI > bus. > This rate is defined statically and shared by the CCKx clocks. So IMHO, as > this rate is unique, it can look strange to let the consumer define it. > Moreover, it seems to me that clock-frequency is already used to configure > the frequency of a provider in some other bindings. > For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml > So, it's not clear for me, what is the restriction on clock-frequency > property. > > > + > > > + ranges: true > > > + > > > + clock-ranges: true > > > + > > > + resets: > > > + maxItems: 1 > > > + > > > + reset-names: > > > + items: > > > + - const: mdf > > > + > > > + access-controllers: > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > + description: | > > > + Phandle to the rifsc device to check access right. > > > + > > > + power-domains: > > > + maxItems: 1 > > > + > > > + st,interleave: > > > + description: | > > > + List of phandles of interleaved filters. The indexes of interleaved filters must be > > > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > > > + are muxed in a single channel and retrieved through the device associated to the filter 0. > > > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > No idea what these even are, but this is probably not the right way to > > represent the relationship between devices. They're apparently ADCs, but > > this is also an ADC so I'm not sure what's going on here at all. I don't under it either, but regardless phandle-array needs constraints on the items. It's really a matrix with array of phandle+args arrays. Rob ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-07 13:47 ` Rob Herring @ 2026-10-07 16:02 ` Olivier MOYSAN 0 siblings, 0 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-07 16:02 UTC (permalink / raw) To: Rob Herring Cc: Conor Dooley, Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Rob, On 10/7/26 15:47, Rob Herring wrote: > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >> Hi Conor, >> >> Thanks for the review >> >> On 10/1/26 20:32, Conor Dooley wrote: >>> On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >>>> Add bindings that describes STM32 MDF settings to support >>>> digital filtering for Pulse Density Modulation (PDM) microphones >>>> and analog sigma delta modulators. >>>> >>>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >>>> --- >>>> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >>>> 1 file changed, 383 insertions(+) >>>> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> >>>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> new file mode 100644 >>>> index 000000000000..f2fbc3e150e8 >>>> --- /dev/null >>>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> @@ -0,0 +1,383 @@ >>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>>> +%YAML 1.2 >>>> +--- >>>> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >>>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>>> + >>>> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >>>> + >>>> +maintainers: >>>> + - Olivier Moysan <olivier.moysan@foss.st.com> >>>> + >>>> +description: | >>>> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >>>> + interface external sigma delta modulators to STM32 micro controllers. >>>> + >>>> +properties: >>>> + compatible: >>>> + enum: >>>> + - st,stm32mp25-mdf >>>> + - st,stm32mp23-mdf >>>> + >>>> + reg: >>>> + minItems: 1 >>>> + maxItems: 2 >>> >>> This needs an items list here. The size of the regions seems like crap >>> to begin with... >>> >>>> + >>>> + clocks: >>>> + maxItems: 1 >>>> + >>>> + clock-names: >>>> + description: Internal clock used for MDF digital processing. >>>> + items: >>>> + - const: ker_ck >>> >>> This is pointless when you only have one. >>> >> >> I agree that it could be dropped. However, it is useful for using >> devm_regmap_init_mmio_clk. > > I don't know what that function is/does, but that's not justification > for bindings. Maybe you need a helper that handles a single clock. Or > that function could take a NULL string for single clock? > Ok. I will drop this clock, and use a helper to replace devm_regmap_init_mmio_clk api calls. >> >>>> + >>>> + "#clock-cells": >>>> + enum: [0, 1] >>> >>> Why is this not fixed? Also why are parts of your own device consuming >>> the clocks? >>> >>>> + >>>> + clock-output-names: >>>> + description: | >>>> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >>>> + but can be gated independently to save power. >>>> + minItems: 1 >>>> + maxItems: 2 >>>> + oneOf: >>>> + - items: >>>> + - const: cck0 >>>> + - items: >>>> + - const: cck1 >>>> + - items: >>>> + - const: cck0 >>>> + - const: cck1 >>>> + >>>> + clock-frequency: >>>> + description: | >>>> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >>>> + The frequency must be a multiple of the "ker_ck" clock frequency. >>>> + maximum: 25000000 >>> >>> Should not be needed, the consumers request what they need. >>> >> >> The CCKx clock frequency depends on the maximum rate supported by the sigma >> delta converters (for instance a digital mic) and the expected decimation >> ratio on the bitstream. Typically this determines the frequency on the SPI >> bus. >> This rate is defined statically and shared by the CCKx clocks. So IMHO, as >> this rate is unique, it can look strange to let the consumer define it. >> Moreover, it seems to me that clock-frequency is already used to configure >> the frequency of a provider in some other bindings. >> For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml >> So, it's not clear for me, what is the restriction on clock-frequency >> property. Would you have any feedback regarding clock-frequency property usage ? >>>> + >>>> + ranges: true >>>> + >>>> + clock-ranges: true >>>> + >>>> + resets: >>>> + maxItems: 1 >>>> + >>>> + reset-names: >>>> + items: >>>> + - const: mdf >>>> + >>>> + access-controllers: >>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>> + description: | >>>> + Phandle to the rifsc device to check access right. >>>> + >>>> + power-domains: >>>> + maxItems: 1 >>>> + >>>> + st,interleave: >>>> + description: | >>>> + List of phandles of interleaved filters. The indexes of interleaved filters must be >>>> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >>>> + are muxed in a single channel and retrieved through the device associated to the filter 0. >>>> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>> >>> No idea what these even are, but this is probably not the right way to >>> represent the relationship between devices. They're apparently ADCs, but >>> this is also an ADC so I'm not sure what's going on here at all. > > I don't under it either, but regardless phandle-array needs constraints > on the items. It's really a matrix with array of phandle+args arrays. > What is expected for this property is a list of phandles (from 2 to 8) For instance: st,interleave = <&filter0 &filter1>; So, if I just consider the missing constraints, I need to add minItems: 2 maxItems: 8 items: maxItems: 1 Is this correct ? > Rob Best regards Olivier ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-07 9:01 ` Olivier MOYSAN 2026-10-07 13:47 ` Rob Herring @ 2026-10-08 10:11 ` Conor Dooley 2026-10-08 16:37 ` Olivier MOYSAN 1 sibling, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-08 10:11 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 20073 bytes --] On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > Hi Conor, > > Thanks for the review > > On 10/1/26 20:32, Conor Dooley wrote: > > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > > > Add bindings that describes STM32 MDF settings to support > > > digital filtering for Pulse Density Modulation (PDM) microphones > > > and analog sigma delta modulators. > > > > > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > > > --- > > > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > > > 1 file changed, 383 insertions(+) > > > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > new file mode 100644 > > > index 000000000000..f2fbc3e150e8 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > @@ -0,0 +1,383 @@ > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > +%YAML 1.2 > > > +--- > > > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > + > > > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > > > + > > > +maintainers: > > > + - Olivier Moysan <olivier.moysan@foss.st.com> > > > + > > > +description: | > > > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > > > + interface external sigma delta modulators to STM32 micro controllers. > > > + > > > +properties: > > > + compatible: > > > + enum: > > > + - st,stm32mp25-mdf > > > + - st,stm32mp23-mdf > > > + > > > + reg: > > > + minItems: 1 > > > + maxItems: 2 > > > > This needs an items list here. The size of the regions seems like crap > > to begin with... > > > > > + > > > + clocks: > > > + maxItems: 1 > > > + > > > + clock-names: > > > + description: Internal clock used for MDF digital processing. > > > + items: > > > + - const: ker_ck > > > > This is pointless when you only have one. > > > > I agree that it could be dropped. However, it is useful for using > devm_regmap_init_mmio_clk. Ah, because that function if you pass NULL to it, it doesn't mean no string, it means no clock. > > > > + > > > + "#clock-cells": > > > + enum: [0, 1] > > > > Why is this not fixed? Also why are parts of your own device consuming > > the clocks? Reading the docs, this has to be 1, you have two clocks? Not sure why you skipped this and skipped explaining why you are consuming your own clocks. > > > + clock-output-names: > > > + description: | > > > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > > > + but can be gated independently to save power. > > > + minItems: 1 > > > + maxItems: 2 > > > + oneOf: > > > + - items: > > > + - const: cck0 > > > + - items: > > > + - const: cck1 > > > + - items: > > > + - const: cck0 > > > + - const: cck1 > > > + > > > + clock-frequency: > > > + description: | > > > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > > > + The frequency must be a multiple of the "ker_ck" clock frequency. > > > + maximum: 25000000 > > > > Should not be needed, the consumers request what they need. > > > > The CCKx clock frequency depends on the maximum rate supported by the sigma > delta converters (for instance a digital mic) and the expected decimation > ratio on the bitstream. Typically this determines the frequency on the SPI > bus. > This rate is defined statically and shared by the CCKx clocks. So IMHO, as > this rate is unique, it can look strange to let the consumer define it. > Moreover, it seems to me that clock-frequency is already used to configure > the frequency of a provider in some other bindings. > For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml This is a binding from the age of antiquity, using it to justify your use is actually harming your argument rather than helping. Your clock consumers should be providing the information about what the rate should be, and if you need to do this in dt you can use assigned-clock-rates. > So, it's not clear for me, what is the restriction on clock-frequency > property. > > > + > > > + ranges: true > > > + > > > + clock-ranges: true > > > + > > > + resets: > > > + maxItems: 1 > > > + > > > + reset-names: > > > + items: > > > + - const: mdf Same applies here as to the clock names fwiw. > > > + > > > + access-controllers: > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > + description: | > > > + Phandle to the rifsc device to check access right. > > > + > > > + power-domains: > > > + maxItems: 1 > > > + > > > + st,interleave: > > > + description: | > > > + List of phandles of interleaved filters. The indexes of interleaved filters must be > > > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > > > + are muxed in a single channel and retrieved through the device associated to the filter 0. > > > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > No idea what these even are, but this is probably not the right way to > > represent the relationship between devices. They're apparently ADCs, but > > this is also an ADC so I'm not sure what's going on here at all. Yeah, after more thought this should not be done like this at all, especially if these filters the phandle point to are part of this device itself, which I suspect they are. If that's the case, you don't need phandles to even do this, you just need an int that says what N is. > > > > > + > > > +required: > > > + - compatible > > > + - reg > > > + - ranges > > > + - clocks > > > + - clock-names > > > + - clock-ranges > > > + - "#address-cells" > > > + - "#size-cells" > > > + > > > +additionalProperties: false > > > + > > > +patternProperties: > > > + "^sitf@[0-9]+$": > > > + type: object > > > + description: Serial interface child node > > > > Why is this a child node at all? > > Probably not worth reviewing more without a link to the docs for this > > device so I can figure out what on earth is going on! > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > analog-to-digital converter itself. > > Here is the link to STM32MP25 reference manuel > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > Chapter 45: Multi-function digital filter (MDF) > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > filters (DFLT) which can be connected through a multiplexer. > > Below is a schematic view of typical applications targeted by this > peripheral > > > Audio use case: > > mdf > +-------------------------------------+ > +------+ | +------+ +------+ +------+ | > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > +------+ | +------+ +------+ +------+ | > +-------------------------------------+ > > For instance, in an audio use case the serial interface can be configured to > provide the clock to the digital microphone (cck0, cck1 or both) at a common > predefined rate, and to retrieve the PDM samples. > The serial interface provides this samples to a digital filter, which > delivers PCM samples on its output. > > > Analog use case: > > mdf > +-------------------------------------+ > +--------+ | +------+ +------+ +------+ | > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > +--------+ | +------+ +------+ +------+ | > +-------------------------------------+ So, looking at the docs and a brief chat with Jonathan about this device, I believe you've got things backwards and this is actually the backend, and the adc should be the one populating the io-backends property pointing to this device. You should have io-backend-cells, and I assume that there should be a cell for the adc to select which dlft it is connected to. I think all of these child nodes should just get deleted - all your devices here seem completely fake, since you've got stuff that's only a single word wide. With that, you could also throw away these mickey mouse nodes with sound-dai-cels of 0, and use 1 instead, with that cell again determining which dlft is in use. The only child node I can really thing of any justification for here is channels - albeit not adc channels since this is not an adc - so that you can individually configure a dlft using those channel nodes. These serial inputs, what is the source for the data that is ever actually sent there? I am assuming it's effectively another IIO device, just not the onboard adc? Are the outputs exposed on pins on the package? I would encourage you to remodel this system, where this device is the backend and also try to get rid of as much of the consuming your own clock as possible. Certainly consuming ker_clk should never be required. It's hard to reason about what should happen with the serial interface clocks, when I have no idea what the input/data source device actually is in those cases. Being a clock controller does make sense, because the device exposes CCK0/1 to the outside world, it's the internal routing to the SITF blocks that I am not sure how to deal with. A ouroboros device that is consuming a clock it provides is not really a done thing, hopefully the IIO guys can tell you how these kinds of things are typically done here, since I'm sure there's plenty of other devices that have some sort of ability to change the clock source for a channel. Probably you need to add two optional input clocks to this device, since mdf_cck0/1 can be inputs too? Let me know if any of this feedback is intractable stuff, and maybe hang on for someone like David or Jonathan to provide some review before going about a significant rework. It's worth bearing in mind that I am a binding reviewer and not a domain expert in ADCs etc. Thanks, Conor. > > > + > > > + properties: > > > + compatible: > > > + enum: > > > + - st,stm32mp25-sitf-mdf > > > + > > > + reg: > > > + description: Specify the SITF serial interface instance > > > + maxItems: 1 > > > + > > > + clocks: > > > + description: | > > > + Serial interface clock (optional depending on interface mode) > > > + maxItems: 1 > > > + > > > + st,sitf-mode: > > > + description: | > > > + Select serial interface protocol > > > + - spi: SPI mode > > > + - lf_spi: low frequency SPI mode for low power applications > > > + $ref: /schemas/types.yaml#/definitions/string > > > + enum: > > > + - spi > > > + - lf_spi > > > + > > > + required: > > > + - reg > > > + - st,sitf-mode > > > + > > > + additionalProperties: false > > > + > > > + "^filter@[0-9]+$": > > > + type: object > > > + description: Digital filter path child node > > > + > > > + properties: > > > + compatible: > > > + enum: > > > + - st,stm32mp25-mdf-dmic > > > + - st,stm32mp25-mdf-adc > > > + > > > + reg: > > > + description: Specify the MDF filter instance > > > + maxItems: 1 > > > + > > > + interrupts: > > > + maxItems: 1 > > > + > > > + clocks: > > > + minItems: 1 > > > + description: Internal clock used for MDF digital processing and control blocks. > > > + > > > + clock-names: > > > + items: > > > + - const: ker_ck > > > + > > > + dmas: > > > + maxItems: 1 > > > + > > > + dma-names: > > > + items: > > > + - const: rx > > > + > > > + "#io-channel-cells": > > > + const: 1 > > > + > > > + '#address-cells': > > > + const: 1 > > > + > > > + '#size-cells': > > > + const: 0 > > > + > > > + st,cic-mode: > > > + description: | > > > + Cascaded-integrator-comb (CIC) filter configuration > > > + - 0: MCIC & ACIC filters in FastSinc mode > > > + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 > > > + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 > > > + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 > > > + This property is mandatory for filter 0 or filters not used in interleave mode. > > > + $ref: /schemas/types.yaml#/definitions/uint32 > > > + minimum: 0 > > > + maximum: 5 > > > + > > > + st,delay: > > > + description: Filter delay in samples > > > + $ref: /schemas/types.yaml#/definitions/uint32 > > > + maximum: 127 > > > + > > > + st,rs-filter-bypass: > > > + description: Bypass RSFLT reshaping filter. > > > + $ref: /schemas/types.yaml#/definitions/flag > > > + > > > + st,hpf-filter-cutoff-bp: > > > + description: | > > > + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. > > > + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. > > > + If this property is not defined the HPF is disabled. > > > + enum: [625, 1250, 2500, 9500] > > > + > > > + st,sync: > > > + description: > > > + Synchronize to another filter. > > > + Must contain the phandle of the filter providing the synchronization. > > > + allOf: > > > + - $ref: /schemas/types.yaml#/definitions/phandle-array > > > + - maxItems: 1 > > > + > > > + st,sitf: > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > + items: > > > + - items: > > > + - description: Phandle of the serial interface connected to the digital filter > > > + - description: | > > > + The phandle's argument selects the bitstream on the falling or rising edge > > > + of the serial interface clock: > > > + - 0: rising edge > > > + - 1: falling edge > > > + enum: [0, 1] > > > + default: 0 > > > + description: > > > + Should be phandle/bitstream pair. > > > + > > > + required: > > > + - compatible > > > + - reg > > > + - interrupts > > > + - dmas > > > + - dma-names > > > + - "#io-channel-cells" > > > + - "#address-cells" > > > + - "#size-cells" > > > + - st,sitf > > > + > > > + unevaluatedProperties: false > > > + > > > + patternProperties: > > > + "^channel@([0-7])$": > > > + type: object > > > + $ref: adc.yaml > > > + description: Represents the external channel which is connected to the MDF. > > > + > > > + properties: > > > + reg: > > > + maximum: 7 > > > + > > > + io-backends: > > > + description: > > > + Used to pipe external sigma delta modulator or internal ADC backend to MDF > > > + channel. > > > + maxItems: 1 > > > + > > > + required: > > > + - reg > > > + > > > + unevaluatedProperties: false > > > + > > > + allOf: > > > + - if: > > > + properties: > > > + compatible: > > > + contains: > > > + const: st,stm32mp25-mdf-adc > > > + > > > + then: > > > + patternProperties: > > > + "^channel@[0-7]$": > > > + required: > > > + - io-backends > > > + > > > + - if: > > > + properties: > > > + compatible: > > > + contains: > > > + const: st,stm32mp25-mdf-dmic > > > + > > > + then: > > > + patternProperties: > > > + "^mdf-dai+$": > > > + type: object > > > + description: child node > > > + > > > + properties: > > > + compatible: > > > + enum: > > > + - st,stm32mp25-mdf-dai > > > + > > > + "#sound-dai-cells": > > > + const: 0 > > > + > > > + io-channels: > > > + description: > > > + From common IIO binding. Used to pipe external sigma delta > > > + modulator or internal ADC output to MDF channel. > > > + > > > + power-domains: > > > + maxItems: 1 > > > + > > > + port: > > > + $ref: /schemas/sound/audio-graph-port.yaml# > > > + unevaluatedProperties: false > > > + > > > + required: > > > + - compatible > > > + - "#sound-dai-cells" > > > + - io-channels > > > + > > > + additionalProperties: false > > > + > > > +examples: > > > + - | > > > + #include <dt-bindings/clock/st,stm32mp25-rcc.h> > > > + #include <dt-bindings/interrupt-controller/arm-gic.h> > > > + mdf1: mdf@504d0000 { > > > + compatible = "st,stm32mp25-mdf"; > > > + ranges = <0 0x504d0000 0x1000>; > > > + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; > > > + #address-cells = <1>; > > > + #size-cells = <1>; > > > + clocks = <&rcc CK_KER_MDF1>; > > > + clock-names = "ker_ck"; > > > + clock-ranges; > > > + #clock-cells = <1>; > > > + clock-output-names = "cck0", "cck1"; > > > + clock-frequency = <2048000>; > > > + > > > + sitf5: sitf@300 { > > > + compatible = "st,stm32mp25-sitf-mdf"; > > > + reg = <0x300 0x4>; > > > + st,sitf-mode = "spi"; > > > + clocks = <&mdf1 0>; > > > + }; > > > + > > > + filter0: filter@84 { > > > + compatible = "st,stm32mp25-mdf-dmic"; > > > + reg = <0x84 0x70>; > > > + #io-channel-cells = <1>; > > > + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; > > > + dmas = <&hpdma 63 0x63 0x12 0>; > > > + dma-names = "rx"; > > > + st,cic-mode = <5>; > > > + st,sitf = <&sitf5 0>; > > > + #address-cells = <1>; > > > + #size-cells = <0>; > > > + > > > + channel@0 { > > > + reg = <0>; > > > + }; > > > + > > > + asoc_pdm0: mdf-dai { > > > + compatible = "st,stm32mp25-mdf-dai"; > > > + #sound-dai-cells = <0>; > > > + io-channels = <&filter0 0>; > > > + }; > > > + }; > > > + > > > + filter1: filter@104 { > > > + compatible = "st,stm32mp25-mdf-adc"; > > > + reg = <0x104 0x70>; > > > + #io-channel-cells = <1>; > > > + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; > > > + dmas = <&hpdma 64 0x63 0x12 0>; > > > + dma-names = "rx"; > > > + st,cic-mode = <2>; > > > + st,sitf = <&sitf5 1>; > > > + #address-cells = <1>; > > > + #size-cells = <0>; > > > + > > > + channel@1 { > > > + reg = <1>; > > > + settling-time-us = <1000>; > > > + io-backends = <&sd_adc1>; > > > + }; > > > + }; > > > + }; > > > + > > > +... > > > -- > > > 2.43.0 > > > > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-08 10:11 ` Conor Dooley @ 2026-10-08 16:37 ` Olivier MOYSAN 2026-10-09 19:12 ` Conor Dooley 0 siblings, 1 reply; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-08 16:37 UTC (permalink / raw) To: Conor Dooley Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Conor, On 10/8/26 12:11, Conor Dooley wrote: > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >> Hi Conor, >> >> Thanks for the review >> >> On 10/1/26 20:32, Conor Dooley wrote: >>> On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >>>> Add bindings that describes STM32 MDF settings to support >>>> digital filtering for Pulse Density Modulation (PDM) microphones >>>> and analog sigma delta modulators. >>>> >>>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >>>> --- >>>> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >>>> 1 file changed, 383 insertions(+) >>>> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> >>>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> new file mode 100644 >>>> index 000000000000..f2fbc3e150e8 >>>> --- /dev/null >>>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>> @@ -0,0 +1,383 @@ >>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>>> +%YAML 1.2 >>>> +--- >>>> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >>>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>>> + >>>> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >>>> + >>>> +maintainers: >>>> + - Olivier Moysan <olivier.moysan@foss.st.com> >>>> + >>>> +description: | >>>> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >>>> + interface external sigma delta modulators to STM32 micro controllers. >>>> + >>>> +properties: >>>> + compatible: >>>> + enum: >>>> + - st,stm32mp25-mdf >>>> + - st,stm32mp23-mdf >>>> + >>>> + reg: >>>> + minItems: 1 >>>> + maxItems: 2 >>> >>> This needs an items list here. The size of the regions seems like crap >>> to begin with... >>> >>>> + >>>> + clocks: >>>> + maxItems: 1 >>>> + >>>> + clock-names: >>>> + description: Internal clock used for MDF digital processing. >>>> + items: >>>> + - const: ker_ck >>> >>> This is pointless when you only have one. >>> >> >> I agree that it could be dropped. However, it is useful for using >> devm_regmap_init_mmio_clk. > > Ah, because that function if you pass NULL to it, it doesn't mean no > string, it means no clock. > The MDF has two clocks (AHB clock for register accesses and ker_ck for peripheral processing). However, these two clocks share the same gate. So, only the ker_ck clock is exposed in the driver. The regmap api is a convenient way to manage registers and gate the AHB clock only on register accesses. Removing clock-names no longer allows you to benefit from clock management handled by the regmap framework, and means that this must be managed explicitly, partially or entirely, in the driver. >> >>>> + >>>> + "#clock-cells": >>>> + enum: [0, 1] >>> >>> Why is this not fixed? Also why are parts of your own device consuming >>> the clocks? > > Reading the docs, this has to be 1, you have two clocks? > > Not sure why you skipped this and skipped explaining why you are > consuming your own clocks. > Yes, we can have two clocks gated independently but sharing the same rate. Using the clock framework apis seemed to me the right way to manage cck1 and cck0 gating and divider computing. I think I would have to introduce proprietary properties and have to implement code in the driver, that would be handled natively by the framework otherwise. >>>> + clock-output-names: >>>> + description: | >>>> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >>>> + but can be gated independently to save power. >>>> + minItems: 1 >>>> + maxItems: 2 >>>> + oneOf: >>>> + - items: >>>> + - const: cck0 >>>> + - items: >>>> + - const: cck1 >>>> + - items: >>>> + - const: cck0 >>>> + - const: cck1 >>>> + >>>> + clock-frequency: >>>> + description: | >>>> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >>>> + The frequency must be a multiple of the "ker_ck" clock frequency. >>>> + maximum: 25000000 >>> >>> Should not be needed, the consumers request what they need. >>> >> >> The CCKx clock frequency depends on the maximum rate supported by the sigma >> delta converters (for instance a digital mic) and the expected decimation >> ratio on the bitstream. Typically this determines the frequency on the SPI >> bus. >> This rate is defined statically and shared by the CCKx clocks. So IMHO, as >> this rate is unique, it can look strange to let the consumer define it. >> Moreover, it seems to me that clock-frequency is already used to configure >> the frequency of a provider in some other bindings. >> For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml > > This is a binding from the age of antiquity, using it to justify your > use is actually harming your argument rather than helping. Your clock > consumers should be providing the information about what the rate should > be, and if you need to do this in dt you can use assigned-clock-rates. > ok, I will move this to clock consumer with assigned-clock properties. >> So, it's not clear for me, what is the restriction on clock-frequency >> property. >>>> + >>>> + ranges: true >>>> + >>>> + clock-ranges: true >>>> + >>>> + resets: >>>> + maxItems: 1 >>>> + >>>> + reset-names: >>>> + items: >>>> + - const: mdf > > Same applies here as to the clock names fwiw. > Yes, I removed this. >>>> + >>>> + access-controllers: >>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>> + description: | >>>> + Phandle to the rifsc device to check access right. >>>> + >>>> + power-domains: >>>> + maxItems: 1 >>>> + >>>> + st,interleave: >>>> + description: | >>>> + List of phandles of interleaved filters. The indexes of interleaved filters must be >>>> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >>>> + are muxed in a single channel and retrieved through the device associated to the filter 0. >>>> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>> >>> No idea what these even are, but this is probably not the right way to >>> represent the relationship between devices. They're apparently ADCs, but >>> this is also an ADC so I'm not sure what's going on here at all. > > Yeah, after more thought this should not be done like this at all, > especially if these filters the phandle point to are part of this device > itself, which I suspect they are. If that's the case, you don't need > phandles to even do this, you just need an int that says what N is. > Yes, can be an index as it is an internal reference. I will change this. >>> >>>> + >>>> +required: >>>> + - compatible >>>> + - reg >>>> + - ranges >>>> + - clocks >>>> + - clock-names >>>> + - clock-ranges >>>> + - "#address-cells" >>>> + - "#size-cells" >>>> + >>>> +additionalProperties: false >>>> + >>>> +patternProperties: >>>> + "^sitf@[0-9]+$": >>>> + type: object >>>> + description: Serial interface child node >>> >>> Why is this a child node at all? >>> Probably not worth reviewing more without a link to the docs for this >>> device so I can figure out what on earth is going on! >>> >> >> The MDF is a digital filter for sigma-delta bitstreams, rather than the >> analog-to-digital converter itself. >> >> Here is the link to STM32MP25 reference manuel >> https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf >> Chapter 45: Multi-function digital filter (MDF) >> >> On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital >> filters (DFLT) which can be connected through a multiplexer. >> >> Below is a schematic view of typical applications targeted by this >> peripheral >> >> >> Audio use case: >> >> mdf >> +-------------------------------------+ >> +------+ | +------+ +------+ +------+ | >> | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device >> +------+ | +------+ +------+ +------+ | >> +-------------------------------------+ >> >> For instance, in an audio use case the serial interface can be configured to >> provide the clock to the digital microphone (cck0, cck1 or both) at a common >> predefined rate, and to retrieve the PDM samples. >> The serial interface provides this samples to a digital filter, which >> delivers PCM samples on its output. >> >> >> Analog use case: >> >> mdf >> +-------------------------------------+ >> +--------+ | +------+ +------+ +------+ | >> | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device >> +--------+ | +------+ +------+ +------+ | >> +-------------------------------------+ > > > So, looking at the docs and a brief chat with Jonathan about this > device, I believe you've got things backwards and this is actually the backend, > and the adc should be the one populating the io-backends property > pointing to this device. You should have io-backend-cells, and I assume > that there should be a cell for the adc to select which dlft it is connected > to. > There have already been lengthy discussions in the past about a DFSDM peripheral on STM32MP1, which has features similar to those of the MDF and similar implementation constraints. For the DFSDM, a solution based on an IIO backend had been upstreamed. The MDF follows the same architecture. I need to take a little time to dive back into this issue. DFSDM sources: drivers/iio/adc/stm32-dfsdm-adc.c drivers/iio/adc/stm32-dfsdm-core.c Here is a sample of DFSDM DT sd_adc0: simple-sd-adc0 { compatible = "sd-modulator"; #io-backend-cells = <0>; vref-supply = <&v3v3>; }; dfsdm0 { compatible = "st,stm32-dfsdm-adc"; ... channel@0 { reg = <0>; label = "in0"; ... io-backends = <&sd_adc0>; }; }; > I think all of these child nodes should just get deleted - all your > devices here seem completely fake, since you've got stuff that's only a > single word wide. With that, you could also throw away these mickey > mouse nodes with sound-dai-cels of 0, and use 1 instead, with that cell > again determining which dlft is in use. > > The only child node I can really thing of any justification for here is > channels - albeit not adc channels since this is not an adc - so that > you can individually configure a dlft using those channel nodes. > > These serial inputs, what is the source for the data that is ever > actually sent there? I am assuming it's effectively another IIO device, > just not the onboard adc? Are the outputs exposed on pins on the > package? > > I would encourage you to remodel this system, where this device is the > backend and also try to get rid of as much of the consuming your own > clock as possible. Certainly consuming ker_clk should never be required. > It's hard to reason about what should happen with the serial interface > clocks, when I have no idea what the input/data source device actually > is in those cases. Being a clock controller does make sense, because the > device exposes CCK0/1 to the outside world, it's the internal routing to > the SITF blocks that I am not sure how to deal with. A ouroboros device > that is consuming a clock it provides is not really a done thing, > hopefully the IIO guys can tell you how these kinds of things are > typically done here, since I'm sure there's plenty of other devices > that have some sort of ability to change the clock source for a channel. > > Probably you need to add two optional input clocks to this device, since > mdf_cck0/1 can be inputs too? > > Let me know if any of this feedback is intractable stuff, and maybe hang > on for someone like David or Jonathan to provide some review before > going about a significant rework. It's worth bearing in mind that I am a > binding reviewer and not a domain expert in ADCs etc. > > Thanks, > Conor. > Best regards Olivier >>>> + >>>> + properties: >>>> + compatible: >>>> + enum: >>>> + - st,stm32mp25-sitf-mdf >>>> + >>>> + reg: >>>> + description: Specify the SITF serial interface instance >>>> + maxItems: 1 >>>> + >>>> + clocks: >>>> + description: | >>>> + Serial interface clock (optional depending on interface mode) >>>> + maxItems: 1 >>>> + >>>> + st,sitf-mode: >>>> + description: | >>>> + Select serial interface protocol >>>> + - spi: SPI mode >>>> + - lf_spi: low frequency SPI mode for low power applications >>>> + $ref: /schemas/types.yaml#/definitions/string >>>> + enum: >>>> + - spi >>>> + - lf_spi >>>> + >>>> + required: >>>> + - reg >>>> + - st,sitf-mode >>>> + >>>> + additionalProperties: false >>>> + >>>> + "^filter@[0-9]+$": >>>> + type: object >>>> + description: Digital filter path child node >>>> + >>>> + properties: >>>> + compatible: >>>> + enum: >>>> + - st,stm32mp25-mdf-dmic >>>> + - st,stm32mp25-mdf-adc >>>> + >>>> + reg: >>>> + description: Specify the MDF filter instance >>>> + maxItems: 1 >>>> + >>>> + interrupts: >>>> + maxItems: 1 >>>> + >>>> + clocks: >>>> + minItems: 1 >>>> + description: Internal clock used for MDF digital processing and control blocks. >>>> + >>>> + clock-names: >>>> + items: >>>> + - const: ker_ck >>>> + >>>> + dmas: >>>> + maxItems: 1 >>>> + >>>> + dma-names: >>>> + items: >>>> + - const: rx >>>> + >>>> + "#io-channel-cells": >>>> + const: 1 >>>> + >>>> + '#address-cells': >>>> + const: 1 >>>> + >>>> + '#size-cells': >>>> + const: 0 >>>> + >>>> + st,cic-mode: >>>> + description: | >>>> + Cascaded-integrator-comb (CIC) filter configuration >>>> + - 0: MCIC & ACIC filters in FastSinc mode >>>> + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 >>>> + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 >>>> + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 >>>> + This property is mandatory for filter 0 or filters not used in interleave mode. >>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>> + minimum: 0 >>>> + maximum: 5 >>>> + >>>> + st,delay: >>>> + description: Filter delay in samples >>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>> + maximum: 127 >>>> + >>>> + st,rs-filter-bypass: >>>> + description: Bypass RSFLT reshaping filter. >>>> + $ref: /schemas/types.yaml#/definitions/flag >>>> + >>>> + st,hpf-filter-cutoff-bp: >>>> + description: | >>>> + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. >>>> + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. >>>> + If this property is not defined the HPF is disabled. >>>> + enum: [625, 1250, 2500, 9500] >>>> + >>>> + st,sync: >>>> + description: >>>> + Synchronize to another filter. >>>> + Must contain the phandle of the filter providing the synchronization. >>>> + allOf: >>>> + - $ref: /schemas/types.yaml#/definitions/phandle-array >>>> + - maxItems: 1 >>>> + >>>> + st,sitf: >>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>> + items: >>>> + - items: >>>> + - description: Phandle of the serial interface connected to the digital filter >>>> + - description: | >>>> + The phandle's argument selects the bitstream on the falling or rising edge >>>> + of the serial interface clock: >>>> + - 0: rising edge >>>> + - 1: falling edge >>>> + enum: [0, 1] >>>> + default: 0 >>>> + description: >>>> + Should be phandle/bitstream pair. >>>> + >>>> + required: >>>> + - compatible >>>> + - reg >>>> + - interrupts >>>> + - dmas >>>> + - dma-names >>>> + - "#io-channel-cells" >>>> + - "#address-cells" >>>> + - "#size-cells" >>>> + - st,sitf >>>> + >>>> + unevaluatedProperties: false >>>> + >>>> + patternProperties: >>>> + "^channel@([0-7])$": >>>> + type: object >>>> + $ref: adc.yaml >>>> + description: Represents the external channel which is connected to the MDF. >>>> + >>>> + properties: >>>> + reg: >>>> + maximum: 7 >>>> + >>>> + io-backends: >>>> + description: >>>> + Used to pipe external sigma delta modulator or internal ADC backend to MDF >>>> + channel. >>>> + maxItems: 1 > >>>> + >>>> + required: >>>> + - reg >>>> + >>>> + unevaluatedProperties: false >>>> + >>>> + allOf: >>>> + - if: >>>> + properties: >>>> + compatible: >>>> + contains: >>>> + const: st,stm32mp25-mdf-adc >>>> + >>>> + then: >>>> + patternProperties: >>>> + "^channel@[0-7]$": >>>> + required: >>>> + - io-backends >>>> + >>>> + - if: >>>> + properties: >>>> + compatible: >>>> + contains: >>>> + const: st,stm32mp25-mdf-dmic >>>> + >>>> + then: >>>> + patternProperties: >>>> + "^mdf-dai+$": >>>> + type: object >>>> + description: child node >>>> + >>>> + properties: >>>> + compatible: >>>> + enum: >>>> + - st,stm32mp25-mdf-dai >>>> + >>>> + "#sound-dai-cells": >>>> + const: 0 >>>> + >>>> + io-channels: >>>> + description: >>>> + From common IIO binding. Used to pipe external sigma delta >>>> + modulator or internal ADC output to MDF channel. >>>> + >>>> + power-domains: >>>> + maxItems: 1 >>>> + >>>> + port: >>>> + $ref: /schemas/sound/audio-graph-port.yaml# >>>> + unevaluatedProperties: false >>>> + >>>> + required: >>>> + - compatible >>>> + - "#sound-dai-cells" >>>> + - io-channels >>>> + >>>> + additionalProperties: false >>>> + >>>> +examples: >>>> + - | >>>> + #include <dt-bindings/clock/st,stm32mp25-rcc.h> >>>> + #include <dt-bindings/interrupt-controller/arm-gic.h> >>>> + mdf1: mdf@504d0000 { >>>> + compatible = "st,stm32mp25-mdf"; >>>> + ranges = <0 0x504d0000 0x1000>; >>>> + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; >>>> + #address-cells = <1>; >>>> + #size-cells = <1>; >>>> + clocks = <&rcc CK_KER_MDF1>; >>>> + clock-names = "ker_ck"; >>>> + clock-ranges; >>>> + #clock-cells = <1>; >>>> + clock-output-names = "cck0", "cck1"; >>>> + clock-frequency = <2048000>; >>>> + >>>> + sitf5: sitf@300 { >>>> + compatible = "st,stm32mp25-sitf-mdf"; >>>> + reg = <0x300 0x4>; >>>> + st,sitf-mode = "spi"; >>>> + clocks = <&mdf1 0>; >>>> + }; >>>> + >>>> + filter0: filter@84 { >>>> + compatible = "st,stm32mp25-mdf-dmic"; >>>> + reg = <0x84 0x70>; >>>> + #io-channel-cells = <1>; >>>> + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; >>>> + dmas = <&hpdma 63 0x63 0x12 0>; >>>> + dma-names = "rx"; >>>> + st,cic-mode = <5>; >>>> + st,sitf = <&sitf5 0>; >>>> + #address-cells = <1>; >>>> + #size-cells = <0>; >>>> + >>>> + channel@0 { >>>> + reg = <0>; >>>> + }; >>>> + >>>> + asoc_pdm0: mdf-dai { >>>> + compatible = "st,stm32mp25-mdf-dai"; >>>> + #sound-dai-cells = <0>; >>>> + io-channels = <&filter0 0>; >>>> + }; >>>> + }; >>>> + >>>> + filter1: filter@104 { >>>> + compatible = "st,stm32mp25-mdf-adc"; >>>> + reg = <0x104 0x70>; >>>> + #io-channel-cells = <1>; >>>> + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; >>>> + dmas = <&hpdma 64 0x63 0x12 0>; >>>> + dma-names = "rx"; >>>> + st,cic-mode = <2>; >>>> + st,sitf = <&sitf5 1>; >>>> + #address-cells = <1>; >>>> + #size-cells = <0>; >>>> + >>>> + channel@1 { >>>> + reg = <1>; >>>> + settling-time-us = <1000>; >>>> + io-backends = <&sd_adc1>; >>>> + }; >>>> + }; >>>> + }; >>>> + >>>> +... >>>> -- >>>> 2.43.0 >>>> >> ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-08 16:37 ` Olivier MOYSAN @ 2026-10-09 19:12 ` Conor Dooley 2026-10-12 12:56 ` Olivier MOYSAN 0 siblings, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-09 19:12 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 25463 bytes --] On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: > Hi Conor, > > On 10/8/26 12:11, Conor Dooley wrote: > > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > > > Hi Conor, > > > > > > Thanks for the review > > > > > > On 10/1/26 20:32, Conor Dooley wrote: > > > > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > > > > > Add bindings that describes STM32 MDF settings to support > > > > > digital filtering for Pulse Density Modulation (PDM) microphones > > > > > and analog sigma delta modulators. > > > > > > > > > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > > > > > --- > > > > > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > > > > > 1 file changed, 383 insertions(+) > > > > > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > new file mode 100644 > > > > > index 000000000000..f2fbc3e150e8 > > > > > --- /dev/null > > > > > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > @@ -0,0 +1,383 @@ > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > > > +%YAML 1.2 > > > > > +--- > > > > > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > > > + > > > > > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > > > > > + > > > > > +maintainers: > > > > > + - Olivier Moysan <olivier.moysan@foss.st.com> > > > > > + > > > > > +description: | > > > > > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > > > > > + interface external sigma delta modulators to STM32 micro controllers. > > > > > + > > > > > +properties: > > > > > + compatible: > > > > > + enum: > > > > > + - st,stm32mp25-mdf > > > > > + - st,stm32mp23-mdf > > > > > + > > > > > + reg: > > > > > + minItems: 1 > > > > > + maxItems: 2 > > > > > > > > This needs an items list here. The size of the regions seems like crap > > > > to begin with... > > > > > > > > > + > > > > > + clocks: > > > > > + maxItems: 1 > > > > > + > > > > > + clock-names: > > > > > + description: Internal clock used for MDF digital processing. > > > > > + items: > > > > > + - const: ker_ck > > > > > > > > This is pointless when you only have one. > > > > > > > > > > I agree that it could be dropped. However, it is useful for using > > > devm_regmap_init_mmio_clk. > > > > Ah, because that function if you pass NULL to it, it doesn't mean no > > string, it means no clock. > > > > The MDF has two clocks (AHB clock for register accesses and ker_ck for > peripheral processing). However, these two clocks share the same gate. So, > only the ker_ck clock is exposed in the driver. That's incorrect, you should have two clocks in DT if the block has two even if they have a shared gate. > The regmap api is a convenient way to manage registers and gate the AHB > clock only on register accesses. Removing clock-names no longer allows you > to benefit from clock management handled by the regmap framework, and means > that this must be managed explicitly, partially or entirely, in the driver. > > > > > > > > > + > > > > > + "#clock-cells": > > > > > + enum: [0, 1] > > > > > > > > Why is this not fixed? Also why are parts of your own device consuming > > > > the clocks? > > > > Reading the docs, this has to be 1, you have two clocks? > > > > Not sure why you skipped this and skipped explaining why you are > > consuming your own clocks. > > > > Yes, we can have two clocks gated independently but sharing the same rate. > > Using the clock framework apis seemed to me the right way to manage cck1 and > cck0 gating and divider computing. I think I would have to introduce > proprietary properties and have to implement code in the driver, that would > be handled natively by the framework otherwise. The CCF is still the right way to do it, especially since CCK0/1 can be exported to other devices. I don't believe you need to actually have a reference in DT to do this though, plenty of "real" clock controllers have only one input clock and hang a whole tree with multiple layers off that. Down below I mentioned this under "ouroboros devices", I think this kind of ability to chose which clock a channel uses is a fairly normal thing to do in IIO land, I just dunno what the preferred mechanism is - I just know that it is not referencing yourself (probably it's some sort of property that you put in a channel node that says 'blah-clock = "cck0"', but better that the IIO folks answer. > > > > > + clock-output-names: > > > > > + description: | > > > > > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > > > > > + but can be gated independently to save power. > > > > > + minItems: 1 > > > > > + maxItems: 2 > > > > > + oneOf: > > > > > + - items: > > > > > + - const: cck0 > > > > > + - items: > > > > > + - const: cck1 > > > > > + - items: > > > > > + - const: cck0 > > > > > + - const: cck1 > > > > > + > > > > > + clock-frequency: > > > > > + description: | > > > > > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > > > > > + The frequency must be a multiple of the "ker_ck" clock frequency. > > > > > + maximum: 25000000 > > > > > > > > Should not be needed, the consumers request what they need. > > > > > > > > > > The CCKx clock frequency depends on the maximum rate supported by the sigma > > > delta converters (for instance a digital mic) and the expected decimation > > > ratio on the bitstream. Typically this determines the frequency on the SPI > > > bus. > > > This rate is defined statically and shared by the CCKx clocks. So IMHO, as > > > this rate is unique, it can look strange to let the consumer define it. > > > Moreover, it seems to me that clock-frequency is already used to configure > > > the frequency of a provider in some other bindings. > > > For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml > > > > This is a binding from the age of antiquity, using it to justify your > > use is actually harming your argument rather than helping. Your clock > > consumers should be providing the information about what the rate should > > be, and if you need to do this in dt you can use assigned-clock-rates. > > > > ok, I will move this to clock consumer with assigned-clock properties. > > > > So, it's not clear for me, what is the restriction on clock-frequency > > > property. > > > > > + > > > > > + ranges: true > > > > > + > > > > > + clock-ranges: true > > > > > + > > > > > + resets: > > > > > + maxItems: 1 > > > > > + > > > > > + reset-names: > > > > > + items: > > > > > + - const: mdf > > > > Same applies here as to the clock names fwiw. > > > > Yes, I removed this. > > > > > > + > > > > > + access-controllers: > > > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > + description: | > > > > > + Phandle to the rifsc device to check access right. > > > > > + > > > > > + power-domains: > > > > > + maxItems: 1 > > > > > + > > > > > + st,interleave: > > > > > + description: | > > > > > + List of phandles of interleaved filters. The indexes of interleaved filters must be > > > > > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > > > > > + are muxed in a single channel and retrieved through the device associated to the filter 0. > > > > > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > > > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > > > > No idea what these even are, but this is probably not the right way to > > > > represent the relationship between devices. They're apparently ADCs, but > > > > this is also an ADC so I'm not sure what's going on here at all. > > > > Yeah, after more thought this should not be done like this at all, > > especially if these filters the phandle point to are part of this device > > itself, which I suspect they are. If that's the case, you don't need > > phandles to even do this, you just need an int that says what N is. > > > > Yes, can be an index as it is an internal reference. I will change this. > > > > > > > > > > + > > > > > +required: > > > > > + - compatible > > > > > + - reg > > > > > + - ranges > > > > > + - clocks > > > > > + - clock-names > > > > > + - clock-ranges > > > > > + - "#address-cells" > > > > > + - "#size-cells" > > > > > + > > > > > +additionalProperties: false > > > > > + > > > > > +patternProperties: > > > > > + "^sitf@[0-9]+$": > > > > > + type: object > > > > > + description: Serial interface child node > > > > > > > > Why is this a child node at all? > > > > Probably not worth reviewing more without a link to the docs for this > > > > device so I can figure out what on earth is going on! > > > > > > > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > > > analog-to-digital converter itself. > > > > > > Here is the link to STM32MP25 reference manuel > > > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > > > Chapter 45: Multi-function digital filter (MDF) > > > > > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > > > filters (DFLT) which can be connected through a multiplexer. > > > > > > Below is a schematic view of typical applications targeted by this > > > peripheral > > > > > > > > > Audio use case: > > > > > > mdf > > > +-------------------------------------+ > > > +------+ | +------+ +------+ +------+ | > > > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > > > +------+ | +------+ +------+ +------+ | > > > +-------------------------------------+ > > > > > > For instance, in an audio use case the serial interface can be configured to > > > provide the clock to the digital microphone (cck0, cck1 or both) at a common > > > predefined rate, and to retrieve the PDM samples. > > > The serial interface provides this samples to a digital filter, which > > > delivers PCM samples on its output. > > > > > > > > > Analog use case: > > > > > > mdf > > > +-------------------------------------+ > > > +--------+ | +------+ +------+ +------+ | > > > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > > > +--------+ | +------+ +------+ +------+ | > > > +-------------------------------------+ > > > > > > So, looking at the docs and a brief chat with Jonathan about this > > device, I believe you've got things backwards and this is actually the backend, > > and the adc should be the one populating the io-backends property > > pointing to this device. You should have io-backend-cells, and I assume > > that there should be a cell for the adc to select which dlft it is connected > > to. > > > > There have already been lengthy discussions in the past about a DFSDM > peripheral on STM32MP1, which has features similar to those of the MDF and > similar implementation constraints. For the DFSDM, a solution based on an > IIO backend had been upstreamed. The MDF follows the same architecture. I > need to take a little time to dive back into this issue. One thing to note there is that you retrofitted the backends onto that device, and the original design here is much older (it's a text binding). > > DFSDM sources: > drivers/iio/adc/stm32-dfsdm-adc.c > drivers/iio/adc/stm32-dfsdm-core.c > > Here is a sample of DFSDM DT > > sd_adc0: simple-sd-adc0 { > compatible = "sd-modulator"; > #io-backend-cells = <0>; > vref-supply = <&v3v3>; Yeah, pretty sure this is wrong (backwards). The backend is the thing that gets data from an ADC not the ADC. Thanks, Conor. > }; > > dfsdm0 { > compatible = "st,stm32-dfsdm-adc"; > ... > > channel@0 { > reg = <0>; > label = "in0"; > ... > io-backends = <&sd_adc0>; > }; > }; > > > I think all of these child nodes should just get deleted - all your > > devices here seem completely fake, since you've got stuff that's only a > > single word wide. With that, you could also throw away these mickey > > mouse nodes with sound-dai-cels of 0, and use 1 instead, with that cell > > again determining which dlft is in use. > > > > The only child node I can really thing of any justification for here is > > channels - albeit not adc channels since this is not an adc - so that > > you can individually configure a dlft using those channel nodes. > > > > These serial inputs, what is the source for the data that is ever > > actually sent there? I am assuming it's effectively another IIO device, > > just not the onboard adc? Are the outputs exposed on pins on the > > package? > > > > I would encourage you to remodel this system, where this device is the > > backend and also try to get rid of as much of the consuming your own > > clock as possible. Certainly consuming ker_clk should never be required. > > It's hard to reason about what should happen with the serial interface > > clocks, when I have no idea what the input/data source device actually > > is in those cases. Being a clock controller does make sense, because the > > device exposes CCK0/1 to the outside world, it's the internal routing to > > the SITF blocks that I am not sure how to deal with. A ouroboros device > > that is consuming a clock it provides is not really a done thing, > > hopefully the IIO guys can tell you how these kinds of things are > > typically done here, since I'm sure there's plenty of other devices > > that have some sort of ability to change the clock source for a channel. > > > > Probably you need to add two optional input clocks to this device, since > > mdf_cck0/1 can be inputs too? > > > > Let me know if any of this feedback is intractable stuff, and maybe hang > > on for someone like David or Jonathan to provide some review before > > going about a significant rework. It's worth bearing in mind that I am a > > binding reviewer and not a domain expert in ADCs etc. > > > > Thanks, > > Conor. > > > > Best regards > Olivier > > > > > > + > > > > > + properties: > > > > > + compatible: > > > > > + enum: > > > > > + - st,stm32mp25-sitf-mdf > > > > > + > > > > > + reg: > > > > > + description: Specify the SITF serial interface instance > > > > > + maxItems: 1 > > > > > + > > > > > + clocks: > > > > > + description: | > > > > > + Serial interface clock (optional depending on interface mode) > > > > > + maxItems: 1 > > > > > + > > > > > + st,sitf-mode: > > > > > + description: | > > > > > + Select serial interface protocol > > > > > + - spi: SPI mode > > > > > + - lf_spi: low frequency SPI mode for low power applications > > > > > + $ref: /schemas/types.yaml#/definitions/string > > > > > + enum: > > > > > + - spi > > > > > + - lf_spi > > > > > + > > > > > + required: > > > > > + - reg > > > > > + - st,sitf-mode > > > > > + > > > > > + additionalProperties: false > > > > > + > > > > > + "^filter@[0-9]+$": > > > > > + type: object > > > > > + description: Digital filter path child node > > > > > + > > > > > + properties: > > > > > + compatible: > > > > > + enum: > > > > > + - st,stm32mp25-mdf-dmic > > > > > + - st,stm32mp25-mdf-adc > > > > > + > > > > > + reg: > > > > > + description: Specify the MDF filter instance > > > > > + maxItems: 1 > > > > > + > > > > > + interrupts: > > > > > + maxItems: 1 > > > > > + > > > > > + clocks: > > > > > + minItems: 1 > > > > > + description: Internal clock used for MDF digital processing and control blocks. > > > > > + > > > > > + clock-names: > > > > > + items: > > > > > + - const: ker_ck > > > > > + > > > > > + dmas: > > > > > + maxItems: 1 > > > > > + > > > > > + dma-names: > > > > > + items: > > > > > + - const: rx > > > > > + > > > > > + "#io-channel-cells": > > > > > + const: 1 > > > > > + > > > > > + '#address-cells': > > > > > + const: 1 > > > > > + > > > > > + '#size-cells': > > > > > + const: 0 > > > > > + > > > > > + st,cic-mode: > > > > > + description: | > > > > > + Cascaded-integrator-comb (CIC) filter configuration > > > > > + - 0: MCIC & ACIC filters in FastSinc mode > > > > > + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 > > > > > + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 > > > > > + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 > > > > > + This property is mandatory for filter 0 or filters not used in interleave mode. > > > > > + $ref: /schemas/types.yaml#/definitions/uint32 > > > > > + minimum: 0 > > > > > + maximum: 5 > > > > > + > > > > > + st,delay: > > > > > + description: Filter delay in samples > > > > > + $ref: /schemas/types.yaml#/definitions/uint32 > > > > > + maximum: 127 > > > > > + > > > > > + st,rs-filter-bypass: > > > > > + description: Bypass RSFLT reshaping filter. > > > > > + $ref: /schemas/types.yaml#/definitions/flag > > > > > + > > > > > + st,hpf-filter-cutoff-bp: > > > > > + description: | > > > > > + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. > > > > > + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. > > > > > + If this property is not defined the HPF is disabled. > > > > > + enum: [625, 1250, 2500, 9500] > > > > > + > > > > > + st,sync: > > > > > + description: > > > > > + Synchronize to another filter. > > > > > + Must contain the phandle of the filter providing the synchronization. > > > > > + allOf: > > > > > + - $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > + - maxItems: 1 > > > > > + > > > > > + st,sitf: > > > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > + items: > > > > > + - items: > > > > > + - description: Phandle of the serial interface connected to the digital filter > > > > > + - description: | > > > > > + The phandle's argument selects the bitstream on the falling or rising edge > > > > > + of the serial interface clock: > > > > > + - 0: rising edge > > > > > + - 1: falling edge > > > > > + enum: [0, 1] > > > > > + default: 0 > > > > > + description: > > > > > + Should be phandle/bitstream pair. > > > > > + > > > > > + required: > > > > > + - compatible > > > > > + - reg > > > > > + - interrupts > > > > > + - dmas > > > > > + - dma-names > > > > > + - "#io-channel-cells" > > > > > + - "#address-cells" > > > > > + - "#size-cells" > > > > > + - st,sitf > > > > > + > > > > > + unevaluatedProperties: false > > > > > + > > > > > + patternProperties: > > > > > + "^channel@([0-7])$": > > > > > + type: object > > > > > + $ref: adc.yaml > > > > > + description: Represents the external channel which is connected to the MDF. > > > > > + > > > > > + properties: > > > > > + reg: > > > > > + maximum: 7 > > > > > + > > > > > + io-backends: > > > > > + description: > > > > > + Used to pipe external sigma delta modulator or internal ADC backend to MDF > > > > > + channel. > > > > > + maxItems: 1 > > > > > > > + > > > > > + required: > > > > > + - reg > > > > > + > > > > > + unevaluatedProperties: false > > > > > + > > > > > + allOf: > > > > > + - if: > > > > > + properties: > > > > > + compatible: > > > > > + contains: > > > > > + const: st,stm32mp25-mdf-adc > > > > > + > > > > > + then: > > > > > + patternProperties: > > > > > + "^channel@[0-7]$": > > > > > + required: > > > > > + - io-backends > > > > > + > > > > > + - if: > > > > > + properties: > > > > > + compatible: > > > > > + contains: > > > > > + const: st,stm32mp25-mdf-dmic > > > > > + > > > > > + then: > > > > > + patternProperties: > > > > > + "^mdf-dai+$": > > > > > + type: object > > > > > + description: child node > > > > > + > > > > > + properties: > > > > > + compatible: > > > > > + enum: > > > > > + - st,stm32mp25-mdf-dai > > > > > + > > > > > + "#sound-dai-cells": > > > > > + const: 0 > > > > > + > > > > > + io-channels: > > > > > + description: > > > > > + From common IIO binding. Used to pipe external sigma delta > > > > > + modulator or internal ADC output to MDF channel. > > > > > + > > > > > + power-domains: > > > > > + maxItems: 1 > > > > > + > > > > > + port: > > > > > + $ref: /schemas/sound/audio-graph-port.yaml# > > > > > + unevaluatedProperties: false > > > > > + > > > > > + required: > > > > > + - compatible > > > > > + - "#sound-dai-cells" > > > > > + - io-channels > > > > > + > > > > > + additionalProperties: false > > > > > + > > > > > +examples: > > > > > + - | > > > > > + #include <dt-bindings/clock/st,stm32mp25-rcc.h> > > > > > + #include <dt-bindings/interrupt-controller/arm-gic.h> > > > > > + mdf1: mdf@504d0000 { > > > > > + compatible = "st,stm32mp25-mdf"; > > > > > + ranges = <0 0x504d0000 0x1000>; > > > > > + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; > > > > > + #address-cells = <1>; > > > > > + #size-cells = <1>; > > > > > + clocks = <&rcc CK_KER_MDF1>; > > > > > + clock-names = "ker_ck"; > > > > > + clock-ranges; > > > > > + #clock-cells = <1>; > > > > > + clock-output-names = "cck0", "cck1"; > > > > > + clock-frequency = <2048000>; > > > > > + > > > > > + sitf5: sitf@300 { > > > > > + compatible = "st,stm32mp25-sitf-mdf"; > > > > > + reg = <0x300 0x4>; > > > > > + st,sitf-mode = "spi"; > > > > > + clocks = <&mdf1 0>; > > > > > + }; > > > > > + > > > > > + filter0: filter@84 { > > > > > + compatible = "st,stm32mp25-mdf-dmic"; > > > > > + reg = <0x84 0x70>; > > > > > + #io-channel-cells = <1>; > > > > > + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; > > > > > + dmas = <&hpdma 63 0x63 0x12 0>; > > > > > + dma-names = "rx"; > > > > > + st,cic-mode = <5>; > > > > > + st,sitf = <&sitf5 0>; > > > > > + #address-cells = <1>; > > > > > + #size-cells = <0>; > > > > > + > > > > > + channel@0 { > > > > > + reg = <0>; > > > > > + }; > > > > > + > > > > > + asoc_pdm0: mdf-dai { > > > > > + compatible = "st,stm32mp25-mdf-dai"; > > > > > + #sound-dai-cells = <0>; > > > > > + io-channels = <&filter0 0>; > > > > > + }; > > > > > + }; > > > > > + > > > > > + filter1: filter@104 { > > > > > + compatible = "st,stm32mp25-mdf-adc"; > > > > > + reg = <0x104 0x70>; > > > > > + #io-channel-cells = <1>; > > > > > + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; > > > > > + dmas = <&hpdma 64 0x63 0x12 0>; > > > > > + dma-names = "rx"; > > > > > + st,cic-mode = <2>; > > > > > + st,sitf = <&sitf5 1>; > > > > > + #address-cells = <1>; > > > > > + #size-cells = <0>; > > > > > + > > > > > + channel@1 { > > > > > + reg = <1>; > > > > > + settling-time-us = <1000>; > > > > > + io-backends = <&sd_adc1>; > > > > > + }; > > > > > + }; > > > > > + }; > > > > > + > > > > > +... > > > > > -- > > > > > 2.43.0 > > > > > > > > > [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-09 19:12 ` Conor Dooley @ 2026-10-12 12:56 ` Olivier MOYSAN 2026-10-14 15:15 ` Conor Dooley 2026-10-19 1:30 ` Jonathan Cameron 0 siblings, 2 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-12 12:56 UTC (permalink / raw) To: Conor Dooley Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Conor, On 10/9/26 21:12, Conor Dooley wrote: > On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: >> Hi Conor, >> >> On 10/8/26 12:11, Conor Dooley wrote: >>> On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >>>> Hi Conor, >>>> >>>> Thanks for the review >>>> >>>> On 10/1/26 20:32, Conor Dooley wrote: >>>>> On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >>>>>> Add bindings that describes STM32 MDF settings to support >>>>>> digital filtering for Pulse Density Modulation (PDM) microphones >>>>>> and analog sigma delta modulators. >>>>>> >>>>>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >>>>>> --- >>>>>> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >>>>>> 1 file changed, 383 insertions(+) >>>>>> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>> >>>>>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>> new file mode 100644 >>>>>> index 000000000000..f2fbc3e150e8 >>>>>> --- /dev/null >>>>>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>> @@ -0,0 +1,383 @@ >>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>>>>> +%YAML 1.2 >>>>>> +--- >>>>>> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>>>>> + >>>>>> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >>>>>> + >>>>>> +maintainers: >>>>>> + - Olivier Moysan <olivier.moysan@foss.st.com> >>>>>> + >>>>>> +description: | >>>>>> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >>>>>> + interface external sigma delta modulators to STM32 micro controllers. >>>>>> + >>>>>> +properties: >>>>>> + compatible: >>>>>> + enum: >>>>>> + - st,stm32mp25-mdf >>>>>> + - st,stm32mp23-mdf >>>>>> + >>>>>> + reg: >>>>>> + minItems: 1 >>>>>> + maxItems: 2 >>>>> >>>>> This needs an items list here. The size of the regions seems like crap >>>>> to begin with... >>>>> >>>>>> + >>>>>> + clocks: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + clock-names: >>>>>> + description: Internal clock used for MDF digital processing. >>>>>> + items: >>>>>> + - const: ker_ck >>>>> >>>>> This is pointless when you only have one. >>>>> >>>> >>>> I agree that it could be dropped. However, it is useful for using >>>> devm_regmap_init_mmio_clk. >>> >>> Ah, because that function if you pass NULL to it, it doesn't mean no >>> string, it means no clock. >>> >> >> The MDF has two clocks (AHB clock for register accesses and ker_ck for >> peripheral processing). However, these two clocks share the same gate. So, >> only the ker_ck clock is exposed in the driver. > > That's incorrect, you should have two clocks in DT if the block has two > even if they have a shared gate. > This would not be consistent with the architectural choice made for the STM32MP25. The RCC driver provides an abstraction to manage these two clocks as one, since they are controlled by the same gate. The binding incorporates this abstraction to manage only a single clock. A large number of peripherals on STM32MP25 have the same architecture and follow this implementation rule. So managing both clocks in the MDF driver would create a consistency issue with the other peripherals. >> The regmap api is a convenient way to manage registers and gate the AHB >> clock only on register accesses. Removing clock-names no longer allows you >> to benefit from clock management handled by the regmap framework, and means >> that this must be managed explicitly, partially or entirely, in the driver. >> >>>> >>>>>> + >>>>>> + "#clock-cells": >>>>>> + enum: [0, 1] >>>>> >>>>> Why is this not fixed? Also why are parts of your own device consuming >>>>> the clocks? >>> >>> Reading the docs, this has to be 1, you have two clocks? >>> >>> Not sure why you skipped this and skipped explaining why you are >>> consuming your own clocks. >>> >> >> Yes, we can have two clocks gated independently but sharing the same rate. >> >> Using the clock framework apis seemed to me the right way to manage cck1 and >> cck0 gating and divider computing. I think I would have to introduce >> proprietary properties and have to implement code in the driver, that would >> be handled natively by the framework otherwise. > > The CCF is still the right way to do it, especially since CCK0/1 can be > exported to other devices. I don't believe you need to actually have a > reference in DT to do this though, plenty of "real" clock controllers > have only one input clock and hang a whole tree with multiple layers off > that. > Down below I mentioned this under "ouroboros devices", I think this kind > of ability to chose which clock a channel uses is a fairly normal thing > to do in IIO land, I just dunno what the preferred mechanism is - I just > know that it is not referencing yourself (probably it's some sort of > property that you put in a channel node that says 'blah-clock = "cck0"', > but better that the IIO folks answer. > The adc.yaml binding do not expose clock properties. But maybe IIO experts can answer about this. >>>>>> + clock-output-names: >>>>>> + description: | >>>>>> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >>>>>> + but can be gated independently to save power. >>>>>> + minItems: 1 >>>>>> + maxItems: 2 >>>>>> + oneOf: >>>>>> + - items: >>>>>> + - const: cck0 >>>>>> + - items: >>>>>> + - const: cck1 >>>>>> + - items: >>>>>> + - const: cck0 >>>>>> + - const: cck1 >>>>>> + >>>>>> + clock-frequency: >>>>>> + description: | >>>>>> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >>>>>> + The frequency must be a multiple of the "ker_ck" clock frequency. >>>>>> + maximum: 25000000 >>>>> >>>>> Should not be needed, the consumers request what they need. >>>>> >>>> >>>> The CCKx clock frequency depends on the maximum rate supported by the sigma >>>> delta converters (for instance a digital mic) and the expected decimation >>>> ratio on the bitstream. Typically this determines the frequency on the SPI >>>> bus. >>>> This rate is defined statically and shared by the CCKx clocks. So IMHO, as >>>> this rate is unique, it can look strange to let the consumer define it. >>>> Moreover, it seems to me that clock-frequency is already used to configure >>>> the frequency of a provider in some other bindings. >>>> For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml >>> >>> This is a binding from the age of antiquity, using it to justify your >>> use is actually harming your argument rather than helping. Your clock >>> consumers should be providing the information about what the rate should >>> be, and if you need to do this in dt you can use assigned-clock-rates. >>> >> >> ok, I will move this to clock consumer with assigned-clock properties. >> >>>> So, it's not clear for me, what is the restriction on clock-frequency >>>> property. >>>>>> + >>>>>> + ranges: true >>>>>> + >>>>>> + clock-ranges: true >>>>>> + >>>>>> + resets: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + reset-names: >>>>>> + items: >>>>>> + - const: mdf >>> >>> Same applies here as to the clock names fwiw. >>> >> >> Yes, I removed this. >> >>>>>> + >>>>>> + access-controllers: >>>>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>>>> + description: | >>>>>> + Phandle to the rifsc device to check access right. >>>>>> + >>>>>> + power-domains: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + st,interleave: >>>>>> + description: | >>>>>> + List of phandles of interleaved filters. The indexes of interleaved filters must be >>>>>> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >>>>>> + are muxed in a single channel and retrieved through the device associated to the filter 0. >>>>>> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >>>>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>>> >>>>> No idea what these even are, but this is probably not the right way to >>>>> represent the relationship between devices. They're apparently ADCs, but >>>>> this is also an ADC so I'm not sure what's going on here at all. >>> >>> Yeah, after more thought this should not be done like this at all, >>> especially if these filters the phandle point to are part of this device >>> itself, which I suspect they are. If that's the case, you don't need >>> phandles to even do this, you just need an int that says what N is. >>> >> >> Yes, can be an index as it is an internal reference. I will change this. >> >>>>> >>>>>> + >>>>>> +required: >>>>>> + - compatible >>>>>> + - reg >>>>>> + - ranges >>>>>> + - clocks >>>>>> + - clock-names >>>>>> + - clock-ranges >>>>>> + - "#address-cells" >>>>>> + - "#size-cells" >>>>>> + >>>>>> +additionalProperties: false >>>>>> + >>>>>> +patternProperties: >>>>>> + "^sitf@[0-9]+$": >>>>>> + type: object >>>>>> + description: Serial interface child node >>>>> >>>>> Why is this a child node at all? >>>>> Probably not worth reviewing more without a link to the docs for this >>>>> device so I can figure out what on earth is going on! >>>>> >>>> >>>> The MDF is a digital filter for sigma-delta bitstreams, rather than the >>>> analog-to-digital converter itself. >>>> >>>> Here is the link to STM32MP25 reference manuel >>>> https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf >>>> Chapter 45: Multi-function digital filter (MDF) >>>> >>>> On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital >>>> filters (DFLT) which can be connected through a multiplexer. >>>> >>>> Below is a schematic view of typical applications targeted by this >>>> peripheral >>>> >>>> >>>> Audio use case: >>>> >>>> mdf >>>> +-------------------------------------+ >>>> +------+ | +------+ +------+ +------+ | >>>> | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device >>>> +------+ | +------+ +------+ +------+ | >>>> +-------------------------------------+ >>>> >>>> For instance, in an audio use case the serial interface can be configured to >>>> provide the clock to the digital microphone (cck0, cck1 or both) at a common >>>> predefined rate, and to retrieve the PDM samples. >>>> The serial interface provides this samples to a digital filter, which >>>> delivers PCM samples on its output. >>>> >>>> >>>> Analog use case: >>>> >>>> mdf >>>> +-------------------------------------+ >>>> +--------+ | +------+ +------+ +------+ | >>>> | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device >>>> +--------+ | +------+ +------+ +------+ | >>>> +-------------------------------------+ >>> >>> >>> So, looking at the docs and a brief chat with Jonathan about this >>> device, I believe you've got things backwards and this is actually the backend, >>> and the adc should be the one populating the io-backends property >>> pointing to this device. You should have io-backend-cells, and I assume >>> that there should be a cell for the adc to select which dlft it is connected >>> to. >>> >> >> There have already been lengthy discussions in the past about a DFSDM >> peripheral on STM32MP1, which has features similar to those of the MDF and >> similar implementation constraints. For the DFSDM, a solution based on an >> IIO backend had been upstreamed. The MDF follows the same architecture. I >> need to take a little time to dive back into this issue. > > One thing to note there is that you retrofitted the backends onto that > device, and the original design here is much older (it's a text > binding). > > >> >> DFSDM sources: >> drivers/iio/adc/stm32-dfsdm-adc.c >> drivers/iio/adc/stm32-dfsdm-core.c >> >> Here is a sample of DFSDM DT >> >> sd_adc0: simple-sd-adc0 { >> compatible = "sd-modulator"; >> #io-backend-cells = <0>; >> vref-supply = <&v3v3>; > > Yeah, pretty sure this is wrong (backwards). The backend is the thing > that gets data from an ADC not the ADC. > The backend framework was introduced to implement complex IIO aggregate devices. The hardwares that were driving this need were analog device ad9467 and ST DFSDM. https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff From drivers/iio/industrialio-backend.c: "The typical architecture is to have one device as the frontend device which can be "linked" against one or multiple backend devices. All the IIO and userspace interface is expected to be registers/managed by the frontend device which will callback into the backends when needed (to get/set some configuration that it does not directly control)." * --------------------- * ------------------ | ------------ * | ADC |-----------------| | ADC CORE | * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- * | |-----------------| ------------ * ------------------ --------------------- The MDF (or DFSDM) use case, follows this topology: - The SD modulator (ADC core) registers in backend framework - The MDF registers in IIO framework and exposes the IIO devices It also get configuration (ref voltage) from SD modulator, to compute scaling. I agree that if we consider the terms frontend and backend, the elements in the data flow do not have the roles that we would naturally expect. However, if we consider the expected role of the elements using the iio-backend framework, the usage seems coherent to me. Best regards Olivier > Thanks, > Conor. > >> }; >> >> dfsdm0 { >> compatible = "st,stm32-dfsdm-adc"; >> ... >> >> channel@0 { >> reg = <0>; >> label = "in0"; >> ... >> io-backends = <&sd_adc0>; >> }; >> }; >> >>> I think all of these child nodes should just get deleted - all your >>> devices here seem completely fake, since you've got stuff that's only a >>> single word wide. With that, you could also throw away these mickey >>> mouse nodes with sound-dai-cels of 0, and use 1 instead, with that cell >>> again determining which dlft is in use. >>> >>> The only child node I can really thing of any justification for here is >>> channels - albeit not adc channels since this is not an adc - so that >>> you can individually configure a dlft using those channel nodes. >>> >>> These serial inputs, what is the source for the data that is ever >>> actually sent there? I am assuming it's effectively another IIO device, >>> just not the onboard adc? Are the outputs exposed on pins on the >>> package? >>> >>> I would encourage you to remodel this system, where this device is the >>> backend and also try to get rid of as much of the consuming your own >>> clock as possible. Certainly consuming ker_clk should never be required. >>> It's hard to reason about what should happen with the serial interface >>> clocks, when I have no idea what the input/data source device actually >>> is in those cases. Being a clock controller does make sense, because the >>> device exposes CCK0/1 to the outside world, it's the internal routing to >>> the SITF blocks that I am not sure how to deal with. A ouroboros device >>> that is consuming a clock it provides is not really a done thing, >>> hopefully the IIO guys can tell you how these kinds of things are >>> typically done here, since I'm sure there's plenty of other devices >>> that have some sort of ability to change the clock source for a channel. >>> >>> Probably you need to add two optional input clocks to this device, since >>> mdf_cck0/1 can be inputs too? >>> >>> Let me know if any of this feedback is intractable stuff, and maybe hang >>> on for someone like David or Jonathan to provide some review before >>> going about a significant rework. It's worth bearing in mind that I am a >>> binding reviewer and not a domain expert in ADCs etc. >>> >>> Thanks, >>> Conor. >>> >> >> Best regards >> Olivier >> >>>>>> + >>>>>> + properties: >>>>>> + compatible: >>>>>> + enum: >>>>>> + - st,stm32mp25-sitf-mdf >>>>>> + >>>>>> + reg: >>>>>> + description: Specify the SITF serial interface instance >>>>>> + maxItems: 1 >>>>>> + >>>>>> + clocks: >>>>>> + description: | >>>>>> + Serial interface clock (optional depending on interface mode) >>>>>> + maxItems: 1 >>>>>> + >>>>>> + st,sitf-mode: >>>>>> + description: | >>>>>> + Select serial interface protocol >>>>>> + - spi: SPI mode >>>>>> + - lf_spi: low frequency SPI mode for low power applications >>>>>> + $ref: /schemas/types.yaml#/definitions/string >>>>>> + enum: >>>>>> + - spi >>>>>> + - lf_spi >>>>>> + >>>>>> + required: >>>>>> + - reg >>>>>> + - st,sitf-mode >>>>>> + >>>>>> + additionalProperties: false >>>>>> + >>>>>> + "^filter@[0-9]+$": >>>>>> + type: object >>>>>> + description: Digital filter path child node >>>>>> + >>>>>> + properties: >>>>>> + compatible: >>>>>> + enum: >>>>>> + - st,stm32mp25-mdf-dmic >>>>>> + - st,stm32mp25-mdf-adc >>>>>> + >>>>>> + reg: >>>>>> + description: Specify the MDF filter instance >>>>>> + maxItems: 1 >>>>>> + >>>>>> + interrupts: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + clocks: >>>>>> + minItems: 1 >>>>>> + description: Internal clock used for MDF digital processing and control blocks. >>>>>> + >>>>>> + clock-names: >>>>>> + items: >>>>>> + - const: ker_ck >>>>>> + >>>>>> + dmas: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + dma-names: >>>>>> + items: >>>>>> + - const: rx >>>>>> + >>>>>> + "#io-channel-cells": >>>>>> + const: 1 >>>>>> + >>>>>> + '#address-cells': >>>>>> + const: 1 >>>>>> + >>>>>> + '#size-cells': >>>>>> + const: 0 >>>>>> + >>>>>> + st,cic-mode: >>>>>> + description: | >>>>>> + Cascaded-integrator-comb (CIC) filter configuration >>>>>> + - 0: MCIC & ACIC filters in FastSinc mode >>>>>> + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 >>>>>> + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 >>>>>> + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 >>>>>> + This property is mandatory for filter 0 or filters not used in interleave mode. >>>>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>>>> + minimum: 0 >>>>>> + maximum: 5 >>>>>> + >>>>>> + st,delay: >>>>>> + description: Filter delay in samples >>>>>> + $ref: /schemas/types.yaml#/definitions/uint32 >>>>>> + maximum: 127 >>>>>> + >>>>>> + st,rs-filter-bypass: >>>>>> + description: Bypass RSFLT reshaping filter. >>>>>> + $ref: /schemas/types.yaml#/definitions/flag >>>>>> + >>>>>> + st,hpf-filter-cutoff-bp: >>>>>> + description: | >>>>>> + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. >>>>>> + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. >>>>>> + If this property is not defined the HPF is disabled. >>>>>> + enum: [625, 1250, 2500, 9500] >>>>>> + >>>>>> + st,sync: >>>>>> + description: >>>>>> + Synchronize to another filter. >>>>>> + Must contain the phandle of the filter providing the synchronization. >>>>>> + allOf: >>>>>> + - $ref: /schemas/types.yaml#/definitions/phandle-array >>>>>> + - maxItems: 1 >>>>>> + >>>>>> + st,sitf: >>>>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>>>> + items: >>>>>> + - items: >>>>>> + - description: Phandle of the serial interface connected to the digital filter >>>>>> + - description: | >>>>>> + The phandle's argument selects the bitstream on the falling or rising edge >>>>>> + of the serial interface clock: >>>>>> + - 0: rising edge >>>>>> + - 1: falling edge >>>>>> + enum: [0, 1] >>>>>> + default: 0 >>>>>> + description: >>>>>> + Should be phandle/bitstream pair. >>>>>> + >>>>>> + required: >>>>>> + - compatible >>>>>> + - reg >>>>>> + - interrupts >>>>>> + - dmas >>>>>> + - dma-names >>>>>> + - "#io-channel-cells" >>>>>> + - "#address-cells" >>>>>> + - "#size-cells" >>>>>> + - st,sitf >>>>>> + >>>>>> + unevaluatedProperties: false >>>>>> + >>>>>> + patternProperties: >>>>>> + "^channel@([0-7])$": >>>>>> + type: object >>>>>> + $ref: adc.yaml >>>>>> + description: Represents the external channel which is connected to the MDF. >>>>>> + >>>>>> + properties: >>>>>> + reg: >>>>>> + maximum: 7 >>>>>> + >>>>>> + io-backends: >>>>>> + description: >>>>>> + Used to pipe external sigma delta modulator or internal ADC backend to MDF >>>>>> + channel. >>>>>> + maxItems: 1 >>> >>>>>> + >>>>>> + required: >>>>>> + - reg >>>>>> + >>>>>> + unevaluatedProperties: false >>>>>> + >>>>>> + allOf: >>>>>> + - if: >>>>>> + properties: >>>>>> + compatible: >>>>>> + contains: >>>>>> + const: st,stm32mp25-mdf-adc >>>>>> + >>>>>> + then: >>>>>> + patternProperties: >>>>>> + "^channel@[0-7]$": >>>>>> + required: >>>>>> + - io-backends >>>>>> + >>>>>> + - if: >>>>>> + properties: >>>>>> + compatible: >>>>>> + contains: >>>>>> + const: st,stm32mp25-mdf-dmic >>>>>> + >>>>>> + then: >>>>>> + patternProperties: >>>>>> + "^mdf-dai+$": >>>>>> + type: object >>>>>> + description: child node >>>>>> + >>>>>> + properties: >>>>>> + compatible: >>>>>> + enum: >>>>>> + - st,stm32mp25-mdf-dai >>>>>> + >>>>>> + "#sound-dai-cells": >>>>>> + const: 0 >>>>>> + >>>>>> + io-channels: >>>>>> + description: >>>>>> + From common IIO binding. Used to pipe external sigma delta >>>>>> + modulator or internal ADC output to MDF channel. >>>>>> + >>>>>> + power-domains: >>>>>> + maxItems: 1 >>>>>> + >>>>>> + port: >>>>>> + $ref: /schemas/sound/audio-graph-port.yaml# >>>>>> + unevaluatedProperties: false >>>>>> + >>>>>> + required: >>>>>> + - compatible >>>>>> + - "#sound-dai-cells" >>>>>> + - io-channels >>>>>> + >>>>>> + additionalProperties: false >>>>>> + >>>>>> +examples: >>>>>> + - | >>>>>> + #include <dt-bindings/clock/st,stm32mp25-rcc.h> >>>>>> + #include <dt-bindings/interrupt-controller/arm-gic.h> >>>>>> + mdf1: mdf@504d0000 { >>>>>> + compatible = "st,stm32mp25-mdf"; >>>>>> + ranges = <0 0x504d0000 0x1000>; >>>>>> + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; >>>>>> + #address-cells = <1>; >>>>>> + #size-cells = <1>; >>>>>> + clocks = <&rcc CK_KER_MDF1>; >>>>>> + clock-names = "ker_ck"; >>>>>> + clock-ranges; >>>>>> + #clock-cells = <1>; >>>>>> + clock-output-names = "cck0", "cck1"; >>>>>> + clock-frequency = <2048000>; >>>>>> + >>>>>> + sitf5: sitf@300 { >>>>>> + compatible = "st,stm32mp25-sitf-mdf"; >>>>>> + reg = <0x300 0x4>; >>>>>> + st,sitf-mode = "spi"; >>>>>> + clocks = <&mdf1 0>; >>>>>> + }; >>>>>> + >>>>>> + filter0: filter@84 { >>>>>> + compatible = "st,stm32mp25-mdf-dmic"; >>>>>> + reg = <0x84 0x70>; >>>>>> + #io-channel-cells = <1>; >>>>>> + interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>; >>>>>> + dmas = <&hpdma 63 0x63 0x12 0>; >>>>>> + dma-names = "rx"; >>>>>> + st,cic-mode = <5>; >>>>>> + st,sitf = <&sitf5 0>; >>>>>> + #address-cells = <1>; >>>>>> + #size-cells = <0>; >>>>>> + >>>>>> + channel@0 { >>>>>> + reg = <0>; >>>>>> + }; >>>>>> + >>>>>> + asoc_pdm0: mdf-dai { >>>>>> + compatible = "st,stm32mp25-mdf-dai"; >>>>>> + #sound-dai-cells = <0>; >>>>>> + io-channels = <&filter0 0>; >>>>>> + }; >>>>>> + }; >>>>>> + >>>>>> + filter1: filter@104 { >>>>>> + compatible = "st,stm32mp25-mdf-adc"; >>>>>> + reg = <0x104 0x70>; >>>>>> + #io-channel-cells = <1>; >>>>>> + interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>; >>>>>> + dmas = <&hpdma 64 0x63 0x12 0>; >>>>>> + dma-names = "rx"; >>>>>> + st,cic-mode = <2>; >>>>>> + st,sitf = <&sitf5 1>; >>>>>> + #address-cells = <1>; >>>>>> + #size-cells = <0>; >>>>>> + >>>>>> + channel@1 { >>>>>> + reg = <1>; >>>>>> + settling-time-us = <1000>; >>>>>> + io-backends = <&sd_adc1>; >>>>>> + }; >>>>>> + }; >>>>>> + }; >>>>>> + >>>>>> +... >>>>>> -- >>>>>> 2.43.0 >>>>>> >>>> >> ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-12 12:56 ` Olivier MOYSAN @ 2026-10-14 15:15 ` Conor Dooley 2026-10-14 16:51 ` Olivier MOYSAN 2026-10-19 1:30 ` Jonathan Cameron 1 sibling, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-14 15:15 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 16944 bytes --] On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: > Hi Conor, > > On 10/9/26 21:12, Conor Dooley wrote: > > On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: > > > Hi Conor, > > > > > > On 10/8/26 12:11, Conor Dooley wrote: > > > > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > > > > > Hi Conor, > > > > > > > > > > Thanks for the review > > > > > > > > > > On 10/1/26 20:32, Conor Dooley wrote: > > > > > > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > > > > > > > Add bindings that describes STM32 MDF settings to support > > > > > > > digital filtering for Pulse Density Modulation (PDM) microphones > > > > > > > and analog sigma delta modulators. > > > > > > > > > > > > > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > > > > > > > --- > > > > > > > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > > > > > > > 1 file changed, 383 insertions(+) > > > > > > > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > > > > > > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > > new file mode 100644 > > > > > > > index 000000000000..f2fbc3e150e8 > > > > > > > --- /dev/null > > > > > > > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > > > > > > @@ -0,0 +1,383 @@ > > > > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > > > > > +%YAML 1.2 > > > > > > > +--- > > > > > > > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > > > > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > > > > > + > > > > > > > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > > > > > > > + > > > > > > > +maintainers: > > > > > > > + - Olivier Moysan <olivier.moysan@foss.st.com> > > > > > > > + > > > > > > > +description: | > > > > > > > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > > > > > > > + interface external sigma delta modulators to STM32 micro controllers. > > > > > > > + > > > > > > > +properties: > > > > > > > + compatible: > > > > > > > + enum: > > > > > > > + - st,stm32mp25-mdf > > > > > > > + - st,stm32mp23-mdf > > > > > > > + > > > > > > > + reg: > > > > > > > + minItems: 1 > > > > > > > + maxItems: 2 > > > > > > > > > > > > This needs an items list here. The size of the regions seems like crap > > > > > > to begin with... > > > > > > > > > > > > > + > > > > > > > + clocks: > > > > > > > + maxItems: 1 > > > > > > > + > > > > > > > + clock-names: > > > > > > > + description: Internal clock used for MDF digital processing. > > > > > > > + items: > > > > > > > + - const: ker_ck > > > > > > > > > > > > This is pointless when you only have one. > > > > > > > > > > > > > > > > I agree that it could be dropped. However, it is useful for using > > > > > devm_regmap_init_mmio_clk. > > > > > > > > Ah, because that function if you pass NULL to it, it doesn't mean no > > > > string, it means no clock. > > > > > > > > > > The MDF has two clocks (AHB clock for register accesses and ker_ck for > > > peripheral processing). However, these two clocks share the same gate. So, > > > only the ker_ck clock is exposed in the driver. > > > > That's incorrect, you should have two clocks in DT if the block has two > > even if they have a shared gate. > > > > This would not be consistent with the architectural choice made for the > STM32MP25. The RCC driver provides an abstraction to manage these two clocks > as one, since they are controlled by the same gate. The binding incorporates > this abstraction to manage only a single clock. > > A large number of peripherals on STM32MP25 have the same architecture and > follow this implementation rule. So managing both clocks in the MDF driver > would create a consistency issue with the other peripherals. Doesn't really matter how you've modelled the clock controller, cos you can just have the same clock be both inputs, and retain a correct model of this hardware? > > > > The regmap api is a convenient way to manage registers and gate the AHB > > > clock only on register accesses. Removing clock-names no longer allows you > > > to benefit from clock management handled by the regmap framework, and means > > > that this must be managed explicitly, partially or entirely, in the driver. > > > > > > > > > > > > > > > + > > > > > > > + "#clock-cells": > > > > > > > + enum: [0, 1] > > > > > > > > > > > > Why is this not fixed? Also why are parts of your own device consuming > > > > > > the clocks? > > > > > > > > Reading the docs, this has to be 1, you have two clocks? > > > > > > > > Not sure why you skipped this and skipped explaining why you are > > > > consuming your own clocks. > > > > > > > > > > Yes, we can have two clocks gated independently but sharing the same rate. > > > > > > Using the clock framework apis seemed to me the right way to manage cck1 and > > > cck0 gating and divider computing. I think I would have to introduce > > > proprietary properties and have to implement code in the driver, that would > > > be handled natively by the framework otherwise. > > > > The CCF is still the right way to do it, especially since CCK0/1 can be > > exported to other devices. I don't believe you need to actually have a > > reference in DT to do this though, plenty of "real" clock controllers > > have only one input clock and hang a whole tree with multiple layers off > > that. > > Down below I mentioned this under "ouroboros devices", I think this kind > > of ability to chose which clock a channel uses is a fairly normal thing > > to do in IIO land, I just dunno what the preferred mechanism is - I just > > know that it is not referencing yourself (probably it's some sort of > > property that you put in a channel node that says 'blah-clock = "cck0"', > > but better that the IIO folks answer. > > > > The adc.yaml binding do not expose clock properties. But maybe IIO experts > can answer about this. > > > > > > > > + clock-output-names: > > > > > > > + description: | > > > > > > > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > > > > > > > + but can be gated independently to save power. > > > > > > > + minItems: 1 > > > > > > > + maxItems: 2 > > > > > > > + oneOf: > > > > > > > + - items: > > > > > > > + - const: cck0 > > > > > > > + - items: > > > > > > > + - const: cck1 > > > > > > > + - items: > > > > > > > + - const: cck0 > > > > > > > + - const: cck1 > > > > > > > + > > > > > > > + clock-frequency: > > > > > > > + description: | > > > > > > > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > > > > > > > + The frequency must be a multiple of the "ker_ck" clock frequency. > > > > > > > + maximum: 25000000 > > > > > > > > > > > > Should not be needed, the consumers request what they need. > > > > > > > > > > > > > > > > The CCKx clock frequency depends on the maximum rate supported by the sigma > > > > > delta converters (for instance a digital mic) and the expected decimation > > > > > ratio on the bitstream. Typically this determines the frequency on the SPI > > > > > bus. > > > > > This rate is defined statically and shared by the CCKx clocks. So IMHO, as > > > > > this rate is unique, it can look strange to let the consumer define it. > > > > > Moreover, it seems to me that clock-frequency is already used to configure > > > > > the frequency of a provider in some other bindings. > > > > > For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml > > > > > > > > This is a binding from the age of antiquity, using it to justify your > > > > use is actually harming your argument rather than helping. Your clock > > > > consumers should be providing the information about what the rate should > > > > be, and if you need to do this in dt you can use assigned-clock-rates. > > > > > > > > > > ok, I will move this to clock consumer with assigned-clock properties. > > > > > > > > So, it's not clear for me, what is the restriction on clock-frequency > > > > > property. > > > > > > > + > > > > > > > + ranges: true > > > > > > > + > > > > > > > + clock-ranges: true > > > > > > > + > > > > > > > + resets: > > > > > > > + maxItems: 1 > > > > > > > + > > > > > > > + reset-names: > > > > > > > + items: > > > > > > > + - const: mdf > > > > > > > > Same applies here as to the clock names fwiw. > > > > > > > > > > Yes, I removed this. > > > > > > > > > > + > > > > > > > + access-controllers: > > > > > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > > > + description: | > > > > > > > + Phandle to the rifsc device to check access right. > > > > > > > + > > > > > > > + power-domains: > > > > > > > + maxItems: 1 > > > > > > > + > > > > > > > + st,interleave: > > > > > > > + description: | > > > > > > > + List of phandles of interleaved filters. The indexes of interleaved filters must be > > > > > > > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > > > > > > > + are muxed in a single channel and retrieved through the device associated to the filter 0. > > > > > > > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > > > > > > > + $ref: /schemas/types.yaml#/definitions/phandle-array > > > > > > > > > > > > No idea what these even are, but this is probably not the right way to > > > > > > represent the relationship between devices. They're apparently ADCs, but > > > > > > this is also an ADC so I'm not sure what's going on here at all. > > > > > > > > Yeah, after more thought this should not be done like this at all, > > > > especially if these filters the phandle point to are part of this device > > > > itself, which I suspect they are. If that's the case, you don't need > > > > phandles to even do this, you just need an int that says what N is. > > > > > > > > > > Yes, can be an index as it is an internal reference. I will change this. > > > > > > > > > > > > > > > > + > > > > > > > +required: > > > > > > > + - compatible > > > > > > > + - reg > > > > > > > + - ranges > > > > > > > + - clocks > > > > > > > + - clock-names > > > > > > > + - clock-ranges > > > > > > > + - "#address-cells" > > > > > > > + - "#size-cells" > > > > > > > + > > > > > > > +additionalProperties: false > > > > > > > + > > > > > > > +patternProperties: > > > > > > > + "^sitf@[0-9]+$": > > > > > > > + type: object > > > > > > > + description: Serial interface child node > > > > > > > > > > > > Why is this a child node at all? > > > > > > Probably not worth reviewing more without a link to the docs for this > > > > > > device so I can figure out what on earth is going on! > > > > > > > > > > > > > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > > > > > analog-to-digital converter itself. > > > > > > > > > > Here is the link to STM32MP25 reference manuel > > > > > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > > > > > Chapter 45: Multi-function digital filter (MDF) > > > > > > > > > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > > > > > filters (DFLT) which can be connected through a multiplexer. > > > > > > > > > > Below is a schematic view of typical applications targeted by this > > > > > peripheral > > > > > > > > > > > > > > > Audio use case: > > > > > > > > > > mdf > > > > > +-------------------------------------+ > > > > > +------+ | +------+ +------+ +------+ | > > > > > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > > > > > +------+ | +------+ +------+ +------+ | > > > > > +-------------------------------------+ > > > > > > > > > > For instance, in an audio use case the serial interface can be configured to > > > > > provide the clock to the digital microphone (cck0, cck1 or both) at a common > > > > > predefined rate, and to retrieve the PDM samples. > > > > > The serial interface provides this samples to a digital filter, which > > > > > delivers PCM samples on its output. > > > > > > > > > > > > > > > Analog use case: > > > > > > > > > > mdf > > > > > +-------------------------------------+ > > > > > +--------+ | +------+ +------+ +------+ | > > > > > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > > > > > +--------+ | +------+ +------+ +------+ | > > > > > +-------------------------------------+ > > > > > > > > > > > > So, looking at the docs and a brief chat with Jonathan about this > > > > device, I believe you've got things backwards and this is actually the backend, > > > > and the adc should be the one populating the io-backends property > > > > pointing to this device. You should have io-backend-cells, and I assume > > > > that there should be a cell for the adc to select which dlft it is connected > > > > to. > > > > > > > > > > There have already been lengthy discussions in the past about a DFSDM > > > peripheral on STM32MP1, which has features similar to those of the MDF and > > > similar implementation constraints. For the DFSDM, a solution based on an > > > IIO backend had been upstreamed. The MDF follows the same architecture. I > > > need to take a little time to dive back into this issue. > > > > One thing to note there is that you retrofitted the backends onto that > > device, and the original design here is much older (it's a text > > binding). > > > > > > > > > > DFSDM sources: > > > drivers/iio/adc/stm32-dfsdm-adc.c > > > drivers/iio/adc/stm32-dfsdm-core.c > > > > > > Here is a sample of DFSDM DT > > > > > > sd_adc0: simple-sd-adc0 { > > > compatible = "sd-modulator"; > > > #io-backend-cells = <0>; > > > vref-supply = <&v3v3>; > > > > Yeah, pretty sure this is wrong (backwards). The backend is the thing > > that gets data from an ADC not the ADC. > > > > The backend framework was introduced to implement complex IIO aggregate > devices. The hardwares that were driving this need were analog device ad9467 > and ST DFSDM. > > https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff > > From drivers/iio/industrialio-backend.c: > > "The typical architecture is to have one device as the frontend device which > can be "linked" against one or multiple backend devices. All the IIO and > userspace interface is expected to be registers/managed by the frontend > device which will callback into the backends when needed (to get/set some > configuration that it does not directly control)." > > * --------------------- > * ------------------ | ------------ > * | ADC |-----------------| | ADC CORE | > * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- > * | |-----------------| ------------ > * ------------------ --------------------- > > The MDF (or DFSDM) use case, follows this topology: > - The SD modulator (ADC core) registers in backend framework > - The MDF registers in IIO framework and exposes the IIO devices > It also get configuration (ref voltage) from SD modulator, to compute > scaling. > > I agree that if we consider the terms frontend and backend, the elements in > the data flow do not have the roles that we would naturally expect. However, > if we consider the expected role of the elements using the iio-backend > framework, the usage seems coherent to me. I didn't even get as far as sd modulators or whatever, if I understand correctly the ADC inputs on this device are fed by the onboard ADC? (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) In that case, I can't really see how it makes sense for the primary iio device to change when data is fed back through the mdf or taken directly from the ADC itself, particularly given how that would affect the userspace interface. The "serial" side of this seems in a similar vein to the adi,axi-adc stuff, which when considered with the ADC inputs, really does give me the impression this is backwards. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-14 15:15 ` Conor Dooley @ 2026-10-14 16:51 ` Olivier MOYSAN 2026-10-14 22:49 ` Conor Dooley 0 siblings, 1 reply; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-14 16:51 UTC (permalink / raw) To: Conor Dooley Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On 10/14/26 17:15, Conor Dooley wrote: > On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: >> Hi Conor, >> >> On 10/9/26 21:12, Conor Dooley wrote: >>> On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: >>>> Hi Conor, >>>> >>>> On 10/8/26 12:11, Conor Dooley wrote: >>>>> On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >>>>>> Hi Conor, >>>>>> >>>>>> Thanks for the review >>>>>> >>>>>> On 10/1/26 20:32, Conor Dooley wrote: >>>>>>> On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >>>>>>>> Add bindings that describes STM32 MDF settings to support >>>>>>>> digital filtering for Pulse Density Modulation (PDM) microphones >>>>>>>> and analog sigma delta modulators. >>>>>>>> >>>>>>>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >>>>>>>> --- >>>>>>>> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >>>>>>>> 1 file changed, 383 insertions(+) >>>>>>>> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>>>> >>>>>>>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>>>> new file mode 100644 >>>>>>>> index 000000000000..f2fbc3e150e8 >>>>>>>> --- /dev/null >>>>>>>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>>>>>>> @@ -0,0 +1,383 @@ >>>>>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>>>>>>> +%YAML 1.2 >>>>>>>> +--- >>>>>>>> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >>>>>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>>>>>>> + >>>>>>>> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >>>>>>>> + >>>>>>>> +maintainers: >>>>>>>> + - Olivier Moysan <olivier.moysan@foss.st.com> >>>>>>>> + >>>>>>>> +description: | >>>>>>>> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >>>>>>>> + interface external sigma delta modulators to STM32 micro controllers. >>>>>>>> + >>>>>>>> +properties: >>>>>>>> + compatible: >>>>>>>> + enum: >>>>>>>> + - st,stm32mp25-mdf >>>>>>>> + - st,stm32mp23-mdf >>>>>>>> + >>>>>>>> + reg: >>>>>>>> + minItems: 1 >>>>>>>> + maxItems: 2 >>>>>>> >>>>>>> This needs an items list here. The size of the regions seems like crap >>>>>>> to begin with... >>>>>>> >>>>>>>> + >>>>>>>> + clocks: >>>>>>>> + maxItems: 1 >>>>>>>> + >>>>>>>> + clock-names: >>>>>>>> + description: Internal clock used for MDF digital processing. >>>>>>>> + items: >>>>>>>> + - const: ker_ck >>>>>>> >>>>>>> This is pointless when you only have one. >>>>>>> >>>>>> >>>>>> I agree that it could be dropped. However, it is useful for using >>>>>> devm_regmap_init_mmio_clk. >>>>> >>>>> Ah, because that function if you pass NULL to it, it doesn't mean no >>>>> string, it means no clock. >>>>> >>>> >>>> The MDF has two clocks (AHB clock for register accesses and ker_ck for >>>> peripheral processing). However, these two clocks share the same gate. So, >>>> only the ker_ck clock is exposed in the driver. >>> >>> That's incorrect, you should have two clocks in DT if the block has two >>> even if they have a shared gate. >>> >> >> This would not be consistent with the architectural choice made for the >> STM32MP25. The RCC driver provides an abstraction to manage these two clocks >> as one, since they are controlled by the same gate. The binding incorporates >> this abstraction to manage only a single clock. >> >> A large number of peripherals on STM32MP25 have the same architecture and >> follow this implementation rule. So managing both clocks in the MDF driver >> would create a consistency issue with the other peripherals. > > Doesn't really matter how you've modelled the clock controller, cos you > can just have the same clock be both inputs, and retain a correct model > of this hardware? > >> >>>> The regmap api is a convenient way to manage registers and gate the AHB >>>> clock only on register accesses. Removing clock-names no longer allows you >>>> to benefit from clock management handled by the regmap framework, and means >>>> that this must be managed explicitly, partially or entirely, in the driver. >>>> >>>>>> >>>>>>>> + >>>>>>>> + "#clock-cells": >>>>>>>> + enum: [0, 1] >>>>>>> >>>>>>> Why is this not fixed? Also why are parts of your own device consuming >>>>>>> the clocks? >>>>> >>>>> Reading the docs, this has to be 1, you have two clocks? >>>>> >>>>> Not sure why you skipped this and skipped explaining why you are >>>>> consuming your own clocks. >>>>> >>>> >>>> Yes, we can have two clocks gated independently but sharing the same rate. >>>> >>>> Using the clock framework apis seemed to me the right way to manage cck1 and >>>> cck0 gating and divider computing. I think I would have to introduce >>>> proprietary properties and have to implement code in the driver, that would >>>> be handled natively by the framework otherwise. >>> >>> The CCF is still the right way to do it, especially since CCK0/1 can be >>> exported to other devices. I don't believe you need to actually have a >>> reference in DT to do this though, plenty of "real" clock controllers >>> have only one input clock and hang a whole tree with multiple layers off >>> that. >>> Down below I mentioned this under "ouroboros devices", I think this kind >>> of ability to chose which clock a channel uses is a fairly normal thing >>> to do in IIO land, I just dunno what the preferred mechanism is - I just >>> know that it is not referencing yourself (probably it's some sort of >>> property that you put in a channel node that says 'blah-clock = "cck0"', >>> but better that the IIO folks answer. >>> >> >> The adc.yaml binding do not expose clock properties. But maybe IIO experts >> can answer about this. >> >>>>>>>> + clock-output-names: >>>>>>>> + description: | >>>>>>>> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >>>>>>>> + but can be gated independently to save power. >>>>>>>> + minItems: 1 >>>>>>>> + maxItems: 2 >>>>>>>> + oneOf: >>>>>>>> + - items: >>>>>>>> + - const: cck0 >>>>>>>> + - items: >>>>>>>> + - const: cck1 >>>>>>>> + - items: >>>>>>>> + - const: cck0 >>>>>>>> + - const: cck1 >>>>>>>> + >>>>>>>> + clock-frequency: >>>>>>>> + description: | >>>>>>>> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >>>>>>>> + The frequency must be a multiple of the "ker_ck" clock frequency. >>>>>>>> + maximum: 25000000 >>>>>>> >>>>>>> Should not be needed, the consumers request what they need. >>>>>>> >>>>>> >>>>>> The CCKx clock frequency depends on the maximum rate supported by the sigma >>>>>> delta converters (for instance a digital mic) and the expected decimation >>>>>> ratio on the bitstream. Typically this determines the frequency on the SPI >>>>>> bus. >>>>>> This rate is defined statically and shared by the CCKx clocks. So IMHO, as >>>>>> this rate is unique, it can look strange to let the consumer define it. >>>>>> Moreover, it seems to me that clock-frequency is already used to configure >>>>>> the frequency of a provider in some other bindings. >>>>>> For instance: Documentation/devicetree/bindings/clock/silabs,si570.yaml >>>>> >>>>> This is a binding from the age of antiquity, using it to justify your >>>>> use is actually harming your argument rather than helping. Your clock >>>>> consumers should be providing the information about what the rate should >>>>> be, and if you need to do this in dt you can use assigned-clock-rates. >>>>> >>>> >>>> ok, I will move this to clock consumer with assigned-clock properties. >>>> >>>>>> So, it's not clear for me, what is the restriction on clock-frequency >>>>>> property. >>>>>>>> + >>>>>>>> + ranges: true >>>>>>>> + >>>>>>>> + clock-ranges: true >>>>>>>> + >>>>>>>> + resets: >>>>>>>> + maxItems: 1 >>>>>>>> + >>>>>>>> + reset-names: >>>>>>>> + items: >>>>>>>> + - const: mdf >>>>> >>>>> Same applies here as to the clock names fwiw. >>>>> >>>> >>>> Yes, I removed this. >>>> >>>>>>>> + >>>>>>>> + access-controllers: >>>>>>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>>>>>> + description: | >>>>>>>> + Phandle to the rifsc device to check access right. >>>>>>>> + >>>>>>>> + power-domains: >>>>>>>> + maxItems: 1 >>>>>>>> + >>>>>>>> + st,interleave: >>>>>>>> + description: | >>>>>>>> + List of phandles of interleaved filters. The indexes of interleaved filters must be >>>>>>>> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >>>>>>>> + are muxed in a single channel and retrieved through the device associated to the filter 0. >>>>>>>> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >>>>>>>> + $ref: /schemas/types.yaml#/definitions/phandle-array >>>>>>> >>>>>>> No idea what these even are, but this is probably not the right way to >>>>>>> represent the relationship between devices. They're apparently ADCs, but >>>>>>> this is also an ADC so I'm not sure what's going on here at all. >>>>> >>>>> Yeah, after more thought this should not be done like this at all, >>>>> especially if these filters the phandle point to are part of this device >>>>> itself, which I suspect they are. If that's the case, you don't need >>>>> phandles to even do this, you just need an int that says what N is. >>>>> >>>> >>>> Yes, can be an index as it is an internal reference. I will change this. >>>> >>>>>>> >>>>>>>> + >>>>>>>> +required: >>>>>>>> + - compatible >>>>>>>> + - reg >>>>>>>> + - ranges >>>>>>>> + - clocks >>>>>>>> + - clock-names >>>>>>>> + - clock-ranges >>>>>>>> + - "#address-cells" >>>>>>>> + - "#size-cells" >>>>>>>> + >>>>>>>> +additionalProperties: false >>>>>>>> + >>>>>>>> +patternProperties: >>>>>>>> + "^sitf@[0-9]+$": >>>>>>>> + type: object >>>>>>>> + description: Serial interface child node >>>>>>> >>>>>>> Why is this a child node at all? >>>>>>> Probably not worth reviewing more without a link to the docs for this >>>>>>> device so I can figure out what on earth is going on! >>>>>>> >>>>>> >>>>>> The MDF is a digital filter for sigma-delta bitstreams, rather than the >>>>>> analog-to-digital converter itself. >>>>>> >>>>>> Here is the link to STM32MP25 reference manuel >>>>>> https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf >>>>>> Chapter 45: Multi-function digital filter (MDF) >>>>>> >>>>>> On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital >>>>>> filters (DFLT) which can be connected through a multiplexer. >>>>>> >>>>>> Below is a schematic view of typical applications targeted by this >>>>>> peripheral >>>>>> >>>>>> >>>>>> Audio use case: >>>>>> >>>>>> mdf >>>>>> +-------------------------------------+ >>>>>> +------+ | +------+ +------+ +------+ | >>>>>> | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device >>>>>> +------+ | +------+ +------+ +------+ | >>>>>> +-------------------------------------+ >>>>>> >>>>>> For instance, in an audio use case the serial interface can be configured to >>>>>> provide the clock to the digital microphone (cck0, cck1 or both) at a common >>>>>> predefined rate, and to retrieve the PDM samples. >>>>>> The serial interface provides this samples to a digital filter, which >>>>>> delivers PCM samples on its output. >>>>>> >>>>>> >>>>>> Analog use case: >>>>>> >>>>>> mdf >>>>>> +-------------------------------------+ >>>>>> +--------+ | +------+ +------+ +------+ | >>>>>> | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device >>>>>> +--------+ | +------+ +------+ +------+ | >>>>>> +-------------------------------------+ >>>>> >>>>> >>>>> So, looking at the docs and a brief chat with Jonathan about this >>>>> device, I believe you've got things backwards and this is actually the backend, >>>>> and the adc should be the one populating the io-backends property >>>>> pointing to this device. You should have io-backend-cells, and I assume >>>>> that there should be a cell for the adc to select which dlft it is connected >>>>> to. >>>>> >>>> >>>> There have already been lengthy discussions in the past about a DFSDM >>>> peripheral on STM32MP1, which has features similar to those of the MDF and >>>> similar implementation constraints. For the DFSDM, a solution based on an >>>> IIO backend had been upstreamed. The MDF follows the same architecture. I >>>> need to take a little time to dive back into this issue. >>> >>> One thing to note there is that you retrofitted the backends onto that >>> device, and the original design here is much older (it's a text >>> binding). >>> >>> >>>> >>>> DFSDM sources: >>>> drivers/iio/adc/stm32-dfsdm-adc.c >>>> drivers/iio/adc/stm32-dfsdm-core.c >>>> >>>> Here is a sample of DFSDM DT >>>> >>>> sd_adc0: simple-sd-adc0 { >>>> compatible = "sd-modulator"; >>>> #io-backend-cells = <0>; >>>> vref-supply = <&v3v3>; >>> >>> Yeah, pretty sure this is wrong (backwards). The backend is the thing >>> that gets data from an ADC not the ADC. >>> >> >> The backend framework was introduced to implement complex IIO aggregate >> devices. The hardwares that were driving this need were analog device ad9467 >> and ST DFSDM. >> >> https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff >> >> From drivers/iio/industrialio-backend.c: >> >> "The typical architecture is to have one device as the frontend device which >> can be "linked" against one or multiple backend devices. All the IIO and >> userspace interface is expected to be registers/managed by the frontend >> device which will callback into the backends when needed (to get/set some >> configuration that it does not directly control)." >> >> * --------------------- >> * ------------------ | ------------ >> * | ADC |-----------------| | ADC CORE | >> * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- >> * | |-----------------| ------------ >> * ------------------ --------------------- >> >> The MDF (or DFSDM) use case, follows this topology: >> - The SD modulator (ADC core) registers in backend framework >> - The MDF registers in IIO framework and exposes the IIO devices >> It also get configuration (ref voltage) from SD modulator, to compute >> scaling. >> >> I agree that if we consider the terms frontend and backend, the elements in >> the data flow do not have the roles that we would naturally expect. However, >> if we consider the expected role of the elements using the iio-backend >> framework, the usage seems coherent to me. > > I didn't even get as far as sd modulators or whatever, if I understand > correctly the ADC inputs on this device are fed by the onboard ADC? > (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) > In that case, I can't really see how it makes sense for the primary iio > device to change when data is fed back through the mdf or taken > directly from the ADC itself, particularly given how that would affect > the userspace interface. > > The "serial" side of this seems in a similar vein to the adi,axi-adc > stuff, which when considered with the ADC inputs, really does give me > the impression this is backwards. Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, and these can be connected to the MDF via a dedicated interface. (but not the serial interface). However, this use case is not supported by the driver. Only sigma-delta modulators, external to the SoC and connected via the serial interface, are supported. On ST boards, the only available SD modulators are digital microphones. Anyway, if the internal ADC to MDF use case was supported, the issue would be the same. The whole ADC + MDF set would be presented at the interface as an aggregated device, and the ADC data would not be directly accessible to the user. BRs Olivier ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-14 16:51 ` Olivier MOYSAN @ 2026-10-14 22:49 ` Conor Dooley 2026-10-15 9:19 ` Olivier MOYSAN 0 siblings, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-14 22:49 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 9728 bytes --] On Wed, Oct 14, 2026 at 06:51:45PM +0200, Olivier MOYSAN wrote: > On 10/14/26 17:15, Conor Dooley wrote: > > On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: > > > On 10/9/26 21:12, Conor Dooley wrote: > > > > On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: > > > > > On 10/8/26 12:11, Conor Dooley wrote: > > > > > > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > > > > > > > On 10/1/26 20:32, Conor Dooley wrote: > > > > > > > > > > > > > > > > > + > > > > > > > > > +required: > > > > > > > > > + - compatible > > > > > > > > > + - reg > > > > > > > > > + - ranges > > > > > > > > > + - clocks > > > > > > > > > + - clock-names > > > > > > > > > + - clock-ranges > > > > > > > > > + - "#address-cells" > > > > > > > > > + - "#size-cells" > > > > > > > > > + > > > > > > > > > +additionalProperties: false > > > > > > > > > + > > > > > > > > > +patternProperties: > > > > > > > > > + "^sitf@[0-9]+$": > > > > > > > > > + type: object > > > > > > > > > + description: Serial interface child node > > > > > > > > > > > > > > > > Why is this a child node at all? > > > > > > > > Probably not worth reviewing more without a link to the docs for this > > > > > > > > device so I can figure out what on earth is going on! > > > > > > > > > > > > > > > > > > > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > > > > > > > analog-to-digital converter itself. > > > > > > > > > > > > > > Here is the link to STM32MP25 reference manuel > > > > > > > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > > > > > > > Chapter 45: Multi-function digital filter (MDF) > > > > > > > > > > > > > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > > > > > > > filters (DFLT) which can be connected through a multiplexer. > > > > > > > > > > > > > > Below is a schematic view of typical applications targeted by this > > > > > > > peripheral > > > > > > > > > > > > > > > > > > > > > Audio use case: > > > > > > > > > > > > > > mdf > > > > > > > +-------------------------------------+ > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > For instance, in an audio use case the serial interface can be configured to > > > > > > > provide the clock to the digital microphone (cck0, cck1 or both) at a common > > > > > > > predefined rate, and to retrieve the PDM samples. > > > > > > > The serial interface provides this samples to a digital filter, which > > > > > > > delivers PCM samples on its output. > > > > > > > > > > > > > > > > > > > > > Analog use case: > > > > > > > > > > > > > > mdf > > > > > > > +-------------------------------------+ > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > > > > > So, looking at the docs and a brief chat with Jonathan about this > > > > > > device, I believe you've got things backwards and this is actually the backend, > > > > > > and the adc should be the one populating the io-backends property > > > > > > pointing to this device. You should have io-backend-cells, and I assume > > > > > > that there should be a cell for the adc to select which dlft it is connected > > > > > > to. > > > > > > > > > > > > > > > > There have already been lengthy discussions in the past about a DFSDM > > > > > peripheral on STM32MP1, which has features similar to those of the MDF and > > > > > similar implementation constraints. For the DFSDM, a solution based on an > > > > > IIO backend had been upstreamed. The MDF follows the same architecture. I > > > > > need to take a little time to dive back into this issue. > > > > > > > > One thing to note there is that you retrofitted the backends onto that > > > > device, and the original design here is much older (it's a text > > > > binding). > > > > > > > > > > > > > > > > > > DFSDM sources: > > > > > drivers/iio/adc/stm32-dfsdm-adc.c > > > > > drivers/iio/adc/stm32-dfsdm-core.c > > > > > > > > > > Here is a sample of DFSDM DT > > > > > > > > > > sd_adc0: simple-sd-adc0 { > > > > > compatible = "sd-modulator"; > > > > > #io-backend-cells = <0>; > > > > > vref-supply = <&v3v3>; > > > > > > > > Yeah, pretty sure this is wrong (backwards). The backend is the thing > > > > that gets data from an ADC not the ADC. > > > > > > > > > > The backend framework was introduced to implement complex IIO aggregate > > > devices. The hardwares that were driving this need were analog device ad9467 > > > and ST DFSDM. > > > > > > https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff > > > > > > From drivers/iio/industrialio-backend.c: > > > > > > "The typical architecture is to have one device as the frontend device which > > > can be "linked" against one or multiple backend devices. All the IIO and > > > userspace interface is expected to be registers/managed by the frontend > > > device which will callback into the backends when needed (to get/set some > > > configuration that it does not directly control)." > > > > > > * --------------------- > > > * ------------------ | ------------ > > > * | ADC |-----------------| | ADC CORE | > > > * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- > > > * | |-----------------| ------------ > > > * ------------------ --------------------- > > > > > > The MDF (or DFSDM) use case, follows this topology: > > > - The SD modulator (ADC core) registers in backend framework > > > - The MDF registers in IIO framework and exposes the IIO devices > > > It also get configuration (ref voltage) from SD modulator, to compute > > > scaling. > > > > > > I agree that if we consider the terms frontend and backend, the elements in > > > the data flow do not have the roles that we would naturally expect. However, > > > if we consider the expected role of the elements using the iio-backend > > > framework, the usage seems coherent to me. > > > > I didn't even get as far as sd modulators or whatever, if I understand > > correctly the ADC inputs on this device are fed by the onboard ADC? > > (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) > > In that case, I can't really see how it makes sense for the primary iio > > device to change when data is fed back through the mdf or taken > > directly from the ADC itself, particularly given how that would affect > > the userspace interface. > > > > The "serial" side of this seems in a similar vein to the adi,axi-adc > > stuff, which when considered with the ADC inputs, really does give me > > the impression this is backwards. > > Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, > and these can be connected to the MDF via a dedicated interface. (but not > the serial interface). > > However, this use case is not supported by the driver. Only sigma-delta > modulators, external to the SoC and connected via the serial interface, are > supported. On ST boards, the only available SD modulators are digital > microphones. Quite frankly, I don't care what you are choosing to implement in the driver or what your first-party boards support. The binding must represent the capabilities of the device, not what subset you deem relevant at this point in time. I'm not going to ack anything that does not consider all use cases for the device, especially since I the more I look the more I am convinced that this is the wrong way to model the relationship between devices and therefore intentionally ignoring a use case is likely to be problematic when someone does decide that they want to use that feature. > Anyway, if the internal ADC to MDF use case was supported, the issue would > be the same. The whole ADC + MDF set would be presented at the interface as > an aggregated device, and the ADC data would not be directly accessible to > the user. Of course, that's what I was talking about when I said: | In that case, I can't really see how it makes sense for the primary iio | device to change when data is fed back through the mdf or taken | directly from the ADC itself, particularly given how that would affect | the userspace interface. To me, in that ADC to MDF use case, the frontend portion of the aggregate device presented to userspace needs to be the ADC and the MDF needs to be the backend, since otherwise the ADC will simultaneously be frontend and backend, depending on which channel is considered. That makes no sense to me when the MDF can always be the backend, for all use cases and avoid that sort of problem entirely. I've heard no argument as to why the MDF cannot be a backend, just that you don't want to because the previous device didn't, but copying what was done before isn't a justification that bears weight if how it was done before isn't the way it should be done. Thanks, Conor. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-14 22:49 ` Conor Dooley @ 2026-10-15 9:19 ` Olivier MOYSAN 2026-10-15 12:34 ` Conor Dooley 0 siblings, 1 reply; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-15 9:19 UTC (permalink / raw) To: Conor Dooley Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Conor, On 10/15/26 00:49, Conor Dooley wrote: > On Wed, Oct 14, 2026 at 06:51:45PM +0200, Olivier MOYSAN wrote: >> On 10/14/26 17:15, Conor Dooley wrote: >>> On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: >>>> On 10/9/26 21:12, Conor Dooley wrote: >>>>> On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: >>>>>> On 10/8/26 12:11, Conor Dooley wrote: >>>>>>> On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >>>>>>>> On 10/1/26 20:32, Conor Dooley wrote: >>>>>>>>> >>>>>>>>>> + >>>>>>>>>> +required: >>>>>>>>>> + - compatible >>>>>>>>>> + - reg >>>>>>>>>> + - ranges >>>>>>>>>> + - clocks >>>>>>>>>> + - clock-names >>>>>>>>>> + - clock-ranges >>>>>>>>>> + - "#address-cells" >>>>>>>>>> + - "#size-cells" >>>>>>>>>> + >>>>>>>>>> +additionalProperties: false >>>>>>>>>> + >>>>>>>>>> +patternProperties: >>>>>>>>>> + "^sitf@[0-9]+$": >>>>>>>>>> + type: object >>>>>>>>>> + description: Serial interface child node >>>>>>>>> >>>>>>>>> Why is this a child node at all? >>>>>>>>> Probably not worth reviewing more without a link to the docs for this >>>>>>>>> device so I can figure out what on earth is going on! >>>>>>>>> >>>>>>>> >>>>>>>> The MDF is a digital filter for sigma-delta bitstreams, rather than the >>>>>>>> analog-to-digital converter itself. >>>>>>>> >>>>>>>> Here is the link to STM32MP25 reference manuel >>>>>>>> https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf >>>>>>>> Chapter 45: Multi-function digital filter (MDF) >>>>>>>> >>>>>>>> On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital >>>>>>>> filters (DFLT) which can be connected through a multiplexer. >>>>>>>> >>>>>>>> Below is a schematic view of typical applications targeted by this >>>>>>>> peripheral >>>>>>>> >>>>>>>> >>>>>>>> Audio use case: >>>>>>>> >>>>>>>> mdf >>>>>>>> +-------------------------------------+ >>>>>>>> +------+ | +------+ +------+ +------+ | >>>>>>>> | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device >>>>>>>> +------+ | +------+ +------+ +------+ | >>>>>>>> +-------------------------------------+ >>>>>>>> >>>>>>>> For instance, in an audio use case the serial interface can be configured to >>>>>>>> provide the clock to the digital microphone (cck0, cck1 or both) at a common >>>>>>>> predefined rate, and to retrieve the PDM samples. >>>>>>>> The serial interface provides this samples to a digital filter, which >>>>>>>> delivers PCM samples on its output. >>>>>>>> >>>>>>>> >>>>>>>> Analog use case: >>>>>>>> >>>>>>>> mdf >>>>>>>> +-------------------------------------+ >>>>>>>> +--------+ | +------+ +------+ +------+ | >>>>>>>> | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device >>>>>>>> +--------+ | +------+ +------+ +------+ | >>>>>>>> +-------------------------------------+ >>>>>>> >>>>>>> >>>>>>> So, looking at the docs and a brief chat with Jonathan about this >>>>>>> device, I believe you've got things backwards and this is actually the backend, >>>>>>> and the adc should be the one populating the io-backends property >>>>>>> pointing to this device. You should have io-backend-cells, and I assume >>>>>>> that there should be a cell for the adc to select which dlft it is connected >>>>>>> to. >>>>>>> >>>>>> >>>>>> There have already been lengthy discussions in the past about a DFSDM >>>>>> peripheral on STM32MP1, which has features similar to those of the MDF and >>>>>> similar implementation constraints. For the DFSDM, a solution based on an >>>>>> IIO backend had been upstreamed. The MDF follows the same architecture. I >>>>>> need to take a little time to dive back into this issue. >>>>> >>>>> One thing to note there is that you retrofitted the backends onto that >>>>> device, and the original design here is much older (it's a text >>>>> binding). >>>>> >>>>> >>>>>> >>>>>> DFSDM sources: >>>>>> drivers/iio/adc/stm32-dfsdm-adc.c >>>>>> drivers/iio/adc/stm32-dfsdm-core.c >>>>>> >>>>>> Here is a sample of DFSDM DT >>>>>> >>>>>> sd_adc0: simple-sd-adc0 { >>>>>> compatible = "sd-modulator"; >>>>>> #io-backend-cells = <0>; >>>>>> vref-supply = <&v3v3>; >>>>> >>>>> Yeah, pretty sure this is wrong (backwards). The backend is the thing >>>>> that gets data from an ADC not the ADC. >>>>> >>>> >>>> The backend framework was introduced to implement complex IIO aggregate >>>> devices. The hardwares that were driving this need were analog device ad9467 >>>> and ST DFSDM. >>>> >>>> https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff >>>> >>>> From drivers/iio/industrialio-backend.c: >>>> >>>> "The typical architecture is to have one device as the frontend device which >>>> can be "linked" against one or multiple backend devices. All the IIO and >>>> userspace interface is expected to be registers/managed by the frontend >>>> device which will callback into the backends when needed (to get/set some >>>> configuration that it does not directly control)." >>>> >>>> * --------------------- >>>> * ------------------ | ------------ >>>> * | ADC |-----------------| | ADC CORE | >>>> * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- >>>> * | |-----------------| ------------ >>>> * ------------------ --------------------- >>>> >>>> The MDF (or DFSDM) use case, follows this topology: >>>> - The SD modulator (ADC core) registers in backend framework >>>> - The MDF registers in IIO framework and exposes the IIO devices >>>> It also get configuration (ref voltage) from SD modulator, to compute >>>> scaling. >>>> >>>> I agree that if we consider the terms frontend and backend, the elements in >>>> the data flow do not have the roles that we would naturally expect. However, >>>> if we consider the expected role of the elements using the iio-backend >>>> framework, the usage seems coherent to me. >>> >>> I didn't even get as far as sd modulators or whatever, if I understand >>> correctly the ADC inputs on this device are fed by the onboard ADC? >>> (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) >>> In that case, I can't really see how it makes sense for the primary iio >>> device to change when data is fed back through the mdf or taken >>> directly from the ADC itself, particularly given how that would affect >>> the userspace interface. >>> >>> The "serial" side of this seems in a similar vein to the adi,axi-adc >>> stuff, which when considered with the ADC inputs, really does give me >>> the impression this is backwards. >> >> Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, >> and these can be connected to the MDF via a dedicated interface. (but not >> the serial interface). >> >> However, this use case is not supported by the driver. Only sigma-delta >> modulators, external to the SoC and connected via the serial interface, are >> supported. On ST boards, the only available SD modulators are digital >> microphones. > > Quite frankly, I don't care what you are choosing to implement in the > driver or what your first-party boards support. The binding must > represent the capabilities of the device, not what subset you deem > relevant at this point in time. I'm not going to ack anything that does > not consider all use cases for the device, especially since I the more I > look the more I am convinced that this is the wrong way to model the > relationship between devices and therefore intentionally ignoring a use case > is likely to be problematic when someone does decide that they want to use > that feature. > >> Anyway, if the internal ADC to MDF use case was supported, the issue would >> be the same. The whole ADC + MDF set would be presented at the interface as >> an aggregated device, and the ADC data would not be directly accessible to >> the user. > > Of course, that's what I was talking about when I said: > | In that case, I can't really see how it makes sense for the primary iio > | device to change when data is fed back through the mdf or taken > | directly from the ADC itself, particularly given how that would affect > | the userspace interface. > > To me, in that ADC to MDF use case, the frontend portion of the aggregate > device presented to userspace needs to be the ADC and the MDF needs to be > the backend, since otherwise the ADC will simultaneously be frontend and > backend, depending on which channel is considered. That makes no sense to me > when the MDF can always be the backend, for all use cases and avoid that > sort of problem entirely. > I've heard no argument as to why the MDF cannot be a backend, just that you > don't want to because the previous device didn't, but copying what was > done before isn't a justification that bears weight if how it was done > before isn't the way it should be done. > These topology problems were discussed at length in the case of DFSDM. The main blocking point being support for interleaved channels (scan mode), a problematic issue that is still found with MDF. The constraints that led to this approach are in the following thread: https://lore.kernel.org/all/20210919191414.09270f4e@jic23-huawei/ FYI: An implementation attempt had been made also via the "concverter framework" proposal, but this approach has been abandoned in favor of the backend framework. https://marc.info/?l=linux-iio&m=169347396021802&w=2 BRs Olivier > Thanks, > Conor. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-15 9:19 ` Olivier MOYSAN @ 2026-10-15 12:34 ` Conor Dooley 2026-10-19 1:25 ` Jonathan Cameron 0 siblings, 1 reply; 31+ messages in thread From: Conor Dooley @ 2026-10-15 12:34 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 12250 bytes --] On Thu, Oct 15, 2026 at 11:19:19AM +0200, Olivier MOYSAN wrote: > Hi Conor, > > On 10/15/26 00:49, Conor Dooley wrote: > > On Wed, Oct 14, 2026 at 06:51:45PM +0200, Olivier MOYSAN wrote: > > > On 10/14/26 17:15, Conor Dooley wrote: > > > > On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: > > > > > On 10/9/26 21:12, Conor Dooley wrote: > > > > > > On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: > > > > > > > On 10/8/26 12:11, Conor Dooley wrote: > > > > > > > > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > > > > > > > > > On 10/1/26 20:32, Conor Dooley wrote: > > > > > > > > > > > > > > > > > > > > > + > > > > > > > > > > > +required: > > > > > > > > > > > + - compatible > > > > > > > > > > > + - reg > > > > > > > > > > > + - ranges > > > > > > > > > > > + - clocks > > > > > > > > > > > + - clock-names > > > > > > > > > > > + - clock-ranges > > > > > > > > > > > + - "#address-cells" > > > > > > > > > > > + - "#size-cells" > > > > > > > > > > > + > > > > > > > > > > > +additionalProperties: false > > > > > > > > > > > + > > > > > > > > > > > +patternProperties: > > > > > > > > > > > + "^sitf@[0-9]+$": > > > > > > > > > > > + type: object > > > > > > > > > > > + description: Serial interface child node > > > > > > > > > > > > > > > > > > > > Why is this a child node at all? > > > > > > > > > > Probably not worth reviewing more without a link to the docs for this > > > > > > > > > > device so I can figure out what on earth is going on! > > > > > > > > > > > > > > > > > > > > > > > > > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > > > > > > > > > analog-to-digital converter itself. > > > > > > > > > > > > > > > > > > Here is the link to STM32MP25 reference manuel > > > > > > > > > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > > > > > > > > > Chapter 45: Multi-function digital filter (MDF) > > > > > > > > > > > > > > > > > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > > > > > > > > > filters (DFLT) which can be connected through a multiplexer. > > > > > > > > > > > > > > > > > > Below is a schematic view of typical applications targeted by this > > > > > > > > > peripheral > > > > > > > > > > > > > > > > > > > > > > > > > > > Audio use case: > > > > > > > > > > > > > > > > > > mdf > > > > > > > > > +-------------------------------------+ > > > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > > > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > > > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > > > > > For instance, in an audio use case the serial interface can be configured to > > > > > > > > > provide the clock to the digital microphone (cck0, cck1 or both) at a common > > > > > > > > > predefined rate, and to retrieve the PDM samples. > > > > > > > > > The serial interface provides this samples to a digital filter, which > > > > > > > > > delivers PCM samples on its output. > > > > > > > > > > > > > > > > > > > > > > > > > > > Analog use case: > > > > > > > > > > > > > > > > > > mdf > > > > > > > > > +-------------------------------------+ > > > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > > > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > > > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > > > > > > > > > > > So, looking at the docs and a brief chat with Jonathan about this > > > > > > > > device, I believe you've got things backwards and this is actually the backend, > > > > > > > > and the adc should be the one populating the io-backends property > > > > > > > > pointing to this device. You should have io-backend-cells, and I assume > > > > > > > > that there should be a cell for the adc to select which dlft it is connected > > > > > > > > to. > > > > > > > > > > > > > > > > > > > > > > There have already been lengthy discussions in the past about a DFSDM > > > > > > > peripheral on STM32MP1, which has features similar to those of the MDF and > > > > > > > similar implementation constraints. For the DFSDM, a solution based on an > > > > > > > IIO backend had been upstreamed. The MDF follows the same architecture. I > > > > > > > need to take a little time to dive back into this issue. > > > > > > > > > > > > One thing to note there is that you retrofitted the backends onto that > > > > > > device, and the original design here is much older (it's a text > > > > > > binding). > > > > > > > > > > > > > > > > > > > > > > > > > > DFSDM sources: > > > > > > > drivers/iio/adc/stm32-dfsdm-adc.c > > > > > > > drivers/iio/adc/stm32-dfsdm-core.c > > > > > > > > > > > > > > Here is a sample of DFSDM DT > > > > > > > > > > > > > > sd_adc0: simple-sd-adc0 { > > > > > > > compatible = "sd-modulator"; > > > > > > > #io-backend-cells = <0>; > > > > > > > vref-supply = <&v3v3>; > > > > > > > > > > > > Yeah, pretty sure this is wrong (backwards). The backend is the thing > > > > > > that gets data from an ADC not the ADC. > > > > > > > > > > > > > > > > The backend framework was introduced to implement complex IIO aggregate > > > > > devices. The hardwares that were driving this need were analog device ad9467 > > > > > and ST DFSDM. > > > > > > > > > > https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff > > > > > > > > > > From drivers/iio/industrialio-backend.c: > > > > > > > > > > "The typical architecture is to have one device as the frontend device which > > > > > can be "linked" against one or multiple backend devices. All the IIO and > > > > > userspace interface is expected to be registers/managed by the frontend > > > > > device which will callback into the backends when needed (to get/set some > > > > > configuration that it does not directly control)." > > > > > > > > > > * --------------------- > > > > > * ------------------ | ------------ > > > > > * | ADC |-----------------| | ADC CORE | > > > > > * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- > > > > > * | |-----------------| ------------ > > > > > * ------------------ --------------------- > > > > > > > > > > The MDF (or DFSDM) use case, follows this topology: > > > > > - The SD modulator (ADC core) registers in backend framework > > > > > - The MDF registers in IIO framework and exposes the IIO devices > > > > > It also get configuration (ref voltage) from SD modulator, to compute > > > > > scaling. > > > > > > > > > > I agree that if we consider the terms frontend and backend, the elements in > > > > > the data flow do not have the roles that we would naturally expect. However, > > > > > if we consider the expected role of the elements using the iio-backend > > > > > framework, the usage seems coherent to me. > > > > > > > > I didn't even get as far as sd modulators or whatever, if I understand > > > > correctly the ADC inputs on this device are fed by the onboard ADC? > > > > (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) > > > > In that case, I can't really see how it makes sense for the primary iio > > > > device to change when data is fed back through the mdf or taken > > > > directly from the ADC itself, particularly given how that would affect > > > > the userspace interface. > > > > > > > > The "serial" side of this seems in a similar vein to the adi,axi-adc > > > > stuff, which when considered with the ADC inputs, really does give me > > > > the impression this is backwards. > > > > > > Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, > > > and these can be connected to the MDF via a dedicated interface. (but not > > > the serial interface). > > > > > > However, this use case is not supported by the driver. Only sigma-delta > > > modulators, external to the SoC and connected via the serial interface, are > > > supported. On ST boards, the only available SD modulators are digital > > > microphones. > > > > Quite frankly, I don't care what you are choosing to implement in the > > driver or what your first-party boards support. The binding must > > represent the capabilities of the device, not what subset you deem > > relevant at this point in time. I'm not going to ack anything that does > > not consider all use cases for the device, especially since I the more I > > look the more I am convinced that this is the wrong way to model the > > relationship between devices and therefore intentionally ignoring a use case > > is likely to be problematic when someone does decide that they want to use > > that feature. > > > > > Anyway, if the internal ADC to MDF use case was supported, the issue would > > > be the same. The whole ADC + MDF set would be presented at the interface as > > > an aggregated device, and the ADC data would not be directly accessible to > > > the user. > > > > Of course, that's what I was talking about when I said: > > | In that case, I can't really see how it makes sense for the primary iio > > | device to change when data is fed back through the mdf or taken > > | directly from the ADC itself, particularly given how that would affect > > | the userspace interface. > > > > To me, in that ADC to MDF use case, the frontend portion of the aggregate > > device presented to userspace needs to be the ADC and the MDF needs to be > > the backend, since otherwise the ADC will simultaneously be frontend and > > backend, depending on which channel is considered. That makes no sense to me > > when the MDF can always be the backend, for all use cases and avoid that > > sort of problem entirely. > > I've heard no argument as to why the MDF cannot be a backend, just that you > > don't want to because the previous device didn't, but copying what was > > done before isn't a justification that bears weight if how it was done > > before isn't the way it should be done. > > > > These topology problems were discussed at length in the case of DFSDM. > The main blocking point being support for interleaved channels (scan mode), > a problematic issue that is still found with MDF. If I am not mistaken, you're talking about what's described in the section labelled "Interleaved-transfer mode" of the document you provided previously? > The constraints that led to this approach are in the following thread: > https://lore.kernel.org/all/20210919191414.09270f4e@jic23-huawei/ That to me seemed like a discussion about why the MDF/interleaver needs to be represented as a separate device, I don't see anything that explains why the MDF cannot be a backend. Reading the document, "Interleaved-transfer mode" doesn't trash the association between data and which fifo, and thereby which sensor or ADC, it came from. Using #io-backend-cells = <1> in the MDF, the sensor/ADC can provide the channel to which it is linked, and the data association restored. You already know what the set of interleaved channels is from the st,interleave property so there's no extra properties required for this I think. The problem here must be that you want to access the interleaved data? That could be handled by having a cell value that represents the interleaved data (e.g. -1), rather than a channel (1-N)? That'd support systems that want interleaved data (like an array of identical sensors?) and systems using the mode for the stated aim of it in documentation of optimising DMA request resources who have disparate devices where interleaved data itself is not useful? Thanks, Conor. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-15 12:34 ` Conor Dooley @ 2026-10-19 1:25 ` Jonathan Cameron 2026-10-19 16:17 ` Olivier MOYSAN 0 siblings, 1 reply; 31+ messages in thread From: Jonathan Cameron @ 2026-10-19 1:25 UTC (permalink / raw) To: Conor Dooley Cc: Olivier MOYSAN, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On Thu, 15 Oct 2026 13:34:04 +0100 Conor Dooley <conor@kernel.org> wrote: > On Thu, Oct 15, 2026 at 11:19:19AM +0200, Olivier MOYSAN wrote: > > Hi Conor, > > > > On 10/15/26 00:49, Conor Dooley wrote: > > > On Wed, Oct 14, 2026 at 06:51:45PM +0200, Olivier MOYSAN wrote: > > > > On 10/14/26 17:15, Conor Dooley wrote: > > > > > On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: > > > > > > On 10/9/26 21:12, Conor Dooley wrote: > > > > > > > On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: > > > > > > > > On 10/8/26 12:11, Conor Dooley wrote: > > > > > > > > > On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: > > > > > > > > > > On 10/1/26 20:32, Conor Dooley wrote: > > > > > > > > > > > > > > > > > > > > > > > + > > > > > > > > > > > > +required: > > > > > > > > > > > > + - compatible > > > > > > > > > > > > + - reg > > > > > > > > > > > > + - ranges > > > > > > > > > > > > + - clocks > > > > > > > > > > > > + - clock-names > > > > > > > > > > > > + - clock-ranges > > > > > > > > > > > > + - "#address-cells" > > > > > > > > > > > > + - "#size-cells" > > > > > > > > > > > > + > > > > > > > > > > > > +additionalProperties: false > > > > > > > > > > > > + > > > > > > > > > > > > +patternProperties: > > > > > > > > > > > > + "^sitf@[0-9]+$": > > > > > > > > > > > > + type: object > > > > > > > > > > > > + description: Serial interface child node > > > > > > > > > > > > > > > > > > > > > > Why is this a child node at all? > > > > > > > > > > > Probably not worth reviewing more without a link to the docs for this > > > > > > > > > > > device so I can figure out what on earth is going on! > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > > > > > > > > > > analog-to-digital converter itself. > > > > > > > > > > > > > > > > > > > > Here is the link to STM32MP25 reference manuel > > > > > > > > > > https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf > > > > > > > > > > Chapter 45: Multi-function digital filter (MDF) > > > > > > > > > > > > > > > > > > > > On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital > > > > > > > > > > filters (DFLT) which can be connected through a multiplexer. > > > > > > > > > > > > > > > > > > > > Below is a schematic view of typical applications targeted by this > > > > > > > > > > peripheral > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Audio use case: > > > > > > > > > > > > > > > > > > > > mdf > > > > > > > > > > +-------------------------------------+ > > > > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > > > > | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device > > > > > > > > > > +------+ | +------+ +------+ +------+ | > > > > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > > > > > > > For instance, in an audio use case the serial interface can be configured to > > > > > > > > > > provide the clock to the digital microphone (cck0, cck1 or both) at a common > > > > > > > > > > predefined rate, and to retrieve the PDM samples. > > > > > > > > > > The serial interface provides this samples to a digital filter, which > > > > > > > > > > delivers PCM samples on its output. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Analog use case: > > > > > > > > > > > > > > > > > > > > mdf > > > > > > > > > > +-------------------------------------+ > > > > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > > > > | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device > > > > > > > > > > +--------+ | +------+ +------+ +------+ | > > > > > > > > > > +-------------------------------------+ > > > > > > > > > > > > > > > > > > > > > > > > > > > So, looking at the docs and a brief chat with Jonathan about this > > > > > > > > > device, I believe you've got things backwards and this is actually the backend, > > > > > > > > > and the adc should be the one populating the io-backends property > > > > > > > > > pointing to this device. You should have io-backend-cells, and I assume > > > > > > > > > that there should be a cell for the adc to select which dlft it is connected > > > > > > > > > to. > > > > > > > > > > > > > > > > > > > > > > > > > There have already been lengthy discussions in the past about a DFSDM > > > > > > > > peripheral on STM32MP1, which has features similar to those of the MDF and > > > > > > > > similar implementation constraints. For the DFSDM, a solution based on an > > > > > > > > IIO backend had been upstreamed. The MDF follows the same architecture. I > > > > > > > > need to take a little time to dive back into this issue. > > > > > > > > > > > > > > One thing to note there is that you retrofitted the backends onto that > > > > > > > device, and the original design here is much older (it's a text > > > > > > > binding). > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > DFSDM sources: > > > > > > > > drivers/iio/adc/stm32-dfsdm-adc.c > > > > > > > > drivers/iio/adc/stm32-dfsdm-core.c > > > > > > > > > > > > > > > > Here is a sample of DFSDM DT > > > > > > > > > > > > > > > > sd_adc0: simple-sd-adc0 { > > > > > > > > compatible = "sd-modulator"; > > > > > > > > #io-backend-cells = <0>; > > > > > > > > vref-supply = <&v3v3>; > > > > > > > > > > > > > > Yeah, pretty sure this is wrong (backwards). The backend is the thing > > > > > > > that gets data from an ADC not the ADC. > > > > > > > > > > > > > > > > > > > The backend framework was introduced to implement complex IIO aggregate > > > > > > devices. The hardwares that were driving this need were analog device ad9467 > > > > > > and ST DFSDM. > > > > > > > > > > > > https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff > > > > > > > > > > > > From drivers/iio/industrialio-backend.c: > > > > > > > > > > > > "The typical architecture is to have one device as the frontend device which > > > > > > can be "linked" against one or multiple backend devices. All the IIO and > > > > > > userspace interface is expected to be registers/managed by the frontend > > > > > > device which will callback into the backends when needed (to get/set some > > > > > > configuration that it does not directly control)." > > > > > > > > > > > > * --------------------- > > > > > > * ------------------ | ------------ > > > > > > * | ADC |-----------------| | ADC CORE | > > > > > > * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- > > > > > > * | |-----------------| ------------ > > > > > > * ------------------ --------------------- > > > > > > > > > > > > The MDF (or DFSDM) use case, follows this topology: > > > > > > - The SD modulator (ADC core) registers in backend framework > > > > > > - The MDF registers in IIO framework and exposes the IIO devices > > > > > > It also get configuration (ref voltage) from SD modulator, to compute > > > > > > scaling. > > > > > > > > > > > > I agree that if we consider the terms frontend and backend, the elements in > > > > > > the data flow do not have the roles that we would naturally expect. However, > > > > > > if we consider the expected role of the elements using the iio-backend > > > > > > framework, the usage seems coherent to me. > > > > > > > > > > I didn't even get as far as sd modulators or whatever, if I understand > > > > > correctly the ADC inputs on this device are fed by the onboard ADC? > > > > > (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) > > > > > In that case, I can't really see how it makes sense for the primary iio > > > > > device to change when data is fed back through the mdf or taken > > > > > directly from the ADC itself, particularly given how that would affect > > > > > the userspace interface. > > > > > > > > > > The "serial" side of this seems in a similar vein to the adi,axi-adc > > > > > stuff, which when considered with the ADC inputs, really does give me > > > > > the impression this is backwards. > > > > > > > > Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, > > > > and these can be connected to the MDF via a dedicated interface. (but not > > > > the serial interface). > > > > > > > > However, this use case is not supported by the driver. Only sigma-delta > > > > modulators, external to the SoC and connected via the serial interface, are > > > > supported. On ST boards, the only available SD modulators are digital > > > > microphones. > > > > > > Quite frankly, I don't care what you are choosing to implement in the > > > driver or what your first-party boards support. The binding must > > > represent the capabilities of the device, not what subset you deem > > > relevant at this point in time. I'm not going to ack anything that does > > > not consider all use cases for the device, especially since I the more I > > > look the more I am convinced that this is the wrong way to model the > > > relationship between devices and therefore intentionally ignoring a use case > > > is likely to be problematic when someone does decide that they want to use > > > that feature. > > > > > > > Anyway, if the internal ADC to MDF use case was supported, the issue would > > > > be the same. The whole ADC + MDF set would be presented at the interface as > > > > an aggregated device, and the ADC data would not be directly accessible to > > > > the user. > > > > > > Of course, that's what I was talking about when I said: > > > | In that case, I can't really see how it makes sense for the primary iio > > > | device to change when data is fed back through the mdf or taken > > > | directly from the ADC itself, particularly given how that would affect > > > | the userspace interface. > > > > > > To me, in that ADC to MDF use case, the frontend portion of the aggregate > > > device presented to userspace needs to be the ADC and the MDF needs to be > > > the backend, since otherwise the ADC will simultaneously be frontend and > > > backend, depending on which channel is considered. That makes no sense to me > > > when the MDF can always be the backend, for all use cases and avoid that > > > sort of problem entirely. > > > I've heard no argument as to why the MDF cannot be a backend, just that you > > > don't want to because the previous device didn't, but copying what was > > > done before isn't a justification that bears weight if how it was done > > > before isn't the way it should be done. > > > > > > > These topology problems were discussed at length in the case of DFSDM. > > The main blocking point being support for interleaved channels (scan mode), > > a problematic issue that is still found with MDF. > > If I am not mistaken, you're talking about what's described in the > section labelled "Interleaved-transfer mode" of the document you > provided previously? > > > The constraints that led to this approach are in the following thread: > > https://lore.kernel.org/all/20210919191414.09270f4e@jic23-huawei/ > > That to me seemed like a discussion about why the MDF/interleaver needs > to be represented as a separate device, I don't see anything that > explains why the MDF cannot be a backend. > > Reading the document, "Interleaved-transfer mode" doesn't trash the > association between data and which fifo, and thereby which sensor or > ADC, it came from. Using #io-backend-cells = <1> in the MDF, the > sensor/ADC can provide the channel to which it is linked, and the data > association restored. You already know what the set of interleaved channels > is from the st,interleave property so there's no extra properties required > for this I think. > > The problem here must be that you want to access the interleaved data? That > could be handled by having a cell value that represents the interleaved > data (e.g. -1), rather than a channel (1-N)? That'd support systems that > want interleaved data (like an array of identical sensors?) and systems > using the mode for the stated aim of it in documentation of optimising > DMA request resources who have disparate devices where interleaved data > itself is not useful? Sorry it took me so long to get to this. I promise I wasn't hiding - it just happened to fall down the gaps in my various flurries of reading IIO from latest emails back in time over the last few weeks. I'd managed to blank the whole complexity of multi channel SD demodulators from my mind since the earlier discussion that was linked (thanks for that - I now remember how these work - though maybe not how we ended up with the binding). We are still evolving so it is also possible the solution from that isn't how we'd do it today. As to the question of front end vs backend question, Nuno is probably best person to give input on that but let me have a go. Backends tend to the datashifter / manging engines that deal with taking data from the 'front end' which is typically the ADC device with the actual pins to which we connect analog signals. Examples being parallel interfaces and the many weird and wonderful specialist SPI engines. Front ends as mentioned are the devices to which the inputs are connected. I think that aligns with what Conor was suggesting (and the quick discussion we had in Prague 10 days or so back). The problem you have with the multiple modulators is actually pretty similar to the one we have with chained SPI devices or those weird addressable ones. - share a bus - extra address bits that allow any given device to 'sometimes' ignore messages. - magic registers that are written whatever the address bits. - Special read out sequences that let you 'stream' from multiple devices. - For these we currently constrain things to 'like' devices rather than a mix. A single data pipe (the interleaver here?) is taking data from multiple front end devices. A question here. Do you care about mixed modulator types? The example suggests you do. Which puts us in the situation of something like ____________ _______ ___________ |Modulator 1 | | | | | |(ADC) |-pulsetrain-|Demod 1|-Digital-|Interleaver| |____________| |_______| | (Skipping | ____________ _______ | dflt as |-> Software dmux | Modulator 2| | | | diag too | |(Audio/ADC) |-Pulsetrain-|Demod 2|-Digital-| fat) | |____________| |_______| |___________| In this if we just took the top half, then simples, the Demodulator 1 and Interleaver (not interleaving) would be a normal IIO Backend for the Modulator 1 (kind of the ADC). If we take the whole thing (but with bottom as an Audio channel, not an ADC) then effectively we have a backend backing both signal types and it's up to software to unwind what turns up in memory. Note that a lot of what follows isn't stuff that ends up in DT, but I'm trying to represent the dataflows through IIO. Some of this is very idealistic :( Also my terminology is probably garbage. For me demods go from an encoded signal on one line to ADC samples. I suspect that maps to the acquisition bit of the digital filters in this device. If they are both IIO style ADCs then this runs into the same challenges as SPI chaining. We really would want to end up with a composite device that presents __ ____________ _______ ___________ | | |Modulator 1 | | | | | | |--|(ADC) |-pulsetrain-|Demod 1|-Digital-|Interleaver| | | |____________| |_______| | (Skipping | |A | ____________ _______ | dflt as |-> Software dmux | | | Modulator 2| | | | diag too | | |--|(ADC) |-Pulsetrain-|Demod 2|-Digital-| fat) | |__| |____________| |_______| |___________| Imagine A for example was an a multichannel analog device such as a 2 axis analog Accelemeter. The ultimate IIO device we want would represent that A. We have these in tree and they work by being consumers of ADC channels but assume those channels come from a single IIO ADC. Here the snag is that Modulators 1 and and 2 would naturally be separate IIO 'devices'. (Note there is an example like A in the datasheet - middle of figure 378 - key is the shared clock I think) So conceptually we have __ ____________ _______ ___________ __________ | | |Modulator 1 | | | | | | Data for | | |--|(ADC) |-pdm-|Demod 1|-D-|Interleaver| /| A chan 0 | | | |____________| |_______| | (Skipping | / | (mod 1) | |A | ____________ _______ | dflt as |-SWDemux |__________| | | | Modulator 2| | | | diag too | \ __________ | |--|(ADC) |-pdm-|Demod 2|-D-| fat) | \| Data for | |__| |____________| |_______| |___________| | A chan 1 | | (mod 2) | |__________| But then we actually want to have A as one device which conceptually requires a mux __ ____________ _______ ___________ __________ | | |Modulator 1 | | | | | | Data for | | |--|(ADC) |-pdm-|Demod 1|-D-|Interleaver| | A chan 0 | | | |____________| |_______| | (Skipping | /| (mod 1) |\ |A | ____________ _______ | dflt as |-SWDemux|__________| SWMux - Data A | | | Modulator 2| | | | diag too | \ __________ / | |--|(ADC) |-pdm-|Demod 2|-D-| fat) | | Data for | |__| |____________| |_______| |___________| | A chan 1 | | (mod 2) | |__________| Obviously in practice we want some way of flattening the and mux so that we don't actually do anything. (FWIW we haven't yet built a SW mux concept into IIO, though it has come up a few times for this soft of case). So what is what in this model. A - Simple IIO consumer of Modulator 1 and Modulator 2. Modulator 1/2 - IIO front end devices - each a device on its own. Demod 1/2 + interleaver - IIO backend (data mangler) SWdemux - new concept we need to unwind from a backend that provides service to a pair of front end (actually similar to the IIO demux. Might be able to reuse that) Data for A chan 0. Kind of a virtual backend for the top half of diag. SWMux - new concept that we haven't built - but here it is only theoretical anyway because we don't want to demux then remux. Trick is never use the apparent interfaces for the IIO devices representing the modulator Anyhow, how on earth to we map this to DT. Hmm.. We don't need to represent the device A, though we may need to figure that out by looking for devices pointing to the backend and build it in software. The backend should be both the demodulators and the interleaver (which I think maps to interleaver + digital fiters + the serial interfaces in this case). Stuff to the right is all software concepts. How to indicate what is interleaved? Maybe we do have to represent that front end device as a consumer of channels provided by the various ADCs (modulators here). Other bits in the device here. Digital filters. Why do we need those in DT? Aren't they software controlled things and associate with a channel? Or are they representing what I have as demodulators above.? Given I think they end up in the backend we may need to extend some interfaces. Anyhow, that probably confused anyone who previously had any idea on how this all fits together. Also, I should have gotten out my UK keyboard or changed keyboard layout. US keyboard, with UK layout makes for tricky to find symbols for asci art :( Jonathan > > Thanks, > Conor. ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-19 1:25 ` Jonathan Cameron @ 2026-10-19 16:17 ` Olivier MOYSAN 0 siblings, 0 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-19 16:17 UTC (permalink / raw) To: Jonathan Cameron, Conor Dooley Cc: David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Jonathan, On 10/19/26 03:25, Jonathan Cameron wrote: > On Thu, 15 Oct 2026 13:34:04 +0100 > Conor Dooley <conor@kernel.org> wrote: > >> On Thu, Oct 15, 2026 at 11:19:19AM +0200, Olivier MOYSAN wrote: >>> Hi Conor, >>> >>> On 10/15/26 00:49, Conor Dooley wrote: >>>> On Wed, Oct 14, 2026 at 06:51:45PM +0200, Olivier MOYSAN wrote: >>>>> On 10/14/26 17:15, Conor Dooley wrote: >>>>>> On Mon, Oct 12, 2026 at 02:56:04PM +0200, Olivier MOYSAN wrote: >>>>>>> On 10/9/26 21:12, Conor Dooley wrote: >>>>>>>> On Thu, Oct 08, 2026 at 06:37:26PM +0200, Olivier MOYSAN wrote: >>>>>>>>> On 10/8/26 12:11, Conor Dooley wrote: >>>>>>>>>> On Wed, Oct 07, 2026 at 11:01:28AM +0200, Olivier MOYSAN wrote: >>>>>>>>>>> On 10/1/26 20:32, Conor Dooley wrote: >>>>>>>>>>>> >>>>>>>>>>>>> + >>>>>>>>>>>>> +required: >>>>>>>>>>>>> + - compatible >>>>>>>>>>>>> + - reg >>>>>>>>>>>>> + - ranges >>>>>>>>>>>>> + - clocks >>>>>>>>>>>>> + - clock-names >>>>>>>>>>>>> + - clock-ranges >>>>>>>>>>>>> + - "#address-cells" >>>>>>>>>>>>> + - "#size-cells" >>>>>>>>>>>>> + >>>>>>>>>>>>> +additionalProperties: false >>>>>>>>>>>>> + >>>>>>>>>>>>> +patternProperties: >>>>>>>>>>>>> + "^sitf@[0-9]+$": >>>>>>>>>>>>> + type: object >>>>>>>>>>>>> + description: Serial interface child node >>>>>>>>>>>> >>>>>>>>>>>> Why is this a child node at all? >>>>>>>>>>>> Probably not worth reviewing more without a link to the docs for this >>>>>>>>>>>> device so I can figure out what on earth is going on! >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> The MDF is a digital filter for sigma-delta bitstreams, rather than the >>>>>>>>>>> analog-to-digital converter itself. >>>>>>>>>>> >>>>>>>>>>> Here is the link to STM32MP25 reference manuel >>>>>>>>>>> https://www.st.com/resource/en/reference_manual/rm0457-stm32mp2325xx-advanced-armbased-3264bit-mpus-stmicroelectronics.pdf >>>>>>>>>>> Chapter 45: Multi-function digital filter (MDF) >>>>>>>>>>> >>>>>>>>>>> On STMP32MP25 SoC, the MDF provides 8 serial interfaces (SITF) and 8 digital >>>>>>>>>>> filters (DFLT) which can be connected through a multiplexer. >>>>>>>>>>> >>>>>>>>>>> Below is a schematic view of typical applications targeted by this >>>>>>>>>>> peripheral >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Audio use case: >>>>>>>>>>> >>>>>>>>>>> mdf >>>>>>>>>>> +-------------------------------------+ >>>>>>>>>>> +------+ | +------+ +------+ +------+ | >>>>>>>>>>> | dmic | -> | | sitf | -> | mux | -> | dflt | -- | -> audio device >>>>>>>>>>> +------+ | +------+ +------+ +------+ | >>>>>>>>>>> +-------------------------------------+ >>>>>>>>>>> >>>>>>>>>>> For instance, in an audio use case the serial interface can be configured to >>>>>>>>>>> provide the clock to the digital microphone (cck0, cck1 or both) at a common >>>>>>>>>>> predefined rate, and to retrieve the PDM samples. >>>>>>>>>>> The serial interface provides this samples to a digital filter, which >>>>>>>>>>> delivers PCM samples on its output. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Analog use case: >>>>>>>>>>> >>>>>>>>>>> mdf >>>>>>>>>>> +-------------------------------------+ >>>>>>>>>>> +--------+ | +------+ +------+ +------+ | >>>>>>>>>>> | sd adc | -> | | sitf | -> | mux | -> | dflt | -- | -> iio device >>>>>>>>>>> +--------+ | +------+ +------+ +------+ | >>>>>>>>>>> +-------------------------------------+ >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> So, looking at the docs and a brief chat with Jonathan about this >>>>>>>>>> device, I believe you've got things backwards and this is actually the backend, >>>>>>>>>> and the adc should be the one populating the io-backends property >>>>>>>>>> pointing to this device. You should have io-backend-cells, and I assume >>>>>>>>>> that there should be a cell for the adc to select which dlft it is connected >>>>>>>>>> to. >>>>>>>>>> >>>>>>>>> >>>>>>>>> There have already been lengthy discussions in the past about a DFSDM >>>>>>>>> peripheral on STM32MP1, which has features similar to those of the MDF and >>>>>>>>> similar implementation constraints. For the DFSDM, a solution based on an >>>>>>>>> IIO backend had been upstreamed. The MDF follows the same architecture. I >>>>>>>>> need to take a little time to dive back into this issue. >>>>>>>> >>>>>>>> One thing to note there is that you retrofitted the backends onto that >>>>>>>> device, and the original design here is much older (it's a text >>>>>>>> binding). >>>>>>>> >>>>>>>> >>>>>>>>> >>>>>>>>> DFSDM sources: >>>>>>>>> drivers/iio/adc/stm32-dfsdm-adc.c >>>>>>>>> drivers/iio/adc/stm32-dfsdm-core.c >>>>>>>>> >>>>>>>>> Here is a sample of DFSDM DT >>>>>>>>> >>>>>>>>> sd_adc0: simple-sd-adc0 { >>>>>>>>> compatible = "sd-modulator"; >>>>>>>>> #io-backend-cells = <0>; >>>>>>>>> vref-supply = <&v3v3>; >>>>>>>> >>>>>>>> Yeah, pretty sure this is wrong (backwards). The backend is the thing >>>>>>>> that gets data from an ADC not the ADC. >>>>>>>> >>>>>>> >>>>>>> The backend framework was introduced to implement complex IIO aggregate >>>>>>> devices. The hardwares that were driving this need were analog device ad9467 >>>>>>> and ST DFSDM. >>>>>>> >>>>>>> https://lore.kernel.org/linux-iio/20231204144925.4fe9922f@jic23-huawei/T/#m222f5175273b81dbfe40b7f0daffcdc67d6cb8ff >>>>>>> >>>>>>> From drivers/iio/industrialio-backend.c: >>>>>>> >>>>>>> "The typical architecture is to have one device as the frontend device which >>>>>>> can be "linked" against one or multiple backend devices. All the IIO and >>>>>>> userspace interface is expected to be registers/managed by the frontend >>>>>>> device which will callback into the backends when needed (to get/set some >>>>>>> configuration that it does not directly control)." >>>>>>> >>>>>>> * --------------------- >>>>>>> * ------------------ | ------------ >>>>>>> * | ADC |-----------------| | ADC CORE | >>>>>>> * | (Frontend/IIO) | Serial Data (eg | |(backend) |------- >>>>>>> * | |-----------------| ------------ >>>>>>> * ------------------ --------------------- >>>>>>> >>>>>>> The MDF (or DFSDM) use case, follows this topology: >>>>>>> - The SD modulator (ADC core) registers in backend framework >>>>>>> - The MDF registers in IIO framework and exposes the IIO devices >>>>>>> It also get configuration (ref voltage) from SD modulator, to compute >>>>>>> scaling. >>>>>>> >>>>>>> I agree that if we consider the terms frontend and backend, the elements in >>>>>>> the data flow do not have the roles that we would naturally expect. However, >>>>>>> if we consider the expected role of the elements using the iio-backend >>>>>>> framework, the usage seems coherent to me. >>>>>> >>>>>> I didn't even get as far as sd modulators or whatever, if I understand >>>>>> correctly the ADC inputs on this device are fed by the onboard ADC? >>>>>> (https://lore.kernel.org/linux-iio/20261006-adc-stm32mp25-v1-v4-0-d31ec75aecf3@foss.st.com/) >>>>>> In that case, I can't really see how it makes sense for the primary iio >>>>>> device to change when data is fed back through the mdf or taken >>>>>> directly from the ADC itself, particularly given how that would affect >>>>>> the userspace interface. >>>>>> >>>>>> The "serial" side of this seems in a similar vein to the adi,axi-adc >>>>>> stuff, which when considered with the ADC inputs, really does give me >>>>>> the impression this is backwards. >>>>> >>>>> Some clarifications about the STM32MP25. This SoC does indeed provide ADCs, >>>>> and these can be connected to the MDF via a dedicated interface. (but not >>>>> the serial interface). >>>>> >>>>> However, this use case is not supported by the driver. Only sigma-delta >>>>> modulators, external to the SoC and connected via the serial interface, are >>>>> supported. On ST boards, the only available SD modulators are digital >>>>> microphones. >>>> >>>> Quite frankly, I don't care what you are choosing to implement in the >>>> driver or what your first-party boards support. The binding must >>>> represent the capabilities of the device, not what subset you deem >>>> relevant at this point in time. I'm not going to ack anything that does >>>> not consider all use cases for the device, especially since I the more I >>>> look the more I am convinced that this is the wrong way to model the >>>> relationship between devices and therefore intentionally ignoring a use case >>>> is likely to be problematic when someone does decide that they want to use >>>> that feature. >>>> >>>>> Anyway, if the internal ADC to MDF use case was supported, the issue would >>>>> be the same. The whole ADC + MDF set would be presented at the interface as >>>>> an aggregated device, and the ADC data would not be directly accessible to >>>>> the user. >>>> >>>> Of course, that's what I was talking about when I said: >>>> | In that case, I can't really see how it makes sense for the primary iio >>>> | device to change when data is fed back through the mdf or taken >>>> | directly from the ADC itself, particularly given how that would affect >>>> | the userspace interface. >>>> >>>> To me, in that ADC to MDF use case, the frontend portion of the aggregate >>>> device presented to userspace needs to be the ADC and the MDF needs to be >>>> the backend, since otherwise the ADC will simultaneously be frontend and >>>> backend, depending on which channel is considered. That makes no sense to me >>>> when the MDF can always be the backend, for all use cases and avoid that >>>> sort of problem entirely. >>>> I've heard no argument as to why the MDF cannot be a backend, just that you >>>> don't want to because the previous device didn't, but copying what was >>>> done before isn't a justification that bears weight if how it was done >>>> before isn't the way it should be done. >>>> >>> >>> These topology problems were discussed at length in the case of DFSDM. >>> The main blocking point being support for interleaved channels (scan mode), >>> a problematic issue that is still found with MDF. >> >> If I am not mistaken, you're talking about what's described in the >> section labelled "Interleaved-transfer mode" of the document you >> provided previously? >> >>> The constraints that led to this approach are in the following thread: >>> https://lore.kernel.org/all/20210919191414.09270f4e@jic23-huawei/ >> >> That to me seemed like a discussion about why the MDF/interleaver needs >> to be represented as a separate device, I don't see anything that >> explains why the MDF cannot be a backend. >> >> Reading the document, "Interleaved-transfer mode" doesn't trash the >> association between data and which fifo, and thereby which sensor or >> ADC, it came from. Using #io-backend-cells = <1> in the MDF, the >> sensor/ADC can provide the channel to which it is linked, and the data >> association restored. You already know what the set of interleaved channels >> is from the st,interleave property so there's no extra properties required >> for this I think. >> >> The problem here must be that you want to access the interleaved data? That >> could be handled by having a cell value that represents the interleaved >> data (e.g. -1), rather than a channel (1-N)? That'd support systems that >> want interleaved data (like an array of identical sensors?) and systems >> using the mode for the stated aim of it in documentation of optimising >> DMA request resources who have disparate devices where interleaved data >> itself is not useful? > > Sorry it took me so long to get to this. I promise I wasn't hiding - it > just happened to fall down the gaps in my various flurries of reading > IIO from latest emails back in time over the last few weeks. > > I'd managed to blank the whole complexity of multi channel SD demodulators > from my mind since the earlier discussion that was linked (thanks for that > - I now remember how these work - though maybe not how we ended up with > the binding). We are still evolving so it is also possible the solution > from that isn't how we'd do it today. > > As to the question of front end vs backend question, Nuno is probably best person > to give input on that but let me have a go. > > Backends tend to the datashifter / manging engines that deal with taking > data from the 'front end' which is typically the ADC device with the actual > pins to which we connect analog signals. Examples being parallel interfaces > and the many weird and wonderful specialist SPI engines. > > Front ends as mentioned are the devices to which the inputs are connected. > I think that aligns with what Conor was suggesting (and the quick discussion > we had in Prague 10 days or so back). > > The problem you have with the multiple modulators is actually pretty similar > to the one we have with chained SPI devices or those weird addressable ones. > - share a bus > - extra address bits that allow any given device to 'sometimes' ignore messages. > - magic registers that are written whatever the address bits. > - Special read out sequences that let you 'stream' from multiple devices. > - For these we currently constrain things to 'like' devices rather than a mix. > > A single data pipe (the interleaver here?) is taking data from multiple front end devices. > > A question here. Do you care about mixed modulator types? The example > suggests you do. Which puts us in the situation of something like > ____________ _______ ___________ > |Modulator 1 | | | | | > |(ADC) |-pulsetrain-|Demod 1|-Digital-|Interleaver| > |____________| |_______| | (Skipping | > ____________ _______ | dflt as |-> Software dmux > | Modulator 2| | | | diag too | > |(Audio/ADC) |-Pulsetrain-|Demod 2|-Digital-| fat) | > |____________| |_______| |___________| > > In this if we just took the top half, then simples, the > Demodulator 1 and Interleaver (not interleaving) would > be a normal IIO Backend for the Modulator 1 (kind of > the ADC). > > If we take the whole thing (but with bottom as an Audio > channel, not an ADC) then effectively we have a backend > backing both signal types and it's up to software to unwind > what turns up in memory. > > Note that a lot of what follows isn't stuff that ends > up in DT, but I'm trying to represent the dataflows through > IIO. Some of this is very idealistic :( Also my terminology > is probably garbage. For me demods go from an encoded signal > on one line to ADC samples. I suspect that maps to the acquisition > bit of the digital filters in this device. > > If they are both IIO style ADCs then this runs into the > same challenges as SPI chaining. We really would want to > end up with a composite device that presents > > __ ____________ _______ ___________ > | | |Modulator 1 | | | | | > | |--|(ADC) |-pulsetrain-|Demod 1|-Digital-|Interleaver| > | | |____________| |_______| | (Skipping | > |A | ____________ _______ | dflt as |-> Software dmux > | | | Modulator 2| | | | diag too | > | |--|(ADC) |-Pulsetrain-|Demod 2|-Digital-| fat) | > |__| |____________| |_______| |___________| > > Imagine A for example was an a multichannel analog device such > as a 2 axis analog Accelemeter. The ultimate IIO device we want > would represent that A. We have these in tree and they work > by being consumers of ADC channels but assume those channels > come from a single IIO ADC. Here the snag is that > Modulators 1 and and 2 would naturally be separate IIO 'devices'. > (Note there is an example like A in the datasheet - middle of figure > 378 - key is the shared clock I think) > > So conceptually we have > > __ ____________ _______ ___________ __________ > | | |Modulator 1 | | | | | | Data for | > | |--|(ADC) |-pdm-|Demod 1|-D-|Interleaver| /| A chan 0 | > | | |____________| |_______| | (Skipping | / | (mod 1) | > |A | ____________ _______ | dflt as |-SWDemux |__________| > | | | Modulator 2| | | | diag too | \ __________ > | |--|(ADC) |-pdm-|Demod 2|-D-| fat) | \| Data for | > |__| |____________| |_______| |___________| | A chan 1 | > | (mod 2) | > |__________| > > But then we actually want to have A as one device which > conceptually requires a mux > > __ ____________ _______ ___________ __________ > | | |Modulator 1 | | | | | | Data for | > | |--|(ADC) |-pdm-|Demod 1|-D-|Interleaver| | A chan 0 | > | | |____________| |_______| | (Skipping | /| (mod 1) |\ > |A | ____________ _______ | dflt as |-SWDemux|__________| SWMux - Data A > | | | Modulator 2| | | | diag too | \ __________ / > | |--|(ADC) |-pdm-|Demod 2|-D-| fat) | | Data for | > |__| |____________| |_______| |___________| | A chan 1 | > | (mod 2) | > |__________| > > Obviously in practice we want some way of flattening the and mux > so that we don't actually do anything. (FWIW we haven't yet built > a SW mux concept into IIO, though it has come up a few times for > this soft of case). > > So what is what in this model. > > A - Simple IIO consumer of Modulator 1 and Modulator 2. > Modulator 1/2 - IIO front end devices - each a device on its own. > Demod 1/2 + interleaver - IIO backend (data mangler) > > SWdemux - new concept we need to unwind from a backend that provides > service to a pair of front end (actually similar to the IIO > demux. Might be able to reuse that) > Data for A chan 0. Kind of a virtual backend for the top half of diag. > > SWMux - new concept that we haven't built - but here it is only theoretical > anyway because we don't want to demux then remux. Trick is > never use the apparent interfaces for the IIO devices > representing the modulator > > Anyhow, how on earth to we map this to DT. Hmm.. > > We don't need to represent the device A, though we may need to figure > that out by looking for devices pointing to the backend and build it > in software. > > The backend should be both the demodulators and the interleaver > (which I think maps to interleaver + digital fiters + the serial > interfaces in this case). > Stuff to the right is all software concepts. > > How to indicate what is interleaved? Maybe we do have to > represent that front end device as a consumer of channels provided > by the various ADCs (modulators here). > > Other bits in the device here. > Digital filters. Why do we need those in DT? Aren't they software > controlled things and associate with a channel? Or are they representing > what I have as demodulators above.? > > Given I think they end up in the backend we may need to extend some interfaces. > > Anyhow, that probably confused anyone who previously had > any idea on how this all fits together. > > Also, I should have gotten out my UK keyboard or changed keyboard layout. > US keyboard, with UK layout makes for tricky to find symbols for asci art :( > > Jonathan > Thanks for your feedback. First, a quick overview of MDF to clarify filter usage. +- - - - - - + ' STM32MP2 ' +--------+ +--------+ 1bit stream ' +--------+ ' | source | --> | SD mod | -------------> ' | MDF | ' +--------+ +--------+ ' +--------+ ' +- - - - - - + The analog input is sampled and converted into a 1-bit digital data stream by the external Sigma-Delta modulator. The MDF filter processing consists mainly in averaging the input serial stream and producing a parallel,lower rate, data output with higher resolution. (there is no other demodulation stage than this decimation) The MDF filters feature a set of configurable parameters that allow to tune the output resolution and data rate. What need to be configured at filter level - filter/serial interface muxing - filter order (exposed in binding. maybe considered as sw tuning ?) - filter dma association and configuration The interleave mode (2 to n filters) is only a special use case, the most common case being a single filter per channel Below is a kind of state of the art regarding the solutions considered for the DFSDM. (MDF inherits these choices) 1 - Initial DFSDM implementation proposed (not upstreamed) +-------------+ | Sysfs | +-------------+ | - Scale | | Sysfs | | - Raw data | +-------------+ +-------------+ +-------------+ | IIO char dev| +-------------+ +-------------+ | IIO char dev| ^ /\ +-------------+ | || | || Userland ------------------------------------------------------------- | || IIO fw | || | || ------------------------------------------------------------- +-------------+ +----|--------------||+ | | | | ||| Drivers | +-----+-------+----+ ||| | | | | ||| +-------|-----+ +-------------------||+ | || ------------------------------------------------------------- | || +-------|-----+ +-------------------||+ | | | ||| Hardware | sd modulator| | DFSDM ||| ================================================== | | | | +-------+-----+ +---------------------+ | Vref ==> data path --> info path Both SD modulator and DFSDM register a IIO device. The DFSDM is a consumer of the SD modulator. vref is retrieved from SD modulator to compute the scaling info. Compatible with interleaved mode The main drawback is that we expose useless SD modulator IIO devices 2 - DFSDM managed as a "hardware accelerator" +-------------+ | Sysfs | | - Scale | +---------------+ | - Raw data | | IIO char dev | +-------------+ +---------------+ ^ /\ | || | || Userland ----------------------------------------------------------- | || IIO fw | || | || ----------------------------------------------------------- | || +--|-------------||--+ +----------------+ | | || | | | Drivers | | ======================= | | | | | || | | +-----------------+-----+--+ || | | +---------+-----+--+ || | +----------|---------+ +-----------||---+ | || ----------------------------------------------------------- | || +----------|---------+ +-----------||---+ | | | || | Hardware | sd modulator | | DFSDM || | ============================================= | | | | | +----------+---------+ +----------------+ | | Vref The DFSDM is a consumer of the SD modulator. In addition to its complexity, the main drawback of this approach is that it is unsuitable for interleaved mode. 3 - Aggregated IIO device +-------------+ | Sysfs | | - Scale | +-------------+ | - Raw data | | IIO char dev| +-------------+ +-------------+ ^ /\ | || | || Userland ------------------------------------------------------------- | || IIO fw Composite IIO component | || | | || | | || ------------------------------------------------------------- +--------------+-----------------+---------------+ | +------------+--+ +--------------+ || | Drivers | | | | | || | | | | | | || | | +---------------+ +--------------+ || | +---------------------------------------------||-+ ------------------------------------------------------------- +---------------+ +--------------+ || | | | | || Hardware | sd modulator | | DFSDM | || =================================================== | | | | +-------+-------+ +--------------+ | Vref The converter framework introduced by Nuno Sa was an attempt to address a similar issue https://lore.kernel.org/linux-iio/dac3967805d7ddbd4653ead6d50e614844e0b70b.camel@gmail.com/ https://marc.info/?l=linux-iio&m=169347939425097&w=2 A trial use of this framework was carried out for DFSDM and seemed suitable. However, this solution was abandoned in favor of the backend framework. 4 - Current DFSDM implementation (upstreamed) +-------------+ | Sysfs | | - Scale | +-------------+ | - Raw data | | IIO char dev| +-------------+ +-------------+ ^ /\ | || | || Userland ------------------------------------------------------------- | || IIO fw +-------------+ | || | Backend fw | | || | | | || +-------------+ | || | || ------------------------------------------------------------- +-------------+ +---|--------------||+ | | | | ||| Drivers | +-----+--------+---+ ||| | | | | ||| +-------|-----+ +------------------||+ | || ------------------------------------------------------------- | || +-------|-----+ +------------------||+ | | | ||| Hardware | sd modulator| | DFSDM ||| ================================================== | | | | +-------+-----+ +--------------------+ | Vref The SD modulator is registered as a backend device. SD modulator is a consumer of the DFSDM. Only DFSDM IIO device is exposed. vref is retrieved from SD modulator to compute the scaling info. Compatible with interleaved mode I agree with your definition of a frontend and a backend. From that point of view, this implementation does not fit the definition. However, it looks to me that the root of the problem is the name of the “backend” framework, which does not correspond to the role it actually plays. In this use case, it should probably be called frontend. But that would indeed need to be confirmed with Nuno. I will also take a closer look at how the framework is used by components such as the AD9467. Best regards Olivier > >> >> Thanks, >> Conor. > ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-12 12:56 ` Olivier MOYSAN 2026-10-14 15:15 ` Conor Dooley @ 2026-10-19 1:30 ` Jonathan Cameron 2026-10-19 18:55 ` Conor Dooley 1 sibling, 1 reply; 31+ messages in thread From: Jonathan Cameron @ 2026-10-19 1:30 UTC (permalink / raw) To: Olivier MOYSAN Cc: Conor Dooley, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel > >> Yes, we can have two clocks gated independently but sharing the same rate. > >> > >> Using the clock framework apis seemed to me the right way to manage cck1 and > >> cck0 gating and divider computing. I think I would have to introduce > >> proprietary properties and have to implement code in the driver, that would > >> be handled natively by the framework otherwise. > > > > The CCF is still the right way to do it, especially since CCK0/1 can be > > exported to other devices. I don't believe you need to actually have a > > reference in DT to do this though, plenty of "real" clock controllers > > have only one input clock and hang a whole tree with multiple layers off > > that. > > Down below I mentioned this under "ouroboros devices", I think this kind > > of ability to chose which clock a channel uses is a fairly normal thing > > to do in IIO land, I just dunno what the preferred mechanism is - I just > > know that it is not referencing yourself (probably it's some sort of > > property that you put in a channel node that says 'blah-clock = "cck0"', > > but better that the IIO folks answer. > > > > The adc.yaml binding do not expose clock properties. But maybe IIO > experts can answer about this. Hmm.. For an 'conventional' ADC channel a clock is a novel thing to have on a per channel basis. What does it mean for an analog signal? I think these are signals between the front end (which here typically has one channel only) and the backend. They are useful because they end up indicating (I think) whether we want to interleave or not? Anyhow, right now I don't have this clear enough in my head to give a firm answer. Jonathan ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-19 1:30 ` Jonathan Cameron @ 2026-10-19 18:55 ` Conor Dooley 0 siblings, 0 replies; 31+ messages in thread From: Conor Dooley @ 2026-10-19 18:55 UTC (permalink / raw) To: Jonathan Cameron Cc: Olivier MOYSAN, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel [-- Attachment #1: Type: text/plain, Size: 3650 bytes --] On Mon, Oct 19, 2026 at 02:30:37AM +0100, Jonathan Cameron wrote: > > > >> Yes, we can have two clocks gated independently but sharing the same rate. > > >> > > >> Using the clock framework apis seemed to me the right way to manage cck1 and > > >> cck0 gating and divider computing. I think I would have to introduce > > >> proprietary properties and have to implement code in the driver, that would > > >> be handled natively by the framework otherwise. > > > > > > The CCF is still the right way to do it, especially since CCK0/1 can be > > > exported to other devices. I don't believe you need to actually have a > > > reference in DT to do this though, plenty of "real" clock controllers > > > have only one input clock and hang a whole tree with multiple layers off > > > that. > > > Down below I mentioned this under "ouroboros devices", I think this kind > > > of ability to chose which clock a channel uses is a fairly normal thing > > > to do in IIO land, I just dunno what the preferred mechanism is - I just > > > know that it is not referencing yourself (probably it's some sort of > > > property that you put in a channel node that says 'blah-clock = "cck0"', > > > but better that the IIO folks answer. > > > > > > > The adc.yaml binding do not expose clock properties. But maybe IIO > > experts can answer about this. > > Hmm.. For an 'conventional' ADC channel a clock is a novel thing to have > on a per channel basis. What does it mean for an analog signal? tbh, I don't think this has anything to do with adc.yaml or ADC channels, the channel that I was talking about here was the channel on the backend since in Figure 349 the serial interfaces can select between the two clocks but also select to be clocked by the MDF_CKIx input. We definitely have some properties about that are used by devices to change between clock sources - I just dunno if any of them have that capability on a per-channel basis. > I think these are signals between the front end (which here typically > has one channel only) and the backend. They are useful because they > end up indicating (I think) whether we want to interleave or not? If it was just about interleaving, I don't think you'd need two of them, since only one set of interleaved channels is possible? There's also the option I mentioned of having the MDF_CKIx be the clock. Maybe being a clock controller is actually the right thing to do, just with the frontend sdmodulator or w/e connected to the SITFx being the consumer? In that case, you'd need to do something to actually represent the clock mux in dt, one mux per SITFx, leaving us with N output clocks from CLK_SITF0 to CLK_SITFx rather than two because we're thinking in terms of programming model not physical outputs. Additionally, the number of input clocks grows by N since MDF_CKIx are all parents of the muxes. You'd then use assigned-clock-parents from the frontend node to set the parent of the mux (I think anyway). I'd be a little afraid of creating a loop there though, that needs to be broken, if the MDF_CKIx provider is the sd-modulator - but idk if that's possible and cyclic dependencies like that can always be dealt with anyway. That's probably the most natural way to go about things from a DT point of view, and makes some sense to me if the clock is being used to drive communication with the sd-modulator - although it seems a little forced. It's still better IMO than the MDF referencing itself as things are done now. > > Anyhow, right now I don't have this clear enough in my head to > give a firm answer. > > Jonathan [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan 2026-10-01 16:25 ` Rob Herring (Arm) 2026-10-01 18:32 ` Conor Dooley @ 2026-10-02 9:22 ` Krzysztof Kozlowski 2026-10-06 15:48 ` Olivier MOYSAN 2026-10-02 9:34 ` Krzysztof Kozlowski 3 siblings, 1 reply; 31+ messages in thread From: Krzysztof Kozlowski @ 2026-10-02 9:22 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > Add bindings that describes STM32 MDF settings to support > digital filtering for Pulse Density Modulation (PDM) microphones > and analog sigma delta modulators. You already received review, so a few things on top to spare you one more cycle: A nit, subject: drop second/last, redundant "bindings for". The "dt-bindings" prefix is already stating that these are bindings. See also: https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23 > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > --- > .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ > 1 file changed, 383 insertions(+) > create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > new file mode 100644 > index 000000000000..f2fbc3e150e8 > --- /dev/null > +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml Filename follows compatible, so st,stm32mp23-mdf > @@ -0,0 +1,383 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC > + > +maintainers: > + - Olivier Moysan <olivier.moysan@foss.st.com> > + > +description: | > + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to > + interface external sigma delta modulators to STM32 micro controllers. > + > +properties: > + compatible: > + enum: > + - st,stm32mp25-mdf > + - st,stm32mp23-mdf Why reversed order? > + ranges: true > + > + clock-ranges: true Do you need it here? > + > + resets: > + maxItems: 1 > + > + reset-names: > + items: > + - const: mdf Drop > + > + access-controllers: > + $ref: /schemas/types.yaml#/definitions/phandle-array > + description: | > + Phandle to the rifsc device to check access right. Look at other code how this is done. Don't come with own stuff. > + > + power-domains: > + maxItems: 1 > + > + st,interleave: > + description: | > + List of phandles of interleaved filters. The indexes of interleaved filters must be > + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters > + are muxed in a single channel and retrieved through the device associated to the filter 0. > + The filters 1..N have to be enabled, but inherit their configuration from filter 0. > + $ref: /schemas/types.yaml#/definitions/phandle-array > + > +required: > + - compatible > + - reg > + - ranges > + - clocks > + - clock-names > + - clock-ranges > + - "#address-cells" > + - "#size-cells" > + > +additionalProperties: false > + > +patternProperties: And this has odd order. Please look at example-schema. > + "^sitf@[0-9]+$": > + type: object > + description: Serial interface child node > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-sitf-mdf > + > + reg: > + description: Specify the SITF serial interface instance > + maxItems: 1 > + > + clocks: > + description: | > + Serial interface clock (optional depending on interface mode) > + maxItems: 1 > + > + st,sitf-mode: > + description: | > + Select serial interface protocol > + - spi: SPI mode > + - lf_spi: low frequency SPI mode for low power applications > + $ref: /schemas/types.yaml#/definitions/string > + enum: > + - spi > + - lf_spi > + > + required: > + - reg > + - st,sitf-mode > + > + additionalProperties: false > + > + "^filter@[0-9]+$": > + type: object > + description: Digital filter path child node > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-mdf-dmic > + - st,stm32mp25-mdf-adc > + > + reg: > + description: Specify the MDF filter instance > + maxItems: 1 > + > + interrupts: > + maxItems: 1 > + > + clocks: > + minItems: 1 Heh? so here min? Is there any logic in your choices of code style? > + description: Internal clock used for MDF digital processing and control blocks. > + > + clock-names: > + items: > + - const: ker_ck > + > + dmas: > + maxItems: 1 > + > + dma-names: > + items: > + - const: rx > + > + "#io-channel-cells": > + const: 1 > + > + '#address-cells': > + const: 1 > + > + '#size-cells': > + const: 0 > + > + st,cic-mode: > + description: | > + Cascaded-integrator-comb (CIC) filter configuration > + - 0: MCIC & ACIC filters in FastSinc mode > + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 > + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 > + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 > + This property is mandatory for filter 0 or filters not used in interleave mode. > + $ref: /schemas/types.yaml#/definitions/uint32 > + minimum: 0 > + maximum: 5 > + > + st,delay: > + description: Filter delay in samples > + $ref: /schemas/types.yaml#/definitions/uint32 > + maximum: 127 > + > + st,rs-filter-bypass: > + description: Bypass RSFLT reshaping filter. > + $ref: /schemas/types.yaml#/definitions/flag > + > + st,hpf-filter-cutoff-bp: > + description: | > + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. > + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. > + If this property is not defined the HPF is disabled. > + enum: [625, 1250, 2500, 9500] > + > + st,sync: > + description: > + Synchronize to another filter. > + Must contain the phandle of the filter providing the synchronization. > + allOf: > + - $ref: /schemas/types.yaml#/definitions/phandle-array > + - maxItems: 1 > + > + st,sitf: > + $ref: /schemas/types.yaml#/definitions/phandle-array > + items: > + - items: > + - description: Phandle of the serial interface connected to the digital filter > + - description: | > + The phandle's argument selects the bitstream on the falling or rising edge > + of the serial interface clock: > + - 0: rising edge > + - 1: falling edge > + enum: [0, 1] > + default: 0 > + description: > + Should be phandle/bitstream pair. > + > + required: > + - compatible > + - reg > + - interrupts > + - dmas > + - dma-names > + - "#io-channel-cells" > + - "#address-cells" > + - "#size-cells" > + - st,sitf > + > + unevaluatedProperties: false > + > + patternProperties: > + "^channel@([0-7])$": > + type: object > + $ref: adc.yaml > + description: Represents the external channel which is connected to the MDF. > + > + properties: > + reg: > + maximum: 7 > + > + io-backends: > + description: > + Used to pipe external sigma delta modulator or internal ADC backend to MDF > + channel. > + maxItems: 1 > + > + required: > + - reg > + > + unevaluatedProperties: false > + > + allOf: > + - if: > + properties: > + compatible: > + contains: > + const: st,stm32mp25-mdf-adc > + > + then: > + patternProperties: > + "^channel@[0-7]$": > + required: > + - io-backends > + > + - if: > + properties: > + compatible: > + contains: > + const: st,stm32mp25-mdf-dmic > + > + then: > + patternProperties: > + "^mdf-dai+$": This makes no sense. Why is this a pattern and why mdf-daiiiii is correct name? Not mentioning that your are not supposed to define properties in if block (do you see any code like that?). Mixing addressable and non-addressable children is another odd thing. This entire schema is quite chaotic and overcomplicated. > + type: object > + description: child node > + > + properties: > + compatible: > + enum: > + - st,stm32mp25-mdf-dai > + > + "#sound-dai-cells": > + const: 0 > + > + io-channels: > + description: > + From common IIO binding. Used to pipe external sigma delta > + modulator or internal ADC output to MDF channel. > + > + power-domains: > + maxItems: 1 > + > + port: > + $ref: /schemas/sound/audio-graph-port.yaml# > + unevaluatedProperties: false > + > + required: > + - compatible > + - "#sound-dai-cells" > + - io-channels > + > + additionalProperties: false > + > +examples: > + - | > + #include <dt-bindings/clock/st,stm32mp25-rcc.h> > + #include <dt-bindings/interrupt-controller/arm-gic.h> > + mdf1: mdf@504d0000 { Node names should be generic. See also an explanation and list of examples (not exhaustive) in DT specification: https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation If you cannot find a name matching your device, please check in kernel sources for similar cases or you can grow the spec (via pull request to DT spec repo). And drop unused labels. > + compatible = "st,stm32mp25-mdf"; > + ranges = <0 0x504d0000 0x1000>; > + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; Address ranges of 2 and 4 words? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-02 9:22 ` Krzysztof Kozlowski @ 2026-10-06 15:48 ` Olivier MOYSAN 2026-10-06 15:59 ` Krzysztof Kozlowski 0 siblings, 1 reply; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-06 15:48 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Krzysztof, Thank you for the review. On 10/2/26 11:22, Krzysztof Kozlowski wrote: > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >> Add bindings that describes STM32 MDF settings to support >> digital filtering for Pulse Density Modulation (PDM) microphones >> and analog sigma delta modulators. > > You already received review, so a few things on top to spare you one > more cycle: > > A nit, subject: drop second/last, redundant "bindings for". The > "dt-bindings" prefix is already stating that these are bindings. > See also: > https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23 > Done >> >> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >> --- >> .../bindings/iio/adc/st,stm32-mdf-adc.yaml | 383 ++++++++++++++++++ >> 1 file changed, 383 insertions(+) >> create mode 100644 Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> >> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> new file mode 100644 >> index 000000000000..f2fbc3e150e8 >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml > > Filename follows compatible, so st,stm32mp23-mdf > stmp32mp25 is the main SoC, while stm32mp23 is a variant. file renamed st,stm32mp25-mdf.yaml >> @@ -0,0 +1,383 @@ >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >> +%YAML 1.2 >> +--- >> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >> +$schema: http://devicetree.org/meta-schemas/core.yaml# >> + >> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >> + >> +maintainers: >> + - Olivier Moysan <olivier.moysan@foss.st.com> >> + >> +description: | >> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >> + interface external sigma delta modulators to STM32 micro controllers. >> + >> +properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf >> + - st,stm32mp23-mdf > > Why reversed order? > Ok. Reordered alphabetically >> + ranges: true >> + >> + clock-ranges: true > > Do you need it here? clock-ranges property is used to allow the filter child nodes to inherit the MDF kernel clock from the parent node. > >> + >> + resets: >> + maxItems: 1 >> + >> + reset-names: >> + items: >> + - const: mdf > > Drop > reset-names removed. >> + >> + access-controllers: >> + $ref: /schemas/types.yaml#/definitions/phandle-array >> + description: | >> + Phandle to the rifsc device to check access right. > > Look at other code how this is done. Don't come with own stuff. > Replaced by: access-controllers: maxItems: 1 >> + >> + power-domains: >> + maxItems: 1 >> + >> + st,interleave: >> + description: | >> + List of phandles of interleaved filters. The indexes of interleaved filters must be >> + consecutives starting from 0 (i.e in range [0..N]). The samples from interleaved filters >> + are muxed in a single channel and retrieved through the device associated to the filter 0. >> + The filters 1..N have to be enabled, but inherit their configuration from filter 0. >> + $ref: /schemas/types.yaml#/definitions/phandle-array >> + >> +required: >> + - compatible >> + - reg >> + - ranges >> + - clocks >> + - clock-names >> + - clock-ranges >> + - "#address-cells" >> + - "#size-cells" >> + >> +additionalProperties: false >> + >> +patternProperties: > > And this has odd order. Please look at example-schema. > ok. Reordered. >> + "^sitf@[0-9]+$": >> + type: object >> + description: Serial interface child node >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-sitf-mdf >> + >> + reg: >> + description: Specify the SITF serial interface instance >> + maxItems: 1 >> + >> + clocks: >> + description: | >> + Serial interface clock (optional depending on interface mode) >> + maxItems: 1 >> + >> + st,sitf-mode: >> + description: | >> + Select serial interface protocol >> + - spi: SPI mode >> + - lf_spi: low frequency SPI mode for low power applications >> + $ref: /schemas/types.yaml#/definitions/string >> + enum: >> + - spi >> + - lf_spi >> + >> + required: >> + - reg >> + - st,sitf-mode >> + >> + additionalProperties: false >> + >> + "^filter@[0-9]+$": >> + type: object >> + description: Digital filter path child node >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf-dmic >> + - st,stm32mp25-mdf-adc >> + >> + reg: >> + description: Specify the MDF filter instance >> + maxItems: 1 >> + >> + interrupts: >> + maxItems: 1 >> + >> + clocks: >> + minItems: 1 > > Heh? so here min? Is there any logic in your choices of code style? > As the filter node always use the kernel clock from parent node we can remove "clocks" item. "clocks" is not relevant here as the filter is not supposed to use another reference. clocks & clock-names removed >> + description: Internal clock used for MDF digital processing and control blocks. >> + >> + clock-names: >> + items: >> + - const: ker_ck >> + >> + dmas: >> + maxItems: 1 >> + >> + dma-names: >> + items: >> + - const: rx >> + >> + "#io-channel-cells": >> + const: 1 >> + >> + '#address-cells': >> + const: 1 >> + >> + '#size-cells': >> + const: 0 >> + >> + st,cic-mode: >> + description: | >> + Cascaded-integrator-comb (CIC) filter configuration >> + - 0: MCIC & ACIC filters in FastSinc mode >> + - [1-3]: MCIC & ACIC filters in Sinc mode order 1 to 3 >> + - [4-5]: Single CIC filter in Sinc mode order 4 to 5 >> + For audio purpose it is recommended to use CIC Sinc4 or Sinc5 >> + This property is mandatory for filter 0 or filters not used in interleave mode. >> + $ref: /schemas/types.yaml#/definitions/uint32 >> + minimum: 0 >> + maximum: 5 >> + >> + st,delay: >> + description: Filter delay in samples >> + $ref: /schemas/types.yaml#/definitions/uint32 >> + maximum: 127 >> + >> + st,rs-filter-bypass: >> + description: Bypass RSFLT reshaping filter. >> + $ref: /schemas/types.yaml#/definitions/flag >> + >> + st,hpf-filter-cutoff-bp: >> + description: | >> + High Pass Filter (HPF) cut-off frequency expressed as a fraction of the PCM sampling rate. >> + Cut-off frequency = st,hpf-filter-cutoff-bp x Fpcm / 10000. >> + If this property is not defined the HPF is disabled. >> + enum: [625, 1250, 2500, 9500] >> + >> + st,sync: >> + description: >> + Synchronize to another filter. >> + Must contain the phandle of the filter providing the synchronization. >> + allOf: >> + - $ref: /schemas/types.yaml#/definitions/phandle-array >> + - maxItems: 1 >> + >> + st,sitf: >> + $ref: /schemas/types.yaml#/definitions/phandle-array >> + items: >> + - items: >> + - description: Phandle of the serial interface connected to the digital filter >> + - description: | >> + The phandle's argument selects the bitstream on the falling or rising edge >> + of the serial interface clock: >> + - 0: rising edge >> + - 1: falling edge >> + enum: [0, 1] >> + default: 0 >> + description: >> + Should be phandle/bitstream pair. >> + >> + required: >> + - compatible >> + - reg >> + - interrupts >> + - dmas >> + - dma-names >> + - "#io-channel-cells" >> + - "#address-cells" >> + - "#size-cells" >> + - st,sitf >> + >> + unevaluatedProperties: false >> + >> + patternProperties: >> + "^channel@([0-7])$": >> + type: object >> + $ref: adc.yaml >> + description: Represents the external channel which is connected to the MDF. >> + >> + properties: >> + reg: >> + maximum: 7 >> + >> + io-backends: >> + description: >> + Used to pipe external sigma delta modulator or internal ADC backend to MDF >> + channel. >> + maxItems: 1 >> + >> + required: >> + - reg >> + >> + unevaluatedProperties: false >> + >> + allOf: >> + - if: >> + properties: >> + compatible: >> + contains: >> + const: st,stm32mp25-mdf-adc >> + >> + then: >> + patternProperties: >> + "^channel@[0-7]$": >> + required: >> + - io-backends >> + >> + - if: >> + properties: >> + compatible: >> + contains: >> + const: st,stm32mp25-mdf-dmic >> + >> + then: >> + patternProperties: >> + "^mdf-dai+$": > > This makes no sense. Why is this a pattern and why mdf-daiiiii is > correct name? > "^mdf-dai$" is intended here > Not mentioning that your are not supposed to define properties in if > block (do you see any code like that?). Mixing addressable and > non-addressable children is another odd thing. > This binding is inspired by the one already adopted for the DFSDM https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml I assume can move the mdf-dai node definition outside the conditional branch easily. However, it seems to me more complicated to avoid mixing addressable and non-addressable nodes here. Can we keep this binding aligned with the DFSDM model? Or would you have another suggestion? > This entire schema is quite chaotic and overcomplicated. > >> + type: object >> + description: child node >> + >> + properties: >> + compatible: >> + enum: >> + - st,stm32mp25-mdf-dai >> + >> + "#sound-dai-cells": >> + const: 0 >> + >> + io-channels: >> + description: >> + From common IIO binding. Used to pipe external sigma delta >> + modulator or internal ADC output to MDF channel. >> + >> + power-domains: >> + maxItems: 1 >> + >> + port: >> + $ref: /schemas/sound/audio-graph-port.yaml# >> + unevaluatedProperties: false >> + >> + required: >> + - compatible >> + - "#sound-dai-cells" >> + - io-channels >> + >> + additionalProperties: false >> + >> +examples: >> + - | >> + #include <dt-bindings/clock/st,stm32mp25-rcc.h> >> + #include <dt-bindings/interrupt-controller/arm-gic.h> >> + mdf1: mdf@504d0000 { > > Node names should be generic. See also an explanation and list of > examples (not exhaustive) in DT specification: > https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation > If you cannot find a name matching your device, please check in kernel > sources for similar cases or you can grow the spec (via pull request to > DT spec repo). > > And drop unused labels. > The MDF is a digital filter for sigma-delta bitstreams, rather than the analog-to-digital converter itself. So "adc" would not be adapted. I did not find "filter", that probably would be the more relevant generic name. The closest similar case is the DFSDM peripheral, which already uses a specific naming: dfsdm: dfsdm@4400d000 { ... https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml What is your recommendation: keep the naming "mdf" or make a pull request to add "filter" or another more appropriate name ? >> + compatible = "st,stm32mp25-mdf"; >> + ranges = <0 0x504d0000 0x1000>; >> + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; > > Address ranges of 2 and 4 words? > These two sections correspond to MDF common registers managed by the core - Control registers: 2 x 32 bits registers - Identification registers: 4 x 32 bits registers The other registers are managed by filter and serial interface driver > Best regards, > Krzysztof > Best regards Olivier ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-06 15:48 ` Olivier MOYSAN @ 2026-10-06 15:59 ` Krzysztof Kozlowski 0 siblings, 0 replies; 31+ messages in thread From: Krzysztof Kozlowski @ 2026-10-06 15:59 UTC (permalink / raw) To: Olivier MOYSAN Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On 06/10/2026 17:48, Olivier MOYSAN wrote: >>> >>> diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >>> new file mode 100644 >>> index 000000000000..f2fbc3e150e8 >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-mdf-adc.yaml >> >> Filename follows compatible, so st,stm32mp23-mdf >> > > stmp32mp25 is the main SoC, while stm32mp23 is a variant. > file renamed st,stm32mp25-mdf.yaml Sure, that's fine. > >>> @@ -0,0 +1,383 @@ >>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) >>> +%YAML 1.2 >>> +--- >>> +$id: http://devicetree.org/schemas/iio/adc/st,stm32-mdf-adc.yaml# >>> +$schema: http://devicetree.org/meta-schemas/core.yaml# >>> + >>> +title: STMicroelectronics STM32 Multi-function Digital Filter (MDF) ADC >>> + >>> +maintainers: >>> + - Olivier Moysan <olivier.moysan@foss.st.com> >>> + >>> +description: | >>> + STM32 MDF ADC is a sigma delta analog-to-digital converter dedicated to >>> + interface external sigma delta modulators to STM32 micro controllers. >>> + >>> +properties: >>> + compatible: >>> + enum: >>> + - st,stm32mp25-mdf >>> + - st,stm32mp23-mdf >> >> Why reversed order? >> > > Ok. Reordered alphabetically > >>> + ranges: true >>> + >>> + clock-ranges: true >> >> Do you need it here? > > clock-ranges property is used to allow the filter child nodes to inherit > the MDF kernel clock from the parent node. You answered why you need it in DTS. I question why do you need it in the binding? Do you see a warning? > >> >>> + >>> + resets: >>> + maxItems: 1 >>> + >>> + reset-names: >>> + items: >>> + - const: mdf >>> + then: >>> + patternProperties: >>> + "^channel@[0-7]$": >>> + required: >>> + - io-backends >>> + >>> + - if: >>> + properties: >>> + compatible: >>> + contains: >>> + const: st,stm32mp25-mdf-dmic >>> + >>> + then: >>> + patternProperties: >>> + "^mdf-dai+$": >> >> This makes no sense. Why is this a pattern and why mdf-daiiiii is >> correct name? >> > > "^mdf-dai$" is intended here > >> Not mentioning that your are not supposed to define properties in if >> block (do you see any code like that?). Mixing addressable and >> non-addressable children is another odd thing. >> > > This binding is inspired by the one already adopted for the DFSDM > https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml > > I assume can move the mdf-dai node definition outside the conditional > branch easily. > However, it seems to me more complicated to avoid mixing addressable and > non-addressable nodes here. Can we keep this binding aligned with the > DFSDM model? Or would you have another suggestion? Why was this model chosen in that dfsdm? The child has no resources, so it should never been made a separate node. > >> This entire schema is quite chaotic and overcomplicated. >> >>> + type: object >>> + description: child node >>> + >>> + properties: >>> + compatible: >>> + enum: >>> + - st,stm32mp25-mdf-dai >>> + >>> + "#sound-dai-cells": >>> + const: 0 >>> + >>> + io-channels: >>> + description: >>> + From common IIO binding. Used to pipe external sigma delta >>> + modulator or internal ADC output to MDF channel. >>> + >>> + power-domains: >>> + maxItems: 1 >>> + >>> + port: >>> + $ref: /schemas/sound/audio-graph-port.yaml# >>> + unevaluatedProperties: false >>> + >>> + required: >>> + - compatible >>> + - "#sound-dai-cells" >>> + - io-channels >>> + >>> + additionalProperties: false >>> + >>> +examples: >>> + - | >>> + #include <dt-bindings/clock/st,stm32mp25-rcc.h> >>> + #include <dt-bindings/interrupt-controller/arm-gic.h> >>> + mdf1: mdf@504d0000 { >> >> Node names should be generic. See also an explanation and list of >> examples (not exhaustive) in DT specification: >> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation >> If you cannot find a name matching your device, please check in kernel >> sources for similar cases or you can grow the spec (via pull request to >> DT spec repo). >> >> And drop unused labels. >> > > The MDF is a digital filter for sigma-delta bitstreams, rather than the > analog-to-digital converter itself. So "adc" would not be adapted. I did > not find "filter", that probably would be the more relevant generic name. > The closest similar case is the DFSDM peripheral, which already uses a > specific naming: > dfsdm: dfsdm@4400d000 { ... > https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml > > What is your recommendation: keep the naming "mdf" or make a pull > request to add "filter" or another more appropriate name ? > >>> + compatible = "st,stm32mp25-mdf"; >>> + ranges = <0 0x504d0000 0x1000>; >>> + reg = <0x504d0000 0x8>, <0x504d0ff0 0x10>; >> >> Address ranges of 2 and 4 words? >> > > These two sections correspond to MDF common registers managed by the core > - Control registers: 2 x 32 bits registers > - Identification registers: 4 x 32 bits registers > The other registers are managed by filter and serial interface driver > Unfortunately this leaves impression of incomplete DT or too granular split of devices to match your driver model. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan ` (2 preceding siblings ...) 2026-10-02 9:22 ` Krzysztof Kozlowski @ 2026-10-02 9:34 ` Krzysztof Kozlowski 2026-10-06 16:04 ` Olivier MOYSAN 3 siblings, 1 reply; 31+ messages in thread From: Krzysztof Kozlowski @ 2026-10-02 9:34 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: > + clock-output-names: > + description: | > + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, > + but can be gated independently to save power. > + minItems: 1 > + maxItems: 2 > + oneOf: > + - items: > + - const: cck0 > + - items: > + - const: cck1 > + - items: > + - const: cck0 > + - const: cck1 Use simpler notation: minItems: 1 items: - enum - const > + > + clock-frequency: > + description: | Drop | when not needed. > + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. > + The frequency must be a multiple of the "ker_ck" clock frequency. > + maximum: 25000000 So here is the clock-frequency. No, these are output clocks as written above, so consumer sets it, not the provider. Or use existing assigned properties. This is even mentioned on DTS101 slides, really... Best regards, Krzysztof ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter 2026-10-02 9:34 ` Krzysztof Kozlowski @ 2026-10-06 16:04 ` Olivier MOYSAN 0 siblings, 0 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-06 16:04 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Maxime Coquelin, Alexandre Torgue, linux-iio, devicetree, linux-stm32, linux-arm-kernel, linux-kernel Hi Krzysztof, On 10/2/26 11:34, Krzysztof Kozlowski wrote: > On Thu, Oct 01, 2026 at 04:56:45PM +0200, Olivier Moysan wrote: >> + clock-output-names: >> + description: | >> + CCK0 and CCK1 are optional output clocks, which share the same clock frequency, >> + but can be gated independently to save power. >> + minItems: 1 >> + maxItems: 2 >> + oneOf: >> + - items: >> + - const: cck0 >> + - items: >> + - const: cck1 >> + - items: >> + - const: cck0 >> + - const: cck1 > > Use simpler notation: > minItems: 1 > items: > - enum > - const > >> + >> + clock-frequency: >> + description: | > > Drop | when not needed. > >> + Common clock frequency (Hz) for CCK0 and CCK1 output clocks. >> + The frequency must be a multiple of the "ker_ck" clock frequency. >> + maximum: 25000000 > > So here is the clock-frequency. No, these are output clocks as written > above, so consumer sets it, not the provider. Or use existing assigned > properties. This is even mentioned on DTS101 slides, really... > We expect the clock frequency to be defined statically for a given board So, using assigned-clocks properties looks the right choice. What bothers me about this solution, is that the frequency will be defined in each consumer, whereas a single rate can be defined for the provider. This may looks a bit strange, but I will implement it this way if there is no other mean to set the provider frequency. > Best regards, > Krzysztof > Best regards Olivier ^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 3/3] ASoC: stm32: add mdf dai support 2026-10-01 14:56 [PATCH 0/3] iio: adc: stm32: add mdf support for stm32mp2 Olivier Moysan 2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan @ 2026-10-01 14:56 ` Olivier Moysan 2026-10-02 9:24 ` Krzysztof Kozlowski [not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com> 2 siblings, 1 reply; 31+ messages in thread From: Olivier Moysan @ 2026-10-01 14:56 UTC (permalink / raw) To: Olivier Moysan, Arnaud Pouliquen, Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai, Maxime Coquelin, Alexandre Torgue Cc: linux-kernel, linux-sound, linux-stm32, linux-arm-kernel Add driver to handle DAI interface for PDM microphones connected to MDF STM32 IP. Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> --- sound/soc/stm/Kconfig | 15 ++ sound/soc/stm/Makefile | 3 + sound/soc/stm/stm32_amdf.c | 376 +++++++++++++++++++++++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 sound/soc/stm/stm32_amdf.c diff --git a/sound/soc/stm/Kconfig b/sound/soc/stm/Kconfig index 2753d6c2a826..6661b3a8e4f8 100644 --- a/sound/soc/stm/Kconfig +++ b/sound/soc/stm/Kconfig @@ -44,4 +44,19 @@ config SND_SOC_STM32_DFSDM Select this option to enable the STM32 Digital Filter for Sigma Delta Modulators (DFSDM) driver used in various STM32 series for digital microphone capture. + +config SND_SOC_STM32_MDF + tristate "SoC Audio support for STM32 MDF" + depends on ARCH_STM32 || COMPILE_TEST + depends on SND_SOC + depends on STM32_MDF_ADC + select SND_SOC_GENERIC_DMAENGINE_PCM + select SND_SOC_DMIC + select IIO_BUFFER_CB + help + Select this option to enable the STM32 Multi-function + Digital Filter (MDF) driver used in STM32MP2 series for + digital microphone capture. + + Module name is stm32_amdf when the driver is built as a module. endmenu diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile index 3372432faa09..4e1b3f943a44 100644 --- a/sound/soc/stm/Makefile +++ b/sound/soc/stm/Makefile @@ -16,3 +16,6 @@ obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o #DFSDM obj-$(CONFIG_SND_SOC_STM32_DFSDM) += stm32_adfsdm.o + +#MDF +obj-$(CONFIG_SND_SOC_STM32_MDF) += stm32_amdf.o diff --git a/sound/soc/stm/stm32_amdf.c b/sound/soc/stm/stm32_amdf.c new file mode 100644 index 000000000000..c946edbc2343 --- /dev/null +++ b/sound/soc/stm/stm32_amdf.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * This file is part of STM32 MDF ASoC DAI driver + * + * Copyright (C) 2023, STMicroelectronics. + * Author: Olivier Moysan <olivier.moysan@foss.st.com>. + */ + +#include <linux/clk.h> +#include <linux/iio/adc/stm32-mdf-adc.h> +#include <linux/iio/consumer.h> +#include <linux/iio/iio.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/slab.h> + +#include <sound/pcm.h> +#include <sound/soc.h> + +#define STM32_AMDF_DRV_NAME "stm32-amdf" + +#define MDF_MAX_PERIOD_SIZE (PAGE_SIZE / 2) +#define MDF_MAX_PERIODS 6 + +struct stm32_amdf_priv { + struct snd_soc_dai_driver dai_drv; + struct snd_pcm_substream *substream; + struct device *dev; + + /* IIO */ + struct iio_channel *iio_ch; + struct iio_cb_buffer *iio_cb; + bool iio_active; + + /* PCM buffer */ + unsigned char *pcm_buff; + unsigned int pos; + + struct mutex lock; /* protect against race condition on iio state */ +}; + +static const struct snd_pcm_hardware stm32_amdf_pcm_hw = { + .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_PAUSE, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, + + .channels_min = 1, + .channels_max = 1, + + .periods_min = 2, + .periods_max = MDF_MAX_PERIODS, + + .period_bytes_max = MDF_MAX_PERIOD_SIZE, + .buffer_bytes_max = MDF_MAX_PERIODS * MDF_MAX_PERIOD_SIZE +}; + +static void stm32_amdf_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct stm32_amdf_priv *priv = snd_soc_dai_get_drvdata(dai); + + mutex_lock(&priv->lock); + if (priv->iio_active) { + iio_channel_stop_all_cb(priv->iio_cb); + priv->iio_active = false; + } + mutex_unlock(&priv->lock); +} + +static int stm32_amdf_dai_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct stm32_amdf_priv *priv = snd_soc_dai_get_drvdata(dai); + int ret; + + mutex_lock(&priv->lock); + if (priv->iio_active) { + iio_channel_stop_all_cb(priv->iio_cb); + priv->iio_active = false; + } + + ret = iio_write_channel_attribute(priv->iio_ch, + substream->runtime->rate, 0, + IIO_CHAN_INFO_SAMP_FREQ); + if (ret < 0) { + dev_err(dai->dev, "%s: Failed to set %d sampling rate\n", + __func__, substream->runtime->rate); + goto out; + } + + if (!priv->iio_active) { + ret = iio_channel_start_all_cb(priv->iio_cb); + if (!ret) + priv->iio_active = true; + else + dev_err(dai->dev, "%s: IIO channel start failed (%d)\n", + __func__, ret); + } + +out: + mutex_unlock(&priv->lock); + + return ret; +} + +static const struct snd_soc_dai_ops stm32_amdf_dai_ops = { + .shutdown = stm32_amdf_shutdown, + .prepare = stm32_amdf_dai_prepare, +}; + +static const struct snd_soc_dai_driver stm32_amdf_dai = { + .capture = { + .channels_min = 1, + .channels_max = 1, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 8000, + .rate_max = 48000, + }, + .ops = &stm32_amdf_dai_ops, +}; + +static const struct snd_soc_component_driver stm32_amdf_dai_component = { + .name = "stm32_mdf_audio", +}; + +static void stm32_memcpy_32to16(void *dest, const void *src, size_t n) +{ + unsigned int i = 0; + u16 *d = (u16 *)dest, *s = (u16 *)src; + + s++; + for (i = n >> 1; i > 0; i--) { + *d++ = *s++; + s++; + } +} + +static int stm32_afsdm_pcm_cb(const void *data, size_t size, void *private) +{ + struct stm32_amdf_priv *priv = private; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(priv->substream); + u8 *pcm_buff = priv->pcm_buff; + u8 *src_buff = (u8 *)data; + unsigned int old_pos = priv->pos; + size_t buff_size = snd_pcm_lib_buffer_bytes(priv->substream); + size_t period_size = snd_pcm_lib_period_bytes(priv->substream); + size_t cur_size, src_size = size; + snd_pcm_format_t format = priv->substream->runtime->format; + + if (format == SNDRV_PCM_FORMAT_S16_LE) + src_size >>= 1; + cur_size = src_size; + + dev_dbg(rtd->dev, "%s: buff_add :%pK, pos = %d, size = %zu\n", + __func__, &pcm_buff[priv->pos], priv->pos, src_size); + + if ((priv->pos + src_size) > buff_size) { + if (format == SNDRV_PCM_FORMAT_S16_LE) + stm32_memcpy_32to16(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos); + else + memcpy(&pcm_buff[priv->pos], src_buff, buff_size - priv->pos); + cur_size -= buff_size - priv->pos; + priv->pos = 0; + } + + if (format == SNDRV_PCM_FORMAT_S16_LE) + stm32_memcpy_32to16(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], cur_size); + else + memcpy(&pcm_buff[priv->pos], &src_buff[src_size - cur_size], cur_size); + + priv->pos = (priv->pos + cur_size) % buff_size; + + if (cur_size != src_size || (old_pos && (old_pos % period_size < size))) + snd_pcm_period_elapsed(priv->substream); + + return 0; +} + +static int stm32_amdf_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_amdf_priv *priv = + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + priv->pos = 0; + return stm32_mdf_get_buff_cb(priv->iio_ch->indio_dev, stm32_afsdm_pcm_cb, priv); + case SNDRV_PCM_TRIGGER_SUSPEND: + case SNDRV_PCM_TRIGGER_STOP: + return stm32_mdf_release_buff_cb(priv->iio_ch->indio_dev); + } + + return -EINVAL; +} + +static int stm32_amdf_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_amdf_priv *priv = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + int ret; + + ret = snd_soc_set_runtime_hwparams(substream, &stm32_amdf_pcm_hw); + if (!ret) + priv->substream = substream; + + return ret; +} + +static int stm32_amdf_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_amdf_priv *priv = + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + + priv->substream = NULL; + + return 0; +} + +static snd_pcm_uframes_t stm32_amdf_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_amdf_priv *priv = + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + + return bytes_to_frames(substream->runtime, priv->pos); +} + +static int stm32_amdf_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct stm32_amdf_priv *priv = + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + + priv->pcm_buff = substream->runtime->dma_area; + + return iio_channel_cb_set_buffer_watermark(priv->iio_cb, + params_period_size(params)); +} + +static int stm32_amdf_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + struct stm32_amdf_priv *priv = + snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); + unsigned int size = MDF_MAX_PERIODS * MDF_MAX_PERIOD_SIZE; + + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + priv->dev, size, size); + + return 0; +} + +static int stm32_amdf_dummy_cb(const void *data, void *private) +{ + /* + * This dummy callback is requested by iio_channel_get_all_cb() API, + * but the stm32_mdf_get_buff_cb() API is used instead, to optimize + * DMA transfers. + */ + return 0; +} + +static void stm32_amdf_cleanup(void *data) +{ + iio_channel_release_all_cb(data); +} + +static const struct snd_soc_component_driver stm32_amdf_soc_platform = { + .open = stm32_amdf_pcm_open, + .close = stm32_amdf_pcm_close, + .hw_params = stm32_amdf_pcm_hw_params, + .trigger = stm32_amdf_trigger, + .pointer = stm32_amdf_pcm_pointer, + .pcm_new = stm32_amdf_pcm_new, + .debugfs_prefix = "pcm", +}; + +static const struct of_device_id stm32_amdf_of_match[] = { + {.compatible = "st,stm32mp25-mdf-dai"}, + {} +}; +MODULE_DEVICE_TABLE(of, stm32_amdf_of_match); + +static int stm32_amdf_probe(struct platform_device *pdev) +{ + struct stm32_amdf_priv *priv; + unsigned int channels_max; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + priv->dai_drv = stm32_amdf_dai; + priv->dai_drv.name = dev_name(&pdev->dev); + mutex_init(&priv->lock); + + dev_set_drvdata(&pdev->dev, priv); + + /* Associate iio channel */ + priv->iio_ch = devm_iio_channel_get_all(&pdev->dev); + if (IS_ERR(priv->iio_ch)) { + dev_err(&pdev->dev, "Failed to get IIO channels %ld\n", PTR_ERR(priv->iio_ch)); + return PTR_ERR(priv->iio_ch); + } + + priv->iio_cb = iio_channel_get_all_cb(&pdev->dev, &stm32_amdf_dummy_cb, NULL); + if (IS_ERR(priv->iio_cb)) { + dev_err(&pdev->dev, "Failed to get IIO callbacks %ld\n", PTR_ERR(priv->iio_cb)); + return PTR_ERR(priv->iio_cb); + } + + ret = devm_add_action_or_reset(&pdev->dev, stm32_amdf_cleanup, priv->iio_cb); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to add action\n"); + return ret; + } + + channels_max = stm32_mdf_get_sub_channels_nb(priv->iio_ch->indio_dev); + priv->dai_drv.capture.channels_max = channels_max; + + ret = devm_snd_soc_register_component(&pdev->dev, &stm32_amdf_dai_component, + &priv->dai_drv, 1); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register %s\n", stm32_amdf_dai_component.name); + return ret; + } + + ret = devm_snd_soc_register_component(&pdev->dev, &stm32_amdf_soc_platform, + NULL, 0); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register PCM platform\n"); + return ret; + } + + pm_runtime_enable(&pdev->dev); + + return ret; +} + +static void stm32_amdf_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); +} + +static struct platform_driver stm32_amdf_driver = { + .driver = { + .name = STM32_AMDF_DRV_NAME, + .of_match_table = stm32_amdf_of_match, + }, + .probe = stm32_amdf_probe, + .remove = stm32_amdf_remove, +}; + +module_platform_driver(stm32_amdf_driver); + +MODULE_DESCRIPTION("stm32 MDF DAI driver"); +MODULE_AUTHOR("Olivier Moysan <olivier.moysan@foss.st.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" STM32_AMDF_DRV_NAME); +MODULE_IMPORT_NS("IIO_CONSUMER"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 3/3] ASoC: stm32: add mdf dai support 2026-10-01 14:56 ` [PATCH 3/3] ASoC: stm32: add mdf dai support Olivier Moysan @ 2026-10-02 9:24 ` Krzysztof Kozlowski 0 siblings, 0 replies; 31+ messages in thread From: Krzysztof Kozlowski @ 2026-10-02 9:24 UTC (permalink / raw) To: Olivier Moysan Cc: Arnaud Pouliquen, Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai, Maxime Coquelin, Alexandre Torgue, linux-kernel, linux-sound, linux-stm32, linux-arm-kernel On Thu, Oct 01, 2026 at 04:56:47PM +0200, Olivier Moysan wrote: > +static struct platform_driver stm32_amdf_driver = { > + .driver = { > + .name = STM32_AMDF_DRV_NAME, > + .of_match_table = stm32_amdf_of_match, > + }, > + .probe = stm32_amdf_probe, > + .remove = stm32_amdf_remove, > +}; > + > +module_platform_driver(stm32_amdf_driver); > + > +MODULE_DESCRIPTION("stm32 MDF DAI driver"); > +MODULE_AUTHOR("Olivier Moysan <olivier.moysan@foss.st.com>"); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:" STM32_AMDF_DRV_NAME); Why do you need this? You have OF table, no? Does it mean that OF table is redundant and should be dropped? Best regards, Krzysztof ^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <20261001145702.2628429-3-olivier.moysan@foss.st.com>]
* Re: [PATCH 2/3] iio: adc: add stm32 mdf support [not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com> @ 2026-10-01 19:13 ` Andy Shevchenko 2026-10-14 16:57 ` Olivier MOYSAN 2026-10-02 9:31 ` Krzysztof Kozlowski 2026-10-19 1:36 ` Jonathan Cameron 2 siblings, 1 reply; 31+ messages in thread From: Andy Shevchenko @ 2026-10-01 19:13 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Maxime Coquelin, Alexandre Torgue, Philipp Zabel, Sumit Semwal, Christian König, linux-kernel, linux-iio, linux-stm32, linux-arm-kernel, linux-media, dri-devel, linaro-mm-sig On Thu, Oct 01, 2026 at 04:56:46PM +0200, Olivier Moysan wrote: > Add the STM32 Multi-function Digital Filter (MDF) core, serial interface > and digital filter drivers. The MDF converts bitstreams from sigma-delta > modulators or digital microphones into samples exposed through IIO. > > Audio: capture PDM microphones via cyclic DMA for an ASoC consumer. > Support CIC scaling and filtering, synchronized and interleaving modes. > Audio use case requires a DMIC filter, and a separate ASoC DAI. > > Analog: expose sigma-delta modulators as IIO voltage channels with > direct reads or DMA buffering mode. STM32 timer triggers can be used as > clock source. > Analog use case requires an IIO backend for the SD modulator. > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> > --- > drivers/iio/adc/Kconfig | 27 + > drivers/iio/adc/Makefile | 3 + > drivers/iio/adc/stm32-mdf-adc.c | 2078 +++++++++++++++++++++++++ > drivers/iio/adc/stm32-mdf-core.c | 857 ++++++++++ > drivers/iio/adc/stm32-mdf-serial.c | 309 ++++ > drivers/iio/adc/stm32-mdf.h | 312 ++++ > include/linux/iio/adc/stm32-mdf-adc.h | 19 + > 7 files changed, 3605 insertions(+) Unreviewable. Make sure the single patch is ~750 lines. -- With Best Regards, Andy Shevchenko ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 2/3] iio: adc: add stm32 mdf support 2026-10-01 19:13 ` [PATCH 2/3] iio: adc: add stm32 mdf support Andy Shevchenko @ 2026-10-14 16:57 ` Olivier MOYSAN 0 siblings, 0 replies; 31+ messages in thread From: Olivier MOYSAN @ 2026-10-14 16:57 UTC (permalink / raw) To: Andy Shevchenko Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Maxime Coquelin, Alexandre Torgue, Philipp Zabel, Sumit Semwal, Christian König, linux-kernel, linux-iio, linux-stm32, linux-arm-kernel, linux-media, dri-devel, linaro-mm-sig Hi Andy, On 10/1/26 21:13, Andy Shevchenko wrote: > On Thu, Oct 01, 2026 at 04:56:46PM +0200, Olivier Moysan wrote: >> Add the STM32 Multi-function Digital Filter (MDF) core, serial interface >> and digital filter drivers. The MDF converts bitstreams from sigma-delta >> modulators or digital microphones into samples exposed through IIO. >> >> Audio: capture PDM microphones via cyclic DMA for an ASoC consumer. >> Support CIC scaling and filtering, synchronized and interleaving modes. >> Audio use case requires a DMIC filter, and a separate ASoC DAI. >> >> Analog: expose sigma-delta modulators as IIO voltage channels with >> direct reads or DMA buffering mode. STM32 timer triggers can be used as >> clock source. >> Analog use case requires an IIO backend for the SD modulator. >> >> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> >> --- >> drivers/iio/adc/Kconfig | 27 + >> drivers/iio/adc/Makefile | 3 + >> drivers/iio/adc/stm32-mdf-adc.c | 2078 +++++++++++++++++++++++++ >> drivers/iio/adc/stm32-mdf-core.c | 857 ++++++++++ >> drivers/iio/adc/stm32-mdf-serial.c | 309 ++++ >> drivers/iio/adc/stm32-mdf.h | 312 ++++ >> include/linux/iio/adc/stm32-mdf-adc.h | 19 + >> 7 files changed, 3605 insertions(+) > > Unreviewable. Make sure the single patch is ~750 lines. > > Ok. I am preparing a v2 series to reduce the size of the patches. Best Regards olivier ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 2/3] iio: adc: add stm32 mdf support [not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com> 2026-10-01 19:13 ` [PATCH 2/3] iio: adc: add stm32 mdf support Andy Shevchenko @ 2026-10-02 9:31 ` Krzysztof Kozlowski 2026-10-19 1:36 ` Jonathan Cameron 2 siblings, 0 replies; 31+ messages in thread From: Krzysztof Kozlowski @ 2026-10-02 9:31 UTC (permalink / raw) To: Olivier Moysan Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko, Maxime Coquelin, Alexandre Torgue, Philipp Zabel, Sumit Semwal, Christian König, linux-kernel, linux-iio, linux-stm32, linux-arm-kernel, linux-media, dri-devel, linaro-mm-sig On Thu, Oct 01, 2026 at 04:56:46PM +0200, Olivier Moysan wrote: > +static int stm32_mdf_core_of_cck_get(struct platform_device *pdev, struct stm32_mdf_priv *priv) > +{ > + struct device *dev = &pdev->dev; > + u32 freq; > + int ret; > + > + ret = device_property_read_u32(dev, "clock-frequency", &freq); How? Your driver depends on OF and there is no such property in OF, so why can you read it? Otherwise what is this: "depends on (ARCH_STM32 && OF)" > + if (ret < 0) { > + /* If property does not exist return immediately */ > + if (ret == -EINVAL) > + return 0; > + > + dev_err(dev, "Failed to read clock-frequency property: %d\n", ret); > + return ret; > + } > + > + if (!freq) { > + dev_err(dev, "Null frequency not allowed for cck output frequency\n"); > + return -EINVAL; > + } > + priv->cck_freq = freq; > + > + return 0; > +} > + > +static int stm32_mdf_core_parse_clocks(struct platform_device *pdev, struct stm32_mdf_priv *priv) > +{ > + struct device *dev = &pdev->dev; > + struct clk *kclk; > + int ret; > + > + kclk = devm_clk_get(dev, "ker_ck"); > + if (IS_ERR(kclk)) > + return dev_err_probe(dev, PTR_ERR(kclk), "Failed to get kernel clock\n"); > + > + priv->kclk = kclk; > + priv->kclk_rate = clk_get_rate(kclk); > + > + /* CCK0 and CCK1 clocks are optional. Used only in SPI master modes. */ > + ret = stm32_mdf_core_of_cck_get(pdev, priv); > + if (ret) > + return ret; > + > + if (priv->cck_freq) { > + ret = stm32_mdf_core_cck_divider_set_rate(pdev, priv, priv->kclk_rate); > + if (ret) { > + dev_err(dev, "Failed to set cck rate: %d\n", ret); > + return ret; > + } > + } > + > + ret = stm32_mdf_core_register_clock_provider(pdev, priv); > + if (ret) > + return ret; > + > + return 0; > +} > + > +static int stm32_mdf_core_parse_of(struct platform_device *pdev, struct stm32_mdf_priv *priv) > +{ > + struct device_node *node = pdev->dev.of_node; > + struct reset_control *rst; > + struct device *dev = &pdev->dev; > + struct fwnode_handle *fwnode = dev_fwnode(dev); > + struct fwnode_handle *handle; > + struct fwnode_handle **fh; > + int count, ret, i; > + > + if (!node) > + return -EINVAL; > + > + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, "mdf"); > + if (IS_ERR(rst)) > + return dev_err_probe(dev, PTR_ERR(rst), "Failed to get reset controller\n"); > + > + ret = reset_control_reset(rst); > + if (ret) { > + dev_err(&pdev->dev, "reset_control_reset failed %d\n", ret); > + return ret; > + } > + > + ret = stm32_mdf_core_parse_clocks(pdev, priv); > + if (ret < 0) > + return ret; > + > + if (device_property_present(&pdev->dev, "st,interleave")) { > + count = fwnode_property_count_u32(fwnode, "st,interleave"); > + if (count < 2 || count > priv->mdf.nbf) { > + dev_err(dev, "Wrong interleave filters number [%d]\n", count); > + return -EINVAL; > + } > + > + fh = devm_kzalloc(dev, count * sizeof(*fh), GFP_KERNEL); > + if (!fh) > + return -ENOMEM; > + priv->mdf.fh_interleave = fh; > + > + for (i = 0; i < count; i++) { > + handle = fwnode_find_reference(fwnode, "st,interleave", i); > + if (IS_ERR(handle)) { > + dev_err(dev, "Failed to read filter handle: %ld\n", > + PTR_ERR(handle)); > + return PTR_ERR(handle); > + } > + priv->mdf.fh_interleave[i] = handle; > + } > + > + priv->mdf.nb_interleave = count; > + > + /* Configure GCR */ > + ret = regmap_update_bits(priv->regmap, MDF_GCR_REG, > + MDF_GCR_ILVNB_MASK, MDF_GCR_ILVNB(count - 1)); > + } > + > + return ret; > +} > + > +static const struct of_device_id stm32_mdf_of_match[] = { > + { .compatible = "st,stm32mp25-mdf" }, > + { .compatible = "st,stm32mp23-mdf", .data = (void *)STM32_MDF_MP23_FILTER_NB }, Again odd order of entries. Why doing things reverse from natural sort order? > + {} > +}; > +MODULE_DEVICE_TABLE(of, stm32_mdf_of_match); > + > +static int stm32_mdf_core_identification(struct platform_device *pdev, struct stm32_mdf_priv *priv) > +{ > + struct stm32_mdf *mdf = &priv->mdf; > + u32 val; > + int ret; > + > + /* If filter number is explicitly defined, don't check identification registers */ > + mdf->nbf = (uintptr_t)device_get_match_data(&pdev->dev); Don't use uintptr_t, but unsigned long. > + if (mdf->nbf) > + return 0; > + > + ret = regmap_read(priv->regmap, MDF_IPIDR_REG, &val); > + if (ret) > + return ret; > + > + if (val == STM32MP25_MDF_IPIDR_NUMBER) { > + ret = regmap_read(priv->regmap, MDF_HWCFGR_REG, &val); > + if (ret) > + return ret; > + > + mdf->nbf = FIELD_GET(MDF_HWCFGR_NBF_MASK, val); > + > + ret = regmap_read(priv->regmap, MDF_VERR_REG, &val); > + > + dev_dbg(&pdev->dev, "MDF version: %lu.%lu\n", FIELD_GET(MDF_VERR_MAJREV_MASK, val), > + FIELD_GET(MDF_VERR_MINREV_MASK, val)); > + } else { > + dev_err(&pdev->dev, "Unexpected ID number: 0x%x\n", val); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int stm32_mdf_core_probe(struct platform_device *pdev) > +{ > + struct stm32_mdf_priv *priv; > + struct resource *res; > + int ret; > + > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + priv->pdev = pdev; > + spin_lock_init(&priv->lock); > + > + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); > + if (IS_ERR(priv->base)) > + return PTR_ERR(priv->base); > + priv->phys_base = res->start; > + > + priv->regmap = > + devm_regmap_init_mmio_clk(&pdev->dev, "ker_ck", priv->base, &stm32_mdf_regmap_cfg); Odd wrappung. > + if (IS_ERR(priv->regmap)) { > + ret = PTR_ERR(priv->regmap); > + dev_err(&pdev->dev, "Failed to allocate regmap: %d\n", ret); We do not print allocation errors. OTOH, every other probe failure should use return dev_err_probe syntax. Again, same with bindings, please take existing recent code as starting point, not upstream your old vendor code. > + return ret; > + } > + > + ret = stm32_mdf_core_identification(pdev, priv); > + if (ret < 0) > + return ret; > + > + ret = stm32_mdf_core_parse_of(pdev, priv); > + if (ret < 0) > + return ret; > + > + INIT_LIST_HEAD(&priv->mdf.sitf_list); > + INIT_LIST_HEAD(&priv->mdf.filter_list); > + > + platform_set_drvdata(pdev, priv); > + > + pm_runtime_get_noresume(&pdev->dev); > + pm_runtime_set_active(&pdev->dev); > + pm_runtime_enable(&pdev->dev); > + > + ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); > + if (ret) > + goto pm_put; > + > + pm_runtime_put(&pdev->dev); > + > + return 0; > + > +pm_put: > + pm_runtime_disable(&pdev->dev); > + pm_runtime_set_suspended(&pdev->dev); > + pm_runtime_put_noidle(&pdev->dev); > + > + return ret; > +} > + > +static void stm32_mdf_core_remove(struct platform_device *pdev) > +{ > + pm_runtime_get_sync(&pdev->dev); > + of_platform_depopulate(&pdev->dev); > + pm_runtime_disable(&pdev->dev); > + pm_runtime_set_suspended(&pdev->dev); > + pm_runtime_put_noidle(&pdev->dev); > +} > + > +static int stm32_mdf_core_suspend(struct device *dev) > +{ > + struct stm32_mdf *mdf = dev_get_drvdata(dev); > + struct stm32_mdf_priv *priv = to_stm32_mdf_priv(mdf); > + int ret; > + > + ret = pm_runtime_force_suspend(dev); > + if (ret) > + return ret; > + > + regcache_cache_only(priv->regmap, true); > + regcache_mark_dirty(priv->regmap); > + > + /* Balance devm_regmap_init_mmio_clk() clk_prepare() */ > + clk_unprepare(priv->kclk); > + > + return pinctrl_pm_select_sleep_state(dev); > +} > + > +static int stm32_mdf_core_resume(struct device *dev) > +{ > + struct stm32_mdf *mdf = dev_get_drvdata(dev); > + struct stm32_mdf_priv *priv = to_stm32_mdf_priv(mdf); > + int ret; > + > + ret = pinctrl_pm_select_default_state(dev); > + if (ret) { > + dev_err(dev, "Failed to set pins default state: %d\n", ret); > + return ret; > + } > + > + ret = clk_prepare(priv->kclk); > + if (ret) { > + dev_err(dev, "Failed to prepare kernel clock: %d\n", ret); > + goto err_clk; > + } > + > + regcache_cache_only(priv->regmap, false); > + ret = regcache_sync(priv->regmap); > + if (ret) { > + dev_err(dev, "Failed to sync cache: %d\n", ret); > + goto err_cache; > + } > + > + return pm_runtime_force_resume(dev); > + > +err_cache: > + clk_unprepare(priv->kclk); > +err_clk: > + pinctrl_pm_select_sleep_state(dev); > + > + return ret; > +} > + > +static int stm32_mdf_core_runtime_suspend(struct device *dev) > +{ > + return 0; > +} > + > +static int stm32_mdf_core_runtime_resume(struct device *dev) > +{ > + return 0; > +} > + > +static const struct dev_pm_ops stm32_mdf_core_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(stm32_mdf_core_suspend, stm32_mdf_core_resume) > + SET_RUNTIME_PM_OPS(stm32_mdf_core_runtime_suspend, stm32_mdf_core_runtime_resume, NULL) > +}; > + > +static struct platform_driver stm32_mdf_driver = { > + .probe = stm32_mdf_core_probe, > + .remove = stm32_mdf_core_remove, > + .driver = { > + .name = "stm32-mdf", > + .of_match_table = stm32_mdf_of_match, > + .pm = &stm32_mdf_core_pm_ops, > + }, > +}; > + > +module_platform_driver(stm32_mdf_driver); > + > +MODULE_AUTHOR("Olivier Moysan <olivier.moysan@foss.st.com>"); > +MODULE_DESCRIPTION("STMicroelectronics STM32 MDF driver"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/iio/adc/stm32-mdf-serial.c b/drivers/iio/adc/stm32-mdf-serial.c > new file mode 100644 > index 000000000000..15a58cf833be > --- /dev/null > +++ b/drivers/iio/adc/stm32-mdf-serial.c > @@ -0,0 +1,309 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > +/* > + * This file is part of STM32 MDF driver > + * > + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved > + */ > + > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > +#include <linux/device.h> > +#include <linux/module.h> > +#include <linux/of_device.h> > +#include <linux/pinctrl/consumer.h> > +#include <linux/platform_device.h> > +#include <linux/regmap.h> > + > +#include "stm32-mdf.h" > + > +#define STM32_MDF_MODE_SZ 12 > + > +enum { > + STM32_MDF_SCKSRC_CCK0, > + STM32_MDF_SCKSRC_CCK1, > + STM32_MDF_SCKSRC_CLK, > + STM32_MDF_SCKSRC_NONE, > +}; > + > +struct stm32_mdf_sf_mode { > + const char *name; > + u32 mode; > +}; > + > +static const struct stm32_mdf_sf_mode stm32_mdf_mode[STM32_MDF_MODE_NB] = { > + { "spi", STM32_MDF_MODE_SPI }, > + { "lf_spi", STM32_MDF_MODE_LF_SPI }, > + { "manchester_r", STM32_MDF_MODE_MANCHESTER_R }, > + { "manchester_f", STM32_MDF_MODE_MANCHESTER_F }, > +}; > + > +static bool stm32_mdf_sitf_readable_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case MDF_SITFCR_REG: > + return true; > + default: > + return false; > + } > +} > + > +static bool stm32_mdf_sitf_writeable_reg(struct device *dev, unsigned int reg) > +{ > + switch (reg) { > + case MDF_SITFCR_REG: > + return true; > + default: > + return false; > + } > +} > + > +static const struct regmap_config stm32_sitf_regmap_cfg = { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = sizeof(u32), > + .max_register = MDF_SITFCR_REG, > + .readable_reg = stm32_mdf_sitf_readable_reg, > + .writeable_reg = stm32_mdf_sitf_writeable_reg, > + .fast_io = true, > + /* Do not use regcache as it does not support single register map */ > +}; > + > +int stm32_mdf_sitf_start(struct stm32_mdf_sitf *sitf) > +{ > + int ret; > + > + spin_lock(&sitf->lock); > + > + ret = regmap_set_bits(sitf->regmap, MDF_SITFCR_REG, MDF_SITFCR_SITFEN); > + if (!ret) > + sitf->refcnt++; > + > + spin_unlock(&sitf->lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(stm32_mdf_sitf_start); You need kerneldoc for all of exports. > + > +int stm32_mdf_sitf_stop(struct stm32_mdf_sitf *sitf) > +{ > + int ret = 0; > + > + spin_lock(&sitf->lock); > + > + if (!sitf->refcnt) { > + dev_err(sitf->dev, "Unbalanced serial interface stop ?\n"); > + ret = -EPERM; > + goto out; > + } else { > + sitf->refcnt--; > + } > + > + if (!sitf->refcnt) > + ret = regmap_clear_bits(sitf->regmap, MDF_SITFCR_REG, MDF_SITFCR_SITFEN); > + > +out: > + spin_unlock(&sitf->lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(stm32_mdf_sitf_stop); > + > +static int stm32_mdf_sitf_get_clk(struct device *dev, struct stm32_mdf_sitf *sitf) > +{ > + struct clk *sck; > + > + /* Optional clock. Clock not needed in Manchester mode */ > + sck = clk_get_optional(sitf->dev, 0); > + if (IS_ERR(sck)) > + return dev_err_probe(sitf->dev, PTR_ERR(sck), "Can't get serial clock\n"); > + > + sitf->sck = sck; > + > + if (sitf->sck) { > + if (!strncmp(__clk_get_name(sck), STM32_MDF_CCK0, sizeof(STM32_MDF_CCK0))) > + sitf->scksrc = STM32_MDF_SCKSRC_CCK0; > + else if (!strncmp(__clk_get_name(sck), STM32_MDF_CCK1, sizeof(STM32_MDF_CCK1))) > + sitf->scksrc = STM32_MDF_SCKSRC_CCK1; > + else > + sitf->scksrc = STM32_MDF_SCKSRC_CLK; > + } > + > + return 0; > +}; > + > +static int stm32_mdf_sitf_parse(struct platform_device *pdev, struct stm32_mdf_sitf *sitf) > +{ > + struct device *dev = &pdev->dev; > + const char *str; > + int ret, i = 0; > + u32 idx, mode, sitfcr; > + > + ret = device_property_read_u32(dev, "reg", &idx); > + if (ret) { > + dev_err(dev, "Could not get interface index: %d\n", ret); > + return ret; > + } > + > + if (idx % 0x80) { > + dev_err(dev, "Unexpected reg property value [%x]\n", idx); > + return -EINVAL; > + } > + > + idx = (idx >> 7) - 1; > + if (idx > sitf->mdf->nbf) { > + dev_err(dev, "Interface index [%d] exceeds maximum [%d]\n", idx, sitf->mdf->nbf); > + return -EINVAL; > + } > + > + /* Get SITF mode */ > + ret = device_property_read_string(dev, "st,sitf-mode", &str); > + if (ret) { > + dev_err(dev, "Could not get interface mode: %d\n", ret); > + return ret; > + } > + > + while (i < STM32_MDF_MODE_NB) { > + if (!strncmp(stm32_mdf_mode[i].name, str, STM32_MDF_MODE_SZ)) { > + mode = stm32_mdf_mode[i].mode; > + break; > + } > + i++; > + } > + > + if (i >= STM32_MDF_MODE_NB) { > + dev_err(dev, "Unknown serial interface mode [%s]\n", str); > + return -EINVAL; > + } > + > + sitf->mode = mode; > + sitfcr = MDF_SITFCR_SITFMOD(mode); > + > + ret = stm32_mdf_sitf_get_clk(dev, sitf); > + if (ret) > + return ret; > + > + if (mode == STM32_MDF_MODE_SPI && sitf->scksrc == STM32_MDF_SCKSRC_NONE) { > + dev_err(dev, "Missing clock for serial interface [%d] in SPI mode\n", idx); > + return -EINVAL; > + } > + > + if (mode == STM32_MDF_MODE_LF_SPI && (sitf->scksrc != STM32_MDF_SCKSRC_CCK0 && > + sitf->scksrc != STM32_MDF_SCKSRC_CCK1)) { > + dev_err(dev, "Missing CCKx clock for serial interface [%d] in LF_SPI mode\n", idx); > + return -EINVAL; > + } > + > + sitf->id = idx; > + sitf->node = dev_fwnode(dev); > + spin_lock_init(&sitf->lock); > + > + sitfcr |= MDF_SITFCR_SCKSRC(sitf->scksrc); > + > + /* Configure SITF register */ > + regmap_set_bits(sitf->regmap, MDF_SITFCR_REG, sitfcr); > + > + dev_dbg(dev, "Serial interface [%d] registered\n", idx); Drop, that's just probe success. > + > + return 0; > +} > + > +static int stm32_mdf_sitf_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct stm32_mdf_sitf *sitf; > + struct regmap *regmap; > + struct resource *res; > + void __iomem *base; > + int ret; > + > + sitf = devm_kzalloc(&pdev->dev, sizeof(*sitf), GFP_KERNEL); > + if (!sitf) > + return -ENOMEM; > + sitf->dev = dev; > + sitf->mdf = dev_get_drvdata(dev->parent); > + > + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); > + if (IS_ERR(base)) > + return PTR_ERR(base); > + > + regmap = devm_regmap_init_mmio_clk(dev, "ker_ck", base, &stm32_sitf_regmap_cfg); > + if (IS_ERR(regmap)) > + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n"); And here quite different choice. Your code is just inconsistent. > + sitf->regmap = regmap; > + > + ret = stm32_mdf_sitf_parse(pdev, sitf); > + if (ret < 0) > + return ret; Best regards, Krzysztof ^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 2/3] iio: adc: add stm32 mdf support [not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com> 2026-10-01 19:13 ` [PATCH 2/3] iio: adc: add stm32 mdf support Andy Shevchenko 2026-10-02 9:31 ` Krzysztof Kozlowski @ 2026-10-19 1:36 ` Jonathan Cameron 2 siblings, 0 replies; 31+ messages in thread From: Jonathan Cameron @ 2026-10-19 1:36 UTC (permalink / raw) To: Olivier Moysan Cc: David Lechner, Nuno Sá, Andy Shevchenko, Maxime Coquelin, Alexandre Torgue, Philipp Zabel, Sumit Semwal, Christian König, linux-kernel, linux-iio, linux-stm32, linux-arm-kernel, linux-media, dri-devel, linaro-mm-sig On Thu, 1 Oct 2026 16:56:46 +0200 Olivier Moysan <olivier.moysan@foss.st.com> wrote: > Add the STM32 Multi-function Digital Filter (MDF) core, serial interface > and digital filter drivers. The MDF converts bitstreams from sigma-delta > modulators or digital microphones into samples exposed through IIO. > > Audio: capture PDM microphones via cyclic DMA for an ASoC consumer. > Support CIC scaling and filtering, synchronized and interleaving modes. > Audio use case requires a DMIC filter, and a separate ASoC DAI. > > Analog: expose sigma-delta modulators as IIO voltage channels with > direct reads or DMA buffering mode. STM32 timer triggers can be used as > clock source. > Analog use case requires an IIO backend for the SD modulator. > > Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com> I'm not going to spend long on this today, but a few trivial things noted from a quick glance. > diff --git a/drivers/iio/adc/stm32-mdf-serial.c b/drivers/iio/adc/stm32-mdf-serial.c > new file mode 100644 > index 000000000000..15a58cf833be > --- /dev/null > +++ b/drivers/iio/adc/stm32-mdf-serial.c ... > + > +int stm32_mdf_sitf_stop(struct stm32_mdf_sitf *sitf) > +{ > + int ret = 0; > + > + spin_lock(&sitf->lock); Use guard() for cases like this. Simplifies the flow and helps readabilty as a result. Everyone loves an early return. > + > + if (!sitf->refcnt) { > + dev_err(sitf->dev, "Unbalanced serial interface stop ?\n"); > + ret = -EPERM; > + goto out; > + } else { > + sitf->refcnt--; > + } > + > + if (!sitf->refcnt) > + ret = regmap_clear_bits(sitf->regmap, MDF_SITFCR_REG, MDF_SITFCR_SITFEN); > + > +out: > + spin_unlock(&sitf->lock); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(stm32_mdf_sitf_stop); > > +static int stm32_mdf_sitf_runtime_suspend(struct device *dev) > +{ Add a comment on why you need these. > + return 0; > +} > + > +static int stm32_mdf_sitf_runtime_resume(struct device *dev) > +{ > + return 0; > +} > diff --git a/drivers/iio/adc/stm32-mdf.h b/drivers/iio/adc/stm32-mdf.h > new file mode 100644 > index 000000000000..7e403c26d4dc > --- /dev/null > +++ b/drivers/iio/adc/stm32-mdf.h > @@ -0,0 +1,312 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * This file is part of STM32 MDF driver > + * > + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved I'd guess you'll modify it enough that this might need an update! > +/* MDF_SIDR: Size Identification Register */ > +#define MDF_SIDR_SID_MASK GENMASK(31, 0) > +#define MDF_SIDR_SID(v) FIELD_PREP(MDF_SIDR_SID_MASK, v) I'd not bother with the second macro. It is only a little shorter than FIELD_PREP() in most case. > ^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2026-10-19 18:55 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-01 14:56 [PATCH 0/3] iio: adc: stm32: add mdf support for stm32mp2 Olivier Moysan
2026-10-01 14:56 ` [PATCH 1/3] dt-bindings: iio: adc: add bindings for stm32 mdf filter Olivier Moysan
2026-10-01 16:25 ` Rob Herring (Arm)
2026-10-01 18:32 ` Conor Dooley
2026-10-07 9:01 ` Olivier MOYSAN
2026-10-07 13:47 ` Rob Herring
2026-10-07 16:02 ` Olivier MOYSAN
2026-10-08 10:11 ` Conor Dooley
2026-10-08 16:37 ` Olivier MOYSAN
2026-10-09 19:12 ` Conor Dooley
2026-10-12 12:56 ` Olivier MOYSAN
2026-10-14 15:15 ` Conor Dooley
2026-10-14 16:51 ` Olivier MOYSAN
2026-10-14 22:49 ` Conor Dooley
2026-10-15 9:19 ` Olivier MOYSAN
2026-10-15 12:34 ` Conor Dooley
2026-10-19 1:25 ` Jonathan Cameron
2026-10-19 16:17 ` Olivier MOYSAN
2026-10-19 1:30 ` Jonathan Cameron
2026-10-19 18:55 ` Conor Dooley
2026-10-02 9:22 ` Krzysztof Kozlowski
2026-10-06 15:48 ` Olivier MOYSAN
2026-10-06 15:59 ` Krzysztof Kozlowski
2026-10-02 9:34 ` Krzysztof Kozlowski
2026-10-06 16:04 ` Olivier MOYSAN
2026-10-01 14:56 ` [PATCH 3/3] ASoC: stm32: add mdf dai support Olivier Moysan
2026-10-02 9:24 ` Krzysztof Kozlowski
[not found] ` <20261001145702.2628429-3-olivier.moysan@foss.st.com>
2026-10-01 19:13 ` [PATCH 2/3] iio: adc: add stm32 mdf support Andy Shevchenko
2026-10-14 16:57 ` Olivier MOYSAN
2026-10-02 9:31 ` Krzysztof Kozlowski
2026-10-19 1:36 ` Jonathan Cameron
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox