IIO: Move core headers to include/linux/iio
[linux-2.6-block.git] / drivers / staging / iio / accel / adis16204_ring.c
CommitLineData
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 7
06458e27 8#include <linux/iio/iio.h>
bb6f19ea 9#include "../ring_sw.h"
06458e27 10#include <linux/iio/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 **/
18static 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 58static 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
91void 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
97static 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
103int 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
132error_iio_sw_rb_free:
14555b14 133 iio_sw_rb_free(indio_dev->buffer);
bb6f19ea
BS
134 return ret;
135}