STM32 ADC may use EXTi signals routed internally as trigger source
for conversions. Configure them as interrupt to configure this path
in HW to adc.
Note: interrupt handler isn't required here, and corresponding interrupt
can be kept masked at exti controller level.

Signed-off-by: Fabrice Gasnier <fabrice.gasn...@st.com>
---
 drivers/iio/adc/stm32/stm32-adc.c | 45 +++++++++++++++++++++++++++++++++++++++
 drivers/iio/adc/stm32/stm32-adc.h |  3 +++
 2 files changed, 48 insertions(+)

diff --git a/drivers/iio/adc/stm32/stm32-adc.c 
b/drivers/iio/adc/stm32/stm32-adc.c
index 25d0307..1a13450 100644
--- a/drivers/iio/adc/stm32/stm32-adc.c
+++ b/drivers/iio/adc/stm32/stm32-adc.c
@@ -482,6 +482,12 @@ static irqreturn_t stm32_adc_common_isr(int irq, void 
*data)
        return ret;
 }
 
+static irqreturn_t stm32_adc_exti_handler(int irq, void *data)
+{
+       /* Exti handler should not be invoqued, and is not used */
+       return IRQ_HANDLED;
+}
+
 /**
  * stm32_adc_validate_trigger() - validate trigger for stm32 adc
  * @indio_dev: IIO device
@@ -1051,6 +1057,41 @@ static void stm32_adc_unregister(struct stm32_adc *adc)
        }
 }
 
+static int stm32_adc_exti_probe(struct stm32_adc_common *common)
+{
+       int i, irq, ret;
+
+       common->gpios = devm_gpiod_get_array_optional(common->dev, NULL,
+                                                     GPIOD_IN);
+       if (!common->gpios)
+               return 0;
+
+       for (i = 0; i < common->gpios->ndescs; i++) {
+               irq = gpiod_to_irq(common->gpios->desc[i]);
+               if (irq < 0) {
+                       dev_err(common->dev, "gpio %d to irq failed\n", i);
+                       return irq;
+               }
+
+               ret = devm_request_irq(common->dev, irq, stm32_adc_exti_handler,
+                                      0, dev_name(common->dev), common);
+               if (ret) {
+                       dev_err(common->dev, "request IRQ %d failed\n", irq);
+                       return ret;
+               }
+
+               /*
+                * gpios are configured as interrupts, so exti trigger path is
+                * configured in HW. But getting interrupts when starting
+                * conversions is unused here, so mask it in on exti
+                * controller by default.
+                */
+               disable_irq(irq);
+       }
+
+       return 0;
+}
+
 int stm32_adc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node, *child;
@@ -1131,6 +1172,10 @@ int stm32_adc_probe(struct platform_device *pdev)
                goto err_clk_disable;
        }
 
+       ret = stm32_adc_exti_probe(common);
+       if (ret)
+               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);
diff --git a/drivers/iio/adc/stm32/stm32-adc.h 
b/drivers/iio/adc/stm32/stm32-adc.h
index 01a0dda..fe3568b 100644
--- a/drivers/iio/adc/stm32/stm32-adc.h
+++ b/drivers/iio/adc/stm32/stm32-adc.h
@@ -23,6 +23,7 @@
 #define __STM32_ADC_H
 
 #include <linux/dmaengine.h>
+#include <linux/gpio/consumer.h>
 #include <linux/irq_work.h>
 
 /*
@@ -323,6 +324,7 @@ struct stm32_adc {
  * @aclk:              common clock for the analog circuitry
  * @vref:              regulator reference
  * @vref_mv:           vref voltage (mv)
+ * @gpio_descs:                gpio descriptor used to configure EXTi triggers
  * @lock:              mutex
  */
 struct stm32_adc_common {
@@ -335,6 +337,7 @@ struct stm32_adc_common {
        struct clk                      *aclk;
        struct regulator                *vref;
        int                             vref_mv;
+       struct gpio_descs               *gpios;
        struct mutex                    lock;   /* read_raw lock */
 };
 
-- 
1.9.1

Reply via email to