Commit | Line | Data |
---|---|---|
8e336a72 | 1 | #include <linux/export.h> |
089a4198 | 2 | #include <linux/interrupt.h> |
089a4198 | 3 | #include <linux/mutex.h> |
089a4198 BS |
4 | #include <linux/kernel.h> |
5 | #include <linux/spi/spi.h> | |
1cb6c1f5 | 6 | #include <linux/slab.h> |
089a4198 BS |
7 | |
8 | #include "../iio.h" | |
089a4198 | 9 | #include "../ring_sw.h" |
3f72395e | 10 | #include "../trigger_consumer.h" |
089a4198 BS |
11 | #include "adis16260.h" |
12 | ||
089a4198 BS |
13 | /** |
14 | * adis16260_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 adis16260_read_ring_data(struct device *dev, u8 *rx) | |
19 | { | |
20 | struct spi_message msg; | |
21 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
d088ab83 | 22 | struct adis16260_state *st = iio_priv(indio_dev); |
089a4198 BS |
23 | struct spi_transfer xfers[ADIS16260_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 <= ADIS16260_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 = 30; | |
37 | xfers[i].tx_buf = st->tx + 2 * i; | |
38 | if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */ | |
39 | st->tx[2 * i] | |
40 | = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT | |
41 | + 2 * i); | |
42 | else /* 0x06 to 0x09 is reserved */ | |
43 | st->tx[2 * i] | |
44 | = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT | |
45 | + 2 * i + 4); | |
46 | st->tx[2 * i + 1] = 0; | |
47 | if (i >= 1) | |
48 | xfers[i].rx_buf = rx + 2 * (i - 1); | |
49 | spi_message_add_tail(&xfers[i], &msg); | |
50 | } | |
51 | ||
52 | ret = spi_sync(st->us, &msg); | |
53 | if (ret) | |
54 | dev_err(&st->us->dev, "problem when burst reading"); | |
55 | ||
56 | mutex_unlock(&st->buf_lock); | |
57 | ||
58 | return ret; | |
59 | } | |
60 | ||
504b4958 | 61 | static irqreturn_t adis16260_trigger_handler(int irq, void *p) |
089a4198 | 62 | { |
504b4958 | 63 | struct iio_poll_func *pf = p; |
e65bc6ac | 64 | struct iio_dev *indio_dev = pf->indio_dev; |
d088ab83 | 65 | struct adis16260_state *st = iio_priv(indio_dev); |
14555b14 | 66 | struct iio_buffer *ring = indio_dev->buffer; |
089a4198 BS |
67 | int i = 0; |
68 | s16 *data; | |
5565a450 | 69 | size_t datasize = ring->access->get_bytes_per_datum(ring); |
089a4198 BS |
70 | |
71 | data = kmalloc(datasize , GFP_KERNEL); | |
72 | if (data == NULL) { | |
73 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | |
504b4958 | 74 | return -ENOMEM; |
089a4198 BS |
75 | } |
76 | ||
504b4958 | 77 | if (ring->scan_count && |
d088ab83 | 78 | adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0) |
504b4958 JC |
79 | for (; i < ring->scan_count; i++) |
80 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | |
089a4198 BS |
81 | |
82 | /* Guaranteed to be aligned with 8 byte boundary */ | |
bf32963c | 83 | if (ring->scan_timestamp) |
504b4958 | 84 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; |
089a4198 | 85 | |
5565a450 | 86 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); |
089a4198 | 87 | |
d088ab83 | 88 | iio_trigger_notify_done(indio_dev->trig); |
089a4198 BS |
89 | kfree(data); |
90 | ||
504b4958 | 91 | return IRQ_HANDLED; |
089a4198 BS |
92 | } |
93 | ||
089a4198 BS |
94 | void adis16260_unconfigure_ring(struct iio_dev *indio_dev) |
95 | { | |
0ed731d2 | 96 | iio_dealloc_pollfunc(indio_dev->pollfunc); |
14555b14 | 97 | iio_sw_rb_free(indio_dev->buffer); |
089a4198 BS |
98 | } |
99 | ||
14555b14 JC |
100 | static const struct iio_buffer_setup_ops adis16260_ring_setup_ops = { |
101 | .preenable = &iio_sw_buffer_preenable, | |
3b99fb76 JC |
102 | .postenable = &iio_triggered_buffer_postenable, |
103 | .predisable = &iio_triggered_buffer_predisable, | |
5565a450 JC |
104 | }; |
105 | ||
089a4198 BS |
106 | int adis16260_configure_ring(struct iio_dev *indio_dev) |
107 | { | |
108 | int ret = 0; | |
14555b14 | 109 | struct iio_buffer *ring; |
089a4198 BS |
110 | |
111 | ring = iio_sw_rb_allocate(indio_dev); | |
112 | if (!ring) { | |
113 | ret = -ENOMEM; | |
114 | return ret; | |
115 | } | |
14555b14 | 116 | indio_dev->buffer = ring; |
089a4198 | 117 | /* Effectively select the ring buffer implementation */ |
5565a450 | 118 | ring->access = &ring_sw_access_funcs; |
43c11b43 | 119 | ring->bpe = 2; |
bf32963c | 120 | ring->scan_timestamp = true; |
5565a450 | 121 | ring->setup_ops = &adis16260_ring_setup_ops; |
089a4198 BS |
122 | ring->owner = THIS_MODULE; |
123 | ||
0ed731d2 JC |
124 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, |
125 | &adis16260_trigger_handler, | |
126 | IRQF_ONESHOT, | |
127 | indio_dev, | |
128 | "adis16260_consumer%d", | |
129 | indio_dev->id); | |
504b4958 JC |
130 | if (indio_dev->pollfunc == NULL) { |
131 | ret = -ENOMEM; | |
15744090 | 132 | goto error_iio_sw_rb_free; |
504b4958 | 133 | } |
15744090 | 134 | |
ec3afa40 | 135 | indio_dev->modes |= INDIO_BUFFER_TRIGGERED; |
089a4198 | 136 | return 0; |
0ed731d2 | 137 | |
089a4198 | 138 | error_iio_sw_rb_free: |
14555b14 | 139 | iio_sw_rb_free(indio_dev->buffer); |
089a4198 BS |
140 | return ret; |
141 | } |