This patch adds support for STMicroelectronics STM32 MCU's analog to
digital converter.

Signed-off-by: Fabrice Gasnier <fabrice.gasn...@st.com>
---
 drivers/iio/adc/Kconfig             |   2 +
 drivers/iio/adc/Makefile            |   1 +
 drivers/iio/adc/stm32/Kconfig       |  34 ++
 drivers/iio/adc/stm32/Makefile      |   4 +
 drivers/iio/adc/stm32/stm32-adc.c   | 999 ++++++++++++++++++++++++++++++++++++
 drivers/iio/adc/stm32/stm32-adc.h   | 442 ++++++++++++++++
 drivers/iio/adc/stm32/stm32f4-adc.c | 574 +++++++++++++++++++++
 7 files changed, 2056 insertions(+)
 create mode 100644 drivers/iio/adc/stm32/Kconfig
 create mode 100644 drivers/iio/adc/stm32/Makefile
 create mode 100644 drivers/iio/adc/stm32/stm32-adc.c
 create mode 100644 drivers/iio/adc/stm32/stm32-adc.h
 create mode 100644 drivers/iio/adc/stm32/stm32f4-adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7edcf32..5c96a55 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -583,4 +583,6 @@ config XILINX_XADC
          The driver can also be build as a module. If so, the module will be 
called
          xilinx-xadc.
 
+source "drivers/iio/adc/stm32/Kconfig"
+
 endmenu
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 7a40c04..a9dbf3a 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AD799X) += ad799x.o
+obj-$(CONFIG_ARCH_STM32) += stm32/
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o
 obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
diff --git a/drivers/iio/adc/stm32/Kconfig b/drivers/iio/adc/stm32/Kconfig
new file mode 100644
index 0000000..245d037
--- /dev/null
+++ b/drivers/iio/adc/stm32/Kconfig
@@ -0,0 +1,34 @@
+#
+# STM32 familly ADC drivers
+#
+
+config STM32_ADC
+       tristate
+       select REGULATOR
+       select REGULATOR_FIXED_VOLTAGE
+       select IIO_BUFFER
+       select IIO_TRIGGERED_BUFFER
+       help
+         Say yes here to build the driver for the STMicroelectronics
+         STM32 analog-to-digital converter (ADC).
+
+         This driver can also be built as a module.  If so, the module
+         will be called stm32-adc.
+
+config STM32F4_ADC
+       tristate "STMicroelectronics STM32F4 adc"
+       depends on ARCH_STM32 || COMPILE_TEST
+       depends on OF
+       select STM32_ADC
+       help
+         Say yes here to build support for STMicroelectronics stm32f4 Analog
+         to Digital Converter (ADC).
+
+         This driver can also be built as a module.  If so, the module
+         will be called stm32f4-adc.
+
+config STM32_ADC_DEBUG
+       bool "Enable debug for stm32 ADC drivers"
+       depends on STM32_ADC
+       help
+         Say "yes" to enable debug messages, on stm32 ADC drivers.
diff --git a/drivers/iio/adc/stm32/Makefile b/drivers/iio/adc/stm32/Makefile
new file mode 100644
index 0000000..83e8154
--- /dev/null
+++ b/drivers/iio/adc/stm32/Makefile
@@ -0,0 +1,4 @@
+# Core
+subdir-ccflags-$(CONFIG_STM32_ADC_DEBUG) := -DDEBUG
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o
+obj-$(CONFIG_STM32F4_ADC) += stm32f4-adc.o
diff --git a/drivers/iio/adc/stm32/stm32-adc.c 
b/drivers/iio/adc/stm32/stm32-adc.c
new file mode 100644
index 0000000..1e0850d
--- /dev/null
+++ b/drivers/iio/adc/stm32/stm32-adc.c
@@ -0,0 +1,999 @@
+/*
+ * This file is part of STM32 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasn...@st.com>.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include "stm32-adc.h"
+
+/**
+ * stm32_adc_conf_scan_seq() - Build regular or injected channels scan sequence
+ * @indio_dev: IIO device
+ * @scan_mask: channels to be converted
+ *
+ * Conversion sequence :
+ * Configure ADC scan sequence based on selected channels in scan_mask.
+ * Add channels to SQR or JSQR registers, from scan_mask LSB to MSB, then
+ * program sequence len.
+ *
+ * Note: This can be done only when ADC enabled and no conversion is ongoing.
+ */
+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 *sq;
+       const struct iio_chan_spec *chan;
+       u32 val, bit;
+       int sq_max, i = 0;
+
+       if (!stm32_adc_is_enabled(adc))
+               return -EBUSY;
+
+       if (adc->injected) {
+               if (stm32_adc_injected_started(adc))
+                       return -EBUSY;
+
+               sq = adc->common->data->adc_reginfo->jsqr_reg;
+               sq_max = STM32_ADC_MAX_JSQ;
+       } else {
+               if (stm32_adc_regular_started(adc))
+                       return -EBUSY;
+
+               sq = adc->common->data->adc_reginfo->sqr_regs;
+               sq_max = STM32_ADC_MAX_SQ;
+       }
+
+       /* Build sequence for regular or injected channels */
+       for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
+               chan = indio_dev->channels + bit;
+               /*
+                * Assign one channel per SQ/JSQ entry in regular/injected
+                * sequence, starting with SQ1/JSQ1.
+                */
+               i++;
+               if (i > sq_max)
+                       return -EINVAL;
+
+               dev_dbg(adc->common->dev, "%s chan %d to %s%d\n",
+                       __func__, chan->channel, adc->injected ? "JSQ" : "SQ",
+                       i);
+
+               val = stm32_adc_readl(adc, sq[i].reg);
+               val &= ~sq[i].mask;
+               val |= (chan->channel << sq[i].shift) & sq[i].mask;
+               stm32_adc_writel(adc, sq[i].reg, val);
+       }
+
+       if (!i)
+               return -EINVAL;
+
+       /* Sequence len */
+       val = stm32_adc_readl(adc, sq[0].reg);
+       val &= ~sq[0].mask;
+       val |= ((i - 1) << sq[0].shift) & sq[0].mask;
+       stm32_adc_writel(adc, sq[0].reg, val);
+
+       return 0;
+}
+
+static int stm32_adc_conf_scan(struct iio_dev *indio_dev,
+                              const unsigned long *scan_mask)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       int ret;
+
+       ret = stm32_adc_clk_sel(adc);
+       if (ret) {
+               dev_err(&indio_dev->dev, "Clock sel failed\n");
+               return ret;
+       }
+
+       ret = stm32_adc_enable(adc);
+       if (ret) {
+               dev_err(&indio_dev->dev, "Failed to enable adc\n");
+               return ret;
+       }
+
+       ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
+       if (ret) {
+               dev_err(&indio_dev->dev, "Failed to configure sequence\n");
+               goto err_dis;
+       }
+
+       return 0;
+
+err_dis:
+       stm32_adc_disable(adc);
+
+       return ret;
+}
+
+/**
+ * stm32_adc_get_trig_index() - Get trigger index
+ * @indio_dev: IIO device
+ * @trig: trigger
+ *
+ * Returns trigger index, if trig matches one of the triggers registered by
+ * stm32 adc driver, -EINVAL otherwise.
+ */
+static int stm32_adc_get_trig_index(struct iio_dev *indio_dev,
+                                   struct iio_trigger *trig)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       struct iio_trigger *tr;
+       int i = 0;
+
+       list_for_each_entry(tr, &adc->extrig_list, alloc_list) {
+               if (tr == trig)
+                       return i;
+               i++;
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * stm32_adc_set_trig() - Set a regular or injected trigger
+ * @indio_dev: IIO device
+ * @trig: IIO trigger
+ *
+ * Set trigger source/polarity (e.g. SW, or HW with polarity) :
+ * - if HW trigger disabled (e.g. trig == NULL, conversion launched by sw)
+ * - if HW trigger enabled, set source & polarity (trigger_pol / jtrigger_pol)
+ *
+ * Note: must be called when ADC is enabled
+ */
+static int stm32_adc_set_trig(struct iio_dev *indio_dev,
+                             struct iio_trigger *trig)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       const struct stm32_adc_trig_info *trig_info;
+       const struct stm32_adc_trig_reginfo *reginfo;
+       u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG;
+       unsigned long flags;
+       int ret;
+
+       if (!stm32_adc_is_enabled(adc))
+               return -EBUSY;
+
+       if (adc->injected) {
+               if (stm32_adc_injected_started(adc))
+                       return -EBUSY;
+               reginfo = adc->common->data->adc_reginfo->jtrig_reginfo;
+               trig_info = adc->common->data->jext_triggers;
+       } else {
+               if (stm32_adc_regular_started(adc))
+                       return -EBUSY;
+               reginfo = adc->common->data->adc_reginfo->trig_reginfo;
+               trig_info = adc->common->data->ext_triggers;
+       }
+
+       if (trig) {
+               ret = stm32_adc_get_trig_index(indio_dev, trig);
+               if (ret < 0)
+                       return ret;
+
+               /* trigger source */
+               extsel = trig_info[ret].extsel;
+               exten = STM32_EXTEN_HWTRIG_RISING_EDGE;
+       }
+
+       spin_lock_irqsave(&adc->lock, flags);
+       val = stm32_adc_readl(adc, reginfo->reg);
+       val &= ~(reginfo->exten_mask | reginfo->extsel_mask);
+       val |= (exten << reginfo->exten_shift) & reginfo->exten_mask;
+       val |= (extsel << reginfo->extsel_shift) & reginfo->extsel_mask;
+       stm32_adc_writel(adc, reginfo->reg, val);
+       spin_unlock_irqrestore(&adc->lock, flags);
+
+       return 0;
+}
+
+/**
+ * stm32_adc_conv_irq_enable() - Unmask end of conversion irq
+ * @adc: stm32 adc instance
+ *
+ * Unmask either eoc or jeoc, depending on injected configuration.
+ */
+static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
+{
+       const struct stm32_adc_reginfo *reginfo =
+               adc->common->data->adc_reginfo;
+       u32 mask;
+
+       if (adc->injected)
+               mask = reginfo->jeocie;
+       else
+               mask = reginfo->eocie;
+
+       stm32_adc_set_bits(adc, reginfo->ier, mask);
+}
+
+/**
+ * stm32_adc_conv_irq_disable() - Mask end of conversion irq
+ * @adc: stm32 adc instance
+ *
+ * Mask either eoc or jeoc, depending on injected configuration.
+ */
+static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
+{
+       const struct stm32_adc_reginfo *reginfo =
+               adc->common->data->adc_reginfo;
+       u32 mask;
+
+       if (adc->injected)
+               mask = reginfo->jeocie;
+       else
+               mask = reginfo->eocie;
+
+       stm32_adc_clr_bits(adc, reginfo->ier, mask);
+}
+
+/**
+ * stm32_adc_single_conv() - perform a single conversion
+ * @indio_dev: IIO device
+ * @chan: IIO channel
+ * @result: conversion result
+ *
+ * The function performs a single conversion on a given channel, by
+ * by:
+ * - creating scan mask with only one channel
+ * - using SW trigger
+ * - then start single conv
+ */
+static int stm32_adc_single_conv(struct iio_dev *indio_dev,
+                                const struct iio_chan_spec *chan,
+                                int *val)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       unsigned long *scan_mask;
+       long timeout;
+       u16 result;
+       int ret;
+
+       scan_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long),
+                           GFP_KERNEL);
+       if (!scan_mask)
+               return -ENOMEM;
+
+       set_bit(chan->scan_index, scan_mask);
+
+       reinit_completion(&adc->completion);
+
+       adc->bufi = 0;
+       adc->num_conv = 1;
+       adc->buffer = &result;
+
+       ret = stm32_adc_conf_scan(indio_dev, scan_mask);
+       if (ret)
+               goto free;
+
+       /* No HW trigger: conversion can be launched in SW */
+       ret = stm32_adc_set_trig(indio_dev, NULL);
+       if (ret) {
+               dev_err(&indio_dev->dev, "Can't set SW trigger\n");
+               goto adc_disable;
+       }
+
+       stm32_adc_conv_irq_enable(adc);
+
+       ret = stm32_adc_start_conv(adc);
+       if (ret) {
+               dev_err(&indio_dev->dev, "Failed to start single conv\n");
+               goto irq_disable;
+       }
+
+       timeout = wait_for_completion_interruptible_timeout(
+                                       &adc->completion, STM32_ADC_TIMEOUT);
+       if (timeout == 0) {
+               dev_warn(&indio_dev->dev, "Conversion timed out!\n");
+               ret = -ETIMEDOUT;
+       } else if (timeout < 0) {
+               dev_warn(&indio_dev->dev, "Interrupted conversion!\n");
+               ret = -EINTR;
+       } else {
+               *val = result & STM32_RESULT_MASK;
+               ret = IIO_VAL_INT;
+       }
+
+       if (stm32_adc_stop_conv(adc))
+               dev_err(&indio_dev->dev, "stop failed\n");
+
+irq_disable:
+       stm32_adc_conv_irq_disable(adc);
+
+adc_disable:
+       stm32_adc_disable(adc);
+
+free:
+       kfree(scan_mask);
+       adc->buffer = NULL;
+
+       return ret;
+}
+
+static int stm32_adc_read_raw(struct iio_dev *indio_dev,
+                             struct iio_chan_spec const *chan,
+                             int *val, int *val2, long mask)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       int ret = -EINVAL;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               ret = iio_device_claim_direct_mode(indio_dev);
+               if (ret)
+                       return ret;
+               if (chan->type == IIO_VOLTAGE)
+                       ret = stm32_adc_single_conv(indio_dev, chan, val);
+               iio_device_release_direct_mode(indio_dev);
+               break;
+       case IIO_CHAN_INFO_SCALE:
+               *val = adc->common->vref_mv;
+               *val2 = chan->scan_type.realbits;
+               ret = IIO_VAL_FRACTIONAL_LOG2;
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+/**
+ * stm32_adc_isr() - Treat interrupt for one ADC instance within ADC block
+ */
+static irqreturn_t stm32_adc_isr(struct stm32_adc *adc)
+{
+       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+       const struct stm32_adc_reginfo *reginfo =
+               adc->common->data->adc_reginfo;
+       u32 mask, clr_mask, status = stm32_adc_readl(adc, reginfo->isr);
+
+       if (adc->injected) {
+               mask = reginfo->jeoc;
+               clr_mask = mask;
+       } else {
+               mask = reginfo->eoc;
+               /* don't clear 'eoc' as it is cleared when reading 'dr' */
+               clr_mask = 0;
+       }
+
+       /* clear irq */
+       stm32_adc_writel(adc, reginfo->isr, status & ~clr_mask);
+       status &= mask;
+
+       /* Regular data */
+       if (status & reginfo->eoc) {
+               adc->buffer[adc->bufi] = stm32_adc_readl(adc, reginfo->dr);
+               if (iio_buffer_enabled(indio_dev)) {
+                       adc->bufi++;
+                       if (adc->bufi >= adc->num_conv) {
+                               stm32_adc_conv_irq_disable(adc);
+                               iio_trigger_poll(indio_dev->trig);
+                       }
+               } else {
+                       complete(&adc->completion);
+               }
+       }
+
+       /* Injected data */
+       if (status & reginfo->jeoc) {
+               int i;
+
+               for (i = 0; i < adc->num_conv; i++) {
+                       adc->buffer[i] = stm32_adc_readl(adc, reginfo->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);
+               }
+       }
+
+       /*
+        * In case end of conversion flags have been handled, this has been
+        * handled for this ADC instance
+        */
+       if (status)
+               return IRQ_HANDLED;
+
+       /* This adc instance didn't trigger this interrupt */
+       return IRQ_NONE;
+}
+
+/**
+ * stm32_adc_common_isr() - Common isr for the whole ADC block
+ *
+ * There is one IRQ for all ADCs in ADC block, check all instances.
+ */
+static irqreturn_t stm32_adc_common_isr(int irq, void *data)
+{
+       struct stm32_adc_common *common = data;
+       irqreturn_t ret = IRQ_NONE;
+       struct stm32_adc *adc;
+
+       list_for_each_entry(adc, &common->adc_list, adc_list)
+               ret |= stm32_adc_isr(adc);
+
+       return ret;
+}
+
+/**
+ * stm32_adc_validate_trigger() - validate trigger for stm32 adc
+ * @indio_dev: IIO device
+ * @trig: new trigger
+ *
+ * Returns: 0 if trig matches one of the triggers registered by stm32 adc
+ * driver, -EINVAL otherwise.
+ */
+static int stm32_adc_validate_trigger(struct iio_dev *indio_dev,
+                                     struct iio_trigger *trig)
+{
+       return stm32_adc_get_trig_index(indio_dev, trig) < 0 ? -EINVAL : 0;
+}
+
+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);
+       int ret;
+       u32 bit;
+
+       adc->num_conv = 0;
+       for_each_set_bit(bit, scan_mask, indio_dev->masklength)
+               adc->num_conv++;
+
+       ret = stm32_adc_conf_scan(indio_dev, scan_mask);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
+                             const struct of_phandle_args *iiospec)
+{
+       int i;
+
+       for (i = 0; i < indio_dev->num_channels; i++)
+               if (indio_dev->channels[i].channel == iiospec->args[0])
+                       return i;
+
+       return -EINVAL;
+}
+
+/**
+ * stm32_adc_debugfs_reg_access - read or write register value
+ *
+ * To read a value from an ADC register:
+ *   echo [ADC reg offset] > direct_reg_access
+ *   cat direct_reg_access
+ *
+ * To write a value in a ADC register:
+ *   echo [ADC_reg_offset] [value] > direct_reg_access
+ */
+static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
+                                       unsigned reg, unsigned writeval,
+                                       unsigned *readval)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       if (!readval)
+               stm32_adc_writel(adc, reg, writeval);
+       else
+               *readval = stm32_adc_readl(adc, reg);
+
+       return 0;
+}
+
+static const struct iio_info stm32_adc_iio_info = {
+       .read_raw = stm32_adc_read_raw,
+       .validate_trigger = stm32_adc_validate_trigger,
+       .update_scan_mode = stm32_adc_update_scan_mode,
+       .debugfs_reg_access = stm32_adc_debugfs_reg_access,
+       .of_xlate = stm32_adc_of_xlate,
+       .driver_module = THIS_MODULE,
+};
+
+static int stm32_adc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       stm32_adc_disable(adc);
+
+       return 0;
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+       .postenable = &iio_triggered_buffer_postenable,
+       .predisable = &iio_triggered_buffer_predisable,
+       .postdisable = &stm32_adc_buffer_postdisable,
+};
+
+static int stm32_adc_validate_device(struct iio_trigger *trig,
+                                    struct iio_dev *indio_dev)
+{
+       struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+
+       return indio != indio_dev ? -EINVAL : 0;
+}
+
+static int stm32_adc_set_trigger_state(struct iio_trigger *trig,
+                                      bool state)
+{
+       struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       int ret;
+
+       if (state) {
+               /* Reset adc buffer index */
+               adc->bufi = 0;
+
+               /* Allocate adc buffer */
+               adc->buffer = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
+               if (!adc->buffer)
+                       return -ENOMEM;
+
+               ret = stm32_adc_set_trig(indio_dev, trig);
+               if (ret) {
+                       dev_err(&indio_dev->dev, "Can't set trigger\n");
+                       goto err_buffer_free;
+               }
+
+               stm32_adc_conv_irq_enable(adc);
+
+               ret = stm32_adc_start_conv(adc);
+               if (ret) {
+                       dev_err(&indio_dev->dev, "Failed to start\n");
+                       goto err_irq_trig_disable;
+               }
+       } else {
+               ret = stm32_adc_stop_conv(adc);
+               if (ret < 0) {
+                       dev_err(&indio_dev->dev, "Failed to stop\n");
+                       return ret;
+               }
+
+               stm32_adc_conv_irq_disable(adc);
+
+               ret = stm32_adc_set_trig(indio_dev, NULL);
+               if (ret)
+                       dev_warn(&indio_dev->dev, "Can't clear trigger\n");
+
+               kfree(adc->buffer);
+               adc->buffer = NULL;
+       }
+
+       return 0;
+
+err_irq_trig_disable:
+       stm32_adc_conv_irq_disable(adc);
+       stm32_adc_set_trig(indio_dev, NULL);
+
+err_buffer_free:
+       kfree(adc->buffer);
+       adc->buffer = NULL;
+
+       return ret;
+}
+
+static const struct iio_trigger_ops stm32_adc_trigger_ops = {
+       .owner = THIS_MODULE,
+       .validate_device = stm32_adc_validate_device,
+       .set_trigger_state = stm32_adc_set_trigger_state,
+};
+
+static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
+{
+       struct iio_poll_func *pf = p;
+       struct iio_dev *indio_dev = pf->indio_dev;
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
+
+       /* reset buffer index */
+       adc->bufi = 0;
+       iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
+                                          pf->timestamp);
+
+       iio_trigger_notify_done(indio_dev->trig);
+
+       /* re-enable eoc irq */
+       stm32_adc_conv_irq_enable(adc);
+
+       return IRQ_HANDLED;
+}
+
+static void stm32_adc_trig_unregister(struct iio_dev *indio_dev)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       struct iio_trigger *trig, *_t;
+
+       list_for_each_entry_safe(trig, _t, &adc->extrig_list, alloc_list) {
+               iio_trigger_unregister(trig);
+               list_del(&trig->alloc_list);
+       }
+}
+
+static int stm32_adc_trig_register(struct iio_dev *indio_dev)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       struct stm32_adc_common *common = adc->common;
+       const struct stm32_adc_trig_info *ext = common->data->ext_triggers;
+       struct iio_trigger *trig;
+       int i, ret = 0;
+
+       if (adc->injected)
+               ext = common->data->jext_triggers;
+       else
+               ext = common->data->ext_triggers;
+
+       for (i = 0; ext && ext[i].name; i++) {
+               trig = devm_iio_trigger_alloc(common->dev, "%s_%s%d_%s",
+                                             indio_dev->name,
+                                             adc->injected ? "jext" : "ext",
+                                             ext[i].extsel, ext[i].name);
+               if (!trig) {
+                       dev_err(common->dev, "trig %s_%s%d_%s alloc failed\n",
+                               indio_dev->name,
+                               adc->injected ? "jext" : "ext",
+                               ext[i].extsel, ext[i].name);
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               trig->dev.parent = common->dev;
+               trig->ops = &stm32_adc_trigger_ops;
+               iio_trigger_set_drvdata(trig, indio_dev);
+
+               ret = iio_trigger_register(trig);
+               if (ret) {
+                       dev_err(common->dev,
+                               "trig %s_%s%d_%s register failed\n",
+                               indio_dev->name,
+                               adc->injected ? "jext" : "ext",
+                               ext[i].extsel, ext[i].name);
+                       goto err;
+               }
+
+               list_add_tail(&trig->alloc_list, &adc->extrig_list);
+       }
+
+       return 0;
+err:
+       stm32_adc_trig_unregister(indio_dev);
+
+       return ret;
+}
+
+static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
+                                   struct iio_chan_spec *chan,
+                                   const struct stm32_adc_chan_spec *channel,
+                                   int scan_index)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+
+       chan->type = channel->type;
+       chan->channel = channel->channel;
+       chan->datasheet_name = channel->name;
+       chan->extend_name = channel->name;
+       chan->scan_index = scan_index;
+       chan->indexed = 1;
+       chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+       chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+       chan->scan_type.sign = 'u';
+       chan->scan_type.realbits = adc->common->data->highres;
+       chan->scan_type.storagebits = STM32_STORAGEBITS;
+       chan->scan_type.shift = 0;
+}
+
+static int stm32_adc_chan_of_init(struct iio_dev *indio_dev,
+                                 const struct stm32_adc_info *adc_info)
+{
+       struct stm32_adc *adc = iio_priv(indio_dev);
+       struct device_node *node = indio_dev->dev.of_node;
+       struct property *prop;
+       const __be32 *cur;
+       struct iio_chan_spec *channels;
+       int scan_index = 0, num_channels = 0;
+       u32 val;
+
+       of_property_for_each_u32(node, "st,adc-channels", prop, cur, val)
+               num_channels++;
+
+       channels = devm_kcalloc(&indio_dev->dev, num_channels,
+                               sizeof(struct iio_chan_spec), GFP_KERNEL);
+       if (!channels)
+               return -ENOMEM;
+
+       of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
+               stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+                                       &adc_info->channels[val],
+                                       scan_index);
+               scan_index++;
+       }
+
+       adc->max_channels = adc_info->max_channels;
+       indio_dev->num_channels = scan_index;
+       indio_dev->channels = channels;
+
+       return 0;
+}
+
+static int stm32_adc_register(struct stm32_adc_common *common,
+                             struct device_node *child)
+{
+       struct iio_dev *indio_dev;
+       struct stm32_adc *adc;
+       int i, ret;
+       u32 reg;
+
+       ret = of_property_read_u32(child, "reg", &reg);
+       if (ret != 0) {
+               dev_err(common->dev, "missing reg property\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; common->data->adc_info[i].channels; i++)
+               if (common->data->adc_info[i].reg == reg)
+                       break;
+
+       if (i >= STM32_ADC_ID_MAX || !common->data->adc_info[i].channels) {
+               dev_err(common->dev, "bad adc reg offset\n");
+               return -ENOENT;
+       }
+
+       indio_dev = devm_iio_device_alloc(common->dev, sizeof(*adc));
+       if (!indio_dev) {
+               dev_err(common->dev, "iio device allocation failed\n");
+               return -ENOMEM;
+       }
+
+       adc = iio_priv(indio_dev);
+       adc->id = i;
+       adc->offset = reg;
+       adc->common = common;
+       INIT_LIST_HEAD(&adc->extrig_list);
+       spin_lock_init(&adc->lock);
+       init_completion(&adc->completion);
+
+       if (child->name)
+               indio_dev->name = child->name;
+       else
+               indio_dev->name = common->data->adc_info[i].name;
+       indio_dev->dev.parent = common->dev;
+       indio_dev->dev.of_node = child;
+       indio_dev->info = &stm32_adc_iio_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+
+       if (of_property_read_bool(child, "st,injected")) {
+               dev_dbg(common->dev, "%s Configured to use injected\n",
+                       indio_dev->name);
+               adc->injected = true;
+       }
+
+       adc->clk = of_clk_get(child, 0);
+       if (IS_ERR(adc->clk)) {
+               adc->clk = NULL;
+               dev_dbg(common->dev, "No child clk found\n");
+       } else {
+               ret = clk_prepare_enable(adc->clk);
+               if (ret < 0)
+                       goto err_clk_put;
+       }
+
+       ret = stm32_adc_chan_of_init(indio_dev, &common->data->adc_info[i]);
+       if (ret < 0) {
+               dev_err(common->dev, "iio channels init failed\n");
+               goto err_clk_disable;
+       }
+
+       ret = stm32_adc_trig_register(indio_dev);
+       if (ret)
+               goto err_clk_disable;
+
+       ret = iio_triggered_buffer_setup(indio_dev,
+                                        &iio_pollfunc_store_time,
+                                        &stm32_adc_trigger_handler,
+                                        &iio_triggered_buffer_setup_ops);
+       if (ret) {
+               dev_err(common->dev, "buffer setup failed\n");
+               goto err_trig_unregister;
+       }
+
+       ret = iio_device_register(indio_dev);
+       if (ret) {
+               dev_err(common->dev, "iio dev register failed\n");
+               goto err_buffer_cleanup;
+       }
+
+       list_add_tail(&adc->adc_list, &common->adc_list);
+
+       return 0;
+
+err_buffer_cleanup:
+       iio_triggered_buffer_cleanup(indio_dev);
+
+err_trig_unregister:
+       stm32_adc_trig_unregister(indio_dev);
+
+err_clk_disable:
+       if (adc->clk)
+               clk_disable_unprepare(adc->clk);
+
+err_clk_put:
+       if (adc->clk)
+               clk_put(adc->clk);
+
+       return ret;
+}
+
+static void stm32_adc_unregister(struct stm32_adc *adc)
+{
+       struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+       iio_device_unregister(indio_dev);
+       iio_triggered_buffer_cleanup(indio_dev);
+       stm32_adc_trig_unregister(indio_dev);
+       if (adc->clk) {
+               clk_disable_unprepare(adc->clk);
+               clk_put(adc->clk);
+       }
+}
+
+int stm32_adc_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node, *child;
+       struct device *dev = &pdev->dev;
+       const struct of_device_id *match;
+       struct stm32_adc_common *common;
+       struct stm32_adc *adc;
+       struct resource *res;
+       int ret;
+
+       match = of_match_device(dev->driver->of_match_table, &pdev->dev);
+       if (!match || !match->data) {
+               dev_err(&pdev->dev, "compatible data not provided\n");
+               return -EINVAL;
+       }
+
+       common = devm_kzalloc(&pdev->dev, sizeof(*common), GFP_KERNEL);
+       if (!common)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       common->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(common->base))
+               return PTR_ERR(common->base);
+
+       common->data = match->data;
+       common->dev = &pdev->dev;
+       platform_set_drvdata(pdev, common);
+       mutex_init(&common->lock);
+       INIT_LIST_HEAD(&common->adc_list);
+
+       common->vref = devm_regulator_get(&pdev->dev, "vref");
+       if (IS_ERR(common->vref)) {
+               ret = PTR_ERR(common->vref);
+               dev_err(&pdev->dev, "vref get failed, %d\n", ret);
+               return ret;
+       }
+
+       ret = regulator_enable(common->vref);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "vref enable failed\n");
+               return ret;
+       }
+
+       ret = regulator_get_voltage(common->vref);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
+               goto err_regulator_disable;
+       }
+       common->vref_mv = ret / 1000;
+       dev_dbg(&pdev->dev, "vref+=%dmV\n", common->vref_mv);
+
+       common->aclk = devm_clk_get(&pdev->dev, "adc");
+       if (IS_ERR(common->aclk)) {
+               ret = PTR_ERR(common->aclk);
+               dev_err(&pdev->dev, "Can't get 'adc' clock\n");
+               goto err_regulator_disable;
+       }
+
+       ret = clk_prepare_enable(common->aclk);
+       if (ret < 0) {
+               dev_err(common->dev, "adc clk enable failed\n");
+               goto err_regulator_disable;
+       }
+
+       common->irq = platform_get_irq(pdev, 0);
+       if (common->irq < 0) {
+               dev_err(&pdev->dev, "failed to get irq\n");
+               ret = common->irq;
+               goto err_clk_disable;
+       }
+
+       ret = devm_request_irq(&pdev->dev, common->irq, stm32_adc_common_isr,
+                              0, pdev->name, common);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to request irq\n");
+               goto err_clk_disable;
+       }
+
+       /* Parse adc child nodes to retrieve master/slave instances data */
+       for_each_available_child_of_node(np, child) {
+               ret = stm32_adc_register(common, child);
+               if (ret)
+                       goto err_unregister;
+       }
+
+       dev_info(&pdev->dev, "registered\n");
+
+       return 0;
+
+err_unregister:
+       list_for_each_entry(adc, &common->adc_list, adc_list)
+               stm32_adc_unregister(adc);
+
+err_clk_disable:
+       clk_disable_unprepare(common->aclk);
+
+err_regulator_disable:
+       regulator_disable(common->vref);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(stm32_adc_probe);
+
+int stm32_adc_remove(struct platform_device *pdev)
+{
+       struct stm32_adc_common *common = platform_get_drvdata(pdev);
+       struct stm32_adc *adc;
+
+       list_for_each_entry(adc, &common->adc_list, adc_list)
+               stm32_adc_unregister(adc);
+       clk_disable_unprepare(common->aclk);
+       regulator_disable(common->vref);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(stm32_adc_remove);
+
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasn...@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/stm32/stm32-adc.h 
b/drivers/iio/adc/stm32/stm32-adc.h
new file mode 100644
index 0000000..0be603c
--- /dev/null
+++ b/drivers/iio/adc/stm32/stm32-adc.h
@@ -0,0 +1,442 @@
+/*
+ * This file is part of STM32 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasn...@st.com>.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __STM32_ADC_H
+#define __STM32_ADC_H
+
+/*
+ * STM32 - ADC global register map
+ * ________________________________________________________
+ * | Offset |                 Register                    |
+ * --------------------------------------------------------
+ * | 0x000  |                Master ADC1                  |
+ * --------------------------------------------------------
+ * | 0x100  |                Slave ADC2                   |
+ * --------------------------------------------------------
+ * | 0x200  |                Slave ADC3                   |
+ * --------------------------------------------------------
+ * | 0x300  |         Master & Slave common regs          |
+ * --------------------------------------------------------
+ */
+#define STM32_ADCX_COMN_OFFSET         0x300
+#define STM32_ADC_ID_MAX               3
+#define STM32_ADC_MAX_SQ               16      /* SQ1..SQ16 */
+#define STM32_ADC_MAX_JSQ              4       /* JSQ1..JSQ4 */
+
+/* STM32 value masks */
+#define STM32_RESULT_MASK      GENMASK(15, 0)
+#define STM32_STORAGEBITS      16
+
+/* External trigger enable for regular or injected channels (exten/jexten) */
+enum stm32_adc_exten {
+       STM32_EXTEN_SWTRIG,
+       STM32_EXTEN_HWTRIG_RISING_EDGE,
+       STM32_EXTEN_HWTRIG_FALLING_EDGE,
+       STM32_EXTEN_HWTRIG_BOTH_EDGES,
+};
+
+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,
+       STM32_EXT21,
+       STM32_EXT22,
+       STM32_EXT23,
+       STM32_EXT24,
+       STM32_EXT25,
+       STM32_EXT26,
+       STM32_EXT27,
+       STM32_EXT28,
+       STM32_EXT29,
+       STM32_EXT30,
+       STM32_EXT31,
+};
+
+enum stm32_adc_jextsel {
+       STM32_JEXT0,
+       STM32_JEXT1,
+       STM32_JEXT2,
+       STM32_JEXT3,
+       STM32_JEXT4,
+       STM32_JEXT5,
+       STM32_JEXT6,
+       STM32_JEXT7,
+       STM32_JEXT8,
+       STM32_JEXT9,
+       STM32_JEXT10,
+       STM32_JEXT11,
+       STM32_JEXT12,
+       STM32_JEXT13,
+       STM32_JEXT14,
+       STM32_JEXT15,
+       STM32_JEXT16,
+       STM32_JEXT17,
+       STM32_JEXT18,
+       STM32_JEXT19,
+       STM32_JEXT20,
+       STM32_JEXT21,
+       STM32_JEXT22,
+       STM32_JEXT23,
+       STM32_JEXT24,
+       STM32_JEXT25,
+       STM32_JEXT26,
+       STM32_JEXT27,
+       STM32_JEXT28,
+       STM32_JEXT29,
+       STM32_JEXT30,
+       STM32_JEXT31,
+};
+
+#define        STM32_ADC_TIMEOUT_US    100000
+#define        STM32_ADC_TIMEOUT       (msecs_to_jiffies(STM32_ADC_TIMEOUT_US 
/ 1000))
+
+/**
+ * struct stm32_adc_chan_spec - specification of stm32 adc channel
+ * @type:      IIO channel type
+ * @channel:   channel number (single ended)
+ * @name:      channel name (single ended)
+ */
+struct stm32_adc_chan_spec {
+       enum iio_chan_type      type;
+       int                     channel;
+       const char              *name;
+};
+
+/**
+ * struct stm32_adc_trig_info - ADC trigger info
+ * @extsel:            trigger selection for regular or injected
+ * @name:              name of the trigger, corresponding to its source
+ */
+struct stm32_adc_trig_info {
+       u32 extsel;
+       const char *name;
+};
+
+/**
+ * struct stm32_adc_info - stm32 ADC, per instance config data
+ * @name:              default name for this instance (like "adc1")
+ * @reg:               reg offset for this instance (e.g. 0x0 for adc1...)
+ * @channels:          Reference to stm32 channels spec
+ * @max_channels:      Number of single ended channels
+ */
+struct stm32_adc_info {
+       const char *name;
+       u32 reg;
+       const struct stm32_adc_chan_spec *channels;
+       int max_channels;
+};
+
+/**
+ * stm32_adc_regs - stm32 ADC misc registers & bitfield desc
+ * @reg:               register offset
+ * @mask:              bitfield mask
+ * @shift:             left shift
+ */
+struct stm32_adc_regs {
+       int reg;
+       int mask;
+       int shift;
+};
+
+/**
+ * stm32_adc_trig_reginfo - stm32 ADC trigger control registers description
+ * @reg:               trigger control register offset (exten/jexten)
+ * @exten_mask:                external trigger en/polarity mask in @reg
+ * @exten_shift:       external trigger en/polarity shift in @reg
+ * @extsel_mask:       external trigger source mask in @reg
+ * @extsel_shift:      external trigger source shift in @reg
+ */
+struct stm32_adc_trig_reginfo {
+       u32 reg;
+       u32 exten_mask;
+       u32 exten_shift;
+       u32 extsel_mask;
+       u32 extsel_shift;
+};
+
+/**
+ * struct stm32_adc_reginfo - stm32 ADC registers description
+ * @isr:               interrupt status register offset
+ * @eoc:               end of conversion mask in @isr
+ * @jeoc:              end of injected conversion sequence mask in @isr
+ * @ier:               interrupt enable register offset
+ * @eocie:             end of conversion interrupt enable mask in @ier
+ * @jeocie:            end of injected conversion sequence interrupt en mask
+ * @dr:                        data register offset
+ * @jdr:               injected data registers offsets
+ * @sqr_regs:          Regular sequence registers description
+ * @jsqr_reg:          Injected sequence register description
+ * @trig_reginfo:      regular trigger control registers description
+ * @jtrig_reginfo:     injected trigger control registers description
+ */
+struct stm32_adc_reginfo {
+       u32 isr;
+       u32 eoc;
+       u32 jeoc;
+       u32 ier;
+       u32 eocie;
+       u32 jeocie;
+       u32 dr;
+       u32 jdr[4];
+       const struct stm32_adc_regs *sqr_regs;
+       const struct stm32_adc_regs *jsqr_reg;
+       const struct stm32_adc_trig_reginfo *trig_reginfo;
+       const struct stm32_adc_trig_reginfo *jtrig_reginfo;
+};
+
+struct stm32_adc;
+
+/**
+ * struct stm32_adc_ops - stm32 ADC, compatible dependent data
+ * - stm32 ADC may work as single ADC, or as tightly coupled master/slave ADCs.
+ *
+ * @adc_info:          Array spec for stm32 adc master/slaves instances
+ * @ext_triggers:      Reference to trigger info for regular channels
+ * @jext_triggers:     Reference to trigger info for injected channels
+ * @adc_reginfo:       stm32 ADC registers description
+ * @highres:           Max resolution
+ * @max_clock_rate:    Max input clock rate
+ * @clk_sel:           routine to select common clock and prescaler
+ * @start_conv:                routine to start conversions
+ * @stop_conv:         routine to stop conversions
+ * @is_started:                routine to get adc 'started' state
+ * @regular_started    routine to check regular conversions status
+ * @injected_started   routine to check injected conversions status
+ * @enable:            optional routine to enable stm32 adc
+ * @disable:           optional routine to disable stm32 adc
+ * @is_enabled         reports enabled state
+ */
+struct stm32_adc_ops {
+       const struct stm32_adc_info *adc_info;
+       const struct stm32_adc_trig_info *ext_triggers;
+       const struct stm32_adc_trig_info *jext_triggers;
+       const struct stm32_adc_reginfo *adc_reginfo;
+       int highres;
+       unsigned long max_clock_rate;
+       int (*clk_sel)(struct stm32_adc *adc);
+       int (*start_conv)(struct stm32_adc *adc);
+       int (*stop_conv)(struct stm32_adc *adc);
+       bool (*is_started)(struct stm32_adc *adc);
+       bool (*regular_started)(struct stm32_adc *adc);
+       bool (*injected_started)(struct stm32_adc *adc);
+       int (*enable)(struct stm32_adc *adc);
+       void (*disable)(struct stm32_adc *adc);
+       bool (*is_enabled)(struct stm32_adc *adc);
+};
+
+struct stm32_adc_common;
+
+/**
+ * struct stm32_adc - private data of each ADC IIO instance
+ * @common:            reference to ADC block common data
+ * @adc_list:          current ADC entry in common ADC list
+ * @id:                        ADC instance number (e.g. adc 1, 2 or 3)
+ * @offset:            ADC instance register offset in ADC block
+ * @max_channels:      Max channels number for this ADC.
+ * @extrig_list:       External trigger list (for regular channel)
+ * @completion:                end of single conversion completion
+ * @buffer:            data buffer
+ * @bufi:              data buffer index
+ * @num_conv:          expected number of scan conversions
+ * @injected:          use injected channels on this adc
+ * @lock:              spinlock
+ * @clk:               optional adc clock, for this adc instance
+ * @calib:             optional calibration data
+ * @en:                        emulates enabled state on some stm32 adc
+ */
+struct stm32_adc {
+       struct stm32_adc_common *common;
+       struct list_head        adc_list;
+       int                     id;
+       int                     offset;
+       int                     max_channels;
+       struct list_head        extrig_list;
+       struct completion       completion;
+       u16                     *buffer;
+       int                     bufi;
+       int                     num_conv;
+       bool                    injected;
+       spinlock_t              lock;           /* interrupt lock */
+       struct clk              *clk;
+       void                    *calib;
+       bool                    en;
+};
+
+/**
+ * struct stm32_adc_common - private data of ADC driver, common to all
+ * ADC instances (ADC block)
+ * @dev:               device for this controller
+ * @base:              control registers base cpu addr
+ * @irq:               Common irq line for all adc instances
+ * @data:              STM32 dependent data from compatible
+ * @adc_list:          list of all stm32 ADC in this ADC block
+ * @aclk:              common clock for the analog circuitry
+ * @vref:              regulator reference
+ * @vref_mv:           vref voltage (mv)
+ * @lock:              mutex
+ */
+struct stm32_adc_common {
+       struct device                   *dev;
+       void __iomem                    *base;
+       int                             irq;
+       const struct stm32_adc_ops      *data;
+       struct list_head                adc_list;
+       struct clk                      *aclk;
+       struct regulator                *vref;
+       int                             vref_mv;
+       struct mutex                    lock;   /* read_raw lock */
+};
+
+/* Helper routines */
+static inline int stm32_adc_start_conv(struct stm32_adc *adc)
+{
+       return adc->common->data->start_conv(adc);
+}
+
+static inline int stm32_adc_stop_conv(struct stm32_adc *adc)
+{
+       return adc->common->data->stop_conv(adc);
+}
+
+static inline bool stm32_adc_is_started(struct stm32_adc *adc)
+{
+       return adc->common->data->is_started(adc);
+}
+
+static inline bool stm32_adc_regular_started(struct stm32_adc *adc)
+{
+       return adc->common->data->regular_started(adc);
+}
+
+static inline bool stm32_adc_injected_started(struct stm32_adc *adc)
+{
+       return adc->common->data->injected_started(adc);
+}
+
+static inline bool stm32_adc_clk_sel(struct stm32_adc *adc)
+{
+       return adc->common->data->clk_sel(adc);
+}
+
+static inline int stm32_adc_enable(struct stm32_adc *adc)
+{
+       if (adc->common->data->enable)
+               return adc->common->data->enable(adc);
+
+       adc->en = true;
+
+       return 0;
+}
+
+static inline bool stm32_adc_is_enabled(struct stm32_adc *adc)
+{
+       if (adc->common->data->is_enabled)
+               return adc->common->data->is_enabled(adc);
+       else
+               return adc->en;
+}
+
+static inline void stm32_adc_disable(struct stm32_adc *adc)
+{
+       /* Check there is no regular or injected on-going conversions */
+       if (stm32_adc_is_started(adc))
+               return;
+
+       if (adc->common->data->disable)
+               adc->common->data->disable(adc);
+       else
+               adc->en = false;
+}
+
+/* STM32 ADC registers access routines */
+static inline u32 stm32_adc_common_readl(struct stm32_adc_common *com, u32 reg)
+{
+       u32 val = readl_relaxed(com->base + reg);
+
+       return val;
+}
+
+static inline void stm32_adc_common_writel(struct stm32_adc_common *com,
+                                          u32 reg, u32 val)
+{
+       writel_relaxed(val, com->base + reg);
+}
+
+static inline u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
+{
+       u32 val = readl_relaxed(adc->common->base + adc->offset + reg);
+
+       return val;
+}
+
+#define stm32_adc_readl_addr(addr)     stm32_adc_readl(adc, addr)
+
+#define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \
+       readx_poll_timeout(stm32_adc_readl_addr, reg, val, \
+                          cond, sleep_us, timeout_us)
+
+static inline void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
+{
+       writel_relaxed(val, adc->common->base + adc->offset + reg);
+}
+
+static inline void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&adc->lock, flags);
+       stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
+       spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static inline void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&adc->lock, flags);
+       stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
+       spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+/* STM32 common extended attributes */
+extern const struct iio_enum stm32_adc_trig_pol;
+int stm32_adc_probe(struct platform_device *pdev);
+int stm32_adc_remove(struct platform_device *pdev);
+
+#endif
diff --git a/drivers/iio/adc/stm32/stm32f4-adc.c 
b/drivers/iio/adc/stm32/stm32f4-adc.c
new file mode 100644
index 0000000..147fe9c
--- /dev/null
+++ b/drivers/iio/adc/stm32/stm32f4-adc.c
@@ -0,0 +1,574 @@
+/*
+ * This file is part of STM32F4 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasn...@st.com>.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/platform_device.h>
+#include "stm32-adc.h"
+
+/*
+ * STM32F4 - ADC global register map
+ * ________________________________________________________
+ * | Offset |                 Register                    |
+ * --------------------------------------------------------
+ * | 0x000  |                Master ADC1                  |
+ * --------------------------------------------------------
+ * | 0x100  |                Slave ADC2                   |
+ * --------------------------------------------------------
+ * | 0x200  |                Slave ADC3                   |
+ * --------------------------------------------------------
+ * | 0x300  |         Master & Slave common regs          |
+ * --------------------------------------------------------
+ */
+
+/* STM32F4 - Registers for each ADC instance */
+#define STM32F4_ADCX_SR                        0x00
+#define STM32F4_ADCX_CR1               0x04
+#define STM32F4_ADCX_CR2               0x08
+#define STM32F4_ADCX_SMPR1             0x0C
+#define STM32F4_ADCX_SMPR2             0x10
+#define STM32F4_ADCX_HTR               0x24
+#define STM32F4_ADCX_LTR               0x28
+#define STM32F4_ADCX_SQR1              0x2C
+#define STM32F4_ADCX_SQR2              0x30
+#define STM32F4_ADCX_SQR3              0x34
+#define STM32F4_ADCX_JSQR              0x38
+#define STM32F4_ADCX_JDR1              0x3C
+#define STM32F4_ADCX_JDR2              0x40
+#define STM32F4_ADCX_JDR3              0x44
+#define STM32F4_ADCX_JDR4              0x48
+#define STM32F4_ADCX_DR                        0x4C
+
+/* STM32 - Master & slave registers (common for all instances: 1, 2 & 3) */
+#define STM32F4_ADC_CSR                        (STM32_ADCX_COMN_OFFSET + 0x00)
+#define STM32F4_ADC_CCR                        (STM32_ADCX_COMN_OFFSET + 0x04)
+#define STM32F4_ADC_CDR                        (STM32_ADCX_COMN_OFFSET + 0x08)
+
+/* STM32F4_ADCX_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_ADCX_CR1 - bit fields */
+#define STM32F4_OVRIE                  BIT(26)
+#define STM32F4_RES_SHIFT              24
+#define STM32F4_RES_MASK               GENMASK(25, 24)
+#define STM32F4_AWDEN                  BIT(23)
+#define STM32F4_JAWDEN                 BIT(22)
+#define STM32F4_DISCNUM_SHIFT          13
+#define STM32F4_DISCNUM_MASK           GENMASK(15, 13)
+#define STM32F4_JDISCEN                        BIT(12)
+#define STM32F4_DISCEN                 BIT(11)
+#define STM32F4_JAUTO                  BIT(10)
+#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_ADCX_CR2 - bit fields */
+#define STM32F4_SWSTART                        BIT(30)
+#define STM32F4_EXTEN_SHIFT            28
+#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_ALIGN                  BIT(11)
+#define STM32F4_EOCS                   BIT(10)
+#define STM32F4_DDS                    BIT(9)
+#define STM32F4_DMA                    BIT(8)
+#define STM32F4_CONT                   BIT(1)
+#define STM32F4_ADON                   BIT(0)
+
+/* STM32F4_ADCX_SMPR1 - bit fields */
+#define STM32F4_SMP18_SHIFT            24
+#define STM32F4_SMP18_MASK             GENMASK(26, 24)
+#define STM32F4_SMP17_SHIFT            21
+#define STM32F4_SMP17_MASK             GENMASK(23, 21)
+#define STM32F4_SMP16_SHIFT            18
+#define STM32F4_SMP16_MASK             GENMASK(20, 18)
+#define STM32F4_SMP15_SHIFT            15
+#define STM32F4_SMP15_MASK             GENMASK(17, 15)
+#define STM32F4_SMP14_SHIFT            12
+#define STM32F4_SMP14_MASK             GENMASK(14, 12)
+#define STM32F4_SMP13_SHIFT            9
+#define STM32F4_SMP13_MASK             GENMASK(11, 9)
+#define STM32F4_SMP12_SHIFT            6
+#define STM32F4_SMP12_MASK             GENMASK(8, 6)
+#define STM32F4_SMP11_SHIFT            3
+#define STM32F4_SMP11_MASK             GENMASK(5, 3)
+#define STM32F4_SMP10_SHIFT            0
+#define STM32F4_SMP10_MASK             GENMASK(2, 0)
+
+/* STM32F4_ADCX_SMPR2 - bit fields */
+#define STM32F4_SMP9_SHIFT             27
+#define STM32F4_SMP9_MASK              GENMASK(29, 27)
+#define STM32F4_SMP8_SHIFT             24
+#define STM32F4_SMP8_MASK              GENMASK(26, 24)
+#define STM32F4_SMP7_SHIFT             21
+#define STM32F4_SMP7_MASK              GENMASK(23, 21)
+#define STM32F4_SMP6_SHIFT             18
+#define STM32F4_SMP6_MASK              GENMASK(20, 18)
+#define STM32F4_SMP5_SHIFT             15
+#define STM32F4_SMP5_MASK              GENMASK(17, 15)
+#define STM32F4_SMP4_SHIFT             12
+#define STM32F4_SMP4_MASK              GENMASK(14, 12)
+#define STM32F4_SMP3_SHIFT             9
+#define STM32F4_SMP3_MASK              GENMASK(11, 9)
+#define STM32F4_SMP2_SHIFT             6
+#define STM32F4_SMP2_MASK              GENMASK(8, 6)
+#define STM32F4_SMP1_SHIFT             3
+#define STM32F4_SMP1_MASK              GENMASK(5, 3)
+#define STM32F4_SMP0_SHIFT             0
+#define STM32F4_SMP0_MASK              GENMASK(2, 0)
+enum stm32f4_adc_smpr {
+       STM32F4_SMPR_3_CK_CYCLES,
+       STM32F4_SMPR_15_CK_CYCLES,
+       STM32F4_SMPR_28_CK_CYCLES,
+       STM32F4_SMPR_56_CK_CYCLES,
+       STM32F4_SMPR_84_CK_CYCLES,
+       STM32F4_SMPR_112_CK_CYCLES,
+       STM32F4_SMPR_144_CK_CYCLES,
+       STM32F4_SMPR_480_CK_CYCLES,
+};
+
+/* STM32F4_ADCX_SQR1 - bit fields */
+#define STM32F4_L_SHIFT                        20
+#define STM32F4_L_MASK                 GENMASK(23, 20)
+#define STM32F4_SQ16_SHIFT             15
+#define STM32F4_SQ16_MASK              GENMASK(19, 15)
+#define STM32F4_SQ15_SHIFT             10
+#define STM32F4_SQ15_MASK              GENMASK(14, 10)
+#define STM32F4_SQ14_SHIFT             5
+#define STM32F4_SQ14_MASK              GENMASK(9, 5)
+#define STM32F4_SQ13_SHIFT             0
+#define STM32F4_SQ13_MASK              GENMASK(4, 0)
+
+/* STM32F4_ADCX_SQR2 - bit fields */
+#define STM32F4_SQ12_SHIFT             25
+#define STM32F4_SQ12_MASK              GENMASK(29, 25)
+#define STM32F4_SQ11_SHIFT             20
+#define STM32F4_SQ11_MASK              GENMASK(24, 20)
+#define STM32F4_SQ10_SHIFT             15
+#define STM32F4_SQ10_MASK              GENMASK(19, 15)
+#define STM32F4_SQ9_SHIFT              10
+#define STM32F4_SQ9_MASK               GENMASK(14, 10)
+#define STM32F4_SQ8_SHIFT              5
+#define STM32F4_SQ8_MASK               GENMASK(9, 5)
+#define STM32F4_SQ7_SHIFT              0
+#define STM32F4_SQ7_MASK               GENMASK(4, 0)
+
+/* STM32F4_ADCX_SQR3 - bit fields */
+#define STM32F4_SQ6_SHIFT              25
+#define STM32F4_SQ6_MASK               GENMASK(29, 25)
+#define STM32F4_SQ5_SHIFT              20
+#define STM32F4_SQ5_MASK               GENMASK(24, 20)
+#define STM32F4_SQ4_SHIFT              15
+#define STM32F4_SQ4_MASK               GENMASK(19, 15)
+#define STM32F4_SQ3_SHIFT              10
+#define STM32F4_SQ3_MASK               GENMASK(14, 10)
+#define STM32F4_SQ2_SHIFT              5
+#define STM32F4_SQ2_MASK               GENMASK(9, 5)
+#define STM32F4_SQ1_SHIFT              0
+#define STM32F4_SQ1_MASK               GENMASK(4, 0)
+
+/* STM32F4_ADCX_JSQR - bit fields */
+#define STM32F4_JL_SHIFT               20
+#define STM32F4_JL_MASK                        GENMASK(21, 20)
+#define STM32F4_JSQ4_SHIFT             15
+#define STM32F4_JSQ4_MASK              GENMASK(19, 15)
+#define STM32F4_JSQ3_SHIFT             10
+#define STM32F4_JSQ3_MASK              GENMASK(14, 10)
+#define STM32F4_JSQ2_SHIFT             5
+#define STM32F4_JSQ2_MASK              GENMASK(9, 5)
+#define STM32F4_JSQ1_SHIFT             0
+#define STM32F4_JSQ1_MASK              GENMASK(4, 0)
+
+/* STM32F4_ADC_CCR - bit fields */
+#define STM32F4_ADC_ADCPRE_SHIFT       16
+#define STM32F4_ADC_ADCPRE_MASK                GENMASK(17, 16)
+
+/*
+ * stm32 ADC1, ADC2 & ADC3 are tightly coupled and may be used in multi mode
+ * Define here all inputs for all ADC instances
+ */
+static const struct stm32_adc_chan_spec stm32f4_adc1_channels[] = {
+       /* master ADC1 */
+       { IIO_VOLTAGE, 0, "in0" },
+       { IIO_VOLTAGE, 1, "in1" },
+       { IIO_VOLTAGE, 2, "in2" },
+       { IIO_VOLTAGE, 3, "in3" },
+       { IIO_VOLTAGE, 4, "in4" },
+       { IIO_VOLTAGE, 5, "in5" },
+       { IIO_VOLTAGE, 6, "in6" },
+       { IIO_VOLTAGE, 7, "in7" },
+       { IIO_VOLTAGE, 8, "in8" },
+       { IIO_VOLTAGE, 9, "in9" },
+       { IIO_VOLTAGE, 10, "in10" },
+       { IIO_VOLTAGE, 11, "in11" },
+       { IIO_VOLTAGE, 12, "in12" },
+       { IIO_VOLTAGE, 13, "in13" },
+       { IIO_VOLTAGE, 14, "in14" },
+       { IIO_VOLTAGE, 15, "in15" },
+       /* internal analog sources available on input 16 to 18 */
+       { IIO_VOLTAGE, 16, "in16" },
+       { IIO_VOLTAGE, 17, "in17" },
+       { IIO_VOLTAGE, 18, "in18" },
+};
+
+static const struct stm32_adc_chan_spec stm32f4_adc23_channels[] = {
+       /* slave ADC2 / ADC3 */
+       { IIO_VOLTAGE, 0, "in0" },
+       { IIO_VOLTAGE, 1, "in1" },
+       { IIO_VOLTAGE, 2, "in2" },
+       { IIO_VOLTAGE, 3, "in3" },
+       { IIO_VOLTAGE, 4, "in4" },
+       { IIO_VOLTAGE, 5, "in5" },
+       { IIO_VOLTAGE, 6, "in6" },
+       { IIO_VOLTAGE, 7, "in7" },
+       { IIO_VOLTAGE, 8, "in8" },
+       { IIO_VOLTAGE, 9, "in9" },
+       { IIO_VOLTAGE, 10, "in10" },
+       { IIO_VOLTAGE, 11, "in11" },
+       { IIO_VOLTAGE, 12, "in12" },
+       { IIO_VOLTAGE, 13, "in13" },
+       { IIO_VOLTAGE, 14, "in14" },
+       { IIO_VOLTAGE, 15, "in15" },
+};
+
+/* Triggers for regular channels */
+static const struct stm32_adc_trig_info stm32f4_adc_ext_triggers[] = {
+       { STM32_EXT0, "TIM1_CH1" },
+       { STM32_EXT1, "TIM1_CH2" },
+       { STM32_EXT2, "TIM1_CH3" },
+       { STM32_EXT3, "TIM2_CH2" },
+       { STM32_EXT4, "TIM2_CH3" },
+       { STM32_EXT5, "TIM2_CH4" },
+       { STM32_EXT6, "TIM2_TRGO" },
+       { STM32_EXT7, "TIM3_CH1" },
+       { STM32_EXT8, "TIM3_TRGO" },
+       { STM32_EXT9, "TIM4_CH4" },
+       { STM32_EXT10, "TIM5_CH1" },
+       { STM32_EXT11, "TIM5_CH2" },
+       { STM32_EXT12, "TIM5_CH3" },
+       { STM32_EXT13, "TIM8_CH1" },
+       { STM32_EXT14, "TIM8_TRGO" },
+       { STM32_EXT15, "EXTI_11" },
+       {},
+};
+
+/* Triggers for injected channels */
+static const struct stm32_adc_trig_info  stm32f4_adc_jext_triggers[] = {
+       { STM32_JEXT0, "TIM1_CH4" },
+       { STM32_JEXT1, "TIM1_TRGO" },
+       { STM32_JEXT2, "TIM2_CH1" },
+       { STM32_JEXT3, "TIM2_TRGO" },
+       { STM32_JEXT4, "TIM3_CH2" },
+       { STM32_JEXT5, "TIM3_CH4" },
+       { STM32_JEXT6, "TIM4_CH1" },
+       { STM32_JEXT7, "TIM4_CH2" },
+       { STM32_JEXT8, "TIM4_CH3" },
+       { STM32_JEXT9, "TIM4_TRGO" },
+       { STM32_JEXT10, "TIM5_CH4" },
+       { STM32_JEXT11, "TIM5_TRGO" },
+       { STM32_JEXT12, "TIM8_CH2" },
+       { STM32_JEXT13, "TIM8_CH3" },
+       { STM32_JEXT14, "TIM8_CH4" },
+       { STM32_JEXT15, "EXTI_15" },
+       {},
+};
+
+static const struct stm32_adc_info stm32f4_adc_info[] = {
+       {
+               .name = "adc1-master",
+               .reg = 0x0,
+               .channels = stm32f4_adc1_channels,
+               .max_channels = ARRAY_SIZE(stm32f4_adc1_channels),
+       },
+       {
+               .name = "adc2-slave",
+               .reg = 0x100,
+               .channels = stm32f4_adc23_channels,
+               .max_channels = ARRAY_SIZE(stm32f4_adc23_channels),
+       },
+       {
+               .name = "adc3-slave",
+               .reg = 0x200,
+               .channels = stm32f4_adc23_channels,
+               .max_channels = ARRAY_SIZE(stm32f4_adc23_channels),
+       },
+       {},
+};
+
+/**
+ * stm32f4_sqr_regs - describe regular sequence registers
+ * - L: sequence len (register & bit field)
+ * - SQ1..SQ16: sequence entries (register & bit field)
+ */
+static const struct stm32_adc_regs stm32f4_sqr_regs[STM32_ADC_MAX_SQ + 1] = {
+       /* L: len bit field description to be kept as first element */
+       { STM32F4_ADCX_SQR1, STM32F4_L_MASK, STM32F4_L_SHIFT },
+       /* SQ1..SQ16 registers & bit fields */
+       { STM32F4_ADCX_SQR3, STM32F4_SQ1_MASK, STM32F4_SQ1_SHIFT },
+       { STM32F4_ADCX_SQR3, STM32F4_SQ2_MASK, STM32F4_SQ2_SHIFT },
+       { STM32F4_ADCX_SQR3, STM32F4_SQ3_MASK, STM32F4_SQ3_SHIFT },
+       { STM32F4_ADCX_SQR3, STM32F4_SQ4_MASK, STM32F4_SQ4_SHIFT },
+       { STM32F4_ADCX_SQR3, STM32F4_SQ5_MASK, STM32F4_SQ5_SHIFT },
+       { STM32F4_ADCX_SQR3, STM32F4_SQ6_MASK, STM32F4_SQ6_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ7_MASK, STM32F4_SQ7_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ8_MASK, STM32F4_SQ8_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ9_MASK, STM32F4_SQ9_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ10_MASK, STM32F4_SQ10_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ11_MASK, STM32F4_SQ11_SHIFT },
+       { STM32F4_ADCX_SQR2, STM32F4_SQ12_MASK, STM32F4_SQ12_SHIFT },
+       { STM32F4_ADCX_SQR1, STM32F4_SQ13_MASK, STM32F4_SQ13_SHIFT },
+       { STM32F4_ADCX_SQR1, STM32F4_SQ14_MASK, STM32F4_SQ14_SHIFT },
+       { STM32F4_ADCX_SQR1, STM32F4_SQ15_MASK, STM32F4_SQ15_SHIFT },
+       { STM32F4_ADCX_SQR1, STM32F4_SQ16_MASK, STM32F4_SQ16_SHIFT },
+};
+
+/**
+ * stm32f4_jsqr_reg - 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_jsqr_reg[STM32_ADC_MAX_JSQ + 1] = {
+       /* JL: len bit field description to be kept as first element */
+       {STM32F4_ADCX_JSQR, STM32F4_JL_MASK, STM32F4_JL_SHIFT},
+       /* JSQ4..JSQ1 registers & bit fields */
+       {STM32F4_ADCX_JSQR, STM32F4_JSQ4_MASK, STM32F4_JSQ4_SHIFT},
+       {STM32F4_ADCX_JSQR, STM32F4_JSQ3_MASK, STM32F4_JSQ3_SHIFT},
+       {STM32F4_ADCX_JSQR, STM32F4_JSQ2_MASK, STM32F4_JSQ2_SHIFT},
+       {STM32F4_ADCX_JSQR, STM32F4_JSQ1_MASK, STM32F4_JSQ1_SHIFT},
+};
+
+static const struct stm32_adc_trig_reginfo stm32f4_adc_trig_reginfo = {
+       .reg = STM32F4_ADCX_CR2,
+       .exten_mask = STM32F4_EXTEN_MASK,
+       .exten_shift = STM32F4_EXTEN_SHIFT,
+       .extsel_mask = STM32F4_EXTSEL_MASK,
+       .extsel_shift = STM32F4_EXTSEL_SHIFT,
+};
+
+static const struct stm32_adc_trig_reginfo stm32f4_adc_jtrig_reginfo = {
+       .reg = STM32F4_ADCX_CR2,
+       .exten_mask = STM32F4_JEXTEN_MASK,
+       .exten_shift = STM32F4_JEXTEN_SHIFT,
+       .extsel_mask = STM32F4_JEXTSEL_MASK,
+       .extsel_shift = STM32F4_JEXTSEL_SHIFT,
+};
+
+static const struct stm32_adc_reginfo stm32f4_adc_reginfo = {
+       .isr = STM32F4_ADCX_SR,
+       .eoc = STM32F4_EOC,
+       .jeoc = STM32F4_JEOC,
+       .ier = STM32F4_ADCX_CR1,
+       .eocie = STM32F4_EOCIE,
+       .jeocie = STM32F4_JEOCIE,
+       .dr = STM32F4_ADCX_DR,
+       .jdr = {
+               STM32F4_ADCX_JDR1,
+               STM32F4_ADCX_JDR2,
+               STM32F4_ADCX_JDR3,
+               STM32F4_ADCX_JDR4,
+       },
+       .sqr_regs = stm32f4_sqr_regs,
+       .jsqr_reg = stm32f4_jsqr_reg,
+       .trig_reginfo = &stm32f4_adc_trig_reginfo,
+       .jtrig_reginfo = &stm32f4_adc_jtrig_reginfo,
+};
+
+static bool stm32f4_adc_is_started(struct stm32_adc *adc)
+{
+       u32 val = stm32_adc_readl(adc, STM32F4_ADCX_CR2) & STM32F4_ADON;
+
+       return !!val;
+}
+
+static bool stm32f4_adc_regular_started(struct stm32_adc *adc)
+{
+       u32 val = stm32_adc_readl(adc, STM32F4_ADCX_SR) & STM32F4_STRT;
+
+       return !!val;
+}
+
+static bool stm32f4_adc_injected_started(struct stm32_adc *adc)
+{
+       u32 val = stm32_adc_readl(adc, STM32F4_ADCX_SR) & STM32F4_JSTRT;
+
+       return !!val;
+}
+
+/**
+ * stm32f4_adc_start_conv() - Start regular or injected conversions
+ * @adc: stm32 adc instance
+ *
+ * Start single conversions for regular or injected channels.
+ */
+static int stm32f4_adc_start_conv(struct stm32_adc *adc)
+{
+       u32 trig_msk, start_msk;
+
+       dev_dbg(adc->common->dev, "%s %s\n", __func__,
+               adc->injected ? "injected" : "regular");
+
+       stm32_adc_set_bits(adc, STM32F4_ADCX_CR1, STM32F4_SCAN);
+
+       if (!stm32f4_adc_is_started(adc)) {
+               stm32_adc_set_bits(adc, STM32F4_ADCX_CR2,
+                                  STM32F4_EOCS | STM32F4_ADON);
+
+               /* 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_ADCX_CR2) & trig_msk))
+               stm32_adc_set_bits(adc, STM32F4_ADCX_CR2, start_msk);
+
+       return 0;
+}
+
+static int stm32f4_adc_stop_conv(struct stm32_adc *adc)
+{
+       u32 val;
+
+       dev_dbg(adc->common->dev, "%s %s\n", __func__,
+               adc->injected ? "injected" : "regular");
+
+       /* First disable trigger for either regular or injected channels */
+       if (adc->injected) {
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_CR2, STM32F4_JEXTEN_MASK);
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_SR, STM32F4_JSTRT);
+       } else {
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_CR2, STM32F4_EXTEN_MASK);
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_SR, STM32F4_STRT);
+       }
+
+       /* Disable adc when all triggered conversion have been disabled */
+       val = stm32_adc_readl(adc, STM32F4_ADCX_CR2);
+       val &= STM32F4_EXTEN_MASK | STM32F4_JEXTEN_MASK;
+       if (!val) {
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_CR1, STM32F4_SCAN);
+               stm32_adc_clr_bits(adc, STM32F4_ADCX_CR2, STM32F4_ADON);
+       }
+
+       return 0;
+}
+
+/* ADC internal common clock prescaler division ratios */
+static int stm32f4_pclk_div[] = {2, 4, 6, 8};
+
+/**
+ * stm32f4_adc_clk_sel() - Select ADC common clock prescaler
+ * @adc: stm32 adc instance
+ * Select clock prescaler used for analog conversions.
+ */
+static int stm32f4_adc_clk_sel(struct stm32_adc *adc)
+{
+       struct stm32_adc_common *common = adc->common;
+       unsigned long rate;
+       u32 val;
+       int i;
+
+       /* Common prescaler is set only once, when 1st ADC instance starts */
+       list_for_each_entry(adc, &common->adc_list, adc_list)
+               if (stm32f4_adc_is_started(adc))
+                       return 0;
+
+       rate = clk_get_rate(common->aclk);
+       for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
+               if ((rate / stm32f4_pclk_div[i]) <=
+                   common->data->max_clock_rate)
+                       break;
+       }
+       if (i >= ARRAY_SIZE(stm32f4_pclk_div))
+               return -EINVAL;
+
+       val = stm32_adc_common_readl(common, STM32F4_ADC_CCR);
+       val &= ~STM32F4_ADC_ADCPRE_MASK;
+       val |= i << STM32F4_ADC_ADCPRE_SHIFT;
+       stm32_adc_common_writel(common, STM32F4_ADC_CCR, val);
+
+       dev_dbg(common->dev, "Using analog clock source at %ld kHz\n",
+               rate / (stm32f4_pclk_div[i] * 1000));
+
+       return 0;
+}
+
+static const struct stm32_adc_ops stm32f4_adc_ops = {
+       .adc_info = stm32f4_adc_info,
+       .ext_triggers = stm32f4_adc_ext_triggers,
+       .jext_triggers = stm32f4_adc_jext_triggers,
+       .adc_reginfo = &stm32f4_adc_reginfo,
+       .highres = 12,
+       .max_clock_rate = 36000000,
+       .clk_sel = stm32f4_adc_clk_sel,
+       .start_conv = stm32f4_adc_start_conv,
+       .stop_conv = stm32f4_adc_stop_conv,
+       .is_started = stm32f4_adc_is_started,
+       .regular_started = stm32f4_adc_regular_started,
+       .injected_started = stm32f4_adc_injected_started,
+};
+
+static const struct of_device_id stm32f4_adc_of_match[] = {
+       { .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_ops},
+       {},
+};
+MODULE_DEVICE_TABLE(of, stm32f4_adc_of_match);
+
+static struct platform_driver stm32f4_adc_driver = {
+       .probe = stm32_adc_probe,
+       .remove = stm32_adc_remove,
+       .driver = {
+               .name = "stm32f4-adc",
+               .of_match_table = stm32f4_adc_of_match,
+       },
+};
+
+module_platform_driver(stm32f4_adc_driver);
+
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasn...@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32F4 ADC driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

Reply via email to