Commit | Line | Data |
---|---|---|
2c834b4d BS |
1 | #include <linux/interrupt.h> |
2 | #include <linux/irq.h> | |
3 | #include <linux/gpio.h> | |
4 | #include <linux/workqueue.h> | |
5 | #include <linux/mutex.h> | |
6 | #include <linux/device.h> | |
7 | #include <linux/kernel.h> | |
8 | #include <linux/spi/spi.h> | |
1cb6c1f5 | 9 | #include <linux/slab.h> |
2c834b4d BS |
10 | #include <linux/sysfs.h> |
11 | #include <linux/list.h> | |
12 | ||
13 | #include "../iio.h" | |
14 | #include "../sysfs.h" | |
15 | #include "../ring_sw.h" | |
16 | #include "accel.h" | |
17 | #include "../trigger.h" | |
18 | #include "adis16240.h" | |
19 | ||
2c834b4d BS |
20 | /** |
21 | * adis16240_read_ring_data() read data registers which will be placed into ring | |
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | |
23 | * @rx: somewhere to pass back the value read | |
24 | **/ | |
25 | static int adis16240_read_ring_data(struct device *dev, u8 *rx) | |
26 | { | |
27 | struct spi_message msg; | |
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
29 | struct adis16240_state *st = iio_dev_get_devdata(indio_dev); | |
30 | struct spi_transfer xfers[ADIS16240_OUTPUTS + 1]; | |
31 | int ret; | |
32 | int i; | |
33 | ||
34 | mutex_lock(&st->buf_lock); | |
35 | ||
36 | spi_message_init(&msg); | |
37 | ||
38 | memset(xfers, 0, sizeof(xfers)); | |
39 | for (i = 0; i <= ADIS16240_OUTPUTS; i++) { | |
40 | xfers[i].bits_per_word = 8; | |
41 | xfers[i].cs_change = 1; | |
42 | xfers[i].len = 2; | |
43 | xfers[i].delay_usecs = 30; | |
44 | xfers[i].tx_buf = st->tx + 2 * i; | |
45 | st->tx[2 * i] | |
46 | = ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i); | |
47 | st->tx[2 * i + 1] = 0; | |
48 | if (i >= 1) | |
49 | xfers[i].rx_buf = rx + 2 * (i - 1); | |
50 | spi_message_add_tail(&xfers[i], &msg); | |
51 | } | |
52 | ||
53 | ret = spi_sync(st->us, &msg); | |
54 | if (ret) | |
55 | dev_err(&st->us->dev, "problem when burst reading"); | |
56 | ||
57 | mutex_unlock(&st->buf_lock); | |
58 | ||
59 | return ret; | |
60 | } | |
61 | ||
d6d30d26 | 62 | static irqreturn_t adis16240_trigger_handler(int irq, void *p) |
2c834b4d | 63 | { |
d6d30d26 JC |
64 | struct iio_poll_func *pf = p; |
65 | struct iio_dev *indio_dev = pf->private_data; | |
66 | struct adis16240_state *st = iio_dev_get_devdata(indio_dev); | |
67 | struct iio_ring_buffer *ring = indio_dev->ring; | |
2c834b4d BS |
68 | |
69 | int i = 0; | |
70 | s16 *data; | |
5565a450 | 71 | size_t datasize = ring->access->get_bytes_per_datum(ring); |
2c834b4d | 72 | |
d6d30d26 | 73 | data = kmalloc(datasize, GFP_KERNEL); |
2c834b4d BS |
74 | if (data == NULL) { |
75 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | |
d6d30d26 | 76 | return -ENOMEM; |
2c834b4d BS |
77 | } |
78 | ||
d6d30d26 JC |
79 | if (ring->scan_count && |
80 | adis16240_read_ring_data(&st->indio_dev->dev, st->rx) >= 0) | |
81 | for (; i < ring->scan_count; i++) | |
82 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | |
2c834b4d BS |
83 | |
84 | /* Guaranteed to be aligned with 8 byte boundary */ | |
bf32963c | 85 | if (ring->scan_timestamp) |
d6d30d26 | 86 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; |
2c834b4d | 87 | |
5565a450 | 88 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); |
2c834b4d BS |
89 | |
90 | iio_trigger_notify_done(st->indio_dev->trig); | |
91 | kfree(data); | |
92 | ||
d6d30d26 | 93 | return IRQ_HANDLED; |
2c834b4d BS |
94 | } |
95 | ||
2c834b4d BS |
96 | void adis16240_unconfigure_ring(struct iio_dev *indio_dev) |
97 | { | |
d6d30d26 | 98 | kfree(indio_dev->pollfunc->name); |
2c834b4d BS |
99 | kfree(indio_dev->pollfunc); |
100 | iio_sw_rb_free(indio_dev->ring); | |
101 | } | |
102 | ||
5565a450 JC |
103 | static const struct iio_ring_setup_ops adis16240_ring_setup_ops = { |
104 | .preenable = &iio_sw_ring_preenable, | |
105 | .postenable = &iio_triggered_ring_postenable, | |
106 | .predisable = &iio_triggered_ring_predisable, | |
107 | }; | |
108 | ||
2c834b4d BS |
109 | int adis16240_configure_ring(struct iio_dev *indio_dev) |
110 | { | |
111 | int ret = 0; | |
2c834b4d | 112 | struct iio_ring_buffer *ring; |
2c834b4d 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 */ | |
5565a450 | 121 | ring->access = &ring_sw_access_funcs; |
43c11b43 | 122 | ring->bpe = 2; |
bf32963c | 123 | ring->scan_timestamp = true; |
5565a450 | 124 | ring->setup_ops = &adis16240_ring_setup_ops; |
2c834b4d BS |
125 | ring->owner = THIS_MODULE; |
126 | ||
bf32963c | 127 | /* Set default scan mode */ |
cd69f57d JC |
128 | iio_scan_mask_set(ring, ADIS16240_SCAN_SUPPLY); |
129 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_X); | |
130 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Y); | |
131 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Z); | |
132 | iio_scan_mask_set(ring, ADIS16240_SCAN_AUX_ADC); | |
133 | iio_scan_mask_set(ring, ADIS16240_SCAN_TEMP); | |
bf32963c | 134 | |
d6d30d26 JC |
135 | indio_dev->pollfunc = kzalloc(sizeof(*indio_dev->pollfunc), GFP_KERNEL); |
136 | if (indio_dev->pollfunc == NULL) { | |
137 | ret = -ENOMEM; | |
15744090 | 138 | goto error_iio_sw_rb_free; |
d6d30d26 JC |
139 | } |
140 | indio_dev->pollfunc->private_data = indio_dev; | |
141 | indio_dev->pollfunc->h = &iio_pollfunc_store_time; | |
142 | indio_dev->pollfunc->thread = &adis16240_trigger_handler; | |
143 | indio_dev->pollfunc->type = IRQF_ONESHOT; | |
144 | indio_dev->pollfunc->name = | |
145 | kasprintf(GFP_KERNEL, "adis16240_consumer%d", indio_dev->id); | |
146 | if (indio_dev->pollfunc->name == NULL) { | |
147 | ret = -ENOMEM; | |
148 | goto error_free_poll_func; | |
149 | } | |
2c834b4d BS |
150 | indio_dev->modes |= INDIO_RING_TRIGGERED; |
151 | return 0; | |
d6d30d26 JC |
152 | error_free_poll_func: |
153 | kfree(indio_dev->pollfunc); | |
2c834b4d BS |
154 | error_iio_sw_rb_free: |
155 | iio_sw_rb_free(indio_dev->ring); | |
156 | return ret; | |
157 | } | |
158 |