.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Common library for ADIS16XXX devices |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2012 Analog Devices Inc. |
---|
5 | 6 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
---|
6 | | - * |
---|
7 | | - * Licensed under the GPL-2 or later. |
---|
8 | 7 | */ |
---|
9 | 8 | |
---|
10 | 9 | #include <linux/export.h> |
---|
.. | .. |
---|
20 | 19 | #include <linux/iio/triggered_buffer.h> |
---|
21 | 20 | #include <linux/iio/imu/adis.h> |
---|
22 | 21 | |
---|
| 22 | +static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, |
---|
| 23 | + const unsigned long *scan_mask) |
---|
| 24 | +{ |
---|
| 25 | + struct adis *adis = iio_device_get_drvdata(indio_dev); |
---|
| 26 | + unsigned int burst_length, burst_max_length; |
---|
| 27 | + u8 *tx; |
---|
| 28 | + |
---|
| 29 | + burst_length = adis->data->burst_len + adis->burst_extra_len; |
---|
| 30 | + |
---|
| 31 | + if (adis->data->burst_max_len) |
---|
| 32 | + burst_max_length = adis->data->burst_max_len; |
---|
| 33 | + else |
---|
| 34 | + burst_max_length = burst_length; |
---|
| 35 | + |
---|
| 36 | + adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); |
---|
| 37 | + if (!adis->xfer) |
---|
| 38 | + return -ENOMEM; |
---|
| 39 | + |
---|
| 40 | + adis->buffer = kzalloc(burst_max_length + sizeof(u16), GFP_KERNEL); |
---|
| 41 | + if (!adis->buffer) { |
---|
| 42 | + kfree(adis->xfer); |
---|
| 43 | + adis->xfer = NULL; |
---|
| 44 | + return -ENOMEM; |
---|
| 45 | + } |
---|
| 46 | + |
---|
| 47 | + tx = adis->buffer + burst_max_length; |
---|
| 48 | + tx[0] = ADIS_READ_REG(adis->data->burst_reg_cmd); |
---|
| 49 | + tx[1] = 0; |
---|
| 50 | + |
---|
| 51 | + adis->xfer[0].tx_buf = tx; |
---|
| 52 | + adis->xfer[0].bits_per_word = 8; |
---|
| 53 | + adis->xfer[0].len = 2; |
---|
| 54 | + adis->xfer[1].rx_buf = adis->buffer; |
---|
| 55 | + adis->xfer[1].bits_per_word = 8; |
---|
| 56 | + adis->xfer[1].len = burst_length; |
---|
| 57 | + |
---|
| 58 | + spi_message_init(&adis->msg); |
---|
| 59 | + spi_message_add_tail(&adis->xfer[0], &adis->msg); |
---|
| 60 | + spi_message_add_tail(&adis->xfer[1], &adis->msg); |
---|
| 61 | + |
---|
| 62 | + return 0; |
---|
| 63 | +} |
---|
| 64 | + |
---|
23 | 65 | int adis_update_scan_mode(struct iio_dev *indio_dev, |
---|
24 | | - const unsigned long *scan_mask) |
---|
| 66 | + const unsigned long *scan_mask) |
---|
25 | 67 | { |
---|
26 | 68 | struct adis *adis = iio_device_get_drvdata(indio_dev); |
---|
27 | 69 | const struct iio_chan_spec *chan; |
---|
.. | .. |
---|
31 | 73 | |
---|
32 | 74 | kfree(adis->xfer); |
---|
33 | 75 | kfree(adis->buffer); |
---|
| 76 | + |
---|
| 77 | + if (adis->data->burst_len) |
---|
| 78 | + return adis_update_scan_mode_burst(indio_dev, scan_mask); |
---|
34 | 79 | |
---|
35 | 80 | scan_count = indio_dev->scan_bytes / 2; |
---|
36 | 81 | |
---|
.. | .. |
---|
55 | 100 | if (j != scan_count) |
---|
56 | 101 | adis->xfer[j].cs_change = 1; |
---|
57 | 102 | adis->xfer[j].len = 2; |
---|
58 | | - adis->xfer[j].delay_usecs = adis->data->read_delay; |
---|
| 103 | + adis->xfer[j].delay.value = adis->data->read_delay; |
---|
| 104 | + adis->xfer[j].delay.unit = SPI_DELAY_UNIT_USECS; |
---|
59 | 105 | if (j < scan_count) |
---|
60 | 106 | adis->xfer[j].tx_buf = &tx[j]; |
---|
61 | 107 | if (j >= 1) |
---|
.. | .. |
---|
74 | 120 | |
---|
75 | 121 | return 0; |
---|
76 | 122 | } |
---|
77 | | -EXPORT_SYMBOL_GPL(adis_update_scan_mode); |
---|
| 123 | +EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode, IIO_ADISLIB); |
---|
78 | 124 | |
---|
79 | 125 | static irqreturn_t adis_trigger_handler(int irq, void *p) |
---|
80 | 126 | { |
---|
.. | .. |
---|
84 | 130 | int ret; |
---|
85 | 131 | |
---|
86 | 132 | if (adis->data->has_paging) { |
---|
87 | | - mutex_lock(&adis->txrx_lock); |
---|
| 133 | + mutex_lock(&adis->state_lock); |
---|
88 | 134 | if (adis->current_page != 0) { |
---|
89 | 135 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); |
---|
90 | 136 | adis->tx[1] = 0; |
---|
.. | .. |
---|
99 | 145 | |
---|
100 | 146 | if (adis->data->has_paging) { |
---|
101 | 147 | adis->current_page = 0; |
---|
102 | | - mutex_unlock(&adis->txrx_lock); |
---|
| 148 | + mutex_unlock(&adis->state_lock); |
---|
103 | 149 | } |
---|
104 | 150 | |
---|
105 | 151 | iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, |
---|
106 | | - pf->timestamp); |
---|
| 152 | + pf->timestamp); |
---|
107 | 153 | |
---|
108 | 154 | iio_trigger_notify_done(indio_dev->trig); |
---|
109 | 155 | |
---|
110 | 156 | return IRQ_HANDLED; |
---|
111 | 157 | } |
---|
112 | 158 | |
---|
| 159 | +static void adis_buffer_cleanup(void *arg) |
---|
| 160 | +{ |
---|
| 161 | + struct adis *adis = arg; |
---|
| 162 | + |
---|
| 163 | + kfree(adis->buffer); |
---|
| 164 | + kfree(adis->xfer); |
---|
| 165 | +} |
---|
| 166 | + |
---|
113 | 167 | /** |
---|
114 | | - * adis_setup_buffer_and_trigger() - Sets up buffer and trigger for the adis device |
---|
115 | | - * @adis: The adis device. |
---|
116 | | - * @indio_dev: The IIO device. |
---|
| 168 | + * devm_adis_setup_buffer_and_trigger() - Sets up buffer and trigger for |
---|
| 169 | + * the managed adis device |
---|
| 170 | + * @adis: The adis device |
---|
| 171 | + * @indio_dev: The IIO device |
---|
117 | 172 | * @trigger_handler: Optional trigger handler, may be NULL. |
---|
118 | 173 | * |
---|
119 | 174 | * Returns 0 on success, a negative error code otherwise. |
---|
.. | .. |
---|
122 | 177 | * 'trigger_handler' is NULL the default trigger handler will be used. The |
---|
123 | 178 | * default trigger handler will simply read the registers assigned to the |
---|
124 | 179 | * currently active channels. |
---|
125 | | - * |
---|
126 | | - * adis_cleanup_buffer_and_trigger() should be called to free the resources |
---|
127 | | - * allocated by this function. |
---|
128 | 180 | */ |
---|
129 | | -int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, |
---|
130 | | - irqreturn_t (*trigger_handler)(int, void *)) |
---|
| 181 | +int |
---|
| 182 | +devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, |
---|
| 183 | + irq_handler_t trigger_handler) |
---|
131 | 184 | { |
---|
132 | 185 | int ret; |
---|
133 | 186 | |
---|
134 | 187 | if (!trigger_handler) |
---|
135 | 188 | trigger_handler = adis_trigger_handler; |
---|
136 | 189 | |
---|
137 | | - ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, |
---|
138 | | - trigger_handler, NULL); |
---|
| 190 | + ret = devm_iio_triggered_buffer_setup(&adis->spi->dev, indio_dev, |
---|
| 191 | + &iio_pollfunc_store_time, |
---|
| 192 | + trigger_handler, NULL); |
---|
139 | 193 | if (ret) |
---|
140 | 194 | return ret; |
---|
141 | 195 | |
---|
142 | 196 | if (adis->spi->irq) { |
---|
143 | | - ret = adis_probe_trigger(adis, indio_dev); |
---|
| 197 | + ret = devm_adis_probe_trigger(adis, indio_dev); |
---|
144 | 198 | if (ret) |
---|
145 | | - goto error_buffer_cleanup; |
---|
| 199 | + return ret; |
---|
146 | 200 | } |
---|
147 | | - return 0; |
---|
148 | 201 | |
---|
149 | | -error_buffer_cleanup: |
---|
150 | | - iio_triggered_buffer_cleanup(indio_dev); |
---|
151 | | - return ret; |
---|
| 202 | + return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup, |
---|
| 203 | + adis); |
---|
152 | 204 | } |
---|
153 | | -EXPORT_SYMBOL_GPL(adis_setup_buffer_and_trigger); |
---|
| 205 | +EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger, IIO_ADISLIB); |
---|
154 | 206 | |
---|
155 | | -/** |
---|
156 | | - * adis_cleanup_buffer_and_trigger() - Free buffer and trigger resources |
---|
157 | | - * @adis: The adis device. |
---|
158 | | - * @indio_dev: The IIO device. |
---|
159 | | - * |
---|
160 | | - * Frees resources allocated by adis_setup_buffer_and_trigger() |
---|
161 | | - */ |
---|
162 | | -void adis_cleanup_buffer_and_trigger(struct adis *adis, |
---|
163 | | - struct iio_dev *indio_dev) |
---|
164 | | -{ |
---|
165 | | - if (adis->spi->irq) |
---|
166 | | - adis_remove_trigger(adis); |
---|
167 | | - kfree(adis->buffer); |
---|
168 | | - kfree(adis->xfer); |
---|
169 | | - iio_triggered_buffer_cleanup(indio_dev); |
---|
170 | | -} |
---|
171 | | -EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger); |
---|