]> Git Repo - linux.git/blob - drivers/iio/imu/adis_buffer.c
ARM: dts: imx7s: Enable SNVS power key according to board design
[linux.git] / drivers / iio / imu / adis_buffer.c
1 /*
2  * Common library for ADIS16XXX devices
3  *
4  * Copyright 2012 Analog Devices Inc.
5  *   Author: Lars-Peter Clausen <[email protected]>
6  *
7  * Licensed under the GPL-2 or later.
8  */
9
10 #include <linux/export.h>
11 #include <linux/interrupt.h>
12 #include <linux/mutex.h>
13 #include <linux/kernel.h>
14 #include <linux/spi/spi.h>
15 #include <linux/slab.h>
16
17 #include <linux/iio/iio.h>
18 #include <linux/iio/buffer.h>
19 #include <linux/iio/trigger_consumer.h>
20 #include <linux/iio/triggered_buffer.h>
21 #include <linux/iio/imu/adis.h>
22
23 static int adis_update_scan_mode_burst(struct iio_dev *indio_dev,
24         const unsigned long *scan_mask)
25 {
26         struct adis *adis = iio_device_get_drvdata(indio_dev);
27         unsigned int burst_length;
28         u8 *tx;
29
30         /* All but the timestamp channel */
31         burst_length = (indio_dev->num_channels - 1) * sizeof(u16);
32         burst_length += adis->burst->extra_len;
33
34         adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL);
35         if (!adis->xfer)
36                 return -ENOMEM;
37
38         adis->buffer = kzalloc(burst_length + sizeof(u16), GFP_KERNEL);
39         if (!adis->buffer)
40                 return -ENOMEM;
41
42         tx = adis->buffer + burst_length;
43         tx[0] = ADIS_READ_REG(adis->burst->reg_cmd);
44         tx[1] = 0;
45
46         adis->xfer[0].tx_buf = tx;
47         adis->xfer[0].bits_per_word = 8;
48         adis->xfer[0].len = 2;
49         adis->xfer[1].rx_buf = adis->buffer;
50         adis->xfer[1].bits_per_word = 8;
51         adis->xfer[1].len = burst_length;
52
53         spi_message_init(&adis->msg);
54         spi_message_add_tail(&adis->xfer[0], &adis->msg);
55         spi_message_add_tail(&adis->xfer[1], &adis->msg);
56
57         return 0;
58 }
59
60 int adis_update_scan_mode(struct iio_dev *indio_dev,
61         const unsigned long *scan_mask)
62 {
63         struct adis *adis = iio_device_get_drvdata(indio_dev);
64         const struct iio_chan_spec *chan;
65         unsigned int scan_count;
66         unsigned int i, j;
67         __be16 *tx, *rx;
68
69         kfree(adis->xfer);
70         kfree(adis->buffer);
71
72         if (adis->burst && adis->burst->en)
73                 return adis_update_scan_mode_burst(indio_dev, scan_mask);
74
75         scan_count = indio_dev->scan_bytes / 2;
76
77         adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
78         if (!adis->xfer)
79                 return -ENOMEM;
80
81         adis->buffer = kcalloc(indio_dev->scan_bytes, 2, GFP_KERNEL);
82         if (!adis->buffer)
83                 return -ENOMEM;
84
85         rx = adis->buffer;
86         tx = rx + scan_count;
87
88         spi_message_init(&adis->msg);
89
90         for (j = 0; j <= scan_count; j++) {
91                 adis->xfer[j].bits_per_word = 8;
92                 if (j != scan_count)
93                         adis->xfer[j].cs_change = 1;
94                 adis->xfer[j].len = 2;
95                 adis->xfer[j].delay_usecs = adis->data->read_delay;
96                 if (j < scan_count)
97                         adis->xfer[j].tx_buf = &tx[j];
98                 if (j >= 1)
99                         adis->xfer[j].rx_buf = &rx[j - 1];
100                 spi_message_add_tail(&adis->xfer[j], &adis->msg);
101         }
102
103         chan = indio_dev->channels;
104         for (i = 0; i < indio_dev->num_channels; i++, chan++) {
105                 if (!test_bit(chan->scan_index, scan_mask))
106                         continue;
107                 if (chan->scan_type.storagebits == 32)
108                         *tx++ = cpu_to_be16((chan->address + 2) << 8);
109                 *tx++ = cpu_to_be16(chan->address << 8);
110         }
111
112         return 0;
113 }
114 EXPORT_SYMBOL_GPL(adis_update_scan_mode);
115
116 static irqreturn_t adis_trigger_handler(int irq, void *p)
117 {
118         struct iio_poll_func *pf = p;
119         struct iio_dev *indio_dev = pf->indio_dev;
120         struct adis *adis = iio_device_get_drvdata(indio_dev);
121         int ret;
122
123         if (!adis->buffer)
124                 return -ENOMEM;
125
126         if (adis->data->has_paging) {
127                 mutex_lock(&adis->txrx_lock);
128                 if (adis->current_page != 0) {
129                         adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
130                         adis->tx[1] = 0;
131                         spi_write(adis->spi, adis->tx, 2);
132                 }
133         }
134
135         ret = spi_sync(adis->spi, &adis->msg);
136         if (ret)
137                 dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
138
139
140         if (adis->data->has_paging) {
141                 adis->current_page = 0;
142                 mutex_unlock(&adis->txrx_lock);
143         }
144
145         iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer,
146                 pf->timestamp);
147
148         iio_trigger_notify_done(indio_dev->trig);
149
150         return IRQ_HANDLED;
151 }
152
153 /**
154  * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device
155  * @adis: The adis device.
156  * @indio_dev: The IIO device.
157  * @trigger_handler: Optional trigger handler, may be NULL.
158  *
159  * Returns 0 on success, a negative error code otherwise.
160  *
161  * This function sets up the buffer and trigger for a adis devices.  If
162  * 'trigger_handler' is NULL the default trigger handler will be used. The
163  * default trigger handler will simply read the registers assigned to the
164  * currently active channels.
165  *
166  * adis_cleanup_buffer_and_trigger() should be called to free the resources
167  * allocated by this function.
168  */
169 int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev,
170         irqreturn_t (*trigger_handler)(int, void *))
171 {
172         int ret;
173
174         if (!trigger_handler)
175                 trigger_handler = adis_trigger_handler;
176
177         ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
178                 trigger_handler, NULL);
179         if (ret)
180                 return ret;
181
182         if (adis->spi->irq) {
183                 ret = adis_probe_trigger(adis, indio_dev);
184                 if (ret)
185                         goto error_buffer_cleanup;
186         }
187         return 0;
188
189 error_buffer_cleanup:
190         iio_triggered_buffer_cleanup(indio_dev);
191         return ret;
192 }
193 EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger);
194
195 /**
196  * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources
197  * @adis: The adis device.
198  * @indio_dev: The IIO device.
199  *
200  * Frees resources allocated by adis_setup_buffer_and_trigger()
201  */
202 void adis_cleanup_buffer_and_trigger(struct adis *adis,
203         struct iio_dev *indio_dev)
204 {
205         if (adis->spi->irq)
206                 adis_remove_trigger(adis);
207         kfree(adis->buffer);
208         kfree(adis->xfer);
209         iio_triggered_buffer_cleanup(indio_dev);
210 }
211 EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);
This page took 0.045913 seconds and 4 git commands to generate.