1
2
3
4
5
6
7
8
9
10#include <linux/interrupt.h>
11#include <linux/gpio.h>
12#include <linux/workqueue.h>
13#include <linux/device.h>
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/sysfs.h>
17#include <linux/list.h>
18#include <linux/spi/spi.h>
19
20#include "../iio.h"
21#include "../ring_generic.h"
22#include "../ring_sw.h"
23#include "../trigger.h"
24#include "../sysfs.h"
25
26#include "ad7476.h"
27
28static IIO_SCAN_EL_C(in0, 0, 0, NULL);
29
30static ssize_t ad7476_show_type(struct device *dev,
31 struct device_attribute *attr,
32 char *buf)
33{
34 struct iio_ring_buffer *ring = dev_get_drvdata(dev);
35 struct iio_dev *indio_dev = ring->indio_dev;
36 struct ad7476_state *st = indio_dev->dev_data;
37
38 return sprintf(buf, "%c%d/%d>>%d\n", st->chip_info->sign,
39 st->chip_info->bits, st->chip_info->storagebits,
40 st->chip_info->res_shift);
41}
42static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7476_show_type, NULL, 0);
43
44static struct attribute *ad7476_scan_el_attrs[] = {
45 &iio_scan_el_in0.dev_attr.attr,
46 &iio_const_attr_in0_index.dev_attr.attr,
47 &iio_dev_attr_in_type.dev_attr.attr,
48 NULL,
49};
50
51static struct attribute_group ad7476_scan_el_group = {
52 .name = "scan_elements",
53 .attrs = ad7476_scan_el_attrs,
54};
55
56int ad7476_scan_from_ring(struct ad7476_state *st)
57{
58 struct iio_ring_buffer *ring = st->indio_dev->ring;
59 int ret;
60 u8 *ring_data;
61
62 ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
63 if (ring_data == NULL) {
64 ret = -ENOMEM;
65 goto error_ret;
66 }
67 ret = ring->access.read_last(ring, ring_data);
68 if (ret)
69 goto error_free_ring_data;
70
71 ret = (ring_data[0] << 8) | ring_data[1];
72
73error_free_ring_data:
74 kfree(ring_data);
75error_ret:
76 return ret;
77}
78
79
80
81
82
83
84
85
86static int ad7476_ring_preenable(struct iio_dev *indio_dev)
87{
88 struct ad7476_state *st = indio_dev->dev_data;
89 size_t d_size;
90
91 if (indio_dev->ring->access.set_bytes_per_datum) {
92 d_size = st->chip_info->storagebits / 8 + sizeof(s64);
93 if (d_size % 8)
94 d_size += 8 - (d_size % 8);
95 indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
96 d_size);
97 }
98
99 return 0;
100}
101
102
103
104
105
106
107
108
109static void ad7476_poll_func_th(struct iio_dev *indio_dev, s64 time)
110{
111 struct ad7476_state *st = indio_dev->dev_data;
112
113 schedule_work(&st->poll_work);
114 return;
115}
116
117
118
119
120
121
122
123
124
125static void ad7476_poll_bh_to_ring(struct work_struct *work_s)
126{
127 struct ad7476_state *st = container_of(work_s, struct ad7476_state,
128 poll_work);
129 struct iio_dev *indio_dev = st->indio_dev;
130 struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
131 s64 time_ns;
132 __u8 *rxbuf;
133 int b_sent;
134 size_t d_size;
135
136
137 d_size = st->chip_info->storagebits / 8 + sizeof(s64);
138 if (d_size % sizeof(s64))
139 d_size += sizeof(s64) - (d_size % sizeof(s64));
140
141
142 if (atomic_inc_return(&st->protect_ring) > 1)
143 return;
144
145 rxbuf = kzalloc(d_size, GFP_KERNEL);
146 if (rxbuf == NULL)
147 return;
148
149 b_sent = spi_read(st->spi, rxbuf, st->chip_info->storagebits / 8);
150 if (b_sent < 0)
151 goto done;
152
153 time_ns = iio_get_time_ns();
154
155 memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
156
157 indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
158done:
159 kfree(rxbuf);
160 atomic_dec(&st->protect_ring);
161}
162
163int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
164{
165 struct ad7476_state *st = indio_dev->dev_data;
166 int ret = 0;
167
168 indio_dev->ring = iio_sw_rb_allocate(indio_dev);
169 if (!indio_dev->ring) {
170 ret = -ENOMEM;
171 goto error_ret;
172 }
173
174 iio_ring_sw_register_funcs(&indio_dev->ring->access);
175 ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7476_poll_func_th);
176 if (ret)
177 goto error_deallocate_sw_rb;
178
179
180
181 indio_dev->ring->preenable = &ad7476_ring_preenable;
182 indio_dev->ring->postenable = &iio_triggered_ring_postenable;
183 indio_dev->ring->predisable = &iio_triggered_ring_predisable;
184 indio_dev->ring->scan_el_attrs = &ad7476_scan_el_group;
185
186 INIT_WORK(&st->poll_work, &ad7476_poll_bh_to_ring);
187
188
189 indio_dev->modes |= INDIO_RING_TRIGGERED;
190 return 0;
191error_deallocate_sw_rb:
192 iio_sw_rb_free(indio_dev->ring);
193error_ret:
194 return ret;
195}
196
197void ad7476_ring_cleanup(struct iio_dev *indio_dev)
198{
199
200 if (indio_dev->trig) {
201 iio_put_trigger(indio_dev->trig);
202 iio_trigger_dettach_poll_func(indio_dev->trig,
203 indio_dev->pollfunc);
204 }
205 kfree(indio_dev->pollfunc);
206 iio_sw_rb_free(indio_dev->ring);
207}
208