linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode
@ 2017-02-15 19:31 Heiner Kallweit
  2017-02-19 11:54 ` Martin Blumenstingl
  2017-02-19 12:19 ` Jonathan Cameron
  0 siblings, 2 replies; 5+ messages in thread
From: Heiner Kallweit @ 2017-02-15 19:31 UTC (permalink / raw)
  To: Jonathan Cameron, Martin Blumenstingl
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio

Switch from polling to interrupt mode.

Successfully tested on a S905GXBB-based Odroid C2.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
v2:
- move enabling / disabling irq to meson_sar_adc_start_sample_engine /
  meson_sar_adc_stop_sample_engine respectively
- move setting FIFO threshold for irq triggering to meson_sar_adc_hw_enable
  to avoid a potential issue when uboot should be involved in system resume
- return IRQ_NONE if the interrupt can't be for us
- document interrupts property in DT documentation
---
 .../bindings/iio/adc/amlogic,meson-saradc.txt      |  2 +
 drivers/iio/adc/meson_saradc.c                     | 56 ++++++++++++++++++++--
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
index f9e3ff2c..04718919 100644
--- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
@@ -7,6 +7,7 @@ Required properties:
 			- "amlogic,meson-gxm-saradc" for GXM
 		along with the generic "amlogic,meson-saradc"
 - reg:		the physical base address and length of the registers
+- interrupts:	the interrupt indicating end of sampling
 - clocks:	phandle and clock identifier (see clock-names)
 - clock-names:	mandatory clocks:
 			- "clkin" for the reference clock (typically XTAL)
@@ -23,6 +24,7 @@ Example:
 		compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
 		#io-channel-cells = <1>;
 		reg = <0x0 0x8680 0x0 0x34>;
+		interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
 		clocks = <&xtal>,
 			 <&clkc CLKID_SAR_ADC>,
 			 <&clkc CLKID_SANA>,
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index 89def603..9f186de2 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -18,7 +18,9 @@
 #include <linux/io.h>
 #include <linux/iio/iio.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -163,6 +165,7 @@
 	#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK	GENMASK(13, 8)
 
 #define MESON_SAR_ADC_MAX_FIFO_SIZE				32
+#define MESON_SAR_ADC_TIMEOUT					100 /* ms */
 
 #define MESON_SAR_ADC_CHAN(_chan) {					\
 	.type = IIO_VOLTAGE,						\
@@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
 	struct clk_gate				clk_gate;
 	struct clk				*adc_div_clk;
 	struct clk_divider			clk_div;
+	struct completion			done;
 };
 
 static const struct regmap_config meson_sar_adc_regmap_config = {
@@ -274,11 +278,11 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
 					 int *val)
 {
 	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
-	int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
+	int regval, fifo_chan, fifo_val, sum = 0, count = 0;
 
-	ret = meson_sar_adc_wait_busy_clear(indio_dev);
-	if (ret)
-		return ret;
+	if(!wait_for_completion_timeout(&priv->done,
+				msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
+		return -ETIMEDOUT;
 
 	while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
 	       count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
@@ -378,6 +382,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
 {
 	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
 
+	reinit_completion(&priv->done);
+
+	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
+			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
+
 	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
 			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
 			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
@@ -392,6 +402,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
 	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
 
 	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
+
+	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
 			   MESON_SAR_ADC_REG0_SAMPLING_STOP,
 			   MESON_SAR_ADC_REG0_SAMPLING_STOP);
 
@@ -643,6 +656,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
 {
 	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
 	int ret;
+	u32 regval;
 
 	ret = meson_sar_adc_lock(indio_dev);
 	if (ret)
@@ -667,6 +681,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
 		goto err_sana_clk;
 	}
 
+	regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
+	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
+			   MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
 	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
 			   MESON_SAR_ADC_REG11_BANDGAP_EN,
 			   MESON_SAR_ADC_REG11_BANDGAP_EN);
@@ -728,6 +745,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
 	return 0;
 }
 
+static irqreturn_t meson_sar_adc_irq(int irq, void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
+	unsigned int cnt, threshold;
+	u32 regval;
+
+	regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
+	cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
+	threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
+
+	if (cnt < threshold)
+		return IRQ_NONE;
+
+	complete(&priv->done);
+
+	return IRQ_HANDLED;
+}
+
 static const struct iio_info meson_sar_adc_iio_info = {
 	.read_raw = meson_sar_adc_iio_info_read_raw,
 	.driver_module = THIS_MODULE,
@@ -770,7 +806,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
 	struct resource *res;
 	void __iomem *base;
 	const struct of_device_id *match;
-	int ret;
+	int irq, ret;
 
 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
 	if (!indio_dev) {
@@ -779,6 +815,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
 	}
 
 	priv = iio_priv(indio_dev);
+	init_completion(&priv->done);
 
 	match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
 	priv->data = match->data;
@@ -797,6 +834,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
+	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	if (!irq)
+		return -EINVAL;
+
+	ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
+			       dev_name(&pdev->dev), indio_dev);
+	if (ret)
+		return ret;
+
 	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 					     &meson_sar_adc_regmap_config);
 	if (IS_ERR(priv->regmap))
-- 
2.11.1



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode
  2017-02-15 19:31 [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode Heiner Kallweit
@ 2017-02-19 11:54 ` Martin Blumenstingl
  2017-02-19 12:19 ` Jonathan Cameron
  1 sibling, 0 replies; 5+ messages in thread
From: Martin Blumenstingl @ 2017-02-19 11:54 UTC (permalink / raw)
  To: Heiner Kallweit
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio

On Wed, Feb 15, 2017 at 8:31 PM, Heiner Kallweit <hkallweit1@gmail.com> wrote:
> Switch from polling to interrupt mode.
>
> Successfully tested on a S905GXBB-based Odroid C2.
>
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

(tested on Khadas VIM board, which uses a S905X / GXL SoC)
one minor comment inline below

> ---
> v2:
> - move enabling / disabling irq to meson_sar_adc_start_sample_engine /
>   meson_sar_adc_stop_sample_engine respectively
> - move setting FIFO threshold for irq triggering to meson_sar_adc_hw_enable
>   to avoid a potential issue when uboot should be involved in system resume
> - return IRQ_NONE if the interrupt can't be for us
> - document interrupts property in DT documentation
> ---
>  .../bindings/iio/adc/amlogic,meson-saradc.txt      |  2 +
>  drivers/iio/adc/meson_saradc.c                     | 56 ++++++++++++++++++++--
>  2 files changed, 53 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> index f9e3ff2c..04718919 100644
> --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> @@ -7,6 +7,7 @@ Required properties:
>                         - "amlogic,meson-gxm-saradc" for GXM
>                 along with the generic "amlogic,meson-saradc"
>  - reg:         the physical base address and length of the registers
> +- interrupts:  the interrupt indicating end of sampling
>  - clocks:      phandle and clock identifier (see clock-names)
>  - clock-names: mandatory clocks:
>                         - "clkin" for the reference clock (typically XTAL)
> @@ -23,6 +24,7 @@ Example:
>                 compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
>                 #io-channel-cells = <1>;
>                 reg = <0x0 0x8680 0x0 0x34>;
> +               interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
>                 clocks = <&xtal>,
>                          <&clkc CLKID_SAR_ADC>,
>                          <&clkc CLKID_SANA>,
> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
> index 89def603..9f186de2 100644
> --- a/drivers/iio/adc/meson_saradc.c
> +++ b/drivers/iio/adc/meson_saradc.c
> @@ -18,7 +18,9 @@
>  #include <linux/io.h>
>  #include <linux/iio/iio.h>
>  #include <linux/module.h>
> +#include <linux/interrupt.h>
>  #include <linux/of.h>
> +#include <linux/of_irq.h>
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -163,6 +165,7 @@
>         #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK      GENMASK(13, 8)
>
>  #define MESON_SAR_ADC_MAX_FIFO_SIZE                            32
> +#define MESON_SAR_ADC_TIMEOUT                                  100 /* ms */
>
>  #define MESON_SAR_ADC_CHAN(_chan) {                                    \
>         .type = IIO_VOLTAGE,                                            \
> @@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
>         struct clk_gate                         clk_gate;
>         struct clk                              *adc_div_clk;
>         struct clk_divider                      clk_div;
> +       struct completion                       done;
>  };
>
>  static const struct regmap_config meson_sar_adc_regmap_config = {
> @@ -274,11 +278,11 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
>                                          int *val)
>  {
>         struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> -       int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
> +       int regval, fifo_chan, fifo_val, sum = 0, count = 0;
>
> -       ret = meson_sar_adc_wait_busy_clear(indio_dev);
> -       if (ret)
> -               return ret;
> +       if(!wait_for_completion_timeout(&priv->done,
> +                               msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
> +               return -ETIMEDOUT;
>
>         while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
>                count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
> @@ -378,6 +382,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
>  {
>         struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>
> +       reinit_completion(&priv->done);
> +
> +       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +                          MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
> +                          MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
> +
>         regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>                            MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
>                            MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
> @@ -392,6 +402,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
>         struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>
>         regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +                          MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
> +
> +       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>                            MESON_SAR_ADC_REG0_SAMPLING_STOP,
>                            MESON_SAR_ADC_REG0_SAMPLING_STOP);
>
> @@ -643,6 +656,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>  {
>         struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>         int ret;
> +       u32 regval;
>
>         ret = meson_sar_adc_lock(indio_dev);
>         if (ret)
> @@ -667,6 +681,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>                 goto err_sana_clk;
>         }
>
> +       regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
> +       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +                          MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>         regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
>                            MESON_SAR_ADC_REG11_BANDGAP_EN,
>                            MESON_SAR_ADC_REG11_BANDGAP_EN);
> @@ -728,6 +745,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
>         return 0;
>  }
>
> +static irqreturn_t meson_sar_adc_irq(int irq, void *data)
> +{
> +       struct iio_dev *indio_dev = data;
> +       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +       unsigned int cnt, threshold;
> +       u32 regval;
> +
> +       regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
> +       cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
this could be replaced with a call to meson_sar_adc_get_fifo_count(),
but I guess you wanted to avoid two reads of the MESON_SAR_ADC_REG0.
I'm fine with either way though.

> +       threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
> +
> +       if (cnt < threshold)
> +               return IRQ_NONE;
> +
> +       complete(&priv->done);
> +
> +       return IRQ_HANDLED;
> +}
> +
>  static const struct iio_info meson_sar_adc_iio_info = {
>         .read_raw = meson_sar_adc_iio_info_read_raw,
>         .driver_module = THIS_MODULE,
> @@ -770,7 +806,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>         struct resource *res;
>         void __iomem *base;
>         const struct of_device_id *match;
> -       int ret;
> +       int irq, ret;
>
>         indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
>         if (!indio_dev) {
> @@ -779,6 +815,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>         }
>
>         priv = iio_priv(indio_dev);
> +       init_completion(&priv->done);
>
>         match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
>         priv->data = match->data;
> @@ -797,6 +834,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>         if (IS_ERR(base))
>                 return PTR_ERR(base);
>
> +       irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +       if (!irq)
> +               return -EINVAL;
> +
> +       ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
> +                              dev_name(&pdev->dev), indio_dev);
> +       if (ret)
> +               return ret;
> +
>         priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>                                              &meson_sar_adc_regmap_config);
>         if (IS_ERR(priv->regmap))
> --
> 2.11.1
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode
  2017-02-15 19:31 [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode Heiner Kallweit
  2017-02-19 11:54 ` Martin Blumenstingl
@ 2017-02-19 12:19 ` Jonathan Cameron
  2017-02-19 12:37   ` Martin Blumenstingl
  1 sibling, 1 reply; 5+ messages in thread
From: Jonathan Cameron @ 2017-02-19 12:19 UTC (permalink / raw)
  To: Heiner Kallweit, Martin Blumenstingl
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio

On 15/02/17 19:31, Heiner Kallweit wrote:
> Switch from polling to interrupt mode.
> 
> Successfully tested on a S905GXBB-based Odroid C2.
> 
> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Looks like a nice change to me.  I'll wait on Martin taking another look though
before applying it.

One question that came up wrt to a similar change in another driver the other
day, are there any reasons why we might not want to use the IRQ and hence preserve
the existing polled approach? On the other device it turned out there was a limit on
the number of interrupts that could be enabled simultaneously so there might be cases
where the ADC was unimportant and they'd elect to do it without the interrupt.  

I have no idea what the situation is here so thought I'd just ask!

Jonathan
> ---
> v2:
> - move enabling / disabling irq to meson_sar_adc_start_sample_engine /
>   meson_sar_adc_stop_sample_engine respectively
> - move setting FIFO threshold for irq triggering to meson_sar_adc_hw_enable
>   to avoid a potential issue when uboot should be involved in system resume
> - return IRQ_NONE if the interrupt can't be for us
> - document interrupts property in DT documentation
> ---
>  .../bindings/iio/adc/amlogic,meson-saradc.txt      |  2 +
>  drivers/iio/adc/meson_saradc.c                     | 56 ++++++++++++++++++++--
>  2 files changed, 53 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> index f9e3ff2c..04718919 100644
> --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> @@ -7,6 +7,7 @@ Required properties:
>  			- "amlogic,meson-gxm-saradc" for GXM
>  		along with the generic "amlogic,meson-saradc"
>  - reg:		the physical base address and length of the registers
> +- interrupts:	the interrupt indicating end of sampling
>  - clocks:	phandle and clock identifier (see clock-names)
>  - clock-names:	mandatory clocks:
>  			- "clkin" for the reference clock (typically XTAL)
> @@ -23,6 +24,7 @@ Example:
>  		compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
>  		#io-channel-cells = <1>;
>  		reg = <0x0 0x8680 0x0 0x34>;
> +		interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
>  		clocks = <&xtal>,
>  			 <&clkc CLKID_SAR_ADC>,
>  			 <&clkc CLKID_SANA>,
> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
> index 89def603..9f186de2 100644
> --- a/drivers/iio/adc/meson_saradc.c
> +++ b/drivers/iio/adc/meson_saradc.c
> @@ -18,7 +18,9 @@
>  #include <linux/io.h>
>  #include <linux/iio/iio.h>
>  #include <linux/module.h>
> +#include <linux/interrupt.h>
>  #include <linux/of.h>
> +#include <linux/of_irq.h>
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -163,6 +165,7 @@
>  	#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK	GENMASK(13, 8)
>  
>  #define MESON_SAR_ADC_MAX_FIFO_SIZE				32
> +#define MESON_SAR_ADC_TIMEOUT					100 /* ms */
>  
>  #define MESON_SAR_ADC_CHAN(_chan) {					\
>  	.type = IIO_VOLTAGE,						\
> @@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
>  	struct clk_gate				clk_gate;
>  	struct clk				*adc_div_clk;
>  	struct clk_divider			clk_div;
> +	struct completion			done;
>  };
>  
>  static const struct regmap_config meson_sar_adc_regmap_config = {
> @@ -274,11 +278,11 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
>  					 int *val)
>  {
>  	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> -	int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
> +	int regval, fifo_chan, fifo_val, sum = 0, count = 0;
>  
> -	ret = meson_sar_adc_wait_busy_clear(indio_dev);
> -	if (ret)
> -		return ret;
> +	if(!wait_for_completion_timeout(&priv->done,
> +				msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
> +		return -ETIMEDOUT;
>  
>  	while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
>  	       count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
> @@ -378,6 +382,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
>  {
>  	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>  
> +	reinit_completion(&priv->done);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
> +			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
> +
>  	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>  			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
>  			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
> @@ -392,6 +402,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
>  	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>  
>  	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>  			   MESON_SAR_ADC_REG0_SAMPLING_STOP,
>  			   MESON_SAR_ADC_REG0_SAMPLING_STOP);
>  
> @@ -643,6 +656,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>  {
>  	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>  	int ret;
> +	u32 regval;
>  
>  	ret = meson_sar_adc_lock(indio_dev);
>  	if (ret)
> @@ -667,6 +681,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>  		goto err_sana_clk;
>  	}
>  
> +	regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>  	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
>  			   MESON_SAR_ADC_REG11_BANDGAP_EN,
>  			   MESON_SAR_ADC_REG11_BANDGAP_EN);
> @@ -728,6 +745,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
>  	return 0;
>  }
>  
> +static irqreturn_t meson_sar_adc_irq(int irq, void *data)
> +{
> +	struct iio_dev *indio_dev = data;
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	unsigned int cnt, threshold;
> +	u32 regval;
> +
> +	regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
> +	cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
> +	threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
> +
> +	if (cnt < threshold)
> +		return IRQ_NONE;
> +
> +	complete(&priv->done);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  static const struct iio_info meson_sar_adc_iio_info = {
>  	.read_raw = meson_sar_adc_iio_info_read_raw,
>  	.driver_module = THIS_MODULE,
> @@ -770,7 +806,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>  	struct resource *res;
>  	void __iomem *base;
>  	const struct of_device_id *match;
> -	int ret;
> +	int irq, ret;
>  
>  	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
>  	if (!indio_dev) {
> @@ -779,6 +815,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>  	}
>  
>  	priv = iio_priv(indio_dev);
> +	init_completion(&priv->done);
>  
>  	match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
>  	priv->data = match->data;
> @@ -797,6 +834,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>  	if (IS_ERR(base))
>  		return PTR_ERR(base);
>  
> +	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +	if (!irq)
> +		return -EINVAL;
> +
> +	ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
> +			       dev_name(&pdev->dev), indio_dev);
> +	if (ret)
> +		return ret;
> +
>  	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>  					     &meson_sar_adc_regmap_config);
>  	if (IS_ERR(priv->regmap))
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode
  2017-02-19 12:19 ` Jonathan Cameron
@ 2017-02-19 12:37   ` Martin Blumenstingl
  2017-02-19 12:53     ` Jonathan Cameron
  0 siblings, 1 reply; 5+ messages in thread
From: Martin Blumenstingl @ 2017-02-19 12:37 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Heiner Kallweit, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio

On Sun, Feb 19, 2017 at 1:19 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> On 15/02/17 19:31, Heiner Kallweit wrote:
>> Switch from polling to interrupt mode.
>>
>> Successfully tested on a S905GXBB-based Odroid C2.
>>
>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
> Looks like a nice change to me.  I'll wait on Martin taking another look though
> before applying it.
I sent my ACK and Tested-By just a few minutes before you sent this
email - so consider this done!

> One question that came up wrt to a similar change in another driver the other
> day, are there any reasons why we might not want to use the IRQ and hence preserve
> the existing polled approach? On the other device it turned out there was a limit on
> the number of interrupts that could be enabled simultaneously so there might be cases
> where the ADC was unimportant and they'd elect to do it without the interrupt.
>
> I have no idea what the situation is here so thought I'd just ask!
interesting question - the SoCs are using an ARM CoreLink GIC-400
interrupt controller.
I could not find a limit for the "maximum number of (simultaneously)
enabled interrupts" though (all I could find was a limit of "maximum
number of interrupt sources/IDs", about which the S905 datasheet page
88 says: "There are 224 interrupt sources in the chip.")

> Jonathan
>> ---
>> v2:
>> - move enabling / disabling irq to meson_sar_adc_start_sample_engine /
>>   meson_sar_adc_stop_sample_engine respectively
>> - move setting FIFO threshold for irq triggering to meson_sar_adc_hw_enable
>>   to avoid a potential issue when uboot should be involved in system resume
>> - return IRQ_NONE if the interrupt can't be for us
>> - document interrupts property in DT documentation
>> ---
>>  .../bindings/iio/adc/amlogic,meson-saradc.txt      |  2 +
>>  drivers/iio/adc/meson_saradc.c                     | 56 ++++++++++++++++++++--
>>  2 files changed, 53 insertions(+), 5 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>> index f9e3ff2c..04718919 100644
>> --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>> +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>> @@ -7,6 +7,7 @@ Required properties:
>>                       - "amlogic,meson-gxm-saradc" for GXM
>>               along with the generic "amlogic,meson-saradc"
>>  - reg:               the physical base address and length of the registers
>> +- interrupts:        the interrupt indicating end of sampling
>>  - clocks:    phandle and clock identifier (see clock-names)
>>  - clock-names:       mandatory clocks:
>>                       - "clkin" for the reference clock (typically XTAL)
>> @@ -23,6 +24,7 @@ Example:
>>               compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
>>               #io-channel-cells = <1>;
>>               reg = <0x0 0x8680 0x0 0x34>;
>> +             interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
>>               clocks = <&xtal>,
>>                        <&clkc CLKID_SAR_ADC>,
>>                        <&clkc CLKID_SANA>,
>> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
>> index 89def603..9f186de2 100644
>> --- a/drivers/iio/adc/meson_saradc.c
>> +++ b/drivers/iio/adc/meson_saradc.c
>> @@ -18,7 +18,9 @@
>>  #include <linux/io.h>
>>  #include <linux/iio/iio.h>
>>  #include <linux/module.h>
>> +#include <linux/interrupt.h>
>>  #include <linux/of.h>
>> +#include <linux/of_irq.h>
>>  #include <linux/of_device.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/regmap.h>
>> @@ -163,6 +165,7 @@
>>       #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK      GENMASK(13, 8)
>>
>>  #define MESON_SAR_ADC_MAX_FIFO_SIZE                          32
>> +#define MESON_SAR_ADC_TIMEOUT                                        100 /* ms */
>>
>>  #define MESON_SAR_ADC_CHAN(_chan) {                                  \
>>       .type = IIO_VOLTAGE,                                            \
>> @@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
>>       struct clk_gate                         clk_gate;
>>       struct clk                              *adc_div_clk;
>>       struct clk_divider                      clk_div;
>> +     struct completion                       done;
>>  };
>>
>>  static const struct regmap_config meson_sar_adc_regmap_config = {
>> @@ -274,11 +278,11 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
>>                                        int *val)
>>  {
>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>> -     int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
>> +     int regval, fifo_chan, fifo_val, sum = 0, count = 0;
>>
>> -     ret = meson_sar_adc_wait_busy_clear(indio_dev);
>> -     if (ret)
>> -             return ret;
>> +     if(!wait_for_completion_timeout(&priv->done,
>> +                             msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
>> +             return -ETIMEDOUT;
>>
>>       while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
>>              count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
>> @@ -378,6 +382,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
>>  {
>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>
>> +     reinit_completion(&priv->done);
>> +
>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
>> +
>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>                          MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
>>                          MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
>> @@ -392,6 +402,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>
>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
>> +
>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>                          MESON_SAR_ADC_REG0_SAMPLING_STOP,
>>                          MESON_SAR_ADC_REG0_SAMPLING_STOP);
>>
>> @@ -643,6 +656,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>>  {
>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>       int ret;
>> +     u32 regval;
>>
>>       ret = meson_sar_adc_lock(indio_dev);
>>       if (ret)
>> @@ -667,6 +681,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>>               goto err_sana_clk;
>>       }
>>
>> +     regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>> +                        MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
>>                          MESON_SAR_ADC_REG11_BANDGAP_EN,
>>                          MESON_SAR_ADC_REG11_BANDGAP_EN);
>> @@ -728,6 +745,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
>>       return 0;
>>  }
>>
>> +static irqreturn_t meson_sar_adc_irq(int irq, void *data)
>> +{
>> +     struct iio_dev *indio_dev = data;
>> +     struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>> +     unsigned int cnt, threshold;
>> +     u32 regval;
>> +
>> +     regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
>> +     cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
>> +     threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>> +
>> +     if (cnt < threshold)
>> +             return IRQ_NONE;
>> +
>> +     complete(&priv->done);
>> +
>> +     return IRQ_HANDLED;
>> +}
>> +
>>  static const struct iio_info meson_sar_adc_iio_info = {
>>       .read_raw = meson_sar_adc_iio_info_read_raw,
>>       .driver_module = THIS_MODULE,
>> @@ -770,7 +806,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>       struct resource *res;
>>       void __iomem *base;
>>       const struct of_device_id *match;
>> -     int ret;
>> +     int irq, ret;
>>
>>       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
>>       if (!indio_dev) {
>> @@ -779,6 +815,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>       }
>>
>>       priv = iio_priv(indio_dev);
>> +     init_completion(&priv->done);
>>
>>       match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
>>       priv->data = match->data;
>> @@ -797,6 +834,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>       if (IS_ERR(base))
>>               return PTR_ERR(base);
>>
>> +     irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>> +     if (!irq)
>> +             return -EINVAL;
>> +
>> +     ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
>> +                            dev_name(&pdev->dev), indio_dev);
>> +     if (ret)
>> +             return ret;
>> +
>>       priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>>                                            &meson_sar_adc_regmap_config);
>>       if (IS_ERR(priv->regmap))
>>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode
  2017-02-19 12:37   ` Martin Blumenstingl
@ 2017-02-19 12:53     ` Jonathan Cameron
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2017-02-19 12:53 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: Heiner Kallweit, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio

On 19/02/17 12:37, Martin Blumenstingl wrote:
> On Sun, Feb 19, 2017 at 1:19 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>> On 15/02/17 19:31, Heiner Kallweit wrote:
>>> Switch from polling to interrupt mode.
>>>
>>> Successfully tested on a S905GXBB-based Odroid C2.
>>>
>>> Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
>> Looks like a nice change to me.  I'll wait on Martin taking another look though
>> before applying it.
> I sent my ACK and Tested-By just a few minutes before you sent this
> email - so consider this done!
Cool. Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.
> 
>> One question that came up wrt to a similar change in another driver the other
>> day, are there any reasons why we might not want to use the IRQ and hence preserve
>> the existing polled approach? On the other device it turned out there was a limit on
>> the number of interrupts that could be enabled simultaneously so there might be cases
>> where the ADC was unimportant and they'd elect to do it without the interrupt.
>>
>> I have no idea what the situation is here so thought I'd just ask!
> interesting question - the SoCs are using an ARM CoreLink GIC-400
> interrupt controller.
> I could not find a limit for the "maximum number of (simultaneously)
> enabled interrupts" though (all I could find was a limit of "maximum
> number of interrupt sources/IDs", about which the S905 datasheet page
> 88 says: "There are 224 interrupt sources in the chip.")
Sounds like we are fine then ;)

Jonathan
> 
>> Jonathan
>>> ---
>>> v2:
>>> - move enabling / disabling irq to meson_sar_adc_start_sample_engine /
>>>   meson_sar_adc_stop_sample_engine respectively
>>> - move setting FIFO threshold for irq triggering to meson_sar_adc_hw_enable
>>>   to avoid a potential issue when uboot should be involved in system resume
>>> - return IRQ_NONE if the interrupt can't be for us
>>> - document interrupts property in DT documentation
>>> ---
>>>  .../bindings/iio/adc/amlogic,meson-saradc.txt      |  2 +
>>>  drivers/iio/adc/meson_saradc.c                     | 56 ++++++++++++++++++++--
>>>  2 files changed, 53 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>>> index f9e3ff2c..04718919 100644
>>> --- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>>> +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>>> @@ -7,6 +7,7 @@ Required properties:
>>>                       - "amlogic,meson-gxm-saradc" for GXM
>>>               along with the generic "amlogic,meson-saradc"
>>>  - reg:               the physical base address and length of the registers
>>> +- interrupts:        the interrupt indicating end of sampling
>>>  - clocks:    phandle and clock identifier (see clock-names)
>>>  - clock-names:       mandatory clocks:
>>>                       - "clkin" for the reference clock (typically XTAL)
>>> @@ -23,6 +24,7 @@ Example:
>>>               compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
>>>               #io-channel-cells = <1>;
>>>               reg = <0x0 0x8680 0x0 0x34>;
>>> +             interrupts = <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>;
>>>               clocks = <&xtal>,
>>>                        <&clkc CLKID_SAR_ADC>,
>>>                        <&clkc CLKID_SANA>,
>>> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
>>> index 89def603..9f186de2 100644
>>> --- a/drivers/iio/adc/meson_saradc.c
>>> +++ b/drivers/iio/adc/meson_saradc.c
>>> @@ -18,7 +18,9 @@
>>>  #include <linux/io.h>
>>>  #include <linux/iio/iio.h>
>>>  #include <linux/module.h>
>>> +#include <linux/interrupt.h>
>>>  #include <linux/of.h>
>>> +#include <linux/of_irq.h>
>>>  #include <linux/of_device.h>
>>>  #include <linux/platform_device.h>
>>>  #include <linux/regmap.h>
>>> @@ -163,6 +165,7 @@
>>>       #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK      GENMASK(13, 8)
>>>
>>>  #define MESON_SAR_ADC_MAX_FIFO_SIZE                          32
>>> +#define MESON_SAR_ADC_TIMEOUT                                        100 /* ms */
>>>
>>>  #define MESON_SAR_ADC_CHAN(_chan) {                                  \
>>>       .type = IIO_VOLTAGE,                                            \
>>> @@ -229,6 +232,7 @@ struct meson_sar_adc_priv {
>>>       struct clk_gate                         clk_gate;
>>>       struct clk                              *adc_div_clk;
>>>       struct clk_divider                      clk_div;
>>> +     struct completion                       done;
>>>  };
>>>
>>>  static const struct regmap_config meson_sar_adc_regmap_config = {
>>> @@ -274,11 +278,11 @@ static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
>>>                                        int *val)
>>>  {
>>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>> -     int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
>>> +     int regval, fifo_chan, fifo_val, sum = 0, count = 0;
>>>
>>> -     ret = meson_sar_adc_wait_busy_clear(indio_dev);
>>> -     if (ret)
>>> -             return ret;
>>> +     if(!wait_for_completion_timeout(&priv->done,
>>> +                             msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
>>> +             return -ETIMEDOUT;
>>>
>>>       while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
>>>              count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
>>> @@ -378,6 +382,12 @@ static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
>>>  {
>>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>>
>>> +     reinit_completion(&priv->done);
>>> +
>>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
>>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
>>> +
>>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>>                          MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
>>>                          MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
>>> @@ -392,6 +402,9 @@ static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
>>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>>
>>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>> +                        MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
>>> +
>>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>>                          MESON_SAR_ADC_REG0_SAMPLING_STOP,
>>>                          MESON_SAR_ADC_REG0_SAMPLING_STOP);
>>>
>>> @@ -643,6 +656,7 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>>>  {
>>>       struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>>       int ret;
>>> +     u32 regval;
>>>
>>>       ret = meson_sar_adc_lock(indio_dev);
>>>       if (ret)
>>> @@ -667,6 +681,9 @@ static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
>>>               goto err_sana_clk;
>>>       }
>>>
>>> +     regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
>>> +     regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
>>> +                        MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>>>       regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
>>>                          MESON_SAR_ADC_REG11_BANDGAP_EN,
>>>                          MESON_SAR_ADC_REG11_BANDGAP_EN);
>>> @@ -728,6 +745,25 @@ static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
>>>       return 0;
>>>  }
>>>
>>> +static irqreturn_t meson_sar_adc_irq(int irq, void *data)
>>> +{
>>> +     struct iio_dev *indio_dev = data;
>>> +     struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
>>> +     unsigned int cnt, threshold;
>>> +     u32 regval;
>>> +
>>> +     regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
>>> +     cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
>>> +     threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
>>> +
>>> +     if (cnt < threshold)
>>> +             return IRQ_NONE;
>>> +
>>> +     complete(&priv->done);
>>> +
>>> +     return IRQ_HANDLED;
>>> +}
>>> +
>>>  static const struct iio_info meson_sar_adc_iio_info = {
>>>       .read_raw = meson_sar_adc_iio_info_read_raw,
>>>       .driver_module = THIS_MODULE,
>>> @@ -770,7 +806,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>>       struct resource *res;
>>>       void __iomem *base;
>>>       const struct of_device_id *match;
>>> -     int ret;
>>> +     int irq, ret;
>>>
>>>       indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
>>>       if (!indio_dev) {
>>> @@ -779,6 +815,7 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>>       }
>>>
>>>       priv = iio_priv(indio_dev);
>>> +     init_completion(&priv->done);
>>>
>>>       match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
>>>       priv->data = match->data;
>>> @@ -797,6 +834,15 @@ static int meson_sar_adc_probe(struct platform_device *pdev)
>>>       if (IS_ERR(base))
>>>               return PTR_ERR(base);
>>>
>>> +     irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
>>> +     if (!irq)
>>> +             return -EINVAL;
>>> +
>>> +     ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED,
>>> +                            dev_name(&pdev->dev), indio_dev);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>>       priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
>>>                                            &meson_sar_adc_regmap_config);
>>>       if (IS_ERR(priv->regmap))
>>>
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-02-19 12:53 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-15 19:31 [PATCH v2 1/2] iio: adc: meson-saradc: switch from polling to interrupt mode Heiner Kallweit
2017-02-19 11:54 ` Martin Blumenstingl
2017-02-19 12:19 ` Jonathan Cameron
2017-02-19 12:37   ` Martin Blumenstingl
2017-02-19 12:53     ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).