.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * ADIS16133/ADIS16135/ADIS16136 gyroscope driver |
---|
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. |
---|
8 | 7 | */ |
---|
9 | 8 | |
---|
10 | 9 | #include <linux/interrupt.h> |
---|
.. | .. |
---|
60 | 59 | struct adis16136_chip_info { |
---|
61 | 60 | unsigned int precision; |
---|
62 | 61 | unsigned int fullscale; |
---|
| 62 | + const struct adis_data adis_data; |
---|
63 | 63 | }; |
---|
64 | 64 | |
---|
65 | 65 | struct adis16136 { |
---|
.. | .. |
---|
81 | 81 | |
---|
82 | 82 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM, |
---|
83 | 83 | &serial); |
---|
84 | | - if (ret < 0) |
---|
| 84 | + if (ret) |
---|
85 | 85 | return ret; |
---|
86 | 86 | |
---|
87 | 87 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1); |
---|
88 | | - if (ret < 0) |
---|
| 88 | + if (ret) |
---|
89 | 89 | return ret; |
---|
90 | 90 | |
---|
91 | 91 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2); |
---|
92 | | - if (ret < 0) |
---|
| 92 | + if (ret) |
---|
93 | 93 | return ret; |
---|
94 | 94 | |
---|
95 | 95 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3); |
---|
96 | | - if (ret < 0) |
---|
| 96 | + if (ret) |
---|
97 | 97 | return ret; |
---|
98 | 98 | |
---|
99 | 99 | len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2, |
---|
.. | .. |
---|
117 | 117 | |
---|
118 | 118 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, |
---|
119 | 119 | &prod_id); |
---|
120 | | - if (ret < 0) |
---|
| 120 | + if (ret) |
---|
121 | 121 | return ret; |
---|
122 | 122 | |
---|
123 | 123 | *val = prod_id; |
---|
.. | .. |
---|
135 | 135 | |
---|
136 | 136 | ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT, |
---|
137 | 137 | &flash_count); |
---|
138 | | - if (ret < 0) |
---|
| 138 | + if (ret) |
---|
139 | 139 | return ret; |
---|
140 | 140 | |
---|
141 | 141 | *val = flash_count; |
---|
.. | .. |
---|
148 | 148 | static int adis16136_debugfs_init(struct iio_dev *indio_dev) |
---|
149 | 149 | { |
---|
150 | 150 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
---|
| 151 | + struct dentry *d = iio_get_debugfs_dentry(indio_dev); |
---|
151 | 152 | |
---|
152 | 153 | debugfs_create_file_unsafe("serial_number", 0400, |
---|
153 | | - indio_dev->debugfs_dentry, adis16136, |
---|
154 | | - &adis16136_serial_fops); |
---|
| 154 | + d, adis16136, &adis16136_serial_fops); |
---|
155 | 155 | debugfs_create_file_unsafe("product_id", 0400, |
---|
156 | | - indio_dev->debugfs_dentry, |
---|
157 | | - adis16136, &adis16136_product_id_fops); |
---|
| 156 | + d, adis16136, &adis16136_product_id_fops); |
---|
158 | 157 | debugfs_create_file_unsafe("flash_count", 0400, |
---|
159 | | - indio_dev->debugfs_dentry, |
---|
160 | | - adis16136, &adis16136_flash_count_fops); |
---|
| 158 | + d, adis16136, &adis16136_flash_count_fops); |
---|
161 | 159 | |
---|
162 | 160 | return 0; |
---|
163 | 161 | } |
---|
.. | .. |
---|
186 | 184 | return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, t); |
---|
187 | 185 | } |
---|
188 | 186 | |
---|
189 | | -static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) |
---|
| 187 | +static int __adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) |
---|
190 | 188 | { |
---|
191 | 189 | uint16_t t; |
---|
192 | 190 | int ret; |
---|
193 | 191 | |
---|
194 | | - ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); |
---|
195 | | - if (ret < 0) |
---|
| 192 | + ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); |
---|
| 193 | + if (ret) |
---|
196 | 194 | return ret; |
---|
197 | 195 | |
---|
198 | 196 | *freq = 32768 / (t + 1); |
---|
.. | .. |
---|
225 | 223 | { |
---|
226 | 224 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
---|
227 | 225 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
---|
| 226 | + struct mutex *slock = &adis16136->adis.state_lock; |
---|
228 | 227 | unsigned int freq; |
---|
229 | 228 | int ret; |
---|
230 | 229 | |
---|
231 | | - ret = adis16136_get_freq(adis16136, &freq); |
---|
232 | | - if (ret < 0) |
---|
| 230 | + mutex_lock(slock); |
---|
| 231 | + ret = __adis16136_get_freq(adis16136, &freq); |
---|
| 232 | + mutex_unlock(slock); |
---|
| 233 | + if (ret) |
---|
233 | 234 | return ret; |
---|
234 | 235 | |
---|
235 | 236 | return sprintf(buf, "%d\n", freq); |
---|
.. | .. |
---|
253 | 254 | static int adis16136_set_filter(struct iio_dev *indio_dev, int val) |
---|
254 | 255 | { |
---|
255 | 256 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
---|
| 257 | + struct mutex *slock = &adis16136->adis.state_lock; |
---|
256 | 258 | unsigned int freq; |
---|
257 | 259 | int i, ret; |
---|
258 | 260 | |
---|
259 | | - ret = adis16136_get_freq(adis16136, &freq); |
---|
260 | | - if (ret < 0) |
---|
261 | | - return ret; |
---|
| 261 | + mutex_lock(slock); |
---|
| 262 | + ret = __adis16136_get_freq(adis16136, &freq); |
---|
| 263 | + if (ret) |
---|
| 264 | + goto out_unlock; |
---|
262 | 265 | |
---|
263 | 266 | for (i = ARRAY_SIZE(adis16136_3db_divisors) - 1; i >= 1; i--) { |
---|
264 | 267 | if (freq / adis16136_3db_divisors[i] >= val) |
---|
265 | 268 | break; |
---|
266 | 269 | } |
---|
267 | 270 | |
---|
268 | | - return adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); |
---|
| 271 | + ret = __adis_write_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, i); |
---|
| 272 | +out_unlock: |
---|
| 273 | + mutex_unlock(slock); |
---|
| 274 | + |
---|
| 275 | + return ret; |
---|
269 | 276 | } |
---|
270 | 277 | |
---|
271 | 278 | static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) |
---|
272 | 279 | { |
---|
273 | 280 | struct adis16136 *adis16136 = iio_priv(indio_dev); |
---|
| 281 | + struct mutex *slock = &adis16136->adis.state_lock; |
---|
274 | 282 | unsigned int freq; |
---|
275 | 283 | uint16_t val16; |
---|
276 | 284 | int ret; |
---|
277 | 285 | |
---|
278 | | - mutex_lock(&indio_dev->mlock); |
---|
| 286 | + mutex_lock(slock); |
---|
279 | 287 | |
---|
280 | | - ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); |
---|
281 | | - if (ret < 0) |
---|
| 288 | + ret = __adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, |
---|
| 289 | + &val16); |
---|
| 290 | + if (ret) |
---|
282 | 291 | goto err_unlock; |
---|
283 | 292 | |
---|
284 | | - ret = adis16136_get_freq(adis16136, &freq); |
---|
285 | | - if (ret < 0) |
---|
| 293 | + ret = __adis16136_get_freq(adis16136, &freq); |
---|
| 294 | + if (ret) |
---|
286 | 295 | goto err_unlock; |
---|
287 | 296 | |
---|
288 | 297 | *val = freq / adis16136_3db_divisors[val16 & 0x07]; |
---|
289 | 298 | |
---|
290 | 299 | err_unlock: |
---|
291 | | - mutex_unlock(&indio_dev->mlock); |
---|
| 300 | + mutex_unlock(slock); |
---|
292 | 301 | |
---|
293 | 302 | return ret ? ret : IIO_VAL_INT; |
---|
294 | 303 | } |
---|
.. | .. |
---|
319 | 328 | case IIO_CHAN_INFO_CALIBBIAS: |
---|
320 | 329 | ret = adis_read_reg_32(&adis16136->adis, |
---|
321 | 330 | ADIS16136_REG_GYRO_OFF2, &val32); |
---|
322 | | - if (ret < 0) |
---|
| 331 | + if (ret) |
---|
323 | 332 | return ret; |
---|
324 | 333 | |
---|
325 | 334 | *val = sign_extend32(val32, 31); |
---|
.. | .. |
---|
455 | 464 | [ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL] = "Flash checksum error", |
---|
456 | 465 | }; |
---|
457 | 466 | |
---|
458 | | -static const struct adis_data adis16136_data = { |
---|
459 | | - .diag_stat_reg = ADIS16136_REG_DIAG_STAT, |
---|
460 | | - .glob_cmd_reg = ADIS16136_REG_GLOB_CMD, |
---|
461 | | - .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, |
---|
462 | | - |
---|
463 | | - .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, |
---|
464 | | - .startup_delay = 80, |
---|
465 | | - |
---|
466 | | - .read_delay = 10, |
---|
467 | | - .write_delay = 10, |
---|
468 | | - |
---|
469 | | - .status_error_msgs = adis16136_status_error_msgs, |
---|
470 | | - .status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) | |
---|
471 | | - BIT(ADIS16136_DIAG_STAT_SPI_FAIL) | |
---|
472 | | - BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) | |
---|
473 | | - BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL), |
---|
474 | | -}; |
---|
| 467 | +#define ADIS16136_DATA(_timeouts) \ |
---|
| 468 | +{ \ |
---|
| 469 | + .diag_stat_reg = ADIS16136_REG_DIAG_STAT, \ |
---|
| 470 | + .glob_cmd_reg = ADIS16136_REG_GLOB_CMD, \ |
---|
| 471 | + .msc_ctrl_reg = ADIS16136_REG_MSC_CTRL, \ |
---|
| 472 | + .self_test_reg = ADIS16136_REG_MSC_CTRL, \ |
---|
| 473 | + .self_test_mask = ADIS16136_MSC_CTRL_SELF_TEST, \ |
---|
| 474 | + .read_delay = 10, \ |
---|
| 475 | + .write_delay = 10, \ |
---|
| 476 | + .status_error_msgs = adis16136_status_error_msgs, \ |
---|
| 477 | + .status_error_mask = BIT(ADIS16136_DIAG_STAT_FLASH_UPDATE_FAIL) | \ |
---|
| 478 | + BIT(ADIS16136_DIAG_STAT_SPI_FAIL) | \ |
---|
| 479 | + BIT(ADIS16136_DIAG_STAT_SELF_TEST_FAIL) | \ |
---|
| 480 | + BIT(ADIS16136_DIAG_STAT_FLASH_CHKSUM_FAIL), \ |
---|
| 481 | + .timeouts = (_timeouts), \ |
---|
| 482 | +} |
---|
475 | 483 | |
---|
476 | 484 | enum adis16136_id { |
---|
477 | 485 | ID_ADIS16133, |
---|
.. | .. |
---|
480 | 488 | ID_ADIS16137, |
---|
481 | 489 | }; |
---|
482 | 490 | |
---|
| 491 | +static const struct adis_timeout adis16133_timeouts = { |
---|
| 492 | + .reset_ms = 75, |
---|
| 493 | + .sw_reset_ms = 75, |
---|
| 494 | + .self_test_ms = 50, |
---|
| 495 | +}; |
---|
| 496 | + |
---|
| 497 | +static const struct adis_timeout adis16136_timeouts = { |
---|
| 498 | + .reset_ms = 128, |
---|
| 499 | + .sw_reset_ms = 75, |
---|
| 500 | + .self_test_ms = 245, |
---|
| 501 | +}; |
---|
| 502 | + |
---|
483 | 503 | static const struct adis16136_chip_info adis16136_chip_info[] = { |
---|
484 | 504 | [ID_ADIS16133] = { |
---|
485 | 505 | .precision = IIO_DEGREE_TO_RAD(1200), |
---|
486 | 506 | .fullscale = 24000, |
---|
| 507 | + .adis_data = ADIS16136_DATA(&adis16133_timeouts), |
---|
487 | 508 | }, |
---|
488 | 509 | [ID_ADIS16135] = { |
---|
489 | 510 | .precision = IIO_DEGREE_TO_RAD(300), |
---|
490 | 511 | .fullscale = 24000, |
---|
| 512 | + .adis_data = ADIS16136_DATA(&adis16133_timeouts), |
---|
491 | 513 | }, |
---|
492 | 514 | [ID_ADIS16136] = { |
---|
493 | 515 | .precision = IIO_DEGREE_TO_RAD(450), |
---|
494 | 516 | .fullscale = 24623, |
---|
| 517 | + .adis_data = ADIS16136_DATA(&adis16136_timeouts), |
---|
495 | 518 | }, |
---|
496 | 519 | [ID_ADIS16137] = { |
---|
497 | 520 | .precision = IIO_DEGREE_TO_RAD(1000), |
---|
498 | 521 | .fullscale = 24609, |
---|
| 522 | + .adis_data = ADIS16136_DATA(&adis16136_timeouts), |
---|
499 | 523 | }, |
---|
500 | 524 | }; |
---|
| 525 | + |
---|
| 526 | +static void adis16136_stop(void *data) |
---|
| 527 | +{ |
---|
| 528 | + adis16136_stop_device(data); |
---|
| 529 | +} |
---|
501 | 530 | |
---|
502 | 531 | static int adis16136_probe(struct spi_device *spi) |
---|
503 | 532 | { |
---|
504 | 533 | const struct spi_device_id *id = spi_get_device_id(spi); |
---|
505 | 534 | struct adis16136 *adis16136; |
---|
506 | 535 | struct iio_dev *indio_dev; |
---|
| 536 | + const struct adis_data *adis16136_data; |
---|
507 | 537 | int ret; |
---|
508 | 538 | |
---|
509 | 539 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16136)); |
---|
.. | .. |
---|
515 | 545 | adis16136 = iio_priv(indio_dev); |
---|
516 | 546 | |
---|
517 | 547 | adis16136->chip_info = &adis16136_chip_info[id->driver_data]; |
---|
518 | | - indio_dev->dev.parent = &spi->dev; |
---|
519 | 548 | indio_dev->name = spi_get_device_id(spi)->name; |
---|
520 | 549 | indio_dev->channels = adis16136_channels; |
---|
521 | 550 | indio_dev->num_channels = ARRAY_SIZE(adis16136_channels); |
---|
522 | 551 | indio_dev->info = &adis16136_info; |
---|
523 | 552 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
524 | 553 | |
---|
525 | | - ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data); |
---|
| 554 | + adis16136_data = &adis16136->chip_info->adis_data; |
---|
| 555 | + |
---|
| 556 | + ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data); |
---|
526 | 557 | if (ret) |
---|
527 | 558 | return ret; |
---|
528 | 559 | |
---|
529 | | - ret = adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL); |
---|
| 560 | + ret = devm_adis_setup_buffer_and_trigger(&adis16136->adis, indio_dev, NULL); |
---|
530 | 561 | if (ret) |
---|
531 | 562 | return ret; |
---|
532 | 563 | |
---|
533 | 564 | ret = adis16136_initial_setup(indio_dev); |
---|
534 | 565 | if (ret) |
---|
535 | | - goto error_cleanup_buffer; |
---|
| 566 | + return ret; |
---|
536 | 567 | |
---|
537 | | - ret = iio_device_register(indio_dev); |
---|
| 568 | + ret = devm_add_action_or_reset(&spi->dev, adis16136_stop, indio_dev); |
---|
538 | 569 | if (ret) |
---|
539 | | - goto error_stop_device; |
---|
| 570 | + return ret; |
---|
| 571 | + |
---|
| 572 | + ret = devm_iio_device_register(&spi->dev, indio_dev); |
---|
| 573 | + if (ret) |
---|
| 574 | + return ret; |
---|
540 | 575 | |
---|
541 | 576 | adis16136_debugfs_init(indio_dev); |
---|
542 | | - |
---|
543 | | - return 0; |
---|
544 | | - |
---|
545 | | -error_stop_device: |
---|
546 | | - adis16136_stop_device(indio_dev); |
---|
547 | | -error_cleanup_buffer: |
---|
548 | | - adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); |
---|
549 | | - return ret; |
---|
550 | | -} |
---|
551 | | - |
---|
552 | | -static int adis16136_remove(struct spi_device *spi) |
---|
553 | | -{ |
---|
554 | | - struct iio_dev *indio_dev = spi_get_drvdata(spi); |
---|
555 | | - struct adis16136 *adis16136 = iio_priv(indio_dev); |
---|
556 | | - |
---|
557 | | - iio_device_unregister(indio_dev); |
---|
558 | | - adis16136_stop_device(indio_dev); |
---|
559 | | - |
---|
560 | | - adis_cleanup_buffer_and_trigger(&adis16136->adis, indio_dev); |
---|
561 | 577 | |
---|
562 | 578 | return 0; |
---|
563 | 579 | } |
---|
.. | .. |
---|
577 | 593 | }, |
---|
578 | 594 | .id_table = adis16136_ids, |
---|
579 | 595 | .probe = adis16136_probe, |
---|
580 | | - .remove = adis16136_remove, |
---|
581 | 596 | }; |
---|
582 | 597 | module_spi_driver(adis16136_driver); |
---|
583 | 598 | |
---|
584 | 599 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
---|
585 | 600 | MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver"); |
---|
586 | 601 | MODULE_LICENSE("GPL v2"); |
---|
| 602 | +MODULE_IMPORT_NS(IIO_ADISLIB); |
---|