[PATCH 2/2] iio: adc: mcp320x: add triggered buffer support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Axel Jonsson <axel.jonsson@xxxxxxxx>

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

Signed-off-by: Axel Jonsson <axel.jonsson@xxxxxxxx>
Signed-off-by: Vincent Whitchurch <vincent.whitchurch@xxxxxxxx>
---
 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




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux