Skip to content

Commit 5e1a1da

Browse files
ehristevjic23
authored andcommitted
iio: adc: at91-sama5d2_adc: add hw trigger and buffer support
Added support for the external hardware trigger on pin ADTRG, integrated the three possible edges into the driver and created buffer management for data retrieval Signed-off-by: Eugen Hristev <[email protected]> Acked-by: Ludovic Desroches <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 6ab6b4e commit 5e1a1da

File tree

1 file changed

+232
-5
lines changed

1 file changed

+232
-5
lines changed

drivers/iio/adc/at91-sama5d2_adc.c

Lines changed: 232 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
#include <linux/wait.h>
2626
#include <linux/iio/iio.h>
2727
#include <linux/iio/sysfs.h>
28+
#include <linux/iio/buffer.h>
29+
#include <linux/iio/trigger.h>
30+
#include <linux/iio/trigger_consumer.h>
31+
#include <linux/iio/triggered_buffer.h>
2832
#include <linux/regulator/consumer.h>
2933

3034
/* Control Register */
@@ -132,6 +136,17 @@
132136
#define AT91_SAMA5D2_PRESSR 0xbc
133137
/* Trigger Register */
134138
#define AT91_SAMA5D2_TRGR 0xc0
139+
/* Mask for TRGMOD field of TRGR register */
140+
#define AT91_SAMA5D2_TRGR_TRGMOD_MASK GENMASK(2, 0)
141+
/* No trigger, only software trigger can start conversions */
142+
#define AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER 0
143+
/* Trigger Mode external trigger rising edge */
144+
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE 1
145+
/* Trigger Mode external trigger falling edge */
146+
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL 2
147+
/* Trigger Mode external trigger any edge */
148+
#define AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY 3
149+
135150
/* Correction Select Register */
136151
#define AT91_SAMA5D2_COSR 0xd0
137152
/* Correction Value Register */
@@ -145,14 +160,29 @@
145160
/* Version Register */
146161
#define AT91_SAMA5D2_VERSION 0xfc
147162

163+
#define AT91_SAMA5D2_HW_TRIG_CNT 3
164+
#define AT91_SAMA5D2_SINGLE_CHAN_CNT 12
165+
#define AT91_SAMA5D2_DIFF_CHAN_CNT 6
166+
167+
/*
168+
* Maximum number of bytes to hold conversion from all channels
169+
* plus the timestamp
170+
*/
171+
#define AT91_BUFFER_MAX_BYTES ((AT91_SAMA5D2_SINGLE_CHAN_CNT + \
172+
AT91_SAMA5D2_DIFF_CHAN_CNT) * 2 + 8)
173+
174+
#define AT91_BUFFER_MAX_HWORDS (AT91_BUFFER_MAX_BYTES / 2)
175+
148176
#define AT91_SAMA5D2_CHAN_SINGLE(num, addr) \
149177
{ \
150178
.type = IIO_VOLTAGE, \
151179
.channel = num, \
152180
.address = addr, \
181+
.scan_index = num, \
153182
.scan_type = { \
154183
.sign = 'u', \
155184
.realbits = 12, \
185+
.storagebits = 16, \
156186
}, \
157187
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
158188
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -168,9 +198,11 @@
168198
.channel = num, \
169199
.channel2 = num2, \
170200
.address = addr, \
201+
.scan_index = num + AT91_SAMA5D2_SINGLE_CHAN_CNT, \
171202
.scan_type = { \
172203
.sign = 's', \
173204
.realbits = 12, \
205+
.storagebits = 16, \
174206
}, \
175207
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
176208
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
@@ -188,25 +220,52 @@ struct at91_adc_soc_info {
188220
unsigned max_sample_rate;
189221
};
190222

223+
struct at91_adc_trigger {
224+
char *name;
225+
unsigned int trgmod_value;
226+
unsigned int edge_type;
227+
};
228+
191229
struct at91_adc_state {
192230
void __iomem *base;
193231
int irq;
194232
struct clk *per_clk;
195233
struct regulator *reg;
196234
struct regulator *vref;
197235
int vref_uv;
236+
struct iio_trigger *trig;
237+
const struct at91_adc_trigger *selected_trig;
198238
const struct iio_chan_spec *chan;
199239
bool conversion_done;
200240
u32 conversion_value;
201241
struct at91_adc_soc_info soc_info;
202242
wait_queue_head_t wq_data_available;
243+
u16 buffer[AT91_BUFFER_MAX_HWORDS];
203244
/*
204245
* lock to prevent concurrent 'single conversion' requests through
205246
* sysfs.
206247
*/
207248
struct mutex lock;
208249
};
209250

251+
static const struct at91_adc_trigger at91_adc_trigger_list[] = {
252+
{
253+
.name = "external_rising",
254+
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE,
255+
.edge_type = IRQ_TYPE_EDGE_RISING,
256+
},
257+
{
258+
.name = "external_falling",
259+
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL,
260+
.edge_type = IRQ_TYPE_EDGE_FALLING,
261+
},
262+
{
263+
.name = "external_any",
264+
.trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY,
265+
.edge_type = IRQ_TYPE_EDGE_BOTH,
266+
},
267+
};
268+
210269
static const struct iio_chan_spec at91_adc_channels[] = {
211270
AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
212271
AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
@@ -226,8 +285,128 @@ static const struct iio_chan_spec at91_adc_channels[] = {
226285
AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
227286
AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
228287
AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
288+
IIO_CHAN_SOFT_TIMESTAMP(AT91_SAMA5D2_SINGLE_CHAN_CNT
289+
+ AT91_SAMA5D2_DIFF_CHAN_CNT + 1),
290+
};
291+
292+
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
293+
{
294+
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
295+
struct at91_adc_state *st = iio_priv(indio);
296+
u32 status = at91_adc_readl(st, AT91_SAMA5D2_TRGR);
297+
u8 bit;
298+
299+
/* clear TRGMOD */
300+
status &= ~AT91_SAMA5D2_TRGR_TRGMOD_MASK;
301+
302+
if (state)
303+
status |= st->selected_trig->trgmod_value;
304+
305+
/* set/unset hw trigger */
306+
at91_adc_writel(st, AT91_SAMA5D2_TRGR, status);
307+
308+
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
309+
struct iio_chan_spec const *chan = indio->channels + bit;
310+
311+
if (state) {
312+
at91_adc_writel(st, AT91_SAMA5D2_CHER,
313+
BIT(chan->channel));
314+
at91_adc_writel(st, AT91_SAMA5D2_IER,
315+
BIT(chan->channel));
316+
} else {
317+
at91_adc_writel(st, AT91_SAMA5D2_IDR,
318+
BIT(chan->channel));
319+
at91_adc_writel(st, AT91_SAMA5D2_CHDR,
320+
BIT(chan->channel));
321+
}
322+
}
323+
324+
return 0;
325+
}
326+
327+
static int at91_adc_reenable_trigger(struct iio_trigger *trig)
328+
{
329+
struct iio_dev *indio = iio_trigger_get_drvdata(trig);
330+
struct at91_adc_state *st = iio_priv(indio);
331+
332+
enable_irq(st->irq);
333+
334+
/* Needed to ACK the DRDY interruption */
335+
at91_adc_readl(st, AT91_SAMA5D2_LCDR);
336+
return 0;
337+
}
338+
339+
static const struct iio_trigger_ops at91_adc_trigger_ops = {
340+
.owner = THIS_MODULE,
341+
.set_trigger_state = &at91_adc_configure_trigger,
342+
.try_reenable = &at91_adc_reenable_trigger,
229343
};
230344

345+
static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *indio,
346+
char *trigger_name)
347+
{
348+
struct iio_trigger *trig;
349+
int ret;
350+
351+
trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
352+
indio->id, trigger_name);
353+
if (!trig)
354+
return NULL;
355+
356+
trig->dev.parent = indio->dev.parent;
357+
iio_trigger_set_drvdata(trig, indio);
358+
trig->ops = &at91_adc_trigger_ops;
359+
360+
ret = devm_iio_trigger_register(&indio->dev, trig);
361+
if (ret)
362+
return ERR_PTR(ret);
363+
364+
return trig;
365+
}
366+
367+
static int at91_adc_trigger_init(struct iio_dev *indio)
368+
{
369+
struct at91_adc_state *st = iio_priv(indio);
370+
371+
st->trig = at91_adc_allocate_trigger(indio, st->selected_trig->name);
372+
if (IS_ERR(st->trig)) {
373+
dev_err(&indio->dev,
374+
"could not allocate trigger\n");
375+
return PTR_ERR(st->trig);
376+
}
377+
378+
return 0;
379+
}
380+
381+
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
382+
{
383+
struct iio_poll_func *pf = p;
384+
struct iio_dev *indio = pf->indio_dev;
385+
struct at91_adc_state *st = iio_priv(indio);
386+
int i = 0;
387+
u8 bit;
388+
389+
for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
390+
struct iio_chan_spec const *chan = indio->channels + bit;
391+
392+
st->buffer[i] = at91_adc_readl(st, chan->address);
393+
i++;
394+
}
395+
396+
iio_push_to_buffers_with_timestamp(indio, st->buffer, pf->timestamp);
397+
398+
iio_trigger_notify_done(indio->trig);
399+
400+
return IRQ_HANDLED;
401+
}
402+
403+
static int at91_adc_buffer_init(struct iio_dev *indio)
404+
{
405+
return devm_iio_triggered_buffer_setup(&indio->dev, indio,
406+
&iio_pollfunc_store_time,
407+
&at91_adc_trigger_handler, NULL);
408+
}
409+
231410
static unsigned at91_adc_startup_time(unsigned startup_time_min,
232411
unsigned adc_clk_khz)
233412
{
@@ -293,14 +472,18 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
293472
u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR);
294473
u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR);
295474

296-
if (status & imr) {
475+
if (!(status & imr))
476+
return IRQ_NONE;
477+
478+
if (iio_buffer_enabled(indio)) {
479+
disable_irq_nosync(irq);
480+
iio_trigger_poll(indio->trig);
481+
} else {
297482
st->conversion_value = at91_adc_readl(st, st->chan->address);
298483
st->conversion_done = true;
299484
wake_up_interruptible(&st->wq_data_available);
300-
return IRQ_HANDLED;
301485
}
302-
303-
return IRQ_NONE;
486+
return IRQ_HANDLED;
304487
}
305488

306489
static int at91_adc_read_raw(struct iio_dev *indio_dev,
@@ -313,6 +496,11 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
313496

314497
switch (mask) {
315498
case IIO_CHAN_INFO_RAW:
499+
/* we cannot use software trigger if hw trigger enabled */
500+
ret = iio_device_claim_direct_mode(indio_dev);
501+
if (ret)
502+
return ret;
503+
316504
mutex_lock(&st->lock);
317505

318506
st->chan = chan;
@@ -344,6 +532,8 @@ static int at91_adc_read_raw(struct iio_dev *indio_dev,
344532
at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel));
345533

346534
mutex_unlock(&st->lock);
535+
536+
iio_device_release_direct_mode(indio_dev);
347537
return ret;
348538

349539
case IIO_CHAN_INFO_SCALE:
@@ -391,7 +581,8 @@ static int at91_adc_probe(struct platform_device *pdev)
391581
struct iio_dev *indio_dev;
392582
struct at91_adc_state *st;
393583
struct resource *res;
394-
int ret;
584+
int ret, i;
585+
u32 edge_type;
395586

396587
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
397588
if (!indio_dev)
@@ -432,6 +623,27 @@ static int at91_adc_probe(struct platform_device *pdev)
432623
return ret;
433624
}
434625

626+
ret = of_property_read_u32(pdev->dev.of_node,
627+
"atmel,trigger-edge-type", &edge_type);
628+
if (ret) {
629+
dev_err(&pdev->dev,
630+
"invalid or missing value for atmel,trigger-edge-type\n");
631+
return ret;
632+
}
633+
634+
st->selected_trig = NULL;
635+
636+
for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++)
637+
if (at91_adc_trigger_list[i].edge_type == edge_type) {
638+
st->selected_trig = &at91_adc_trigger_list[i];
639+
break;
640+
}
641+
642+
if (!st->selected_trig) {
643+
dev_err(&pdev->dev, "invalid external trigger edge value\n");
644+
return -EINVAL;
645+
}
646+
435647
init_waitqueue_head(&st->wq_data_available);
436648
mutex_init(&st->lock);
437649

@@ -499,10 +711,25 @@ static int at91_adc_probe(struct platform_device *pdev)
499711

500712
platform_set_drvdata(pdev, indio_dev);
501713

714+
ret = at91_adc_buffer_init(indio_dev);
715+
if (ret < 0) {
716+
dev_err(&pdev->dev, "couldn't initialize the buffer.\n");
717+
goto per_clk_disable_unprepare;
718+
}
719+
720+
ret = at91_adc_trigger_init(indio_dev);
721+
if (ret < 0) {
722+
dev_err(&pdev->dev, "couldn't setup the triggers.\n");
723+
goto per_clk_disable_unprepare;
724+
}
725+
502726
ret = iio_device_register(indio_dev);
503727
if (ret < 0)
504728
goto per_clk_disable_unprepare;
505729

730+
dev_info(&pdev->dev, "setting up trigger as %s\n",
731+
st->selected_trig->name);
732+
506733
dev_info(&pdev->dev, "version: %x\n",
507734
readl_relaxed(st->base + AT91_SAMA5D2_VERSION));
508735

0 commit comments

Comments
 (0)