* [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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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 ` Andy Shevchenko
2026-10-02 9:31 ` Krzysztof Kozlowski
1 sibling, 0 replies; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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
1 sibling, 0 replies; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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
0 siblings, 0 replies; 18+ 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] 18+ messages in thread
end of thread, other threads:[~2026-10-08 16:37 UTC | newest]
Thread overview: 18+ 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-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-02 9:31 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox