aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/adc
diff options
context:
space:
mode:
authorZubair Lutfullah <zubair.lutfullah@gmail.com>2013-09-19 02:24:00 -0400
committerJonathan Cameron <jic23@kernel.org>2013-09-21 14:23:47 -0400
commitca9a563805f7ae821e3303b1bdbc65d3a3c783ff (patch)
tree7453f8ace4421b3d23b53c5bf8c222e0a5ffbbaf /drivers/iio/adc
parent0f6fc7d56fe56aad5410fdaa7cebbb918580a33c (diff)
iio: ti_am335x_adc: Add continuous sampling support
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> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/adc')
-rw-r--r--drivers/iio/adc/Kconfig1
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c213
2 files changed, 209 insertions, 5 deletions
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 0cf5c611b4c6..8b885188b839 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -177,6 +177,7 @@ config TI_ADC081C
177config TI_AM335X_ADC 177config TI_AM335X_ADC
178 tristate "TI's AM335X ADC driver" 178 tristate "TI's AM335X ADC driver"
179 depends on MFD_TI_AM335X_TSCADC 179 depends on MFD_TI_AM335X_TSCADC
180 select IIO_KFIFO_BUF
180 help 181 help
181 Say yes here to build support for Texas Instruments ADC 182 Say yes here to build support for Texas Instruments ADC
182 driver which is also a MFD client. 183 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 ebe93eba3ec8..5287bffd8a75 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -28,12 +28,20 @@
28#include <linux/iio/driver.h> 28#include <linux/iio/driver.h>
29 29
30#include <linux/mfd/ti_am335x_tscadc.h> 30#include <linux/mfd/ti_am335x_tscadc.h>
31#include <linux/iio/buffer.h>
32#include <linux/iio/kfifo_buf.h>
33#include <linux/iio/trigger.h>
34#include <linux/iio/trigger_consumer.h>
35#include <linux/iio/triggered_buffer.h>
31 36
32struct tiadc_device { 37struct tiadc_device {
33 struct ti_tscadc_dev *mfd_tscadc; 38 struct ti_tscadc_dev *mfd_tscadc;
34 int channels; 39 int channels;
35 u8 channel_line[8]; 40 u8 channel_line[8];
36 u8 channel_step[8]; 41 u8 channel_step[8];
42 int buffer_en_ch_steps;
43 struct iio_trigger *trig;
44 u16 data[8];
37}; 45};
38 46
39static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) 47static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
@@ -56,8 +64,14 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
56 return step_en; 64 return step_en;
57} 65}
58 66
59static void tiadc_step_config(struct tiadc_device *adc_dev) 67static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
60{ 68{
69 return 1 << adc_dev->channel_step[chan];
70}
71
72static void tiadc_step_config(struct iio_dev *indio_dev)
73{
74 struct tiadc_device *adc_dev = iio_priv(indio_dev);
61 unsigned int stepconfig; 75 unsigned int stepconfig;
62 int i, steps; 76 int i, steps;
63 77
@@ -72,7 +86,11 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
72 */ 86 */
73 87
74 steps = TOTAL_STEPS - adc_dev->channels; 88 steps = TOTAL_STEPS - adc_dev->channels;
75 stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; 89 if (iio_buffer_enabled(indio_dev))
90 stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
91 | STEPCONFIG_MODE_SWCNT;
92 else
93 stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
76 94
77 for (i = 0; i < adc_dev->channels; i++) { 95 for (i = 0; i < adc_dev->channels; i++) {
78 int chan; 96 int chan;
@@ -85,9 +103,175 @@ static void tiadc_step_config(struct tiadc_device *adc_dev)
85 adc_dev->channel_step[i] = steps; 103 adc_dev->channel_step[i] = steps;
86 steps++; 104 steps++;
87 } 105 }
106}
107
108static irqreturn_t tiadc_irq_h(int irq, void *private)
109{
110 struct iio_dev *indio_dev = private;
111 struct tiadc_device *adc_dev = iio_priv(indio_dev);
112 unsigned int status, config;
113 status = tiadc_readl(adc_dev, REG_IRQSTATUS);
114
115 /*
116 * ADC and touchscreen share the IRQ line.
117 * FIFO0 interrupts are used by TSC. Handle FIFO1 IRQs here only
118 */
119 if (status & IRQENB_FIFO1OVRRUN) {
120 /* FIFO Overrun. Clear flag. Disable/Enable ADC to recover */
121 config = tiadc_readl(adc_dev, REG_CTRL);
122 config &= ~(CNTRLREG_TSCSSENB);
123 tiadc_writel(adc_dev, REG_CTRL, config);
124 tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1OVRRUN
125 | IRQENB_FIFO1UNDRFLW | IRQENB_FIFO1THRES);
126 tiadc_writel(adc_dev, REG_CTRL, (config | CNTRLREG_TSCSSENB));
127 return IRQ_HANDLED;
128 } else if (status & IRQENB_FIFO1THRES) {
129 /* Disable irq and wake worker thread */
130 tiadc_writel(adc_dev, REG_IRQCLR, IRQENB_FIFO1THRES);
131 return IRQ_WAKE_THREAD;
132 }
133
134 return IRQ_NONE;
135}
136
137static irqreturn_t tiadc_worker_h(int irq, void *private)
138{
139 struct iio_dev *indio_dev = private;
140 struct tiadc_device *adc_dev = iio_priv(indio_dev);
141 int i, k, fifo1count, read;
142 u16 *data = adc_dev->data;
143
144 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
145 for (k = 0; k < fifo1count; k = k + i) {
146 for (i = 0; i < (indio_dev->scan_bytes)/2; i++) {
147 read = tiadc_readl(adc_dev, REG_FIFO1);
148 data[i] = read & FIFOREAD_DATA_MASK;
149 }
150 iio_push_to_buffers(indio_dev, (u8 *) data);
151 }
152
153 tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES);
154 tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
155
156 return IRQ_HANDLED;
157}
158
159static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
160{
161 struct tiadc_device *adc_dev = iio_priv(indio_dev);
162 int i, fifo1count, read;
163
164 tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
165 IRQENB_FIFO1OVRRUN |
166 IRQENB_FIFO1UNDRFLW));
167
168 /* Flush FIFO. Needed in corner cases in simultaneous tsc/adc use */
169 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
170 for (i = 0; i < fifo1count; i++)
171 read = tiadc_readl(adc_dev, REG_FIFO1);
172
173 return iio_sw_buffer_preenable(indio_dev);
174}
175
176static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
177{
178 struct tiadc_device *adc_dev = iio_priv(indio_dev);
179 struct iio_buffer *buffer = indio_dev->buffer;
180 unsigned int enb = 0;
181 u8 bit;
182
183 tiadc_step_config(indio_dev);
184 for_each_set_bit(bit, buffer->scan_mask, adc_dev->channels)
185 enb |= (get_adc_step_bit(adc_dev, bit) << 1);
186 adc_dev->buffer_en_ch_steps = enb;
187
188 am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
189
190 tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
191 | IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
192 tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES
193 | IRQENB_FIFO1OVRRUN);
194
195 return 0;
196}
197
198static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
199{
200 struct tiadc_device *adc_dev = iio_priv(indio_dev);
201 int fifo1count, i, read;
202
203 tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
204 IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
205 am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
88 206
207 /* Flush FIFO of leftover data in the time it takes to disable adc */
208 fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
209 for (i = 0; i < fifo1count; i++)
210 read = tiadc_readl(adc_dev, REG_FIFO1);
211
212 return 0;
89} 213}
90 214
215static int tiadc_buffer_postdisable(struct iio_dev *indio_dev)
216{
217 tiadc_step_config(indio_dev);
218
219 return 0;
220}
221
222static const struct iio_buffer_setup_ops tiadc_buffer_setup_ops = {
223 .preenable = &tiadc_buffer_preenable,
224 .postenable = &tiadc_buffer_postenable,
225 .predisable = &tiadc_buffer_predisable,
226 .postdisable = &tiadc_buffer_postdisable,
227};
228
229int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
230 irqreturn_t (*pollfunc_bh)(int irq, void *p),
231 irqreturn_t (*pollfunc_th)(int irq, void *p),
232 int irq,
233 unsigned long flags,
234 const struct iio_buffer_setup_ops *setup_ops)
235{
236 int ret;
237
238 indio_dev->buffer = iio_kfifo_allocate(indio_dev);
239 if (!indio_dev->buffer)
240 return -ENOMEM;
241
242 ret = request_threaded_irq(irq, pollfunc_th, pollfunc_bh,
243 flags, indio_dev->name, indio_dev);
244 if (ret)
245 goto error_kfifo_free;
246
247 indio_dev->setup_ops = setup_ops;
248 indio_dev->modes |= INDIO_BUFFER_HARDWARE;
249
250 ret = iio_buffer_register(indio_dev,
251 indio_dev->channels,
252 indio_dev->num_channels);
253 if (ret)
254 goto error_free_irq;
255
256 return 0;
257
258error_free_irq:
259 free_irq(irq, indio_dev);
260error_kfifo_free:
261 iio_kfifo_free(indio_dev->buffer);
262 return ret;
263}
264
265static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
266{
267 struct tiadc_device *adc_dev = iio_priv(indio_dev);
268
269 free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
270 iio_kfifo_free(indio_dev->buffer);
271 iio_buffer_unregister(indio_dev);
272}
273
274
91static const char * const chan_name_ain[] = { 275static const char * const chan_name_ain[] = {
92 "AIN0", 276 "AIN0",
93 "AIN1", 277 "AIN1",
@@ -120,6 +304,7 @@ static int tiadc_channel_init(struct iio_dev *indio_dev, int channels)
120 chan->channel = adc_dev->channel_line[i]; 304 chan->channel = adc_dev->channel_line[i];
121 chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 305 chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
122 chan->datasheet_name = chan_name_ain[chan->channel]; 306 chan->datasheet_name = chan_name_ain[chan->channel];
307 chan->scan_index = i;
123 chan->scan_type.sign = 'u'; 308 chan->scan_type.sign = 'u';
124 chan->scan_type.realbits = 12; 309 chan->scan_type.realbits = 12;
125 chan->scan_type.storagebits = 16; 310 chan->scan_type.storagebits = 16;
@@ -147,6 +332,10 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
147 u32 step_en; 332 u32 step_en;
148 unsigned long timeout = jiffies + usecs_to_jiffies 333 unsigned long timeout = jiffies + usecs_to_jiffies
149 (IDLE_TIMEOUT * adc_dev->channels); 334 (IDLE_TIMEOUT * adc_dev->channels);
335
336 if (iio_buffer_enabled(indio_dev))
337 return -EBUSY;
338
150 step_en = get_adc_step_mask(adc_dev); 339 step_en = get_adc_step_mask(adc_dev);
151 am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); 340 am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
152 341
@@ -237,20 +426,33 @@ static int tiadc_probe(struct platform_device *pdev)
237 indio_dev->modes = INDIO_DIRECT_MODE; 426 indio_dev->modes = INDIO_DIRECT_MODE;
238 indio_dev->info = &tiadc_info; 427 indio_dev->info = &tiadc_info;
239 428
240 tiadc_step_config(adc_dev); 429 tiadc_step_config(indio_dev);
430 tiadc_writel(adc_dev, REG_FIFO1THR, FIFO1_THRESHOLD);
241 431
242 err = tiadc_channel_init(indio_dev, adc_dev->channels); 432 err = tiadc_channel_init(indio_dev, adc_dev->channels);
243 if (err < 0) 433 if (err < 0)
244 return err; 434 return err;
245 435
246 err = iio_device_register(indio_dev); 436 err = tiadc_iio_buffered_hardware_setup(indio_dev,
437 &tiadc_worker_h,
438 &tiadc_irq_h,
439 adc_dev->mfd_tscadc->irq,
440 IRQF_SHARED,
441 &tiadc_buffer_setup_ops);
442
247 if (err) 443 if (err)
248 goto err_free_channels; 444 goto err_free_channels;
249 445
446 err = iio_device_register(indio_dev);
447 if (err)
448 goto err_buffer_unregister;
449
250 platform_set_drvdata(pdev, indio_dev); 450 platform_set_drvdata(pdev, indio_dev);
251 451
252 return 0; 452 return 0;
253 453
454err_buffer_unregister:
455 tiadc_iio_buffered_hardware_remove(indio_dev);
254err_free_channels: 456err_free_channels:
255 tiadc_channels_remove(indio_dev); 457 tiadc_channels_remove(indio_dev);
256 return err; 458 return err;
@@ -263,6 +465,7 @@ static int tiadc_remove(struct platform_device *pdev)
263 u32 step_en; 465 u32 step_en;
264 466
265 iio_device_unregister(indio_dev); 467 iio_device_unregister(indio_dev);
468 tiadc_iio_buffered_hardware_remove(indio_dev);
266 tiadc_channels_remove(indio_dev); 469 tiadc_channels_remove(indio_dev);
267 470
268 step_en = get_adc_step_mask(adc_dev); 471 step_en = get_adc_step_mask(adc_dev);
@@ -301,7 +504,7 @@ static int tiadc_resume(struct device *dev)
301 restore &= ~(CNTRLREG_POWERDOWN); 504 restore &= ~(CNTRLREG_POWERDOWN);
302 tiadc_writel(adc_dev, REG_CTRL, restore); 505 tiadc_writel(adc_dev, REG_CTRL, restore);
303 506
304 tiadc_step_config(adc_dev); 507 tiadc_step_config(indio_dev);
305 508
306 return 0; 509 return 0;
307} 510}