All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V8 0/2] iio: input: ti_am335x_tscadc: Add continuous sampling support to adc
@ 2013-09-01 11:17 Zubair Lutfullah
  2013-09-01 11:17   ` Zubair Lutfullah
  2013-09-01 11:17 ` [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support Zubair Lutfullah
  0 siblings, 2 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-01 11:17 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Round 8 updates
Rebased to togreg branch of IIO..

Round 7 updates
- Fixes to error handling path for trigger register

- Optimization of step enable calculations based
on input from Sebastian

- trigger unregister added to remove section. was missing

- missing entry in Kconfig for triggered buffer support. added

- TSC/ADC IRQ handling was based on wierd ack system. not required. removed.
each irq handler deals with its own stuff *only*

Thanks for all the input

Regards
Zubair Lutfullah Kakakhel

Zubair Lutfullah (2):
  input: ti_am335x_tsc: Enable shared IRQ for TSC
  iio: ti_am335x_adc: Add continuous sampling support

 drivers/iio/adc/Kconfig                   |    1 +
 drivers/iio/adc/ti_am335x_adc.c           |  243 ++++++++++++++++++++++++++---
 drivers/input/touchscreen/ti_am335x_tsc.c |   12 +-
 include/linux/mfd/ti_am335x_tscadc.h      |   13 ++
 4 files changed, 246 insertions(+), 23 deletions(-)

-- 
1.7.9.5


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

* [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-01 11:17   ` Zubair Lutfullah
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-01 11:17 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Enable shared IRQ to allow ADC to share IRQ line from
parent MFD core. Only FIFO0 IRQs are for TSC and handled
on the TSC side.

Step mask would be updated from cached variable only previously.
In rare cases when both TSC and ADC are used, the cached
variable gets mixed up.
The step mask is written with the required mask every time.

Rachna Patil (TI) laid ground work for shared IRQ.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index e1c5300..24e625c 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -52,6 +52,7 @@ struct titsc {
 	u32			config_inp[4];
 	u32			bit_xp, bit_xn, bit_yp, bit_yn;
 	u32			inp_xp, inp_xn, inp_yp, inp_yn;
+	u32			step_mask;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -196,7 +197,8 @@ static void titsc_step_config(struct titsc *ts_dev)
 
 	/* The steps1 … end and bit 0 for TS_Charge */
 	stepenable = (1 << (end_step + 2)) - 1;
-	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+	ts_dev->step_mask = stepenable;
+	am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -260,6 +262,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 	unsigned int fsm;
 
 	status = titsc_readl(ts_dev, REG_IRQSTATUS);
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
+	 */
 	if (status & IRQENB_FIFO0THRES) {
 
 		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
@@ -316,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 
 	if (irqclr) {
 		titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
-		am335x_tsc_se_update(ts_dev->mfd_tscadc);
+		am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
@@ -389,7 +395,7 @@ static int titsc_probe(struct platform_device *pdev)
 	}
 
 	err = request_irq(ts_dev->irq, titsc_irq,
-			  0, pdev->dev.driver->name, ts_dev);
+			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
 		goto err_free_mem;
-- 
1.7.9.5


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

* [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-01 11:17   ` Zubair Lutfullah
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-01 11:17 UTC (permalink / raw)
  To: jic23-KWPb1pKIrIJaa/9Udqfwiw, dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w

Enable shared IRQ to allow ADC to share IRQ line from
parent MFD core. Only FIFO0 IRQs are for TSC and handled
on the TSC side.

Step mask would be updated from cached variable only previously.
In rare cases when both TSC and ADC are used, the cached
variable gets mixed up.
The step mask is written with the required mask every time.

Rachna Patil (TI) laid ground work for shared IRQ.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index e1c5300..24e625c 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -52,6 +52,7 @@ struct titsc {
 	u32			config_inp[4];
 	u32			bit_xp, bit_xn, bit_yp, bit_yn;
 	u32			inp_xp, inp_xn, inp_yp, inp_yn;
+	u32			step_mask;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -196,7 +197,8 @@ static void titsc_step_config(struct titsc *ts_dev)
 
 	/* The steps1 … end and bit 0 for TS_Charge */
 	stepenable = (1 << (end_step + 2)) - 1;
-	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
+	ts_dev->step_mask = stepenable;
+	am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -260,6 +262,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 	unsigned int fsm;
 
 	status = titsc_readl(ts_dev, REG_IRQSTATUS);
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
+	 */
 	if (status & IRQENB_FIFO0THRES) {
 
 		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
@@ -316,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 
 	if (irqclr) {
 		titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
-		am335x_tsc_se_update(ts_dev->mfd_tscadc);
+		am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 		return IRQ_HANDLED;
 	}
 	return IRQ_NONE;
@@ -389,7 +395,7 @@ static int titsc_probe(struct platform_device *pdev)
 	}
 
 	err = request_irq(ts_dev->irq, titsc_irq,
-			  0, pdev->dev.driver->name, ts_dev);
+			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 	if (err) {
 		dev_err(&pdev->dev, "failed to allocate irq.\n");
 		goto err_free_mem;
-- 
1.7.9.5

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

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-01 11:17 [PATCH V8 0/2] iio: input: ti_am335x_tscadc: Add continuous sampling support to adc Zubair Lutfullah
  2013-09-01 11:17   ` Zubair Lutfullah
@ 2013-09-01 11:17 ` Zubair Lutfullah
  2013-09-08 13:42     ` Jonathan Cameron
  1 sibling, 1 reply; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-01 11:17 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Previously the driver had only one-shot reading functionality.
This patch adds triggered buffer support to the driver.

Continuous sampling starts when buffer is enabled.
And samples are pushed to userpace by the trigger which
triggers automatically at every hardware interrupt
of FIFO1 filling with samples upto threshold value.

Userspace responsibility to stop sampling by writing zero
in the buffer enable file.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added trigger support.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/iio/adc/Kconfig              |    1 +
 drivers/iio/adc/ti_am335x_adc.c      |  243 +++++++++++++++++++++++++++++++---
 include/linux/mfd/ti_am335x_tscadc.h |   13 ++
 3 files changed, 237 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 09371cb..cfa2039 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -167,6 +167,7 @@ config TI_ADC081C
 config TI_AM335X_ADC
 	tristate "TI's AM335X ADC driver"
 	depends on MFD_TI_AM335X_TSCADC
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Texas Instruments ADC
 	  driver which is also a MFD client.
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..1626e16 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -24,16 +24,23 @@
 #include <linux/iio/iio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int irq;
+	int buffer_en_ch_steps;
+	struct iio_trigger *trig;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,10 +63,16 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 {
+	return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
-	int i, steps;
+	int i, steps, chan;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -72,11 +85,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
-		int chan;
-
 		chan = adc_dev->channel_line[i];
 		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
 				stepconfig | STEPCONFIG_INP(chan));
@@ -85,7 +100,167 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+		return IRQ_HANDLED;
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Trigger to push FIFO data to iio buffer */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
+
+}
+
+static irqreturn_t tiadc_trigger_h(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
 
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO before starting sampling */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+	adc_dev->buffer_en_ch_steps = enb;
+
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of any leftover data */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops tiadc_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_trigger *trig = adc_dev->trig;
+	int ret;
+
+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
+	if (trig == NULL)
+		return -ENOMEM;
+
+	trig->dev.parent = indio_dev->dev.parent;
+	trig->ops = &tiadc_trigger_ops;
+	iio_trigger_set_drvdata(trig, indio_dev);
+
+	ret = iio_trigger_register(trig);
+	if (ret)
+		goto err_free_trigger;
+
+	return 0;
+
+err_free_trigger:
+	iio_trigger_free(adc_dev->trig);
+
+	return ret;
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
-	u32 step = UINT_MAX;
 	bool found = false;
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -168,15 +347,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	 * Hence we need to flush out this data.
 	 */
 
-	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
-		if (chan->channel == adc_dev->channel_line[i]) {
-			step = adc_dev->channel_step[i];
-			break;
-		}
-	}
-	if (WARN_ON_ONCE(step == UINT_MAX))
-		return -EINVAL;
-
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -231,26 +401,49 @@ static int tiadc_probe(struct platform_device *pdev)
 		channels++;
 	}
 	adc_dev->channels = channels;
+	adc_dev->irq = adc_dev->mfd_tscadc->irq;
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
 		return err;
 
-	err = iio_device_register(indio_dev);
+	err = tiadc_iio_allocate_trigger(indio_dev);
 	if (err)
 		goto err_free_channels;
 
+	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
+		indio_dev->name, indio_dev);
+	if (err)
+		goto err_unregister_trigger;
+
+	err = iio_triggered_buffer_setup(indio_dev, NULL,
+			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
+	if (err)
+		goto err_free_irq;
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_buffer_unregister;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	iio_buffer_unregister(indio_dev);
+err_free_irq:
+	free_irq(adc_dev->irq, indio_dev);
+err_unregister_trigger:
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
 	return err;
@@ -262,7 +455,11 @@ static int tiadc_remove(struct platform_device *pdev)
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	u32 step_en;
 
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
+	free_irq(adc_dev->irq, indio_dev);
 	iio_device_unregister(indio_dev);
+	iio_buffer_unregister(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
@@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
 
 	/* Make sure ADC is powered up */
 	restore = tiadc_readl(adc_dev, REG_CTRL);
-	restore &= ~(CNTRLREG_POWERDOWN);
+	restore &= ~(CNTRLREG_TSCSSENB);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+	tiadc_step_config(indio_dev);
+
+	/* Make sure ADC is powered up */
+	restore &= ~(CNTRLREG_POWERDOWN);
+	restore |= CNTRLREG_TSCSSENB;
+	tiadc_writel(adc_dev, REG_CTRL, restore);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..a372ebf 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,17 +46,25 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
 #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
@@ -153,6 +162,10 @@ struct ti_tscadc_dev {
 
 	/* adc device */
 	struct adc_device *adc;
+
+	/* Context save */
+	unsigned int irqstat;
+	unsigned int ctrl;
 };
 
 static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
-- 
1.7.9.5


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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-08 11:29     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-08 11:29 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: dmitry.torokhov, linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On 09/01/13 12:17, Zubair Lutfullah wrote:
> Enable shared IRQ to allow ADC to share IRQ line from
> parent MFD core. Only FIFO0 IRQs are for TSC and handled
> on the TSC side.
> 
> Step mask would be updated from cached variable only previously.
> In rare cases when both TSC and ADC are used, the cached
> variable gets mixed up.
> The step mask is written with the required mask every time.
> 
> Rachna Patil (TI) laid ground work for shared IRQ.
> 
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Whilst I would have prefered an mfd under these drivers and elegant handling
of the interrupts, I guess if this works it is at least not terribly invasive.

However, this does need an Ack from Dmitry before I can take it (or for
Dmitry to take it himself?)

> ---
>  drivers/input/touchscreen/ti_am335x_tsc.c |   12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
> index e1c5300..24e625c 100644
> --- a/drivers/input/touchscreen/ti_am335x_tsc.c
> +++ b/drivers/input/touchscreen/ti_am335x_tsc.c
> @@ -52,6 +52,7 @@ struct titsc {
>  	u32			config_inp[4];
>  	u32			bit_xp, bit_xn, bit_yp, bit_yn;
>  	u32			inp_xp, inp_xn, inp_yp, inp_yn;
> +	u32			step_mask;
>  };
>  
>  static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
> @@ -196,7 +197,8 @@ static void titsc_step_config(struct titsc *ts_dev)
>  
>  	/* The steps1 … end and bit 0 for TS_Charge */
>  	stepenable = (1 << (end_step + 2)) - 1;
> -	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
> +	ts_dev->step_mask = stepenable;
> +	am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
>  }
>  
>  static void titsc_read_coordinates(struct titsc *ts_dev,
> @@ -260,6 +262,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
>  	unsigned int fsm;
>  
>  	status = titsc_readl(ts_dev, REG_IRQSTATUS);
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
> +	 */
>  	if (status & IRQENB_FIFO0THRES) {
>  
>  		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
> @@ -316,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
>  
>  	if (irqclr) {
>  		titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
> -		am335x_tsc_se_update(ts_dev->mfd_tscadc);
> +		am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
>  		return IRQ_HANDLED;
>  	}
>  	return IRQ_NONE;
> @@ -389,7 +395,7 @@ static int titsc_probe(struct platform_device *pdev)
>  	}
>  
>  	err = request_irq(ts_dev->irq, titsc_irq,
> -			  0, pdev->dev.driver->name, ts_dev);
> +			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
>  	if (err) {
>  		dev_err(&pdev->dev, "failed to allocate irq.\n");
>  		goto err_free_mem;
> 

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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-08 11:29     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-08 11:29 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On 09/01/13 12:17, Zubair Lutfullah wrote:
> Enable shared IRQ to allow ADC to share IRQ line from
> parent MFD core. Only FIFO0 IRQs are for TSC and handled
> on the TSC side.
> 
> Step mask would be updated from cached variable only previously.
> In rare cases when both TSC and ADC are used, the cached
> variable gets mixed up.
> The step mask is written with the required mask every time.
> 
> Rachna Patil (TI) laid ground work for shared IRQ.
> 
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Whilst I would have prefered an mfd under these drivers and elegant handling
of the interrupts, I guess if this works it is at least not terribly invasive.

However, this does need an Ack from Dmitry before I can take it (or for
Dmitry to take it himself?)

> ---
>  drivers/input/touchscreen/ti_am335x_tsc.c |   12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
> index e1c5300..24e625c 100644
> --- a/drivers/input/touchscreen/ti_am335x_tsc.c
> +++ b/drivers/input/touchscreen/ti_am335x_tsc.c
> @@ -52,6 +52,7 @@ struct titsc {
>  	u32			config_inp[4];
>  	u32			bit_xp, bit_xn, bit_yp, bit_yn;
>  	u32			inp_xp, inp_xn, inp_yp, inp_yn;
> +	u32			step_mask;
>  };
>  
>  static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
> @@ -196,7 +197,8 @@ static void titsc_step_config(struct titsc *ts_dev)
>  
>  	/* The steps1 … end and bit 0 for TS_Charge */
>  	stepenable = (1 << (end_step + 2)) - 1;
> -	am335x_tsc_se_set(ts_dev->mfd_tscadc, stepenable);
> +	ts_dev->step_mask = stepenable;
> +	am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
>  }
>  
>  static void titsc_read_coordinates(struct titsc *ts_dev,
> @@ -260,6 +262,10 @@ static irqreturn_t titsc_irq(int irq, void *dev)
>  	unsigned int fsm;
>  
>  	status = titsc_readl(ts_dev, REG_IRQSTATUS);
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
> +	 */
>  	if (status & IRQENB_FIFO0THRES) {
>  
>  		titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
> @@ -316,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
>  
>  	if (irqclr) {
>  		titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
> -		am335x_tsc_se_update(ts_dev->mfd_tscadc);
> +		am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
>  		return IRQ_HANDLED;
>  	}
>  	return IRQ_NONE;
> @@ -389,7 +395,7 @@ static int titsc_probe(struct platform_device *pdev)
>  	}
>  
>  	err = request_irq(ts_dev->irq, titsc_irq,
> -			  0, pdev->dev.driver->name, ts_dev);
> +			  IRQF_SHARED, pdev->dev.driver->name, ts_dev);
>  	if (err) {
>  		dev_err(&pdev->dev, "failed to allocate irq.\n");
>  		goto err_free_mem;
> 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-08 13:42     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-08 13:42 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: dmitry.torokhov, linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On 09/01/13 12:17, Zubair Lutfullah wrote:
> Previously the driver had only one-shot reading functionality.
> This patch adds triggered buffer support to the driver.
>
> Continuous sampling starts when buffer is enabled.
> And samples are pushed to userpace by the trigger which
> triggers automatically at every hardware interrupt
> of FIFO1 filling with samples upto threshold value.
>
> Userspace responsibility to stop sampling by writing zero
> in the buffer enable file.
>
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
>
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added trigger support.
>
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Russ Dill <Russ.Dill@ti.com>
> Acked-by: Lee Jones <lee.jones@linaro.org>
> Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Hi

I'm afraid I'm still unconvinced that we can use the trigger infrastructure
as done here.  This trigger from a fifo threshold does not agree with how it
happens in any other driver. Unfortunately as the first hardware buffered
device we have had in recent times (there is the sca3000 in staging, but that
does not have a front end kfifo) you get to break some new ground.

I've suggested below how I would handle this.  In short, drop the trigger
and drive the buffers directly, marking the mode as INDIO_BUFFER_HARDWARE to
avoid the core code complaining at the lack of trigger.  It will end up simpler
and not expose a trigger to userspace that is doing 'interesting' things.
This is the only way I can envision a hardware buffer equiped device like this
working.  It's certainly what I've been intending to do with the sca3000
driver when I finally get around to bringing it up to date. I don't think
we can take the current approach because it would give us horribly inconsistent
userspace interfaces we can't maintain in the long run.

Few other little bits and bobs inline to do with unused variables and
a few places where a small comment or two might make the operation easier
to follow when we have all forgotten how the hardware works ;)

Jonathan

> ---
>  drivers/iio/adc/Kconfig              |    1 +
>  drivers/iio/adc/ti_am335x_adc.c      |  243 +++++++++++++++++++++++++++++++---
>  include/linux/mfd/ti_am335x_tscadc.h |   13 ++
>  3 files changed, 237 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 09371cb..cfa2039 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -167,6 +167,7 @@ config TI_ADC081C
>  config TI_AM335X_ADC
>  	tristate "TI's AM335X ADC driver"
>  	depends on MFD_TI_AM335X_TSCADC
> +	select IIO_TRIGGERED_BUFFER
>  	help
>  	  Say yes here to build support for Texas Instruments ADC
>  	  driver which is also a MFD client.
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index a952538..1626e16 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -24,16 +24,23 @@
>  #include <linux/iio/iio.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
Ouch, how did that slip in here.  Dropping this should have been
in a separate patch as it doesn't really have anything to do with
the rest of this series.

> -#include <linux/iio/machine.h>
>  #include <linux/iio/driver.h>
>
>  #include <linux/mfd/ti_am335x_tscadc.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>
>  struct tiadc_device {
>  	struct ti_tscadc_dev *mfd_tscadc;
>  	int channels;
>  	u8 channel_line[8];
>  	u8 channel_step[8];
> +	int irq;
> +	int buffer_en_ch_steps;
> +	struct iio_trigger *trig;
> +	u32 *data;
>  };
>
>  static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
> @@ -56,10 +63,16 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
>  	return step_en;
>  }
>
> -static void tiadc_step_config(struct tiadc_device *adc_dev)
> +static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
>  {
> +	return 1 << adc_dev->channel_step[chan];
> +}
> +
> +static void tiadc_step_config(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	unsigned int stepconfig;
> -	int i, steps;
> +	int i, steps, chan;
Whilst I agree that pulling chan up here is slightly cleaner, technically that
is a bit of unconnected cleanup and should have been in a precursor patch.
(though don't bother doing so now!)
>
>  	/*
>  	 * There are 16 configurable steps and 8 analog input
> @@ -72,11 +85,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>  	 */
>
>  	steps = TOTAL_STEPS - adc_dev->channels;
> -	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
> +	if (iio_buffer_enabled(indio_dev))
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
> +					| STEPCONFIG_MODE_SWCNT;
> +	else
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
>
>  	for (i = 0; i < adc_dev->channels; i++) {
> -		int chan;
> -
>  		chan = adc_dev->channel_line[i];
>  		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
>  				stepconfig | STEPCONFIG_INP(chan));
> @@ -85,7 +100,167 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>  		adc_dev->channel_step[i] = steps;
>  		steps++;
>  	}
> +}
> +
> +static irqreturn_t tiadc_irq(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	unsigned int status, config;
> +	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
> +
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
> +	 */
> +	if (status & IRQENB_FIFO1OVRRUN) {
> +		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
> +		config = tiadc_readl(adc_dev, REG_CTRL);
> +		config &= ~(CNTRLREG_TSCSSENB);
> +		tiadc_writel(adc_dev, REG_CTRL, config);
> +		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
> +				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
> +		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
> +		return IRQ_HANDLED;
> +	} else if (status & IRQENB_FIFO1THRES) {
> +		/* Trigger to push FIFO data to iio buffer */
> +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);

So this is triggering at the threshold.  Thus it isn't acting as a conventional
trigger in the IIO sense at all.  It is of no real use to anything outside
this driver, so at the very least add the two callbacks to prevent this
driver using any other trigger and the trigger being used by any other device.
However, I'm really not happy with this solution.

Take a look at running with no trigger at all and calling the buffer
filling more directly.  The issue is that if we have a trigger now it will
become part of the userspace interface and become a pain to drop later.

It is valid here I think to use the INDIO_BUFFER_HARDWARE mode (which skips
the checks for a trigger) then just don't call iio_triggered_buffer_post_enable
or iio_triggered_buffer_predisable.  Then make this a threaded interrupt and
put your tiadc_trigger_h as the thread.  Finally just return IRQ_WAKE_THREAD
in this case.  You'll have to pull a few bits out of
industrialio-triggered-buffer.c to create the kfifo etc, but no more than
a few lines given the pollfunc won't exist.

Actually, might be cleaner to move the flush case into the thread as well
and just have a single check in this top half of the handler. That bit
is up to you given it is really a question of how long it take and hence
if it is acceptable in interrupt context.

> +		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
> +		return IRQ_HANDLED;
> +	} else
> +		return IRQ_NONE;
> +
> +}
> +
> +static irqreturn_t tiadc_trigger_h(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, k, fifo1count, read;
> +	u32 *data = adc_dev->data;
> +

Hmm.. This results in all data in the fifo being read from a single
trigger.  I think I would still be happier if in the case of hardware
buffers like this we didn't use a visible trigger at all.  Such
a trigger has a somewhat fuzzy meaning to say the least.

> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (k = 0; k < fifo1count; k = k + i) {
As mentioned below, why not use 16 bit storage in the kfifo?
> +		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> +			read = tiadc_readl(adc_dev, REG_FIFO1);
> +			data[i] = read & FIFOREAD_DATA_MASK;
> +		}
> +		iio_push_to_buffers(indio_dev, (u8 *) data);
> +	}
>
> +	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
> +	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
> +
> +	iio_trigger_notify_done(indio_dev->trig);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, fifo1count, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN |
> +				IRQENB_FIFO1UNDRFLW));
> +

Why would there be data in the fifo?  Seems to me that flushing
after disabling it and before enabling it should not both be
necessary? Is this just a case of playing safe?

> +	/* Flush FIFO before starting sampling */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_sw_buffer_preenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_buffer *buffer = indio_dev->buffer;
> +	unsigned int enb = 0;
> +	u8 bit;
> +
> +	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> +	if (adc_dev->data == NULL)
> +		return -ENOMEM;
> +
> +	tiadc_step_config(indio_dev);
> +	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
> +		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
> +	adc_dev->buffer_en_ch_steps = enb;
> +
> +	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
> +
> +	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
> +	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN);
> +
> +	return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int fifo1count, i, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
> +	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
> +
> +	/* Flush FIFO of any leftover data */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_triggered_buffer_predisable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +
> +	tiadc_step_config(indio_dev);
> +	kfree(adc_dev->data);
blank line here please.

> +	return 0;
> +}
> +
> +static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
> +	.preenable = &tiadc_buffer_preenable,
> +	.postenable = &tiadc_buffer_postenable,
> +	.predisable = &tiadc_buffer_predisable,
> +	.postdisable = &tiadc_buffer_postdisable,
> +};
> +
> +static const struct iio_trigger_ops tiadc_trigger_ops = {
> +	.owner = THIS_MODULE,
> +};
> +

If you want a utility function for allocation, convention would
say have one for freeing as well so that the code is obviously
balanced and easy to check.  Also this registers the buffer as
well so the name should probably reflect that.

> +static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_trigger *trig = adc_dev->trig;
> +	int ret;
> +
devm_iio_trigger_alloc is now available and will simplify things a little.

> +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
> +	if (trig == NULL)
> +		return -ENOMEM;
> +
> +	trig->dev.parent = indio_dev->dev.parent;
> +	trig->ops = &tiadc_trigger_ops;
> +	iio_trigger_set_drvdata(trig, indio_dev);
> +
> +	ret = iio_trigger_register(trig);
> +	if (ret)
> +		goto err_free_trigger;
> +
> +	return 0;
> +
> +err_free_trigger:
> +	iio_trigger_free(adc_dev->trig);
> +
> +	return ret;
>  }
>
>  static const char * const chan_name_ain[] = {
> @@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
>  		chan->channel = adc_dev->channel_line[i];
>  		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
>  		chan->datasheet_name = chan_name_ain[chan->channel];
> +		chan->scan_index = i;
>  		chan->scan_type.sign = 'u';
>  		chan->scan_type.realbits = 12;
>  		chan->scan_type.storagebits = 32;
I never noticed this before but putting 12 bit values in 32 bit storage
does seem rather wasteful.  Far as I can see above there is no real
reason for doing so.  If there is, then please add a comment justifying this
choice!

> @@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	int i, map_val;
>  	unsigned int fifo1count, read, stepid;
> -	u32 step = UINT_MAX;
>  	bool found = false;
>  	u32 step_en;
>  	unsigned long timeout = jiffies + usecs_to_jiffies
>  				(IDLE_TIMEOUT * adc_dev->channels);
> +
> +	if (iio_buffer_enabled(indio_dev))
> +		return -EBUSY;
> +
>  	step_en = get_adc_step_mask(adc_dev);
>  	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
>
> @@ -168,15 +347,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
>  	 * Hence we need to flush out this data.
>  	 */
Is the comment above still valid?  I'd guess it referred to this code
which has now gone.
>
> -	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
> -		if (chan->channel == adc_dev->channel_line[i]) {
> -			step = adc_dev->channel_step[i];
> -			break;
> -		}
> -	}
> -	if (WARN_ON_ONCE(step == UINT_MAX))
> -		return -EINVAL;
> -
>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>  	for (i = 0; i < fifo1count; i++) {
>  		read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -231,26 +401,49 @@ static int tiadc_probe(struct platform_device *pdev)
>  		channels++;
>  	}
>  	adc_dev->channels = channels;

Use the devm interfaces and there is no need to keep a copy
of the irq number about.

> +	adc_dev->irq = adc_dev->mfd_tscadc->irq;
>
>  	indio_dev->dev.parent = &pdev->dev;
>  	indio_dev->name = dev_name(&pdev->dev);
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->info = &tiadc_info;
>
> -	tiadc_step_config(adc_dev);
> +	tiadc_step_config(indio_dev);
> +	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
>
>  	err = tiadc_channel_init(indio_dev, adc_dev->channels);
>  	if (err < 0)
>  		return err;
>
> -	err = iio_device_register(indio_dev);
> +	err = tiadc_iio_allocate_trigger(indio_dev);
>  	if (err)
>  		goto err_free_channels;
>
devm_request_irq will simplify error handling a little.

> +	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
> +		indio_dev->name, indio_dev);
> +	if (err)
> +		goto err_unregister_trigger;
> +
> +	err = iio_triggered_buffer_setup(indio_dev, NULL,
> +			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
> +	if (err)
> +		goto err_free_irq;
> +
> +	err = iio_device_register(indio_dev);
> +	if (err)
> +		goto err_buffer_unregister;
> +
>  	platform_set_drvdata(pdev, indio_dev);
>
>  	return 0;
>
> +err_buffer_unregister:
> +	iio_buffer_unregister(indio_dev);
> +err_free_irq:
> +	free_irq(adc_dev->irq, indio_dev);
> +err_unregister_trigger:
> +	iio_trigger_unregister(adc_dev->trig);
> +	iio_trigger_free(adc_dev->trig);
>  err_free_channels:
>  	tiadc_channels_remove(indio_dev);
>  	return err;
> @@ -262,7 +455,11 @@ static int tiadc_remove(struct platform_device *pdev)
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	u32 step_en;
>
> +	iio_trigger_unregister(adc_dev->trig);
> +	iio_trigger_free(adc_dev->trig);
There is a devm trigger allocation function now. Using that
would make things a little cleaner.

> +	free_irq(adc_dev->irq, indio_dev);
Best to use the devm interfaces for irq handling unless
there is a good reason to not do so (cleaner code ;)

>  	iio_device_unregister(indio_dev);

We would normally expect this function to run in exact
reverse order of the probe.  That is not the case here
so please reorder things so it is.
> +	iio_buffer_unregister(indio_dev);
>  	tiadc_channels_remove(indio_dev);
>
>  	step_en = get_adc_step_mask(adc_dev);
> @@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
>
>  	/* Make sure ADC is powered up */
This comment doesn't seem to me to be true any more.
>  	restore = tiadc_readl(adc_dev, REG_CTRL);
> -	restore &= ~(CNTRLREG_POWERDOWN);
Some coments here would be good to explain the sequence that
is going on.

I'm guessing a bit, but looks like you turn off the touch screen
but leave everything else alone, then set the threshold then
reenable the touch screen before powering up the screen?

> +	restore &= ~(CNTRLREG_TSCSSENB);
>  	tiadc_writel(adc_dev, REG_CTRL, restore);
>
> -	tiadc_step_config(adc_dev);
> +	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
> +	tiadc_step_config(indio_dev);
> +
> +	/* Make sure ADC is powered up */
> +	restore &= ~(CNTRLREG_POWERDOWN);
> +	restore |= CNTRLREG_TSCSSENB;
> +	tiadc_writel(adc_dev, REG_CTRL, restore);
>
>  	return 0;
>  }
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index db1791b..a372ebf 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -46,17 +46,25 @@
>  /* Step Enable */
>  #define STEPENB_MASK		(0x1FFFF << 0)
>  #define STEPENB(val)		((val) << 0)
> +#define ENB(val)			(1 << (val))
> +#define STPENB_STEPENB		STEPENB(0x1FFFF)
> +#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
>
>  /* IRQ enable */
>  #define IRQENB_HW_PEN		BIT(0)
>  #define IRQENB_FIFO0THRES	BIT(2)
> +#define IRQENB_FIFO0OVRRUN	BIT(3)
> +#define IRQENB_FIFO0UNDRFLW	BIT(4)
>  #define IRQENB_FIFO1THRES	BIT(5)
> +#define IRQENB_FIFO1OVRRUN	BIT(6)
> +#define IRQENB_FIFO1UNDRFLW	BIT(7)
>  #define IRQENB_PENUP		BIT(9)
>
>  /* Step Configuration */
>  #define STEPCONFIG_MODE_MASK	(3 << 0)
>  #define STEPCONFIG_MODE(val)	((val) << 0)
>  #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
> +#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
>  #define STEPCONFIG_AVG_MASK	(7 << 2)
>  #define STEPCONFIG_AVG(val)	((val) << 2)
>  #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
> @@ -124,6 +132,7 @@
>  #define	MAX_CLK_DIV		7
>  #define TOTAL_STEPS		16
>  #define TOTAL_CHANNELS		8
> +#define FIFO1_THRESHOLD		19
>
>  /*
>  * ADC runs at 3MHz, and it takes
> @@ -153,6 +162,10 @@ struct ti_tscadc_dev {
>
>  	/* adc device */
>  	struct adc_device *adc;
> +
> +	/* Context save */
> +	unsigned int irqstat;
Where are these used?
> +	unsigned int ctrl;
>  };
>
>  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
>

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-08 13:42     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-08 13:42 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On 09/01/13 12:17, Zubair Lutfullah wrote:
> Previously the driver had only one-shot reading functionality.
> This patch adds triggered buffer support to the driver.
>
> Continuous sampling starts when buffer is enabled.
> And samples are pushed to userpace by the trigger which
> triggers automatically at every hardware interrupt
> of FIFO1 filling with samples upto threshold value.
>
> Userspace responsibility to stop sampling by writing zero
> in the buffer enable file.
>
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
>
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added trigger support.
>
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> Signed-off-by: Russ Dill <Russ.Dill-l0cyMroinI0@public.gmane.org>
> Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Acked-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>

Hi

I'm afraid I'm still unconvinced that we can use the trigger infrastructure
as done here.  This trigger from a fifo threshold does not agree with how it
happens in any other driver. Unfortunately as the first hardware buffered
device we have had in recent times (there is the sca3000 in staging, but that
does not have a front end kfifo) you get to break some new ground.

I've suggested below how I would handle this.  In short, drop the trigger
and drive the buffers directly, marking the mode as INDIO_BUFFER_HARDWARE to
avoid the core code complaining at the lack of trigger.  It will end up simpler
and not expose a trigger to userspace that is doing 'interesting' things.
This is the only way I can envision a hardware buffer equiped device like this
working.  It's certainly what I've been intending to do with the sca3000
driver when I finally get around to bringing it up to date. I don't think
we can take the current approach because it would give us horribly inconsistent
userspace interfaces we can't maintain in the long run.

Few other little bits and bobs inline to do with unused variables and
a few places where a small comment or two might make the operation easier
to follow when we have all forgotten how the hardware works ;)

Jonathan

> ---
>  drivers/iio/adc/Kconfig              |    1 +
>  drivers/iio/adc/ti_am335x_adc.c      |  243 +++++++++++++++++++++++++++++++---
>  include/linux/mfd/ti_am335x_tscadc.h |   13 ++
>  3 files changed, 237 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 09371cb..cfa2039 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -167,6 +167,7 @@ config TI_ADC081C
>  config TI_AM335X_ADC
>  	tristate "TI's AM335X ADC driver"
>  	depends on MFD_TI_AM335X_TSCADC
> +	select IIO_TRIGGERED_BUFFER
>  	help
>  	  Say yes here to build support for Texas Instruments ADC
>  	  driver which is also a MFD client.
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index a952538..1626e16 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -24,16 +24,23 @@
>  #include <linux/iio/iio.h>
>  #include <linux/of.h>
>  #include <linux/of_device.h>
Ouch, how did that slip in here.  Dropping this should have been
in a separate patch as it doesn't really have anything to do with
the rest of this series.

> -#include <linux/iio/machine.h>
>  #include <linux/iio/driver.h>
>
>  #include <linux/mfd/ti_am335x_tscadc.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>
>  struct tiadc_device {
>  	struct ti_tscadc_dev *mfd_tscadc;
>  	int channels;
>  	u8 channel_line[8];
>  	u8 channel_step[8];
> +	int irq;
> +	int buffer_en_ch_steps;
> +	struct iio_trigger *trig;
> +	u32 *data;
>  };
>
>  static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
> @@ -56,10 +63,16 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
>  	return step_en;
>  }
>
> -static void tiadc_step_config(struct tiadc_device *adc_dev)
> +static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
>  {
> +	return 1 << adc_dev->channel_step[chan];
> +}
> +
> +static void tiadc_step_config(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	unsigned int stepconfig;
> -	int i, steps;
> +	int i, steps, chan;
Whilst I agree that pulling chan up here is slightly cleaner, technically that
is a bit of unconnected cleanup and should have been in a precursor patch.
(though don't bother doing so now!)
>
>  	/*
>  	 * There are 16 configurable steps and 8 analog input
> @@ -72,11 +85,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>  	 */
>
>  	steps = TOTAL_STEPS - adc_dev->channels;
> -	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
> +	if (iio_buffer_enabled(indio_dev))
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
> +					| STEPCONFIG_MODE_SWCNT;
> +	else
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
>
>  	for (i = 0; i < adc_dev->channels; i++) {
> -		int chan;
> -
>  		chan = adc_dev->channel_line[i];
>  		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
>  				stepconfig | STEPCONFIG_INP(chan));
> @@ -85,7 +100,167 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>  		adc_dev->channel_step[i] = steps;
>  		steps++;
>  	}
> +}
> +
> +static irqreturn_t tiadc_irq(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	unsigned int status, config;
> +	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
> +
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
> +	 */
> +	if (status & IRQENB_FIFO1OVRRUN) {
> +		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
> +		config = tiadc_readl(adc_dev, REG_CTRL);
> +		config &= ~(CNTRLREG_TSCSSENB);
> +		tiadc_writel(adc_dev, REG_CTRL, config);
> +		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
> +				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
> +		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
> +		return IRQ_HANDLED;
> +	} else if (status & IRQENB_FIFO1THRES) {
> +		/* Trigger to push FIFO data to iio buffer */
> +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);

So this is triggering at the threshold.  Thus it isn't acting as a conventional
trigger in the IIO sense at all.  It is of no real use to anything outside
this driver, so at the very least add the two callbacks to prevent this
driver using any other trigger and the trigger being used by any other device.
However, I'm really not happy with this solution.

Take a look at running with no trigger at all and calling the buffer
filling more directly.  The issue is that if we have a trigger now it will
become part of the userspace interface and become a pain to drop later.

It is valid here I think to use the INDIO_BUFFER_HARDWARE mode (which skips
the checks for a trigger) then just don't call iio_triggered_buffer_post_enable
or iio_triggered_buffer_predisable.  Then make this a threaded interrupt and
put your tiadc_trigger_h as the thread.  Finally just return IRQ_WAKE_THREAD
in this case.  You'll have to pull a few bits out of
industrialio-triggered-buffer.c to create the kfifo etc, but no more than
a few lines given the pollfunc won't exist.

Actually, might be cleaner to move the flush case into the thread as well
and just have a single check in this top half of the handler. That bit
is up to you given it is really a question of how long it take and hence
if it is acceptable in interrupt context.

> +		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
> +		return IRQ_HANDLED;
> +	} else
> +		return IRQ_NONE;
> +
> +}
> +
> +static irqreturn_t tiadc_trigger_h(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, k, fifo1count, read;
> +	u32 *data = adc_dev->data;
> +

Hmm.. This results in all data in the fifo being read from a single
trigger.  I think I would still be happier if in the case of hardware
buffers like this we didn't use a visible trigger at all.  Such
a trigger has a somewhat fuzzy meaning to say the least.

> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (k = 0; k < fifo1count; k = k + i) {
As mentioned below, why not use 16 bit storage in the kfifo?
> +		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> +			read = tiadc_readl(adc_dev, REG_FIFO1);
> +			data[i] = read & FIFOREAD_DATA_MASK;
> +		}
> +		iio_push_to_buffers(indio_dev, (u8 *) data);
> +	}
>
> +	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
> +	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
> +
> +	iio_trigger_notify_done(indio_dev->trig);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, fifo1count, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN |
> +				IRQENB_FIFO1UNDRFLW));
> +

Why would there be data in the fifo?  Seems to me that flushing
after disabling it and before enabling it should not both be
necessary? Is this just a case of playing safe?

> +	/* Flush FIFO before starting sampling */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_sw_buffer_preenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_buffer *buffer = indio_dev->buffer;
> +	unsigned int enb = 0;
> +	u8 bit;
> +
> +	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> +	if (adc_dev->data == NULL)
> +		return -ENOMEM;
> +
> +	tiadc_step_config(indio_dev);
> +	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
> +		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
> +	adc_dev->buffer_en_ch_steps = enb;
> +
> +	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
> +
> +	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
> +	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN);
> +
> +	return iio_triggered_buffer_postenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int fifo1count, i, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
> +	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
> +
> +	/* Flush FIFO of any leftover data */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_triggered_buffer_predisable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +
> +	tiadc_step_config(indio_dev);
> +	kfree(adc_dev->data);
blank line here please.

> +	return 0;
> +}
> +
> +static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
> +	.preenable = &tiadc_buffer_preenable,
> +	.postenable = &tiadc_buffer_postenable,
> +	.predisable = &tiadc_buffer_predisable,
> +	.postdisable = &tiadc_buffer_postdisable,
> +};
> +
> +static const struct iio_trigger_ops tiadc_trigger_ops = {
> +	.owner = THIS_MODULE,
> +};
> +

If you want a utility function for allocation, convention would
say have one for freeing as well so that the code is obviously
balanced and easy to check.  Also this registers the buffer as
well so the name should probably reflect that.

> +static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_trigger *trig = adc_dev->trig;
> +	int ret;
> +
devm_iio_trigger_alloc is now available and will simplify things a little.

> +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
> +	if (trig == NULL)
> +		return -ENOMEM;
> +
> +	trig->dev.parent = indio_dev->dev.parent;
> +	trig->ops = &tiadc_trigger_ops;
> +	iio_trigger_set_drvdata(trig, indio_dev);
> +
> +	ret = iio_trigger_register(trig);
> +	if (ret)
> +		goto err_free_trigger;
> +
> +	return 0;
> +
> +err_free_trigger:
> +	iio_trigger_free(adc_dev->trig);
> +
> +	return ret;
>  }
>
>  static const char * const chan_name_ain[] = {
> @@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
>  		chan->channel = adc_dev->channel_line[i];
>  		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
>  		chan->datasheet_name = chan_name_ain[chan->channel];
> +		chan->scan_index = i;
>  		chan->scan_type.sign = 'u';
>  		chan->scan_type.realbits = 12;
>  		chan->scan_type.storagebits = 32;
I never noticed this before but putting 12 bit values in 32 bit storage
does seem rather wasteful.  Far as I can see above there is no real
reason for doing so.  If there is, then please add a comment justifying this
choice!

> @@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	int i, map_val;
>  	unsigned int fifo1count, read, stepid;
> -	u32 step = UINT_MAX;
>  	bool found = false;
>  	u32 step_en;
>  	unsigned long timeout = jiffies + usecs_to_jiffies
>  				(IDLE_TIMEOUT * adc_dev->channels);
> +
> +	if (iio_buffer_enabled(indio_dev))
> +		return -EBUSY;
> +
>  	step_en = get_adc_step_mask(adc_dev);
>  	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
>
> @@ -168,15 +347,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
>  	 * Hence we need to flush out this data.
>  	 */
Is the comment above still valid?  I'd guess it referred to this code
which has now gone.
>
> -	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
> -		if (chan->channel == adc_dev->channel_line[i]) {
> -			step = adc_dev->channel_step[i];
> -			break;
> -		}
> -	}
> -	if (WARN_ON_ONCE(step == UINT_MAX))
> -		return -EINVAL;
> -
>  	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>  	for (i = 0; i < fifo1count; i++) {
>  		read = tiadc_readl(adc_dev, REG_FIFO1);
> @@ -231,26 +401,49 @@ static int tiadc_probe(struct platform_device *pdev)
>  		channels++;
>  	}
>  	adc_dev->channels = channels;

Use the devm interfaces and there is no need to keep a copy
of the irq number about.

> +	adc_dev->irq = adc_dev->mfd_tscadc->irq;
>
>  	indio_dev->dev.parent = &pdev->dev;
>  	indio_dev->name = dev_name(&pdev->dev);
>  	indio_dev->modes = INDIO_DIRECT_MODE;
>  	indio_dev->info = &tiadc_info;
>
> -	tiadc_step_config(adc_dev);
> +	tiadc_step_config(indio_dev);
> +	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
>
>  	err = tiadc_channel_init(indio_dev, adc_dev->channels);
>  	if (err < 0)
>  		return err;
>
> -	err = iio_device_register(indio_dev);
> +	err = tiadc_iio_allocate_trigger(indio_dev);
>  	if (err)
>  		goto err_free_channels;
>
devm_request_irq will simplify error handling a little.

> +	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
> +		indio_dev->name, indio_dev);
> +	if (err)
> +		goto err_unregister_trigger;
> +
> +	err = iio_triggered_buffer_setup(indio_dev, NULL,
> +			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
> +	if (err)
> +		goto err_free_irq;
> +
> +	err = iio_device_register(indio_dev);
> +	if (err)
> +		goto err_buffer_unregister;
> +
>  	platform_set_drvdata(pdev, indio_dev);
>
>  	return 0;
>
> +err_buffer_unregister:
> +	iio_buffer_unregister(indio_dev);
> +err_free_irq:
> +	free_irq(adc_dev->irq, indio_dev);
> +err_unregister_trigger:
> +	iio_trigger_unregister(adc_dev->trig);
> +	iio_trigger_free(adc_dev->trig);
>  err_free_channels:
>  	tiadc_channels_remove(indio_dev);
>  	return err;
> @@ -262,7 +455,11 @@ static int tiadc_remove(struct platform_device *pdev)
>  	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>  	u32 step_en;
>
> +	iio_trigger_unregister(adc_dev->trig);
> +	iio_trigger_free(adc_dev->trig);
There is a devm trigger allocation function now. Using that
would make things a little cleaner.

> +	free_irq(adc_dev->irq, indio_dev);
Best to use the devm interfaces for irq handling unless
there is a good reason to not do so (cleaner code ;)

>  	iio_device_unregister(indio_dev);

We would normally expect this function to run in exact
reverse order of the probe.  That is not the case here
so please reorder things so it is.
> +	iio_buffer_unregister(indio_dev);
>  	tiadc_channels_remove(indio_dev);
>
>  	step_en = get_adc_step_mask(adc_dev);
> @@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
>
>  	/* Make sure ADC is powered up */
This comment doesn't seem to me to be true any more.
>  	restore = tiadc_readl(adc_dev, REG_CTRL);
> -	restore &= ~(CNTRLREG_POWERDOWN);
Some coments here would be good to explain the sequence that
is going on.

I'm guessing a bit, but looks like you turn off the touch screen
but leave everything else alone, then set the threshold then
reenable the touch screen before powering up the screen?

> +	restore &= ~(CNTRLREG_TSCSSENB);
>  	tiadc_writel(adc_dev, REG_CTRL, restore);
>
> -	tiadc_step_config(adc_dev);
> +	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
> +	tiadc_step_config(indio_dev);
> +
> +	/* Make sure ADC is powered up */
> +	restore &= ~(CNTRLREG_POWERDOWN);
> +	restore |= CNTRLREG_TSCSSENB;
> +	tiadc_writel(adc_dev, REG_CTRL, restore);
>
>  	return 0;
>  }
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index db1791b..a372ebf 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -46,17 +46,25 @@
>  /* Step Enable */
>  #define STEPENB_MASK		(0x1FFFF << 0)
>  #define STEPENB(val)		((val) << 0)
> +#define ENB(val)			(1 << (val))
> +#define STPENB_STEPENB		STEPENB(0x1FFFF)
> +#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
>
>  /* IRQ enable */
>  #define IRQENB_HW_PEN		BIT(0)
>  #define IRQENB_FIFO0THRES	BIT(2)
> +#define IRQENB_FIFO0OVRRUN	BIT(3)
> +#define IRQENB_FIFO0UNDRFLW	BIT(4)
>  #define IRQENB_FIFO1THRES	BIT(5)
> +#define IRQENB_FIFO1OVRRUN	BIT(6)
> +#define IRQENB_FIFO1UNDRFLW	BIT(7)
>  #define IRQENB_PENUP		BIT(9)
>
>  /* Step Configuration */
>  #define STEPCONFIG_MODE_MASK	(3 << 0)
>  #define STEPCONFIG_MODE(val)	((val) << 0)
>  #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
> +#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
>  #define STEPCONFIG_AVG_MASK	(7 << 2)
>  #define STEPCONFIG_AVG(val)	((val) << 2)
>  #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
> @@ -124,6 +132,7 @@
>  #define	MAX_CLK_DIV		7
>  #define TOTAL_STEPS		16
>  #define TOTAL_CHANNELS		8
> +#define FIFO1_THRESHOLD		19
>
>  /*
>  * ADC runs at 3MHz, and it takes
> @@ -153,6 +162,10 @@ struct ti_tscadc_dev {
>
>  	/* adc device */
>  	struct adc_device *adc;
> +
> +	/* Context save */
> +	unsigned int irqstat;
Where are these used?
> +	unsigned int ctrl;
>  };
>
>  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
>

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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-09 16:12       ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-09 16:12 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On Sun, Sep 08, 2013 at 12:29:26PM +0100, Jonathan Cameron wrote:
> On 09/01/13 12:17, Zubair Lutfullah wrote:
> > Enable shared IRQ to allow ADC to share IRQ line from
> > parent MFD core. Only FIFO0 IRQs are for TSC and handled
> > on the TSC side.
> > 
> > Step mask would be updated from cached variable only previously.
> > In rare cases when both TSC and ADC are used, the cached
> > variable gets mixed up.
> > The step mask is written with the required mask every time.
> > 
> > Rachna Patil (TI) laid ground work for shared IRQ.
> > 
> > Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> Whilst I would have prefered an mfd under these drivers and elegant handling
> of the interrupts, I guess if this works it is at least not terribly invasive.
> 
> However, this does need an Ack from Dmitry before I can take it (or for
> Dmitry to take it himself?)

I completely agree with Jonathan, more elegant handling would be nice
but current one will do for now.

Since most of the work on the driver is going through IIO tree I think
it would make sense for this patch to go through it as well.

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Thanks.

-- 
Dmitry

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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-09 16:12       ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-09 16:12 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Sun, Sep 08, 2013 at 12:29:26PM +0100, Jonathan Cameron wrote:
> On 09/01/13 12:17, Zubair Lutfullah wrote:
> > Enable shared IRQ to allow ADC to share IRQ line from
> > parent MFD core. Only FIFO0 IRQs are for TSC and handled
> > on the TSC side.
> > 
> > Step mask would be updated from cached variable only previously.
> > In rare cases when both TSC and ADC are used, the cached
> > variable gets mixed up.
> > The step mask is written with the required mask every time.
> > 
> > Rachna Patil (TI) laid ground work for shared IRQ.
> > 
> > Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Whilst I would have prefered an mfd under these drivers and elegant handling
> of the interrupts, I guess if this works it is at least not terribly invasive.
> 
> However, this does need an Ack from Dmitry before I can take it (or for
> Dmitry to take it himself?)

I completely agree with Jonathan, more elegant handling would be nice
but current one will do for now.

Since most of the work on the driver is going through IIO tree I think
it would make sense for this patch to go through it as well.

Acked-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-11 16:02       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-11 16:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, dmitry.torokhov, linux-iio, linux-input,
	linux-kernel, bigeasy, gregkh

On Sun, Sep 08, 2013 at 02:42:51PM +0100, Jonathan Cameron wrote:
> On 09/01/13 12:17, Zubair Lutfullah wrote:

Thanks for the review. Fitting this driver in the usual trigger ABI
is a bad workaround indeed.

I am still a bit unclear regarding the implementation.
Questions and replies inline.

I hope I find the time to pursue the approach you suggest.

Thanks
ZubairLK


> >  #include <linux/of.h>
> Ouch, how did that slip in here.  Dropping this should have been
> in a separate patch as it doesn't really have anything to do with
> the rest of this series.
> 
> > -#include <linux/iio/machine.h>

Squashed it in.. I'll do a cleanup patch separately.

> >  #include <linux/iio/driver.h>
> > +static void tiadc_step_config(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >  	unsigned int stepconfig;
> > -	int i, steps;
> > +	int i, steps, chan;
> Whilst I agree that pulling chan up here is slightly cleaner, technically that
> is a bit of unconnected cleanup and should have been in a precursor patch.
> (though don't bother doing so now!)

Again. Squashed in..

> > +
> > +static irqreturn_t tiadc_irq(int irq, void *private)
> > +{
...
> > +		return IRQ_HANDLED;
> > +	} else if (status & IRQENB_FIFO1THRES) {
> > +		/* Trigger to push FIFO data to iio buffer */
> > +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
> 
> So this is triggering at the threshold.  Thus it isn't acting as a conventional
> trigger in the IIO sense at all.  It is of no real use to anything outside
> this driver, so at the very least add the two callbacks to prevent this
> driver using any other trigger and the trigger being used by any other device.
> However, I'm really not happy with this solution.
> 
> Take a look at running with no trigger at all and calling the buffer
> filling more directly.  The issue is that if we have a trigger now it will
> become part of the userspace interface and become a pain to drop later.
> 
> It is valid here I think to use the INDIO_BUFFER_HARDWARE mode (which skips
> the checks for a trigger) then just don't call iio_triggered_buffer_post_enable
> or iio_triggered_buffer_predisable.  Then make this a threaded interrupt and
> put your tiadc_trigger_h as the thread.  Finally just return IRQ_WAKE_THREAD
> in this case.  You'll have to pull a few bits out of
> industrialio-triggered-buffer.c to create the kfifo etc, but no more than
> a few lines given the pollfunc won't exist.

If I understand correctly.
buffer setup ops for postenable and predisable have 

return iio_triggered_buffer_*(indio_dev)

calls at the end. I return 0 instead.

Insead of iio_triggered_buffer setup. I only use iio_kfifo_alloc
(what size fifo is made? :s )
And do 

indio_dev->modes |= INDIO_BUFFER_HARDWARE;

Then I use request_threaded_irq(*). The hardware IRQ line for the fifos
So the HW irq handler runs in interrupt context which wakes the threaded handler
which pushes samples to the iio buffer.

Shared IRQ line. ADC uses request_threaded_irq(). TSC uses request_irq()
ADC returns IRQ_WAKE_THREAD. But the TSC side returns NONE/HANDLED.
Does this change to a threaded irq affect the TSC side of things?
I just received an ack by Dmitry for that patch..

> 
> Actually, might be cleaner to move the flush case into the thread as well
> and just have a single check in this top half of the handler. That bit
> is up to you given it is really a question of how long it take and hence
> if it is acceptable in interrupt context.

Sorry. I don't understand this paragraph.. Could you please elaborate?
The flushing fifo before/after enabling/disabling the buffer part? 
I explained the reason behind the flushes

> 
> > +		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
> > +		return IRQ_HANDLED;
> > +	} else
> > +		return IRQ_NONE;
> > +
> > +}
> > +
> > +static irqreturn_t tiadc_trigger_h(int irq, void *p)
> > +{
...
> 
> > +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> > +	for (k = 0; k < fifo1count; k = k + i) {
> As mentioned below, why not use 16 bit storage in the kfifo?

32 bit storage is because the FIFO is 32 bit in hardware.
It returns 12 bits data. some reserve bits. And 4 bit channel id.
The channel id is used to separate which channel data which.
Need the full 32 bits..

I've added a comment. Not here. but when the storage_bits = 32 is 
set.

...
> > +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
...
> Why would there be data in the fifo?  Seems to me that flushing
> after disabling it and before enabling it should not both be
> necessary? Is this just a case of playing safe?
> 
> > +	/* Flush FIFO before starting sampling */
> > +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> > +	for (i = 0; i < fifo1count; i++)
> > +		read = tiadc_readl(adc_dev, REG_FIFO1);

Pre-flush was needed because TSC events would cause some
redundant ADC samples in the FIFO. Fixes have been sent to input.
Shouldn't happen now.

Post-flush is playing safe. There 'might' be a chance that 
another sample comes in the time it takes for fifocount to be read
And that number of samples read from fifo. and then adc disabled.

> > +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > +
> > +	tiadc_step_config(indio_dev);
> > +	kfree(adc_dev->data);
> blank line here please.

ok

> > +	return 0;
> > +}
> > +
> > +static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
> > +	.preenable = &tiadc_buffer_preenable,
> > +	.postenable = &tiadc_buffer_postenable,
> > +	.predisable = &tiadc_buffer_predisable,
> > +	.postdisable = &tiadc_buffer_postdisable,
> > +};
> > +
> > +static const struct iio_trigger_ops tiadc_trigger_ops = {
> > +	.owner = THIS_MODULE,
> > +};
> > +
> 
> If you want a utility function for allocation, convention would
> say have one for freeing as well so that the code is obviously
> balanced and easy to check.  Also this registers the buffer as
> well so the name should probably reflect that.
> 

Noted.

> > +static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > +	struct iio_trigger *trig = adc_dev->trig;
> > +	int ret;
> > +
> devm_iio_trigger_alloc is now available and will simplify things a little.
> 

Trigger related stuff is redundant anyways as moving away from trigger..

> > +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);

> > @@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
> >  		chan->scan_type.realbits = 12;
> >  		chan->scan_type.storagebits = 32;
> I never noticed this before but putting 12 bit values in 32 bit storage
> does seem rather wasteful.  Far as I can see above there is no real
> reason for doing so.  If there is, then please add a comment justifying this
> choice!
>

Answered earlier. I added a comment here explaining. 

> > @@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
...
> >  	 * Hence we need to flush out this data.
> >  	 */
> Is the comment above still valid?  I'd guess it referred to this code
> which has now gone.
> >

Its valid when the comment is read completely. All ADC channels
are sampled even if only one is read. The one needed is returned
to userspace. The rest of the fifo is flushed. 

Not the ideal way. But I'm focusing on continuous sampling mode at the moment

> >  	adc_dev->channels = channels;
> 
> Use the devm interfaces and there is no need to keep a copy
> of the irq number about.
>

Noted. 
...

> >
> devm_request_irq will simplify error handling a little.
> 

Indeed error handling gets confusing. I'll update.
...

> > +	iio_trigger_free(adc_dev->trig);
> There is a devm trigger allocation function now. Using that
> would make things a little cleaner.

Noted

> 
> > +	free_irq(adc_dev->irq, indio_dev);
> Best to use the devm interfaces for irq handling unless
> there is a good reason to not do so (cleaner code ;)
> 
> >  	iio_device_unregister(indio_dev);
> 

Noted.

> We would normally expect this function to run in exact
> reverse order of the probe.  That is not the case here
> so please reorder things so it is.
> > +	iio_buffer_unregister(indio_dev);

I'll look into it.

> >  	tiadc_channels_remove(indio_dev);
> >
> >  	step_en = get_adc_step_mask(adc_dev);
> > @@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
> >
> >  	/* Make sure ADC is powered up */
> This comment doesn't seem to me to be true any more.
> >  	restore = tiadc_readl(adc_dev, REG_CTRL);
> > -	restore &= ~(CNTRLREG_POWERDOWN);
> Some coments here would be good to explain the sequence that
> is going on.
> 
> I'm guessing a bit, but looks like you turn off the touch screen
> but leave everything else alone, then set the threshold then
> reenable the touch screen before powering up the screen?
> 

To be honest. I don't even remember. 
It might have been a patch I squashed in.
does not seem to be related to the continuous sampling I guess..
I should remove this and send it separately.

> > +	restore &= ~(CNTRLREG_TSCSSENB);
...
> >  	tiadc_writel(adc_dev, REG_CTRL, restore);
> >  	return 0;
> >  }
> > diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> > index db1791b..a372ebf 100644
> > --- a/include/linux/mfd/ti_am335x_tscadc.h
> > +++ b/include/linux/mfd/ti_am335x_tscadc.h
> > @@ -46,17 +46,25 @@
> >  	/* adc device */
> >  	struct adc_device *adc;
> > +
> > +	/* Context save */
> > +	unsigned int irqstat;
> Where are these used?
> > +	unsigned int ctrl;
> >  };
Oops. Don't think they are used anywhere.
Thanks for pointing it out.
> >
> >  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
> >

Thanks
ZubairLK

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-11 16:02       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-11 16:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Sun, Sep 08, 2013 at 02:42:51PM +0100, Jonathan Cameron wrote:
> On 09/01/13 12:17, Zubair Lutfullah wrote:

Thanks for the review. Fitting this driver in the usual trigger ABI
is a bad workaround indeed.

I am still a bit unclear regarding the implementation.
Questions and replies inline.

I hope I find the time to pursue the approach you suggest.

Thanks
ZubairLK


> >  #include <linux/of.h>
> Ouch, how did that slip in here.  Dropping this should have been
> in a separate patch as it doesn't really have anything to do with
> the rest of this series.
> 
> > -#include <linux/iio/machine.h>

Squashed it in.. I'll do a cleanup patch separately.

> >  #include <linux/iio/driver.h>
> > +static void tiadc_step_config(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >  	unsigned int stepconfig;
> > -	int i, steps;
> > +	int i, steps, chan;
> Whilst I agree that pulling chan up here is slightly cleaner, technically that
> is a bit of unconnected cleanup and should have been in a precursor patch.
> (though don't bother doing so now!)

Again. Squashed in..

> > +
> > +static irqreturn_t tiadc_irq(int irq, void *private)
> > +{
...
> > +		return IRQ_HANDLED;
> > +	} else if (status & IRQENB_FIFO1THRES) {
> > +		/* Trigger to push FIFO data to iio buffer */
> > +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
> 
> So this is triggering at the threshold.  Thus it isn't acting as a conventional
> trigger in the IIO sense at all.  It is of no real use to anything outside
> this driver, so at the very least add the two callbacks to prevent this
> driver using any other trigger and the trigger being used by any other device.
> However, I'm really not happy with this solution.
> 
> Take a look at running with no trigger at all and calling the buffer
> filling more directly.  The issue is that if we have a trigger now it will
> become part of the userspace interface and become a pain to drop later.
> 
> It is valid here I think to use the INDIO_BUFFER_HARDWARE mode (which skips
> the checks for a trigger) then just don't call iio_triggered_buffer_post_enable
> or iio_triggered_buffer_predisable.  Then make this a threaded interrupt and
> put your tiadc_trigger_h as the thread.  Finally just return IRQ_WAKE_THREAD
> in this case.  You'll have to pull a few bits out of
> industrialio-triggered-buffer.c to create the kfifo etc, but no more than
> a few lines given the pollfunc won't exist.

If I understand correctly.
buffer setup ops for postenable and predisable have 

return iio_triggered_buffer_*(indio_dev)

calls at the end. I return 0 instead.

Insead of iio_triggered_buffer setup. I only use iio_kfifo_alloc
(what size fifo is made? :s )
And do 

indio_dev->modes |= INDIO_BUFFER_HARDWARE;

Then I use request_threaded_irq(*). The hardware IRQ line for the fifos
So the HW irq handler runs in interrupt context which wakes the threaded handler
which pushes samples to the iio buffer.

Shared IRQ line. ADC uses request_threaded_irq(). TSC uses request_irq()
ADC returns IRQ_WAKE_THREAD. But the TSC side returns NONE/HANDLED.
Does this change to a threaded irq affect the TSC side of things?
I just received an ack by Dmitry for that patch..

> 
> Actually, might be cleaner to move the flush case into the thread as well
> and just have a single check in this top half of the handler. That bit
> is up to you given it is really a question of how long it take and hence
> if it is acceptable in interrupt context.

Sorry. I don't understand this paragraph.. Could you please elaborate?
The flushing fifo before/after enabling/disabling the buffer part? 
I explained the reason behind the flushes

> 
> > +		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
> > +		return IRQ_HANDLED;
> > +	} else
> > +		return IRQ_NONE;
> > +
> > +}
> > +
> > +static irqreturn_t tiadc_trigger_h(int irq, void *p)
> > +{
...
> 
> > +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> > +	for (k = 0; k < fifo1count; k = k + i) {
> As mentioned below, why not use 16 bit storage in the kfifo?

32 bit storage is because the FIFO is 32 bit in hardware.
It returns 12 bits data. some reserve bits. And 4 bit channel id.
The channel id is used to separate which channel data which.
Need the full 32 bits..

I've added a comment. Not here. but when the storage_bits = 32 is 
set.

...
> > +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
...
> Why would there be data in the fifo?  Seems to me that flushing
> after disabling it and before enabling it should not both be
> necessary? Is this just a case of playing safe?
> 
> > +	/* Flush FIFO before starting sampling */
> > +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> > +	for (i = 0; i < fifo1count; i++)
> > +		read = tiadc_readl(adc_dev, REG_FIFO1);

Pre-flush was needed because TSC events would cause some
redundant ADC samples in the FIFO. Fixes have been sent to input.
Shouldn't happen now.

Post-flush is playing safe. There 'might' be a chance that 
another sample comes in the time it takes for fifocount to be read
And that number of samples read from fifo. and then adc disabled.

> > +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > +
> > +	tiadc_step_config(indio_dev);
> > +	kfree(adc_dev->data);
> blank line here please.

ok

> > +	return 0;
> > +}
> > +
> > +static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
> > +	.preenable = &tiadc_buffer_preenable,
> > +	.postenable = &tiadc_buffer_postenable,
> > +	.predisable = &tiadc_buffer_predisable,
> > +	.postdisable = &tiadc_buffer_postdisable,
> > +};
> > +
> > +static const struct iio_trigger_ops tiadc_trigger_ops = {
> > +	.owner = THIS_MODULE,
> > +};
> > +
> 
> If you want a utility function for allocation, convention would
> say have one for freeing as well so that the code is obviously
> balanced and easy to check.  Also this registers the buffer as
> well so the name should probably reflect that.
> 

Noted.

> > +static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> > +{
> > +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > +	struct iio_trigger *trig = adc_dev->trig;
> > +	int ret;
> > +
> devm_iio_trigger_alloc is now available and will simplify things a little.
> 

Trigger related stuff is redundant anyways as moving away from trigger..

> > +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);

> > @@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
> >  		chan->scan_type.realbits = 12;
> >  		chan->scan_type.storagebits = 32;
> I never noticed this before but putting 12 bit values in 32 bit storage
> does seem rather wasteful.  Far as I can see above there is no real
> reason for doing so.  If there is, then please add a comment justifying this
> choice!
>

Answered earlier. I added a comment here explaining. 

> > @@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
...
> >  	 * Hence we need to flush out this data.
> >  	 */
> Is the comment above still valid?  I'd guess it referred to this code
> which has now gone.
> >

Its valid when the comment is read completely. All ADC channels
are sampled even if only one is read. The one needed is returned
to userspace. The rest of the fifo is flushed. 

Not the ideal way. But I'm focusing on continuous sampling mode at the moment

> >  	adc_dev->channels = channels;
> 
> Use the devm interfaces and there is no need to keep a copy
> of the irq number about.
>

Noted. 
...

> >
> devm_request_irq will simplify error handling a little.
> 

Indeed error handling gets confusing. I'll update.
...

> > +	iio_trigger_free(adc_dev->trig);
> There is a devm trigger allocation function now. Using that
> would make things a little cleaner.

Noted

> 
> > +	free_irq(adc_dev->irq, indio_dev);
> Best to use the devm interfaces for irq handling unless
> there is a good reason to not do so (cleaner code ;)
> 
> >  	iio_device_unregister(indio_dev);
> 

Noted.

> We would normally expect this function to run in exact
> reverse order of the probe.  That is not the case here
> so please reorder things so it is.
> > +	iio_buffer_unregister(indio_dev);

I'll look into it.

> >  	tiadc_channels_remove(indio_dev);
> >
> >  	step_en = get_adc_step_mask(adc_dev);
> > @@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
> >
> >  	/* Make sure ADC is powered up */
> This comment doesn't seem to me to be true any more.
> >  	restore = tiadc_readl(adc_dev, REG_CTRL);
> > -	restore &= ~(CNTRLREG_POWERDOWN);
> Some coments here would be good to explain the sequence that
> is going on.
> 
> I'm guessing a bit, but looks like you turn off the touch screen
> but leave everything else alone, then set the threshold then
> reenable the touch screen before powering up the screen?
> 

To be honest. I don't even remember. 
It might have been a patch I squashed in.
does not seem to be related to the continuous sampling I guess..
I should remove this and send it separately.

> > +	restore &= ~(CNTRLREG_TSCSSENB);
...
> >  	tiadc_writel(adc_dev, REG_CTRL, restore);
> >  	return 0;
> >  }
> > diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> > index db1791b..a372ebf 100644
> > --- a/include/linux/mfd/ti_am335x_tscadc.h
> > +++ b/include/linux/mfd/ti_am335x_tscadc.h
> > @@ -46,17 +46,25 @@
> >  	/* adc device */
> >  	struct adc_device *adc;
> > +
> > +	/* Context save */
> > +	unsigned int irqstat;
> Where are these used?
> > +	unsigned int ctrl;
> >  };
Oops. Don't think they are used anywhere.
Thanks for pointing it out.
> >
> >  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
> >

Thanks
ZubairLK

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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-11 16:08         ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-11 16:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jonathan Cameron, Zubair Lutfullah, linux-iio, linux-input,
	linux-kernel, bigeasy, gregkh

On Mon, Sep 09, 2013 at 09:12:30AM -0700, Dmitry Torokhov wrote:
> On Sun, Sep 08, 2013 at 12:29:26PM +0100, Jonathan Cameron wrote:
> > On 09/01/13 12:17, Zubair Lutfullah wrote:
> > > Enable shared IRQ to allow ADC to share IRQ line from
> > > parent MFD core. Only FIFO0 IRQs are for TSC and handled
> > > on the TSC side.
> > > 
> > > Step mask would be updated from cached variable only previously.
> > > In rare cases when both TSC and ADC are used, the cached
> > > variable gets mixed up.
> > > The step mask is written with the required mask every time.
> > > 
> > > Rachna Patil (TI) laid ground work for shared IRQ.
> > > 
> > > Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> > Whilst I would have prefered an mfd under these drivers and elegant handling
> > of the interrupts, I guess if this works it is at least not terribly invasive.
> > 
> > However, this does need an Ack from Dmitry before I can take it (or for
> > Dmitry to take it himself?)
> 
> I completely agree with Jonathan, more elegant handling would be nice
> but current one will do for now.
> 
> Since most of the work on the driver is going through IIO tree I think
> it would make sense for this patch to go through it as well.
> 
> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Thank-you.
ZubairLK


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

* Re: [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC
@ 2013-09-11 16:08         ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-11 16:08 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jonathan Cameron, Zubair Lutfullah,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Mon, Sep 09, 2013 at 09:12:30AM -0700, Dmitry Torokhov wrote:
> On Sun, Sep 08, 2013 at 12:29:26PM +0100, Jonathan Cameron wrote:
> > On 09/01/13 12:17, Zubair Lutfullah wrote:
> > > Enable shared IRQ to allow ADC to share IRQ line from
> > > parent MFD core. Only FIFO0 IRQs are for TSC and handled
> > > on the TSC side.
> > > 
> > > Step mask would be updated from cached variable only previously.
> > > In rare cases when both TSC and ADC are used, the cached
> > > variable gets mixed up.
> > > The step mask is written with the required mask every time.
> > > 
> > > Rachna Patil (TI) laid ground work for shared IRQ.
> > > 
> > > Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > Whilst I would have prefered an mfd under these drivers and elegant handling
> > of the interrupts, I guess if this works it is at least not terribly invasive.
> > 
> > However, this does need an Ack from Dmitry before I can take it (or for
> > Dmitry to take it himself?)
> 
> I completely agree with Jonathan, more elegant handling would be nice
> but current one will do for now.
> 
> Since most of the work on the driver is going through IIO tree I think
> it would make sense for this patch to go through it as well.
> 
> Acked-by: Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

Thank-you.
ZubairLK

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:55           ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-19  5:55 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	jic23, dmitry.torokhov, linux-iio, linux-input, linux-kernel,
	bigeasy, gregkh

On Thu, Sep 19, 2013 at 06:41:22AM +0100, Jonathan Cameron wrote:
> 
> 
> >...
> >> >
> >> >  struct tiadc_device {
> >> >  	struct ti_tscadc_dev *mfd_tscadc;
> >> >  	int channels;
> >> >  	u8 channel_line[8];
> >> >  	u8 channel_step[8];
> >> >+	int buffer_en_ch_steps;
> >> >+	u32 *data;
> >> u16 *data;
> >> 
> >> Also it might actually save memory to simply have a fixed size array
> >> of the maximum size used here and avoid the extra allocations for
> >> the cost
> >> of 16 bytes in here.
> >> 
> >> Hence,
> >> 
> >> u16 data[8];
> >> >  };
> >
> >Why data[8]? The length is dynamic. 
> >This would be valid for the usual one sample per trigger case.
> >But here its continuous sampling and the hardware pushes samples
> >*quickly*
> >Dynamic allocation is needed.
> 
> As far as I can see you pull one set of channels into data[] then push that out to the kfifo. 
> 
> That is repeated lots of times but only up to 8 entries are ever used in this array. If not what is the maximum scanbytes can be?
> 

You have a good eye :).
I understand and will update.

Thanks
Zubair

> >
> >
> >...
> >
> >> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
> >> >+{
> >> >+	struct iio_dev *indio_dev = private;
> >> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >> >+	int i, k, fifo1count, read;
> >> >+	u32 *data = adc_dev->data;
> >> 	u16* data = adc_dev->data;
> >> >+
> >> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> >> >+	for (k = 0; k < fifo1count; k = k + i) {
> >> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> >> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
> >> >+			data[i] = read & FIFOREAD_DATA_MASK;
> 
> i is only ever up to scanbytes / 4.
> Hence max of 8 I think?
> 
> Now there is a good argument for adding some bulk filling code for the buffers but that is not happening here.
> >> //This is a 12 bit number after the mask so will fit just fine into
> >16 bits.
> >

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:55           ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-19  5:55 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	jic23-KWPb1pKIrIJaa/9Udqfwiw,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Thu, Sep 19, 2013 at 06:41:22AM +0100, Jonathan Cameron wrote:
> 
> 
> >...
> >> >
> >> >  struct tiadc_device {
> >> >  	struct ti_tscadc_dev *mfd_tscadc;
> >> >  	int channels;
> >> >  	u8 channel_line[8];
> >> >  	u8 channel_step[8];
> >> >+	int buffer_en_ch_steps;
> >> >+	u32 *data;
> >> u16 *data;
> >> 
> >> Also it might actually save memory to simply have a fixed size array
> >> of the maximum size used here and avoid the extra allocations for
> >> the cost
> >> of 16 bytes in here.
> >> 
> >> Hence,
> >> 
> >> u16 data[8];
> >> >  };
> >
> >Why data[8]? The length is dynamic. 
> >This would be valid for the usual one sample per trigger case.
> >But here its continuous sampling and the hardware pushes samples
> >*quickly*
> >Dynamic allocation is needed.
> 
> As far as I can see you pull one set of channels into data[] then push that out to the kfifo. 
> 
> That is repeated lots of times but only up to 8 entries are ever used in this array. If not what is the maximum scanbytes can be?
> 

You have a good eye :).
I understand and will update.

Thanks
Zubair

> >
> >
> >...
> >
> >> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
> >> >+{
> >> >+	struct iio_dev *indio_dev = private;
> >> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >> >+	int i, k, fifo1count, read;
> >> >+	u32 *data = adc_dev->data;
> >> 	u16* data = adc_dev->data;
> >> >+
> >> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> >> >+	for (k = 0; k < fifo1count; k = k + i) {
> >> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> >> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
> >> >+			data[i] = read & FIFOREAD_DATA_MASK;
> 
> i is only ever up to scanbytes / 4.
> Hence max of 8 I think?
> 
> Now there is a good argument for adding some bulk filling code for the buffers but that is not happening here.
> >> //This is a 12 bit number after the mask so will fit just fine into
> >16 bits.
> >

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:41         ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-19  5:41 UTC (permalink / raw)
  To: Zubair Lutfullah :
  Cc: jic23, dmitry.torokhov, linux-iio, linux-input, linux-kernel,
	bigeasy, gregkh



"Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>On Wed, Sep 18, 2013 at 02:58:47PM +0100, Jonathan Cameron wrote:
>> On 18/09/13 12:23, Zubair Lutfullah wrote:
>> >Previously the driver had only one-shot reading functionality.
>> >This patch adds continuous sampling support to the driver.
>> >
>...
>> 
>> Very very nearly there. Couple of suggestions in-line.
>> (about 30 seconds work + testing ;)
>
>Thank-you so much. Makes me want to put in more work and finish it :)
>
>> 
>> I'm still unsure of why we need 32bit storage in the fifo
>> for the data.  I've proposed the changes I'd make to put it in 16 bit
>> storage inline.  The fact that the device is working in 32bits
>> is irrelevant given we only have a 12 bit number coming out and
>> it is in 12 least significant bits.  I guess there might be a tiny
>> cost in doing the conversion, but you kfifo will be half the size
>> as a result and that seems more likely to a worthwhile gain!
>> 
>
>I understand and will make the changes.
>
>> Out of interest, are you testing this with generic_buffer.c?
>> If so, what changes were necessary?  Given this driver will not
>> have a trigger it would be nice to update that example code to handle
>> that case if it doesn't already.
>
>I simply remove the lines like goto err_trigger etc. :p
>Sneaky but works. I wasn't sure how to make the code understand its a 
>INDIO_BUFFER_HARDWARE..
>But this is a separate discussion..
>
>> 
>> 
>> >---
>> >  drivers/iio/adc/ti_am335x_adc.c      |  216
>+++++++++++++++++++++++++++++++++-
>> >  include/linux/mfd/ti_am335x_tscadc.h |    9 ++
>> >  2 files changed, 220 insertions(+), 5 deletions(-)
>> >
>> >diff --git a/drivers/iio/adc/ti_am335x_adc.c
>b/drivers/iio/adc/ti_am335x_adc.c
>...
>> >
>> >  struct tiadc_device {
>> >  	struct ti_tscadc_dev *mfd_tscadc;
>> >  	int channels;
>> >  	u8 channel_line[8];
>> >  	u8 channel_step[8];
>> >+	int buffer_en_ch_steps;
>> >+	u32 *data;
>> u16 *data;
>> 
>> Also it might actually save memory to simply have a fixed size array
>> of the maximum size used here and avoid the extra allocations for
>> the cost
>> of 16 bytes in here.
>> 
>> Hence,
>> 
>> u16 data[8];
>> >  };
>
>Why data[8]? The length is dynamic. 
>This would be valid for the usual one sample per trigger case.
>But here its continuous sampling and the hardware pushes samples
>*quickly*
>Dynamic allocation is needed.

As far as I can see you pull one set of channels into data[] then push that out to the kfifo. 

That is repeated lots of times but only up to 8 entries are ever used in this array. If not what is the maximum scanbytes can be?

>
>
>...
>
>> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
>> >+{
>> >+	struct iio_dev *indio_dev = private;
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	int i, k, fifo1count, read;
>> >+	u32 *data = adc_dev->data;
>> 	u16* data = adc_dev->data;
>> >+
>> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> >+	for (k = 0; k < fifo1count; k = k + i) {
>> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
>> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
>> >+			data[i] = read & FIFOREAD_DATA_MASK;

i is only ever up to scanbytes / 4.
Hence max of 8 I think?

Now there is a good argument for adding some bulk filling code for the buffers but that is not happening here.
>> //This is a 12 bit number after the mask so will fit just fine into
>16 bits.
>
>Indeed
>...
>> >+
>> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	struct iio_buffer *buffer = indio_dev->buffer;
>> >+	unsigned int enb = 0;
>> >+	u8 bit;
>> >+
>> (can drop this if doing the array with adc_dev as suggested above)
>> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
>> >+	if (adc_dev->data == NULL)
>> >+		return -ENOMEM;
>
>As explained previously. Large array.. This is needed..
>
>...
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+
>> >+	tiadc_step_config(indio_dev);
>> (can drop this if doing the array withing adc_dev as suggested above)
>> >+	kfree(adc_dev->data);
>> This is also missbalanced with the preenable (which is true of quite
>> a few drivers - one day I'll clean those up!)
>
>Misbalanced? :s
>
>> >+
>> >+	return 0;
>> >+}
>> 
>
>Thanks for the review and feedback.
>I'll resend the patches with 16 bit everything and dynamic allocation.
>
>Zubair
>> 


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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:41         ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-19  5:41 UTC (permalink / raw)
  To: Zubair Lutfullah :
  Cc: jic23-KWPb1pKIrIJaa/9Udqfwiw,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r



"Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>On Wed, Sep 18, 2013 at 02:58:47PM +0100, Jonathan Cameron wrote:
>> On 18/09/13 12:23, Zubair Lutfullah wrote:
>> >Previously the driver had only one-shot reading functionality.
>> >This patch adds continuous sampling support to the driver.
>> >
>...
>> 
>> Very very nearly there. Couple of suggestions in-line.
>> (about 30 seconds work + testing ;)
>
>Thank-you so much. Makes me want to put in more work and finish it :)
>
>> 
>> I'm still unsure of why we need 32bit storage in the fifo
>> for the data.  I've proposed the changes I'd make to put it in 16 bit
>> storage inline.  The fact that the device is working in 32bits
>> is irrelevant given we only have a 12 bit number coming out and
>> it is in 12 least significant bits.  I guess there might be a tiny
>> cost in doing the conversion, but you kfifo will be half the size
>> as a result and that seems more likely to a worthwhile gain!
>> 
>
>I understand and will make the changes.
>
>> Out of interest, are you testing this with generic_buffer.c?
>> If so, what changes were necessary?  Given this driver will not
>> have a trigger it would be nice to update that example code to handle
>> that case if it doesn't already.
>
>I simply remove the lines like goto err_trigger etc. :p
>Sneaky but works. I wasn't sure how to make the code understand its a 
>INDIO_BUFFER_HARDWARE..
>But this is a separate discussion..
>
>> 
>> 
>> >---
>> >  drivers/iio/adc/ti_am335x_adc.c      |  216
>+++++++++++++++++++++++++++++++++-
>> >  include/linux/mfd/ti_am335x_tscadc.h |    9 ++
>> >  2 files changed, 220 insertions(+), 5 deletions(-)
>> >
>> >diff --git a/drivers/iio/adc/ti_am335x_adc.c
>b/drivers/iio/adc/ti_am335x_adc.c
>...
>> >
>> >  struct tiadc_device {
>> >  	struct ti_tscadc_dev *mfd_tscadc;
>> >  	int channels;
>> >  	u8 channel_line[8];
>> >  	u8 channel_step[8];
>> >+	int buffer_en_ch_steps;
>> >+	u32 *data;
>> u16 *data;
>> 
>> Also it might actually save memory to simply have a fixed size array
>> of the maximum size used here and avoid the extra allocations for
>> the cost
>> of 16 bytes in here.
>> 
>> Hence,
>> 
>> u16 data[8];
>> >  };
>
>Why data[8]? The length is dynamic. 
>This would be valid for the usual one sample per trigger case.
>But here its continuous sampling and the hardware pushes samples
>*quickly*
>Dynamic allocation is needed.

As far as I can see you pull one set of channels into data[] then push that out to the kfifo. 

That is repeated lots of times but only up to 8 entries are ever used in this array. If not what is the maximum scanbytes can be?

>
>
>...
>
>> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
>> >+{
>> >+	struct iio_dev *indio_dev = private;
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	int i, k, fifo1count, read;
>> >+	u32 *data = adc_dev->data;
>> 	u16* data = adc_dev->data;
>> >+
>> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> >+	for (k = 0; k < fifo1count; k = k + i) {
>> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
>> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
>> >+			data[i] = read & FIFOREAD_DATA_MASK;

i is only ever up to scanbytes / 4.
Hence max of 8 I think?

Now there is a good argument for adding some bulk filling code for the buffers but that is not happening here.
>> //This is a 12 bit number after the mask so will fit just fine into
>16 bits.
>
>Indeed
>...
>> >+
>> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	struct iio_buffer *buffer = indio_dev->buffer;
>> >+	unsigned int enb = 0;
>> >+	u8 bit;
>> >+
>> (can drop this if doing the array with adc_dev as suggested above)
>> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
>> >+	if (adc_dev->data == NULL)
>> >+		return -ENOMEM;
>
>As explained previously. Large array.. This is needed..
>
>...
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+
>> >+	tiadc_step_config(indio_dev);
>> (can drop this if doing the array withing adc_dev as suggested above)
>> >+	kfree(adc_dev->data);
>> This is also missbalanced with the preenable (which is true of quite
>> a few drivers - one day I'll clean those up!)
>
>Misbalanced? :s
>
>> >+
>> >+	return 0;
>> >+}
>> 
>
>Thanks for the review and feedback.
>I'll resend the patches with 16 bit everything and dynamic allocation.
>
>Zubair
>> 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:41         ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-19  5:41 UTC (permalink / raw)
  To: Zubair Lutfullah :
  Cc: jic23, dmitry.torokhov, linux-iio, linux-input, linux-kernel,
	bigeasy, gregkh



"Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>On Wed, Sep 18, 2013 at 02:58:47PM +0100, Jonathan Cameron wrote:
>> On 18/09/13 12:23, Zubair Lutfullah wrote:
>> >Previously the driver had only one-shot reading functionality.
>> >This patch adds continuous sampling support to the driver.
>> >
>...
>> 
>> Very very nearly there. Couple of suggestions in-line.
>> (about 30 seconds work + testing ;)
>
>Thank-you so much. Makes me want to put in more work and finish it :)
>
>> 
>> I'm still unsure of why we need 32bit storage in the fifo
>> for the data.  I've proposed the changes I'd make to put it in 16 bit
>> storage inline.  The fact that the device is working in 32bits
>> is irrelevant given we only have a 12 bit number coming out and
>> it is in 12 least significant bits.  I guess there might be a tiny
>> cost in doing the conversion, but you kfifo will be half the size
>> as a result and that seems more likely to a worthwhile gain!
>> 
>
>I understand and will make the changes.
>
>> Out of interest, are you testing this with generic_buffer.c?
>> If so, what changes were necessary?  Given this driver will not
>> have a trigger it would be nice to update that example code to handle
>> that case if it doesn't already.
>
>I simply remove the lines like goto err_trigger etc. :p
>Sneaky but works. I wasn't sure how to make the code understand its a 
>INDIO_BUFFER_HARDWARE..
>But this is a separate discussion..
>
>> 
>> 
>> >---
>> >  drivers/iio/adc/ti_am335x_adc.c      |  216
>+++++++++++++++++++++++++++++++++-
>> >  include/linux/mfd/ti_am335x_tscadc.h |    9 ++
>> >  2 files changed, 220 insertions(+), 5 deletions(-)
>> >
>> >diff --git a/drivers/iio/adc/ti_am335x_adc.c
>b/drivers/iio/adc/ti_am335x_adc.c
>...
>> >
>> >  struct tiadc_device {
>> >  	struct ti_tscadc_dev *mfd_tscadc;
>> >  	int channels;
>> >  	u8 channel_line[8];
>> >  	u8 channel_step[8];
>> >+	int buffer_en_ch_steps;
>> >+	u32 *data;
>> u16 *data;
>> 
>> Also it might actually save memory to simply have a fixed size array
>> of the maximum size used here and avoid the extra allocations for
>> the cost
>> of 16 bytes in here.
>> 
>> Hence,
>> 
>> u16 data[8];
>> >  };
>
>Why data[8]? The length is dynamic. 
>This would be valid for the usual one sample per trigger case.
>But here its continuous sampling and the hardware pushes samples
>*quickly*
>Dynamic allocation is needed.

As far as I can see you pull one set of channels into data[] then push that out to the kfifo. 

That is repeated lots of times but only up to 8 entries are ever used in this array. If not what is the maximum scanbytes can be?

>
>
>...
>
>> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
>> >+{
>> >+	struct iio_dev *indio_dev = private;
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	int i, k, fifo1count, read;
>> >+	u32 *data = adc_dev->data;
>> 	u16* data = adc_dev->data;
>> >+
>> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
>> >+	for (k = 0; k < fifo1count; k = k + i) {
>> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
>> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
>> >+			data[i] = read & FIFOREAD_DATA_MASK;

i is only ever up to scanbytes / 4.
Hence max of 8 I think?

Now there is a good argument for adding some bulk filling code for the buffers but that is not happening here.
>> //This is a 12 bit number after the mask so will fit just fine into
>16 bits.
>
>Indeed
>...
>> >+
>> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+	struct iio_buffer *buffer = indio_dev->buffer;
>> >+	unsigned int enb = 0;
>> >+	u8 bit;
>> >+
>> (can drop this if doing the array with adc_dev as suggested above)
>> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
>> >+	if (adc_dev->data == NULL)
>> >+		return -ENOMEM;
>
>As explained previously. Large array.. This is needed..
>
>...
>> >+{
>> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> >+
>> >+	tiadc_step_config(indio_dev);
>> (can drop this if doing the array withing adc_dev as suggested above)
>> >+	kfree(adc_dev->data);
>> This is also missbalanced with the preenable (which is true of quite
>> a few drivers - one day I'll clean those up!)
>
>Misbalanced? :s
>
>> >+
>> >+	return 0;
>> >+}
>> 
>
>Thanks for the review and feedback.
>I'll resend the patches with 16 bit everything and dynamic allocation.
>
>Zubair
>> 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:33                     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-19  5:33 UTC (permalink / raw)
  To: Zubair Lutfullah :
  Cc: Dmitry Torokhov, linux-iio, linux-input, linux-kernel, bigeasy, gregkh



"Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>On Wed, Sep 18, 2013 at 06:05:12PM +0100, Jonathan Cameron wrote:
>> 
>> >> >However in this case such conversion us dangerous. With all but
>IRQ
>> >> >resource managed by the traditional methods they will be released
>> >first
>> >> >with IRQ handler deregistered very last. Therefore if device is
>not
>> >> >properly quiesced IRQ raised during driver unbinding is likely to
>> >> >result
>> >> >in kernel oops.
>> >> >
>> >> >IOW devm_request_irq() is very often evil (it is still useful if
>> >_all_
>> >> >your resources are managed by devm_*).
>> >> >
>> >> >In case of your driver I'd recommend switching to
>> >> >request_irq()/free_irq() instead.
>> >> >
>> >> >Thanks.
>> >> 
>> >> Pretty much all resources are devm managed in here
>> >> 
>> >>
>>
>>https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347
>> >
>> >
>> >So we are guaranteed that that new kfifo that is being allocated
>just
>> >before we requesting IRQ and will be freed way before we free the
>IRQ
>> >will not be used by the IOTQ handler?
>> >
>> >Thanks.
>> Good point. I forgot about that.  The source of interrupts 'should'
>be disabled before the kfifo is freed but I guess perhaps better to
>play it safe. Would take a fair bit of review to be sure that is not
>going to cause grief.
>> 
>> A few more devm handlers need writing before it is truly useful here.
>> 
>> Thanks for pointing this out.
>> 
>> J
>
>If I understand the conclusion correctly, no devm here?

No devm for the irq. The rest are fine.
>
>Zubair
>--
>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

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:33                     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-19  5:33 UTC (permalink / raw)
  To: Zubair Lutfullah :
  Cc: Dmitry Torokhov, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r



"Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>On Wed, Sep 18, 2013 at 06:05:12PM +0100, Jonathan Cameron wrote:
>> 
>> >> >However in this case such conversion us dangerous. With all but
>IRQ
>> >> >resource managed by the traditional methods they will be released
>> >first
>> >> >with IRQ handler deregistered very last. Therefore if device is
>not
>> >> >properly quiesced IRQ raised during driver unbinding is likely to
>> >> >result
>> >> >in kernel oops.
>> >> >
>> >> >IOW devm_request_irq() is very often evil (it is still useful if
>> >_all_
>> >> >your resources are managed by devm_*).
>> >> >
>> >> >In case of your driver I'd recommend switching to
>> >> >request_irq()/free_irq() instead.
>> >> >
>> >> >Thanks.
>> >> 
>> >> Pretty much all resources are devm managed in here
>> >> 
>> >>
>>
>>https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347
>> >
>> >
>> >So we are guaranteed that that new kfifo that is being allocated
>just
>> >before we requesting IRQ and will be freed way before we free the
>IRQ
>> >will not be used by the IOTQ handler?
>> >
>> >Thanks.
>> Good point. I forgot about that.  The source of interrupts 'should'
>be disabled before the kfifo is freed but I guess perhaps better to
>play it safe. Would take a fair bit of review to be sure that is not
>going to cause grief.
>> 
>> A few more devm handlers need writing before it is truly useful here.
>> 
>> Thanks for pointing this out.
>> 
>> J
>
>If I understand the conclusion correctly, no devm here?

No devm for the irq. The rest are fine.
>
>Zubair
>--
>To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:24       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-19  5:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, jic23, dmitry.torokhov, linux-iio, linux-input,
	linux-kernel, bigeasy, gregkh

On Wed, Sep 18, 2013 at 02:58:47PM +0100, Jonathan Cameron wrote:
> On 18/09/13 12:23, Zubair Lutfullah wrote:
> >Previously the driver had only one-shot reading functionality.
> >This patch adds continuous sampling support to the driver.
> >
...
> 
> Very very nearly there. Couple of suggestions in-line.
> (about 30 seconds work + testing ;)

Thank-you so much. Makes me want to put in more work and finish it :)

> 
> I'm still unsure of why we need 32bit storage in the fifo
> for the data.  I've proposed the changes I'd make to put it in 16 bit
> storage inline.  The fact that the device is working in 32bits
> is irrelevant given we only have a 12 bit number coming out and
> it is in 12 least significant bits.  I guess there might be a tiny
> cost in doing the conversion, but you kfifo will be half the size
> as a result and that seems more likely to a worthwhile gain!
> 

I understand and will make the changes.

> Out of interest, are you testing this with generic_buffer.c?
> If so, what changes were necessary?  Given this driver will not
> have a trigger it would be nice to update that example code to handle
> that case if it doesn't already.

I simply remove the lines like goto err_trigger etc. :p
Sneaky but works. I wasn't sure how to make the code understand its a 
INDIO_BUFFER_HARDWARE..
But this is a separate discussion..

> 
> 
> >---
> >  drivers/iio/adc/ti_am335x_adc.c      |  216 +++++++++++++++++++++++++++++++++-
> >  include/linux/mfd/ti_am335x_tscadc.h |    9 ++
> >  2 files changed, 220 insertions(+), 5 deletions(-)
> >
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
...
> >
> >  struct tiadc_device {
> >  	struct ti_tscadc_dev *mfd_tscadc;
> >  	int channels;
> >  	u8 channel_line[8];
> >  	u8 channel_step[8];
> >+	int buffer_en_ch_steps;
> >+	u32 *data;
> u16 *data;
> 
> Also it might actually save memory to simply have a fixed size array
> of the maximum size used here and avoid the extra allocations for
> the cost
> of 16 bytes in here.
> 
> Hence,
> 
> u16 data[8];
> >  };

Why data[8]? The length is dynamic. 
This would be valid for the usual one sample per trigger case.
But here its continuous sampling and the hardware pushes samples
*quickly*
Dynamic allocation is needed.


...

> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
> >+{
> >+	struct iio_dev *indio_dev = private;
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+	int i, k, fifo1count, read;
> >+	u32 *data = adc_dev->data;
> 	u16* data = adc_dev->data;
> >+
> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> >+	for (k = 0; k < fifo1count; k = k + i) {
> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
> >+			data[i] = read & FIFOREAD_DATA_MASK;
> //This is a 12 bit number after the mask so will fit just fine into 16 bits.

Indeed
...
> >+
> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> >+{
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+	struct iio_buffer *buffer = indio_dev->buffer;
> >+	unsigned int enb = 0;
> >+	u8 bit;
> >+
> (can drop this if doing the array with adc_dev as suggested above)
> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> >+	if (adc_dev->data == NULL)
> >+		return -ENOMEM;

As explained previously. Large array.. This is needed..

...
> >+{
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+
> >+	tiadc_step_config(indio_dev);
> (can drop this if doing the array withing adc_dev as suggested above)
> >+	kfree(adc_dev->data);
> This is also missbalanced with the preenable (which is true of quite
> a few drivers - one day I'll clean those up!)

Misbalanced? :s

> >+
> >+	return 0;
> >+}
> 

Thanks for the review and feedback.
I'll resend the patches with 16 bit everything and dynamic allocation.

Zubair
> 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-19  5:24       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-19  5:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah, jic23-KWPb1pKIrIJaa/9Udqfwiw,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Wed, Sep 18, 2013 at 02:58:47PM +0100, Jonathan Cameron wrote:
> On 18/09/13 12:23, Zubair Lutfullah wrote:
> >Previously the driver had only one-shot reading functionality.
> >This patch adds continuous sampling support to the driver.
> >
...
> 
> Very very nearly there. Couple of suggestions in-line.
> (about 30 seconds work + testing ;)

Thank-you so much. Makes me want to put in more work and finish it :)

> 
> I'm still unsure of why we need 32bit storage in the fifo
> for the data.  I've proposed the changes I'd make to put it in 16 bit
> storage inline.  The fact that the device is working in 32bits
> is irrelevant given we only have a 12 bit number coming out and
> it is in 12 least significant bits.  I guess there might be a tiny
> cost in doing the conversion, but you kfifo will be half the size
> as a result and that seems more likely to a worthwhile gain!
> 

I understand and will make the changes.

> Out of interest, are you testing this with generic_buffer.c?
> If so, what changes were necessary?  Given this driver will not
> have a trigger it would be nice to update that example code to handle
> that case if it doesn't already.

I simply remove the lines like goto err_trigger etc. :p
Sneaky but works. I wasn't sure how to make the code understand its a 
INDIO_BUFFER_HARDWARE..
But this is a separate discussion..

> 
> 
> >---
> >  drivers/iio/adc/ti_am335x_adc.c      |  216 +++++++++++++++++++++++++++++++++-
> >  include/linux/mfd/ti_am335x_tscadc.h |    9 ++
> >  2 files changed, 220 insertions(+), 5 deletions(-)
> >
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
...
> >
> >  struct tiadc_device {
> >  	struct ti_tscadc_dev *mfd_tscadc;
> >  	int channels;
> >  	u8 channel_line[8];
> >  	u8 channel_step[8];
> >+	int buffer_en_ch_steps;
> >+	u32 *data;
> u16 *data;
> 
> Also it might actually save memory to simply have a fixed size array
> of the maximum size used here and avoid the extra allocations for
> the cost
> of 16 bytes in here.
> 
> Hence,
> 
> u16 data[8];
> >  };

Why data[8]? The length is dynamic. 
This would be valid for the usual one sample per trigger case.
But here its continuous sampling and the hardware pushes samples
*quickly*
Dynamic allocation is needed.


...

> >+static irqreturn_t tiadc_worker_h(int irq, void *private)
> >+{
> >+	struct iio_dev *indio_dev = private;
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+	int i, k, fifo1count, read;
> >+	u32 *data = adc_dev->data;
> 	u16* data = adc_dev->data;
> >+
> >+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> >+	for (k = 0; k < fifo1count; k = k + i) {
> >+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> >+			read = tiadc_readl(adc_dev, REG_FIFO1);
> >+			data[i] = read & FIFOREAD_DATA_MASK;
> //This is a 12 bit number after the mask so will fit just fine into 16 bits.

Indeed
...
> >+
> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> >+{
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+	struct iio_buffer *buffer = indio_dev->buffer;
> >+	unsigned int enb = 0;
> >+	u8 bit;
> >+
> (can drop this if doing the array with adc_dev as suggested above)
> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> >+	if (adc_dev->data == NULL)
> >+		return -ENOMEM;

As explained previously. Large array.. This is needed..

...
> >+{
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+
> >+	tiadc_step_config(indio_dev);
> (can drop this if doing the array withing adc_dev as suggested above)
> >+	kfree(adc_dev->data);
> This is also missbalanced with the preenable (which is true of quite
> a few drivers - one day I'll clean those up!)

Misbalanced? :s

> >+
> >+	return 0;
> >+}
> 

Thanks for the review and feedback.
I'll resend the patches with 16 bit everything and dynamic allocation.

Zubair
> 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-18 17:05                 ` Jonathan Cameron
  (?)
@ 2013-09-19  5:16                 ` Zubair Lutfullah :
  2013-09-19  5:33                     ` Jonathan Cameron
  -1 siblings, 1 reply; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-19  5:16 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Dmitry Torokhov, Zubair Lutfullah :,
	linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On Wed, Sep 18, 2013 at 06:05:12PM +0100, Jonathan Cameron wrote:
> 
> >> >However in this case such conversion us dangerous. With all but IRQ
> >> >resource managed by the traditional methods they will be released
> >first
> >> >with IRQ handler deregistered very last. Therefore if device is not
> >> >properly quiesced IRQ raised during driver unbinding is likely to
> >> >result
> >> >in kernel oops.
> >> >
> >> >IOW devm_request_irq() is very often evil (it is still useful if
> >_all_
> >> >your resources are managed by devm_*).
> >> >
> >> >In case of your driver I'd recommend switching to
> >> >request_irq()/free_irq() instead.
> >> >
> >> >Thanks.
> >> 
> >> Pretty much all resources are devm managed in here
> >> 
> >>
> >https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347
> >
> >
> >So we are guaranteed that that new kfifo that is being allocated just
> >before we requesting IRQ and will be freed way before we free the IRQ
> >will not be used by the IOTQ handler?
> >
> >Thanks.
> Good point. I forgot about that.  The source of interrupts 'should' be disabled before the kfifo is freed but I guess perhaps better to play it safe. Would take a fair bit of review to be sure that is not going to cause grief.
> 
> A few more devm handlers need writing before it is truly useful here.
> 
> Thanks for pointing this out.
> 
> J

If I understand the conclusion correctly, no devm here?

Zubair

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 17:05                 ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 17:05 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah :,
	linux-iio, linux-input, linux-kernel, bigeasy, gregkh



Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>On Wed, Sep 18, 2013 at 05:12:02PM +0100, Jonathan Cameron wrote:
>> 
>> 
>> Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>> >On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
>> >> 
>> >> 
>> >> "Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>> >> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> >> >> Hi Zubair,
>> >> >> 
>> >> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah
>wrote:
>> >> >> > +
>> >> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> >> >> > +				irq,
>> >> >> > +				pollfunc_th, pollfunc_bh,
>> >> >> > +				flags, indio_dev->name,
>> >> >> > +				indio_dev);
>> >> >> > +	if (ret)
>> >> >> > +		goto error_kfifo_free;
>> >> >> > +
>> >> >> > +	indio_dev->setup_ops = setup_ops;
>> >> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> >> >> > +
>> >> >> > +	ret = iio_buffer_register(indio_dev,
>> >> >> > +				  indio_dev->channels,
>> >> >> > +				  indio_dev->num_channels);
>> >> >> > +	if (ret)
>> >> >> > +		goto error_free_irq;
>> >> >> > +
>> >> >> > +	return 0;
>> >> >> > +
>> >> >> > +error_free_irq:
>> >> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> >> >> 
>> >> >> What is the point of using devm_* here if you are doing
>explicit
>> >> >> management of the resource anyway (you explicitly release it in
>> >all
>> >> >code
>> >> >> paths)?
>> >> >> 
>> >> >> Thanks.
>> >> >> 
>> >> >> -- 
>> >> >> Dmitry
>> >> >
>> >> >I admit I am unaware at the moment about how it works.
>> >> >
>> >> >I use devm and simply ignore the error path?
>> >> >
>> >> >The devm function header description said something about using
>> >> >devm_free when freeing. And this is the way I am used to seeing 
>> >> >error handling.
>> >> 
>> >
>> >> The devm interfaces ensure this is all cleaned when the device is
>> >> removed thus avoiding the need to free the stuff explicitly. 
>Device
>> >> will get freed on deliberate remove and on an error from probe.
>Hence
>> >> you can drop all calls to devm free. The devm free functions are
>only
>> >> needed if you wish to free in order to reallocate. This might
>happen
>> >> if you want to change a buffer size for instance.
>> >
>> >However in this case such conversion us dangerous. With all but IRQ
>> >resource managed by the traditional methods they will be released
>first
>> >with IRQ handler deregistered very last. Therefore if device is not
>> >properly quiesced IRQ raised during driver unbinding is likely to
>> >result
>> >in kernel oops.
>> >
>> >IOW devm_request_irq() is very often evil (it is still useful if
>_all_
>> >your resources are managed by devm_*).
>> >
>> >In case of your driver I'd recommend switching to
>> >request_irq()/free_irq() instead.
>> >
>> >Thanks.
>> 
>> Pretty much all resources are devm managed in here
>> 
>>
>https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347
>
>
>So we are guaranteed that that new kfifo that is being allocated just
>before we requesting IRQ and will be freed way before we free the IRQ
>will not be used by the IOTQ handler?
>
>Thanks.
Good point. I forgot about that.  The source of interrupts 'should' be disabled before the kfifo is freed but I guess perhaps better to play it safe. Would take a fair bit of review to be sure that is not going to cause grief.

A few more devm handlers need writing before it is truly useful here.

Thanks for pointing this out.

J

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 17:05                 ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 17:05 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah :,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r



Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>On Wed, Sep 18, 2013 at 05:12:02PM +0100, Jonathan Cameron wrote:
>> 
>> 
>> Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> >On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
>> >> 
>> >> 
>> >> "Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> >> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> >> >> Hi Zubair,
>> >> >> 
>> >> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah
>wrote:
>> >> >> > +
>> >> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> >> >> > +				irq,
>> >> >> > +				pollfunc_th, pollfunc_bh,
>> >> >> > +				flags, indio_dev->name,
>> >> >> > +				indio_dev);
>> >> >> > +	if (ret)
>> >> >> > +		goto error_kfifo_free;
>> >> >> > +
>> >> >> > +	indio_dev->setup_ops = setup_ops;
>> >> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> >> >> > +
>> >> >> > +	ret = iio_buffer_register(indio_dev,
>> >> >> > +				  indio_dev->channels,
>> >> >> > +				  indio_dev->num_channels);
>> >> >> > +	if (ret)
>> >> >> > +		goto error_free_irq;
>> >> >> > +
>> >> >> > +	return 0;
>> >> >> > +
>> >> >> > +error_free_irq:
>> >> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> >> >> 
>> >> >> What is the point of using devm_* here if you are doing
>explicit
>> >> >> management of the resource anyway (you explicitly release it in
>> >all
>> >> >code
>> >> >> paths)?
>> >> >> 
>> >> >> Thanks.
>> >> >> 
>> >> >> -- 
>> >> >> Dmitry
>> >> >
>> >> >I admit I am unaware at the moment about how it works.
>> >> >
>> >> >I use devm and simply ignore the error path?
>> >> >
>> >> >The devm function header description said something about using
>> >> >devm_free when freeing. And this is the way I am used to seeing 
>> >> >error handling.
>> >> 
>> >
>> >> The devm interfaces ensure this is all cleaned when the device is
>> >> removed thus avoiding the need to free the stuff explicitly. 
>Device
>> >> will get freed on deliberate remove and on an error from probe.
>Hence
>> >> you can drop all calls to devm free. The devm free functions are
>only
>> >> needed if you wish to free in order to reallocate. This might
>happen
>> >> if you want to change a buffer size for instance.
>> >
>> >However in this case such conversion us dangerous. With all but IRQ
>> >resource managed by the traditional methods they will be released
>first
>> >with IRQ handler deregistered very last. Therefore if device is not
>> >properly quiesced IRQ raised during driver unbinding is likely to
>> >result
>> >in kernel oops.
>> >
>> >IOW devm_request_irq() is very often evil (it is still useful if
>_all_
>> >your resources are managed by devm_*).
>> >
>> >In case of your driver I'd recommend switching to
>> >request_irq()/free_irq() instead.
>> >
>> >Thanks.
>> 
>> Pretty much all resources are devm managed in here
>> 
>>
>https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347
>
>
>So we are guaranteed that that new kfifo that is being allocated just
>before we requesting IRQ and will be freed way before we free the IRQ
>will not be used by the IOTQ handler?
>
>Thanks.
Good point. I forgot about that.  The source of interrupts 'should' be disabled before the kfifo is freed but I guess perhaps better to play it safe. Would take a fair bit of review to be sure that is not going to cause grief.

A few more devm handlers need writing before it is truly useful here.

Thanks for pointing this out.

J

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-18 16:12             ` Jonathan Cameron
  (?)
@ 2013-09-18 16:24             ` Dmitry Torokhov
  2013-09-18 17:05                 ` Jonathan Cameron
  -1 siblings, 1 reply; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-18 16:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On Wed, Sep 18, 2013 at 05:12:02PM +0100, Jonathan Cameron wrote:
> 
> 
> Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> >On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
> >> 
> >> 
> >> "Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
> >> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> >> >> Hi Zubair,
> >> >> 
> >> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> >> >> > +
> >> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> >> >> > +				irq,
> >> >> > +				pollfunc_th, pollfunc_bh,
> >> >> > +				flags, indio_dev->name,
> >> >> > +				indio_dev);
> >> >> > +	if (ret)
> >> >> > +		goto error_kfifo_free;
> >> >> > +
> >> >> > +	indio_dev->setup_ops = setup_ops;
> >> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> >> >> > +
> >> >> > +	ret = iio_buffer_register(indio_dev,
> >> >> > +				  indio_dev->channels,
> >> >> > +				  indio_dev->num_channels);
> >> >> > +	if (ret)
> >> >> > +		goto error_free_irq;
> >> >> > +
> >> >> > +	return 0;
> >> >> > +
> >> >> > +error_free_irq:
> >> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> >> >> 
> >> >> What is the point of using devm_* here if you are doing explicit
> >> >> management of the resource anyway (you explicitly release it in
> >all
> >> >code
> >> >> paths)?
> >> >> 
> >> >> Thanks.
> >> >> 
> >> >> -- 
> >> >> Dmitry
> >> >
> >> >I admit I am unaware at the moment about how it works.
> >> >
> >> >I use devm and simply ignore the error path?
> >> >
> >> >The devm function header description said something about using
> >> >devm_free when freeing. And this is the way I am used to seeing 
> >> >error handling.
> >> 
> >
> >> The devm interfaces ensure this is all cleaned when the device is
> >> removed thus avoiding the need to free the stuff explicitly.  Device
> >> will get freed on deliberate remove and on an error from probe. Hence
> >> you can drop all calls to devm free. The devm free functions are only
> >> needed if you wish to free in order to reallocate. This might happen
> >> if you want to change a buffer size for instance.
> >
> >However in this case such conversion us dangerous. With all but IRQ
> >resource managed by the traditional methods they will be released first
> >with IRQ handler deregistered very last. Therefore if device is not
> >properly quiesced IRQ raised during driver unbinding is likely to
> >result
> >in kernel oops.
> >
> >IOW devm_request_irq() is very often evil (it is still useful if _all_
> >your resources are managed by devm_*).
> >
> >In case of your driver I'd recommend switching to
> >request_irq()/free_irq() instead.
> >
> >Thanks.
> 
> Pretty much all resources are devm managed in here
> 
> https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347


So we are guaranteed that that new kfifo that is being allocated just
before we requesting IRQ and will be freed way before we free the IRQ
will not be used by the IOTQ handler?

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 16:12             ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 16:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah :,
	linux-iio, linux-input, linux-kernel, bigeasy, gregkh



Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
>> 
>> 
>> "Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> >> Hi Zubair,
>> >> 
>> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
>> >> > +
>> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> >> > +				irq,
>> >> > +				pollfunc_th, pollfunc_bh,
>> >> > +				flags, indio_dev->name,
>> >> > +				indio_dev);
>> >> > +	if (ret)
>> >> > +		goto error_kfifo_free;
>> >> > +
>> >> > +	indio_dev->setup_ops = setup_ops;
>> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> >> > +
>> >> > +	ret = iio_buffer_register(indio_dev,
>> >> > +				  indio_dev->channels,
>> >> > +				  indio_dev->num_channels);
>> >> > +	if (ret)
>> >> > +		goto error_free_irq;
>> >> > +
>> >> > +	return 0;
>> >> > +
>> >> > +error_free_irq:
>> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> >> 
>> >> What is the point of using devm_* here if you are doing explicit
>> >> management of the resource anyway (you explicitly release it in
>all
>> >code
>> >> paths)?
>> >> 
>> >> Thanks.
>> >> 
>> >> -- 
>> >> Dmitry
>> >
>> >I admit I am unaware at the moment about how it works.
>> >
>> >I use devm and simply ignore the error path?
>> >
>> >The devm function header description said something about using
>> >devm_free when freeing. And this is the way I am used to seeing 
>> >error handling.
>> 
>
>> The devm interfaces ensure this is all cleaned when the device is
>> removed thus avoiding the need to free the stuff explicitly.  Device
>> will get freed on deliberate remove and on an error from probe. Hence
>> you can drop all calls to devm free. The devm free functions are only
>> needed if you wish to free in order to reallocate. This might happen
>> if you want to change a buffer size for instance.
>
>However in this case such conversion us dangerous. With all but IRQ
>resource managed by the traditional methods they will be released first
>with IRQ handler deregistered very last. Therefore if device is not
>properly quiesced IRQ raised during driver unbinding is likely to
>result
>in kernel oops.
>
>IOW devm_request_irq() is very often evil (it is still useful if _all_
>your resources are managed by devm_*).
>
>In case of your driver I'd recommend switching to
>request_irq()/free_irq() instead.
>
>Thanks.

Pretty much all resources are devm managed in here

https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347

There is a left over calloc which could be converted but that's it.
-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 16:12             ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 16:12 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah :,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r



Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
>> 
>> 
>> "Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> >> Hi Zubair,
>> >> 
>> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
>> >> > +
>> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> >> > +				irq,
>> >> > +				pollfunc_th, pollfunc_bh,
>> >> > +				flags, indio_dev->name,
>> >> > +				indio_dev);
>> >> > +	if (ret)
>> >> > +		goto error_kfifo_free;
>> >> > +
>> >> > +	indio_dev->setup_ops = setup_ops;
>> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> >> > +
>> >> > +	ret = iio_buffer_register(indio_dev,
>> >> > +				  indio_dev->channels,
>> >> > +				  indio_dev->num_channels);
>> >> > +	if (ret)
>> >> > +		goto error_free_irq;
>> >> > +
>> >> > +	return 0;
>> >> > +
>> >> > +error_free_irq:
>> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> >> 
>> >> What is the point of using devm_* here if you are doing explicit
>> >> management of the resource anyway (you explicitly release it in
>all
>> >code
>> >> paths)?
>> >> 
>> >> Thanks.
>> >> 
>> >> -- 
>> >> Dmitry
>> >
>> >I admit I am unaware at the moment about how it works.
>> >
>> >I use devm and simply ignore the error path?
>> >
>> >The devm function header description said something about using
>> >devm_free when freeing. And this is the way I am used to seeing 
>> >error handling.
>> 
>
>> The devm interfaces ensure this is all cleaned when the device is
>> removed thus avoiding the need to free the stuff explicitly.  Device
>> will get freed on deliberate remove and on an error from probe. Hence
>> you can drop all calls to devm free. The devm free functions are only
>> needed if you wish to free in order to reallocate. This might happen
>> if you want to change a buffer size for instance.
>
>However in this case such conversion us dangerous. With all but IRQ
>resource managed by the traditional methods they will be released first
>with IRQ handler deregistered very last. Therefore if device is not
>properly quiesced IRQ raised during driver unbinding is likely to
>result
>in kernel oops.
>
>IOW devm_request_irq() is very often evil (it is still useful if _all_
>your resources are managed by devm_*).
>
>In case of your driver I'd recommend switching to
>request_irq()/free_irq() instead.
>
>Thanks.

Pretty much all resources are devm managed in here

https://git.kernel.org/cgit/linux/kernel/git/jic23/iio.git/tree/drivers/iio/adc/ti_am335x_adc.c?h=togreg&id=7a1aeba7ed0d5a1e83fd5a8ee2a2869430d40347

There is a left over calloc which could be converted but that's it.
-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 14:15           ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-18 14:15 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	linux-iio, linux-input, linux-kernel, bigeasy, gregkh

On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
> 
> 
> "Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> >> Hi Zubair,
> >> 
> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> >> > +
> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> >> > +				irq,
> >> > +				pollfunc_th, pollfunc_bh,
> >> > +				flags, indio_dev->name,
> >> > +				indio_dev);
> >> > +	if (ret)
> >> > +		goto error_kfifo_free;
> >> > +
> >> > +	indio_dev->setup_ops = setup_ops;
> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> >> > +
> >> > +	ret = iio_buffer_register(indio_dev,
> >> > +				  indio_dev->channels,
> >> > +				  indio_dev->num_channels);
> >> > +	if (ret)
> >> > +		goto error_free_irq;
> >> > +
> >> > +	return 0;
> >> > +
> >> > +error_free_irq:
> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> >> 
> >> What is the point of using devm_* here if you are doing explicit
> >> management of the resource anyway (you explicitly release it in all
> >code
> >> paths)?
> >> 
> >> Thanks.
> >> 
> >> -- 
> >> Dmitry
> >
> >I admit I am unaware at the moment about how it works.
> >
> >I use devm and simply ignore the error path?
> >
> >The devm function header description said something about using
> >devm_free when freeing. And this is the way I am used to seeing 
> >error handling.
> 

> The devm interfaces ensure this is all cleaned when the device is
> removed thus avoiding the need to free the stuff explicitly.  Device
> will get freed on deliberate remove and on an error from probe. Hence
> you can drop all calls to devm free. The devm free functions are only
> needed if you wish to free in order to reallocate. This might happen
> if you want to change a buffer size for instance.

However in this case such conversion us dangerous. With all but IRQ
resource managed by the traditional methods they will be released first
with IRQ handler deregistered very last. Therefore if device is not
properly quiesced IRQ raised during driver unbinding is likely to result
in kernel oops.

IOW devm_request_irq() is very often evil (it is still useful if _all_
your resources are managed by devm_*).

In case of your driver I'd recommend switching to
request_irq()/free_irq() instead.

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 14:15           ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-18 14:15 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
> 
> 
> "Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> >> Hi Zubair,
> >> 
> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> >> > +
> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> >> > +				irq,
> >> > +				pollfunc_th, pollfunc_bh,
> >> > +				flags, indio_dev->name,
> >> > +				indio_dev);
> >> > +	if (ret)
> >> > +		goto error_kfifo_free;
> >> > +
> >> > +	indio_dev->setup_ops = setup_ops;
> >> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> >> > +
> >> > +	ret = iio_buffer_register(indio_dev,
> >> > +				  indio_dev->channels,
> >> > +				  indio_dev->num_channels);
> >> > +	if (ret)
> >> > +		goto error_free_irq;
> >> > +
> >> > +	return 0;
> >> > +
> >> > +error_free_irq:
> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> >> 
> >> What is the point of using devm_* here if you are doing explicit
> >> management of the resource anyway (you explicitly release it in all
> >code
> >> paths)?
> >> 
> >> Thanks.
> >> 
> >> -- 
> >> Dmitry
> >
> >I admit I am unaware at the moment about how it works.
> >
> >I use devm and simply ignore the error path?
> >
> >The devm function header description said something about using
> >devm_free when freeing. And this is the way I am used to seeing 
> >error handling.
> 

> The devm interfaces ensure this is all cleaned when the device is
> removed thus avoiding the need to free the stuff explicitly.  Device
> will get freed on deliberate remove and on an error from probe. Hence
> you can drop all calls to devm free. The devm free functions are only
> needed if you wish to free in order to reallocate. This might happen
> if you want to change a buffer size for instance.

However in this case such conversion us dangerous. With all but IRQ
resource managed by the traditional methods they will be released first
with IRQ handler deregistered very last. Therefore if device is not
properly quiesced IRQ raised during driver unbinding is likely to result
in kernel oops.

IOW devm_request_irq() is very often evil (it is still useful if _all_
your resources are managed by devm_*).

In case of your driver I'd recommend switching to
request_irq()/free_irq() instead.

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 13:58     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 13:58 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, dmitry.torokhov, linux-iio, linux-input, linux-kernel,
	bigeasy, gregkh

On 18/09/13 12:23, Zubair Lutfullah wrote:
> Previously the driver had only one-shot reading functionality.
> This patch adds continuous sampling support to the driver.
>
> Continuous sampling starts when buffer is enabled.
> HW IRQ wakes worker thread that pushes samples to userspace.
> Sampling stops when buffer is disabled by userspace.
>
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
>
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added INDIO_BUFFER_HARDWARE mode.
>
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Russ Dill <Russ.Dill@ti.com>
> Acked-by: Lee Jones <lee.jones@linaro.org>
> Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Very very nearly there. Couple of suggestions in-line.
(about 30 seconds work + testing ;)

I'm still unsure of why we need 32bit storage in the fifo
for the data.  I've proposed the changes I'd make to put it in 16 bit
storage inline.  The fact that the device is working in 32bits
is irrelevant given we only have a 12 bit number coming out and
it is in 12 least significant bits.  I guess there might be a tiny
cost in doing the conversion, but you kfifo will be half the size
as a result and that seems more likely to a worthwhile gain!

Out of interest, are you testing this with generic_buffer.c?
If so, what changes were necessary?  Given this driver will not
have a trigger it would be nice to update that example code to handle
that case if it doesn't already.

Thanks,

Jonathan


> ---
>   drivers/iio/adc/ti_am335x_adc.c      |  216 +++++++++++++++++++++++++++++++++-
>   include/linux/mfd/ti_am335x_tscadc.h |    9 ++
>   2 files changed, 220 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index a952538..b4b2ea0 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -28,12 +28,19 @@
>   #include <linux/iio/driver.h>
>
>   #include <linux/mfd/ti_am335x_tscadc.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>
>   struct tiadc_device {
>   	struct ti_tscadc_dev *mfd_tscadc;
>   	int channels;
>   	u8 channel_line[8];
>   	u8 channel_step[8];
> +	int buffer_en_ch_steps;
> +	u32 *data;
u16 *data;

Also it might actually save memory to simply have a fixed size array of 
the maximum size used here and avoid the extra allocations for the cost
of 16 bytes in here.

Hence,

u16 data[8];
>   };
>
>   static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
> @@ -56,8 +63,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
>   	return step_en;
>   }
>
> -static void tiadc_step_config(struct tiadc_device *adc_dev)
> +static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
>   {
> +	return 1 << adc_dev->channel_step[chan];
> +}
> +
> +static void tiadc_step_config(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>   	unsigned int stepconfig;
>   	int i, steps;
>
> @@ -72,7 +85,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>   	 */
>
>   	steps = TOTAL_STEPS - adc_dev->channels;
> -	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
> +	if (iio_buffer_enabled(indio_dev))
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
> +					| STEPCONFIG_MODE_SWCNT;
> +	else
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
>
>   	for (i = 0; i < adc_dev->channels; i++) {
>   		int chan;
> @@ -85,7 +102,177 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>   		adc_dev->channel_step[i] = steps;
>   		steps++;
>   	}
> +}
> +
> +static irqreturn_t tiadc_irq_h(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	unsigned int status, config;
> +	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
> +
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
> +	 */
> +	if (status & IRQENB_FIFO1OVRRUN) {
> +		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
> +		config = tiadc_readl(adc_dev, REG_CTRL);
> +		config &= ~(CNTRLREG_TSCSSENB);
> +		tiadc_writel(adc_dev, REG_CTRL, config);
> +		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
> +				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
> +		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
> +		return IRQ_HANDLED;
> +	} else if (status & IRQENB_FIFO1THRES) {
> +		/* Disable irq and wake worker thread */
> +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
I guess this is necessary given the sharing will make IRQF_ONESHOT
tricky. As disabling the source of the interrupts is nice and
easy here this will do the job.
> +		return IRQ_WAKE_THREAD;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static irqreturn_t tiadc_worker_h(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, k, fifo1count, read;
> +	u32 *data = adc_dev->data;
	u16* data = adc_dev->data;
> +
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (k = 0; k < fifo1count; k = k + i) {
> +		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> +			read = tiadc_readl(adc_dev, REG_FIFO1);
> +			data[i] = read & FIFOREAD_DATA_MASK;
//This is a 12 bit number after the mask so will fit just fine into 16 bits.
> +		}
> +		iio_push_to_buffers(indio_dev, (u8 *) data);
> +	}
>
> +	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
> +	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, fifo1count, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN |
> +				IRQENB_FIFO1UNDRFLW));
> +
> +	/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_sw_buffer_preenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_buffer *buffer = indio_dev->buffer;
> +	unsigned int enb = 0;
> +	u8 bit;
> +
(can drop this if doing the array with adc_dev as suggested above)
> +	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> +	if (adc_dev->data == NULL)
> +		return -ENOMEM;
> +
> +	tiadc_step_config(indio_dev);
> +	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
> +		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
> +	adc_dev->buffer_en_ch_steps = enb;
> +
> +	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
> +
> +	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
> +	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN);
> +
> +	return 0;
> +}
> +
> +static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int fifo1count, i, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
> +	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
> +
> +	/* Flush FIFO of leftover data in the time it takes to disable adc */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return 0;
> +}
> +
> +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +
> +	tiadc_step_config(indio_dev);
(can drop this if doing the array withing adc_dev as suggested above)
> +	kfree(adc_dev->data);
This is also missbalanced with the preenable (which is true of quite
a few drivers - one day I'll clean those up!)
> +
> +	return 0;
> +}



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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 13:58     ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18 13:58 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23-KWPb1pKIrIJaa/9Udqfwiw,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On 18/09/13 12:23, Zubair Lutfullah wrote:
> Previously the driver had only one-shot reading functionality.
> This patch adds continuous sampling support to the driver.
>
> Continuous sampling starts when buffer is enabled.
> HW IRQ wakes worker thread that pushes samples to userspace.
> Sampling stops when buffer is disabled by userspace.
>
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
>
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added INDIO_BUFFER_HARDWARE mode.
>
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
> Signed-off-by: Russ Dill <Russ.Dill-l0cyMroinI0@public.gmane.org>
> Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Acked-by: Sebastian Andrzej Siewior <bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>

Very very nearly there. Couple of suggestions in-line.
(about 30 seconds work + testing ;)

I'm still unsure of why we need 32bit storage in the fifo
for the data.  I've proposed the changes I'd make to put it in 16 bit
storage inline.  The fact that the device is working in 32bits
is irrelevant given we only have a 12 bit number coming out and
it is in 12 least significant bits.  I guess there might be a tiny
cost in doing the conversion, but you kfifo will be half the size
as a result and that seems more likely to a worthwhile gain!

Out of interest, are you testing this with generic_buffer.c?
If so, what changes were necessary?  Given this driver will not
have a trigger it would be nice to update that example code to handle
that case if it doesn't already.

Thanks,

Jonathan


> ---
>   drivers/iio/adc/ti_am335x_adc.c      |  216 +++++++++++++++++++++++++++++++++-
>   include/linux/mfd/ti_am335x_tscadc.h |    9 ++
>   2 files changed, 220 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> index a952538..b4b2ea0 100644
> --- a/drivers/iio/adc/ti_am335x_adc.c
> +++ b/drivers/iio/adc/ti_am335x_adc.c
> @@ -28,12 +28,19 @@
>   #include <linux/iio/driver.h>
>
>   #include <linux/mfd/ti_am335x_tscadc.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
>
>   struct tiadc_device {
>   	struct ti_tscadc_dev *mfd_tscadc;
>   	int channels;
>   	u8 channel_line[8];
>   	u8 channel_step[8];
> +	int buffer_en_ch_steps;
> +	u32 *data;
u16 *data;

Also it might actually save memory to simply have a fixed size array of 
the maximum size used here and avoid the extra allocations for the cost
of 16 bytes in here.

Hence,

u16 data[8];
>   };
>
>   static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
> @@ -56,8 +63,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
>   	return step_en;
>   }
>
> -static void tiadc_step_config(struct tiadc_device *adc_dev)
> +static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
>   {
> +	return 1 << adc_dev->channel_step[chan];
> +}
> +
> +static void tiadc_step_config(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>   	unsigned int stepconfig;
>   	int i, steps;
>
> @@ -72,7 +85,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>   	 */
>
>   	steps = TOTAL_STEPS - adc_dev->channels;
> -	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
> +	if (iio_buffer_enabled(indio_dev))
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
> +					| STEPCONFIG_MODE_SWCNT;
> +	else
> +		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
>
>   	for (i = 0; i < adc_dev->channels; i++) {
>   		int chan;
> @@ -85,7 +102,177 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
>   		adc_dev->channel_step[i] = steps;
>   		steps++;
>   	}
> +}
> +
> +static irqreturn_t tiadc_irq_h(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	unsigned int status, config;
> +	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
> +
> +	/*
> +	 * ADC and touchscreen share the IRQ line.
> +	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
> +	 */
> +	if (status & IRQENB_FIFO1OVRRUN) {
> +		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
> +		config = tiadc_readl(adc_dev, REG_CTRL);
> +		config &= ~(CNTRLREG_TSCSSENB);
> +		tiadc_writel(adc_dev, REG_CTRL, config);
> +		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
> +				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
> +		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
> +		return IRQ_HANDLED;
> +	} else if (status & IRQENB_FIFO1THRES) {
> +		/* Disable irq and wake worker thread */
> +		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
I guess this is necessary given the sharing will make IRQF_ONESHOT
tricky. As disabling the source of the interrupts is nice and
easy here this will do the job.
> +		return IRQ_WAKE_THREAD;
> +	}
> +
> +	return IRQ_NONE;
> +}
> +
> +static irqreturn_t tiadc_worker_h(int irq, void *private)
> +{
> +	struct iio_dev *indio_dev = private;
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, k, fifo1count, read;
> +	u32 *data = adc_dev->data;
	u16* data = adc_dev->data;
> +
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (k = 0; k < fifo1count; k = k + i) {
> +		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
> +			read = tiadc_readl(adc_dev, REG_FIFO1);
> +			data[i] = read & FIFOREAD_DATA_MASK;
//This is a 12 bit number after the mask so will fit just fine into 16 bits.
> +		}
> +		iio_push_to_buffers(indio_dev, (u8 *) data);
> +	}
>
> +	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
> +	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int i, fifo1count, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN |
> +				IRQENB_FIFO1UNDRFLW));
> +
> +	/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return iio_sw_buffer_preenable(indio_dev);
> +}
> +
> +static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	struct iio_buffer *buffer = indio_dev->buffer;
> +	unsigned int enb = 0;
> +	u8 bit;
> +
(can drop this if doing the array with adc_dev as suggested above)
> +	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> +	if (adc_dev->data == NULL)
> +		return -ENOMEM;
> +
> +	tiadc_step_config(indio_dev);
> +	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
> +		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
> +	adc_dev->buffer_en_ch_steps = enb;
> +
> +	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
> +
> +	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
> +	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
> +				| IRQENB_FIFO1OVRRUN);
> +
> +	return 0;
> +}
> +
> +static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +	int fifo1count, i, read;
> +
> +	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
> +				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
> +	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
> +
> +	/* Flush FIFO of leftover data in the time it takes to disable adc */
> +	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> +	for (i = 0; i < fifo1count; i++)
> +		read = tiadc_readl(adc_dev, REG_FIFO1);
> +
> +	return 0;
> +}
> +
> +static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
> +{
> +	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> +
> +	tiadc_step_config(indio_dev);
(can drop this if doing the array withing adc_dev as suggested above)
> +	kfree(adc_dev->data);
This is also missbalanced with the preenable (which is true of quite
a few drivers - one day I'll clean those up!)
> +
> +	return 0;
> +}

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 11:25           ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-18 11:25 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	Dmitry Torokhov, linux-iio, linux-input, linux-kernel, bigeasy,
	gregkh

On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
> "Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> >> Hi Zubair,
> >> 
> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> >> > +
> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> >> > +				irq,
> >> > +				pollfunc_th, pollfunc_bh,
> >> > +				flags, indio_dev->name,
> >> > +				indio_dev);
> >> > +	if (ret)
> >> > +		goto error_kfifo_free;
...
> >> > +
> >> > +error_free_irq:
> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> >> 
> >> What is the point of using devm_* here if you are doing explicit
> >> management of the resource anyway (you explicitly release it in all
> >> Dmitry
> 
> The devm interfaces ensure this is all cleaned when the device is removed thus avoiding the need to free the stuff explicitly.
> Device will get freed on deliberate remove and on an error from probe. Hence you can drop all calls to devm free. The devm free functions are only needed if you wish to free in order to reallocate. This might happen if you want to change a buffer size for instance.
>

Thank-you for the feedback.
Updated and resent the series.

Zubair
 
> -- 

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18 11:25           ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-18 11:25 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Zubair Lutfullah :,
	Dmitry Torokhov, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Wed, Sep 18, 2013 at 10:39:42AM +0100, Jonathan Cameron wrote:
> "Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> >> Hi Zubair,
> >> 
> >> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> >> > +
> >> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> >> > +				irq,
> >> > +				pollfunc_th, pollfunc_bh,
> >> > +				flags, indio_dev->name,
> >> > +				indio_dev);
> >> > +	if (ret)
> >> > +		goto error_kfifo_free;
...
> >> > +
> >> > +error_free_irq:
> >> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> >> 
> >> What is the point of using devm_* here if you are doing explicit
> >> management of the resource anyway (you explicitly release it in all
> >> Dmitry
> 
> The devm interfaces ensure this is all cleaned when the device is removed thus avoiding the need to free the stuff explicitly.
> Device will get freed on deliberate remove and on an error from probe. Hence you can drop all calls to devm free. The devm free functions are only needed if you wish to free in order to reallocate. This might happen if you want to change a buffer size for instance.
>

Thank-you for the feedback.
Updated and resent the series.

Zubair
 
> -- 

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

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-18 11:23 [PATCH V10 0/2] iio: input: " Zubair Lutfullah
@ 2013-09-18 11:23 ` Zubair Lutfullah
  2013-09-18 13:58     ` Jonathan Cameron
  0 siblings, 1 reply; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-18 11:23 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Previously the driver had only one-shot reading functionality.
This patch adds continuous sampling support to the driver.

Continuous sampling starts when buffer is enabled.
HW IRQ wakes worker thread that pushes samples to userspace.
Sampling stops when buffer is disabled by userspace.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added INDIO_BUFFER_HARDWARE mode.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/iio/adc/ti_am335x_adc.c      |  216 +++++++++++++++++++++++++++++++++-
 include/linux/mfd/ti_am335x_tscadc.h |    9 ++
 2 files changed, 220 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..b4b2ea0 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,19 @@
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int buffer_en_ch_steps;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,8 +63,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 {
+	return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
 	int i, steps;
 
@@ -72,7 +85,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
 		int chan;
@@ -85,7 +102,177 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+		return IRQ_HANDLED;
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Disable irq and wake worker thread */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_worker_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
 
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+	adc_dev->buffer_en_ch_steps = enb;
+
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return 0;
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of leftover data in the time it takes to disable adc */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return 0;
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
+	irqreturn_t (*pollfunc_bh)(int irq, void *p),
+	irqreturn_t (*pollfunc_th)(int irq, void *p),
+	int irq,
+	unsigned long flags,
+	const struct iio_buffer_setup_ops *setup_ops)
+{
+	int ret;
+
+	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+	if (!indio_dev->buffer)
+		return -ENOMEM;
+
+	ret = devm_request_threaded_irq(indio_dev->dev.parent,
+				irq,
+				pollfunc_th, pollfunc_bh,
+				flags, indio_dev->name,
+				indio_dev);
+	if (ret)
+		goto error_kfifo_free;
+
+	indio_dev->setup_ops = setup_ops;
+	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+
+	ret = iio_buffer_register(indio_dev,
+				  indio_dev->channels,
+				  indio_dev->num_channels);
+	if (ret)
+		goto error_kfifo_free;
+
+	return 0;
+
+error_kfifo_free:
+	iio_kfifo_free(indio_dev->buffer);
+	return ret;
+}
+
+static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
+{
+	iio_kfifo_free(indio_dev->buffer);
+	iio_buffer_unregister(indio_dev);
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +307,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -147,6 +335,10 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -237,20 +429,33 @@ static int tiadc_probe(struct platform_device *pdev)
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
 		return err;
 
-	err = iio_device_register(indio_dev);
+	err = tiadc_iio_buffered_hardware_setup(indio_dev,
+		&tiadc_worker_h,
+		&tiadc_irq_h,
+		adc_dev->mfd_tscadc->irq,
+		IRQF_SHARED,
+		&tiadc_buffer_setup_ops);
+
 	if (err)
 		goto err_free_channels;
 
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_buffer_unregister;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
 	return err;
@@ -263,6 +468,7 @@ static int tiadc_remove(struct platform_device *pdev)
 	u32 step_en;
 
 	iio_device_unregister(indio_dev);
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
@@ -301,7 +507,7 @@ static int tiadc_resume(struct device *dev)
 	restore &= ~(CNTRLREG_POWERDOWN);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..7d98562 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,16 +46,24 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
-- 
1.7.9.5


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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  9:39         ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18  9:39 UTC (permalink / raw)
  To: Zubair Lutfullah :, Dmitry Torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh



"Zubair Lutfullah :" <zubair.lutfullah@gmail.com> wrote:
>On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> Hi Zubair,
>> 
>> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
>> > +
>> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> > +				irq,
>> > +				pollfunc_th, pollfunc_bh,
>> > +				flags, indio_dev->name,
>> > +				indio_dev);
>> > +	if (ret)
>> > +		goto error_kfifo_free;
>> > +
>> > +	indio_dev->setup_ops = setup_ops;
>> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> > +
>> > +	ret = iio_buffer_register(indio_dev,
>> > +				  indio_dev->channels,
>> > +				  indio_dev->num_channels);
>> > +	if (ret)
>> > +		goto error_free_irq;
>> > +
>> > +	return 0;
>> > +
>> > +error_free_irq:
>> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> 
>> What is the point of using devm_* here if you are doing explicit
>> management of the resource anyway (you explicitly release it in all
>code
>> paths)?
>> 
>> Thanks.
>> 
>> -- 
>> Dmitry
>
>I admit I am unaware at the moment about how it works.
>
>I use devm and simply ignore the error path?
>
>The devm function header description said something about using
>devm_free when freeing. And this is the way I am used to seeing 
>error handling.

The devm interfaces ensure this is all cleaned when the device is removed thus avoiding the need to free the stuff explicitly.
Device will get freed on deliberate remove and on an error from probe. Hence you can drop all calls to devm free. The devm free functions are only needed if you wish to free in order to reallocate. This might happen if you want to change a buffer size for instance.
>
>Zubair

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  9:39         ` Jonathan Cameron
  0 siblings, 0 replies; 67+ messages in thread
From: Jonathan Cameron @ 2013-09-18  9:39 UTC (permalink / raw)
  To: Zubair Lutfullah :, Dmitry Torokhov
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r



"Zubair Lutfullah :" <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
>> Hi Zubair,
>> 
>> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
>> > +
>> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
>> > +				irq,
>> > +				pollfunc_th, pollfunc_bh,
>> > +				flags, indio_dev->name,
>> > +				indio_dev);
>> > +	if (ret)
>> > +		goto error_kfifo_free;
>> > +
>> > +	indio_dev->setup_ops = setup_ops;
>> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
>> > +
>> > +	ret = iio_buffer_register(indio_dev,
>> > +				  indio_dev->channels,
>> > +				  indio_dev->num_channels);
>> > +	if (ret)
>> > +		goto error_free_irq;
>> > +
>> > +	return 0;
>> > +
>> > +error_free_irq:
>> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
>> 
>> What is the point of using devm_* here if you are doing explicit
>> management of the resource anyway (you explicitly release it in all
>code
>> paths)?
>> 
>> Thanks.
>> 
>> -- 
>> Dmitry
>
>I admit I am unaware at the moment about how it works.
>
>I use devm and simply ignore the error path?
>
>The devm function header description said something about using
>devm_free when freeing. And this is the way I am used to seeing 
>error handling.

The devm interfaces ensure this is all cleaned when the device is removed thus avoiding the need to free the stuff explicitly.
Device will get freed on deliberate remove and on an error from probe. Hence you can drop all calls to devm free. The devm free functions are only needed if you wish to free in order to reallocate. This might happen if you want to change a buffer size for instance.
>
>Zubair

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  6:54       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-18  6:54 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah, jic23, linux-iio, linux-input, linux-kernel,
	bigeasy, gregkh

On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> Hi Zubair,
> 
> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> > +
> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> > +				irq,
> > +				pollfunc_th, pollfunc_bh,
> > +				flags, indio_dev->name,
> > +				indio_dev);
> > +	if (ret)
> > +		goto error_kfifo_free;
> > +
> > +	indio_dev->setup_ops = setup_ops;
> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> > +
> > +	ret = iio_buffer_register(indio_dev,
> > +				  indio_dev->channels,
> > +				  indio_dev->num_channels);
> > +	if (ret)
> > +		goto error_free_irq;
> > +
> > +	return 0;
> > +
> > +error_free_irq:
> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> 
> What is the point of using devm_* here if you are doing explicit
> management of the resource anyway (you explicitly release it in all code
> paths)?
> 
> Thanks.
> 
> -- 
> Dmitry

I admit I am unaware at the moment about how it works.

I use devm and simply ignore the error path?

The devm function header description said something about using
devm_free when freeing. And this is the way I am used to seeing 
error handling.

Zubair

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  6:54       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-09-18  6:54 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Zubair Lutfullah, jic23-KWPb1pKIrIJaa/9Udqfwiw,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Tue, Sep 17, 2013 at 09:27:27PM -0700, Dmitry Torokhov wrote:
> Hi Zubair,
> 
> On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> > +
> > +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> > +				irq,
> > +				pollfunc_th, pollfunc_bh,
> > +				flags, indio_dev->name,
> > +				indio_dev);
> > +	if (ret)
> > +		goto error_kfifo_free;
> > +
> > +	indio_dev->setup_ops = setup_ops;
> > +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> > +
> > +	ret = iio_buffer_register(indio_dev,
> > +				  indio_dev->channels,
> > +				  indio_dev->num_channels);
> > +	if (ret)
> > +		goto error_free_irq;
> > +
> > +	return 0;
> > +
> > +error_free_irq:
> > +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
> 
> What is the point of using devm_* here if you are doing explicit
> management of the resource anyway (you explicitly release it in all code
> paths)?
> 
> Thanks.
> 
> -- 
> Dmitry

I admit I am unaware at the moment about how it works.

I use devm and simply ignore the error path?

The devm function header description said something about using
devm_free when freeing. And this is the way I am used to seeing 
error handling.

Zubair

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  4:27     ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-18  4:27 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, linux-iio, linux-input, linux-kernel, bigeasy, gregkh

Hi Zubair,

On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> +
> +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> +				irq,
> +				pollfunc_th, pollfunc_bh,
> +				flags, indio_dev->name,
> +				indio_dev);
> +	if (ret)
> +		goto error_kfifo_free;
> +
> +	indio_dev->setup_ops = setup_ops;
> +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> +
> +	ret = iio_buffer_register(indio_dev,
> +				  indio_dev->channels,
> +				  indio_dev->num_channels);
> +	if (ret)
> +		goto error_free_irq;
> +
> +	return 0;
> +
> +error_free_irq:
> +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);

What is the point of using devm_* here if you are doing explicit
management of the resource anyway (you explicitly release it in all code
paths)?

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-09-18  4:27     ` Dmitry Torokhov
  0 siblings, 0 replies; 67+ messages in thread
From: Dmitry Torokhov @ 2013-09-18  4:27 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23-KWPb1pKIrIJaa/9Udqfwiw, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	bigeasy-hfZtesqFncYOwBW4kG4KsQ,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

Hi Zubair,

On Tue, Sep 17, 2013 at 09:44:07AM +0500, Zubair Lutfullah wrote:
> +
> +	ret = devm_request_threaded_irq(indio_dev->dev.parent,
> +				irq,
> +				pollfunc_th, pollfunc_bh,
> +				flags, indio_dev->name,
> +				indio_dev);
> +	if (ret)
> +		goto error_kfifo_free;
> +
> +	indio_dev->setup_ops = setup_ops;
> +	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
> +
> +	ret = iio_buffer_register(indio_dev,
> +				  indio_dev->channels,
> +				  indio_dev->num_channels);
> +	if (ret)
> +		goto error_free_irq;
> +
> +	return 0;
> +
> +error_free_irq:
> +	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);

What is the point of using devm_* here if you are doing explicit
management of the resource anyway (you explicitly release it in all code
paths)?

Thanks.

-- 
Dmitry

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

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-17  4:44 [PATCH V9 0/2] iio: input: " Zubair Lutfullah
@ 2013-09-17  4:44 ` Zubair Lutfullah
  2013-09-18  4:27     ` Dmitry Torokhov
  0 siblings, 1 reply; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-17  4:44 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Previously the driver had only one-shot reading functionality.
This patch adds continuous sampling support to the driver.

Continuous sampling starts when buffer is enabled.
HW IRQ wakes worker thread that pushes samples to userspace.
Sampling stops when buffer is disabled by userspace.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added INDIO_BUFFER_HARDWARE mode.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/iio/adc/ti_am335x_adc.c      |  222 +++++++++++++++++++++++++++++++++-
 include/linux/mfd/ti_am335x_tscadc.h |    9 ++
 2 files changed, 226 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..fa916f3 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,19 @@
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int buffer_en_ch_steps;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,8 +63,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 {
+	return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
 	int i, steps;
 
@@ -72,7 +85,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
 		int chan;
@@ -85,7 +102,183 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+		return IRQ_HANDLED;
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Disable irq and wake worker thread */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_worker_h(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
+
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
 
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+	adc_dev->buffer_en_ch_steps = enb;
+
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return 0;
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of leftover data in the time it takes to disable adc */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return 0;
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
+	irqreturn_t (*pollfunc_bh)(int irq, void *p),
+	irqreturn_t (*pollfunc_th)(int irq, void *p),
+	int irq,
+	unsigned long flags,
+	const struct iio_buffer_setup_ops *setup_ops)
+{
+	int ret;
+
+	indio_dev->buffer = iio_kfifo_allocate(indio_dev);
+	if (!indio_dev->buffer)
+		return -ENOMEM;
+
+	ret = devm_request_threaded_irq(indio_dev->dev.parent,
+				irq,
+				pollfunc_th, pollfunc_bh,
+				flags, indio_dev->name,
+				indio_dev);
+	if (ret)
+		goto error_kfifo_free;
+
+	indio_dev->setup_ops = setup_ops;
+	indio_dev->modes |= INDIO_BUFFER_HARDWARE;
+
+	ret = iio_buffer_register(indio_dev,
+				  indio_dev->channels,
+				  indio_dev->num_channels);
+	if (ret)
+		goto error_free_irq;
+
+	return 0;
+
+error_free_irq:
+	devm_free_irq(indio_dev->dev.parent, irq, indio_dev);
+error_kfifo_free:
+	iio_kfifo_free(indio_dev->buffer);
+	return ret;
+}
+
+static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	devm_free_irq(indio_dev->dev.parent,
+			adc_dev->mfd_tscadc->irq, indio_dev);
+	iio_kfifo_free(indio_dev->buffer);
+	iio_buffer_unregister(indio_dev);
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +313,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -147,6 +341,10 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -237,20 +435,33 @@ static int tiadc_probe(struct platform_device *pdev)
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
 		return err;
 
-	err = iio_device_register(indio_dev);
+	err = tiadc_iio_buffered_hardware_setup(indio_dev,
+		&tiadc_worker_h,
+		&tiadc_irq_h,
+		adc_dev->mfd_tscadc->irq,
+		IRQF_SHARED,
+		&tiadc_buffer_setup_ops);
+
 	if (err)
 		goto err_free_channels;
 
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_buffer_unregister;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
 	return err;
@@ -263,6 +474,7 @@ static int tiadc_remove(struct platform_device *pdev)
 	u32 step_en;
 
 	iio_device_unregister(indio_dev);
+	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
@@ -301,7 +513,7 @@ static int tiadc_resume(struct device *dev)
 	restore &= ~(CNTRLREG_POWERDOWN);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..7d98562 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,16 +46,24 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
-- 
1.7.9.5


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

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-09-01 11:07 [PATCH V7 0/2] iio: input: ti_am335x_tscadc: Add continuous sampling support to adc Zubair Lutfullah
@ 2013-09-01 11:07 ` Zubair Lutfullah
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-09-01 11:07 UTC (permalink / raw)
  To: jic23, dmitry.torokhov
  Cc: linux-iio, linux-input, linux-kernel, bigeasy, gregkh, zubair.lutfullah

Previously the driver had only one-shot reading functionality.
This patch adds triggered buffer support to the driver.

Continuous sampling starts when buffer is enabled.
And samples are pushed to userpace by the trigger which
triggers automatically at every hardware interrupt
of FIFO1 filling with samples upto threshold value.

Userspace responsibility to stop sampling by writing zero
in the buffer enable file.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added trigger support.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russ Dill <Russ.Dill@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/iio/adc/Kconfig              |    1 +
 drivers/iio/adc/ti_am335x_adc.c      |  243 +++++++++++++++++++++++++++++++---
 include/linux/mfd/ti_am335x_tscadc.h |   13 ++
 3 files changed, 237 insertions(+), 20 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 09371cb..cfa2039 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -167,6 +167,7 @@ config TI_ADC081C
 config TI_AM335X_ADC
 	tristate "TI's AM335X ADC driver"
 	depends on MFD_TI_AM335X_TSCADC
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Texas Instruments ADC
 	  driver which is also a MFD client.
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..1626e16 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -24,16 +24,23 @@
 #include <linux/iio/iio.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int irq;
+	int buffer_en_ch_steps;
+	struct iio_trigger *trig;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,10 +63,16 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
 {
+	return 1 << adc_dev->channel_step[chan];
+}
+
+static void tiadc_step_config(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
-	int i, steps;
+	int i, steps, chan;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -72,11 +85,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
-		int chan;
-
 		chan = adc_dev->channel_line[i];
 		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
 				stepconfig | STEPCONFIG_INP(chan));
@@ -85,7 +100,167 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+		return IRQ_HANDLED;
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Trigger to push FIFO data to iio buffer */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
+
+}
+
+static irqreturn_t tiadc_trigger_h(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
 
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO before starting sampling */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+	adc_dev->buffer_en_ch_steps = enb;
+
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of any leftover data */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops tiadc_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static int tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_trigger *trig = adc_dev->trig;
+	int ret;
+
+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
+	if (trig == NULL)
+		return -ENOMEM;
+
+	trig->dev.parent = indio_dev->dev.parent;
+	trig->ops = &tiadc_trigger_ops;
+	iio_trigger_set_drvdata(trig, indio_dev);
+
+	ret = iio_trigger_register(trig);
+	if (ret)
+		goto err_free_trigger;
+
+	return 0;
+
+err_free_trigger:
+	iio_trigger_free(adc_dev->trig);
+
+	return ret;
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +295,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -142,11 +318,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
-	u32 step = UINT_MAX;
 	bool found = false;
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -168,15 +347,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	 * Hence we need to flush out this data.
 	 */
 
-	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
-		if (chan->channel == adc_dev->channel_line[i]) {
-			step = adc_dev->channel_step[i];
-			break;
-		}
-	}
-	if (WARN_ON_ONCE(step == UINT_MAX))
-		return -EINVAL;
-
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -231,26 +401,49 @@ static int tiadc_probe(struct platform_device *pdev)
 		channels++;
 	}
 	adc_dev->channels = channels;
+	adc_dev->irq = adc_dev->mfd_tscadc->irq;
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
 		return err;
 
-	err = iio_device_register(indio_dev);
+	err = tiadc_iio_allocate_trigger(indio_dev);
 	if (err)
 		goto err_free_channels;
 
+	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
+		indio_dev->name, indio_dev);
+	if (err)
+		goto err_unregister_trigger;
+
+	err = iio_triggered_buffer_setup(indio_dev, NULL,
+			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
+	if (err)
+		goto err_free_irq;
+
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_buffer_unregister;
+
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	iio_buffer_unregister(indio_dev);
+err_free_irq:
+	free_irq(adc_dev->irq, indio_dev);
+err_unregister_trigger:
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
 	return err;
@@ -262,7 +455,11 @@ static int tiadc_remove(struct platform_device *pdev)
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	u32 step_en;
 
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
+	free_irq(adc_dev->irq, indio_dev);
 	iio_device_unregister(indio_dev);
+	iio_buffer_unregister(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
@@ -298,10 +495,16 @@ static int tiadc_resume(struct device *dev)
 
 	/* Make sure ADC is powered up */
 	restore = tiadc_readl(adc_dev, REG_CTRL);
-	restore &= ~(CNTRLREG_POWERDOWN);
+	restore &= ~(CNTRLREG_TSCSSENB);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+	tiadc_step_config(indio_dev);
+
+	/* Make sure ADC is powered up */
+	restore &= ~(CNTRLREG_POWERDOWN);
+	restore |= CNTRLREG_TSCSSENB;
+	tiadc_writel(adc_dev, REG_CTRL, restore);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..a372ebf 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,17 +46,25 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
 #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
@@ -153,6 +162,10 @@ struct ti_tscadc_dev {
 
 	/* adc device */
 	struct adc_device *adc;
+
+	/* Context save */
+	unsigned int irqstat;
+	unsigned int ctrl;
 };
 
 static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
-- 
1.7.9.5


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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:59         ` Zubair Lutfullah :
@ 2013-08-29  7:56           ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-29  7:56 UTC (permalink / raw)
  To: zubair.lutfullah
  Cc: Zubair Lutfullah: zubair.lutfullah, jic23, lee.jones, linux-iio,
	linux-input, linux-kernel, gregkh

On 08/28/2013 08:59 PM, Zubair Lutfullah : wrote:
>>>>> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>>>>> +	iio_device_free(indio_dev);
> ...
>> Point me one driver please. Do they use devm_iio_device_alloc() like
>> you do or iio_device_alloc()? In case of the latter you need to
>> manually free the memory.
> Aah. So the devm_* stuff makes the difference.
> Thanks for pointing it out. Will remove it.

Yes, devm_* stuff. There is also matching kmalloc() version of it for
the very same purpose and a few others…

In future please post a bugfix (adding iio_device_free() to plug a
memory leak) as a separate patch. It has nothing todo with "continuous
sampling support" and it case it is valid it could be applied
independantly and ported back to earlier kernel if necessary. The way
you did here you just "silently" plugged a memory leak.

> 
> ZubairLK
> 

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:43     ` Zubair Lutfullah :
@ 2013-08-29  7:49       ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-29  7:49 UTC (permalink / raw)
  To: zubair.lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

On 08/28/2013 08:43 PM, Zubair Lutfullah : wrote:
> On Wed, Aug 28, 2013 at 03:01:24PM +0200, Sebastian Andrzej Siewior wrote:
>> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
>>
>> I am mostly happy with it. There are just two things I pointed out.
>> Besides that, it looks good from my side.
> Sign-off?

Acked-by if anything. For that you should fix the things I pointed out.

>>> +static irqreturn_t tiadc_irq(int irq, void *private)
>>> +{
> ...
>>> +	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
>>> +	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
>>> +	if (status == false)
>>> +		return IRQ_HANDLED;
>>> +	else
>>> +		return IRQ_NONE;
>>
>> As I said in 1/2 of this series, you shouldn't do this. Both handlers of a
>> shared line are invoked once an interrupt is detected.
>>
>> …
> I somehow missed sending these patches to Dmitry.. 
> I'll do it next series.
> 
> He originally suggested this way.
> An alternative was to handle irqs in mfd core which would 
> seriously complicate code and patches..
> 
> Whenever I change the handlers to the way you suggest.
> i.e. Handle what each irq handler does and return IRQ_HANDLED
> if the irq handler handled nothing then return IRQ_NONE.
> 
> The driver hangs when I'm brutal while touching the TSC and 
> continuously sampling the ADC. Not always. But happens.
> 
> When I check /proc/interrupts the hardware irqs seem to be firing.
> But for some reason the whole thing messes up..

In that case it is likely that the irqs are not acked properly and
therefore fired again. So you should check that.

If you look at handle_irq_event_percpu() in kernel/irq/handle.c. That
is the function that invokes your handler. It looks the following in
short:

	do {
		res = action->handler(irq, action->dev_id);
		retval |= res;
		action = action->next;
	} while (action);
	note_interrupt(irq, desc, retval);

As you see all registered handlers are invoked no matter of the return
code. The common return code is pass over to note_interrupt() which will
disable the irq line if IRQ_NONE is returned too many times.

It is possible that the read of REG_IRQSTATUS will ACK those and
therefore it does not fire anymore. I don't have the manual next to me
right now, so please check how the interrupt is acked by reading the
status register or by writing a bit to the status register etc.
_If_ the status bit is auto-cleared on read but the interrupt is not
acked and remains acktive then you won't see it in the "other" handler,
do nothing but the source will remain active.
This might match your description. In that case I suggest to register
that interrupt in the MFD part let TSC & ADC register via the mfd part.
The MFD part would read the status register and pass it to the two
handlers so it not lost.

In any case: please check what is really going on. This workaround you
have now does not look good.

> Thanks
> ZubairLK


Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:35       ` Sebastian Andrzej Siewior
@ 2013-08-28 18:59         ` Zubair Lutfullah :
  2013-08-29  7:56           ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:59 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: zubair.lutfullah, jic23, lee.jones, linux-iio, linux-input,
	linux-kernel, gregkh

On Wed, Aug 28, 2013 at 08:35:30PM +0200, Sebastian Andrzej Siewior wrote:
> On 08/28/2013 08:19 PM, Zubair Lutfullah : wrote:
> > On Wed, Aug 28, 2013 at 06:43:08PM +0200, Sebastian Andrzej Siewior wrote:
> >> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> >>
> >>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >>> index a952538..ae2202b 100644
> >>> --- a/drivers/iio/adc/ti_am335x_adc.c
> >>> +++ b/drivers/iio/adc/ti_am335x_adc.c
> >>> @@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
> >> …
> >>> +err_free_device:
> >>> +	iio_device_free(indio_dev);
> >>
> >> I am not sure about this one.
> > 
> > If I understand correctly, if devm_iio_device_alloc 
> > is successful earlier in the code and subsequent stuff fails. 
> > 
> > Then the code jumps to err_free_device and this is needed.
> 
> Yes, but devm_() helper release the memory on failer _or_ device /
> driver removal.
I see. 

> >>> @@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> >>> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
...
> >>> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
> >>> +	iio_device_free(indio_dev);
...
> Point me one driver please. Do they use devm_iio_device_alloc() like
> you do or iio_device_alloc()? In case of the latter you need to
> manually free the memory.
Aah. So the devm_* stuff makes the difference.
Thanks for pointing it out. Will remove it.

ZubairLK

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:38       ` Sebastian Andrzej Siewior
@ 2013-08-28 18:55         ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:55 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: zubair.lutfullah, jic23, lee.jones, linux-iio, linux-input,
	linux-kernel, gregkh

On Wed, Aug 28, 2013 at 08:38:55PM +0200, Sebastian Andrzej Siewior wrote:
> On 08/28/2013 08:22 PM, Zubair Lutfullah : wrote:
> > On Wed, Aug 28, 2013 at 04:18:35PM +0200, Sebastian Andrzej Siewior wrote:
> >> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> >>
> >>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >>> index a952538..ae2202b 100644
> >>> --- a/drivers/iio/adc/ti_am335x_adc.c
> >>> +++ b/drivers/iio/adc/ti_am335x_adc.c
> >> …
> >>
> >>> +static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> > ...
> >>> +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
> >>> +	if (trig == NULL)
> >>> +		return NULL;
> >>> +
> > ...
> >>> +	ret = iio_trigger_register(trig);
> >>> +	if (ret)
> >>
> >> shouldn't you free the trigger / undo iio_trigger_alloc() here?
> >>
> >>> +		return NULL;
> >>> +
> > ...
> > Possible. It's done in the probe section just 
> > to keep error handling bunched there.
> 
> The caller of iio_trigger *tiadc_iio_allocate_trigger() should not
> cleanup after it in case of a half failure. The function itself should
> be in charge of it. However you never assign the pointer so you leak
> the memory here.
> 
A very valid point indeed.
I'll fix this.
Thanks.
> >>
> >>>
> >>> static const char * const chan_name_ain[] = {
> >>> @@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> >>> 					  sizeof(struct tiadc_device));
> >>> 	if (indio_dev == NULL) {
> >>> 		dev_err(&pdev->dev, "failed to allocate iio device\n");
> >>> -		return -ENOMEM;
> >>> +		err = -ENOMEM;
> >>> +		goto err_ret;
> >> Why the jump instead of leave right away?
> >>
> >>> 	}
> > Again. Error handling all in one place.
> 
> But you simply leave at the end of the function, no error handling is
> done / required if you leave here. So this a zero change and has
> nothing to do with the "continuous sampling support" support.
> 
Again. Thanks.

ZubairLK

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 13:01     ` Sebastian Andrzej Siewior
  (?)
@ 2013-08-28 18:43     ` Zubair Lutfullah :
  2013-08-29  7:49       ` Sebastian Andrzej Siewior
  -1 siblings, 1 reply; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:43 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Zubair Lutfullah, jic23, lee.jones, linux-iio, linux-input,
	linux-kernel, gregkh

On Wed, Aug 28, 2013 at 03:01:24PM +0200, Sebastian Andrzej Siewior wrote:
> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> 
> I am mostly happy with it. There are just two things I pointed out.
> Besides that, it looks good from my side.
Sign-off?

> >+static irqreturn_t tiadc_irq(int irq, void *private)
> >+{
...
> >+	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
> >+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
> >+	if (status == false)
> >+		return IRQ_HANDLED;
> >+	else
> >+		return IRQ_NONE;
> 
> As I said in 1/2 of this series, you shouldn't do this. Both handlers of a
> shared line are invoked once an interrupt is detected.
> 
> …
I somehow missed sending these patches to Dmitry.. 
I'll do it next series.

He originally suggested this way.
An alternative was to handle irqs in mfd core which would 
seriously complicate code and patches..

Whenever I change the handlers to the way you suggest.
i.e. Handle what each irq handler does and return IRQ_HANDLED
if the irq handler handled nothing then return IRQ_NONE.

The driver hangs when I'm brutal while touching the TSC and 
continuously sampling the ADC. Not always. But happens.

When I check /proc/interrupts the hardware irqs seem to be firing.
But for some reason the whole thing messes up..

> >+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
> >+{
> >+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> >+	struct iio_buffer *buffer = indio_dev->buffer;
> >+	unsigned int enb = 0, stepnum;
> >+	u8 bit;
> >+
> >+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
> >+	if (adc_dev->data == NULL)
> >+		return -ENOMEM;
> >+
> >+	tiadc_step_config(indio_dev);
> >+	for_each_set_bit(bit, buffer->scan_mask,
> >+			adc_dev->channels) {
> >+		struct iio_chan_spec const *chan = indio_dev->channels + bit;
> >+		/*
> >+		 * There are a total of 16 steps available
> >+		 * that are shared between ADC and touchscreen.
> >+		 * We start configuring from step 16 to 0 incase of
> >+		 * ADC. Hence the relation between input channel
> >+		 * and step for ADC would be as below.
> >+		 */
> >+		stepnum = chan->channel + 9;
> >+		enb |= (1 << stepnum);
> 
> Hmm. This looks odd.
>  
> In tiadc_step_config() we do:
> | steps = TOTAL_STEPS - adc_dev->channels;
> |…
> | for (i = 0; i < adc_dev->channels; i++) {
> |         chan = adc_dev->channel_line[i];
> |         tiadc_writel(adc_dev,
> |                         REG_STEPCONFIG(steps),
> |                         stepconfig
> |                         |
> |                         STEPCONFIG_INP(chan));
> |         tiadc_writel(adc_dev,
> |                         REG_STEPDELAY(steps),
> |                         STEPCONFIG_OPENDLY);
> |         adc_dev->channel_step[i]
> |                 =
> |                 steps;
> |         steps++;
> | }
> 
> That means if we have only one channel we enable the last step bit /
> topmost that is bit 16. For the "default" four channels we get 0x1e000
> as mask which means bit 13 to 16. 
> If you do have only one channel with the number 4 you then
> get_adc_step_mask() will compute the correct step mask but here enable
> step 14 instead of step 16.
> 
> What about the following as replacement?
I sense a mismatch. Probably because of different styles of coding
these bit handling :).

I'll look into it and the alternative way you suggested as well.

Thanks
ZubairLK


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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:22       ` Zubair Lutfullah :
  (?)
@ 2013-08-28 18:38       ` Sebastian Andrzej Siewior
  2013-08-28 18:55         ` Zubair Lutfullah :
  -1 siblings, 1 reply; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 18:38 UTC (permalink / raw)
  To: zubair.lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

On 08/28/2013 08:22 PM, Zubair Lutfullah : wrote:
> On Wed, Aug 28, 2013 at 04:18:35PM +0200, Sebastian Andrzej Siewior wrote:
>> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
>>
>>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>>> index a952538..ae2202b 100644
>>> --- a/drivers/iio/adc/ti_am335x_adc.c
>>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>> …
>>
>>> +static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
> ...
>>> +	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
>>> +	if (trig == NULL)
>>> +		return NULL;
>>> +
> ...
>>> +	ret = iio_trigger_register(trig);
>>> +	if (ret)
>>
>> shouldn't you free the trigger / undo iio_trigger_alloc() here?
>>
>>> +		return NULL;
>>> +
> ...
> Possible. It's done in the probe section just 
> to keep error handling bunched there.

The caller of iio_trigger *tiadc_iio_allocate_trigger() should not
cleanup after it in case of a half failure. The function itself should
be in charge of it. However you never assign the pointer so you leak
the memory here.

>>
>>>
>>> static const char * const chan_name_ain[] = {
>>> @@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
>>> 					  sizeof(struct tiadc_device));
>>> 	if (indio_dev == NULL) {
>>> 		dev_err(&pdev->dev, "failed to allocate iio device\n");
>>> -		return -ENOMEM;
>>> +		err = -ENOMEM;
>>> +		goto err_ret;
>> Why the jump instead of leave right away?
>>
>>> 	}
> Again. Error handling all in one place.

But you simply leave at the end of the function, no error handling is
done / required if you leave here. So this a zero change and has
nothing to do with the "continuous sampling support" support.

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-28 18:19       ` Zubair Lutfullah :
  (?)
@ 2013-08-28 18:35       ` Sebastian Andrzej Siewior
  2013-08-28 18:59         ` Zubair Lutfullah :
  -1 siblings, 1 reply; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 18:35 UTC (permalink / raw)
  To: zubair.lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

On 08/28/2013 08:19 PM, Zubair Lutfullah : wrote:
> On Wed, Aug 28, 2013 at 06:43:08PM +0200, Sebastian Andrzej Siewior wrote:
>> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
>>
>>> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>>> index a952538..ae2202b 100644
>>> --- a/drivers/iio/adc/ti_am335x_adc.c
>>> +++ b/drivers/iio/adc/ti_am335x_adc.c
>>> @@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
>> …
>>> +err_free_device:
>>> +	iio_device_free(indio_dev);
>>
>> I am not sure about this one.
> 
> If I understand correctly, if devm_iio_device_alloc 
> is successful earlier in the code and subsequent stuff fails. 
> 
> Then the code jumps to err_free_device and this is needed.

Yes, but devm_() helper release the memory on failer _or_ device /
driver removal.

>>> +err_ret:
>>> 	return err;
>>> }
>>>
>>> @@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
>>> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>>> 	u32 step_en;
>>>
>>> +	free_irq(adc_dev->irq, indio_dev);
>>> 	iio_device_unregister(indio_dev);
>>> +	iio_buffer_unregister(indio_dev);
>>> 	tiadc_channels_remove(indio_dev);
>>>
>>> 	step_en = get_adc_step_mask(adc_dev);
>>> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>>> +	iio_device_free(indio_dev);
>>
>> But this one is wrong. The will be removed via dev_res() and if you do
>> it here as well then dev_res() will decrement the reference of an unused
>> object.
> I was unaware of this aspect.
> 
> *but*
> 
> iio_simple_dummy.c has it in its remove function.
> And I just checked and found it in several drivers as well.
> 
> I'll leave this to the more experienced folks on the list..

You can belive me one thing or the other :)
Point me one driver please. Do they use devm_iio_device_alloc() like
you do or iio_device_alloc()? In case of the latter you need to
manually free the memory.

>>>
>>> 	return 0;
>>> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 18:22       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:22 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Zubair Lutfullah, jic23, lee.jones, linux-iio, linux-input,
	linux-kernel, gregkh

On Wed, Aug 28, 2013 at 04:18:35PM +0200, Sebastian Andrzej Siewior wrote:
> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> 
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >index a952538..ae2202b 100644
> >--- a/drivers/iio/adc/ti_am335x_adc.c
> >+++ b/drivers/iio/adc/ti_am335x_adc.c
> …
> 
> >+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
...
> >+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
> >+	if (trig == NULL)
> >+		return NULL;
> >+
...
> >+	ret = iio_trigger_register(trig);
> >+	if (ret)
> 
> shouldn't you free the trigger / undo iio_trigger_alloc() here?
> 
> >+		return NULL;
> >+
...
Possible. It's done in the probe section just 
to keep error handling bunched there.
> 
> > 
> > static const char * const chan_name_ain[] = {
> >@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> > 					  sizeof(struct tiadc_device));
> > 	if (indio_dev == NULL) {
> > 		dev_err(&pdev->dev, "failed to allocate iio device\n");
> >-		return -ENOMEM;
> >+		err = -ENOMEM;
> >+		goto err_ret;
> Why the jump instead of leave right away?
> 
> > 	}
Again. Error handling all in one place.

> > 
> >@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> > 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > 	u32 step_en;
> > 
> >+	free_irq(adc_dev->irq, indio_dev);
> > 	iio_device_unregister(indio_dev);
> >+	iio_buffer_unregister(indio_dev);
> > 	tiadc_channels_remove(indio_dev);
> 
> I think you need also to
> 
> 	iio_trigger_unregister(adc_dev->trig);
> 	iio_trigger_free(adc_dev->trig);
> 
> here.
Indeed.
Thanks for pointing it out.

Zubair

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 18:22       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:22 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Zubair Lutfullah, jic23-KWPb1pKIrIJaa/9Udqfwiw,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Wed, Aug 28, 2013 at 04:18:35PM +0200, Sebastian Andrzej Siewior wrote:
> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> 
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >index a952538..ae2202b 100644
> >--- a/drivers/iio/adc/ti_am335x_adc.c
> >+++ b/drivers/iio/adc/ti_am335x_adc.c
> …
> 
> >+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
...
> >+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
> >+	if (trig == NULL)
> >+		return NULL;
> >+
...
> >+	ret = iio_trigger_register(trig);
> >+	if (ret)
> 
> shouldn't you free the trigger / undo iio_trigger_alloc() here?
> 
> >+		return NULL;
> >+
...
Possible. It's done in the probe section just 
to keep error handling bunched there.
> 
> > 
> > static const char * const chan_name_ain[] = {
> >@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> > 					  sizeof(struct tiadc_device));
> > 	if (indio_dev == NULL) {
> > 		dev_err(&pdev->dev, "failed to allocate iio device\n");
> >-		return -ENOMEM;
> >+		err = -ENOMEM;
> >+		goto err_ret;
> Why the jump instead of leave right away?
> 
> > 	}
Again. Error handling all in one place.

> > 
> >@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> > 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > 	u32 step_en;
> > 
> >+	free_irq(adc_dev->irq, indio_dev);
> > 	iio_device_unregister(indio_dev);
> >+	iio_buffer_unregister(indio_dev);
> > 	tiadc_channels_remove(indio_dev);
> 
> I think you need also to
> 
> 	iio_trigger_unregister(adc_dev->trig);
> 	iio_trigger_free(adc_dev->trig);
> 
> here.
Indeed.
Thanks for pointing it out.

Zubair

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 18:19       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:19 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Zubair Lutfullah, jic23, lee.jones, linux-iio, linux-input,
	linux-kernel, gregkh

On Wed, Aug 28, 2013 at 06:43:08PM +0200, Sebastian Andrzej Siewior wrote:
> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> 
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >index a952538..ae2202b 100644
> >--- a/drivers/iio/adc/ti_am335x_adc.c
> >+++ b/drivers/iio/adc/ti_am335x_adc.c
> >@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
> …
> >+err_free_device:
> >+	iio_device_free(indio_dev);
> 
> I am not sure about this one.

If I understand correctly, if devm_iio_device_alloc 
is successful earlier in the code and subsequent stuff fails. 

Then the code jumps to err_free_device and this is needed.

> 
> >+err_ret:
> > 	return err;
> > }
> > 
> >@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> > 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > 	u32 step_en;
> > 
> >+	free_irq(adc_dev->irq, indio_dev);
> > 	iio_device_unregister(indio_dev);
> >+	iio_buffer_unregister(indio_dev);
> > 	tiadc_channels_remove(indio_dev);
> > 
> > 	step_en = get_adc_step_mask(adc_dev);
> > 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
> >+	iio_device_free(indio_dev);
> 
> But this one is wrong. The will be removed via dev_res() and if you do
> it here as well then dev_res() will decrement the reference of an unused
> object.
I was unaware of this aspect.

*but*

iio_simple_dummy.c has it in its remove function.
And I just checked and found it in several drivers as well.

I'll leave this to the more experienced folks on the list..
> > 
> > 	return 0;
> > }
> 
> Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 18:19       ` Zubair Lutfullah :
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah : @ 2013-08-28 18:19 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: Zubair Lutfullah, jic23-KWPb1pKIrIJaa/9Udqfwiw,
	lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

On Wed, Aug 28, 2013 at 06:43:08PM +0200, Sebastian Andrzej Siewior wrote:
> * Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:
> 
> >diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
> >index a952538..ae2202b 100644
> >--- a/drivers/iio/adc/ti_am335x_adc.c
> >+++ b/drivers/iio/adc/ti_am335x_adc.c
> >@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
> …
> >+err_free_device:
> >+	iio_device_free(indio_dev);
> 
> I am not sure about this one.

If I understand correctly, if devm_iio_device_alloc 
is successful earlier in the code and subsequent stuff fails. 

Then the code jumps to err_free_device and this is needed.

> 
> >+err_ret:
> > 	return err;
> > }
> > 
> >@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> > 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> > 	u32 step_en;
> > 
> >+	free_irq(adc_dev->irq, indio_dev);
> > 	iio_device_unregister(indio_dev);
> >+	iio_buffer_unregister(indio_dev);
> > 	tiadc_channels_remove(indio_dev);
> > 
> > 	step_en = get_adc_step_mask(adc_dev);
> > 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
> >+	iio_device_free(indio_dev);
> 
> But this one is wrong. The will be removed via dev_res() and if you do
> it here as well then dev_res() will decrement the reference of an unused
> object.
I was unaware of this aspect.

*but*

iio_simple_dummy.c has it in its remove function.
And I just checked and found it in several drivers as well.

I'll leave this to the more experienced folks on the list..
> > 
> > 	return 0;
> > }
> 
> Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 16:43     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 16:43 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
>+err_free_device:
>+	iio_device_free(indio_dev);

I am not sure about this one.

>+err_ret:
> 	return err;
> }
> 
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> 	u32 step_en;
> 
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);
> 
> 	step_en = get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);

But this one is wrong. The will be removed via dev_res() and if you do
it here as well then dev_res() will decrement the reference of an unused
object.

> 
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 16:43     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 16:43 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23-KWPb1pKIrIJaa/9Udqfwiw, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
>+err_free_device:
>+	iio_device_free(indio_dev);

I am not sure about this one.

>+err_ret:
> 	return err;
> }
> 
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> 	u32 step_en;
> 
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);
> 
> 	step_en = get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);

But this one is wrong. The will be removed via dev_res() and if you do
it here as well then dev_res() will decrement the reference of an unused
object.

> 
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 16:43     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 16:43 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_a=
dc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
=E2=80=A6
>+err_free_device:
>+	iio_device_free(indio_dev);

I am not sure about this one.

>+err_ret:
> 	return err;
> }
>=20
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
> 	u32 step_en;
>=20
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);
>=20
> 	step_en =3D get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);

But this one is wrong. The will be removed via dev_res() and if you do
it here as well then dev_res() will decrement the reference of an unused
object.

>=20
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 14:18     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 14:18 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
>+{
>+	struct iio_trigger *trig;
>+	int ret;
>+
>+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
>+	if (trig == NULL)
>+		return NULL;
>+
>+	trig->dev.parent = indio_dev->dev.parent;
>+	trig->ops = &tiadc_trigger_ops;
>+	iio_trigger_set_drvdata(trig, indio_dev);
>+
>+	ret = iio_trigger_register(trig);
>+	if (ret)

shouldn't you free the trigger / undo iio_trigger_alloc() here?

>+		return NULL;
>+
>+	return trig;
> }

> 
> static const char * const chan_name_ain[] = {
>@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> 					  sizeof(struct tiadc_device));
> 	if (indio_dev == NULL) {
> 		dev_err(&pdev->dev, "failed to allocate iio device\n");
>-		return -ENOMEM;
>+		err = -ENOMEM;
>+		goto err_ret;
Why the jump instead of leave right away?

> 	}
> 	adc_dev = iio_priv(indio_dev);
> 
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> 	u32 step_en;
> 
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);

I think you need also to

	iio_trigger_unregister(adc_dev->trig);
	iio_trigger_free(adc_dev->trig);

here.
 
> 	step_en = get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);
> 
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 14:18     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 14:18 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23-KWPb1pKIrIJaa/9Udqfwiw, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
>+{
>+	struct iio_trigger *trig;
>+	int ret;
>+
>+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
>+	if (trig == NULL)
>+		return NULL;
>+
>+	trig->dev.parent = indio_dev->dev.parent;
>+	trig->ops = &tiadc_trigger_ops;
>+	iio_trigger_set_drvdata(trig, indio_dev);
>+
>+	ret = iio_trigger_register(trig);
>+	if (ret)

shouldn't you free the trigger / undo iio_trigger_alloc() here?

>+		return NULL;
>+
>+	return trig;
> }

> 
> static const char * const chan_name_ain[] = {
>@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> 					  sizeof(struct tiadc_device));
> 	if (indio_dev == NULL) {
> 		dev_err(&pdev->dev, "failed to allocate iio device\n");
>-		return -ENOMEM;
>+		err = -ENOMEM;
>+		goto err_ret;
Why the jump instead of leave right away?

> 	}
> 	adc_dev = iio_priv(indio_dev);
> 
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
> 	u32 step_en;
> 
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);

I think you need also to

	iio_trigger_unregister(adc_dev->trig);
	iio_trigger_free(adc_dev->trig);

here.
 
> 	step_en = get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);
> 
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 14:18     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 14:18 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_a=
dc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
=E2=80=A6

>+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *ind=
io_dev)
>+{
>+	struct iio_trigger *trig;
>+	int ret;
>+
>+	trig =3D iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
>+	if (trig =3D=3D NULL)
>+		return NULL;
>+
>+	trig->dev.parent =3D indio_dev->dev.parent;
>+	trig->ops =3D &tiadc_trigger_ops;
>+	iio_trigger_set_drvdata(trig, indio_dev);
>+
>+	ret =3D iio_trigger_register(trig);
>+	if (ret)

shouldn't you free the trigger / undo iio_trigger_alloc() here?

>+		return NULL;
>+
>+	return trig;
> }

>=20
> static const char * const chan_name_ain[] =3D {
>@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
> 					  sizeof(struct tiadc_device));
> 	if (indio_dev =3D=3D NULL) {
> 		dev_err(&pdev->dev, "failed to allocate iio device\n");
>-		return -ENOMEM;
>+		err =3D -ENOMEM;
>+		goto err_ret;
Why the jump instead of leave right away?

> 	}
> 	adc_dev =3D iio_priv(indio_dev);
>=20
>@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
> 	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
> 	u32 step_en;
>=20
>+	free_irq(adc_dev->irq, indio_dev);
> 	iio_device_unregister(indio_dev);
>+	iio_buffer_unregister(indio_dev);
> 	tiadc_channels_remove(indio_dev);

I think you need also to

	iio_trigger_unregister(adc_dev->trig);
	iio_trigger_free(adc_dev->trig);

here.
=20
> 	step_en =3D get_adc_step_mask(adc_dev);
> 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
>+	iio_device_free(indio_dev);
>=20
> 	return 0;
> }

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-25 22:45   ` Zubair Lutfullah
@ 2013-08-28 13:01     ` Sebastian Andrzej Siewior
  -1 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 13:01 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

I am mostly happy with it. There are just two things I pointed out.
Besides that, it looks good from my side.

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>@@ -85,7 +96,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
> 		adc_dev->channel_step[i] = steps;
> 		steps++;
> 	}
>+}
>+
>+static irqreturn_t tiadc_irq(int irq, void *private)
>+{
>+	struct iio_dev *indio_dev = private;
>+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>+	unsigned int status, config;
>+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
>+
>+	/*
>+	 * ADC and touchscreen share the IRQ line.
>+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
>+	 */
>+	if (status & IRQENB_FIFO1OVRRUN) {
>+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
>+		config = tiadc_readl(adc_dev, REG_CTRL);
>+		config &= ~(CNTRLREG_TSCSSENB);
>+		tiadc_writel(adc_dev, REG_CTRL, config);
>+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
>+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
>+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
>+	} else if (status & IRQENB_FIFO1THRES) {
>+		/* Trigger to push FIFO data to iio buffer */
>+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
>+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
>+	} else
>+		return IRQ_NONE;
>+
>+	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
>+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
>+	if (status == false)
>+		return IRQ_HANDLED;
>+	else
>+		return IRQ_NONE;

As I said in 1/2 of this series, you shouldn't do this. Both handlers of a
shared line are invoked once an interrupt is detected.

…

>+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>+{
>+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
>+	struct iio_buffer *buffer = indio_dev->buffer;
>+	unsigned int enb = 0, stepnum;
>+	u8 bit;
>+
>+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
>+	if (adc_dev->data == NULL)
>+		return -ENOMEM;
>+
>+	tiadc_step_config(indio_dev);
>+	for_each_set_bit(bit, buffer->scan_mask,
>+			adc_dev->channels) {
>+		struct iio_chan_spec const *chan = indio_dev->channels + bit;
>+		/*
>+		 * There are a total of 16 steps available
>+		 * that are shared between ADC and touchscreen.
>+		 * We start configuring from step 16 to 0 incase of
>+		 * ADC. Hence the relation between input channel
>+		 * and step for ADC would be as below.
>+		 */
>+		stepnum = chan->channel + 9;
>+		enb |= (1 << stepnum);

Hmm. This looks odd.
 
In tiadc_step_config() we do:
| steps = TOTAL_STEPS - adc_dev->channels;
|…
| for (i = 0; i < adc_dev->channels; i++) {
|         chan = adc_dev->channel_line[i];
|         tiadc_writel(adc_dev,
|                         REG_STEPCONFIG(steps),
|                         stepconfig
|                         |
|                         STEPCONFIG_INP(chan));
|         tiadc_writel(adc_dev,
|                         REG_STEPDELAY(steps),
|                         STEPCONFIG_OPENDLY);
|         adc_dev->channel_step[i]
|                 =
|                 steps;
|         steps++;
| }

That means if we have only one channel we enable the last step bit /
topmost that is bit 16. For the "default" four channels we get 0x1e000
as mask which means bit 13 to 16. 
If you do have only one channel with the number 4 you then
get_adc_step_mask() will compute the correct step mask but here enable
step 14 instead of step 16.

What about the following as replacement?

index 08681d3..3bfcf1b 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -65,6 +65,11 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
+{
+	return 1 << adc_dev->channel_step[chan];
+}
+
 static void tiadc_step_config(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
@@ -179,7 +187,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	struct iio_buffer *buffer = indio_dev->buffer;
-	unsigned int enb = 0, stepnum;
+	unsigned int enb = 0;
 	u8 bit;
 
 	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
@@ -187,19 +195,8 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 		return -ENOMEM;
 
 	tiadc_step_config(indio_dev);
-	for_each_set_bit(bit, buffer->scan_mask,
-			adc_dev->channels) {
-		struct iio_chan_spec const *chan = indio_dev->channels + bit;
-		/*
-		 * There are a total of 16 steps available
-		 * that are shared between ADC and touchscreen.
-		 * We start configuring from step 16 to 0 incase of
-		 * ADC. Hence the relation between input channel
-		 * and step for ADC would be as below.
-		 */
-		stepnum = chan->channel + 9;
-		enb |= (1 << stepnum);
-	}
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |= get_adc_step_bit(adc_dev, bit);
 
 	adc_dev->buffer_en_ch_steps = enb;
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);


Would it work? This is untested but it could work :)

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-28 13:01     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 67+ messages in thread
From: Sebastian Andrzej Siewior @ 2013-08-28 13:01 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, lee.jones, linux-iio, linux-input, linux-kernel, gregkh

* Zubair Lutfullah | 2013-08-25 23:45:24 [+0100]:

I am mostly happy with it. There are just two things I pointed out.
Besides that, it looks good from my side.

>diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_a=
dc.c
>index a952538..ae2202b 100644
>--- a/drivers/iio/adc/ti_am335x_adc.c
>+++ b/drivers/iio/adc/ti_am335x_adc.c
>@@ -85,7 +96,175 @@ static void tiadc_step_config(struct tiadc_device *adc=
_dev)
> 		adc_dev->channel_step[i] =3D steps;
> 		steps++;
> 	}
>+}
>+
>+static irqreturn_t tiadc_irq(int irq, void *private)
>+{
>+	struct iio_dev *indio_dev =3D private;
>+	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
>+	unsigned int status, config;
>+	status =3D tiadc_readl(adc_dev, REG_IRQSTATUS);
>+
>+	/*
>+	 * ADC and touchscreen share the IRQ line.
>+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
>+	 */
>+	if (status & IRQENB_FIFO1OVRRUN) {
>+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
>+		config =3D tiadc_readl(adc_dev, REG_CTRL);
>+		config &=3D ~(CNTRLREG_TSCSSENB);
>+		tiadc_writel(adc_dev, REG_CTRL, config);
>+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
>+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
>+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
>+	} else if (status & IRQENB_FIFO1THRES) {
>+		/* Trigger to push FIFO data to iio buffer */
>+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
>+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
>+	} else
>+		return IRQ_NONE;
>+
>+	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
>+	status =3D tiadc_readl(adc_dev, REG_IRQSTATUS);
>+	if (status =3D=3D false)
>+		return IRQ_HANDLED;
>+	else
>+		return IRQ_NONE;

As I said in 1/2 of this series, you shouldn't do this. Both handlers of a
shared line are invoked once an interrupt is detected.

=E2=80=A6

>+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
>+{
>+	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
>+	struct iio_buffer *buffer =3D indio_dev->buffer;
>+	unsigned int enb =3D 0, stepnum;
>+	u8 bit;
>+
>+	adc_dev->data =3D kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
>+	if (adc_dev->data =3D=3D NULL)
>+		return -ENOMEM;
>+
>+	tiadc_step_config(indio_dev);
>+	for_each_set_bit(bit, buffer->scan_mask,
>+			adc_dev->channels) {
>+		struct iio_chan_spec const *chan =3D indio_dev->channels + bit;
>+		/*
>+		 * There are a total of 16 steps available
>+		 * that are shared between ADC and touchscreen.
>+		 * We start configuring from step 16 to 0 incase of
>+		 * ADC. Hence the relation between input channel
>+		 * and step for ADC would be as below.
>+		 */
>+		stepnum =3D chan->channel + 9;
>+		enb |=3D (1 << stepnum);

Hmm. This looks odd.
=20
In tiadc_step_config() we do:
| steps =3D TOTAL_STEPS - adc_dev->channels;
|=E2=80=A6
| for (i =3D 0; i < adc_dev->channels; i++) {
|         chan =3D adc_dev->channel_line[i];
|         tiadc_writel(adc_dev,
|                         REG_STEPCONFIG(steps),
|                         stepconfig
|                         |
|                         STEPCONFIG_INP(chan));
|         tiadc_writel(adc_dev,
|                         REG_STEPDELAY(steps),
|                         STEPCONFIG_OPENDLY);
|         adc_dev->channel_step[i]
|                 =3D
|                 steps;
|         steps++;
| }

That means if we have only one channel we enable the last step bit /
topmost that is bit 16. For the "default" four channels we get 0x1e000
as mask which means bit 13 to 16.=20
If you do have only one channel with the number 4 you then
get_adc_step_mask() will compute the correct step mask but here enable
step 14 instead of step 16.

What about the following as replacement?

index 08681d3..3bfcf1b 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -65,6 +65,11 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_de=
v)
 	return step_en;
 }
=20
+static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
+{
+	return 1 << adc_dev->channel_step[chan];
+}
+
 static void tiadc_step_config(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
@@ -179,7 +187,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indi=
o_dev)
 {
 	struct tiadc_device *adc_dev =3D iio_priv(indio_dev);
 	struct iio_buffer *buffer =3D indio_dev->buffer;
-	unsigned int enb =3D 0, stepnum;
+	unsigned int enb =3D 0;
 	u8 bit;
=20
 	adc_dev->data =3D kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
@@ -187,19 +195,8 @@ static int tiadc_buffer_postenable(struct iio_dev *ind=
io_dev)
 		return -ENOMEM;
=20
 	tiadc_step_config(indio_dev);
-	for_each_set_bit(bit, buffer->scan_mask,
-			adc_dev->channels) {
-		struct iio_chan_spec const *chan =3D indio_dev->channels + bit;
-		/*
-		 * There are a total of 16 steps available
-		 * that are shared between ADC and touchscreen.
-		 * We start configuring from step 16 to 0 incase of
-		 * ADC. Hence the relation between input channel
-		 * and step for ADC would be as below.
-		 */
-		stepnum =3D chan->channel + 9;
-		enb |=3D (1 << stepnum);
-	}
+	for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
+		enb |=3D get_adc_step_bit(adc_dev, bit);
=20
 	adc_dev->buffer_en_ch_steps =3D enb;
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);


Would it work? This is untested but it could work :)

Sebastian

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
  2013-08-25 22:45   ` Zubair Lutfullah
@ 2013-08-27  8:42     ` Lee Jones
  -1 siblings, 0 replies; 67+ messages in thread
From: Lee Jones @ 2013-08-27  8:42 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, bigeasy, linux-iio, linux-input, linux-kernel, gregkh

On Sun, 25 Aug 2013, Zubair Lutfullah wrote:

> Previously the driver had only one-shot reading functionality.
> This patch adds triggered buffer support to the driver.
> 
> Continuous sampling starts when buffer is enabled.
> And samples are pushed to userpace by the trigger which
> triggers automatically at every hardware interrupt
> of FIFO1 filling with samples upto threshold value.
> 
> Userspace responsibility to stop sampling by writing zero
> in the buffer enable file.
> 
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
> 
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added trigger support.
> 
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Russ Dill <Russ.Dill@ti.com>
> ---
>  drivers/iio/adc/ti_am335x_adc.c      |  254 +++++++++++++++++++++++++++++++---
>  include/linux/mfd/ti_am335x_tscadc.h |   13 ++
>  2 files changed, 246 insertions(+), 21 deletions(-)

MFD stuff looks okay to me.

Acked-by: Lee Jones <lee.jones@linaro.org>

<snip>

> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index db1791b..a372ebf 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -46,17 +46,25 @@
>  /* Step Enable */
>  #define STEPENB_MASK		(0x1FFFF << 0)
>  #define STEPENB(val)		((val) << 0)
> +#define ENB(val)			(1 << (val))
> +#define STPENB_STEPENB		STEPENB(0x1FFFF)
> +#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
>  
>  /* IRQ enable */
>  #define IRQENB_HW_PEN		BIT(0)
>  #define IRQENB_FIFO0THRES	BIT(2)
> +#define IRQENB_FIFO0OVRRUN	BIT(3)
> +#define IRQENB_FIFO0UNDRFLW	BIT(4)
>  #define IRQENB_FIFO1THRES	BIT(5)
> +#define IRQENB_FIFO1OVRRUN	BIT(6)
> +#define IRQENB_FIFO1UNDRFLW	BIT(7)
>  #define IRQENB_PENUP		BIT(9)
>  
>  /* Step Configuration */
>  #define STEPCONFIG_MODE_MASK	(3 << 0)
>  #define STEPCONFIG_MODE(val)	((val) << 0)
>  #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
> +#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
>  #define STEPCONFIG_AVG_MASK	(7 << 2)
>  #define STEPCONFIG_AVG(val)	((val) << 2)
>  #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
> @@ -124,6 +132,7 @@
>  #define	MAX_CLK_DIV		7
>  #define TOTAL_STEPS		16
>  #define TOTAL_CHANNELS		8
> +#define FIFO1_THRESHOLD		19
>  
>  /*
>  * ADC runs at 3MHz, and it takes
> @@ -153,6 +162,10 @@ struct ti_tscadc_dev {
>  
>  	/* adc device */
>  	struct adc_device *adc;
> +
> +	/* Context save */
> +	unsigned int irqstat;
> +	unsigned int ctrl;
>  };
>  
>  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-27  8:42     ` Lee Jones
  0 siblings, 0 replies; 67+ messages in thread
From: Lee Jones @ 2013-08-27  8:42 UTC (permalink / raw)
  To: Zubair Lutfullah
  Cc: jic23, bigeasy, linux-iio, linux-input, linux-kernel, gregkh

On Sun, 25 Aug 2013, Zubair Lutfullah wrote:

> Previously the driver had only one-shot reading functionality.
> This patch adds triggered buffer support to the driver.
> 
> Continuous sampling starts when buffer is enabled.
> And samples are pushed to userpace by the trigger which
> triggers automatically at every hardware interrupt
> of FIFO1 filling with samples upto threshold value.
> 
> Userspace responsibility to stop sampling by writing zero
> in the buffer enable file.
> 
> Patil Rachna (TI) laid the ground work for ADC HW register access.
> Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.
> 
> I fixed channel scanning so multiple ADC channels can be read
> simultaneously and pushed to userspace.
> Restructured the driver to fit IIO ABI.
> And added trigger support.
> 
> Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Russ Dill <Russ.Dill@ti.com>
> ---
>  drivers/iio/adc/ti_am335x_adc.c      |  254 +++++++++++++++++++++++++++++++---
>  include/linux/mfd/ti_am335x_tscadc.h |   13 ++
>  2 files changed, 246 insertions(+), 21 deletions(-)

MFD stuff looks okay to me.

Acked-by: Lee Jones <lee.jones@linaro.org>

<snip>

> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index db1791b..a372ebf 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -46,17 +46,25 @@
>  /* Step Enable */
>  #define STEPENB_MASK		(0x1FFFF << 0)
>  #define STEPENB(val)		((val) << 0)
> +#define ENB(val)			(1 << (val))
> +#define STPENB_STEPENB		STEPENB(0x1FFFF)
> +#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
>  
>  /* IRQ enable */
>  #define IRQENB_HW_PEN		BIT(0)
>  #define IRQENB_FIFO0THRES	BIT(2)
> +#define IRQENB_FIFO0OVRRUN	BIT(3)
> +#define IRQENB_FIFO0UNDRFLW	BIT(4)
>  #define IRQENB_FIFO1THRES	BIT(5)
> +#define IRQENB_FIFO1OVRRUN	BIT(6)
> +#define IRQENB_FIFO1UNDRFLW	BIT(7)
>  #define IRQENB_PENUP		BIT(9)
>  
>  /* Step Configuration */
>  #define STEPCONFIG_MODE_MASK	(3 << 0)
>  #define STEPCONFIG_MODE(val)	((val) << 0)
>  #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
> +#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
>  #define STEPCONFIG_AVG_MASK	(7 << 2)
>  #define STEPCONFIG_AVG(val)	((val) << 2)
>  #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
> @@ -124,6 +132,7 @@
>  #define	MAX_CLK_DIV		7
>  #define TOTAL_STEPS		16
>  #define TOTAL_CHANNELS		8
> +#define FIFO1_THRESHOLD		19
>  
>  /*
>  * ADC runs at 3MHz, and it takes
> @@ -153,6 +162,10 @@ struct ti_tscadc_dev {
>  
>  	/* adc device */
>  	struct adc_device *adc;
> +
> +	/* Context save */
> +	unsigned int irqstat;
> +	unsigned int ctrl;
>  };
>  
>  static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-input" 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] 67+ messages in thread

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-25 22:45   ` Zubair Lutfullah
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-08-25 22:45 UTC (permalink / raw)
  To: jic23, lee.jones; +Cc: bigeasy, linux-iio, linux-input, linux-kernel, gregkh

Previously the driver had only one-shot reading functionality.
This patch adds triggered buffer support to the driver.

Continuous sampling starts when buffer is enabled.
And samples are pushed to userpace by the trigger which
triggers automatically at every hardware interrupt
of FIFO1 filling with samples upto threshold value.

Userspace responsibility to stop sampling by writing zero
in the buffer enable file.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added trigger support.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah@gmail.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Russ Dill <Russ.Dill@ti.com>
---
 drivers/iio/adc/ti_am335x_adc.c      |  254 +++++++++++++++++++++++++++++++---
 include/linux/mfd/ti_am335x_tscadc.h |   13 ++
 2 files changed, 246 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..ae2202b 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,20 @@
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int irq;
+	int buffer_en_ch_steps;
+	struct iio_trigger *trig;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,10 +64,11 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static void tiadc_step_config(struct iio_dev *indio_dev)
 {
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
-	int i, steps;
+	int i, steps, chan;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -72,11 +81,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
-		int chan;
-
 		chan = adc_dev->channel_line[i];
 		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
 				stepconfig | STEPCONFIG_INP(chan));
@@ -85,7 +96,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Trigger to push FIFO data to iio buffer */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
+	} else
+		return IRQ_NONE;
+
+	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+	if (status == false)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_trigger_h(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
 
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO before starting sampling */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0, stepnum;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask,
+			adc_dev->channels) {
+		struct iio_chan_spec const *chan = indio_dev->channels + bit;
+		/*
+		 * There are a total of 16 steps available
+		 * that are shared between ADC and touchscreen.
+		 * We start configuring from step 16 to 0 incase of
+		 * ADC. Hence the relation between input channel
+		 * and step for ADC would be as below.
+		 */
+		stepnum = chan->channel + 9;
+		enb |= (1 << stepnum);
+	}
+
+	adc_dev->buffer_en_ch_steps = enb;
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of any leftover data */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops tiadc_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
+{
+	struct iio_trigger *trig;
+	int ret;
+
+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
+	if (trig == NULL)
+		return NULL;
+
+	trig->dev.parent = indio_dev->dev.parent;
+	trig->ops = &tiadc_trigger_ops;
+	iio_trigger_set_drvdata(trig, indio_dev);
+
+	ret = iio_trigger_register(trig);
+	if (ret)
+		return NULL;
+
+	return trig;
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +299,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -142,11 +322,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
-	u32 step = UINT_MAX;
 	bool found = false;
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -168,15 +351,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	 * Hence we need to flush out this data.
 	 */
 
-	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
-		if (chan->channel == adc_dev->channel_line[i]) {
-			step = adc_dev->channel_step[i];
-			break;
-		}
-	}
-	if (WARN_ON_ONCE(step == UINT_MAX))
-		return -EINVAL;
-
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
 					  sizeof(struct tiadc_device));
 	if (indio_dev == NULL) {
 		dev_err(&pdev->dev, "failed to allocate iio device\n");
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_ret;
 	}
 	adc_dev = iio_priv(indio_dev);
 
@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
 		channels++;
 	}
 	adc_dev->channels = channels;
+	adc_dev->irq = adc_dev->mfd_tscadc->irq;
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
-		return err;
+		goto err_free_device;
+
+	adc_dev->trig = tiadc_iio_allocate_trigger(indio_dev);
+	if (adc_dev->trig == NULL) {
+		err = -ENOMEM;
+		goto err_free_channels;
+	}
+
+	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
+		indio_dev->name, indio_dev);
+	if (err)
+		goto err_free_trigger;
+
+	err = iio_triggered_buffer_setup(indio_dev, NULL,
+			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
+	if (err)
+		goto err_free_irq;
 
 	err = iio_device_register(indio_dev);
 	if (err)
-		goto err_free_channels;
+		goto err_buffer_unregister;
 
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	iio_buffer_unregister(indio_dev);
+err_free_irq:
+	free_irq(adc_dev->irq, indio_dev);
+err_free_trigger:
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
+err_free_device:
+	iio_device_free(indio_dev);
+err_ret:
 	return err;
 }
 
@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	u32 step_en;
 
+	free_irq(adc_dev->irq, indio_dev);
 	iio_device_unregister(indio_dev);
+	iio_buffer_unregister(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
+	iio_device_free(indio_dev);
 
 	return 0;
 }
@@ -298,10 +504,16 @@ static int tiadc_resume(struct device *dev)
 
 	/* Make sure ADC is powered up */
 	restore = tiadc_readl(adc_dev, REG_CTRL);
-	restore &= ~(CNTRLREG_POWERDOWN);
+	restore &= ~(CNTRLREG_TSCSSENB);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+	tiadc_step_config(indio_dev);
+
+	/* Make sure ADC is powered up */
+	restore &= ~(CNTRLREG_POWERDOWN);
+	restore |= CNTRLREG_TSCSSENB;
+	tiadc_writel(adc_dev, REG_CTRL, restore);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..a372ebf 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,17 +46,25 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
 #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
@@ -153,6 +162,10 @@ struct ti_tscadc_dev {
 
 	/* adc device */
 	struct adc_device *adc;
+
+	/* Context save */
+	unsigned int irqstat;
+	unsigned int ctrl;
 };
 
 static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
-- 
1.7.9.5


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

* [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support
@ 2013-08-25 22:45   ` Zubair Lutfullah
  0 siblings, 0 replies; 67+ messages in thread
From: Zubair Lutfullah @ 2013-08-25 22:45 UTC (permalink / raw)
  To: jic23-KWPb1pKIrIJaa/9Udqfwiw, lee.jones-QSEj5FYQhm4dnm+yROfE0A
  Cc: bigeasy-hfZtesqFncYOwBW4kG4KsQ, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r

Previously the driver had only one-shot reading functionality.
This patch adds triggered buffer support to the driver.

Continuous sampling starts when buffer is enabled.
And samples are pushed to userpace by the trigger which
triggers automatically at every hardware interrupt
of FIFO1 filling with samples upto threshold value.

Userspace responsibility to stop sampling by writing zero
in the buffer enable file.

Patil Rachna (TI) laid the ground work for ADC HW register access.
Russ Dill (TI) fixed bugs in the driver relevant to FIFOs and IRQs.

I fixed channel scanning so multiple ADC channels can be read
simultaneously and pushed to userspace.
Restructured the driver to fit IIO ABI.
And added trigger support.

Signed-off-by: Zubair Lutfullah <zubair.lutfullah-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>
Signed-off-by: Russ Dill <Russ.Dill-l0cyMroinI0@public.gmane.org>
---
 drivers/iio/adc/ti_am335x_adc.c      |  254 +++++++++++++++++++++++++++++++---
 include/linux/mfd/ti_am335x_tscadc.h |   13 ++
 2 files changed, 246 insertions(+), 21 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index a952538..ae2202b 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,20 @@
 #include <linux/iio/driver.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
 	int channels;
 	u8 channel_line[8];
 	u8 channel_step[8];
+	int irq;
+	int buffer_en_ch_steps;
+	struct iio_trigger *trig;
+	u32 *data;
 };
 
 static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,10 +64,11 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
 	return step_en;
 }
 
-static void tiadc_step_config(struct tiadc_device *adc_dev)
+static void tiadc_step_config(struct iio_dev *indio_dev)
 {
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	unsigned int stepconfig;
-	int i, steps;
+	int i, steps, chan;
 
 	/*
 	 * There are 16 configurable steps and 8 analog input
@@ -72,11 +81,13 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 	 */
 
 	steps = TOTAL_STEPS - adc_dev->channels;
-	stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
+	if (iio_buffer_enabled(indio_dev))
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
+					| STEPCONFIG_MODE_SWCNT;
+	else
+		stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
 
 	for (i = 0; i < adc_dev->channels; i++) {
-		int chan;
-
 		chan = adc_dev->channel_line[i];
 		tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
 				stepconfig | STEPCONFIG_INP(chan));
@@ -85,7 +96,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
 		adc_dev->channel_step[i] = steps;
 		steps++;
 	}
+}
+
+static irqreturn_t tiadc_irq(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	unsigned int status, config;
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+
+	/*
+	 * ADC and touchscreen share the IRQ line.
+	 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
+	 */
+	if (status & IRQENB_FIFO1OVRRUN) {
+		/* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
+		config = tiadc_readl(adc_dev, REG_CTRL);
+		config &= ~(CNTRLREG_TSCSSENB);
+		tiadc_writel(adc_dev, REG_CTRL, config);
+		tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
+				| IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
+		tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
+	} else if (status & IRQENB_FIFO1THRES) {
+		/* Trigger to push FIFO data to iio buffer */
+		tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
+		iio_trigger_poll(indio_dev->trig, iio_get_time_ns());
+	} else
+		return IRQ_NONE;
+
+	/* If any IRQ flags left, return none. So TSC can handle its IRQs */
+	status = tiadc_readl(adc_dev, REG_IRQSTATUS);
+	if (status == false)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+static irqreturn_t tiadc_trigger_h(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, k, fifo1count, read;
+	u32 *data = adc_dev->data;
+
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (k = 0; k < fifo1count; k = k + i) {
+		for (i = 0; i < (indio_dev->scan_bytes)/4; i++) {
+			read = tiadc_readl(adc_dev, REG_FIFO1);
+			data[i] = read & FIFOREAD_DATA_MASK;
+		}
+		iio_push_to_buffers(indio_dev, (u8 *) data);
+	}
 
+	tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
+	tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int i, fifo1count, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN |
+				IRQENB_FIFO1UNDRFLW));
+
+	/* Flush FIFO before starting sampling */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_sw_buffer_preenable(indio_dev);
+}
+
+static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct iio_buffer *buffer = indio_dev->buffer;
+	unsigned int enb = 0, stepnum;
+	u8 bit;
+
+	adc_dev->data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	if (adc_dev->data == NULL)
+		return -ENOMEM;
+
+	tiadc_step_config(indio_dev);
+	for_each_set_bit(bit, buffer->scan_mask,
+			adc_dev->channels) {
+		struct iio_chan_spec const *chan = indio_dev->channels + bit;
+		/*
+		 * There are a total of 16 steps available
+		 * that are shared between ADC and touchscreen.
+		 * We start configuring from step 16 to 0 incase of
+		 * ADC. Hence the relation between input channel
+		 * and step for ADC would be as below.
+		 */
+		stepnum = chan->channel + 9;
+		enb |= (1 << stepnum);
+	}
+
+	adc_dev->buffer_en_ch_steps = enb;
+	am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
+	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
+				| IRQENB_FIFO1OVRRUN);
+
+	return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	int fifo1count, i, read;
+
+	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
+				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
+	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+
+	/* Flush FIFO of any leftover data */
+	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+	for (i = 0; i < fifo1count; i++)
+		read = tiadc_readl(adc_dev, REG_FIFO1);
+
+	return iio_triggered_buffer_predisable(indio_dev);
+}
+
+static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+
+	tiadc_step_config(indio_dev);
+	kfree(adc_dev->data);
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
+	.preenable = &tiadc_buffer_preenable,
+	.postenable = &tiadc_buffer_postenable,
+	.predisable = &tiadc_buffer_predisable,
+	.postdisable = &tiadc_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops tiadc_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static struct iio_trigger *tiadc_iio_allocate_trigger(struct iio_dev *indio_dev)
+{
+	struct iio_trigger *trig;
+	int ret;
+
+	trig = iio_trigger_alloc("%s-dev%d", indio_dev->name, indio_dev->id);
+	if (trig == NULL)
+		return NULL;
+
+	trig->dev.parent = indio_dev->dev.parent;
+	trig->ops = &tiadc_trigger_ops;
+	iio_trigger_set_drvdata(trig, indio_dev);
+
+	ret = iio_trigger_register(trig);
+	if (ret)
+		return NULL;
+
+	return trig;
 }
 
 static const char * const chan_name_ain[] = {
@@ -120,6 +299,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
 		chan->channel = adc_dev->channel_line[i];
 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
 		chan->datasheet_name = chan_name_ain[chan->channel];
+		chan->scan_index = i;
 		chan->scan_type.sign = 'u';
 		chan->scan_type.realbits = 12;
 		chan->scan_type.storagebits = 32;
@@ -142,11 +322,14 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	int i, map_val;
 	unsigned int fifo1count, read, stepid;
-	u32 step = UINT_MAX;
 	bool found = false;
 	u32 step_en;
 	unsigned long timeout = jiffies + usecs_to_jiffies
 				(IDLE_TIMEOUT * adc_dev->channels);
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
 
@@ -168,15 +351,6 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
 	 * Hence we need to flush out this data.
 	 */
 
-	for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
-		if (chan->channel == adc_dev->channel_line[i]) {
-			step = adc_dev->channel_step[i];
-			break;
-		}
-	}
-	if (WARN_ON_ONCE(step == UINT_MAX))
-		return -EINVAL;
-
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
 	for (i = 0; i < fifo1count; i++) {
 		read = tiadc_readl(adc_dev, REG_FIFO1);
@@ -220,7 +394,8 @@ static int tiadc_probe(struct platform_device *pdev)
 					  sizeof(struct tiadc_device));
 	if (indio_dev == NULL) {
 		dev_err(&pdev->dev, "failed to allocate iio device\n");
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_ret;
 	}
 	adc_dev = iio_priv(indio_dev);
 
@@ -231,28 +406,56 @@ static int tiadc_probe(struct platform_device *pdev)
 		channels++;
 	}
 	adc_dev->channels = channels;
+	adc_dev->irq = adc_dev->mfd_tscadc->irq;
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &tiadc_info;
 
-	tiadc_step_config(adc_dev);
+	tiadc_step_config(indio_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
 
 	err = tiadc_channel_init(indio_dev, adc_dev->channels);
 	if (err < 0)
-		return err;
+		goto err_free_device;
+
+	adc_dev->trig = tiadc_iio_allocate_trigger(indio_dev);
+	if (adc_dev->trig == NULL) {
+		err = -ENOMEM;
+		goto err_free_channels;
+	}
+
+	err = request_irq(adc_dev->irq, tiadc_irq, IRQF_SHARED,
+		indio_dev->name, indio_dev);
+	if (err)
+		goto err_free_trigger;
+
+	err = iio_triggered_buffer_setup(indio_dev, NULL,
+			&tiadc_trigger_h, &tiadc_buffer_setup_ops);
+	if (err)
+		goto err_free_irq;
 
 	err = iio_device_register(indio_dev);
 	if (err)
-		goto err_free_channels;
+		goto err_buffer_unregister;
 
 	platform_set_drvdata(pdev, indio_dev);
 
 	return 0;
 
+err_buffer_unregister:
+	iio_buffer_unregister(indio_dev);
+err_free_irq:
+	free_irq(adc_dev->irq, indio_dev);
+err_free_trigger:
+	iio_trigger_unregister(adc_dev->trig);
+	iio_trigger_free(adc_dev->trig);
 err_free_channels:
 	tiadc_channels_remove(indio_dev);
+err_free_device:
+	iio_device_free(indio_dev);
+err_ret:
 	return err;
 }
 
@@ -262,11 +465,14 @@ static int tiadc_remove(struct platform_device *pdev)
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
 	u32 step_en;
 
+	free_irq(adc_dev->irq, indio_dev);
 	iio_device_unregister(indio_dev);
+	iio_buffer_unregister(indio_dev);
 	tiadc_channels_remove(indio_dev);
 
 	step_en = get_adc_step_mask(adc_dev);
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, step_en);
+	iio_device_free(indio_dev);
 
 	return 0;
 }
@@ -298,10 +504,16 @@ static int tiadc_resume(struct device *dev)
 
 	/* Make sure ADC is powered up */
 	restore = tiadc_readl(adc_dev, REG_CTRL);
-	restore &= ~(CNTRLREG_POWERDOWN);
+	restore &= ~(CNTRLREG_TSCSSENB);
 	tiadc_writel(adc_dev, REG_CTRL, restore);
 
-	tiadc_step_config(adc_dev);
+	tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
+	tiadc_step_config(indio_dev);
+
+	/* Make sure ADC is powered up */
+	restore &= ~(CNTRLREG_POWERDOWN);
+	restore |= CNTRLREG_TSCSSENB;
+	tiadc_writel(adc_dev, REG_CTRL, restore);
 
 	return 0;
 }
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index db1791b..a372ebf 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -46,17 +46,25 @@
 /* Step Enable */
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
+#define ENB(val)			(1 << (val))
+#define STPENB_STEPENB		STEPENB(0x1FFFF)
+#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
 #define IRQENB_FIFO0THRES	BIT(2)
+#define IRQENB_FIFO0OVRRUN	BIT(3)
+#define IRQENB_FIFO0UNDRFLW	BIT(4)
 #define IRQENB_FIFO1THRES	BIT(5)
+#define IRQENB_FIFO1OVRRUN	BIT(6)
+#define IRQENB_FIFO1UNDRFLW	BIT(7)
 #define IRQENB_PENUP		BIT(9)
 
 /* Step Configuration */
 #define STEPCONFIG_MODE_MASK	(3 << 0)
 #define STEPCONFIG_MODE(val)	((val) << 0)
 #define STEPCONFIG_MODE_HWSYNC	STEPCONFIG_MODE(2)
+#define STEPCONFIG_MODE_SWCNT	STEPCONFIG_MODE(1)
 #define STEPCONFIG_AVG_MASK	(7 << 2)
 #define STEPCONFIG_AVG(val)	((val) << 2)
 #define STEPCONFIG_AVG_16	STEPCONFIG_AVG(4)
@@ -124,6 +132,7 @@
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
 #define TOTAL_CHANNELS		8
+#define FIFO1_THRESHOLD		19
 
 /*
 * ADC runs at 3MHz, and it takes
@@ -153,6 +162,10 @@ struct ti_tscadc_dev {
 
 	/* adc device */
 	struct adc_device *adc;
+
+	/* Context save */
+	unsigned int irqstat;
+	unsigned int ctrl;
 };
 
 static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
-- 
1.7.9.5

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

end of thread, other threads:[~2013-09-19  5:55 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-01 11:17 [PATCH V8 0/2] iio: input: ti_am335x_tscadc: Add continuous sampling support to adc Zubair Lutfullah
2013-09-01 11:17 ` [PATCH 1/2] input: ti_am335x_tsc: Enable shared IRQ for TSC Zubair Lutfullah
2013-09-01 11:17   ` Zubair Lutfullah
2013-09-08 11:29   ` Jonathan Cameron
2013-09-08 11:29     ` Jonathan Cameron
2013-09-09 16:12     ` Dmitry Torokhov
2013-09-09 16:12       ` Dmitry Torokhov
2013-09-11 16:08       ` Zubair Lutfullah :
2013-09-11 16:08         ` Zubair Lutfullah :
2013-09-01 11:17 ` [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support Zubair Lutfullah
2013-09-08 13:42   ` Jonathan Cameron
2013-09-08 13:42     ` Jonathan Cameron
2013-09-11 16:02     ` Zubair Lutfullah :
2013-09-11 16:02       ` Zubair Lutfullah :
  -- strict thread matches above, loose matches on Subject: below --
2013-09-18 11:23 [PATCH V10 0/2] iio: input: " Zubair Lutfullah
2013-09-18 11:23 ` [PATCH 2/2] iio: " Zubair Lutfullah
2013-09-18 13:58   ` Jonathan Cameron
2013-09-18 13:58     ` Jonathan Cameron
2013-09-19  5:24     ` Zubair Lutfullah :
2013-09-19  5:24       ` Zubair Lutfullah :
2013-09-19  5:41       ` Jonathan Cameron
2013-09-19  5:41         ` Jonathan Cameron
2013-09-19  5:41         ` Jonathan Cameron
2013-09-19  5:55         ` Zubair Lutfullah :
2013-09-19  5:55           ` Zubair Lutfullah :
2013-09-17  4:44 [PATCH V9 0/2] iio: input: " Zubair Lutfullah
2013-09-17  4:44 ` [PATCH 2/2] iio: " Zubair Lutfullah
2013-09-18  4:27   ` Dmitry Torokhov
2013-09-18  4:27     ` Dmitry Torokhov
2013-09-18  6:54     ` Zubair Lutfullah :
2013-09-18  6:54       ` Zubair Lutfullah :
2013-09-18  9:39       ` Jonathan Cameron
2013-09-18  9:39         ` Jonathan Cameron
2013-09-18 11:25         ` Zubair Lutfullah :
2013-09-18 11:25           ` Zubair Lutfullah :
2013-09-18 14:15         ` Dmitry Torokhov
2013-09-18 14:15           ` Dmitry Torokhov
2013-09-18 16:12           ` Jonathan Cameron
2013-09-18 16:12             ` Jonathan Cameron
2013-09-18 16:24             ` Dmitry Torokhov
2013-09-18 17:05               ` Jonathan Cameron
2013-09-18 17:05                 ` Jonathan Cameron
2013-09-19  5:16                 ` Zubair Lutfullah :
2013-09-19  5:33                   ` Jonathan Cameron
2013-09-19  5:33                     ` Jonathan Cameron
2013-09-01 11:07 [PATCH V7 0/2] iio: input: ti_am335x_tscadc: Add continuous sampling support to adc Zubair Lutfullah
2013-09-01 11:07 ` [PATCH 2/2] iio: ti_am335x_adc: Add continuous sampling support Zubair Lutfullah
2013-08-25 22:45 [PATCH V6 0/2] iio: input: " Zubair Lutfullah
2013-08-25 22:45 ` [PATCH 2/2] iio: " Zubair Lutfullah
2013-08-25 22:45   ` Zubair Lutfullah
2013-08-27  8:42   ` Lee Jones
2013-08-27  8:42     ` Lee Jones
2013-08-28 13:01   ` Sebastian Andrzej Siewior
2013-08-28 13:01     ` Sebastian Andrzej Siewior
2013-08-28 18:43     ` Zubair Lutfullah :
2013-08-29  7:49       ` Sebastian Andrzej Siewior
2013-08-28 14:18   ` Sebastian Andrzej Siewior
2013-08-28 14:18     ` Sebastian Andrzej Siewior
2013-08-28 14:18     ` Sebastian Andrzej Siewior
2013-08-28 18:22     ` Zubair Lutfullah :
2013-08-28 18:22       ` Zubair Lutfullah :
2013-08-28 18:38       ` Sebastian Andrzej Siewior
2013-08-28 18:55         ` Zubair Lutfullah :
2013-08-28 16:43   ` Sebastian Andrzej Siewior
2013-08-28 16:43     ` Sebastian Andrzej Siewior
2013-08-28 16:43     ` Sebastian Andrzej Siewior
2013-08-28 18:19     ` Zubair Lutfullah :
2013-08-28 18:19       ` Zubair Lutfullah :
2013-08-28 18:35       ` Sebastian Andrzej Siewior
2013-08-28 18:59         ` Zubair Lutfullah :
2013-08-29  7:56           ` Sebastian Andrzej Siewior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.