1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Common library for ADIS16XXX devices |
4 | * |
5 | * Copyright 2012 Analog Devices Inc. |
6 | * Author: Lars-Peter Clausen <lars@metafoo.de> |
7 | */ |
8 | |
9 | #include <linux/delay.h> |
10 | #include <linux/gpio/consumer.h> |
11 | #include <linux/mutex.h> |
12 | #include <linux/device.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/spi/spi.h> |
15 | #include <linux/module.h> |
16 | #include <asm/unaligned.h> |
17 | |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/imu/adis.h> |
20 | |
21 | #define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2) |
22 | #define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1) |
23 | #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) |
24 | #define ADIS_GLOB_CMD_SW_RESET BIT(7) |
25 | |
26 | /** |
27 | * __adis_write_reg() - write N bytes to register (unlocked version) |
28 | * @adis: The adis device |
29 | * @reg: The address of the lower of the two registers |
30 | * @value: The value to write to device (up to 4 bytes) |
31 | * @size: The size of the @value (in bytes) |
32 | */ |
33 | int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, |
34 | unsigned int size) |
35 | { |
36 | unsigned int page = reg / ADIS_PAGE_SIZE; |
37 | int ret, i; |
38 | struct spi_message msg; |
39 | struct spi_transfer xfers[] = { |
40 | { |
41 | .tx_buf = adis->tx, |
42 | .bits_per_word = 8, |
43 | .len = 2, |
44 | .cs_change = 1, |
45 | .delay.value = adis->data->write_delay, |
46 | .delay.unit = SPI_DELAY_UNIT_USECS, |
47 | .cs_change_delay.value = adis->data->cs_change_delay, |
48 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
49 | }, { |
50 | .tx_buf = adis->tx + 2, |
51 | .bits_per_word = 8, |
52 | .len = 2, |
53 | .cs_change = 1, |
54 | .delay.value = adis->data->write_delay, |
55 | .delay.unit = SPI_DELAY_UNIT_USECS, |
56 | .cs_change_delay.value = adis->data->cs_change_delay, |
57 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
58 | }, { |
59 | .tx_buf = adis->tx + 4, |
60 | .bits_per_word = 8, |
61 | .len = 2, |
62 | .cs_change = 1, |
63 | .delay.value = adis->data->write_delay, |
64 | .delay.unit = SPI_DELAY_UNIT_USECS, |
65 | .cs_change_delay.value = adis->data->cs_change_delay, |
66 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
67 | }, { |
68 | .tx_buf = adis->tx + 6, |
69 | .bits_per_word = 8, |
70 | .len = 2, |
71 | .delay.value = adis->data->write_delay, |
72 | .delay.unit = SPI_DELAY_UNIT_USECS, |
73 | }, { |
74 | .tx_buf = adis->tx + 8, |
75 | .bits_per_word = 8, |
76 | .len = 2, |
77 | .delay.value = adis->data->write_delay, |
78 | .delay.unit = SPI_DELAY_UNIT_USECS, |
79 | }, |
80 | }; |
81 | |
82 | spi_message_init(m: &msg); |
83 | |
84 | if (adis->current_page != page) { |
85 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); |
86 | adis->tx[1] = page; |
87 | spi_message_add_tail(t: &xfers[0], m: &msg); |
88 | } |
89 | |
90 | switch (size) { |
91 | case 4: |
92 | adis->tx[8] = ADIS_WRITE_REG(reg + 3); |
93 | adis->tx[9] = (value >> 24) & 0xff; |
94 | adis->tx[6] = ADIS_WRITE_REG(reg + 2); |
95 | adis->tx[7] = (value >> 16) & 0xff; |
96 | fallthrough; |
97 | case 2: |
98 | adis->tx[4] = ADIS_WRITE_REG(reg + 1); |
99 | adis->tx[5] = (value >> 8) & 0xff; |
100 | fallthrough; |
101 | case 1: |
102 | adis->tx[2] = ADIS_WRITE_REG(reg); |
103 | adis->tx[3] = value & 0xff; |
104 | break; |
105 | default: |
106 | return -EINVAL; |
107 | } |
108 | |
109 | xfers[size].cs_change = 0; |
110 | |
111 | for (i = 1; i <= size; i++) |
112 | spi_message_add_tail(t: &xfers[i], m: &msg); |
113 | |
114 | ret = spi_sync(spi: adis->spi, message: &msg); |
115 | if (ret) { |
116 | dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n" , |
117 | reg, ret); |
118 | } else { |
119 | adis->current_page = page; |
120 | } |
121 | |
122 | return ret; |
123 | } |
124 | EXPORT_SYMBOL_NS_GPL(__adis_write_reg, IIO_ADISLIB); |
125 | |
126 | /** |
127 | * __adis_read_reg() - read N bytes from register (unlocked version) |
128 | * @adis: The adis device |
129 | * @reg: The address of the lower of the two registers |
130 | * @val: The value read back from the device |
131 | * @size: The size of the @val buffer |
132 | */ |
133 | int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, |
134 | unsigned int size) |
135 | { |
136 | unsigned int page = reg / ADIS_PAGE_SIZE; |
137 | struct spi_message msg; |
138 | int ret; |
139 | struct spi_transfer xfers[] = { |
140 | { |
141 | .tx_buf = adis->tx, |
142 | .bits_per_word = 8, |
143 | .len = 2, |
144 | .cs_change = 1, |
145 | .delay.value = adis->data->write_delay, |
146 | .delay.unit = SPI_DELAY_UNIT_USECS, |
147 | .cs_change_delay.value = adis->data->cs_change_delay, |
148 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
149 | }, { |
150 | .tx_buf = adis->tx + 2, |
151 | .bits_per_word = 8, |
152 | .len = 2, |
153 | .cs_change = 1, |
154 | .delay.value = adis->data->read_delay, |
155 | .delay.unit = SPI_DELAY_UNIT_USECS, |
156 | .cs_change_delay.value = adis->data->cs_change_delay, |
157 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
158 | }, { |
159 | .tx_buf = adis->tx + 4, |
160 | .rx_buf = adis->rx, |
161 | .bits_per_word = 8, |
162 | .len = 2, |
163 | .cs_change = 1, |
164 | .delay.value = adis->data->read_delay, |
165 | .delay.unit = SPI_DELAY_UNIT_USECS, |
166 | .cs_change_delay.value = adis->data->cs_change_delay, |
167 | .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, |
168 | }, { |
169 | .rx_buf = adis->rx + 2, |
170 | .bits_per_word = 8, |
171 | .len = 2, |
172 | .delay.value = adis->data->read_delay, |
173 | .delay.unit = SPI_DELAY_UNIT_USECS, |
174 | }, |
175 | }; |
176 | |
177 | spi_message_init(m: &msg); |
178 | |
179 | if (adis->current_page != page) { |
180 | adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); |
181 | adis->tx[1] = page; |
182 | spi_message_add_tail(t: &xfers[0], m: &msg); |
183 | } |
184 | |
185 | switch (size) { |
186 | case 4: |
187 | adis->tx[2] = ADIS_READ_REG(reg + 2); |
188 | adis->tx[3] = 0; |
189 | spi_message_add_tail(t: &xfers[1], m: &msg); |
190 | fallthrough; |
191 | case 2: |
192 | adis->tx[4] = ADIS_READ_REG(reg); |
193 | adis->tx[5] = 0; |
194 | spi_message_add_tail(t: &xfers[2], m: &msg); |
195 | spi_message_add_tail(t: &xfers[3], m: &msg); |
196 | break; |
197 | default: |
198 | return -EINVAL; |
199 | } |
200 | |
201 | ret = spi_sync(spi: adis->spi, message: &msg); |
202 | if (ret) { |
203 | dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n" , |
204 | reg, ret); |
205 | return ret; |
206 | } |
207 | |
208 | adis->current_page = page; |
209 | |
210 | switch (size) { |
211 | case 4: |
212 | *val = get_unaligned_be32(p: adis->rx); |
213 | break; |
214 | case 2: |
215 | *val = get_unaligned_be16(p: adis->rx + 2); |
216 | break; |
217 | } |
218 | |
219 | return ret; |
220 | } |
221 | EXPORT_SYMBOL_NS_GPL(__adis_read_reg, IIO_ADISLIB); |
222 | /** |
223 | * __adis_update_bits_base() - ADIS Update bits function - Unlocked version |
224 | * @adis: The adis device |
225 | * @reg: The address of the lower of the two registers |
226 | * @mask: Bitmask to change |
227 | * @val: Value to be written |
228 | * @size: Size of the register to update |
229 | * |
230 | * Updates the desired bits of @reg in accordance with @mask and @val. |
231 | */ |
232 | int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, |
233 | const u32 val, u8 size) |
234 | { |
235 | int ret; |
236 | u32 __val; |
237 | |
238 | ret = __adis_read_reg(adis, reg, &__val, size); |
239 | if (ret) |
240 | return ret; |
241 | |
242 | __val = (__val & ~mask) | (val & mask); |
243 | |
244 | return __adis_write_reg(adis, reg, __val, size); |
245 | } |
246 | EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB); |
247 | |
248 | #ifdef CONFIG_DEBUG_FS |
249 | |
250 | int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg, |
251 | unsigned int writeval, unsigned int *readval) |
252 | { |
253 | struct adis *adis = iio_device_get_drvdata(indio_dev); |
254 | |
255 | if (readval) { |
256 | u16 val16; |
257 | int ret; |
258 | |
259 | ret = adis_read_reg_16(adis, reg, val: &val16); |
260 | if (ret == 0) |
261 | *readval = val16; |
262 | |
263 | return ret; |
264 | } |
265 | |
266 | return adis_write_reg_16(adis, reg, val: writeval); |
267 | } |
268 | EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB); |
269 | |
270 | #endif |
271 | |
272 | /** |
273 | * __adis_enable_irq() - Enable or disable data ready IRQ (unlocked) |
274 | * @adis: The adis device |
275 | * @enable: Whether to enable the IRQ |
276 | * |
277 | * Returns 0 on success, negative error code otherwise |
278 | */ |
279 | int __adis_enable_irq(struct adis *adis, bool enable) |
280 | { |
281 | int ret; |
282 | u16 msc; |
283 | |
284 | if (adis->data->enable_irq) |
285 | return adis->data->enable_irq(adis, enable); |
286 | |
287 | if (adis->data->unmasked_drdy) { |
288 | if (enable) |
289 | enable_irq(irq: adis->spi->irq); |
290 | else |
291 | disable_irq(irq: adis->spi->irq); |
292 | |
293 | return 0; |
294 | } |
295 | |
296 | ret = __adis_read_reg_16(adis, reg: adis->data->msc_ctrl_reg, val: &msc); |
297 | if (ret) |
298 | return ret; |
299 | |
300 | msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; |
301 | msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; |
302 | if (enable) |
303 | msc |= ADIS_MSC_CTRL_DATA_RDY_EN; |
304 | else |
305 | msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; |
306 | |
307 | return __adis_write_reg_16(adis, reg: adis->data->msc_ctrl_reg, val: msc); |
308 | } |
309 | EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB); |
310 | |
311 | /** |
312 | * __adis_check_status() - Check the device for error conditions (unlocked) |
313 | * @adis: The adis device |
314 | * |
315 | * Returns 0 on success, a negative error code otherwise |
316 | */ |
317 | int __adis_check_status(struct adis *adis) |
318 | { |
319 | u16 status; |
320 | int ret; |
321 | int i; |
322 | |
323 | ret = __adis_read_reg_16(adis, reg: adis->data->diag_stat_reg, val: &status); |
324 | if (ret) |
325 | return ret; |
326 | |
327 | status &= adis->data->status_error_mask; |
328 | |
329 | if (status == 0) |
330 | return 0; |
331 | |
332 | for (i = 0; i < 16; ++i) { |
333 | if (status & BIT(i)) { |
334 | dev_err(&adis->spi->dev, "%s.\n" , |
335 | adis->data->status_error_msgs[i]); |
336 | } |
337 | } |
338 | |
339 | return -EIO; |
340 | } |
341 | EXPORT_SYMBOL_NS_GPL(__adis_check_status, IIO_ADISLIB); |
342 | |
343 | /** |
344 | * __adis_reset() - Reset the device (unlocked version) |
345 | * @adis: The adis device |
346 | * |
347 | * Returns 0 on success, a negative error code otherwise |
348 | */ |
349 | int __adis_reset(struct adis *adis) |
350 | { |
351 | int ret; |
352 | const struct adis_timeout *timeouts = adis->data->timeouts; |
353 | |
354 | ret = __adis_write_reg_8(adis, reg: adis->data->glob_cmd_reg, |
355 | ADIS_GLOB_CMD_SW_RESET); |
356 | if (ret) { |
357 | dev_err(&adis->spi->dev, "Failed to reset device: %d\n" , ret); |
358 | return ret; |
359 | } |
360 | |
361 | msleep(msecs: timeouts->sw_reset_ms); |
362 | |
363 | return 0; |
364 | } |
365 | EXPORT_SYMBOL_NS_GPL(__adis_reset, IIO_ADIS_LIB); |
366 | |
367 | static int adis_self_test(struct adis *adis) |
368 | { |
369 | int ret; |
370 | const struct adis_timeout *timeouts = adis->data->timeouts; |
371 | |
372 | ret = __adis_write_reg_16(adis, reg: adis->data->self_test_reg, |
373 | val: adis->data->self_test_mask); |
374 | if (ret) { |
375 | dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n" , |
376 | ret); |
377 | return ret; |
378 | } |
379 | |
380 | msleep(msecs: timeouts->self_test_ms); |
381 | |
382 | ret = __adis_check_status(adis); |
383 | |
384 | if (adis->data->self_test_no_autoclear) |
385 | __adis_write_reg_16(adis, reg: adis->data->self_test_reg, val: 0x00); |
386 | |
387 | return ret; |
388 | } |
389 | |
390 | /** |
391 | * __adis_initial_startup() - Device initial setup |
392 | * @adis: The adis device |
393 | * |
394 | * The function performs a HW reset via a reset pin that should be specified |
395 | * via GPIOLIB. If no pin is configured a SW reset will be performed. |
396 | * The RST pin for the ADIS devices should be configured as ACTIVE_LOW. |
397 | * |
398 | * After the self-test operation is performed, the function will also check |
399 | * that the product ID is as expected. This assumes that drivers providing |
400 | * 'prod_id_reg' will also provide the 'prod_id'. |
401 | * |
402 | * Returns 0 if the device is operational, a negative error code otherwise. |
403 | * |
404 | * This function should be called early on in the device initialization sequence |
405 | * to ensure that the device is in a sane and known state and that it is usable. |
406 | */ |
407 | int __adis_initial_startup(struct adis *adis) |
408 | { |
409 | const struct adis_timeout *timeouts = adis->data->timeouts; |
410 | struct gpio_desc *gpio; |
411 | u16 prod_id; |
412 | int ret; |
413 | |
414 | /* check if the device has rst pin low */ |
415 | gpio = devm_gpiod_get_optional(dev: &adis->spi->dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
416 | if (IS_ERR(ptr: gpio)) |
417 | return PTR_ERR(ptr: gpio); |
418 | |
419 | if (gpio) { |
420 | usleep_range(min: 10, max: 12); |
421 | /* bring device out of reset */ |
422 | gpiod_set_value_cansleep(desc: gpio, value: 0); |
423 | msleep(msecs: timeouts->reset_ms); |
424 | } else { |
425 | ret = __adis_reset(adis); |
426 | if (ret) |
427 | return ret; |
428 | } |
429 | |
430 | ret = adis_self_test(adis); |
431 | if (ret) |
432 | return ret; |
433 | |
434 | /* |
435 | * don't bother calling this if we can't unmask the IRQ as in this case |
436 | * the IRQ is most likely not yet requested and we will request it |
437 | * with 'IRQF_NO_AUTOEN' anyways. |
438 | */ |
439 | if (!adis->data->unmasked_drdy) |
440 | __adis_enable_irq(adis, false); |
441 | |
442 | if (!adis->data->prod_id_reg) |
443 | return 0; |
444 | |
445 | ret = adis_read_reg_16(adis, reg: adis->data->prod_id_reg, val: &prod_id); |
446 | if (ret) |
447 | return ret; |
448 | |
449 | if (prod_id != adis->data->prod_id) |
450 | dev_warn(&adis->spi->dev, |
451 | "Device ID(%u) and product ID(%u) do not match.\n" , |
452 | adis->data->prod_id, prod_id); |
453 | |
454 | return 0; |
455 | } |
456 | EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, IIO_ADISLIB); |
457 | |
458 | /** |
459 | * adis_single_conversion() - Performs a single sample conversion |
460 | * @indio_dev: The IIO device |
461 | * @chan: The IIO channel |
462 | * @error_mask: Mask for the error bit |
463 | * @val: Result of the conversion |
464 | * |
465 | * Returns IIO_VAL_INT on success, a negative error code otherwise. |
466 | * |
467 | * The function performs a single conversion on a given channel and post |
468 | * processes the value accordingly to the channel spec. If a error_mask is given |
469 | * the function will check if the mask is set in the returned raw value. If it |
470 | * is set the function will perform a self-check. If the device does not report |
471 | * a error bit in the channels raw value set error_mask to 0. |
472 | */ |
473 | int adis_single_conversion(struct iio_dev *indio_dev, |
474 | const struct iio_chan_spec *chan, |
475 | unsigned int error_mask, int *val) |
476 | { |
477 | struct adis *adis = iio_device_get_drvdata(indio_dev); |
478 | unsigned int uval; |
479 | int ret; |
480 | |
481 | mutex_lock(&adis->state_lock); |
482 | |
483 | ret = __adis_read_reg(adis, chan->address, &uval, |
484 | chan->scan_type.storagebits / 8); |
485 | if (ret) |
486 | goto err_unlock; |
487 | |
488 | if (uval & error_mask) { |
489 | ret = __adis_check_status(adis); |
490 | if (ret) |
491 | goto err_unlock; |
492 | } |
493 | |
494 | if (chan->scan_type.sign == 's') |
495 | *val = sign_extend32(value: uval, index: chan->scan_type.realbits - 1); |
496 | else |
497 | *val = uval & ((1 << chan->scan_type.realbits) - 1); |
498 | |
499 | ret = IIO_VAL_INT; |
500 | err_unlock: |
501 | mutex_unlock(lock: &adis->state_lock); |
502 | return ret; |
503 | } |
504 | EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB); |
505 | |
506 | /** |
507 | * adis_init() - Initialize adis device structure |
508 | * @adis: The adis device |
509 | * @indio_dev: The iio device |
510 | * @spi: The spi device |
511 | * @data: Chip specific data |
512 | * |
513 | * Returns 0 on success, a negative error code otherwise. |
514 | * |
515 | * This function must be called, before any other adis helper function may be |
516 | * called. |
517 | */ |
518 | int adis_init(struct adis *adis, struct iio_dev *indio_dev, |
519 | struct spi_device *spi, const struct adis_data *data) |
520 | { |
521 | if (!data || !data->timeouts) { |
522 | dev_err(&spi->dev, "No config data or timeouts not defined!\n" ); |
523 | return -EINVAL; |
524 | } |
525 | |
526 | mutex_init(&adis->state_lock); |
527 | adis->spi = spi; |
528 | adis->data = data; |
529 | iio_device_set_drvdata(indio_dev, data: adis); |
530 | |
531 | if (data->has_paging) { |
532 | /* Need to set the page before first read/write */ |
533 | adis->current_page = -1; |
534 | } else { |
535 | /* Page will always be 0 */ |
536 | adis->current_page = 0; |
537 | } |
538 | |
539 | return 0; |
540 | } |
541 | EXPORT_SYMBOL_NS_GPL(adis_init, IIO_ADISLIB); |
542 | |
543 | MODULE_LICENSE("GPL" ); |
544 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>" ); |
545 | MODULE_DESCRIPTION("Common library code for ADIS16XXX devices" ); |
546 | |