linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] iio: adc: mcp320x: Add triggered buffer support
@ 2022-08-24 10:40 Vincent Whitchurch
  2022-08-24 10:40 ` [PATCH 1/2] iio: adc: mcp320x: use device managed functions Vincent Whitchurch
  2022-08-24 10:40 ` [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support Vincent Whitchurch
  0 siblings, 2 replies; 12+ messages in thread
From: Vincent Whitchurch @ 2022-08-24 10:40 UTC (permalink / raw)
  To: jic23
  Cc: kernel, lars, axel.jonsson, Vincent Whitchurch, linux-iio, linux-kernel

This series adds triggered buffer support to the mcp320x ADC driver.  Tested on
MCP3008.

Cc: linux-iio@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

Axel Jonsson (1):
  iio: adc: mcp320x: add triggered buffer support

Vincent Whitchurch (1):
  iio: adc: mcp320x: use device managed functions

 drivers/iio/adc/Kconfig   |   2 +
 drivers/iio/adc/mcp320x.c | 158 +++++++++++++++++++++++++-------------
 2 files changed, 108 insertions(+), 52 deletions(-)

-- 
2.34.1


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

* [PATCH 1/2] iio: adc: mcp320x: use device managed functions
  2022-08-24 10:40 [PATCH 0/2] iio: adc: mcp320x: Add triggered buffer support Vincent Whitchurch
@ 2022-08-24 10:40 ` Vincent Whitchurch
  2022-08-25 20:01   ` Andy Shevchenko
  2022-08-24 10:40 ` [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support Vincent Whitchurch
  1 sibling, 1 reply; 12+ messages in thread
From: Vincent Whitchurch @ 2022-08-24 10:40 UTC (permalink / raw)
  To: jic23
  Cc: kernel, lars, axel.jonsson, Vincent Whitchurch, linux-iio, linux-kernel

Use devm_* functions in probe to remove some code and to make it easier
to add further calls to the probe function.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
 drivers/iio/adc/mcp320x.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index b4c69acb33e3..28398f34628a 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -371,6 +371,11 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = {
 	},
 };
 
+static void mcp320x_reg_disable(void *reg)
+{
+	regulator_disable(reg);
+}
+
 static int mcp320x_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
@@ -445,27 +450,13 @@ static int mcp320x_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	mutex_init(&adc->lock);
-
-	ret = iio_device_register(indio_dev);
-	if (ret < 0)
-		goto reg_disable;
-
-	return 0;
-
-reg_disable:
-	regulator_disable(adc->reg);
-
-	return ret;
-}
+	ret = devm_add_action_or_reset(&spi->dev, mcp320x_reg_disable, adc->reg);
+	if (ret)
+		return ret;
 
-static void mcp320x_remove(struct spi_device *spi)
-{
-	struct iio_dev *indio_dev = spi_get_drvdata(spi);
-	struct mcp320x *adc = iio_priv(indio_dev);
+	mutex_init(&adc->lock);
 
-	iio_device_unregister(indio_dev);
-	regulator_disable(adc->reg);
+	return devm_iio_device_register(&spi->dev, indio_dev);
 }
 
 static const struct of_device_id mcp320x_dt_ids[] = {
@@ -520,7 +511,6 @@ static struct spi_driver mcp320x_driver = {
 		.of_match_table = mcp320x_dt_ids,
 	},
 	.probe = mcp320x_probe,
-	.remove = mcp320x_remove,
 	.id_table = mcp320x_id,
 };
 module_spi_driver(mcp320x_driver);
-- 
2.34.1


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

* [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-24 10:40 [PATCH 0/2] iio: adc: mcp320x: Add triggered buffer support Vincent Whitchurch
  2022-08-24 10:40 ` [PATCH 1/2] iio: adc: mcp320x: use device managed functions Vincent Whitchurch
@ 2022-08-24 10:40 ` Vincent Whitchurch
  2022-08-25 20:06   ` Andy Shevchenko
  2022-08-28 17:24   ` Jonathan Cameron
  1 sibling, 2 replies; 12+ messages in thread
From: Vincent Whitchurch @ 2022-08-24 10:40 UTC (permalink / raw)
  To: jic23
  Cc: kernel, lars, axel.jonsson, Vincent Whitchurch, linux-iio, linux-kernel

From: Axel Jonsson <axel.jonsson@axis.com>

Add support for triggered buffers.  Just read the channels in a loop to
keep things simple.

Signed-off-by: Axel Jonsson <axel.jonsson@axis.com>
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
---
 drivers/iio/adc/Kconfig   |   2 +
 drivers/iio/adc/mcp320x.c | 130 ++++++++++++++++++++++++++++----------
 2 files changed, 99 insertions(+), 33 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 48ace7412874..9f2628120885 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -696,6 +696,8 @@ config MAX9611
 config MCP320X
 	tristate "Microchip Technology MCP3x01/02/04/08 and MCP3550/1/3"
 	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Microchip Technology's
 	  MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 28398f34628a..9782cbd37728 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -43,6 +43,10 @@
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 #include <linux/regulator/consumer.h>
 
 enum {
@@ -231,37 +235,51 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev,
 	return ret;
 }
 
-#define MCP320X_VOLTAGE_CHANNEL(num)				\
-	{							\
-		.type = IIO_VOLTAGE,				\
-		.indexed = 1,					\
-		.channel = (num),				\
-		.address = (num),				\
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
+#define MCP320X_VOLTAGE_CHANNEL(num)					\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = (num),					\
+		.address = (num),					\
+		.scan_index = (num),					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 32,					\
+			.storagebits = 32,				\
+			.endianness = IIO_CPU,				\
+		},							\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
 	}
 
-#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2)		\
-	{							\
-		.type = IIO_VOLTAGE,				\
-		.indexed = 1,					\
-		.channel = (chan1),				\
-		.channel2 = (chan2),				\
-		.address = (chan1),				\
-		.differential = 1,				\
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
+#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2, diffoff)		\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.indexed = 1,						\
+		.channel = (chan1),					\
+		.channel2 = (chan2),					\
+		.address = (chan1),					\
+		.scan_index = (chan1 + diffoff),			\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 32,					\
+			.storagebits = 32,				\
+			.endianness = IIO_CPU,				\
+		},							\
+		.differential = 1,					\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
 	}
 
 static const struct iio_chan_spec mcp3201_channels[] = {
-	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 1),
 };
 
 static const struct iio_chan_spec mcp3202_channels[] = {
 	MCP320X_VOLTAGE_CHANNEL(0),
 	MCP320X_VOLTAGE_CHANNEL(1),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0, 2),
 };
 
 static const struct iio_chan_spec mcp3204_channels[] = {
@@ -269,10 +287,10 @@ static const struct iio_chan_spec mcp3204_channels[] = {
 	MCP320X_VOLTAGE_CHANNEL(1),
 	MCP320X_VOLTAGE_CHANNEL(2),
 	MCP320X_VOLTAGE_CHANNEL(3),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 4),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0, 4),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3, 4),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2, 4),
 };
 
 static const struct iio_chan_spec mcp3208_channels[] = {
@@ -284,14 +302,14 @@ static const struct iio_chan_spec mcp3208_channels[] = {
 	MCP320X_VOLTAGE_CHANNEL(5),
 	MCP320X_VOLTAGE_CHANNEL(6),
 	MCP320X_VOLTAGE_CHANNEL(7),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7),
-	MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7, 8),
+	MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6, 8),
 };
 
 static const struct iio_info mcp320x_info = {
@@ -371,6 +389,46 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = {
 	},
 };
 
+static irqreturn_t mcp320x_buffer_trigger_handler(int irq, void *pollfunc)
+{
+	struct iio_poll_func *pf = pollfunc;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct mcp320x *adc = iio_priv(indio_dev);
+	s32 data[ARRAY_SIZE(mcp3208_channels)];
+	int device_index;
+	int i = 0;
+	int chan;
+
+	device_index = spi_get_device_id(adc->spi)->driver_data;
+
+	mutex_lock(&adc->lock);
+
+	for_each_set_bit(chan, indio_dev->active_scan_mask, indio_dev->masklength) {
+		const struct iio_chan_spec *spec = &indio_dev->channels[chan];
+		int ret, val;
+
+		ret = mcp320x_adc_conversion(adc, spec->address,
+					     spec->differential, device_index,
+					     &val);
+		if (ret < 0) {
+			dev_err_ratelimited(&adc->spi->dev, "Failed to read data: %d\n",
+					    ret);
+			goto out;
+		}
+
+		data[i++] = val;
+	}
+
+	iio_push_to_buffers(indio_dev, data);
+
+out:
+	mutex_unlock(&adc->lock);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
 static void mcp320x_reg_disable(void *reg)
 {
 	regulator_disable(reg);
@@ -456,6 +514,12 @@ static int mcp320x_probe(struct spi_device *spi)
 
 	mutex_init(&adc->lock);
 
+	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL,
+					      mcp320x_buffer_trigger_handler,
+					      NULL);
+	if (ret)
+		return ret;
+
 	return devm_iio_device_register(&spi->dev, indio_dev);
 }
 
-- 
2.34.1


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

* Re: [PATCH 1/2] iio: adc: mcp320x: use device managed functions
  2022-08-24 10:40 ` [PATCH 1/2] iio: adc: mcp320x: use device managed functions Vincent Whitchurch
@ 2022-08-25 20:01   ` Andy Shevchenko
  2022-08-26 11:38     ` Vincent Whitchurch
  0 siblings, 1 reply; 12+ messages in thread
From: Andy Shevchenko @ 2022-08-25 20:01 UTC (permalink / raw)
  To: Vincent Whitchurch
  Cc: Jonathan Cameron, kernel, Lars-Peter Clausen, axel.jonsson,
	linux-iio, Linux Kernel Mailing List

On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
<vincent.whitchurch@axis.com> wrote:
>
> Use devm_* functions in probe to remove some code and to make it easier
> to add further calls to the probe function.

...

> +       mutex_init(&adc->lock);

> +       return devm_iio_device_register(&spi->dev, indio_dev);

Do you still need to destroy the mutex? If so, you may not call devm_
variant of iio_device_register() or you have to wrap mutex_destroy()
accordingly.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-24 10:40 ` [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support Vincent Whitchurch
@ 2022-08-25 20:06   ` Andy Shevchenko
  2022-08-28 17:15     ` Jonathan Cameron
  2022-08-28 17:24   ` Jonathan Cameron
  1 sibling, 1 reply; 12+ messages in thread
From: Andy Shevchenko @ 2022-08-25 20:06 UTC (permalink / raw)
  To: Vincent Whitchurch
  Cc: Jonathan Cameron, kernel, Lars-Peter Clausen, axel.jonsson,
	linux-iio, Linux Kernel Mailing List

On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
<vincent.whitchurch@axis.com> wrote:
>
> From: Axel Jonsson <axel.jonsson@axis.com>
>
> Add support for triggered buffers.  Just read the channels in a loop to
> keep things simple.

...

>  #include <linux/module.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/iio/iio.h>
> +#include <linux/interrupt.h>

Ordering?

But honestly, I prefer the linux/iio/* to be split in a separate group...

> +#include <linux/iio/buffer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/trigger_consumer.h>
>  #include <linux/regulator/consumer.h>
>

...and be put here.

...

> +       device_index = spi_get_device_id(adc->spi)->driver_data;

Hmm... Wondering if this can be derived from channel number or alike.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 1/2] iio: adc: mcp320x: use device managed functions
  2022-08-25 20:01   ` Andy Shevchenko
@ 2022-08-26 11:38     ` Vincent Whitchurch
       [not found]       ` <CAHp75VffYzNTfrki4+o8JJayUGo1n91bP0hSzB-fR=RfcFq-fw@mail.gmail.com>
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Whitchurch @ 2022-08-26 11:38 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Jonathan Cameron, kernel, Lars-Peter Clausen, Axel Jonsson,
	linux-iio, Linux Kernel Mailing List

On Thu, Aug 25, 2022 at 10:01:58PM +0200, Andy Shevchenko wrote:
> On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
> <vincent.whitchurch@axis.com> wrote:
> >
> > Use devm_* functions in probe to remove some code and to make it easier
> > to add further calls to the probe function.
> 
> ...
> 
> > +       mutex_init(&adc->lock);
> 
> > +       return devm_iio_device_register(&spi->dev, indio_dev);
> 
> Do you still need to destroy the mutex? If so, you may not call devm_
> variant of iio_device_register() or you have to wrap mutex_destroy()
> accordingly.

mutex_destroy() is only used to ensure that mutex debugging catches
further use of the mutex.  Isn't it rather overkill to add specific
cleanup to do only that, especially in this case when it's anyway going
to get freed immediately afterwards?  The vast majority of IIO drivers
don't call mutex_destroy() (256 calls to mutex_init() in HEAD vs 12 to
mutex_destroy()).

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

* Re: [PATCH 1/2] iio: adc: mcp320x: use device managed functions
       [not found]       ` <CAHp75VffYzNTfrki4+o8JJayUGo1n91bP0hSzB-fR=RfcFq-fw@mail.gmail.com>
@ 2022-08-28 17:06         ` Jonathan Cameron
  2022-08-29  8:16           ` Andy Shevchenko
  0 siblings, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2022-08-28 17:06 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vincent Whitchurch, kernel, Lars-Peter Clausen, Axel Jonsson,
	linux-iio, Linux Kernel Mailing List

On Fri, 26 Aug 2022 14:57:44 +0300
Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

> On Friday, August 26, 2022, Vincent Whitchurch <vincent.whitchurch@axis.com>
> wrote:
> 
> > On Thu, Aug 25, 2022 at 10:01:58PM +0200, Andy Shevchenko wrote:  
> > > On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
> > > <vincent.whitchurch@axis.com> wrote:  
> > > >
> > > > Use devm_* functions in probe to remove some code and to make it easier
> > > > to add further calls to the probe function.  
> > >
> > > ...
> > >  
> > > > +       mutex_init(&adc->lock);  
> > >  
> > > > +       return devm_iio_device_register(&spi->dev, indio_dev);  
> > >
> > > Do you still need to destroy the mutex? If so, you may not call devm_
> > > variant of iio_device_register() or you have to wrap mutex_destroy()
> > > accordingly.  
> >
> > mutex_destroy() is only used to ensure that mutex debugging catches
> > further use of the mutex.  Isn't it rather overkill to add specific
> > cleanup to do only that, especially in this case when it's anyway going
> > to get freed immediately afterwards?  The vast majority of IIO drivers
> > don't call mutex_destroy() (256 calls to mutex_init() in HEAD vs 12 to
> > mutex_destroy()).
> >  
> 
> 
>  So 256 - 12 = 244 drivers are not pedantic.

I long ago decided mutex_destroy() in remove() paths just isn't worth the
effort. It makes absolute sense in more complex flows, but in cases
like this it's just annoying and makes the cleanup harder.

Hence I'd prefer we just ignore it's existence in cases like this.

If someone finds me a bug that it would have caught then I might
change my mind ;)

If anyone wants a giggle via adding a devm_mutex_init() call it
might be interesting to see the responses.  Would be unusual in
that it would just be mutex_init() in unless the mutex debugging
is turned on...

Jonathan



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

* Re: [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-25 20:06   ` Andy Shevchenko
@ 2022-08-28 17:15     ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2022-08-28 17:15 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Vincent Whitchurch, kernel, Lars-Peter Clausen, axel.jonsson,
	linux-iio, Linux Kernel Mailing List

On Thu, 25 Aug 2022 23:06:01 +0300
Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

> On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
> <vincent.whitchurch@axis.com> wrote:
> >
> > From: Axel Jonsson <axel.jonsson@axis.com>
> >
> > Add support for triggered buffers.  Just read the channels in a loop to
> > keep things simple.  
> 
> ...
> 
> >  #include <linux/module.h>
> >  #include <linux/mod_devicetable.h>
> >  #include <linux/iio/iio.h>
> > +#include <linux/interrupt.h>  
> 
> Ordering?
> 
> But honestly, I prefer the linux/iio/* to be split in a separate group...
> 
> > +#include <linux/iio/buffer.h>
> > +#include <linux/iio/triggered_buffer.h>
> > +#include <linux/iio/trigger_consumer.h>
> >  #include <linux/regulator/consumer.h>
> >  
> 
> ...and be put here.
> 
> ...
> 
> > +       device_index = spi_get_device_id(adc->spi)->driver_data;  
> 
> Hmm... Wondering if this can be derived from channel number or alike.
> 
It is weirder than the name implies. 
Seem device_index is actually the chip type from amongst those the driver
supports.

That wants cleaning up, particularly there is also a chip_info structure.
Various ways of doing it, but simplest is probably a set of callbacks
covering the different data extraction methods in mcp320x_adc_conversion.

Jonathan



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

* Re: [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-24 10:40 ` [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support Vincent Whitchurch
  2022-08-25 20:06   ` Andy Shevchenko
@ 2022-08-28 17:24   ` Jonathan Cameron
  2022-08-31  7:47     ` Vincent Whitchurch
  1 sibling, 1 reply; 12+ messages in thread
From: Jonathan Cameron @ 2022-08-28 17:24 UTC (permalink / raw)
  To: Vincent Whitchurch; +Cc: kernel, lars, axel.jonsson, linux-iio, linux-kernel

On Wed, 24 Aug 2022 12:40:02 +0200
Vincent Whitchurch <vincent.whitchurch@axis.com> wrote:

> From: Axel Jonsson <axel.jonsson@axis.com>
> 
> Add support for triggered buffers.  Just read the channels in a loop to
> keep things simple.

Just curious, but what other options are there?  A quick datasheet scroll
through didn't seem to suggest you can overlap setup of next read with
reading out the previous (common on SPI ADCs).

A few minor additional comments inline.

Thanks,

Jonathan


> 
> Signed-off-by: Axel Jonsson <axel.jonsson@axis.com>
> Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
> ---
>  drivers/iio/adc/Kconfig   |   2 +
>  drivers/iio/adc/mcp320x.c | 130 ++++++++++++++++++++++++++++----------
>  2 files changed, 99 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 48ace7412874..9f2628120885 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -696,6 +696,8 @@ config MAX9611
>  config MCP320X
>  	tristate "Microchip Technology MCP3x01/02/04/08 and MCP3550/1/3"
>  	depends on SPI
> +	select IIO_BUFFER
> +	select IIO_TRIGGERED_BUFFER
>  	help
>  	  Say yes here to build support for Microchip Technology's
>  	  MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
> diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
> index 28398f34628a..9782cbd37728 100644
> --- a/drivers/iio/adc/mcp320x.c
> +++ b/drivers/iio/adc/mcp320x.c
> @@ -43,6 +43,10 @@
>  #include <linux/module.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/iio/iio.h>
> +#include <linux/interrupt.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/trigger_consumer.h>
>  #include <linux/regulator/consumer.h>
>  
>  enum {
> @@ -231,37 +235,51 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev,
>  	return ret;
>  }
>  
> -#define MCP320X_VOLTAGE_CHANNEL(num)				\
> -	{							\
> -		.type = IIO_VOLTAGE,				\
> -		.indexed = 1,					\
> -		.channel = (num),				\
> -		.address = (num),				\
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
> -		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
> +#define MCP320X_VOLTAGE_CHANNEL(num)					\
> +	{								\
> +		.type = IIO_VOLTAGE,					\
> +		.indexed = 1,						\
> +		.channel = (num),					\
> +		.address = (num),					\
> +		.scan_index = (num),					\
> +		.scan_type = {						\
> +			.sign = 's',					\
> +			.realbits = 32,					\
> +			.storagebits = 32,				\
> +			.endianness = IIO_CPU,				\
> +		},							\
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
>  	}
>  
> -#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2)		\
> -	{							\
> -		.type = IIO_VOLTAGE,				\
> -		.indexed = 1,					\
> -		.channel = (chan1),				\
> -		.channel2 = (chan2),				\
> -		.address = (chan1),				\
> -		.differential = 1,				\
> -		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
> -		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
> +#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2, diffoff)		\
> +	{								\
> +		.type = IIO_VOLTAGE,					\
> +		.indexed = 1,						\
> +		.channel = (chan1),					\
> +		.channel2 = (chan2),					\
> +		.address = (chan1),					\
> +		.scan_index = (chan1 + diffoff),			\

I wonder if it's just more readable to use scan_index as one of the parameters
of this macro. If it's the first one, then you'll
see 
	*VOLTAGE_CHANNEL(0),
	*VOLTAGE_CHANNEL(1),
	*VOLTAGE_CHANNEL_DIFF(2, 0, 1),
	*VOLTAGE_CHANNEL_DIFF(3, 1, 0),
etc

If we can avoid reformatting this in the same patch that adds the new
stuff it will make it easier to see the changes.

If you want to reformat, add another patch to do that as a no-op change.


> +		.scan_type = {						\
> +			.sign = 's',					\
> +			.realbits = 32,					\
> +			.storagebits = 32,				\
> +			.endianness = IIO_CPU,				\
> +		},							\
> +		.differential = 1,					\
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
> +		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
>  	}
>  
>  static const struct iio_chan_spec mcp3201_channels[] = {
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 1),
>  };
>  
>  static const struct iio_chan_spec mcp3202_channels[] = {
>  	MCP320X_VOLTAGE_CHANNEL(0),
>  	MCP320X_VOLTAGE_CHANNEL(1),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0, 2),
>  };
>  
>  static const struct iio_chan_spec mcp3204_channels[] = {
> @@ -269,10 +287,10 @@ static const struct iio_chan_spec mcp3204_channels[] = {
>  	MCP320X_VOLTAGE_CHANNEL(1),
>  	MCP320X_VOLTAGE_CHANNEL(2),
>  	MCP320X_VOLTAGE_CHANNEL(3),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
> -	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1, 4),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0, 4),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3, 4),
> +	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2, 4),
>  };



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

* Re: [PATCH 1/2] iio: adc: mcp320x: use device managed functions
  2022-08-28 17:06         ` Jonathan Cameron
@ 2022-08-29  8:16           ` Andy Shevchenko
  0 siblings, 0 replies; 12+ messages in thread
From: Andy Shevchenko @ 2022-08-29  8:16 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Vincent Whitchurch, kernel, Lars-Peter Clausen, Axel Jonsson,
	linux-iio, Linux Kernel Mailing List

On Sun, Aug 28, 2022 at 8:40 PM Jonathan Cameron <jic23@kernel.org> wrote:
> On Fri, 26 Aug 2022 14:57:44 +0300
> Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Friday, August 26, 2022, Vincent Whitchurch <vincent.whitchurch@axis.com>
> > wrote:
> > > On Thu, Aug 25, 2022 at 10:01:58PM +0200, Andy Shevchenko wrote:
> > > > On Wed, Aug 24, 2022 at 1:46 PM Vincent Whitchurch
> > > > <vincent.whitchurch@axis.com> wrote:
> > > > >
> > > > > Use devm_* functions in probe to remove some code and to make it easier
> > > > > to add further calls to the probe function.
> > > >
> > > > ...
> > > >
> > > > > +       mutex_init(&adc->lock);
> > > >
> > > > > +       return devm_iio_device_register(&spi->dev, indio_dev);
> > > >
> > > > Do you still need to destroy the mutex? If so, you may not call devm_
> > > > variant of iio_device_register() or you have to wrap mutex_destroy()
> > > > accordingly.
> > >
> > > mutex_destroy() is only used to ensure that mutex debugging catches
> > > further use of the mutex.  Isn't it rather overkill to add specific
> > > cleanup to do only that, especially in this case when it's anyway going
> > > to get freed immediately afterwards?  The vast majority of IIO drivers
> > > don't call mutex_destroy() (256 calls to mutex_init() in HEAD vs 12 to
> > > mutex_destroy()).
> >
> >  So 256 - 12 = 244 drivers are not pedantic.
>
> I long ago decided mutex_destroy() in remove() paths just isn't worth the
> effort. It makes absolute sense in more complex flows, but in cases
> like this it's just annoying and makes the cleanup harder.
>
> Hence I'd prefer we just ignore it's existence in cases like this.
>
> If someone finds me a bug that it would have caught then I might
> change my mind ;)
>
> If anyone wants a giggle via adding a devm_mutex_init() call it
> might be interesting to see the responses.  Would be unusual in
> that it would just be mutex_init() in unless the mutex debugging
> is turned on...

Agree on these points. Sometimes too much pedanticy is too much.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-28 17:24   ` Jonathan Cameron
@ 2022-08-31  7:47     ` Vincent Whitchurch
  2022-09-04 16:29       ` Jonathan Cameron
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Whitchurch @ 2022-08-31  7:47 UTC (permalink / raw)
  To: Jonathan Cameron; +Cc: kernel, lars, Axel Jonsson, linux-iio, linux-kernel

On Sun, Aug 28, 2022 at 07:24:30PM +0200, Jonathan Cameron wrote:
> On Wed, 24 Aug 2022 12:40:02 +0200
> Vincent Whitchurch <vincent.whitchurch@axis.com> wrote:
> > Add support for triggered buffers.  Just read the channels in a loop to
> > keep things simple.
> 
> Just curious, but what other options are there?  A quick datasheet scroll
> through didn't seem to suggest you can overlap setup of next read with
> reading out the previous (common on SPI ADCs).

You're right that the hardware doesn't support any special method to
read out multiple channels; I can mention that in the commit message.
But I think you could construct a spi_message which a bunch of
spi_transfers which toggle the CS appropriately between them to read out
multiple channels in one go?  (Note that the variants have different
data formats, and many of the variants only have one channel.)

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

* Re: [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support
  2022-08-31  7:47     ` Vincent Whitchurch
@ 2022-09-04 16:29       ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2022-09-04 16:29 UTC (permalink / raw)
  To: Vincent Whitchurch; +Cc: kernel, lars, Axel Jonsson, linux-iio, linux-kernel

On Wed, 31 Aug 2022 09:47:50 +0200
Vincent Whitchurch <vincent.whitchurch@axis.com> wrote:

> On Sun, Aug 28, 2022 at 07:24:30PM +0200, Jonathan Cameron wrote:
> > On Wed, 24 Aug 2022 12:40:02 +0200
> > Vincent Whitchurch <vincent.whitchurch@axis.com> wrote:  
> > > Add support for triggered buffers.  Just read the channels in a loop to
> > > keep things simple.  
> > 
> > Just curious, but what other options are there?  A quick datasheet scroll
> > through didn't seem to suggest you can overlap setup of next read with
> > reading out the previous (common on SPI ADCs).  
> 
> You're right that the hardware doesn't support any special method to
> read out multiple channels; I can mention that in the commit message.
> But I think you could construct a spi_message which a bunch of
> spi_transfers which toggle the CS appropriately between them to read out
> multiple channels in one go?  (Note that the variants have different
> data formats, and many of the variants only have one channel.)

That might be a little more efficient on a suitably advanced
SPI controller, or where the overhead of jumping between drivers
is large, but in many cases it won't save that much.

Would need an experiment on a platform someone cares about to decide
if it is worthwhile.

Jonathan


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

end of thread, other threads:[~2022-09-04 17:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-24 10:40 [PATCH 0/2] iio: adc: mcp320x: Add triggered buffer support Vincent Whitchurch
2022-08-24 10:40 ` [PATCH 1/2] iio: adc: mcp320x: use device managed functions Vincent Whitchurch
2022-08-25 20:01   ` Andy Shevchenko
2022-08-26 11:38     ` Vincent Whitchurch
     [not found]       ` <CAHp75VffYzNTfrki4+o8JJayUGo1n91bP0hSzB-fR=RfcFq-fw@mail.gmail.com>
2022-08-28 17:06         ` Jonathan Cameron
2022-08-29  8:16           ` Andy Shevchenko
2022-08-24 10:40 ` [PATCH 2/2] iio: adc: mcp320x: add triggered buffer support Vincent Whitchurch
2022-08-25 20:06   ` Andy Shevchenko
2022-08-28 17:15     ` Jonathan Cameron
2022-08-28 17:24   ` Jonathan Cameron
2022-08-31  7:47     ` Vincent Whitchurch
2022-09-04 16:29       ` 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).