Commit | Line | Data |
---|---|---|
f7fe1d1d BS |
1 | #include <linux/interrupt.h> |
2 | #include <linux/irq.h> | |
f7fe1d1d BS |
3 | #include <linux/mutex.h> |
4 | #include <linux/device.h> | |
5 | #include <linux/kernel.h> | |
6 | #include <linux/spi/spi.h> | |
7 | #include <linux/slab.h> | |
8 | #include <linux/sysfs.h> | |
f7fe1d1d BS |
9 | |
10 | #include "../iio.h" | |
11 | #include "../sysfs.h" | |
12 | #include "../ring_sw.h" | |
13 | #include "accel.h" | |
14 | #include "../trigger.h" | |
15 | #include "adis16201.h" | |
16 | ||
f7fe1d1d | 17 | |
f7fe1d1d BS |
18 | /** |
19 | * adis16201_read_ring_data() read data registers which will be placed into ring | |
20 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | |
21 | * @rx: somewhere to pass back the value read | |
22 | **/ | |
cf96ffd8 | 23 | static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) |
f7fe1d1d BS |
24 | { |
25 | struct spi_message msg; | |
f7fe1d1d BS |
26 | struct adis16201_state *st = iio_dev_get_devdata(indio_dev); |
27 | struct spi_transfer xfers[ADIS16201_OUTPUTS + 1]; | |
28 | int ret; | |
29 | int i; | |
30 | ||
31 | mutex_lock(&st->buf_lock); | |
32 | ||
33 | spi_message_init(&msg); | |
34 | ||
35 | memset(xfers, 0, sizeof(xfers)); | |
36 | for (i = 0; i <= ADIS16201_OUTPUTS; i++) { | |
37 | xfers[i].bits_per_word = 8; | |
38 | xfers[i].cs_change = 1; | |
39 | xfers[i].len = 2; | |
40 | xfers[i].delay_usecs = 20; | |
41 | xfers[i].tx_buf = st->tx + 2 * i; | |
cf96ffd8 JC |
42 | st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + |
43 | 2 * i); | |
f7fe1d1d BS |
44 | st->tx[2 * i + 1] = 0; |
45 | if (i >= 1) | |
46 | xfers[i].rx_buf = rx + 2 * (i - 1); | |
47 | spi_message_add_tail(&xfers[i], &msg); | |
48 | } | |
49 | ||
50 | ret = spi_sync(st->us, &msg); | |
51 | if (ret) | |
52 | dev_err(&st->us->dev, "problem when burst reading"); | |
53 | ||
54 | mutex_unlock(&st->buf_lock); | |
55 | ||
56 | return ret; | |
57 | } | |
58 | ||
59 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | |
60 | * specific to be rolled into the core. | |
61 | */ | |
05c2858d | 62 | static irqreturn_t adis16201_trigger_handler(int irq, void *p) |
f7fe1d1d | 63 | { |
05c2858d JC |
64 | struct iio_poll_func *pf = p; |
65 | struct iio_dev *indio_dev = pf->private_data; | |
66 | struct adis16201_state *st = iio_dev_get_devdata(indio_dev); | |
67 | struct iio_ring_buffer *ring = indio_dev->ring; | |
f7fe1d1d BS |
68 | |
69 | int i = 0; | |
70 | s16 *data; | |
5565a450 | 71 | size_t datasize = ring->access->get_bytes_per_datum(ring); |
f7fe1d1d BS |
72 | |
73 | data = kmalloc(datasize, GFP_KERNEL); | |
74 | if (data == NULL) { | |
75 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | |
05c2858d | 76 | return -ENOMEM; |
f7fe1d1d BS |
77 | } |
78 | ||
79 | if (ring->scan_count) | |
cf96ffd8 | 80 | if (adis16201_read_ring_data(st->indio_dev, st->rx) >= 0) |
f7fe1d1d BS |
81 | for (; i < ring->scan_count; i++) |
82 | data[i] = be16_to_cpup( | |
83 | (__be16 *)&(st->rx[i*2])); | |
84 | ||
85 | /* Guaranteed to be aligned with 8 byte boundary */ | |
86 | if (ring->scan_timestamp) | |
05c2858d | 87 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; |
f7fe1d1d | 88 | |
5565a450 | 89 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); |
f7fe1d1d BS |
90 | |
91 | iio_trigger_notify_done(st->indio_dev->trig); | |
92 | kfree(data); | |
93 | ||
05c2858d | 94 | return IRQ_HANDLED; |
f7fe1d1d BS |
95 | } |
96 | ||
97 | void adis16201_unconfigure_ring(struct iio_dev *indio_dev) | |
98 | { | |
21b185f8 | 99 | iio_dealloc_pollfunc(indio_dev->pollfunc); |
f7fe1d1d BS |
100 | iio_sw_rb_free(indio_dev->ring); |
101 | } | |
102 | ||
5565a450 JC |
103 | static const struct iio_ring_setup_ops adis16201_ring_setup_ops = { |
104 | .preenable = &iio_sw_ring_preenable, | |
105 | .postenable = &iio_triggered_ring_postenable, | |
106 | .predisable = &iio_triggered_ring_predisable, | |
107 | }; | |
108 | ||
f7fe1d1d BS |
109 | int adis16201_configure_ring(struct iio_dev *indio_dev) |
110 | { | |
111 | int ret = 0; | |
f7fe1d1d | 112 | struct iio_ring_buffer *ring; |
f7fe1d1d BS |
113 | |
114 | ring = iio_sw_rb_allocate(indio_dev); | |
115 | if (!ring) { | |
116 | ret = -ENOMEM; | |
117 | return ret; | |
118 | } | |
119 | indio_dev->ring = ring; | |
120 | /* Effectively select the ring buffer implementation */ | |
f7fe1d1d | 121 | ring->bpe = 2; |
f7fe1d1d | 122 | ring->scan_timestamp = true; |
5565a450 JC |
123 | ring->access = &ring_sw_access_funcs; |
124 | ring->setup_ops = &adis16201_ring_setup_ops; | |
f7fe1d1d BS |
125 | ring->owner = THIS_MODULE; |
126 | ||
127 | /* Set default scan mode */ | |
cf96ffd8 JC |
128 | iio_scan_mask_set(ring, ADIS16201_SCAN_SUPPLY); |
129 | iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_X); | |
130 | iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_Y); | |
131 | iio_scan_mask_set(ring, ADIS16201_SCAN_AUX_ADC); | |
132 | iio_scan_mask_set(ring, ADIS16201_SCAN_TEMP); | |
133 | iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_X); | |
134 | iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_Y); | |
f7fe1d1d | 135 | |
21b185f8 JC |
136 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, |
137 | &adis16201_trigger_handler, | |
138 | IRQF_ONESHOT, | |
139 | indio_dev, | |
140 | "adis16201_consumer%d", | |
141 | indio_dev->id); | |
05c2858d JC |
142 | if (indio_dev->pollfunc == NULL) { |
143 | ret = -ENOMEM; | |
f7fe1d1d | 144 | goto error_iio_sw_rb_free; |
05c2858d | 145 | } |
f7fe1d1d BS |
146 | |
147 | indio_dev->modes |= INDIO_RING_TRIGGERED; | |
148 | return 0; | |
f7fe1d1d BS |
149 | error_iio_sw_rb_free: |
150 | iio_sw_rb_free(indio_dev->ring); | |
151 | return ret; | |
152 | } |