1#include <linux/export.h>
2#include <linux/interrupt.h>
3#include <linux/mutex.h>
4#include <linux/kernel.h>
5#include <linux/spi/spi.h>
6#include <linux/slab.h>
7
8#include <linux/iio/iio.h>
9#include "../ring_sw.h"
10#include <linux/iio/trigger_consumer.h>
11#include "adis16203.h"
12
13
14
15
16
17
18static int adis16203_read_ring_data(struct iio_dev *indio_dev, u8 *rx)
19{
20 struct spi_message msg;
21 struct adis16203_state *st = iio_priv(indio_dev);
22 struct spi_transfer xfers[ADIS16203_OUTPUTS + 1];
23 int ret;
24 int i;
25
26 mutex_lock(&st->buf_lock);
27
28 spi_message_init(&msg);
29
30 memset(xfers, 0, sizeof(xfers));
31 for (i = 0; i <= ADIS16203_OUTPUTS; i++) {
32 xfers[i].bits_per_word = 8;
33 xfers[i].cs_change = 1;
34 xfers[i].len = 2;
35 xfers[i].delay_usecs = 20;
36 xfers[i].tx_buf = st->tx + 2 * i;
37 if (i < 1)
38 st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i);
39 else
40 st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6);
41 st->tx[2 * i + 1] = 0;
42 if (i >= 1)
43 xfers[i].rx_buf = rx + 2 * (i - 1);
44 spi_message_add_tail(&xfers[i], &msg);
45 }
46
47 ret = spi_sync(st->us, &msg);
48 if (ret)
49 dev_err(&st->us->dev, "problem when burst reading");
50
51 mutex_unlock(&st->buf_lock);
52
53 return ret;
54}
55
56
57
58
59static irqreturn_t adis16203_trigger_handler(int irq, void *p)
60{
61 struct iio_poll_func *pf = p;
62 struct iio_dev *indio_dev = pf->indio_dev;
63 struct adis16203_state *st = iio_priv(indio_dev);
64 struct iio_buffer *ring = indio_dev->buffer;
65
66 int i = 0;
67 s16 *data;
68
69 data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
70 if (data == NULL) {
71 dev_err(&st->us->dev, "memory alloc failed in ring bh");
72 goto done;
73 }
74
75 if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) &&
76 adis16203_read_ring_data(indio_dev, st->rx) >= 0)
77 for (; i < bitmap_weight(indio_dev->active_scan_mask,
78 indio_dev->masklength); i++)
79 data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2]));
80
81
82 if (indio_dev->scan_timestamp)
83 *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp;
84
85 ring->access->store_to(ring,
86 (u8 *)data,
87 pf->timestamp);
88
89 kfree(data);
90done:
91 iio_trigger_notify_done(indio_dev->trig);
92
93 return IRQ_HANDLED;
94}
95
96void adis16203_unconfigure_ring(struct iio_dev *indio_dev)
97{
98 iio_dealloc_pollfunc(indio_dev->pollfunc);
99 iio_sw_rb_free(indio_dev->buffer);
100}
101
102static const struct iio_buffer_setup_ops adis16203_ring_setup_ops = {
103 .preenable = &iio_sw_buffer_preenable,
104 .postenable = &iio_triggered_buffer_postenable,
105 .predisable = &iio_triggered_buffer_predisable,
106};
107
108int adis16203_configure_ring(struct iio_dev *indio_dev)
109{
110 int ret = 0;
111 struct iio_buffer *ring;
112
113 ring = iio_sw_rb_allocate(indio_dev);
114 if (!ring) {
115 ret = -ENOMEM;
116 return ret;
117 }
118 indio_dev->buffer = ring;
119 ring->scan_timestamp = true;
120 indio_dev->setup_ops = &adis16203_ring_setup_ops;
121
122 indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
123 &adis16203_trigger_handler,
124 IRQF_ONESHOT,
125 indio_dev,
126 "adis16203_consumer%d",
127 indio_dev->id);
128 if (indio_dev->pollfunc == NULL) {
129 ret = -ENOMEM;
130 goto error_iio_sw_rb_free;
131 }
132
133 indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
134 return 0;
135
136error_iio_sw_rb_free:
137 iio_sw_rb_free(indio_dev->buffer);
138 return ret;
139}
140