Commit | Line | Data |
---|---|---|
b9618c0c MH |
1 | /* |
2 | * Copyright 2011 Analog Devices Inc. | |
3 | * | |
4 | * Licensed under the GPL-2. | |
5 | * | |
6 | */ | |
7 | ||
8 | #include <linux/interrupt.h> | |
9 | #include <linux/gpio.h> | |
b9618c0c MH |
10 | #include <linux/device.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/slab.h> | |
b9618c0c MH |
13 | |
14 | #include "../iio.h" | |
af5046af | 15 | #include "../buffer.h" |
b9618c0c | 16 | #include "../ring_sw.h" |
3f72395e | 17 | #include "../trigger_consumer.h" |
b9618c0c MH |
18 | |
19 | #include "ad7606.h" | |
20 | ||
b9618c0c | 21 | /** |
1caf7cb4 | 22 | * ad7606_trigger_handler_th() th/bh of trigger launched polling to ring buffer |
b9618c0c MH |
23 | * |
24 | **/ | |
1caf7cb4 | 25 | static irqreturn_t ad7606_trigger_handler_th_bh(int irq, void *p) |
b9618c0c | 26 | { |
13cfac20 | 27 | struct iio_poll_func *pf = p; |
e65bc6ac | 28 | struct ad7606_state *st = iio_priv(pf->indio_dev); |
1caf7cb4 | 29 | |
b9618c0c MH |
30 | gpio_set_value(st->pdata->gpio_convst, 1); |
31 | ||
13cfac20 | 32 | return IRQ_HANDLED; |
b9618c0c | 33 | } |
13cfac20 | 34 | |
b9618c0c MH |
35 | /** |
36 | * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer | |
37 | * @work_s: the work struct through which this was scheduled | |
38 | * | |
39 | * Currently there is no option in this driver to disable the saving of | |
40 | * timestamps within the ring. | |
41 | * I think the one copy of this at a time was to avoid problems if the | |
42 | * trigger was set far too high and the reads then locked up the computer. | |
43 | **/ | |
44 | static void ad7606_poll_bh_to_ring(struct work_struct *work_s) | |
45 | { | |
46 | struct ad7606_state *st = container_of(work_s, struct ad7606_state, | |
47 | poll_work); | |
e61181d0 | 48 | struct iio_dev *indio_dev = iio_priv_to_dev(st); |
14555b14 | 49 | struct iio_buffer *ring = indio_dev->buffer; |
b9618c0c MH |
50 | s64 time_ns; |
51 | __u8 *buf; | |
52 | int ret; | |
53 | ||
420fe2e9 | 54 | buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); |
b9618c0c MH |
55 | if (buf == NULL) |
56 | return; | |
57 | ||
68b41aef | 58 | if (gpio_is_valid(st->pdata->gpio_frstdata)) { |
b9618c0c MH |
59 | ret = st->bops->read_block(st->dev, 1, buf); |
60 | if (ret) | |
61 | goto done; | |
62 | if (!gpio_get_value(st->pdata->gpio_frstdata)) { | |
63 | /* This should never happen. However | |
64 | * some signal glitch caused by bad PCB desgin or | |
65 | * electrostatic discharge, could cause an extra read | |
66 | * or clock. This allows recovery. | |
67 | */ | |
68 | ad7606_reset(st); | |
69 | goto done; | |
70 | } | |
71 | ret = st->bops->read_block(st->dev, | |
72 | st->chip_info->num_channels - 1, buf + 2); | |
73 | if (ret) | |
74 | goto done; | |
75 | } else { | |
76 | ret = st->bops->read_block(st->dev, | |
77 | st->chip_info->num_channels, buf); | |
78 | if (ret) | |
79 | goto done; | |
80 | } | |
81 | ||
82 | time_ns = iio_get_time_ns(); | |
dcfb0863 | 83 | |
fd6487f8 JC |
84 | if (indio_dev->scan_timestamp) |
85 | *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns; | |
b9618c0c | 86 | |
14555b14 | 87 | ring->access->store_to(indio_dev->buffer, buf, time_ns); |
b9618c0c MH |
88 | done: |
89 | gpio_set_value(st->pdata->gpio_convst, 0); | |
1caf7cb4 | 90 | iio_trigger_notify_done(indio_dev->trig); |
b9618c0c | 91 | kfree(buf); |
b9618c0c MH |
92 | } |
93 | ||
14555b14 | 94 | static const struct iio_buffer_setup_ops ad7606_ring_setup_ops = { |
4f5495d0 | 95 | .preenable = &iio_sw_buffer_preenable, |
3b99fb76 JC |
96 | .postenable = &iio_triggered_buffer_postenable, |
97 | .predisable = &iio_triggered_buffer_predisable, | |
5565a450 JC |
98 | }; |
99 | ||
b9618c0c MH |
100 | int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev) |
101 | { | |
44039a67 | 102 | struct ad7606_state *st = iio_priv(indio_dev); |
b9618c0c MH |
103 | int ret; |
104 | ||
14555b14 JC |
105 | indio_dev->buffer = iio_sw_rb_allocate(indio_dev); |
106 | if (!indio_dev->buffer) { | |
b9618c0c MH |
107 | ret = -ENOMEM; |
108 | goto error_ret; | |
109 | } | |
110 | ||
0ed731d2 JC |
111 | indio_dev->pollfunc = iio_alloc_pollfunc(&ad7606_trigger_handler_th_bh, |
112 | &ad7606_trigger_handler_th_bh, | |
113 | 0, | |
114 | indio_dev, | |
115 | "%s_consumer%d", | |
116 | indio_dev->name, | |
117 | indio_dev->id); | |
13cfac20 JC |
118 | if (indio_dev->pollfunc == NULL) { |
119 | ret = -ENOMEM; | |
b9618c0c | 120 | goto error_deallocate_sw_rb; |
13cfac20 | 121 | } |
1caf7cb4 | 122 | |
b9618c0c MH |
123 | /* Ring buffer functions - here trigger setup related */ |
124 | ||
1612244f | 125 | indio_dev->setup_ops = &ad7606_ring_setup_ops; |
14555b14 | 126 | indio_dev->buffer->scan_timestamp = true ; |
b9618c0c MH |
127 | |
128 | INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring); | |
129 | ||
130 | /* Flag that polled ring buffering is possible */ | |
ec3afa40 | 131 | indio_dev->modes |= INDIO_BUFFER_TRIGGERED; |
b9618c0c | 132 | return 0; |
0ed731d2 | 133 | |
b9618c0c | 134 | error_deallocate_sw_rb: |
14555b14 | 135 | iio_sw_rb_free(indio_dev->buffer); |
b9618c0c MH |
136 | error_ret: |
137 | return ret; | |
138 | } | |
139 | ||
140 | void ad7606_ring_cleanup(struct iio_dev *indio_dev) | |
141 | { | |
0ed731d2 | 142 | iio_dealloc_pollfunc(indio_dev->pollfunc); |
14555b14 | 143 | iio_sw_rb_free(indio_dev->buffer); |
b9618c0c | 144 | } |