From 4134cd0a2ec7d17327dbdf141ec05268e195cd71 Mon Sep 17 00:00:00 2001
From: Romuald JEANNE <romuald.jeanne@st.com>
Date: Tue, 13 Nov 2018 12:19:04 +0100
Subject: [PATCH 05/52] ARM: stm32mp1-r0-rc1: IIO

---
 drivers/iio/adc/Kconfig                   |   10 +
 drivers/iio/adc/Makefile                  |    1 +
 drivers/iio/adc/stm32-adc-core.c          |  399 ++++++--
 drivers/iio/adc/stm32-adc-core.h          |   87 ++
 drivers/iio/adc/stm32-adc-temp.c          |  412 +++++++++
 drivers/iio/adc/stm32-adc.c               | 1431 ++++++++++++++++++++++++-----
 drivers/iio/adc/stm32-dfsdm-adc.c         |  627 ++++++++++---
 drivers/iio/adc/stm32-dfsdm-core.c        |  176 +++-
 drivers/iio/counter/stm32-lptimer-cnt.c   |   55 ++
 drivers/iio/trigger/stm32-timer-trigger.c |  167 +++-
 10 files changed, 2870 insertions(+), 495 deletions(-)
 create mode 100644 drivers/iio/adc/stm32-adc-temp.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4a75492..f2c1d8b 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -679,6 +679,16 @@ config STM32_ADC
 	  This driver can also be built as a module.  If so, the module
 	  will be called stm32-adc.
 
+config STM32_ADC_TEMP
+	tristate "STMicroelectronics STM32 ADC temperature sensor"
+	depends on STM32_ADC
+	help
+	  Select this option to enable the driver for temperature sensor
+	  connected internally to STM32 ADC.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called stm32-adc-temp.
+
 config STM32_DFSDM_CORE
 	tristate "STMicroelectronics STM32 DFSDM core"
 	depends on (ARCH_STM32 && OF) || COMPILE_TEST
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 03db7b5..527f9ef 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_STX104) += stx104.o
 obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o
 obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
 obj-$(CONFIG_STM32_ADC) += stm32-adc.o
+obj-$(CONFIG_STM32_ADC_TEMP) += stm32-adc-temp.o
 obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o
 obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index ca432e7..a32e826 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -10,12 +10,16 @@
  */
 
 #include <linux/clk.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
 #include <linux/interrupt.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdesc.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
@@ -23,12 +27,29 @@
 
 /* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
 #define STM32F4_ADC_CSR			(STM32_ADCX_COMN_OFFSET + 0x00)
-#define STM32F4_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x04)
 
 /* STM32F4_ADC_CSR - bit fields */
+#define STM32F4_OVR3			BIT(21)
+#define STM32F4_JEOC3			BIT(18)
 #define STM32F4_EOC3			BIT(17)
+#define STM32F4_AWD3			BIT(16)
+#define STM32F4_OVR2			BIT(13)
+#define STM32F4_JEOC2			BIT(10)
 #define STM32F4_EOC2			BIT(9)
+#define STM32F4_AWD2			BIT(8)
+#define STM32F4_OVR1			BIT(5)
+#define STM32F4_JEOC1			BIT(2)
 #define STM32F4_EOC1			BIT(1)
+#define STM32F4_AWD1			BIT(0)
+#define STM32F4_EOC_MASK1		(STM32F4_EOC1 | STM32F4_AWD1 | \
+					 STM32F4_OVR1)
+#define STM32F4_EOC_MASK2		(STM32F4_EOC2 | STM32F4_AWD2 | \
+					 STM32F4_OVR2)
+#define STM32F4_EOC_MASK3		(STM32F4_EOC3 | STM32F4_AWD3 | \
+					 STM32F4_OVR3)
+#define STM32F4_JEOC_MASK1		(STM32F4_JEOC1 | STM32F4_AWD1)
+#define STM32F4_JEOC_MASK2		(STM32F4_JEOC2 | STM32F4_AWD2)
+#define STM32F4_JEOC_MASK3		(STM32F4_JEOC3 | STM32F4_AWD3)
 
 /* STM32F4_ADC_CCR - bit fields */
 #define STM32F4_ADC_ADCPRE_SHIFT	16
@@ -36,11 +57,30 @@
 
 /* STM32H7 - common registers for all ADC instances */
 #define STM32H7_ADC_CSR			(STM32_ADCX_COMN_OFFSET + 0x00)
-#define STM32H7_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x08)
 
 /* STM32H7_ADC_CSR - bit fields */
+#define STM32H7_AWD3_SLV		BIT(25)
+#define STM32H7_AWD2_SLV		BIT(24)
+#define STM32H7_AWD1_SLV		BIT(23)
+#define STM32H7_JEOS_SLV		BIT(22)
+#define STM32H7_OVR_SLV			BIT(20)
 #define STM32H7_EOC_SLV			BIT(18)
+#define STM32H7_AWD3_MST		BIT(9)
+#define STM32H7_AWD2_MST		BIT(8)
+#define STM32H7_AWD1_MST		BIT(7)
+#define STM32H7_JEOS_MST		BIT(6)
+#define STM32H7_OVR_MST			BIT(4)
 #define STM32H7_EOC_MST			BIT(2)
+#define STM32H7_EOC_MASK1		(STM32H7_EOC_MST | STM32H7_AWD1_MST | \
+					 STM32H7_AWD2_MST | STM32H7_AWD3_MST | \
+					 STM32H7_OVR_MST)
+#define STM32H7_EOC_MASK2		(STM32H7_EOC_SLV | STM32H7_AWD1_SLV | \
+					 STM32H7_AWD2_SLV | STM32H7_AWD3_SLV | \
+					 STM32H7_OVR_SLV)
+#define STM32H7_JEOC_MASK1		(STM32H7_JEOS_MST | STM32H7_AWD1_MST | \
+					 STM32H7_AWD2_MST | STM32H7_AWD3_MST)
+#define STM32H7_JEOC_MASK2		(STM32H7_JEOS_SLV | STM32H7_AWD1_SLV | \
+					 STM32H7_AWD2_SLV | STM32H7_AWD3_SLV)
 
 /* STM32H7_ADC_CCR - bit fields */
 #define STM32H7_PRESC_SHIFT		18
@@ -51,15 +91,23 @@
 /**
  * stm32_adc_common_regs - stm32 common registers, compatible dependent data
  * @csr:	common status register offset
+ * @ccr:	common control register offset
  * @eoc1:	adc1 end of conversion flag in @csr
  * @eoc2:	adc2 end of conversion flag in @csr
  * @eoc3:	adc3 end of conversion flag in @csr
+ * @jeoc1:	adc1 end of injected conversion flag in @csr
+ * @jeoc2:	adc2 end of injected conversion flag in @csr
+ * @jeoc3:	adc3 end of injected conversion flag in @csr
  */
 struct stm32_adc_common_regs {
 	u32 csr;
+	u32 ccr;
 	u32 eoc1_msk;
 	u32 eoc2_msk;
 	u32 eoc3_msk;
+	u32 jeoc1_msk;
+	u32 jeoc2_msk;
+	u32 jeoc3_msk;
 };
 
 struct stm32_adc_priv;
@@ -69,11 +117,13 @@ struct stm32_adc_priv;
  * @regs:	common registers for all instances
  * @clk_sel:	clock selection routine
  * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
+ * @exti_trigs	EXTI triggers info
  */
 struct stm32_adc_priv_cfg {
 	const struct stm32_adc_common_regs *regs;
 	int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
 	u32 max_clk_rate_hz;
+	struct stm32_adc_trig_info *exti_trigs;
 };
 
 /**
@@ -82,18 +132,22 @@ struct stm32_adc_priv_cfg {
  * @domain:		irq domain reference
  * @aclk:		clock reference for the analog circuitry
  * @bclk:		bus clock common for all ADCs, depends on part used
+ * @max_clk_rate	desired maximum clock rate
  * @vref:		regulator reference
  * @cfg:		compatible configuration data
  * @common:		common data for all ADC instances
+ * @ccr_bak:		backup'ed CCR in low power mode
  */
 struct stm32_adc_priv {
 	int				irq[STM32_ADC_MAX_ADCS];
 	struct irq_domain		*domain;
 	struct clk			*aclk;
 	struct clk			*bclk;
+	u32				max_clk_rate;
 	struct regulator		*vref;
 	const struct stm32_adc_priv_cfg	*cfg;
 	struct stm32_adc_common		common;
+	u32				ccr_bak;
 };
 
 static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
@@ -129,7 +183,7 @@ static int stm32f4_adc_clk_sel(struct platform_device *pdev,
 	}
 
 	for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
-		if ((rate / stm32f4_pclk_div[i]) <= priv->cfg->max_clk_rate_hz)
+		if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate)
 			break;
 	}
 	if (i >= ARRAY_SIZE(stm32f4_pclk_div)) {
@@ -218,7 +272,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
 			if (ckmode)
 				continue;
 
-			if ((rate / div) <= priv->cfg->max_clk_rate_hz)
+			if ((rate / div) <= priv->max_clk_rate)
 				goto out;
 		}
 	}
@@ -238,7 +292,7 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
 		if (!ckmode)
 			continue;
 
-		if ((rate / div) <= priv->cfg->max_clk_rate_hz)
+		if ((rate / div) <= priv->max_clk_rate)
 			goto out;
 	}
 
@@ -265,16 +319,23 @@ static int stm32h7_adc_clk_sel(struct platform_device *pdev,
 /* STM32F4 common registers definitions */
 static const struct stm32_adc_common_regs stm32f4_adc_common_regs = {
 	.csr = STM32F4_ADC_CSR,
-	.eoc1_msk = STM32F4_EOC1,
-	.eoc2_msk = STM32F4_EOC2,
-	.eoc3_msk = STM32F4_EOC3,
+	.ccr = STM32F4_ADC_CCR,
+	.eoc1_msk = STM32F4_EOC_MASK1,
+	.eoc2_msk = STM32F4_EOC_MASK2,
+	.eoc3_msk = STM32F4_EOC_MASK3,
+	.jeoc1_msk = STM32F4_JEOC_MASK1,
+	.jeoc2_msk = STM32F4_JEOC_MASK2,
+	.jeoc3_msk = STM32F4_JEOC_MASK3,
 };
 
 /* STM32H7 common registers definitions */
 static const struct stm32_adc_common_regs stm32h7_adc_common_regs = {
 	.csr = STM32H7_ADC_CSR,
-	.eoc1_msk = STM32H7_EOC_MST,
-	.eoc2_msk = STM32H7_EOC_SLV,
+	.ccr = STM32H7_ADC_CCR,
+	.eoc1_msk = STM32H7_EOC_MASK1,
+	.eoc2_msk = STM32H7_EOC_MASK2,
+	.jeoc1_msk = STM32H7_JEOC_MASK1,
+	.jeoc2_msk = STM32H7_JEOC_MASK2,
 };
 
 /* ADC common interrupt for all instances */
@@ -296,6 +357,15 @@ static void stm32_adc_irq_handler(struct irq_desc *desc)
 	if (status & priv->cfg->regs->eoc3_msk)
 		generic_handle_irq(irq_find_mapping(priv->domain, 2));
 
+	if (status & priv->cfg->regs->jeoc1_msk)
+		generic_handle_irq(irq_find_mapping(priv->domain, 3));
+
+	if (status & priv->cfg->regs->jeoc2_msk)
+		generic_handle_irq(irq_find_mapping(priv->domain, 4));
+
+	if (status & priv->cfg->regs->jeoc3_msk)
+		generic_handle_irq(irq_find_mapping(priv->domain, 5));
+
 	chained_irq_exit(chip, desc);
 };
 
@@ -344,7 +414,8 @@ static int stm32_adc_irq_probe(struct platform_device *pdev,
 		}
 	}
 
-	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
+	/* 2 interrupt sources per ADC instance: regular & injected */
+	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS * 2, 0,
 					     &stm32_adc_domain_ops,
 					     priv);
 	if (!priv->domain) {
@@ -368,7 +439,7 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
 	int hwirq;
 	unsigned int i;
 
-	for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
+	for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS * 2; hwirq++)
 		irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
 	irq_domain_remove(priv->domain);
 
@@ -379,13 +450,186 @@ static void stm32_adc_irq_remove(struct platform_device *pdev,
 	}
 }
 
+static struct stm32_adc_trig_info stm32f4_adc_exti_trigs[] = {
+	{ "exti11", STM32_EXT15, 0, TRG_REGULAR },
+	{ "exti15", 0, STM32_EXT15, TRG_INJECTED },
+	{},
+};
+
+static struct stm32_adc_trig_info stm32h7_adc_exti_trigs[] = {
+	{ "exti11", STM32_EXT6, 0, TRG_REGULAR },
+	{ "exti15", 0, STM32_EXT6, TRG_INJECTED },
+	{},
+};
+
+static int is_stm32_adc_child_dev(struct device *dev, void *data)
+{
+	return dev == data;
+}
+
+static int stm32_adc_validate_device(struct iio_trigger *trig,
+				     struct iio_dev *indio_dev)
+{
+	/* Iterate over stm32 adc child devices, is indio_dev one of them ? */
+	if (device_for_each_child(trig->dev.parent, indio_dev->dev.parent,
+				  is_stm32_adc_child_dev))
+		return 0;
+
+	return -EINVAL;
+}
+
+static const struct iio_trigger_ops stm32_adc_trigger_ops = {
+	.validate_device = stm32_adc_validate_device,
+};
+
+static irqreturn_t stm32_adc_trigger_isr(int irq, void *p)
+{
+	/* EXTI handler shouldn't be invoked, and isn't used */
+	return IRQ_HANDLED;
+}
+
+static struct iio_trigger *stm32_adc_trig_alloc_register(
+					struct platform_device *pdev,
+					struct stm32_adc_priv *priv,
+					struct stm32_adc_trig_info *trinfo)
+{
+	struct iio_trigger *trig;
+	int ret;
+
+	trig = devm_iio_trigger_alloc(&pdev->dev, "%s-%s", trinfo->name,
+				      dev_name(&pdev->dev));
+	if (!trig)
+		return ERR_PTR(-ENOMEM);
+
+	trig->dev.parent = &pdev->dev;
+	trig->ops = &stm32_adc_trigger_ops;
+	iio_trigger_set_drvdata(trig, trinfo);
+
+	ret = devm_iio_trigger_register(&pdev->dev, trig);
+	if (ret) {
+		dev_err(&pdev->dev, "%s trig register failed\n", trinfo->name);
+		return ERR_PTR(ret);
+	}
+
+	list_add_tail(&trig->alloc_list, &priv->common.extrig_list);
+
+	return trig;
+}
+
+static int stm32_adc_triggers_probe(struct platform_device *pdev,
+				    struct stm32_adc_priv *priv)
+{
+	struct device_node *child, *node = pdev->dev.of_node;
+	struct stm32_adc_trig_info *trinfo = priv->cfg->exti_trigs;
+	struct iio_trigger *trig;
+	int i, irq, ret;
+
+	INIT_LIST_HEAD(&priv->common.extrig_list);
+
+	for (i = 0; trinfo && trinfo[i].name; i++) {
+		for_each_available_child_of_node(node, child) {
+			if (of_property_match_string(child, "trigger-name",
+						     trinfo[i].name) < 0)
+				continue;
+			trig = stm32_adc_trig_alloc_register(pdev, priv,
+							     &trinfo[i]);
+			if (IS_ERR(trig))
+				return PTR_ERR(trig);
+
+			/*
+			 * STM32 ADC can use EXTI GPIO (external interrupt line)
+			 * as trigger source. EXTI line can generate IRQs and/or
+			 * be used as trigger: EXTI line is hard wired as
+			 * an input of ADC trigger selection MUX (muxed in with
+			 * extsel on ADC controller side).
+			 * Getting IRQs when trigger occurs is unused, rely on
+			 * EOC interrupt instead. So, get EXTI IRQ, then mask it
+			 * by default (on EXTI controller). After this, EXTI
+			 * line HW path is configured (GPIO->EXTI->ADC),
+			 */
+			irq = of_irq_get(child, 0);
+			if (irq <= 0) {
+				dev_err(&pdev->dev, "Can't get trigger irq\n");
+				return irq ? irq : -ENODEV;
+			}
+
+			ret = devm_request_irq(&pdev->dev, irq,
+					       stm32_adc_trigger_isr, 0, NULL,
+					       trig);
+			if (ret) {
+				dev_err(&pdev->dev, "Request IRQ failed\n");
+				return ret;
+			}
+			disable_irq(irq);
+		}
+	}
+
+	return 0;
+}
+
+static int stm32_adc_core_hw_start(struct device *dev)
+{
+	struct stm32_adc_common *common = dev_get_drvdata(dev);
+	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
+	int ret;
+
+	ret = regulator_enable(priv->vref);
+	if (ret < 0) {
+		dev_err(dev, "vref enable failed\n");
+		return ret;
+	}
+
+	if (priv->bclk) {
+		ret = clk_prepare_enable(priv->bclk);
+		if (ret < 0) {
+			dev_err(dev, "bus clk enable failed\n");
+			goto err_regulator_disable;
+		}
+	}
+
+	if (priv->aclk) {
+		ret = clk_prepare_enable(priv->aclk);
+		if (ret < 0) {
+			dev_err(dev, "adc clk enable failed\n");
+			goto err_bclk_disable;
+		}
+	}
+
+	writel_relaxed(priv->ccr_bak, priv->common.base + priv->cfg->regs->ccr);
+
+	return 0;
+
+err_bclk_disable:
+	if (priv->bclk)
+		clk_disable_unprepare(priv->bclk);
+err_regulator_disable:
+	regulator_disable(priv->vref);
+
+	return ret;
+}
+
+static void stm32_adc_core_hw_stop(struct device *dev)
+{
+	struct stm32_adc_common *common = dev_get_drvdata(dev);
+	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
+
+	/* Backup CCR that may be lost (depends on power state to achieve) */
+	priv->ccr_bak = readl_relaxed(priv->common.base + priv->cfg->regs->ccr);
+	if (priv->aclk)
+		clk_disable_unprepare(priv->aclk);
+	if (priv->bclk)
+		clk_disable_unprepare(priv->bclk);
+	regulator_disable(priv->vref);
+}
+
 static int stm32_adc_probe(struct platform_device *pdev)
 {
 	struct stm32_adc_priv *priv;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = pdev->dev.of_node;
 	struct resource *res;
-	int ret;
+	u32 max_rate;
+	int i, ret;
 
 	if (!pdev->dev.of_node)
 		return -ENODEV;
@@ -393,6 +637,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
+	platform_set_drvdata(pdev, &priv->common);
 
 	priv->cfg = (const struct stm32_adc_priv_cfg *)
 		of_match_device(dev->driver->of_match_table, dev)->data;
@@ -402,6 +647,8 @@ static int stm32_adc_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->common.base))
 		return PTR_ERR(priv->common.base);
 	priv->common.phys_base = res->start;
+	for (i = 0; i < STM32_ADC_MAX_ADCS; i++)
+		mutex_init(&priv->common.inj[i]);
 
 	priv->vref = devm_regulator_get(&pdev->dev, "vref");
 	if (IS_ERR(priv->vref)) {
@@ -410,67 +657,60 @@ static int stm32_adc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = regulator_enable(priv->vref);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "vref enable failed\n");
-		return ret;
-	}
-
-	ret = regulator_get_voltage(priv->vref);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
-		goto err_regulator_disable;
-	}
-	priv->common.vref_mv = ret / 1000;
-	dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
-
 	priv->aclk = devm_clk_get(&pdev->dev, "adc");
 	if (IS_ERR(priv->aclk)) {
 		ret = PTR_ERR(priv->aclk);
-		if (ret == -ENOENT) {
-			priv->aclk = NULL;
-		} else {
+		if (ret != -ENOENT) {
 			dev_err(&pdev->dev, "Can't get 'adc' clock\n");
-			goto err_regulator_disable;
-		}
-	}
-
-	if (priv->aclk) {
-		ret = clk_prepare_enable(priv->aclk);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "adc clk enable failed\n");
-			goto err_regulator_disable;
+			return ret;
 		}
+		priv->aclk = NULL;
 	}
 
 	priv->bclk = devm_clk_get(&pdev->dev, "bus");
 	if (IS_ERR(priv->bclk)) {
 		ret = PTR_ERR(priv->bclk);
-		if (ret == -ENOENT) {
-			priv->bclk = NULL;
-		} else {
+		if (ret != -ENOENT) {
 			dev_err(&pdev->dev, "Can't get 'bus' clock\n");
-			goto err_aclk_disable;
+			return ret;
 		}
+		priv->bclk = NULL;
 	}
 
-	if (priv->bclk) {
-		ret = clk_prepare_enable(priv->bclk);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "adc clk enable failed\n");
-			goto err_aclk_disable;
-		}
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	ret = stm32_adc_core_hw_start(dev);
+	if (ret)
+		goto err_pm_stop;
+
+	ret = regulator_get_voltage(priv->vref);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
+		goto err_hw_stop;
 	}
+	priv->common.vref_mv = ret / 1000;
+	dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
+
+	ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz",
+				   &max_rate);
+	if (!ret)
+		priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz);
+	else
+		priv->max_clk_rate = priv->cfg->max_clk_rate_hz;
 
 	ret = priv->cfg->clk_sel(pdev, priv);
 	if (ret < 0)
-		goto err_bclk_disable;
+		goto err_hw_stop;
 
 	ret = stm32_adc_irq_probe(pdev, priv);
 	if (ret < 0)
-		goto err_bclk_disable;
+		goto err_hw_stop;
 
-	platform_set_drvdata(pdev, &priv->common);
+	ret = stm32_adc_triggers_probe(pdev, priv);
+	if (ret < 0)
+		goto err_irq_remove;
 
 	ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
 	if (ret < 0) {
@@ -478,21 +718,18 @@ static int stm32_adc_probe(struct platform_device *pdev)
 		goto err_irq_remove;
 	}
 
+	pm_runtime_put(dev);
+
 	return 0;
 
 err_irq_remove:
 	stm32_adc_irq_remove(pdev, priv);
-
-err_bclk_disable:
-	if (priv->bclk)
-		clk_disable_unprepare(priv->bclk);
-
-err_aclk_disable:
-	if (priv->aclk)
-		clk_disable_unprepare(priv->aclk);
-
-err_regulator_disable:
-	regulator_disable(priv->vref);
+err_hw_stop:
+	stm32_adc_core_hw_stop(dev);
+err_pm_stop:
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	return ret;
 }
@@ -502,33 +739,58 @@ static int stm32_adc_remove(struct platform_device *pdev)
 	struct stm32_adc_common *common = platform_get_drvdata(pdev);
 	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
 
+	pm_runtime_get_sync(&pdev->dev);
 	of_platform_depopulate(&pdev->dev);
 	stm32_adc_irq_remove(pdev, priv);
-	if (priv->bclk)
-		clk_disable_unprepare(priv->bclk);
-	if (priv->aclk)
-		clk_disable_unprepare(priv->aclk);
-	regulator_disable(priv->vref);
+	stm32_adc_core_hw_stop(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 
 	return 0;
 }
 
+#if defined(CONFIG_PM)
+static int stm32_adc_core_runtime_suspend(struct device *dev)
+{
+	stm32_adc_core_hw_stop(dev);
+
+	return 0;
+}
+
+static int stm32_adc_core_runtime_resume(struct device *dev)
+{
+	return stm32_adc_core_hw_start(dev);
+}
+#endif
+
+static const struct dev_pm_ops stm32_adc_core_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
+			   stm32_adc_core_runtime_resume,
+			   NULL)
+};
+
 static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
 	.regs = &stm32f4_adc_common_regs,
 	.clk_sel = stm32f4_adc_clk_sel,
 	.max_clk_rate_hz = 36000000,
+	.exti_trigs = stm32f4_adc_exti_trigs,
 };
 
 static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
 	.regs = &stm32h7_adc_common_regs,
 	.clk_sel = stm32h7_adc_clk_sel,
 	.max_clk_rate_hz = 36000000,
+	.exti_trigs = stm32h7_adc_exti_trigs,
 };
 
 static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
 	.regs = &stm32h7_adc_common_regs,
 	.clk_sel = stm32h7_adc_clk_sel,
 	.max_clk_rate_hz = 40000000,
+	.exti_trigs = stm32h7_adc_exti_trigs,
 };
 
 static const struct of_device_id stm32_adc_of_match[] = {
@@ -552,6 +814,7 @@ static struct platform_driver stm32_adc_driver = {
 	.driver = {
 		.name = "stm32-adc-core",
 		.of_match_table = stm32_adc_of_match,
+		.pm = &stm32_adc_core_pm_ops,
 	},
 };
 module_platform_driver(stm32_adc_driver);
diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
index 8af507b..a209ea4 100644
--- a/drivers/iio/adc/stm32-adc-core.h
+++ b/drivers/iio/adc/stm32-adc-core.h
@@ -25,20 +25,107 @@
  * --------------------------------------------------------
  */
 #define STM32_ADC_MAX_ADCS		3
+#define STM32_ADC_OFFSET		0x100
 #define STM32_ADCX_COMN_OFFSET		0x300
 
+/* Number of linear calibration shadow registers / LINCALRDYW control bits */
+#define STM32H7_LINCALFACT_NUM		6
+
+/**
+ * struct stm32_adc_calib - optional adc calibration data
+ * @calfact_s: Calibration offset for single ended channels
+ * @calfact_d: Calibration offset in differential
+ * @lincalfact: Linearity calibration factor
+ * @calibrated: Indicates calibration status
+ */
+struct stm32_adc_calib {
+	u32			calfact_s;
+	u32			calfact_d;
+	u32			lincalfact[STM32H7_LINCALFACT_NUM];
+	bool			calibrated;
+};
+
+/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
+#define STM32F4_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x04)
+
+/* STM32F4_ADC_CCR - bit fields */
+#define STM32F4_ADC_TSVREFE		BIT(23)
+
+/* STM32H7 - common registers for all ADC instances */
+#define STM32H7_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32H7_ADC_CCR - bit fields */
+#define STM32H7_VSENSEEN		BIT(23)
+
 /**
  * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
  * @base:		control registers base cpu addr
  * @phys_base:		control registers base physical addr
  * @rate:		clock rate used for analog circuitry
  * @vref_mv:		vref voltage (mv)
+ * @extrig_list:	External trigger list registered by adc core
+ *
+ * Reserved variables for child devices, shared between regular/injected:
+ * @difsel		bitmask array to set single-ended/differential channel
+ * @pcsel		bitmask array to preselect channels on some devices
+ * @smpr_val:		sampling time settings (e.g. smpr1 / smpr2)
  */
 struct stm32_adc_common {
 	void __iomem			*base;
 	phys_addr_t			phys_base;
 	unsigned long			rate;
 	int				vref_mv;
+	struct list_head		extrig_list;
+	u32				difsel[STM32_ADC_MAX_ADCS];
+	u32				pcsel[STM32_ADC_MAX_ADCS];
+	u32				smpr_val[STM32_ADC_MAX_ADCS][2];
+	int				prepcnt[STM32_ADC_MAX_ADCS];
+	struct mutex			inj[STM32_ADC_MAX_ADCS]; /* injected */
+	struct stm32_adc_calib		cal[STM32_ADC_MAX_ADCS];
+};
+
+/* extsel - trigger mux selection value */
+enum stm32_adc_extsel {
+	STM32_EXT0,
+	STM32_EXT1,
+	STM32_EXT2,
+	STM32_EXT3,
+	STM32_EXT4,
+	STM32_EXT5,
+	STM32_EXT6,
+	STM32_EXT7,
+	STM32_EXT8,
+	STM32_EXT9,
+	STM32_EXT10,
+	STM32_EXT11,
+	STM32_EXT12,
+	STM32_EXT13,
+	STM32_EXT14,
+	STM32_EXT15,
+	STM32_EXT16,
+	STM32_EXT17,
+	STM32_EXT18,
+	STM32_EXT19,
+	STM32_EXT20,
+};
+
+/* trigger information flags */
+#define TRG_REGULAR	BIT(0)
+#define TRG_INJECTED	BIT(1)
+#define TRG_BOTH	(TRG_REGULAR | TRG_INJECTED)
+
+/**
+ * struct stm32_adc_trig_info - ADC trigger info
+ * @name:		name of the trigger, corresponding to its source
+ * @extsel:		regular trigger selection
+ * @jextsel:		injected trigger selection
+ * @flags:		trigger flags: e.g. for regular, injected or both
+ */
+struct stm32_adc_trig_info {
+	const char *name;
+	u32 extsel;
+	u32 jextsel;
+	u32 flags;
 };
 
 #endif
diff --git a/drivers/iio/adc/stm32-adc-temp.c b/drivers/iio/adc/stm32-adc-temp.c
new file mode 100644
index 0000000..dd31916
--- /dev/null
+++ b/drivers/iio/adc/stm32-adc-temp.c
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * STM32 ADC temperature sensor driver.
+ * This file is part of STM32 ADC driver.
+ *
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com> for STMicroelectronics.
+ */
+
+#include <linux/delay.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#include "stm32-adc-core.h"
+
+#define STM32_ADC_TEMP_SUSPEND_DELAY_MS	2000
+
+/*
+ * stm32_adc_temp_cfg - stm32 temperature compatible configuration data
+ * @avg_slope:		temp sensor average slope (uV/deg: from datasheet)
+ * @ts:			temp sensor sample temperature (°C: from datasheet)
+ * @vts:		temp sensor voltage @ts (mV: V25 or V30 in datasheet)
+ * @en_bit:		temp sensor enable bits
+ * @en_reg:		temp sensor enable register
+ * @ts_cal_bits:	temp sensor ts_cal[1..2] raw resolution (bits)
+ * @t1:			ts_cal1 sample temperature (°C: from datasheet)
+ * @t2:			ts_cal2 sample temperature (°C: from datasheet)
+ */
+struct stm32_adc_temp_cfg {
+	unsigned int avg_slope;
+	unsigned int ts;
+	unsigned int vts;
+	unsigned int en_bit;
+	unsigned int en_reg;
+	unsigned int ts_cal_bits;
+	unsigned int t1;
+	unsigned int t2;
+};
+
+/*
+ * stm32_adc_temp - private data of STM32 ADC temperature sensor driver
+ * @base:		control registers base cpu addr
+ * @cfg:		compatible configuration data
+ * @temp_offset:	temperature sensor offset
+ * @temp_scale:		temperature sensor scale
+ * @realbits:		adc resolution
+ * @ts_chan		temperature sensor ADC channel (consumer)
+ * @tzd:		thermal zone device
+ */
+struct stm32_adc_temp {
+	void __iomem			*base;
+	const struct stm32_adc_temp_cfg	*cfg;
+	int				temp_offset;
+	int				temp_scale;
+	int				realbits;
+	struct iio_channel		*ts_chan;
+	struct thermal_zone_device	*tzd;
+};
+
+static const struct iio_chan_spec stm32_adc_temp_channel = {
+	.type = IIO_TEMP,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+		BIT(IIO_CHAN_INFO_SCALE) |
+		BIT(IIO_CHAN_INFO_OFFSET),
+	.datasheet_name = "adc_temp",
+};
+
+static int stm32_adc_temp_get_temp(void *data, int *temp)
+{
+	struct stm32_adc_temp *priv = data;
+	struct iio_dev *indio_dev = iio_priv_to_dev(priv);
+	struct device *dev = indio_dev->dev.parent;
+	s64 val64;
+	int sense, ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
+
+	ret = iio_read_channel_raw(priv->ts_chan, &sense);
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+	if (ret != IIO_VAL_INT)
+		return ret < 0 ? ret : -EINVAL;
+
+	val64 = (s64)(sense + priv->temp_offset) * priv->temp_scale;
+	*temp = val64 >> priv->realbits;
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops stm32_adc_tzd_ops = {
+	.get_temp = &stm32_adc_temp_get_temp,
+};
+
+static int stm32_adc_temp_read_raw(struct iio_dev *indio_dev,
+				   struct iio_chan_spec const *chan,
+				   int *val, int *val2, long mask)
+{
+	struct stm32_adc_temp *priv = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = pm_runtime_get_sync(dev);
+		if (ret < 0) {
+			pm_runtime_put_noidle(dev);
+			return ret;
+		}
+		ret = iio_read_channel_raw(priv->ts_chan, val);
+		pm_runtime_mark_last_busy(dev);
+		pm_runtime_put_autosuspend(dev);
+		return ret;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = priv->temp_scale;
+		*val2 = priv->realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	case IIO_CHAN_INFO_OFFSET:
+		*val = priv->temp_offset;
+		return IIO_VAL_INT;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info stm32_adc_temp_iio_info = {
+	.read_raw = stm32_adc_temp_read_raw,
+};
+
+static void stm32_adc_temp_set_enable_state(struct device *dev, bool en)
+{
+	struct stm32_adc_temp *priv = dev_get_drvdata(dev);
+	u32 val = readl_relaxed(priv->base + priv->cfg->en_reg);
+
+	if (en)
+		val |= priv->cfg->en_bit;
+	else
+		val &= ~priv->cfg->en_bit;
+	writel_relaxed(val, priv->base + priv->cfg->en_reg);
+
+	/*
+	 * Temperature sensor "startup time" from datasheet, must be greater
+	 * than slowest supported device.
+	 */
+	if (en)
+		usleep_range(40, 50);
+}
+
+static int stm32_adc_temp_setup_offset_scale(struct platform_device *pdev,
+					     struct stm32_adc_temp *priv)
+{
+	int scale_type, vref_mv, ret;
+	u16 ts_cal1 = 0, ts_cal2 = 0;
+	unsigned int slope, vts, ts;
+	u64 val64;
+
+	scale_type = iio_read_channel_scale(priv->ts_chan, &vref_mv,
+					    &priv->realbits);
+	if (scale_type != IIO_VAL_FRACTIONAL_LOG2)
+		return scale_type < 0 ? scale_type : -EINVAL;
+
+	/* Optional read of temperature sensor calibration data */
+	ret = nvmem_cell_read_u16(&pdev->dev, "ts_cal1", &ts_cal1);
+	if (ret && ret != -ENOENT && ret != -ENOSYS)
+		return ret;
+	ret = nvmem_cell_read_u16(&pdev->dev, "ts_cal2", &ts_cal2);
+	if (ret && ret != -ENOENT && ret != -ENOSYS)
+		return ret;
+
+	if (!ts_cal1 || !ts_cal2) {
+		/* Use datasheet temperature sensor characteristics */
+		slope = priv->cfg->avg_slope;
+		ts = priv->cfg->ts;
+		vts = priv->cfg->vts;
+	} else {
+		/*
+		 * Compute average slope (µV/°C) from calibration data:
+		 * - ts_cal1: raw data @t1(°C), factory vref = 3.3V
+		 * - ts_cal2: raw data @t2(°C), factory vref = 3.3V
+		 */
+		slope = ts_cal2 - ts_cal1;
+		slope *= 3300000 / (priv->cfg->t2 - priv->cfg->t1);
+		slope >>= priv->cfg->ts_cal_bits;
+		ts = priv->cfg->t1;
+		vts = ts_cal1 * 3300;
+		vts >>= priv->cfg->ts_cal_bits;
+	}
+
+	dev_dbg(&pdev->dev, "ts_cal1=%x ts_cal2=%x slope=%d vts=%d\n",
+		ts_cal1, ts_cal2, slope, vts);
+
+	priv->temp_scale = vref_mv * 1000000 / slope;
+
+	/*
+	 * T (°C) = (Vsense - V25) / AVG_slope + 25.
+	 * raw offset to subtract @0°C: Vts0 = V25 - 25 * AVG_slope
+	 */
+	val64 = ts << priv->realbits;
+	priv->temp_offset = div_u64(val64 * (u64)slope, 1000LL);
+	priv->temp_offset -= vts << priv->realbits;
+	priv->temp_offset /= vref_mv;
+
+	return 0;
+}
+
+static int stm32_adc_temp_probe(struct platform_device *pdev)
+{
+	struct stm32_adc_common *common = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	struct stm32_adc_temp *priv;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &stm32_adc_temp_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = &stm32_adc_temp_channel;
+	indio_dev->num_channels = 1;
+
+	priv = iio_priv(indio_dev);
+	priv->base = common->base;
+	priv->cfg = (const struct stm32_adc_temp_cfg *)
+		of_match_device(dev->driver->of_match_table, dev)->data;
+
+	priv->ts_chan = devm_iio_channel_get(dev, NULL);
+	platform_set_drvdata(pdev, priv);
+	if (IS_ERR(priv->ts_chan)) {
+		ret = PTR_ERR(priv->ts_chan);
+		dev_err(&indio_dev->dev, "Can't get temp channel: %d\n", ret);
+		return ret;
+	}
+
+	ret = stm32_adc_temp_setup_offset_scale(pdev, priv);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Can't get offset/scale: %d\n", ret);
+		return ret;
+	}
+
+	/* Get stm32-adc-core PM online */
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_set_autosuspend_delay(dev, STM32_ADC_TEMP_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_enable(dev);
+
+	/* Power-on temperature sensor */
+	stm32_adc_temp_set_enable_state(dev, true);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Can't register iio dev: %d\n", ret);
+		goto fail;
+	}
+
+	priv->tzd = thermal_zone_of_sensor_register(dev, 0, priv,
+						    &stm32_adc_tzd_ops);
+	/* Optional thermal zone device */
+	if (IS_ERR(priv->tzd)) {
+		ret = PTR_ERR(priv->tzd);
+		if (ret != -ENOENT && ret != -ENODEV) {
+			dev_err(&indio_dev->dev, "Can't register thermal: %d\n",
+				ret);
+			goto unreg;
+		}
+		dev_dbg(&indio_dev->dev, "Not using thermal: %d\n", ret);
+		priv->tzd = NULL;
+	}
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	return 0;
+
+unreg:
+	iio_device_unregister(indio_dev);
+
+fail:
+	stm32_adc_temp_set_enable_state(dev, false);
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
+
+	return ret;
+}
+
+static int stm32_adc_temp_remove(struct platform_device *pdev)
+{
+	struct stm32_adc_temp *priv = platform_get_drvdata(pdev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(priv);
+
+	pm_runtime_get_sync(&pdev->dev);
+	if (priv->tzd)
+		thermal_zone_of_sensor_unregister(&pdev->dev, priv->tzd);
+	iio_device_unregister(indio_dev);
+	stm32_adc_temp_set_enable_state(&pdev->dev, false);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+static int stm32_adc_temp_runtime_suspend(struct device *dev)
+{
+	stm32_adc_temp_set_enable_state(dev, false);
+
+	return 0;
+}
+
+static int stm32_adc_temp_runtime_resume(struct device *dev)
+{
+	stm32_adc_temp_set_enable_state(dev, true);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops stm32_adc_temp_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(stm32_adc_temp_runtime_suspend,
+			   stm32_adc_temp_runtime_resume,
+			   NULL)
+};
+
+static const struct stm32_adc_temp_cfg stm32f4_adc_temp_cfg = {
+	.avg_slope = 2500,
+	.ts = 25,
+	.vts = 760, /* V25 from datasheet */
+	.en_reg = STM32F4_ADC_CCR,
+	.en_bit = STM32F4_ADC_TSVREFE,
+	.ts_cal_bits = 12,
+	.t1 = 30, /* ts_cal1 @30°C */
+	.t2 = 110, /* ts_cal2 @110°C */
+};
+
+static const struct stm32_adc_temp_cfg stm32h7_adc_temp_cfg = {
+	.avg_slope = 2000,
+	.ts = 30,
+	.vts = 620, /* V30 from datasheet */
+	.en_reg = STM32H7_ADC_CCR,
+	.en_bit = STM32H7_VSENSEEN,
+	.ts_cal_bits = 16,
+	.t1 = 30, /* ts_cal1 @30°C */
+	.t2 = 110, /* ts_cal2 @110°C */
+};
+
+/* TODO: update typical values when confirmed for stm32mp1 */
+static const struct stm32_adc_temp_cfg stm32mp1_adc_temp_cfg = {
+	.avg_slope = 2050,
+	.ts = 30,
+	.vts = 620, /* V30 from datasheet */
+	.en_reg = STM32H7_ADC_CCR,
+	.en_bit = STM32H7_VSENSEEN,
+	.ts_cal_bits = 16,
+	.t1 = 30, /* ts_cal1 @30°C */
+	.t2 = 130, /* ts_cal2 @130°C */
+};
+
+static const struct of_device_id stm32_adc_temp_of_match[] = {
+	{
+		.compatible = "st,stm32f4-adc-temp",
+		.data = (void *)&stm32f4_adc_temp_cfg,
+	},
+	{
+		.compatible = "st,stm32h7-adc-temp",
+		.data = (void *)&stm32h7_adc_temp_cfg,
+	},
+	{
+		.compatible = "st,stm32mp1-adc-temp",
+		.data = (void *)&stm32mp1_adc_temp_cfg,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32_adc_temp_of_match);
+
+static struct platform_driver stm32_adc_temp_driver = {
+	.probe = stm32_adc_temp_probe,
+	.remove = stm32_adc_temp_remove,
+	.driver = {
+		.name = "stm32-adc-temp",
+		.of_match_table = of_match_ptr(stm32_adc_temp_of_match),
+		.pm = &stm32_adc_temp_pm_ops,
+	},
+};
+module_platform_driver(stm32_adc_temp_driver);
+
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 ADC Temperature IIO driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:stm32-adc-temp");
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 3784118..980355e 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -12,6 +12,7 @@
 #include <linux/dmaengine.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
 #include <linux/iio/timer/stm32-lptim-trigger.h>
 #include <linux/iio/timer/stm32-timer-trigger.h>
 #include <linux/iio/trigger.h>
@@ -22,6 +23,7 @@
 #include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 
@@ -46,14 +48,26 @@
 #define STM32F4_ADC_DR			0x4C
 
 /* STM32F4_ADC_SR - bit fields */
+#define STM32F4_OVR			BIT(5)
 #define STM32F4_STRT			BIT(4)
+#define STM32F4_JSTRT			BIT(3)
+#define STM32F4_JEOC			BIT(2)
 #define STM32F4_EOC			BIT(1)
+#define STM32F4_AWD			BIT(0)
 
 /* STM32F4_ADC_CR1 - bit fields */
 #define STM32F4_RES_SHIFT		24
+#define STM32F4_OVRIE			BIT(26)
 #define STM32F4_RES_MASK		GENMASK(25, 24)
+#define STM32F4_AWDEN			BIT(23)
+#define STM32F4_JAWDEN			BIT(22)
+#define STM32F4_AWDSGL			BIT(9)
 #define STM32F4_SCAN			BIT(8)
+#define STM32F4_JEOCIE			BIT(7)
+#define STM32F4_AWDIE			BIT(6)
 #define STM32F4_EOCIE			BIT(5)
+#define STM32F4_AWDCH_SHIFT		0
+#define STM32F4_AWDCH_MASK		GENMASK(4, 0)
 
 /* STM32F4_ADC_CR2 - bit fields */
 #define STM32F4_SWSTART			BIT(30)
@@ -61,6 +75,11 @@
 #define STM32F4_EXTEN_MASK		GENMASK(29, 28)
 #define STM32F4_EXTSEL_SHIFT		24
 #define STM32F4_EXTSEL_MASK		GENMASK(27, 24)
+#define STM32F4_JSWSTART		BIT(22)
+#define STM32F4_JEXTEN_SHIFT		20
+#define STM32F4_JEXTEN_MASK		GENMASK(21, 20)
+#define STM32F4_JEXTSEL_SHIFT		16
+#define STM32F4_JEXTSEL_MASK		GENMASK(19, 16)
 #define STM32F4_EOCS			BIT(10)
 #define STM32F4_DDS			BIT(9)
 #define STM32F4_DMA			BIT(8)
@@ -74,21 +93,44 @@
 #define STM32H7_ADC_SMPR1		0x14
 #define STM32H7_ADC_SMPR2		0x18
 #define STM32H7_ADC_PCSEL		0x1C
+#define STM32H7_ADC_LTR1		0x20
+#define STM32H7_ADC_HTR1		0x24
 #define STM32H7_ADC_SQR1		0x30
 #define STM32H7_ADC_SQR2		0x34
 #define STM32H7_ADC_SQR3		0x38
 #define STM32H7_ADC_SQR4		0x3C
 #define STM32H7_ADC_DR			0x40
+#define STM32H7_ADC_JSQR		0x4C
+#define STM32H7_ADC_JDR1		0x80
+#define STM32H7_ADC_JDR2		0x84
+#define STM32H7_ADC_JDR3		0x88
+#define STM32H7_ADC_JDR4		0x8C
+#define STM32H7_ADC_AWD2CR		0xA0
+#define STM32H7_ADC_AWD3CR		0xA4
+#define STM32H7_ADC_LTR2		0xB0
+#define STM32H7_ADC_HTR2		0xB4
+#define STM32H7_ADC_LTR3		0xB8
+#define STM32H7_ADC_HTR3		0xBC
 #define STM32H7_ADC_DIFSEL		0xC0
 #define STM32H7_ADC_CALFACT		0xC4
 #define STM32H7_ADC_CALFACT2		0xC8
 
 /* STM32H7_ADC_ISR - bit fields */
 #define STM32MP1_VREGREADY		BIT(12)
+#define STM32H7_AWD3			BIT(9)
+#define STM32H7_AWD2			BIT(8)
+#define STM32H7_AWD1			BIT(7)
+#define STM32H7_JEOS			BIT(6)
+#define STM32H7_OVR			BIT(4)
 #define STM32H7_EOC			BIT(2)
 #define STM32H7_ADRDY			BIT(0)
 
 /* STM32H7_ADC_IER - bit fields */
+#define STM32H7_AWD3IE			STM32H7_AWD3
+#define STM32H7_AWD2IE			STM32H7_AWD2
+#define STM32H7_AWD1IE			STM32H7_AWD1
+#define STM32H7_JEOSIE			STM32H7_JEOS
+#define STM32H7_OVRIE			STM32H7_OVR
 #define STM32H7_EOCIE			STM32H7_EOC
 
 /* STM32H7_ADC_CR - bit fields */
@@ -104,12 +146,19 @@
 #define STM32H7_LINCALRDYW1		BIT(22)
 #define STM32H7_ADCALLIN		BIT(16)
 #define STM32H7_BOOST			BIT(8)
+#define STM32H7_JADSTP			BIT(5)
 #define STM32H7_ADSTP			BIT(4)
+#define STM32H7_JADSTART		BIT(3)
 #define STM32H7_ADSTART			BIT(2)
 #define STM32H7_ADDIS			BIT(1)
 #define STM32H7_ADEN			BIT(0)
 
 /* STM32H7_ADC_CFGR bit fields */
+#define STM32H7_AWD1CH_SHIFT		26
+#define STM32H7_AWD1CH_MASK		GENMASK(30, 26)
+#define STM32H7_JAWD1EN			BIT(24)
+#define STM32H7_AWD1EN			BIT(23)
+#define STM32H7_AWD1SGL			BIT(22)
 #define STM32H7_EXTEN_SHIFT		10
 #define STM32H7_EXTEN_MASK		GENMASK(11, 10)
 #define STM32H7_EXTSEL_SHIFT		5
@@ -126,6 +175,12 @@ enum stm32h7_adc_dmngt {
 	STM32H7_DMNGT_DMA_CIRC,		/* DMA circular mode */
 };
 
+/* STM32H7_ADC_JSQR - bit fields */
+#define STM32H7_JEXTEN_SHIFT		7
+#define STM32H7_JEXTEN_MASK		GENMASK(8, 7)
+#define STM32H7_JEXTSEL_SHIFT		2
+#define STM32H7_JEXTSEL_MASK		GENMASK(6, 2)
+
 /* STM32H7_ADC_CALFACT - bit fields */
 #define STM32H7_CALFACT_D_SHIFT		16
 #define STM32H7_CALFACT_D_MASK		GENMASK(26, 16)
@@ -136,18 +191,17 @@ enum stm32h7_adc_dmngt {
 #define STM32H7_LINCALFACT_SHIFT	0
 #define STM32H7_LINCALFACT_MASK		GENMASK(29, 0)
 
-/* Number of linear calibration shadow registers / LINCALRDYW control bits */
-#define STM32H7_LINCALFACT_NUM		6
-
 /* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
 #define STM32H7_BOOST_CLKRATE		20000000UL
 
 #define STM32_ADC_CH_MAX		20	/* max number of channels */
 #define STM32_ADC_CH_SZ			10	/* max channel name size */
 #define STM32_ADC_MAX_SQ		16	/* SQ1..SQ16 */
+#define STM32_ADC_MAX_JSQ		4	/* JSQ1..JSQ4 */
 #define STM32_ADC_MAX_SMP		7	/* SMPx range is [0..7] */
 #define STM32_ADC_TIMEOUT_US		100000
 #define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
+#define STM32_ADC_AUTO_SUSPEND_DELAY_MS	2000
 
 #define STM32_DMA_BUFFER_SIZE		PAGE_SIZE
 
@@ -159,53 +213,6 @@ enum stm32_adc_exten {
 	STM32_EXTEN_HWTRIG_BOTH_EDGES,
 };
 
-/* extsel - trigger mux selection value */
-enum stm32_adc_extsel {
-	STM32_EXT0,
-	STM32_EXT1,
-	STM32_EXT2,
-	STM32_EXT3,
-	STM32_EXT4,
-	STM32_EXT5,
-	STM32_EXT6,
-	STM32_EXT7,
-	STM32_EXT8,
-	STM32_EXT9,
-	STM32_EXT10,
-	STM32_EXT11,
-	STM32_EXT12,
-	STM32_EXT13,
-	STM32_EXT14,
-	STM32_EXT15,
-	STM32_EXT16,
-	STM32_EXT17,
-	STM32_EXT18,
-	STM32_EXT19,
-	STM32_EXT20,
-};
-
-/**
- * struct stm32_adc_trig_info - ADC trigger info
- * @name:		name of the trigger, corresponding to its source
- * @extsel:		trigger selection
- */
-struct stm32_adc_trig_info {
-	const char *name;
-	enum stm32_adc_extsel extsel;
-};
-
-/**
- * struct stm32_adc_calib - optional adc calibration data
- * @calfact_s: Calibration offset for single ended channels
- * @calfact_d: Calibration offset in differential
- * @lincalfact: Linearity calibration factor
- */
-struct stm32_adc_calib {
-	u32			calfact_s;
-	u32			calfact_d;
-	u32			lincalfact[STM32H7_LINCALFACT_NUM];
-};
-
 /**
  * stm32_adc_regs - stm32 ADC misc registers & bitfield desc
  * @reg:		register offset
@@ -219,27 +226,73 @@ struct stm32_adc_regs {
 };
 
 /**
+ * struct stm32_adc_awd_reginfo - stm32 ADC analog watchdog regs desc
+ * @reg:		awd control register offset
+ * @en_bits:		ADW enable bits for regular conversions, in @reg
+ * @jen_bits:		ADW enable bits for injected conversions, in @reg
+ * @awdch_mask:		AWDCH bitfield mask, in @reg
+ * @awdch_shift:	AWDCH shift, in @reg
+ * @htr:		High threshold register offset
+ * @ltr:		Low threshold register offset
+ * @ier_msk:		interrupt enable bit mask in ier register
+ * @isr_msk:		interrupt status bit mask in isr register
+ */
+struct stm32_adc_awd_reginfo {
+	u32 reg;
+	u32 en_bits;
+	u32 jen_bits;
+	u32 awdch_mask;
+	u32 awdch_shift;
+	u32 htr;
+	u32 ltr;
+	u32 ier_msk;
+	u32 isr_msk;
+};
+
+/**
  * stm32_adc_regspec - stm32 registers definition, compatible dependent data
  * @dr:			data register offset
+ * @jdr:		injected data registers offsets
  * @ier_eoc:		interrupt enable register & eocie bitfield
+ * @ier_jeoc:		interrupt enable register & jeocie bitfield
+ * @ier_ovr:		interrupt enable register & overrun bitfield
  * @isr_eoc:		interrupt status register & eoc bitfield
+ * @isr_jeoc:		interrupt status register & jeoc bitfield
+ * @isr_ovr:		interrupt status register & overrun bitfield
  * @sqr:		reference to sequence registers array
+ * @jsqr:		reference to injected sequence registers array
  * @exten:		trigger control register & bitfield
  * @extsel:		trigger selection register & bitfield
+ * @jexten:		injected trigger control register & bitfield
+ * @jextsel:		injected trigger selection register & bitfield
  * @res:		resolution selection register & bitfield
  * @smpr:		smpr1 & smpr2 registers offset array
  * @smp_bits:		smpr1 & smpr2 index and bitfields
+ * @write_one_to_clear:	clear isr flags by writing one to it
+ * @awd_reginfo:	Analog watchdog description
+ * @num_awd:		Number of Analog watchdog
  */
 struct stm32_adc_regspec {
 	const u32 dr;
+	const u32 jdr[4];
 	const struct stm32_adc_regs ier_eoc;
+	const struct stm32_adc_regs ier_jeoc;
+	const struct stm32_adc_regs ier_ovr;
 	const struct stm32_adc_regs isr_eoc;
+	const struct stm32_adc_regs isr_jeoc;
+	const struct stm32_adc_regs isr_ovr;
 	const struct stm32_adc_regs *sqr;
+	const struct stm32_adc_regs *jsqr;
 	const struct stm32_adc_regs exten;
 	const struct stm32_adc_regs extsel;
+	const struct stm32_adc_regs jexten;
+	const struct stm32_adc_regs jextsel;
 	const struct stm32_adc_regs res;
 	const u32 smpr[2];
 	const struct stm32_adc_regs *smp_bits;
+	const bool write_one_to_clear;
+	const struct stm32_adc_awd_reginfo *awd_reginfo;
+	unsigned int num_awd;
 };
 
 struct stm32_adc;
@@ -251,12 +304,12 @@ struct stm32_adc;
  * @trigs:		external trigger sources
  * @clk_required:	clock is required
  * @has_vregready:	vregready status flag presence
- * @selfcalib:		optional routine for self-calibration
  * @prepare:		optional prepare routine (power-up, enable)
  * @start_conv:		routine to start conversions
  * @stop_conv:		routine to stop conversions
  * @unprepare:		optional unprepare routine (disable, power-down)
  * @smp_cycles:		programmable sampling time (ADC clock cycles)
+ * @is_started:		routine to get adc 'started' state
  */
 struct stm32_adc_cfg {
 	const struct stm32_adc_regspec	*regs;
@@ -264,18 +317,39 @@ struct stm32_adc_cfg {
 	struct stm32_adc_trig_info	*trigs;
 	bool clk_required;
 	bool has_vregready;
-	int (*selfcalib)(struct stm32_adc *);
 	int (*prepare)(struct stm32_adc *);
 	void (*start_conv)(struct stm32_adc *, bool dma);
 	void (*stop_conv)(struct stm32_adc *);
 	void (*unprepare)(struct stm32_adc *);
 	const unsigned int *smp_cycles;
+	bool (*is_started)(struct stm32_adc *adc);
+};
+
+/**
+ * struct stm32_adc_evt - Configuration data for Analog watchdog events
+ * @list:		event configuration list
+ * @awd_id:		assigned AWD index
+ * @chan:		IIO chan spec reference for this event
+ * @hthresh:		High threshold value
+ * @lthresh:		Low threshold value
+ * @enabled:		Event enabled state
+ * @set:		Flag, event has been assigned an AWD and has been set
+ */
+struct stm32_adc_evt {
+	struct list_head list;
+	int awd_id;
+	const struct iio_chan_spec *chan;
+	u32 hthresh;
+	u32 lthresh;
+	bool enabled;
+	bool set;
 };
 
 /**
  * struct stm32_adc - private data of each ADC IIO instance
  * @common:		reference to ADC block common data
  * @offset:		ADC instance register offset in ADC block
+ * @id:			ADC instance id from offset
  * @cfg:		compatible configuration data
  * @completion:		end of single conversion completion
  * @buffer:		data buffer
@@ -290,15 +364,15 @@ struct stm32_adc_cfg {
  * @rx_buf:		dma rx buffer cpu address
  * @rx_dma_buf:		dma rx buffer bus address
  * @rx_buf_sz:		dma rx buffer size
- * @difsel		bitmask to set single-ended/differential channel
- * @pcsel		bitmask to preselect channels on some devices
- * @smpr_val:		sampling time settings (e.g. smpr1 / smpr2)
- * @cal:		optional calibration data on some devices
  * @chan_name:		channel name array
+ * @injected:		use injected channels on this adc
+ * @evt_list:		list of all events configured for this ADC block
+ * @awd_mask:		analog watchdog bitmask for this adc
  */
 struct stm32_adc {
 	struct stm32_adc_common	*common;
 	u32			offset;
+	u32			id;
 	const struct stm32_adc_cfg	*cfg;
 	struct completion	completion;
 	u16			buffer[STM32_ADC_MAX_SQ];
@@ -313,11 +387,10 @@ struct stm32_adc {
 	u8			*rx_buf;
 	dma_addr_t		rx_dma_buf;
 	unsigned int		rx_buf_sz;
-	u32			difsel;
-	u32			pcsel;
-	u32			smpr_val[2];
-	struct stm32_adc_calib	cal;
 	char			chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
+	bool			injected;
+	struct list_head	evt_list;
+	u32			awd_mask;
 };
 
 struct stm32_adc_diff_channel {
@@ -342,9 +415,9 @@ static const unsigned int stm32f4_adc_resolutions[] = {
 	12, 10, 8, 6,
 };
 
-/* stm32f4 can have up to 16 channels */
+/* stm32f4 can have up to 19 channels (incl. 16 external sources) */
 static const struct stm32_adc_info stm32f4_adc_info = {
-	.max_channels = 16,
+	.max_channels = 19,
 	.resolutions = stm32f4_adc_resolutions,
 	.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
 };
@@ -390,25 +463,58 @@ static const struct stm32_adc_regs stm32f4_sq[STM32_ADC_MAX_SQ + 1] = {
 
 /* STM32F4 external trigger sources for all instances */
 static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
-	{ TIM1_CH1, STM32_EXT0 },
-	{ TIM1_CH2, STM32_EXT1 },
-	{ TIM1_CH3, STM32_EXT2 },
-	{ TIM2_CH2, STM32_EXT3 },
-	{ TIM2_CH3, STM32_EXT4 },
-	{ TIM2_CH4, STM32_EXT5 },
-	{ TIM2_TRGO, STM32_EXT6 },
-	{ TIM3_CH1, STM32_EXT7 },
-	{ TIM3_TRGO, STM32_EXT8 },
-	{ TIM4_CH4, STM32_EXT9 },
-	{ TIM5_CH1, STM32_EXT10 },
-	{ TIM5_CH2, STM32_EXT11 },
-	{ TIM5_CH3, STM32_EXT12 },
-	{ TIM8_CH1, STM32_EXT13 },
-	{ TIM8_TRGO, STM32_EXT14 },
+	{ TIM1_CH1, STM32_EXT0, 0, TRG_REGULAR },
+	{ TIM1_CH2, STM32_EXT1, 0, TRG_REGULAR },
+	{ TIM1_CH3, STM32_EXT2, 0, TRG_REGULAR },
+	{ TIM2_CH2, STM32_EXT3, 0, TRG_REGULAR },
+	{ TIM2_CH3, STM32_EXT4, 0, TRG_REGULAR },
+	{ TIM2_CH4, STM32_EXT5, 0, TRG_REGULAR },
+	{ TIM2_TRGO, STM32_EXT6, STM32_EXT3, TRG_BOTH },
+	{ TIM3_CH1, STM32_EXT7, 0, TRG_REGULAR },
+	{ TIM3_TRGO, STM32_EXT8, 0, TRG_REGULAR },
+	{ TIM4_CH4, STM32_EXT9, 0, TRG_REGULAR },
+	{ TIM5_CH1, STM32_EXT10, 0, TRG_REGULAR },
+	{ TIM5_CH2, STM32_EXT11, 0, TRG_REGULAR },
+	{ TIM5_CH3, STM32_EXT12, 0, TRG_REGULAR },
+	{ TIM8_CH1, STM32_EXT13, 0, TRG_REGULAR },
+	{ TIM8_TRGO, STM32_EXT14, 0, TRG_REGULAR },
+	{ TIM1_CH4, 0, STM32_EXT0, TRG_INJECTED },
+	{ TIM1_TRGO, 0, STM32_EXT1, TRG_INJECTED },
+	{ TIM2_CH1, 0, STM32_EXT2, TRG_INJECTED },
+	{ TIM3_CH2, 0, STM32_EXT4, TRG_INJECTED },
+	{ TIM3_CH4, 0, STM32_EXT5, TRG_INJECTED },
+	{ TIM4_CH1, 0, STM32_EXT6, TRG_INJECTED },
+	{ TIM4_CH2, 0, STM32_EXT7, TRG_INJECTED  },
+	{ TIM4_CH3, 0, STM32_EXT8, TRG_INJECTED },
+	{ TIM4_TRGO, 0, STM32_EXT9, TRG_INJECTED },
+	{ TIM5_CH4, 0, STM32_EXT10, TRG_INJECTED },
+	{ TIM5_TRGO, 0, STM32_EXT11, TRG_INJECTED },
+	{ TIM8_CH2, 0, STM32_EXT12, TRG_INJECTED },
+	{ TIM8_CH3, 0, STM32_EXT13, TRG_INJECTED },
+	{ TIM8_CH4, 0, STM32_EXT14, TRG_INJECTED },
 	{}, /* sentinel */
 };
 
 /**
+ * stm32f4_jsq - describe injected sequence register:
+ * - JL: injected sequence len
+ * - JSQ4..SQ1: sequence entries
+ * When JL == 3, ADC converts JSQ1, JSQ2, JSQ3, JSQ4
+ * When JL == 2, ADC converts JSQ2, JSQ3, JSQ4
+ * When JL == 1, ADC converts JSQ3, JSQ4
+ * When JL == 0, ADC converts JSQ4
+ */
+static const struct stm32_adc_regs stm32f4_jsq[STM32_ADC_MAX_JSQ + 1] = {
+	/* JL: len bit field description to be kept as first element */
+	{ STM32F4_ADC_JSQR, GENMASK(21, 20), 20 },
+	/* JSQ4..JSQ1 registers & bit fields (reg, mask, shift) */
+	{ STM32F4_ADC_JSQR, GENMASK(19, 15), 15 },
+	{ STM32F4_ADC_JSQR, GENMASK(14, 10), 10 },
+	{ STM32F4_ADC_JSQR, GENMASK(9, 5), 5 },
+	{ STM32F4_ADC_JSQR, GENMASK(4, 0), 0 },
+};
+
+/**
  * stm32f4_smp_bits[] - describe sampling time register index & bit fields
  * Sorted so it can be indexed by channel number.
  */
@@ -441,17 +547,46 @@ static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
 	3, 15, 28, 56, 84, 112, 144, 480,
 };
 
+static const struct stm32_adc_awd_reginfo stm32f4_awd_reginfo = {
+	.reg = STM32F4_ADC_CR1,
+	.en_bits = STM32F4_AWDSGL | STM32F4_AWDEN,
+	.jen_bits = STM32F4_AWDSGL | STM32F4_JAWDEN,
+	.awdch_mask = STM32F4_AWDCH_MASK,
+	.awdch_shift = STM32F4_AWDCH_SHIFT,
+	.htr = STM32F4_ADC_HTR,
+	.ltr = STM32F4_ADC_LTR,
+	.ier_msk = STM32F4_AWDIE,
+	.isr_msk = STM32F4_AWD,
+};
+
 static const struct stm32_adc_regspec stm32f4_adc_regspec = {
 	.dr = STM32F4_ADC_DR,
+	.jdr = {
+		STM32F4_ADC_JDR1,
+		STM32F4_ADC_JDR2,
+		STM32F4_ADC_JDR3,
+		STM32F4_ADC_JDR4,
+	},
 	.ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
+	.ier_jeoc = { STM32F4_ADC_CR1, STM32F4_JEOCIE },
+	.ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE },
 	.isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC },
+	.isr_jeoc = { STM32F4_ADC_SR, STM32F4_JEOC },
+	.isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR },
 	.sqr = stm32f4_sq,
+	.jsqr = stm32f4_jsq,
 	.exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT },
 	.extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
 		    STM32F4_EXTSEL_SHIFT },
+	.jexten = { STM32F4_ADC_CR2, STM32F4_JEXTEN_MASK,
+		    STM32F4_JEXTEN_SHIFT },
+	.jextsel = { STM32F4_ADC_CR2, STM32F4_JEXTSEL_MASK,
+		     STM32F4_JEXTSEL_SHIFT },
 	.res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT },
 	.smpr = { STM32F4_ADC_SMPR1, STM32F4_ADC_SMPR2 },
 	.smp_bits = stm32f4_smp_bits,
+	.awd_reginfo = &stm32f4_awd_reginfo,
+	.num_awd = 1,
 };
 
 static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
@@ -476,26 +611,41 @@ static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
 	{ STM32H7_ADC_SQR4, GENMASK(10, 6), 6 },
 };
 
+static const struct stm32_adc_regs stm32h7_jsq[STM32_ADC_MAX_JSQ + 1] = {
+	/* JL: len bit field description to be kept as first element */
+	{ STM32H7_ADC_JSQR, GENMASK(1, 0), 0 },
+	/* JSQ1..JSQ4 registers & bit fields (reg, mask, shift) */
+	{ STM32H7_ADC_JSQR, GENMASK(13, 9), 9 },
+	{ STM32H7_ADC_JSQR, GENMASK(19, 15), 15 },
+	{ STM32H7_ADC_JSQR, GENMASK(25, 21), 21 },
+	{ STM32H7_ADC_JSQR, GENMASK(31, 27), 27 },
+};
+
 /* STM32H7 external trigger sources for all instances */
 static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
-	{ TIM1_CH1, STM32_EXT0 },
-	{ TIM1_CH2, STM32_EXT1 },
-	{ TIM1_CH3, STM32_EXT2 },
-	{ TIM2_CH2, STM32_EXT3 },
-	{ TIM3_TRGO, STM32_EXT4 },
-	{ TIM4_CH4, STM32_EXT5 },
-	{ TIM8_TRGO, STM32_EXT7 },
-	{ TIM8_TRGO2, STM32_EXT8 },
-	{ TIM1_TRGO, STM32_EXT9 },
-	{ TIM1_TRGO2, STM32_EXT10 },
-	{ TIM2_TRGO, STM32_EXT11 },
-	{ TIM4_TRGO, STM32_EXT12 },
-	{ TIM6_TRGO, STM32_EXT13 },
-	{ TIM15_TRGO, STM32_EXT14 },
-	{ TIM3_CH4, STM32_EXT15 },
-	{ LPTIM1_OUT, STM32_EXT18 },
-	{ LPTIM2_OUT, STM32_EXT19 },
-	{ LPTIM3_OUT, STM32_EXT20 },
+	{ TIM1_CH1, STM32_EXT0, 0, TRG_REGULAR },
+	{ TIM1_CH2, STM32_EXT1, 0, TRG_REGULAR },
+	{ TIM1_CH3, STM32_EXT2, 0, TRG_REGULAR },
+	{ TIM2_CH2, STM32_EXT3, 0, TRG_REGULAR },
+	{ TIM3_TRGO, STM32_EXT4, STM32_EXT12, TRG_BOTH },
+	{ TIM4_CH4, STM32_EXT5, 0, TRG_REGULAR },
+	{ TIM8_TRGO, STM32_EXT7, STM32_EXT9, TRG_BOTH },
+	{ TIM8_TRGO2, STM32_EXT8, STM32_EXT10, TRG_BOTH },
+	{ TIM1_TRGO, STM32_EXT9, STM32_EXT0, TRG_BOTH },
+	{ TIM1_TRGO2, STM32_EXT10, STM32_EXT8, TRG_BOTH },
+	{ TIM2_TRGO, STM32_EXT11, STM32_EXT2, TRG_BOTH },
+	{ TIM4_TRGO, STM32_EXT12, STM32_EXT5, TRG_BOTH },
+	{ TIM6_TRGO, STM32_EXT13, STM32_EXT14, TRG_BOTH },
+	{ TIM15_TRGO, STM32_EXT14, STM32_EXT15, TRG_BOTH },
+	{ TIM3_CH4, STM32_EXT15, STM32_EXT4, TRG_BOTH },
+	{ LPTIM1_OUT, STM32_EXT18, STM32_EXT18, TRG_BOTH },
+	{ LPTIM2_OUT, STM32_EXT19, STM32_EXT19, TRG_BOTH },
+	{ LPTIM3_OUT, STM32_EXT20, STM32_EXT20, TRG_BOTH },
+	{ TIM1_CH4, 0, STM32_EXT1, TRG_INJECTED },
+	{ TIM2_CH1, 0, STM32_EXT3, TRG_INJECTED },
+	{ TIM8_CH4, 0, STM32_EXT7, TRG_INJECTED },
+	{ TIM3_CH3, 0, STM32_EXT11, TRG_INJECTED },
+	{ TIM3_CH1, 0, STM32_EXT13, TRG_INJECTED },
 	{},
 };
 
@@ -533,17 +683,72 @@ static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
 	1, 2, 8, 16, 32, 64, 387, 810,
 };
 
+/**
+ * stm32h7_awd_reginfo[] - Analog watchdog description.
+ *
+ * two watchdog types are found in stm32h7 ADC:
+ * - AWD1 has en_bits, and can select either a single or all channel(s)
+ * - AWD2 & AWD3 are enabled by channel mask (in AWDxCR)
+ * Remaining is similar (high/low threshold regs, ier/isr regs & mask)
+ */
+static const struct stm32_adc_awd_reginfo stm32h7_awd_reginfo[] = {
+	{
+		/* AWD1: has en_bits, configure it to guard one channel */
+		.reg = STM32H7_ADC_CFGR,
+		.en_bits = STM32H7_AWD1SGL | STM32H7_AWD1EN,
+		.jen_bits = STM32H7_AWD1SGL | STM32H7_JAWD1EN,
+		.awdch_mask = STM32H7_AWD1CH_MASK,
+		.awdch_shift = STM32H7_AWD1CH_SHIFT,
+		.htr = STM32H7_ADC_HTR1,
+		.ltr = STM32H7_ADC_LTR1,
+		.ier_msk = STM32H7_AWD1IE,
+		.isr_msk = STM32H7_AWD1,
+	}, {
+		/* AWD2 uses channel mask in AWD2CR register */
+		.reg = STM32H7_ADC_AWD2CR,
+		.htr = STM32H7_ADC_HTR2,
+		.ltr = STM32H7_ADC_LTR2,
+		.ier_msk = STM32H7_AWD2IE,
+		.isr_msk = STM32H7_AWD2,
+	}, {
+		/* AWD3 uses channel mask in AWD3CR register */
+		.reg = STM32H7_ADC_AWD3CR,
+		.htr = STM32H7_ADC_HTR3,
+		.ltr = STM32H7_ADC_LTR3,
+		.ier_msk = STM32H7_AWD3IE,
+		.isr_msk = STM32H7_AWD3,
+	},
+};
+
 static const struct stm32_adc_regspec stm32h7_adc_regspec = {
 	.dr = STM32H7_ADC_DR,
+	.jdr = {
+		STM32H7_ADC_JDR1,
+		STM32H7_ADC_JDR2,
+		STM32H7_ADC_JDR3,
+		STM32H7_ADC_JDR4,
+	},
 	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
+	.ier_jeoc = { STM32H7_ADC_IER, STM32H7_JEOSIE },
+	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
 	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
+	.isr_jeoc = { STM32H7_ADC_ISR, STM32H7_JEOS },
+	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
 	.sqr = stm32h7_sq,
+	.jsqr = stm32h7_jsq,
 	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
 	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
 		    STM32H7_EXTSEL_SHIFT },
+	.jexten = { STM32H7_ADC_JSQR, STM32H7_JEXTEN_MASK,
+		    STM32H7_JEXTEN_SHIFT },
+	.jextsel = { STM32H7_ADC_JSQR, STM32H7_JEXTSEL_MASK,
+		     STM32H7_JEXTSEL_SHIFT },
 	.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
 	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
 	.smp_bits = stm32h7_smp_bits,
+	.write_one_to_clear = true,
+	.awd_reginfo = stm32h7_awd_reginfo,
+	.num_awd = ARRAY_SIZE(stm32h7_awd_reginfo),
 };
 
 /**
@@ -599,8 +804,12 @@ static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
  */
 static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
 {
-	stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg,
-			   adc->cfg->regs->ier_eoc.mask);
+	if (adc->injected)
+		stm32_adc_set_bits(adc, adc->cfg->regs->ier_jeoc.reg,
+				   adc->cfg->regs->ier_jeoc.mask);
+	else
+		stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg,
+				   adc->cfg->regs->ier_eoc.mask);
 };
 
 /**
@@ -609,8 +818,30 @@ static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
  */
 static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
 {
-	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg,
-			   adc->cfg->regs->ier_eoc.mask);
+	if (adc->injected)
+		stm32_adc_clr_bits(adc, adc->cfg->regs->ier_jeoc.reg,
+				   adc->cfg->regs->ier_jeoc.mask);
+	else
+		stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg,
+				   adc->cfg->regs->ier_eoc.mask);
+}
+
+static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc)
+{
+	if (adc->injected)
+		return;
+
+	stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg,
+			   adc->cfg->regs->ier_ovr.mask);
+}
+
+static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc)
+{
+	if (adc->injected)
+		return;
+
+	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg,
+			   adc->cfg->regs->ier_ovr.mask);
 }
 
 static void stm32_adc_set_res(struct stm32_adc *adc)
@@ -623,6 +854,57 @@ static void stm32_adc_set_res(struct stm32_adc *adc)
 	stm32_adc_writel(adc, res->reg, val);
 }
 
+static int stm32_adc_hw_stop(struct device *dev)
+{
+	struct stm32_adc *adc = dev_get_drvdata(dev);
+
+	if (adc->cfg->unprepare)
+		adc->cfg->unprepare(adc);
+
+	if (adc->clk)
+		clk_disable_unprepare(adc->clk);
+
+	return 0;
+}
+
+static int stm32_adc_hw_start(struct device *dev)
+{
+	struct stm32_adc *adc = dev_get_drvdata(dev);
+	int ret;
+
+	if (adc->clk) {
+		ret = clk_prepare_enable(adc->clk);
+		if (ret)
+			return ret;
+	}
+
+	stm32_adc_set_res(adc);
+
+	if (adc->cfg->prepare) {
+		ret = adc->cfg->prepare(adc);
+		if (ret)
+			goto err_clk_dis;
+	}
+
+	return 0;
+
+err_clk_dis:
+	if (adc->clk)
+		clk_disable_unprepare(adc->clk);
+
+	return ret;
+}
+
+static bool stm32f4_adc_is_started(struct stm32_adc *adc)
+{
+	u32 val = stm32_adc_readl(adc, STM32F4_ADC_SR);
+
+	if (adc->injected)
+		return !!(val & STM32F4_JSTRT);
+	else
+		return !!(val & STM32F4_STRT);
+}
+
 /**
  * stm32f4_adc_start_conv() - Start conversions for regular channels.
  * @adc: stm32 adc instance
@@ -635,30 +917,80 @@ static void stm32_adc_set_res(struct stm32_adc *adc)
  */
 static void stm32f4_adc_start_conv(struct stm32_adc *adc, bool dma)
 {
+	u32 trig_msk, start_msk;
+
 	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
 
-	if (dma)
+	if (!adc->injected && dma)
 		stm32_adc_set_bits(adc, STM32F4_ADC_CR2,
 				   STM32F4_DMA | STM32F4_DDS);
 
-	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
+	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_ADON)) {
+		stm32_adc_set_bits(adc, STM32F4_ADC_CR2,
+				   STM32F4_EOCS | STM32F4_ADON);
+
+		/* Wait for Power-up time (tSTAB from datasheet) */
+		usleep_range(2, 3);
+	}
 
-	/* Wait for Power-up time (tSTAB from datasheet) */
-	usleep_range(2, 3);
+	if (adc->injected) {
+		trig_msk = STM32F4_JEXTEN_MASK;
+		start_msk = STM32F4_JSWSTART;
+	} else {
+		trig_msk = STM32F4_EXTEN_MASK;
+		start_msk = STM32F4_SWSTART;
+	}
 
 	/* Software start ? (e.g. trigger detection disabled ?) */
-	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
-		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
+	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & trig_msk))
+		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, start_msk);
 }
 
 static void stm32f4_adc_stop_conv(struct stm32_adc *adc)
 {
-	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
-	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
+	u32 val;
+
+	if (adc->injected) {
+		stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_JEXTEN_MASK);
+		stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_JSTRT);
+	} else {
+		stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
+		stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
+	}
+
+	/* Disable adc when all triggered conversion have been disabled */
+	val = stm32_adc_readl(adc, STM32F4_ADC_CR2);
+	val &= STM32F4_EXTEN_MASK | STM32F4_JEXTEN_MASK;
+	if (!val) {
+		stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
+		stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_ADON);
+	}
+
+	if (!adc->injected)
+		stm32_adc_clr_bits(adc, STM32F4_ADC_CR2,
+				   STM32F4_DMA | STM32F4_DDS);
+}
+
+static bool stm32h7_adc_is_enabled(struct stm32_adc *adc)
+{
+	return !!(stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_ADEN);
+}
+
+static bool stm32h7_adc_any_ongoing_conv(struct stm32_adc *adc)
+{
+	u32 val = stm32_adc_readl(adc, STM32H7_ADC_CR);
 
-	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
-	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2,
-			   STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
+	return !!(val & (STM32H7_ADSTART | STM32H7_JADSTART));
+}
+
+static bool stm32h7_adc_is_started(struct stm32_adc *adc)
+{
+	u32 val = stm32_adc_readl(adc, STM32H7_ADC_CR);
+
+	if (adc->injected)
+		return !!(val & STM32H7_JADSTART);
+	else
+		return !!(val & STM32H7_ADSTART);
 }
 
 static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma)
@@ -667,6 +999,11 @@ static void stm32h7_adc_start_conv(struct stm32_adc *adc, bool dma)
 	unsigned long flags;
 	u32 val;
 
+	if (adc->injected) {
+		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_JADSTART);
+		return;
+	}
+
 	if (dma)
 		dmngt = STM32H7_DMNGT_DMA_CIRC;
 	else
@@ -687,6 +1024,16 @@ static void stm32h7_adc_stop_conv(struct stm32_adc *adc)
 	int ret;
 	u32 val;
 
+	if (adc->injected) {
+		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_JADSTP);
+		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
+						   !(val & (STM32H7_JADSTART)),
+						   100, STM32_ADC_TIMEOUT_US);
+		if (ret)
+			dev_warn(&indio_dev->dev, "stop failed\n");
+		return;
+	}
+
 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP);
 
 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
@@ -704,6 +1051,10 @@ static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
 	int ret;
 	u32 val;
 
+	/* Is ADC already up ? */
+	if (stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_ADVREGEN)
+		return 0;
+
 	/* Exit deep power down, then enable ADC voltage regulator */
 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
@@ -730,6 +1081,10 @@ static int stm32h7_adc_exit_pwr_down(struct stm32_adc *adc)
 
 static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
 {
+	/* Check there is no regular or injected on-going conversions */
+	if (stm32h7_adc_any_ongoing_conv(adc))
+		return;
+
 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
 
 	/* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
@@ -742,6 +1097,9 @@ static int stm32h7_adc_enable(struct stm32_adc *adc)
 	int ret;
 	u32 val;
 
+	if (stm32h7_adc_is_enabled(adc))
+		return 0;
+
 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN);
 
 	/* Poll for ADRDY to be set (after adc startup time) */
@@ -765,6 +1123,10 @@ static void stm32h7_adc_disable(struct stm32_adc *adc)
 	int ret;
 	u32 val;
 
+	/* Check there is no regular or injected on-going conversions */
+	if (stm32h7_adc_any_ongoing_conv(adc))
+		return;
+
 	/* Disable ADC and wait until it's effectively disabled */
 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
@@ -777,18 +1139,15 @@ static void stm32h7_adc_disable(struct stm32_adc *adc)
 /**
  * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
  * @adc: stm32 adc instance
+ * Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable
  */
 static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct stm32_adc_calib *cal = &adc->common->cal[adc->id];
 	int i, ret;
 	u32 lincalrdyw_mask, val;
 
-	/* Enable adc so LINCALRDYW1..6 bits are writable */
-	ret = stm32h7_adc_enable(adc);
-	if (ret)
-		return ret;
-
 	/* Read linearity calibration */
 	lincalrdyw_mask = STM32H7_LINCALRDYW6;
 	for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
@@ -801,27 +1160,25 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
 						   100, STM32_ADC_TIMEOUT_US);
 		if (ret) {
 			dev_err(&indio_dev->dev, "Failed to read calfact\n");
-			goto disable;
+			return ret;
 		}
 
 		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
-		adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK);
-		adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT;
+		cal->lincalfact[i] = (val & STM32H7_LINCALFACT_MASK);
+		cal->lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT;
 
 		lincalrdyw_mask >>= 1;
 	}
 
 	/* Read offset calibration */
 	val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT);
-	adc->cal.calfact_s = (val & STM32H7_CALFACT_S_MASK);
-	adc->cal.calfact_s >>= STM32H7_CALFACT_S_SHIFT;
-	adc->cal.calfact_d = (val & STM32H7_CALFACT_D_MASK);
-	adc->cal.calfact_d >>= STM32H7_CALFACT_D_SHIFT;
-
-disable:
-	stm32h7_adc_disable(adc);
+	cal->calfact_s = (val & STM32H7_CALFACT_S_MASK);
+	cal->calfact_s >>= STM32H7_CALFACT_S_SHIFT;
+	cal->calfact_d = (val & STM32H7_CALFACT_D_MASK);
+	cal->calfact_d >>= STM32H7_CALFACT_D_SHIFT;
+	cal->calibrated = true;
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -832,11 +1189,16 @@ static int stm32h7_adc_read_selfcalib(struct stm32_adc *adc)
 static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct stm32_adc_calib *cal = &adc->common->cal[adc->id];
 	int i, ret;
 	u32 lincalrdyw_mask, val;
 
-	val = (adc->cal.calfact_s << STM32H7_CALFACT_S_SHIFT) |
-		(adc->cal.calfact_d << STM32H7_CALFACT_D_SHIFT);
+	/* Check there is no regular or injected on-going conversions */
+	if (stm32h7_adc_any_ongoing_conv(adc))
+		return 0;
+
+	val = (cal->calfact_s << STM32H7_CALFACT_S_SHIFT) |
+		(cal->calfact_d << STM32H7_CALFACT_D_SHIFT);
 	stm32_adc_writel(adc, STM32H7_ADC_CALFACT, val);
 
 	lincalrdyw_mask = STM32H7_LINCALRDYW6;
@@ -846,7 +1208,7 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
 		 * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger
 		 * data write. Then poll to wait for complete transfer.
 		 */
-		val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT;
+		val = cal->lincalfact[i] << STM32H7_LINCALFACT_SHIFT;
 		stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val);
 		stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
 		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
@@ -873,7 +1235,7 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
 			return ret;
 		}
 		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
-		if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) {
+		if (val != cal->lincalfact[i] << STM32H7_LINCALFACT_SHIFT) {
 			dev_err(&indio_dev->dev, "calfact not consistent\n");
 			return -EIO;
 		}
@@ -898,19 +1260,19 @@ static int stm32h7_adc_restore_selfcalib(struct stm32_adc *adc)
 #define STM32H7_ADC_CALIB_TIMEOUT_US		100000
 
 /**
- * stm32h7_adc_selfcalib() - Procedure to calibrate ADC (from power down)
+ * stm32h7_adc_selfcalib() - Procedure to calibrate ADC
  * @adc: stm32 adc instance
- * Exit from power down, calibrate ADC, then return to power down.
+ * Note: Must be called once ADC is out of power down.
  */
 static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct stm32_adc_calib *cal = &adc->common->cal[adc->id];
 	int ret;
 	u32 val;
 
-	ret = stm32h7_adc_exit_pwr_down(adc);
-	if (ret)
-		return ret;
+	if (cal->calibrated)
+		return cal->calibrated;
 
 	/*
 	 * Select calibration mode:
@@ -927,7 +1289,7 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
 					   STM32H7_ADC_CALIB_TIMEOUT_US);
 	if (ret) {
 		dev_err(&indio_dev->dev, "calibration failed\n");
-		goto pwr_dwn;
+		goto out;
 	}
 
 	/*
@@ -944,18 +1306,13 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
 					   STM32H7_ADC_CALIB_TIMEOUT_US);
 	if (ret) {
 		dev_err(&indio_dev->dev, "calibration failed\n");
-		goto pwr_dwn;
+		goto out;
 	}
 
+out:
 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR,
 			   STM32H7_ADCALDIF | STM32H7_ADCALLIN);
 
-	/* Read calibration result for future reference */
-	ret = stm32h7_adc_read_selfcalib(adc);
-
-pwr_dwn:
-	stm32h7_adc_enter_pwr_down(adc);
-
 	return ret;
 }
 
@@ -972,23 +1329,43 @@ static int stm32h7_adc_selfcalib(struct stm32_adc *adc)
  */
 static int stm32h7_adc_prepare(struct stm32_adc *adc)
 {
-	int ret;
+	u32 *difsel = &adc->common->difsel[adc->id];
+	u32 *pcsel = &adc->common->pcsel[adc->id];
+	int calib, ret;
+
+	/* protect race between regular/injected prepare, unprepare */
+	mutex_lock(&adc->common->inj[adc->id]);
+	adc->common->prepcnt[adc->id]++;
+	if (adc->common->prepcnt[adc->id] > 1) {
+		mutex_unlock(&adc->common->inj[adc->id]);
+		return 0;
+	}
 
 	ret = stm32h7_adc_exit_pwr_down(adc);
 	if (ret)
-		return ret;
+		goto unlock;
+
+	ret = stm32h7_adc_selfcalib(adc);
+	if (ret < 0)
+		goto pwr_dwn;
+	calib = ret;
 
-	stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, adc->difsel);
+	stm32_adc_writel(adc, STM32H7_ADC_DIFSEL, *difsel);
 
 	ret = stm32h7_adc_enable(adc);
 	if (ret)
 		goto pwr_dwn;
 
-	ret = stm32h7_adc_restore_selfcalib(adc);
+	/* Either restore or read calibration result for future reference */
+	if (calib)
+		ret = stm32h7_adc_restore_selfcalib(adc);
+	else
+		ret = stm32h7_adc_read_selfcalib(adc);
 	if (ret)
 		goto disable;
 
-	stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
+	stm32_adc_writel(adc, STM32H7_ADC_PCSEL, *pcsel);
+	mutex_unlock(&adc->common->inj[adc->id]);
 
 	return 0;
 
@@ -996,39 +1373,196 @@ static int stm32h7_adc_prepare(struct stm32_adc *adc)
 	stm32h7_adc_disable(adc);
 pwr_dwn:
 	stm32h7_adc_enter_pwr_down(adc);
+unlock:
+	adc->common->prepcnt[adc->id]--;
+	mutex_unlock(&adc->common->inj[adc->id]);
 
 	return ret;
 }
 
 static void stm32h7_adc_unprepare(struct stm32_adc *adc)
 {
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+	mutex_lock(&adc->common->inj[adc->id]);
+	adc->common->prepcnt[adc->id]--;
+	if (adc->common->prepcnt[adc->id] > 0) {
+		mutex_unlock(&adc->common->inj[adc->id]);
+		return;
+	}
+
+	if (adc->common->prepcnt[adc->id] < 0)
+		dev_err(&indio_dev->dev, "Unbalanced (un)prepare\n");
 	stm32h7_adc_disable(adc);
 	stm32h7_adc_enter_pwr_down(adc);
+	mutex_unlock(&adc->common->inj[adc->id]);
 }
 
 /**
- * stm32_adc_conf_scan_seq() - Build regular channels scan sequence
+ * stm32_adc_find_unused_awd() - Find an unused analog watchdog
+ * @adc: stm32 adc instance
+ *
+ * Loop for all AWD to find a free AWD.
+ * Returns free AWD index or busy error.
+ */
+static int stm32_adc_find_unused_awd(struct stm32_adc *adc)
+{
+	const struct stm32_adc_awd_reginfo *awd_reginfo =
+		adc->cfg->regs->awd_reginfo;
+	u32 val, mask;
+	int i;
+
+	/* find unused AWD, either use en bits or channel mask */
+	for (i = 0; i < adc->cfg->regs->num_awd; i++) {
+		val = stm32_adc_readl(adc, awd_reginfo[i].reg);
+		mask = awd_reginfo[i].en_bits | awd_reginfo[i].jen_bits;
+		if (mask && !(val & mask))
+			break;
+		if (!mask && !val)
+			break;
+	}
+
+	if (i >= adc->cfg->regs->num_awd)
+		return -EBUSY;
+
+	return i;
+}
+
+/**
+ * stm32_adc_awd_clear() - Disable analog watchdog for one adc
+ * @adc: stm32 adc instance
+ *
+ * Mask awd interrupts, disable awd.
+ */
+static void stm32_adc_awd_clear(struct stm32_adc *adc)
+{
+	int i;
+	u32 en_bits, ier = adc->cfg->regs->ier_eoc.reg;
+	struct stm32_adc_evt *evt;
+	const struct stm32_adc_awd_reginfo *awd_reginfo =
+		adc->cfg->regs->awd_reginfo;
+
+	list_for_each_entry(evt, &adc->evt_list, list) {
+		if (!evt->set)
+			continue;
+
+		i = evt->awd_id;
+
+		/* Disable AWD interrupt */
+		stm32_adc_clr_bits(adc, ier, awd_reginfo[i].ier_msk);
+
+		/* Disable AWD: either use en bits and channel num, or mask */
+		en_bits = awd_reginfo[i].en_bits | awd_reginfo[i].jen_bits;
+		if (en_bits)
+			stm32_adc_clr_bits(adc, awd_reginfo[i].reg, en_bits);
+		else
+			stm32_adc_writel(adc, awd_reginfo[i].reg, 0);
+
+		adc->awd_mask &= ~awd_reginfo[i].isr_msk;
+		evt->set = false;
+	}
+}
+
+/**
+ * stm32_adc_awd_set() - Set analog watchdog
+ * @adc: stm32 adc instance
+ *
+ * Set analog watchdog registers based on pre-built event list.
+ *
+ * Two watchdog types can be found in stm32 ADC:
+ * - 1st type can be used either on all channels, or on one channel. Choice
+ *   is made to assing it to one channel only. It is enabled with enable bits
+ *   and channel number.
+ * - 2nd type uses channel mask (choice to assign it to one channel only).
+ * In both case, set high & low threshold. Also unmask interrupt.
+ */
+static int stm32_adc_awd_set(struct stm32_adc *adc)
+{
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	int i;
+	struct stm32_adc_evt *evt;
+	const struct stm32_adc_awd_reginfo *awd_reginfo =
+		adc->cfg->regs->awd_reginfo;
+	u32 val, ier = adc->cfg->regs->ier_eoc.reg;
+
+	list_for_each_entry(evt, &adc->evt_list, list) {
+		if (!evt->enabled)
+			continue;
+
+		i = stm32_adc_find_unused_awd(adc);
+		if (i < 0) {
+			stm32_adc_awd_clear(adc);
+			return i;
+		}
+
+		evt->awd_id = i;
+		evt->set = true;
+		dev_dbg(&indio_dev->dev, "%s chan%d htr:%d ltr:%d\n",
+			__func__, evt->chan->channel, evt->hthresh,
+			evt->lthresh);
+
+		stm32_adc_writel(adc, awd_reginfo[i].htr, evt->hthresh);
+		stm32_adc_writel(adc, awd_reginfo[i].ltr, evt->lthresh);
+
+		/* Enable AWD: either use en bits and channel num, or mask */
+		if (awd_reginfo[i].en_bits | awd_reginfo[i].jen_bits) {
+			u32 mask = awd_reginfo[i].awdch_mask;
+			u32 shift = awd_reginfo[i].awdch_shift;
+
+			val = stm32_adc_readl(adc, awd_reginfo[i].reg);
+			val &= ~mask;
+			val |= (evt->chan->channel << shift) & mask;
+
+			if (adc->injected)
+				val |= awd_reginfo[i].jen_bits;
+			else
+				val |= awd_reginfo[i].en_bits;
+			stm32_adc_writel(adc, awd_reginfo[i].reg, val);
+		} else {
+			stm32_adc_writel(adc, awd_reginfo[i].reg,
+					 BIT(evt->chan->channel));
+		}
+
+		/* Enable AWD interrupt */
+		adc->awd_mask |= awd_reginfo[i].isr_msk;
+		stm32_adc_set_bits(adc, ier, awd_reginfo[i].ier_msk);
+	}
+
+	return 0;
+}
+
+/**
+ * stm32_adc_conf_scan_seq() - Build channels scan sequence
  * @indio_dev: IIO device
  * @scan_mask: channels to be converted
  *
  * Conversion sequence :
  * Apply sampling time settings for all channels.
  * Configure ADC scan sequence based on selected channels in scan_mask.
- * Add channels to SQR registers, from scan_mask LSB to MSB, then
+ * Add channels to (J)SQR registers, from scan_mask LSB to MSB, then
  * program sequence len.
  */
 static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
 				   const unsigned long *scan_mask)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
-	const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr;
+	u32 *smpr_val = adc->common->smpr_val[adc->id];
+	const struct stm32_adc_regs *sqr;
 	const struct iio_chan_spec *chan;
 	u32 val, bit;
-	int i = 0;
+	int sq_max, i = 0;
+
+	if (adc->injected) {
+		sqr = adc->cfg->regs->jsqr;
+		sq_max = STM32_ADC_MAX_JSQ;
+	} else {
+		sqr = adc->cfg->regs->sqr;
+		sq_max = STM32_ADC_MAX_SQ;
+	}
 
 	/* Apply sampling time settings */
-	stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]);
-	stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]);
+	stm32_adc_writel(adc, adc->cfg->regs->smpr[0], smpr_val[0]);
+	stm32_adc_writel(adc, adc->cfg->regs->smpr[1], smpr_val[1]);
 
 	for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
 		chan = indio_dev->channels + bit;
@@ -1037,11 +1571,12 @@ static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
 		 * sequence, starting with SQ1.
 		 */
 		i++;
-		if (i > STM32_ADC_MAX_SQ)
+		if (i > sq_max)
 			return -EINVAL;
 
-		dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n",
-			__func__, chan->channel, i);
+		dev_dbg(&indio_dev->dev, "%s chan %d to %s%d\n",
+			__func__, chan->channel, adc->injected ? "JSQ" : "SQ",
+			i);
 
 		val = stm32_adc_readl(adc, sqr[i].reg);
 		val &= ~sqr[i].mask;
@@ -1071,18 +1606,36 @@ static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
 				     struct iio_trigger *trig)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct stm32_adc_trig_info *trinfo;
+	struct iio_trigger *tr;
 	int i;
 
 	/* lookup triggers registered by stm32 timer trigger driver */
 	for (i = 0; adc->cfg->trigs[i].name; i++) {
+		trinfo = &adc->cfg->trigs[i];
 		/**
 		 * Checking both stm32 timer trigger type and trig name
 		 * should be safe against arbitrary trigger names.
 		 */
 		if ((is_stm32_timer_trigger(trig) ||
 		     is_stm32_lptim_trigger(trig)) &&
-		    !strcmp(adc->cfg->trigs[i].name, trig->name)) {
-			return adc->cfg->trigs[i].extsel;
+		    !strcmp(trinfo->name, trig->name)) {
+			if (adc->injected && (trinfo->flags & TRG_INJECTED))
+				return trinfo->jextsel;
+
+			if (!adc->injected && (trinfo->flags & TRG_REGULAR))
+				return trinfo->extsel;
+		}
+	}
+
+	/* loop for triggers registered by stm32-adc-core */
+	list_for_each_entry(tr, &adc->common->extrig_list, alloc_list) {
+		if (tr == trig) {
+			trinfo = iio_trigger_get_drvdata(trig);
+			if (adc->injected && (trinfo->flags & TRG_INJECTED))
+				return trinfo->jextsel;
+			if (!adc->injected && (trinfo->flags & TRG_REGULAR))
+				return trinfo->extsel;
 		}
 	}
 
@@ -1102,10 +1655,24 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
 			      struct iio_trigger *trig)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
-	u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG;
+	u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG, reg, mask,
+	    exten_shift, extsel_shift;
 	unsigned long flags;
 	int ret;
 
+	if (adc->injected) {
+		reg = adc->cfg->regs->jexten.reg;
+		mask = adc->cfg->regs->jexten.mask |
+			adc->cfg->regs->jextsel.mask;
+		exten_shift = adc->cfg->regs->jexten.shift;
+		extsel_shift = adc->cfg->regs->jextsel.shift;
+	} else {
+		reg = adc->cfg->regs->exten.reg;
+		mask = adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask;
+		exten_shift = adc->cfg->regs->exten.shift;
+		extsel_shift = adc->cfg->regs->extsel.shift;
+	}
+
 	if (trig) {
 		ret = stm32_adc_get_trig_extsel(indio_dev, trig);
 		if (ret < 0)
@@ -1117,11 +1684,9 @@ static int stm32_adc_set_trig(struct iio_dev *indio_dev,
 	}
 
 	spin_lock_irqsave(&adc->lock, flags);
-	val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg);
-	val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask);
-	val |= exten << adc->cfg->regs->exten.shift;
-	val |= extsel << adc->cfg->regs->extsel.shift;
-	stm32_adc_writel(adc,  adc->cfg->regs->exten.reg, val);
+	val = stm32_adc_readl(adc, reg) & ~mask;
+	val |= (exten << exten_shift) | (extsel << extsel_shift);
+	stm32_adc_writel(adc,  reg, val);
 	spin_unlock_irqrestore(&adc->lock, flags);
 
 	return 0;
@@ -1174,36 +1739,47 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
 				 int *res)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
 	const struct stm32_adc_regspec *regs = adc->cfg->regs;
+	u32 *smpr_val = adc->common->smpr_val[adc->id];
+	const struct stm32_adc_regs *sqr;
 	long timeout;
 	u32 val;
 	int ret;
 
 	reinit_completion(&adc->completion);
 
+	adc->num_conv = 1;
 	adc->bufi = 0;
 
-	if (adc->cfg->prepare) {
-		ret = adc->cfg->prepare(adc);
-		if (ret)
-			return ret;
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
 	}
 
 	/* Apply sampling time settings */
-	stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]);
-	stm32_adc_writel(adc, regs->smpr[1], adc->smpr_val[1]);
+	stm32_adc_writel(adc, regs->smpr[0], smpr_val[0]);
+	stm32_adc_writel(adc, regs->smpr[1], smpr_val[1]);
+
+	if (adc->injected)
+		sqr = regs->jsqr;
+	else
+		sqr = regs->sqr;
 
 	/* Program chan number in regular sequence (SQ1) */
-	val = stm32_adc_readl(adc, regs->sqr[1].reg);
-	val &= ~regs->sqr[1].mask;
-	val |= chan->channel << regs->sqr[1].shift;
-	stm32_adc_writel(adc, regs->sqr[1].reg, val);
+	val = stm32_adc_readl(adc, sqr[1].reg) & ~sqr[1].mask;
+	val |= chan->channel << sqr[1].shift;
+	stm32_adc_writel(adc, sqr[1].reg, val);
 
 	/* Set regular sequence len (0 for 1 conversion) */
-	stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask);
+	stm32_adc_clr_bits(adc, sqr[0].reg, sqr[0].mask);
 
 	/* Trigger detection disabled (conversion can be launched in SW) */
-	stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask);
+	if (adc->injected)
+		stm32_adc_clr_bits(adc, regs->jexten.reg, regs->jexten.mask);
+	else
+		stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask);
 
 	stm32_adc_conv_irq_enable(adc);
 
@@ -1224,8 +1800,8 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
 
 	stm32_adc_conv_irq_disable(adc);
 
-	if (adc->cfg->unprepare)
-		adc->cfg->unprepare(adc);
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 
 	return ret;
 }
@@ -1272,14 +1848,72 @@ static int stm32_adc_read_raw(struct iio_dev *indio_dev,
 	}
 }
 
+static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
+{
+	struct stm32_adc *adc = data;
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct stm32_adc_evt *evt;
+	const struct stm32_adc_regspec *regs = adc->cfg->regs;
+	const struct stm32_adc_awd_reginfo *awd_reginfo = regs->awd_reginfo;
+	u32 ier = regs->ier_eoc.reg, isr = regs->isr_eoc.reg;
+	u32 status = stm32_adc_readl(adc, isr);
+	irqreturn_t ret = IRQ_NONE;
+
+	/* Handle analog watchdog events */
+	list_for_each_entry(evt, &adc->evt_list, list) {
+		if (!evt->set || !(status & awd_reginfo[evt->awd_id].isr_msk))
+			continue;
+
+		/* We don't know whether it is a upper or lower threshold. */
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(evt->chan->type,
+						    evt->chan->channel,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_EITHER),
+			       iio_get_time_ns(indio_dev));
+
+		/* clear analog watchdog flag */
+		if (regs->write_one_to_clear)
+			stm32_adc_set_bits(adc, isr,
+					   awd_reginfo[evt->awd_id].isr_msk);
+		else
+			stm32_adc_clr_bits(adc, isr,
+					   awd_reginfo[evt->awd_id].isr_msk);
+
+		/* re-enable current awd interrupt */
+		stm32_adc_set_bits(adc, ier, awd_reginfo[evt->awd_id].ier_msk);
+
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
 static irqreturn_t stm32_adc_isr(int irq, void *data)
 {
 	struct stm32_adc *adc = data;
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 	const struct stm32_adc_regspec *regs = adc->cfg->regs;
+	const struct stm32_adc_awd_reginfo *awd_reginfo = regs->awd_reginfo;
 	u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
+	u32 ier = adc->cfg->regs->ier_eoc.reg;
+	irqreturn_t ret = IRQ_NONE;
+	int i;
+
+	if (!adc->injected && (status & regs->isr_ovr.mask)) {
+		/*
+		 * Overrun occured on regular conversions. Can't recover easily
+		 * especially in scan mode: data for wrong channel may be read.
+		 * Then, unconditionally disable interrupts to stop processing
+		 * data, and lazily print error message (once).
+		 */
+		stm32_adc_ovr_irq_disable(adc);
+		stm32_adc_conv_irq_disable(adc);
+		dev_err(&indio_dev->dev, "Overrun interrupt, stopping.\n");
+		return IRQ_HANDLED;
+	}
 
-	if (status & regs->isr_eoc.mask) {
+	if (!adc->injected && (status & regs->isr_eoc.mask)) {
 		/* Reading DR also clears EOC status flag */
 		adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr);
 		if (iio_buffer_enabled(indio_dev)) {
@@ -1291,10 +1925,48 @@ static irqreturn_t stm32_adc_isr(int irq, void *data)
 		} else {
 			complete(&adc->completion);
 		}
-		return IRQ_HANDLED;
+		ret = IRQ_HANDLED;
+	}
+
+	if (adc->injected && (status & regs->isr_jeoc.mask)) {
+		int i;
+
+		if (regs->write_one_to_clear)
+			stm32_adc_writel(adc, regs->isr_jeoc.reg,
+					 regs->isr_jeoc.mask);
+		else
+			stm32_adc_writel(adc, regs->isr_jeoc.reg,
+					 ~regs->isr_jeoc.mask);
+
+		for (i = 0; i < adc->num_conv; i++) {
+			adc->buffer[i] = stm32_adc_readw(adc, regs->jdr[i]);
+			adc->bufi++;
+		}
+
+		if (iio_buffer_enabled(indio_dev)) {
+			stm32_adc_conv_irq_disable(adc);
+			iio_trigger_poll(indio_dev->trig);
+		} else {
+			complete(&adc->completion);
+		}
+		ret = IRQ_HANDLED;
+	}
+
+	/* only check AWD assigned to this ADC (e.g. regular or injected) */
+	status &= adc->awd_mask;
+	if (status) {
+		for (i = 0; i < adc->cfg->regs->num_awd; i++) {
+			/* mask current awd interrupt */
+			if (status & awd_reginfo[i].isr_msk)
+				stm32_adc_clr_bits(adc, ier,
+						   awd_reginfo[i].ier_msk);
+		}
+
+		/* AWD has detected an event, need to wake IRQ thread */
+		ret = IRQ_WAKE_THREAD;
 	}
 
-	return IRQ_NONE;
+	return ret;
 }
 
 /**
@@ -1333,13 +2005,168 @@ static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev,
 				      const unsigned long *scan_mask)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
 	int ret;
 
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
+
 	adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength);
 
 	ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
-	if (ret)
-		return ret;
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
+	return ret;
+}
+
+/*
+ * stm32 awd monitors specified channel(s) are within window range.
+ * Define events here as high/low thresholds, with a common enable for
+ * both directions. There is no way to know from interrupt flags, which
+ * direction an event occurred. It's up to upper layers then to check
+ * value.
+ */
+static const struct iio_event_spec stm32_adc_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static int stm32_adc_read_event_config(struct iio_dev *indio_dev,
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct stm32_adc_evt *evt;
+
+	list_for_each_entry(evt, &adc->evt_list, list)
+		if (evt->chan == chan)
+			return evt->enabled;
+
+	return 0;
+}
+
+static int stm32_adc_write_event_config(struct iio_dev *indio_dev,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
+					int state)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct stm32_adc_evt *evt;
+	bool found = false;
+	int i = 0;
+
+	/* AWD can only be configured before starting conversions */
+	if (adc->cfg->is_started(adc))
+		return -EBUSY;
+
+	list_for_each_entry(evt, &adc->evt_list, list) {
+		if (evt->chan == chan) {
+			found = true;
+			evt->enabled = !!state;
+		}
+
+		/* number of enabled AWD for this adc instance */
+		if (evt->enabled)
+			i++;
+
+		/* unique event per AWD: don't exceed number of AWD */
+		if (i > adc->cfg->regs->num_awd)
+			goto err_busy;
+	}
+
+	/* In case no threshold have been configured, can't enable evt */
+	if (!found)
+		return -EINVAL;
+
+	return 0;
+
+err_busy:
+	dev_err(&indio_dev->dev, "Number of awd exceeded\n");
+
+	list_for_each_entry(evt, &adc->evt_list, list)
+		if (evt->chan == chan)
+			evt->enabled = false;
+
+	return -EBUSY;
+}
+
+static int stm32_adc_read_thresh(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir,
+				 enum iio_event_info info, int *val,
+				 int *val2)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct stm32_adc_evt *evt;
+
+	*val = 0;
+
+	list_for_each_entry(evt, &adc->evt_list, list) {
+		if (evt->chan == chan) {
+			if (dir == IIO_EV_DIR_RISING)
+				*val = evt->hthresh;
+			else
+				*val = evt->lthresh;
+			break;
+		}
+	}
+
+	return IIO_VAL_INT;
+}
+
+static int stm32_adc_write_thresh(struct iio_dev *indio_dev,
+				  const struct iio_chan_spec *chan,
+				  enum iio_event_type type,
+				  enum iio_event_direction dir,
+				  enum iio_event_info info, int val,
+				  int val2)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct stm32_adc_evt *evt;
+	unsigned long flags;
+
+	if (adc->cfg->is_started(adc))
+		return -EBUSY;
+
+	/* Look for existing evt for this channel */
+	list_for_each_entry(evt, &adc->evt_list, list)
+		if (evt->chan == chan)
+			goto found;
+
+	/* Allocate new event: up to num_channels evts */
+	evt = devm_kzalloc(&indio_dev->dev, sizeof(*evt), GFP_KERNEL);
+	if (!evt)
+		return -ENOMEM;
+
+	evt->chan = chan;
+
+	spin_lock_irqsave(&adc->lock, flags);
+	list_add_tail(&evt->list, &adc->evt_list);
+	spin_unlock_irqrestore(&adc->lock, flags);
+
+found:
+	if (dir == IIO_EV_DIR_RISING)
+		evt->hthresh = val;
+	else
+		evt->lthresh = val;
 
 	return 0;
 }
@@ -1371,12 +2198,23 @@ static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
 					unsigned *readval)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
 
 	if (!readval)
 		stm32_adc_writel(adc, reg, writeval);
 	else
 		*readval = stm32_adc_readl(adc, reg);
 
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
 	return 0;
 }
 
@@ -1385,6 +2223,10 @@ static const struct iio_info stm32_adc_iio_info = {
 	.validate_trigger = stm32_adc_validate_trigger,
 	.hwfifo_set_watermark = stm32_adc_set_watermark,
 	.update_scan_mode = stm32_adc_update_scan_mode,
+	.read_event_config = &stm32_adc_read_event_config,
+	.write_event_config = &stm32_adc_write_event_config,
+	.read_event_value = stm32_adc_read_thresh,
+	.write_event_value = stm32_adc_write_thresh,
 	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
 	.of_xlate = stm32_adc_of_xlate,
 };
@@ -1459,21 +2301,28 @@ static int stm32_adc_dma_start(struct iio_dev *indio_dev)
 	return 0;
 }
 
-static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
+static int __stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
 	int ret;
 
-	if (adc->cfg->prepare) {
-		ret = adc->cfg->prepare(adc);
-		if (ret)
-			return ret;
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
+
+	ret = stm32_adc_awd_set(adc);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Failed to configure awd\n");
+		goto err_pm_put;
 	}
 
 	ret = stm32_adc_set_trig(indio_dev, indio_dev->trig);
 	if (ret) {
 		dev_err(&indio_dev->dev, "Can't set trigger\n");
-		goto err_unprepare;
+		goto err_clr_awd;
 	}
 
 	ret = stm32_adc_dma_start(indio_dev);
@@ -1482,13 +2331,11 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
 		goto err_clr_trig;
 	}
 
-	ret = iio_triggered_buffer_postenable(indio_dev);
-	if (ret < 0)
-		goto err_stop_dma;
-
 	/* Reset adc buffer index */
 	adc->bufi = 0;
 
+	stm32_adc_ovr_irq_enable(adc);
+
 	if (!adc->dma_chan)
 		stm32_adc_conv_irq_enable(adc);
 
@@ -1496,30 +2343,42 @@ static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
 
 	return 0;
 
-err_stop_dma:
-	if (adc->dma_chan)
-		dmaengine_terminate_all(adc->dma_chan);
 err_clr_trig:
 	stm32_adc_set_trig(indio_dev, NULL);
-err_unprepare:
-	if (adc->cfg->unprepare)
-		adc->cfg->unprepare(adc);
+err_clr_awd:
+	stm32_adc_awd_clear(adc);
+err_pm_put:
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 
 	return ret;
 }
 
-static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
+static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
 {
-	struct stm32_adc *adc = iio_priv(indio_dev);
 	int ret;
 
+	ret = iio_triggered_buffer_postenable(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	ret = __stm32_adc_buffer_postenable(indio_dev);
+	if (ret < 0)
+		iio_triggered_buffer_predisable(indio_dev);
+
+	return ret;
+}
+
+static void __stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	struct device *dev = indio_dev->dev.parent;
+
 	adc->cfg->stop_conv(adc);
 	if (!adc->dma_chan)
 		stm32_adc_conv_irq_disable(adc);
 
-	ret = iio_triggered_buffer_predisable(indio_dev);
-	if (ret < 0)
-		dev_err(&indio_dev->dev, "predisable failed\n");
+	stm32_adc_ovr_irq_disable(adc);
 
 	if (adc->dma_chan)
 		dmaengine_terminate_all(adc->dma_chan);
@@ -1527,8 +2386,21 @@ static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
 	if (stm32_adc_set_trig(indio_dev, NULL))
 		dev_err(&indio_dev->dev, "Can't clear trigger\n");
 
-	if (adc->cfg->unprepare)
-		adc->cfg->unprepare(adc);
+	stm32_adc_awd_clear(adc);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
+static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	int ret;
+
+	__stm32_adc_buffer_predisable(indio_dev);
+
+	ret = iio_triggered_buffer_predisable(indio_dev);
+	if (ret < 0)
+		dev_err(&indio_dev->dev, "predisable failed\n");
 
 	return ret;
 }
@@ -1613,6 +2485,7 @@ static int stm32_adc_of_get_resolution(struct iio_dev *indio_dev)
 static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
 {
 	const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel];
+	u32 *smpr_val = adc->common->smpr_val[adc->id];
 	u32 period_ns, shift = smpr->shift, mask = smpr->mask;
 	unsigned int smp, r = smpr->reg;
 
@@ -1625,7 +2498,7 @@ static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
 		smp = STM32_ADC_MAX_SMP;
 
 	/* pre-build sampling time registers (e.g. smpr1, smpr2) */
-	adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift);
+	smpr_val[r] = (smpr_val[r] & ~mask) | (smp << shift);
 }
 
 static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
@@ -1634,6 +2507,8 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
 	char *name = adc->chan_name[vinp];
+	u32 *difsel = &adc->common->difsel[adc->id];
+	u32 *pcsel = &adc->common->pcsel[adc->id];
 
 	chan->type = IIO_VOLTAGE;
 	chan->channel = vinp;
@@ -1654,14 +2529,16 @@ static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
 	chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
 	chan->scan_type.storagebits = 16;
 	chan->ext_info = stm32_adc_ext_info;
+	chan->event_spec = stm32_adc_events;
+	chan->num_event_specs = ARRAY_SIZE(stm32_adc_events);
 
 	/* pre-build selected channels mask */
-	adc->pcsel |= BIT(chan->channel);
+	*pcsel |= BIT(chan->channel);
 	if (differential) {
 		/* pre-build diff channels mask */
-		adc->difsel |= BIT(chan->channel);
+		*difsel |= BIT(chan->channel);
 		/* Also add negative input to pre-selected channels */
-		adc->pcsel |= BIT(chan->channel2);
+		*pcsel |= BIT(chan->channel2);
 	}
 }
 
@@ -1677,6 +2554,11 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
 	int scan_index = 0, num_channels = 0, num_diff = 0, ret, i;
 	u32 val, smp = 0;
 
+	if (of_property_read_bool(node, "st,injected")) {
+		dev_dbg(&indio_dev->dev, "Configured to use injected\n");
+		adc->injected = true;
+	}
+
 	ret = of_property_count_u32_elems(node, "st,adc-channels");
 	if (ret > adc_info->max_channels) {
 		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
@@ -1828,6 +2710,7 @@ static int stm32_adc_probe(struct platform_device *pdev)
 	init_completion(&adc->completion);
 	adc->cfg = (const struct stm32_adc_cfg *)
 		of_match_device(dev->driver->of_match_table, dev)->data;
+	INIT_LIST_HEAD(&adc->evt_list);
 
 	indio_dev->name = dev_name(&pdev->dev);
 	indio_dev->dev.parent = &pdev->dev;
@@ -1838,10 +2721,18 @@ static int stm32_adc_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, adc);
 
 	ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
-	if (ret != 0) {
+	if (ret != 0 || adc->offset >= STM32_ADCX_COMN_OFFSET) {
 		dev_err(&pdev->dev, "missing reg property\n");
 		return -EINVAL;
 	}
+	adc->id = adc->offset / STM32_ADC_OFFSET;
+
+	of_property_read_u32(pdev->dev.of_node, "st,trigger-polarity",
+			     &adc->trigger_polarity);
+	if (adc->trigger_polarity >= ARRAY_SIZE(stm32_trig_pol_items)) {
+		dev_err(&pdev->dev, "Invalid st,trigger-polarity property\n");
+		return -EINVAL;
+	}
 
 	adc->irq = platform_get_irq(pdev, 0);
 	if (adc->irq < 0) {
@@ -1849,8 +2740,9 @@ static int stm32_adc_probe(struct platform_device *pdev)
 		return adc->irq;
 	}
 
-	ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr,
-			       0, pdev->name, adc);
+	ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
+					stm32_adc_threaded_isr,
+					0, pdev->name, adc);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
 		return ret;
@@ -1867,32 +2759,17 @@ static int stm32_adc_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (adc->clk) {
-		ret = clk_prepare_enable(adc->clk);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "clk enable failed\n");
-			return ret;
-		}
-	}
-
 	ret = stm32_adc_of_get_resolution(indio_dev);
 	if (ret < 0)
-		goto err_clk_disable;
-	stm32_adc_set_res(adc);
-
-	if (adc->cfg->selfcalib) {
-		ret = adc->cfg->selfcalib(adc);
-		if (ret)
-			goto err_clk_disable;
-	}
+		return ret;
 
 	ret = stm32_adc_chan_of_init(indio_dev);
 	if (ret < 0)
-		goto err_clk_disable;
+		return ret;
 
 	ret = stm32_adc_dma_request(indio_dev);
 	if (ret < 0)
-		goto err_clk_disable;
+		return ret;
 
 	ret = iio_triggered_buffer_setup(indio_dev,
 					 &iio_pollfunc_store_time,
@@ -1903,15 +2780,35 @@ static int stm32_adc_probe(struct platform_device *pdev)
 		goto err_dma_disable;
 	}
 
+	/* Get stm32-adc-core PM online */
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_set_autosuspend_delay(dev, STM32_ADC_AUTO_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_enable(dev);
+
+	ret = stm32_adc_hw_start(dev);
+	if (ret)
+		goto err_buffer_cleanup;
+
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "iio dev register failed\n");
-		goto err_buffer_cleanup;
+		goto err_hw_stop;
 	}
 
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
 	return 0;
 
+err_hw_stop:
+	stm32_adc_hw_stop(dev);
+
 err_buffer_cleanup:
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 
 err_dma_disable:
@@ -1921,9 +2818,6 @@ static int stm32_adc_probe(struct platform_device *pdev)
 				  adc->rx_buf, adc->rx_dma_buf);
 		dma_release_channel(adc->dma_chan);
 	}
-err_clk_disable:
-	if (adc->clk)
-		clk_disable_unprepare(adc->clk);
 
 	return ret;
 }
@@ -1933,7 +2827,12 @@ static int stm32_adc_remove(struct platform_device *pdev)
 	struct stm32_adc *adc = platform_get_drvdata(pdev);
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 
+	pm_runtime_get_sync(&pdev->dev);
 	iio_device_unregister(indio_dev);
+	stm32_adc_hw_stop(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	if (adc->dma_chan) {
 		dma_free_coherent(adc->dma_chan->device->dev,
@@ -1941,12 +2840,62 @@ static int stm32_adc_remove(struct platform_device *pdev)
 				  adc->rx_buf, adc->rx_dma_buf);
 		dma_release_channel(adc->dma_chan);
 	}
-	if (adc->clk)
-		clk_disable_unprepare(adc->clk);
 
 	return 0;
 }
 
+#if defined(CONFIG_PM_SLEEP)
+static int stm32_adc_suspend(struct device *dev)
+{
+	struct stm32_adc *adc = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+	if (iio_buffer_enabled(indio_dev))
+		__stm32_adc_buffer_predisable(indio_dev);
+
+	return pm_runtime_force_suspend(dev);
+}
+
+static int stm32_adc_resume(struct device *dev)
+{
+	struct stm32_adc *adc = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	int ret;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		return ret;
+
+	if (!iio_buffer_enabled(indio_dev))
+		return 0;
+
+	ret = stm32_adc_update_scan_mode(indio_dev,
+					 indio_dev->active_scan_mask);
+	if (ret < 0)
+		return ret;
+
+	return __stm32_adc_buffer_postenable(indio_dev);
+}
+#endif
+
+#if defined(CONFIG_PM)
+static int stm32_adc_runtime_suspend(struct device *dev)
+{
+	return stm32_adc_hw_stop(dev);
+}
+
+static int stm32_adc_runtime_resume(struct device *dev)
+{
+	return stm32_adc_hw_start(dev);
+}
+#endif
+
+static const struct dev_pm_ops stm32_adc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume)
+	SET_RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume,
+			   NULL)
+};
+
 static const struct stm32_adc_cfg stm32f4_adc_cfg = {
 	.regs = &stm32f4_adc_regspec,
 	.adc_info = &stm32f4_adc_info,
@@ -1955,18 +2904,19 @@ static const struct stm32_adc_cfg stm32f4_adc_cfg = {
 	.start_conv = stm32f4_adc_start_conv,
 	.stop_conv = stm32f4_adc_stop_conv,
 	.smp_cycles = stm32f4_adc_smp_cycles,
+	.is_started = stm32f4_adc_is_started,
 };
 
 static const struct stm32_adc_cfg stm32h7_adc_cfg = {
 	.regs = &stm32h7_adc_regspec,
 	.adc_info = &stm32h7_adc_info,
 	.trigs = stm32h7_adc_trigs,
-	.selfcalib = stm32h7_adc_selfcalib,
 	.start_conv = stm32h7_adc_start_conv,
 	.stop_conv = stm32h7_adc_stop_conv,
 	.prepare = stm32h7_adc_prepare,
 	.unprepare = stm32h7_adc_unprepare,
 	.smp_cycles = stm32h7_adc_smp_cycles,
+	.is_started = stm32h7_adc_is_started,
 };
 
 static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
@@ -1974,12 +2924,12 @@ static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
 	.adc_info = &stm32h7_adc_info,
 	.trigs = stm32h7_adc_trigs,
 	.has_vregready = true,
-	.selfcalib = stm32h7_adc_selfcalib,
 	.start_conv = stm32h7_adc_start_conv,
 	.stop_conv = stm32h7_adc_stop_conv,
 	.prepare = stm32h7_adc_prepare,
 	.unprepare = stm32h7_adc_unprepare,
 	.smp_cycles = stm32h7_adc_smp_cycles,
+	.is_started = stm32h7_adc_is_started,
 };
 
 static const struct of_device_id stm32_adc_of_match[] = {
@@ -1996,6 +2946,7 @@ static struct platform_driver stm32_adc_driver = {
 	.driver = {
 		.name = "stm32-adc",
 		.of_match_table = stm32_adc_of_match,
+		.pm = &stm32_adc_pm_ops,
 	},
 };
 module_platform_driver(stm32_adc_driver);
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index fcd4a1c..c97d9ee 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -12,6 +12,11 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/hw-consumer.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/timer/stm32-lptim-trigger.h>
+#include <linux/iio/timer/stm32-timer-trigger.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -38,6 +43,11 @@
 #define DFSDM_MAX_RES BIT(31)
 #define DFSDM_DATA_RES BIT(23)
 
+/* Filter configuration */
+#define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \
+			    DFSDM_CR1_RSYNC_MASK | DFSDM_CR1_JSYNC_MASK | \
+			    DFSDM_CR1_JSCAN_MASK)
+
 enum sd_converter_type {
 	DFSDM_AUDIO,
 	DFSDM_IIO,
@@ -54,6 +64,8 @@ struct stm32_dfsdm_adc {
 	struct stm32_dfsdm *dfsdm;
 	const struct stm32_dfsdm_dev_data *dev_data;
 	unsigned int fl_id;
+	unsigned int nconv;
+	unsigned long smask;
 
 	/* ADC specific */
 	unsigned int oversamp;
@@ -114,6 +126,61 @@ static int stm32_dfsdm_str2val(const char *str,
 	return -EINVAL;
 }
 
+/**
+ * struct stm32_dfsdm_trig_info - DFSDM trigger info
+ * @name:		name of the trigger, corresponding to its source
+ * @jextsel:		trigger signal selection
+ */
+struct stm32_dfsdm_trig_info {
+	const char *name;
+	unsigned int jextsel;
+};
+
+/* hardware injected trigger enable, edge selection */
+enum stm32_dfsdm_jexten {
+	STM32_DFSDM_JEXTEN_DISABLED,
+	STM32_DFSDM_JEXTEN_RISING_EDGE,
+	STM32_DFSDM_JEXTEN_FALLING_EDGE,
+	STM32_DFSDM_EXTEN_BOTH_EDGES,
+};
+
+static const struct stm32_dfsdm_trig_info stm32_dfsdm_trigs[] = {
+	{ TIM1_TRGO, 0 },
+	{ TIM1_TRGO2, 1 },
+	{ TIM8_TRGO, 2 },
+	{ TIM8_TRGO2, 3 },
+	{ TIM3_TRGO, 4 },
+	{ TIM4_TRGO, 5 },
+	{ TIM16_OC1, 6 },
+	{ TIM6_TRGO, 7 },
+	{ TIM7_TRGO, 8 },
+	{ LPTIM1_OUT, 26 },
+	{ LPTIM2_OUT, 27 },
+	{ LPTIM3_OUT, 28 },
+	{},
+};
+
+static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev,
+				   struct iio_trigger *trig)
+{
+	int i;
+
+	/* lookup triggers registered by stm32 timer trigger driver */
+	for (i = 0; stm32_dfsdm_trigs[i].name; i++) {
+		/**
+		 * Checking both stm32 timer trigger type and trig name
+		 * should be safe against arbitrary trigger names.
+		 */
+		if ((is_stm32_timer_trigger(trig) ||
+		     is_stm32_lptim_trigger(trig)) &&
+		    !strcmp(stm32_dfsdm_trigs[i].name, trig->name)) {
+			return stm32_dfsdm_trigs[i].jextsel;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
 				unsigned int fast, unsigned int oversamp)
 {
@@ -200,19 +267,39 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
 	return 0;
 }
 
-static int stm32_dfsdm_start_channel(struct stm32_dfsdm *dfsdm,
-				     unsigned int ch_id)
+static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc)
 {
-	return regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id),
-				  DFSDM_CHCFGR1_CHEN_MASK,
-				  DFSDM_CHCFGR1_CHEN(1));
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct regmap *regmap = adc->dfsdm->regmap;
+	const struct iio_chan_spec *chan;
+	unsigned int bit;
+	int ret;
+
+	for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) {
+		chan = indio_dev->channels + bit;
+		ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel),
+					 DFSDM_CHCFGR1_CHEN_MASK,
+					 DFSDM_CHCFGR1_CHEN(1));
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
 }
 
-static void stm32_dfsdm_stop_channel(struct stm32_dfsdm *dfsdm,
-				     unsigned int ch_id)
+static void stm32_dfsdm_stop_channel(struct stm32_dfsdm_adc *adc)
 {
-	regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id),
-			   DFSDM_CHCFGR1_CHEN_MASK, DFSDM_CHCFGR1_CHEN(0));
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct regmap *regmap = adc->dfsdm->regmap;
+	const struct iio_chan_spec *chan;
+	unsigned int bit;
+
+	for_each_set_bit(bit, &adc->smask, sizeof(adc->smask) * BITS_PER_BYTE) {
+		chan = indio_dev->channels + bit;
+		regmap_update_bits(regmap, DFSDM_CHCFGR1(chan->channel),
+				   DFSDM_CHCFGR1_CHEN_MASK,
+				   DFSDM_CHCFGR1_CHEN(0));
+	}
 }
 
 static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm,
@@ -237,9 +324,11 @@ static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm,
 				  DFSDM_CHCFGR1_CHINSEL(ch->alt_si));
 }
 
-static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm,
-				    unsigned int fl_id)
+static int stm32_dfsdm_start_filter(struct stm32_dfsdm_adc *adc,
+				    unsigned int fl_id,
+				    struct iio_trigger *trig)
 {
+	struct stm32_dfsdm *dfsdm = adc->dfsdm;
 	int ret;
 
 	/* Enable filter */
@@ -248,7 +337,11 @@ static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm,
 	if (ret < 0)
 		return ret;
 
-	/* Start conversion */
+	/* Nothing more to do for injected (scan mode/triggered) conversions */
+	if (adc->nconv > 1 || trig)
+		return 0;
+
+	/* Software start (single or continuous) regular conversion */
 	return regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id),
 				  DFSDM_CR1_RSWSTART_MASK,
 				  DFSDM_CR1_RSWSTART(1));
@@ -262,11 +355,45 @@ static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm,
 			   DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0));
 }
 
-static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm,
-					unsigned int fl_id, unsigned int ch_id)
+static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc,
+				       unsigned int fl_id,
+				       struct iio_trigger *trig)
 {
-	struct regmap *regmap = dfsdm->regmap;
-	struct stm32_dfsdm_filter *fl = &dfsdm->fl_list[fl_id];
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct regmap *regmap = adc->dfsdm->regmap;
+	u32 jextsel = 0, jexten = STM32_DFSDM_JEXTEN_DISABLED;
+	int ret;
+
+	if (trig) {
+		ret = stm32_dfsdm_get_jextsel(indio_dev, trig);
+		if (ret < 0)
+			return ret;
+
+		/* set trigger source and polarity (default to rising edge) */
+		jextsel = ret;
+		jexten = STM32_DFSDM_JEXTEN_RISING_EDGE;
+	}
+
+	ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id),
+				 DFSDM_CR1_JEXTSEL_MASK | DFSDM_CR1_JEXTEN_MASK,
+				 DFSDM_CR1_JEXTSEL(jextsel) |
+				 DFSDM_CR1_JEXTEN(jexten));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
+					unsigned int fl_id,
+					struct iio_trigger *trig)
+{
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct regmap *regmap = adc->dfsdm->regmap;
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
+	u32 cr1;
+	const struct iio_chan_spec *chan;
+	unsigned int bit, jchg = 0;
 	int ret;
 
 	/* Average integrator oversampling */
@@ -286,15 +413,68 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm,
 	if (ret)
 		return ret;
 
-	/* No scan mode supported for the moment */
-	ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RCH_MASK,
-				 DFSDM_CR1_RCH(ch_id));
+	ret = stm32_dfsdm_filter_set_trig(adc, fl_id, trig);
 	if (ret)
 		return ret;
 
-	return regmap_update_bits(regmap, DFSDM_CR1(fl_id),
-				  DFSDM_CR1_RSYNC_MASK,
-				  DFSDM_CR1_RSYNC(fl->sync_mode));
+	/*
+	 * DFSDM modes configuration W.R.T audio/iio type modes
+	 * ----------------------------------------------------------------
+	 * Modes         | regular |  regular     | injected | injected   |
+	 *               |         |  continuous  |          | + scan     |
+	 * --------------|---------|--------------|----------|------------|
+	 * single conv   |    x    |              |          |            |
+	 * (1 chan)      |         |              |          |            |
+	 * --------------|---------|--------------|----------|------------|
+	 * 1 Audio chan	 |         | sample freq  |          |            |
+	 *               |         | or sync_mode |          |            |
+	 * --------------|---------|--------------|----------|------------|
+	 * 1 IIO chan	 |         | sample freq  | trigger  |            |
+	 *               |         | or sync_mode |          |            |
+	 * --------------|---------|--------------|----------|------------|
+	 * 2+ IIO chans  |         |              |          | trigger or |
+	 *               |         |              |          | sync_mode  |
+	 * ----------------------------------------------------------------
+	 */
+	if (adc->nconv == 1 && !trig) {
+		bit = __ffs(adc->smask);
+		chan = indio_dev->channels + bit;
+
+		/* Use regular conversion for single channel without trigger */
+		cr1 = DFSDM_CR1_RCH(chan->channel);
+
+		/* Continuous conversions triggered by SPI clock in buffer mode */
+		if (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)
+			cr1 |= DFSDM_CR1_RCONT(1);
+
+		cr1 |= DFSDM_CR1_RSYNC(fl->sync_mode);
+	} else {
+		/* Use injected conversion for multiple channels */
+		for_each_set_bit(bit, &adc->smask,
+				 sizeof(adc->smask) * BITS_PER_BYTE) {
+			chan = indio_dev->channels + bit;
+			jchg |= BIT(chan->channel);
+		}
+		ret = regmap_write(regmap, DFSDM_JCHGR(fl_id), jchg);
+		if (ret < 0)
+			return ret;
+
+		/* Use scan mode for multiple channels */
+		cr1 = DFSDM_CR1_JSCAN(!!(adc->nconv > 1));
+
+		/*
+		 * Continuous conversions not supported in injected mode,
+		 * either use:
+		 * - conversions in sync with filter 0
+		 * - triggered conversions
+		 */
+		if (!fl->sync_mode && !trig)
+			return -EINVAL;
+		cr1 |= DFSDM_CR1_JSYNC(fl->sync_mode);
+	}
+
+	return regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_CFG_MASK,
+				  cr1);
 }
 
 static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm,
@@ -378,13 +558,37 @@ static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev,
 	return snprintf(buf, PAGE_SIZE, "%d\n", adc->spi_freq);
 }
 
+static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
+				   unsigned int sample_freq,
+				   unsigned int spi_freq)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	unsigned int oversamp;
+	int ret;
+
+	oversamp = DIV_ROUND_CLOSEST(spi_freq, sample_freq);
+	if (spi_freq % sample_freq)
+		dev_warn(&indio_dev->dev, "Sampling rate not accurate (%d)\n",
+			 spi_freq / oversamp);
+
+	ret = stm32_dfsdm_set_osrs(fl, 0, oversamp);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "No filter parameters that match!\n");
+		return ret;
+	}
+	adc->sample_freq = spi_freq / oversamp;
+	adc->oversamp = oversamp;
+
+	return 0;
+}
+
 static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
 					  uintptr_t priv,
 					  const struct iio_chan_spec *chan,
 					  const char *buf, size_t len)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
 	struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel];
 	unsigned int sample_freq = adc->sample_freq;
 	unsigned int spi_freq;
@@ -403,17 +607,9 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
 		return -EINVAL;
 
 	if (sample_freq) {
-		if (spi_freq % sample_freq)
-			dev_warn(&indio_dev->dev,
-				 "Sampling rate not accurate (%d)\n",
-				 spi_freq / (spi_freq / sample_freq));
-
-		ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / sample_freq));
-		if (ret < 0) {
-			dev_err(&indio_dev->dev,
-				"No filter parameters that match!\n");
+		ret = dfsdm_adc_set_samp_freq(indio_dev, sample_freq, spi_freq);
+		if (ret < 0)
 			return ret;
-		}
 	}
 	adc->spi_freq = spi_freq;
 
@@ -421,72 +617,44 @@ static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev,
 }
 
 static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc,
-				  const struct iio_chan_spec *chan,
-				  bool dma)
+				  struct iio_trigger *trig)
 {
 	struct regmap *regmap = adc->dfsdm->regmap;
 	int ret;
-	unsigned int dma_en = 0, cont_en = 0;
 
-	ret = stm32_dfsdm_start_channel(adc->dfsdm, chan->channel);
+	ret = stm32_dfsdm_start_channel(adc);
 	if (ret < 0)
 		return ret;
 
-	ret = stm32_dfsdm_filter_configure(adc->dfsdm, adc->fl_id,
-					   chan->channel);
+	ret = stm32_dfsdm_filter_configure(adc, adc->fl_id, trig);
 	if (ret < 0)
 		goto stop_channels;
 
-	if (dma) {
-		/* Enable DMA transfer*/
-		dma_en =  DFSDM_CR1_RDMAEN(1);
-		/* Enable conversion triggered by SPI clock*/
-		cont_en = DFSDM_CR1_RCONT(1);
-	}
-	/* Enable DMA transfer*/
-	ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-				 DFSDM_CR1_RDMAEN_MASK, dma_en);
+	ret = stm32_dfsdm_start_filter(adc, adc->fl_id, trig);
 	if (ret < 0)
-		goto stop_channels;
-
-	/* Enable conversion triggered by SPI clock*/
-	ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-				 DFSDM_CR1_RCONT_MASK, cont_en);
-	if (ret < 0)
-		goto stop_channels;
-
-	ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id);
-	if (ret < 0)
-		goto stop_channels;
+		goto filter_unconfigure;
 
 	return 0;
 
-stop_channels:
+filter_unconfigure:
 	regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-			   DFSDM_CR1_RDMAEN_MASK, 0);
-
-	regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-			   DFSDM_CR1_RCONT_MASK, 0);
-	stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel);
+			   DFSDM_CR1_CFG_MASK, 0);
+stop_channels:
+	stm32_dfsdm_stop_channel(adc);
 
 	return ret;
 }
 
-static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc,
-				  const struct iio_chan_spec *chan)
+static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc)
 {
 	struct regmap *regmap = adc->dfsdm->regmap;
 
 	stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id);
 
-	/* Clean conversion options */
-	regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-			   DFSDM_CR1_RDMAEN_MASK, 0);
-
 	regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id),
-			   DFSDM_CR1_RCONT_MASK, 0);
+			   DFSDM_CR1_CFG_MASK, 0);
 
-	stm32_dfsdm_stop_channel(adc->dfsdm, chan->channel);
+	stm32_dfsdm_stop_channel(adc);
 }
 
 static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
@@ -494,6 +662,7 @@ static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 	unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2;
+	unsigned int rx_buf_sz = DFSDM_DMA_BUFFER_SIZE;
 
 	/*
 	 * DMA cyclic transfers are used, buffer is split into two periods.
@@ -502,7 +671,7 @@ static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev,
 	 * - one buffer (period) driver pushed to ASoC side.
 	 */
 	watermark = min(watermark, val * (unsigned int)(sizeof(u32)));
-	adc->buf_sz = watermark * 2;
+	adc->buf_sz = min(rx_buf_sz, watermark * 2 * adc->nconv);
 
 	return 0;
 }
@@ -532,13 +701,41 @@ static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc)
 	return 0;
 }
 
-static void stm32_dfsdm_audio_dma_buffer_done(void *data)
+static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	int available = stm32_dfsdm_adc_dma_residue(adc);
+
+	while (available >= indio_dev->scan_bytes) {
+		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
+
+		iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+						   pf->timestamp);
+		available -= indio_dev->scan_bytes;
+		adc->bufi += indio_dev->scan_bytes;
+		if (adc->bufi >= adc->buf_sz)
+			adc->bufi = 0;
+	}
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static void stm32_dfsdm_dma_buffer_done(void *data)
 {
 	struct iio_dev *indio_dev = data;
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 	int available = stm32_dfsdm_adc_dma_residue(adc);
 	size_t old_pos;
 
+	if (indio_dev->currentmode & INDIO_BUFFER_TRIGGERED) {
+		iio_trigger_poll_chained(indio_dev->trig);
+		return;
+	}
+
 	/*
 	 * FIXME: In Kernel interface does not support cyclic DMA buffer,and
 	 * offers only an interface to push data samples per samples.
@@ -566,6 +763,9 @@ static void stm32_dfsdm_audio_dma_buffer_done(void *data)
 			adc->bufi = 0;
 			old_pos = 0;
 		}
+		/* regular iio buffer without trigger */
+		if (adc->dev_data->type == DFSDM_IIO)
+			iio_push_to_buffers(indio_dev, buffer);
 	}
 	if (adc->cb)
 		adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos,
@@ -575,6 +775,10 @@ static void stm32_dfsdm_audio_dma_buffer_done(void *data)
 static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct dma_slave_config config = {
+		.src_addr = (dma_addr_t)adc->dfsdm->phys_base,
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+	};
 	struct dma_async_tx_descriptor *desc;
 	dma_cookie_t cookie;
 	int ret;
@@ -585,6 +789,14 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
 	dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
 		adc->buf_sz, adc->buf_sz / 2);
 
+	if (adc->nconv == 1 && !indio_dev->trig)
+		config.src_addr += DFSDM_RDATAR(adc->fl_id);
+	else
+		config.src_addr += DFSDM_JDATAR(adc->fl_id);
+	ret = dmaengine_slave_config(adc->dma_chan, &config);
+	if (ret)
+		return ret;
+
 	/* Prepare a DMA cyclic transaction */
 	desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
 					 adc->dma_buf,
@@ -594,71 +806,154 @@ static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
 	if (!desc)
 		return -EBUSY;
 
-	desc->callback = stm32_dfsdm_audio_dma_buffer_done;
+	desc->callback = stm32_dfsdm_dma_buffer_done;
 	desc->callback_param = indio_dev;
 
 	cookie = dmaengine_submit(desc);
 	ret = dma_submit_error(cookie);
-	if (ret) {
-		dmaengine_terminate_all(adc->dma_chan);
-		return ret;
-	}
+	if (ret)
+		goto err_stop_dma;
 
 	/* Issue pending DMA requests */
 	dma_async_issue_pending(adc->dma_chan);
 
+	if (adc->nconv == 1 && !indio_dev->trig) {
+		/* Enable regular DMA transfer*/
+		ret = regmap_update_bits(adc->dfsdm->regmap,
+					 DFSDM_CR1(adc->fl_id),
+					 DFSDM_CR1_RDMAEN_MASK,
+					 DFSDM_CR1_RDMAEN_MASK);
+	} else {
+		/* Enable injected DMA transfer*/
+		ret = regmap_update_bits(adc->dfsdm->regmap,
+					 DFSDM_CR1(adc->fl_id),
+					 DFSDM_CR1_JDMAEN_MASK,
+					 DFSDM_CR1_JDMAEN_MASK);
+	}
+
+	if (ret < 0)
+		goto err_stop_dma;
+
 	return 0;
+
+err_stop_dma:
+	dmaengine_terminate_all(adc->dma_chan);
+
+	return ret;
 }
 
-static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
+static void stm32_dfsdm_adc_dma_stop(struct iio_dev *indio_dev)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+
+	if (!adc->dma_chan)
+		return;
+
+	regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR1(adc->fl_id),
+			   DFSDM_CR1_RDMAEN_MASK | DFSDM_CR1_JDMAEN_MASK, 0);
+	dmaengine_terminate_all(adc->dma_chan);
+}
+
+static int stm32_dfsdm_update_scan_mode(struct iio_dev *indio_dev,
+					const unsigned long *scan_mask)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+
+	adc->nconv = bitmap_weight(scan_mask, indio_dev->masklength);
+	adc->smask = *scan_mask;
+
+	dev_dbg(&indio_dev->dev, "nconv=%d mask=%lx\n", adc->nconv, *scan_mask);
+
+	return 0;
+}
+
+static int __stm32_dfsdm_postenable(struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	const struct iio_chan_spec *chan = &indio_dev->channels[0];
 	int ret;
 
 	/* Reset adc buffer index */
 	adc->bufi = 0;
 
+	if (adc->hwc) {
+		ret = iio_hw_consumer_enable(adc->hwc);
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = stm32_dfsdm_start_dfsdm(adc->dfsdm);
 	if (ret < 0)
-		return ret;
+		goto err_stop_hwc;
 
-	ret = stm32_dfsdm_start_conv(adc, chan, true);
+	ret = stm32_dfsdm_adc_dma_start(indio_dev);
 	if (ret) {
-		dev_err(&indio_dev->dev, "Can't start conversion\n");
+		dev_err(&indio_dev->dev, "Can't start DMA\n");
 		goto stop_dfsdm;
 	}
 
-	if (adc->dma_chan) {
-		ret = stm32_dfsdm_adc_dma_start(indio_dev);
-		if (ret) {
-			dev_err(&indio_dev->dev, "Can't start DMA\n");
-			goto err_stop_conv;
-		}
+	ret = stm32_dfsdm_start_conv(adc, indio_dev->trig);
+	if (ret) {
+		dev_err(&indio_dev->dev, "Can't start conversion\n");
+		goto err_stop_dma;
 	}
 
 	return 0;
 
-err_stop_conv:
-	stm32_dfsdm_stop_conv(adc, chan);
+err_stop_dma:
+	stm32_dfsdm_adc_dma_stop(indio_dev);
 stop_dfsdm:
 	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
+err_stop_hwc:
+	if (adc->hwc)
+		iio_hw_consumer_disable(adc->hwc);
 
 	return ret;
 }
 
-static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
+static int stm32_dfsdm_postenable(struct iio_dev *indio_dev)
+{
+	int ret;
+
+	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
+		ret = iio_triggered_buffer_postenable(indio_dev);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = __stm32_dfsdm_postenable(indio_dev);
+	if (ret < 0)
+		goto err_predisable;
+
+	return 0;
+
+err_predisable:
+	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
+		iio_triggered_buffer_predisable(indio_dev);
+
+	return ret;
+}
+
+static void __stm32_dfsdm_predisable(struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	const struct iio_chan_spec *chan = &indio_dev->channels[0];
 
-	if (adc->dma_chan)
-		dmaengine_terminate_all(adc->dma_chan);
+	stm32_dfsdm_stop_conv(adc);
 
-	stm32_dfsdm_stop_conv(adc, chan);
+	stm32_dfsdm_adc_dma_stop(indio_dev);
 
 	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
 
+	if (adc->hwc)
+		iio_hw_consumer_disable(adc->hwc);
+}
+
+static int stm32_dfsdm_predisable(struct iio_dev *indio_dev)
+{
+	__stm32_dfsdm_predisable(indio_dev);
+
+	if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
+		iio_triggered_buffer_predisable(indio_dev);
+
 	return 0;
 }
 
@@ -736,7 +1031,9 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
 	if (ret < 0)
 		goto stop_dfsdm;
 
-	ret = stm32_dfsdm_start_conv(adc, chan, false);
+	adc->nconv = 1;
+	adc->smask = BIT(chan->scan_index);
+	ret = stm32_dfsdm_start_conv(adc, NULL);
 	if (ret < 0) {
 		regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id),
 				   DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0));
@@ -757,7 +1054,7 @@ static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev,
 	else
 		ret = IIO_VAL_INT;
 
-	stm32_dfsdm_stop_conv(adc, chan);
+	stm32_dfsdm_stop_conv(adc);
 
 stop_dfsdm:
 	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
@@ -777,16 +1074,23 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 		ret = stm32_dfsdm_set_osrs(fl, 0, val);
 		if (!ret)
 			adc->oversamp = val;
-
+		iio_device_release_direct_mode(indio_dev);
 		return ret;
 
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		if (!val)
 			return -EINVAL;
 
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
+
 		switch (ch->src) {
 		case DFSDM_CHANNEL_SPI_CLOCK_INTERNAL:
 			spi_freq = adc->dfsdm->spi_master_freq;
@@ -799,20 +1103,9 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 			spi_freq = adc->spi_freq;
 		}
 
-		if (spi_freq % val)
-			dev_warn(&indio_dev->dev,
-				 "Sampling rate not accurate (%d)\n",
-				 spi_freq / (spi_freq / val));
-
-		ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / val));
-		if (ret < 0) {
-			dev_err(&indio_dev->dev,
-				"Not able to find parameter that match!\n");
-			return ret;
-		}
-		adc->sample_freq = val;
-
-		return 0;
+		ret = dfsdm_adc_set_samp_freq(indio_dev, val, spi_freq);
+		iio_device_release_direct_mode(indio_dev);
+		return ret;
 	}
 
 	return -EINVAL;
@@ -827,11 +1120,15 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 		ret = iio_hw_consumer_enable(adc->hwc);
 		if (ret < 0) {
 			dev_err(&indio_dev->dev,
 				"%s: IIO enable failed (channel %d)\n",
 				__func__, chan->channel);
+			iio_device_release_direct_mode(indio_dev);
 			return ret;
 		}
 		ret = stm32_dfsdm_single_conv(indio_dev, chan, val);
@@ -840,8 +1137,10 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
 			dev_err(&indio_dev->dev,
 				"%s: Conversion failed (channel %d)\n",
 				__func__, chan->channel);
+			iio_device_release_direct_mode(indio_dev);
 			return ret;
 		}
+		iio_device_release_direct_mode(indio_dev);
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -858,15 +1157,25 @@ static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev,
 	return -EINVAL;
 }
 
+static int stm32_dfsdm_validate_trigger(struct iio_dev *indio_dev,
+					struct iio_trigger *trig)
+{
+	return stm32_dfsdm_get_jextsel(indio_dev, trig) < 0 ? -EINVAL : 0;
+}
+
 static const struct iio_info stm32_dfsdm_info_audio = {
 	.hwfifo_set_watermark = stm32_dfsdm_set_watermark,
 	.read_raw = stm32_dfsdm_read_raw,
 	.write_raw = stm32_dfsdm_write_raw,
+	.update_scan_mode = stm32_dfsdm_update_scan_mode,
 };
 
 static const struct iio_info stm32_dfsdm_info_adc = {
+	.hwfifo_set_watermark = stm32_dfsdm_set_watermark,
 	.read_raw = stm32_dfsdm_read_raw,
 	.write_raw = stm32_dfsdm_write_raw,
+	.update_scan_mode = stm32_dfsdm_update_scan_mode,
+	.validate_trigger = stm32_dfsdm_validate_trigger,
 };
 
 static irqreturn_t stm32_dfsdm_irq(int irq, void *arg)
@@ -926,12 +1235,6 @@ static void stm32_dfsdm_dma_release(struct iio_dev *indio_dev)
 static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	struct dma_slave_config config = {
-		.src_addr = (dma_addr_t)adc->dfsdm->phys_base +
-			DFSDM_RDATAR(adc->fl_id),
-		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-	};
-	int ret;
 
 	adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
 	if (!adc->dma_chan)
@@ -941,23 +1244,14 @@ static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev)
 					 DFSDM_DMA_BUFFER_SIZE,
 					 &adc->dma_buf, GFP_KERNEL);
 	if (!adc->rx_buf) {
-		ret = -ENOMEM;
-		goto err_release;
+		dma_release_channel(adc->dma_chan);
+		return -ENOMEM;
 	}
 
-	ret = dmaengine_slave_config(adc->dma_chan, &config);
-	if (ret)
-		goto err_free;
+	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
+	indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops;
 
 	return 0;
-
-err_free:
-	dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE,
-			  adc->rx_buf, adc->dma_buf);
-err_release:
-	dma_release_channel(adc->dma_chan);
-
-	return ret;
 }
 
 static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
@@ -978,7 +1272,8 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
 	 * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling
 	 */
 	ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
-	ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO);
+	ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+					BIT(IIO_CHAN_INFO_SAMP_FREQ);
 
 	if (adc->dev_data->type == DFSDM_AUDIO) {
 		ch->scan_type.sign = 's';
@@ -1000,9 +1295,6 @@ static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev)
 	struct stm32_dfsdm_channel *d_ch;
 	int ret;
 
-	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
-	indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops;
-
 	ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL);
 	if (!ch)
 		return -ENOMEM;
@@ -1070,6 +1362,25 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
 
 	init_completion(&adc->completion);
 
+	/* Optionally request DMA */
+	if (stm32_dfsdm_dma_request(indio_dev)) {
+	    dev_dbg(&indio_dev->dev, "No DMA support\n");
+	    return 0;
+	}
+
+	ret = iio_triggered_buffer_setup(indio_dev,
+					 &iio_pollfunc_store_time,
+					 &stm32_dfsdm_adc_trigger_handler,
+					 &stm32_dfsdm_buffer_setup_ops);
+	if (ret) {
+		stm32_dfsdm_dma_release(indio_dev);
+		dev_err(&indio_dev->dev, "buffer setup failed\n");
+		return ret;
+	}
+
+	/* lptimer/timer hardware triggers */
+	indio_dev->modes |= INDIO_HARDWARE_TRIGGERED;
+
 	return 0;
 }
 
@@ -1117,7 +1428,7 @@ static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
 
 	iio->dev.parent = dev;
 	iio->dev.of_node = np;
-	iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+	iio->modes = INDIO_DIRECT_MODE;
 
 	platform_set_drvdata(pdev, adc);
 
@@ -1203,10 +1514,48 @@ static int stm32_dfsdm_adc_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int stm32_dfsdm_adc_suspend(struct device *dev)
+{
+	struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+	if (iio_buffer_enabled(indio_dev))
+		__stm32_dfsdm_predisable(indio_dev);
+
+	return 0;
+}
+static int stm32_dfsdm_adc_resume(struct device *dev)
+{
+	struct stm32_dfsdm_adc *adc = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	const struct iio_chan_spec *chan;
+	struct stm32_dfsdm_channel *ch;
+	int i, ret;
+
+	/* restore channels configuration */
+	for (i = 0; i < indio_dev->num_channels; i++) {
+		chan = indio_dev->channels + i;
+		ch = &adc->dfsdm->ch_list[chan->channel];
+		ret = stm32_dfsdm_chan_configure(adc->dfsdm, ch);
+		if (ret)
+			return ret;
+	}
+
+	if (iio_buffer_enabled(indio_dev))
+		__stm32_dfsdm_postenable(indio_dev);
+
+	return 0;
+}
+#endif
+static SIMPLE_DEV_PM_OPS(stm32_dfsdm_adc_pm_ops,
+			 stm32_dfsdm_adc_suspend, stm32_dfsdm_adc_resume);
+
 static struct platform_driver stm32_dfsdm_adc_driver = {
 	.driver = {
 		.name = "stm32-dfsdm-adc",
 		.of_match_table = stm32_dfsdm_adc_match,
+		.pm = &stm32_dfsdm_adc_pm_ops,
 	},
 	.probe = stm32_dfsdm_adc_probe,
 	.remove = stm32_dfsdm_adc_remove,
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index bf089f5..2d2c640 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -12,6 +12,8 @@
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 
@@ -90,6 +92,36 @@ struct dfsdm_priv {
 	struct clk *aclk; /* audio clock */
 };
 
+static inline struct dfsdm_priv *to_stm32_dfsdm_priv(struct stm32_dfsdm *dfsdm)
+{
+	return container_of(dfsdm, struct dfsdm_priv, dfsdm);
+}
+
+static int stm32_dfsdm_clk_prepare_enable(struct stm32_dfsdm *dfsdm)
+{
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
+	int ret;
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret || !priv->aclk)
+		return ret;
+
+	ret = clk_prepare_enable(priv->aclk);
+	if (ret)
+		clk_disable_unprepare(priv->clk);
+
+	return ret;
+}
+
+static void stm32_dfsdm_clk_disable_unprepare(struct stm32_dfsdm *dfsdm)
+{
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
+
+	if (priv->aclk)
+		clk_disable_unprepare(priv->aclk);
+	clk_disable_unprepare(priv->clk);
+}
+
 /**
  * stm32_dfsdm_start_dfsdm - start global dfsdm interface.
  *
@@ -98,24 +130,17 @@ struct dfsdm_priv {
  */
 int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
 {
-	struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
 	struct device *dev = &priv->pdev->dev;
 	unsigned int clk_div = priv->spi_clk_out_div, clk_src;
 	int ret;
 
 	if (atomic_inc_return(&priv->n_active_ch) == 1) {
-		ret = clk_prepare_enable(priv->clk);
+		ret = pm_runtime_get_sync(dev);
 		if (ret < 0) {
-			dev_err(dev, "Failed to start clock\n");
+			pm_runtime_put_noidle(dev);
 			goto error_ret;
 		}
-		if (priv->aclk) {
-			ret = clk_prepare_enable(priv->aclk);
-			if (ret < 0) {
-				dev_err(dev, "Failed to start audio clock\n");
-				goto disable_clk;
-			}
-		}
 
 		/* select clock source, e.g. 0 for "dfsdm" or 1 for "audio" */
 		clk_src = priv->aclk ? 1 : 0;
@@ -123,21 +148,21 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
 					 DFSDM_CHCFGR1_CKOUTSRC_MASK,
 					 DFSDM_CHCFGR1_CKOUTSRC(clk_src));
 		if (ret < 0)
-			goto disable_aclk;
+			goto pm_put;
 
 		/* Output the SPI CLKOUT (if clk_div == 0 clock if OFF) */
 		ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
 					 DFSDM_CHCFGR1_CKOUTDIV_MASK,
 					 DFSDM_CHCFGR1_CKOUTDIV(clk_div));
 		if (ret < 0)
-			goto disable_aclk;
+			goto pm_put;
 
 		/* Global enable of DFSDM interface */
 		ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0),
 					 DFSDM_CHCFGR1_DFSDMEN_MASK,
 					 DFSDM_CHCFGR1_DFSDMEN(1));
 		if (ret < 0)
-			goto disable_aclk;
+			goto pm_put;
 	}
 
 	dev_dbg(dev, "%s: n_active_ch %d\n", __func__,
@@ -145,11 +170,8 @@ int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm)
 
 	return 0;
 
-disable_aclk:
-	clk_disable_unprepare(priv->aclk);
-disable_clk:
-	clk_disable_unprepare(priv->clk);
-
+pm_put:
+	pm_runtime_put_sync(dev);
 error_ret:
 	atomic_dec(&priv->n_active_ch);
 
@@ -165,7 +187,7 @@ EXPORT_SYMBOL_GPL(stm32_dfsdm_start_dfsdm);
  */
 int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm)
 {
-	struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm);
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
 	int ret;
 
 	if (atomic_dec_and_test(&priv->n_active_ch)) {
@@ -183,9 +205,7 @@ int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm)
 		if (ret < 0)
 			return ret;
 
-		clk_disable_unprepare(priv->clk);
-		if (priv->aclk)
-			clk_disable_unprepare(priv->aclk);
+		pm_runtime_put_sync(&priv->pdev->dev);
 	}
 	dev_dbg(&priv->pdev->dev, "%s: n_active_ch %d\n", __func__,
 		atomic_read(&priv->n_active_ch));
@@ -243,13 +263,18 @@ static int stm32_dfsdm_parse_of(struct platform_device *pdev,
 		return 0;
 	}
 
-	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1;
+	priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem);
+
+	/* round up divider when clkout isn't accurate (e.g. !rem) */
+	if (priv->spi_clk_out_div && !rem)
+		priv->spi_clk_out_div--;
+
 	if (!priv->spi_clk_out_div) {
 		/* spi_clk_out_div == 0 means ckout is OFF */
 		dev_err(&pdev->dev, "spi-max-frequency not achievable\n");
 		return -EINVAL;
 	}
-	priv->dfsdm.spi_master_freq = spi_freq;
+	priv->dfsdm.spi_master_freq = clk_freq / (priv->spi_clk_out_div + 1);
 
 	if (rem) {
 		dev_warn(&pdev->dev, "SPI clock not accurate\n");
@@ -318,14 +343,115 @@ static int stm32_dfsdm_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, dfsdm);
 
-	return devm_of_platform_populate(&pdev->dev);
+	ret = stm32_dfsdm_clk_prepare_enable(dfsdm);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to start clock\n");
+		return ret;
+	}
+
+	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);
+	stm32_dfsdm_clk_disable_unprepare(dfsdm);
+
+	return ret;
 }
 
+static int stm32_dfsdm_core_remove(struct platform_device *pdev)
+{
+	struct stm32_dfsdm *dfsdm = platform_get_drvdata(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);
+	stm32_dfsdm_clk_disable_unprepare(dfsdm);
+
+	return 0;
+}
+
+#if defined CONFIG_PM_SLEEP
+static int stm32_dfsdm_core_suspend(struct device *dev)
+{
+	struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
+	int ret;
+
+	ret = pm_runtime_force_suspend(dev);
+	if (ret)
+		return ret;
+
+	/* Balance devm_regmap_init_mmio_clk() clk_prepare() */
+	clk_unprepare(priv->clk);
+
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int stm32_dfsdm_core_resume(struct device *dev)
+{
+	struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
+	struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
+	int ret;
+
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare(priv->clk);
+	if (ret)
+		return ret;
+
+	return pm_runtime_force_resume(dev);
+}
+#endif
+
+#ifdef CONFIG_PM
+static int stm32_dfsdm_core_runtime_suspend(struct device *dev)
+{
+	struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
+
+	stm32_dfsdm_clk_disable_unprepare(dfsdm);
+
+	return 0;
+}
+
+static int stm32_dfsdm_core_runtime_resume(struct device *dev)
+{
+	struct stm32_dfsdm *dfsdm = dev_get_drvdata(dev);
+
+	return stm32_dfsdm_clk_prepare_enable(dfsdm);
+}
+#endif
+
+static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(stm32_dfsdm_core_suspend,
+				stm32_dfsdm_core_resume)
+	SET_RUNTIME_PM_OPS(stm32_dfsdm_core_runtime_suspend,
+			   stm32_dfsdm_core_runtime_resume,
+			   NULL)
+};
+
 static struct platform_driver stm32_dfsdm_driver = {
 	.probe = stm32_dfsdm_probe,
+	.remove = stm32_dfsdm_core_remove,
 	.driver = {
 		.name = "stm32-dfsdm",
 		.of_match_table = stm32_dfsdm_of_match,
+		.pm = &stm32_dfsdm_core_pm_ops,
 	},
 };
 
diff --git a/drivers/iio/counter/stm32-lptimer-cnt.c b/drivers/iio/counter/stm32-lptimer-cnt.c
index 42fb8ba..2a49cce 100644
--- a/drivers/iio/counter/stm32-lptimer-cnt.c
+++ b/drivers/iio/counter/stm32-lptimer-cnt.c
@@ -14,6 +14,7 @@
 #include <linux/iio/iio.h>
 #include <linux/mfd/stm32-lptimer.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 
 struct stm32_lptim_cnt {
@@ -23,6 +24,7 @@ struct stm32_lptim_cnt {
 	u32 preset;
 	u32 polarity;
 	u32 quadrature_mode;
+	bool enabled;
 };
 
 static int stm32_lptim_is_enabled(struct stm32_lptim_cnt *priv)
@@ -50,6 +52,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv,
 
 	if (!enable) {
 		clk_disable(priv->clk);
+		priv->enabled = false;
 		return 0;
 	}
 
@@ -79,6 +82,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv,
 		regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
 		return ret;
 	}
+	priv->enabled = true;
 
 	/* Start LP timer in continuous mode */
 	return regmap_update_bits(priv->regmap, STM32_LPTIM_CR,
@@ -361,6 +365,56 @@ static int stm32_lptim_cnt_probe(struct platform_device *pdev)
 	return devm_iio_device_register(&pdev->dev, indio_dev);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int stm32_lptim_cnt_suspend(struct device *dev)
+{
+	struct stm32_lptim_cnt *priv = dev_get_drvdata(dev);
+	int ret;
+
+	/* Only take care of enabled counter: don't disturb other MFD child */
+	if (priv->enabled) {
+		ret = stm32_lptim_setup(priv, 0);
+		if (ret)
+			return ret;
+
+		ret = stm32_lptim_set_enable_state(priv, 0);
+		if (ret)
+			return ret;
+
+		/* Force enable state for later resume */
+		priv->enabled = true;
+	}
+
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int stm32_lptim_cnt_resume(struct device *dev)
+{
+	struct stm32_lptim_cnt *priv = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret)
+		return ret;
+
+	if (priv->enabled) {
+		priv->enabled = false;
+		ret = stm32_lptim_setup(priv, 1);
+		if (ret)
+			return ret;
+
+		ret = stm32_lptim_set_enable_state(priv, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stm32_lptim_cnt_pm_ops, stm32_lptim_cnt_suspend,
+			 stm32_lptim_cnt_resume);
+
 static const struct of_device_id stm32_lptim_cnt_of_match[] = {
 	{ .compatible = "st,stm32-lptimer-counter", },
 	{},
@@ -372,6 +426,7 @@ static struct platform_driver stm32_lptim_cnt_driver = {
 	.driver = {
 		.name = "stm32-lptimer-counter",
 		.of_match_table = stm32_lptim_cnt_of_match,
+		.pm = &stm32_lptim_cnt_pm_ops,
 	},
 };
 module_platform_driver(stm32_lptim_cnt_driver);
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index ccf1ce6..4a4ce3c 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -12,6 +12,7 @@
 #include <linux/iio/trigger.h>
 #include <linux/mfd/stm32-timers.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
 
@@ -79,10 +80,20 @@ struct stm32_timer_trigger {
 	struct device *dev;
 	struct regmap *regmap;
 	struct clk *clk;
+	bool clk_enabled;
 	u32 max_arr;
 	const void *triggers;
 	const void *valids;
 	bool has_trgo2;
+	struct mutex lock; /* concurrent sysfs configuration */
+	unsigned int freq;
+	bool counter_en;
+	u32 cr1;
+	u32 cr2;
+	u32 psc;
+	u32 arr;
+	u32 cnt;
+	u32 smcr;
 };
 
 struct stm32_timer_trigger_cfg {
@@ -106,7 +117,7 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
 {
 	unsigned long long prd, div;
 	int prescaler = 0;
-	u32 ccer, cr1;
+	u32 ccer;
 
 	/* Period and prescaler values depends of clock rate */
 	div = (unsigned long long)clk_get_rate(priv->clk);
@@ -136,9 +147,11 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
 	if (ccer & TIM_CCER_CCXE)
 		return -EBUSY;
 
-	regmap_read(priv->regmap, TIM_CR1, &cr1);
-	if (!(cr1 & TIM_CR1_CEN))
+	mutex_lock(&priv->lock);
+	if (!priv->clk_enabled) {
+		priv->clk_enabled = true;
 		clk_enable(priv->clk);
+	}
 
 	regmap_write(priv->regmap, TIM_PSC, prescaler);
 	regmap_write(priv->regmap, TIM_ARR, prd - 1);
@@ -157,30 +170,41 @@ static int stm32_timer_start(struct stm32_timer_trigger *priv,
 
 	/* Enable controller */
 	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
+	mutex_unlock(&priv->lock);
 
 	return 0;
 }
 
-static void stm32_timer_stop(struct stm32_timer_trigger *priv)
+static void stm32_timer_stop(struct stm32_timer_trigger *priv,
+			     struct iio_trigger *trig)
 {
-	u32 ccer, cr1;
+	u32 ccer;
 
 	regmap_read(priv->regmap, TIM_CCER, &ccer);
 	if (ccer & TIM_CCER_CCXE)
 		return;
 
-	regmap_read(priv->regmap, TIM_CR1, &cr1);
-	if (cr1 & TIM_CR1_CEN)
-		clk_disable(priv->clk);
-
+	mutex_lock(&priv->lock);
 	/* Stop timer */
 	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
 	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
 	regmap_write(priv->regmap, TIM_PSC, 0);
 	regmap_write(priv->regmap, TIM_ARR, 0);
 
+	/* Force disable master mode */
+	if (stm32_timer_is_trgo2_name(trig->name))
+		regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0);
+	else
+		regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0);
+
 	/* Make sure that registers are updated */
 	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
+
+	if (priv->clk_enabled) {
+		priv->clk_enabled = false;
+		clk_disable(priv->clk);
+	}
+	mutex_unlock(&priv->lock);
 }
 
 static ssize_t stm32_tt_store_frequency(struct device *dev,
@@ -197,12 +221,13 @@ static ssize_t stm32_tt_store_frequency(struct device *dev,
 		return ret;
 
 	if (freq == 0) {
-		stm32_timer_stop(priv);
+		stm32_timer_stop(priv, trig);
 	} else {
 		ret = stm32_timer_start(priv, trig, freq);
 		if (ret)
 			return ret;
 	}
+	priv->freq = freq;
 
 	return len;
 }
@@ -295,11 +320,15 @@ static ssize_t stm32_tt_store_master_mode(struct device *dev,
 	for (i = 0; i <= master_mode_max; i++) {
 		if (!strncmp(master_mode_table[i], buf,
 			     strlen(master_mode_table[i]))) {
+			mutex_lock(&priv->lock);
+			if (!priv->clk_enabled) {
+				/* Clock should be enabled first */
+				priv->clk_enabled = true;
+				clk_enable(priv->clk);
+			}
 			regmap_update_bits(priv->regmap, TIM_CR2, mask,
 					   i << shift);
-			/* Make sure that registers are updated */
-			regmap_update_bits(priv->regmap, TIM_EGR,
-					   TIM_EGR_UG, TIM_EGR_UG);
+			mutex_unlock(&priv->lock);
 			return len;
 		}
 	}
@@ -437,7 +466,6 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
 				   int val, int val2, long mask)
 {
 	struct stm32_timer_trigger *priv = iio_priv(indio_dev);
-	u32 dat;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
@@ -448,19 +476,24 @@ static int stm32_counter_write_raw(struct iio_dev *indio_dev,
 		return -EINVAL;
 
 	case IIO_CHAN_INFO_ENABLE:
+		mutex_lock(&priv->lock);
 		if (val) {
-			regmap_read(priv->regmap, TIM_CR1, &dat);
-			if (!(dat & TIM_CR1_CEN))
+			if (!priv->clk_enabled) {
+				priv->clk_enabled = true;
 				clk_enable(priv->clk);
+			}
 			regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
 					   TIM_CR1_CEN);
 		} else {
-			regmap_read(priv->regmap, TIM_CR1, &dat);
 			regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
 					   0);
-			if (dat & TIM_CR1_CEN)
+			if (priv->clk_enabled) {
+				priv->clk_enabled = false;
 				clk_disable(priv->clk);
+			}
 		}
+		priv->counter_en = !!val;
+		mutex_unlock(&priv->lock);
 		return 0;
 	}
 
@@ -556,7 +589,6 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev,
 {
 	struct stm32_timer_trigger *priv = iio_priv(indio_dev);
 	int sms = stm32_enable_mode2sms(mode);
-	u32 val;
 
 	if (sms < 0)
 		return sms;
@@ -564,11 +596,12 @@ static int stm32_set_enable_mode(struct iio_dev *indio_dev,
 	 * Triggered mode sets CEN bit automatically by hardware. So, first
 	 * enable counter clock, so it can use it. Keeps it in sync with CEN.
 	 */
-	if (sms == 6) {
-		regmap_read(priv->regmap, TIM_CR1, &val);
-		if (!(val & TIM_CR1_CEN))
-			clk_enable(priv->clk);
+	mutex_lock(&priv->lock);
+	if (sms == 6 && !priv->clk_enabled) {
+		clk_enable(priv->clk);
+		priv->clk_enabled = true;
 	}
+	mutex_unlock(&priv->lock);
 
 	regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
 
@@ -836,6 +869,7 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev)
 	priv->triggers = triggers_table[index];
 	priv->valids = cfg->valids_table[index];
 	stm32_timer_detect_trgo2(priv);
+	mutex_init(&priv->lock);
 
 	ret = stm32_setup_iio_triggers(priv);
 	if (ret)
@@ -846,6 +880,91 @@ static int stm32_timer_trigger_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static int stm32_timer_trigger_remove(struct platform_device *pdev)
+{
+	struct stm32_timer_trigger *priv = platform_get_drvdata(pdev);
+	u32 val;
+
+	/* Check if nobody else use the timer, then disable it */
+	regmap_read(priv->regmap, TIM_CCER, &val);
+	if (!(val & TIM_CCER_CCXE))
+		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
+
+	if (priv->clk_enabled)
+		clk_disable(priv->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int stm32_tt_suspend(struct device *dev)
+{
+	struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
+
+	/* Disable the timer */
+	if (priv->freq)
+		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
+	/* Register contents may be lost depending on low power mode. */
+	regmap_read(priv->regmap, TIM_CR1, &priv->cr1);
+	regmap_read(priv->regmap, TIM_CR2, &priv->cr2);
+	regmap_read(priv->regmap, TIM_PSC, &priv->psc);
+	regmap_read(priv->regmap, TIM_ARR, &priv->arr);
+	regmap_read(priv->regmap, TIM_CNT, &priv->cnt);
+	regmap_read(priv->regmap, TIM_SMCR, &priv->smcr);
+
+	if (priv->clk_enabled)
+		clk_disable(priv->clk);
+
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int stm32_tt_resume(struct device *dev)
+{
+	struct stm32_timer_trigger *priv = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pinctrl_pm_select_default_state(dev);
+	if (ret)
+		return ret;
+
+	if (priv->clk_enabled) {
+		ret = clk_enable(priv->clk);
+		if (ret)
+			return ret;
+	}
+
+	/* restore master/slave modes */
+	regmap_write(priv->regmap, TIM_SMCR, priv->smcr);
+	regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS | TIM_CR2_MMS2,
+			   priv->cr2);
+
+	if (priv->freq) {
+		/* restore sampling_frequency (trgo / trgo2 triggers) */
+		regmap_write(priv->regmap, TIM_PSC, priv->psc);
+		regmap_write(priv->regmap, TIM_ARR, priv->arr);
+		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE,
+				   TIM_CR1_ARPE);
+		regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG,
+				   TIM_EGR_UG);
+	}
+
+	if (priv->counter_en) {
+		/* restore counter value, count_direction */
+		regmap_write(priv->regmap, TIM_CNT, priv->cnt);
+		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_DIR,
+				   priv->cr1);
+	}
+
+	if (priv->freq || priv->counter_en)
+		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
+				   TIM_CR1_CEN);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(stm32_tt_pm_ops, stm32_tt_suspend, stm32_tt_resume);
+
 static const struct stm32_timer_trigger_cfg stm32_timer_trg_cfg = {
 	.valids_table = valids_table,
 	.num_valids_table = ARRAY_SIZE(valids_table),
@@ -870,9 +989,11 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
 
 static struct platform_driver stm32_timer_trigger_driver = {
 	.probe = stm32_timer_trigger_probe,
+	.remove = stm32_timer_trigger_remove,
 	.driver = {
 		.name = "stm32-timer-trigger",
 		.of_match_table = stm32_trig_of_match,
+		.pm = &stm32_tt_pm_ops,
 	},
 };
 module_platform_driver(stm32_timer_trigger_driver);
-- 
2.7.4

