Commit | Line | Data |
---|---|---|
8e336a72 | 1 | #include <linux/export.h> |
bb6f19ea | 2 | #include <linux/interrupt.h> |
bb6f19ea | 3 | #include <linux/mutex.h> |
bb6f19ea BS |
4 | #include <linux/kernel.h> |
5 | #include <linux/spi/spi.h> | |
6 | #include <linux/slab.h> | |
bb6f19ea BS |
7 | |
8 | #include "../iio.h" | |
bb6f19ea | 9 | #include "../ring_sw.h" |
3f72395e | 10 | #include "../trigger_consumer.h" |
bb6f19ea BS |
11 | #include "adis16204.h" |
12 | ||
bb6f19ea BS |
13 | /** |
14 | * adis16204_read_ring_data() read data registers which will be placed into ring | |
15 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | |
16 | * @rx: somewhere to pass back the value read | |
17 | **/ | |
18 | static int adis16204_read_ring_data(struct device *dev, u8 *rx) | |
19 | { | |
20 | struct spi_message msg; | |
21 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
4de66bbb | 22 | struct adis16204_state *st = iio_priv(indio_dev); |
bb6f19ea BS |
23 | struct spi_transfer xfers[ADIS16204_OUTPUTS + 1]; |
24 | int ret; | |
25 | int i; | |
26 | ||
27 | mutex_lock(&st->buf_lock); | |
28 | ||
29 | spi_message_init(&msg); | |
30 | ||
31 | memset(xfers, 0, sizeof(xfers)); | |
32 | for (i = 0; i <= ADIS16204_OUTPUTS; i++) { | |
33 | xfers[i].bits_per_word = 8; | |
34 | xfers[i].cs_change = 1; | |
35 | xfers[i].len = 2; | |
36 | xfers[i].delay_usecs = 20; | |
37 | xfers[i].tx_buf = st->tx + 2 * i; | |
ad3eb9ab JC |
38 | st->tx[2 * i] |
39 | = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i); | |
bb6f19ea BS |
40 | st->tx[2 * i + 1] = 0; |
41 | if (i >= 1) | |
42 | xfers[i].rx_buf = rx + 2 * (i - 1); | |
43 | spi_message_add_tail(&xfers[i], &msg); | |
44 | } | |
45 | ||
46 | ret = spi_sync(st->us, &msg); | |
47 | if (ret) | |
48 | dev_err(&st->us->dev, "problem when burst reading"); | |
49 | ||
50 | mutex_unlock(&st->buf_lock); | |
51 | ||
52 | return ret; | |
53 | } | |
54 | ||
55 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | |
56 | * specific to be rolled into the core. | |
57 | */ | |
80142f0d | 58 | static irqreturn_t adis16204_trigger_handler(int irq, void *p) |
bb6f19ea | 59 | { |
80142f0d | 60 | struct iio_poll_func *pf = p; |
e65bc6ac | 61 | struct iio_dev *indio_dev = pf->indio_dev; |
4de66bbb | 62 | struct adis16204_state *st = iio_priv(indio_dev); |
14555b14 | 63 | struct iio_buffer *ring = indio_dev->buffer; |
bb6f19ea BS |
64 | int i = 0; |
65 | s16 *data; | |
bb6f19ea | 66 | |
420fe2e9 | 67 | data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); |
bb6f19ea BS |
68 | if (data == NULL) { |
69 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | |
80142f0d | 70 | return -ENOMEM; |
bb6f19ea BS |
71 | } |
72 | ||
550268ca JC |
73 | if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength) && |
74 | adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0) | |
75 | for (; i < bitmap_weight(indio_dev->active_scan_mask, | |
76 | indio_dev->masklength); i++) | |
77 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | |
bb6f19ea BS |
78 | |
79 | /* Guaranteed to be aligned with 8 byte boundary */ | |
fd6487f8 | 80 | if (indio_dev->scan_timestamp) |
80142f0d | 81 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; |
bb6f19ea | 82 | |
5565a450 | 83 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); |
bb6f19ea | 84 | |
4de66bbb | 85 | iio_trigger_notify_done(indio_dev->trig); |
bb6f19ea BS |
86 | kfree(data); |
87 | ||
80142f0d | 88 | return IRQ_HANDLED; |
bb6f19ea BS |
89 | } |
90 | ||
91 | void adis16204_unconfigure_ring(struct iio_dev *indio_dev) | |
92 | { | |
21b185f8 | 93 | iio_dealloc_pollfunc(indio_dev->pollfunc); |
14555b14 | 94 | iio_sw_rb_free(indio_dev->buffer); |
bb6f19ea BS |
95 | } |
96 | ||
14555b14 JC |
97 | static const struct iio_buffer_setup_ops adis16204_ring_setup_ops = { |
98 | .preenable = &iio_sw_buffer_preenable, | |
3b99fb76 JC |
99 | .postenable = &iio_triggered_buffer_postenable, |
100 | .predisable = &iio_triggered_buffer_predisable, | |
5565a450 JC |
101 | }; |
102 | ||
bb6f19ea BS |
103 | int adis16204_configure_ring(struct iio_dev *indio_dev) |
104 | { | |
105 | int ret = 0; | |
14555b14 | 106 | struct iio_buffer *ring; |
bb6f19ea BS |
107 | |
108 | ring = iio_sw_rb_allocate(indio_dev); | |
109 | if (!ring) { | |
110 | ret = -ENOMEM; | |
111 | return ret; | |
112 | } | |
14555b14 | 113 | indio_dev->buffer = ring; |
bb6f19ea | 114 | ring->scan_timestamp = true; |
1612244f | 115 | indio_dev->setup_ops = &adis16204_ring_setup_ops; |
bb6f19ea | 116 | |
21b185f8 JC |
117 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, |
118 | &adis16204_trigger_handler, | |
119 | IRQF_ONESHOT, | |
120 | indio_dev, | |
121 | "%s_consumer%d", | |
122 | indio_dev->name, | |
123 | indio_dev->id); | |
80142f0d JC |
124 | if (indio_dev->pollfunc == NULL) { |
125 | ret = -ENOMEM; | |
bb6f19ea | 126 | goto error_iio_sw_rb_free; |
80142f0d | 127 | } |
bb6f19ea | 128 | |
ec3afa40 | 129 | indio_dev->modes |= INDIO_BUFFER_TRIGGERED; |
bb6f19ea BS |
130 | return 0; |
131 | ||
132 | error_iio_sw_rb_free: | |
14555b14 | 133 | iio_sw_rb_free(indio_dev->buffer); |
bb6f19ea BS |
134 | return ret; |
135 | } |