| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ad2s1210.c support for the ADI Resolver to Digital Converters: AD2S1210 |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2010-2010 Analog Devices Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 8 | | - * published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | #include <linux/types.h> |
|---|
| 12 | 8 | #include <linux/mutex.h> |
|---|
| .. | .. |
|---|
| 15 | 11 | #include <linux/slab.h> |
|---|
| 16 | 12 | #include <linux/sysfs.h> |
|---|
| 17 | 13 | #include <linux/delay.h> |
|---|
| 18 | | -#include <linux/gpio.h> |
|---|
| 14 | +#include <linux/gpio/consumer.h> |
|---|
| 19 | 15 | #include <linux/module.h> |
|---|
| 20 | 16 | |
|---|
| 21 | 17 | #include <linux/iio/iio.h> |
|---|
| 22 | 18 | #include <linux/iio/sysfs.h> |
|---|
| 23 | | -#include "ad2s1210.h" |
|---|
| 24 | 19 | |
|---|
| 25 | 20 | #define DRV_NAME "ad2s1210" |
|---|
| 26 | 21 | |
|---|
| .. | .. |
|---|
| 67 | 62 | MOD_RESERVED, |
|---|
| 68 | 63 | }; |
|---|
| 69 | 64 | |
|---|
| 65 | +enum ad2s1210_gpios { |
|---|
| 66 | + AD2S1210_SAMPLE, |
|---|
| 67 | + AD2S1210_A0, |
|---|
| 68 | + AD2S1210_A1, |
|---|
| 69 | + AD2S1210_RES0, |
|---|
| 70 | + AD2S1210_RES1, |
|---|
| 71 | +}; |
|---|
| 72 | + |
|---|
| 73 | +struct ad2s1210_gpio { |
|---|
| 74 | + const char *name; |
|---|
| 75 | + unsigned long flags; |
|---|
| 76 | +}; |
|---|
| 77 | + |
|---|
| 78 | +static const struct ad2s1210_gpio gpios[] = { |
|---|
| 79 | + [AD2S1210_SAMPLE] = { .name = "adi,sample", .flags = GPIOD_OUT_LOW }, |
|---|
| 80 | + [AD2S1210_A0] = { .name = "adi,a0", .flags = GPIOD_OUT_LOW }, |
|---|
| 81 | + [AD2S1210_A1] = { .name = "adi,a1", .flags = GPIOD_OUT_LOW }, |
|---|
| 82 | + [AD2S1210_RES0] = { .name = "adi,res0", .flags = GPIOD_OUT_LOW }, |
|---|
| 83 | + [AD2S1210_RES1] = { .name = "adi,res1", .flags = GPIOD_OUT_LOW }, |
|---|
| 84 | +}; |
|---|
| 85 | + |
|---|
| 70 | 86 | static const unsigned int ad2s1210_resolution_value[] = { 10, 12, 14, 16 }; |
|---|
| 71 | 87 | |
|---|
| 72 | 88 | struct ad2s1210_state { |
|---|
| 73 | | - const struct ad2s1210_platform_data *pdata; |
|---|
| 74 | 89 | struct mutex lock; |
|---|
| 75 | 90 | struct spi_device *sdev; |
|---|
| 91 | + struct gpio_desc *gpios[5]; |
|---|
| 76 | 92 | unsigned int fclkin; |
|---|
| 77 | 93 | unsigned int fexcit; |
|---|
| 78 | 94 | bool hysteresis; |
|---|
| .. | .. |
|---|
| 85 | 101 | static const int ad2s1210_mode_vals[4][2] = { |
|---|
| 86 | 102 | [MOD_POS] = { 0, 0 }, |
|---|
| 87 | 103 | [MOD_VEL] = { 0, 1 }, |
|---|
| 88 | | - [MOD_CONFIG] = { 1, 0 }, |
|---|
| 104 | + [MOD_CONFIG] = { 1, 1 }, |
|---|
| 89 | 105 | }; |
|---|
| 90 | 106 | |
|---|
| 91 | 107 | static inline void ad2s1210_set_mode(enum ad2s1210_mode mode, |
|---|
| 92 | 108 | struct ad2s1210_state *st) |
|---|
| 93 | 109 | { |
|---|
| 94 | | - gpio_set_value(st->pdata->a[0], ad2s1210_mode_vals[mode][0]); |
|---|
| 95 | | - gpio_set_value(st->pdata->a[1], ad2s1210_mode_vals[mode][1]); |
|---|
| 110 | + gpiod_set_value(st->gpios[AD2S1210_A0], ad2s1210_mode_vals[mode][0]); |
|---|
| 111 | + gpiod_set_value(st->gpios[AD2S1210_A1], ad2s1210_mode_vals[mode][1]); |
|---|
| 96 | 112 | st->mode = mode; |
|---|
| 97 | 113 | } |
|---|
| 98 | 114 | |
|---|
| .. | .. |
|---|
| 157 | 173 | return ad2s1210_config_write(st, fcw); |
|---|
| 158 | 174 | } |
|---|
| 159 | 175 | |
|---|
| 160 | | -static unsigned char ad2s1210_read_resolution_pin(struct ad2s1210_state *st) |
|---|
| 161 | | -{ |
|---|
| 162 | | - int resolution = (gpio_get_value(st->pdata->res[0]) << 1) | |
|---|
| 163 | | - gpio_get_value(st->pdata->res[1]); |
|---|
| 164 | | - |
|---|
| 165 | | - return ad2s1210_resolution_value[resolution]; |
|---|
| 166 | | -} |
|---|
| 167 | | - |
|---|
| 168 | 176 | static const int ad2s1210_res_pins[4][2] = { |
|---|
| 169 | 177 | { 0, 0 }, {0, 1}, {1, 0}, {1, 1} |
|---|
| 170 | 178 | }; |
|---|
| 171 | 179 | |
|---|
| 172 | 180 | static inline void ad2s1210_set_resolution_pin(struct ad2s1210_state *st) |
|---|
| 173 | 181 | { |
|---|
| 174 | | - gpio_set_value(st->pdata->res[0], |
|---|
| 175 | | - ad2s1210_res_pins[(st->resolution - 10) / 2][0]); |
|---|
| 176 | | - gpio_set_value(st->pdata->res[1], |
|---|
| 177 | | - ad2s1210_res_pins[(st->resolution - 10) / 2][1]); |
|---|
| 182 | + gpiod_set_value(st->gpios[AD2S1210_RES0], |
|---|
| 183 | + ad2s1210_res_pins[(st->resolution - 10) / 2][0]); |
|---|
| 184 | + gpiod_set_value(st->gpios[AD2S1210_RES1], |
|---|
| 185 | + ad2s1210_res_pins[(st->resolution - 10) / 2][1]); |
|---|
| 178 | 186 | } |
|---|
| 179 | 187 | |
|---|
| 180 | 188 | static inline int ad2s1210_soft_reset(struct ad2s1210_state *st) |
|---|
| .. | .. |
|---|
| 308 | 316 | "ad2s1210: write control register fail\n"); |
|---|
| 309 | 317 | goto error_ret; |
|---|
| 310 | 318 | } |
|---|
| 311 | | - st->resolution |
|---|
| 312 | | - = ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; |
|---|
| 313 | | - if (st->pdata->gpioin) { |
|---|
| 314 | | - data = ad2s1210_read_resolution_pin(st); |
|---|
| 315 | | - if (data != st->resolution) |
|---|
| 316 | | - dev_warn(dev, "ad2s1210: resolution settings not match\n"); |
|---|
| 317 | | - } else { |
|---|
| 318 | | - ad2s1210_set_resolution_pin(st); |
|---|
| 319 | | - } |
|---|
| 319 | + st->resolution = |
|---|
| 320 | + ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; |
|---|
| 321 | + ad2s1210_set_resolution_pin(st); |
|---|
| 320 | 322 | ret = len; |
|---|
| 321 | 323 | st->hysteresis = !!(data & AD2S1210_ENABLE_HYSTERESIS); |
|---|
| 322 | 324 | |
|---|
| .. | .. |
|---|
| 370 | 372 | dev_err(dev, "ad2s1210: setting resolution fail\n"); |
|---|
| 371 | 373 | goto error_ret; |
|---|
| 372 | 374 | } |
|---|
| 373 | | - st->resolution |
|---|
| 374 | | - = ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; |
|---|
| 375 | | - if (st->pdata->gpioin) { |
|---|
| 376 | | - data = ad2s1210_read_resolution_pin(st); |
|---|
| 377 | | - if (data != st->resolution) |
|---|
| 378 | | - dev_warn(dev, "ad2s1210: resolution settings not match\n"); |
|---|
| 379 | | - } else { |
|---|
| 380 | | - ad2s1210_set_resolution_pin(st); |
|---|
| 381 | | - } |
|---|
| 375 | + st->resolution = |
|---|
| 376 | + ad2s1210_resolution_value[data & AD2S1210_SET_RESOLUTION]; |
|---|
| 377 | + ad2s1210_set_resolution_pin(st); |
|---|
| 382 | 378 | ret = len; |
|---|
| 383 | 379 | error_ret: |
|---|
| 384 | 380 | mutex_unlock(&st->lock); |
|---|
| .. | .. |
|---|
| 408 | 404 | int ret; |
|---|
| 409 | 405 | |
|---|
| 410 | 406 | mutex_lock(&st->lock); |
|---|
| 411 | | - gpio_set_value(st->pdata->sample, 0); |
|---|
| 407 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 0); |
|---|
| 412 | 408 | /* delay (2 * tck + 20) nano seconds */ |
|---|
| 413 | 409 | udelay(1); |
|---|
| 414 | | - gpio_set_value(st->pdata->sample, 1); |
|---|
| 410 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 1); |
|---|
| 415 | 411 | ret = ad2s1210_config_read(st, AD2S1210_REG_FAULT); |
|---|
| 416 | 412 | if (ret < 0) |
|---|
| 417 | 413 | goto error_ret; |
|---|
| 418 | | - gpio_set_value(st->pdata->sample, 0); |
|---|
| 419 | | - gpio_set_value(st->pdata->sample, 1); |
|---|
| 414 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 0); |
|---|
| 415 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 1); |
|---|
| 420 | 416 | error_ret: |
|---|
| 421 | 417 | mutex_unlock(&st->lock); |
|---|
| 422 | 418 | |
|---|
| .. | .. |
|---|
| 473 | 469 | s16 vel; |
|---|
| 474 | 470 | |
|---|
| 475 | 471 | mutex_lock(&st->lock); |
|---|
| 476 | | - gpio_set_value(st->pdata->sample, 0); |
|---|
| 472 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 0); |
|---|
| 477 | 473 | /* delay (6 * tck + 20) nano seconds */ |
|---|
| 478 | 474 | udelay(1); |
|---|
| 479 | 475 | |
|---|
| .. | .. |
|---|
| 519 | 515 | } |
|---|
| 520 | 516 | |
|---|
| 521 | 517 | error_ret: |
|---|
| 522 | | - gpio_set_value(st->pdata->sample, 1); |
|---|
| 518 | + gpiod_set_value(st->gpios[AD2S1210_SAMPLE], 1); |
|---|
| 523 | 519 | /* delay (2 * tck + 20) nano seconds */ |
|---|
| 524 | 520 | udelay(1); |
|---|
| 525 | 521 | mutex_unlock(&st->lock); |
|---|
| .. | .. |
|---|
| 599 | 595 | int ret; |
|---|
| 600 | 596 | |
|---|
| 601 | 597 | mutex_lock(&st->lock); |
|---|
| 602 | | - if (st->pdata->gpioin) |
|---|
| 603 | | - st->resolution = ad2s1210_read_resolution_pin(st); |
|---|
| 604 | | - else |
|---|
| 605 | | - ad2s1210_set_resolution_pin(st); |
|---|
| 598 | + ad2s1210_set_resolution_pin(st); |
|---|
| 606 | 599 | |
|---|
| 607 | 600 | ret = ad2s1210_config_write(st, AD2S1210_REG_CONTROL); |
|---|
| 608 | 601 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 637 | 630 | |
|---|
| 638 | 631 | static int ad2s1210_setup_gpios(struct ad2s1210_state *st) |
|---|
| 639 | 632 | { |
|---|
| 640 | | - unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT; |
|---|
| 641 | | - struct gpio ad2s1210_gpios[] = { |
|---|
| 642 | | - { st->pdata->sample, GPIOF_DIR_IN, "sample" }, |
|---|
| 643 | | - { st->pdata->a[0], flags, "a0" }, |
|---|
| 644 | | - { st->pdata->a[1], flags, "a1" }, |
|---|
| 645 | | - { st->pdata->res[0], flags, "res0" }, |
|---|
| 646 | | - { st->pdata->res[0], flags, "res1" }, |
|---|
| 647 | | - }; |
|---|
| 633 | + struct spi_device *spi = st->sdev; |
|---|
| 634 | + int i, ret; |
|---|
| 648 | 635 | |
|---|
| 649 | | - return gpio_request_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios)); |
|---|
| 650 | | -} |
|---|
| 636 | + for (i = 0; i < ARRAY_SIZE(gpios); i++) { |
|---|
| 637 | + st->gpios[i] = devm_gpiod_get(&spi->dev, gpios[i].name, |
|---|
| 638 | + gpios[i].flags); |
|---|
| 639 | + if (IS_ERR(st->gpios[i])) { |
|---|
| 640 | + ret = PTR_ERR(st->gpios[i]); |
|---|
| 641 | + dev_err(&spi->dev, |
|---|
| 642 | + "ad2s1210: failed to request %s GPIO: %d\n", |
|---|
| 643 | + gpios[i].name, ret); |
|---|
| 644 | + return ret; |
|---|
| 645 | + } |
|---|
| 646 | + } |
|---|
| 651 | 647 | |
|---|
| 652 | | -static void ad2s1210_free_gpios(struct ad2s1210_state *st) |
|---|
| 653 | | -{ |
|---|
| 654 | | - unsigned long flags = st->pdata->gpioin ? GPIOF_DIR_IN : GPIOF_DIR_OUT; |
|---|
| 655 | | - struct gpio ad2s1210_gpios[] = { |
|---|
| 656 | | - { st->pdata->sample, GPIOF_DIR_IN, "sample" }, |
|---|
| 657 | | - { st->pdata->a[0], flags, "a0" }, |
|---|
| 658 | | - { st->pdata->a[1], flags, "a1" }, |
|---|
| 659 | | - { st->pdata->res[0], flags, "res0" }, |
|---|
| 660 | | - { st->pdata->res[0], flags, "res1" }, |
|---|
| 661 | | - }; |
|---|
| 662 | | - |
|---|
| 663 | | - gpio_free_array(ad2s1210_gpios, ARRAY_SIZE(ad2s1210_gpios)); |
|---|
| 648 | + return 0; |
|---|
| 664 | 649 | } |
|---|
| 665 | 650 | |
|---|
| 666 | 651 | static int ad2s1210_probe(struct spi_device *spi) |
|---|
| .. | .. |
|---|
| 669 | 654 | struct ad2s1210_state *st; |
|---|
| 670 | 655 | int ret; |
|---|
| 671 | 656 | |
|---|
| 672 | | - if (!spi->dev.platform_data) |
|---|
| 673 | | - return -EINVAL; |
|---|
| 674 | | - |
|---|
| 675 | 657 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
|---|
| 676 | 658 | if (!indio_dev) |
|---|
| 677 | 659 | return -ENOMEM; |
|---|
| 678 | 660 | st = iio_priv(indio_dev); |
|---|
| 679 | | - st->pdata = spi->dev.platform_data; |
|---|
| 680 | 661 | ret = ad2s1210_setup_gpios(st); |
|---|
| 681 | 662 | if (ret < 0) |
|---|
| 682 | 663 | return ret; |
|---|
| .. | .. |
|---|
| 690 | 671 | st->resolution = 12; |
|---|
| 691 | 672 | st->fexcit = AD2S1210_DEF_EXCIT; |
|---|
| 692 | 673 | |
|---|
| 693 | | - indio_dev->dev.parent = &spi->dev; |
|---|
| 694 | 674 | indio_dev->info = &ad2s1210_info; |
|---|
| 695 | 675 | indio_dev->modes = INDIO_DIRECT_MODE; |
|---|
| 696 | 676 | indio_dev->channels = ad2s1210_channels; |
|---|
| 697 | 677 | indio_dev->num_channels = ARRAY_SIZE(ad2s1210_channels); |
|---|
| 698 | 678 | indio_dev->name = spi_get_device_id(spi)->name; |
|---|
| 699 | 679 | |
|---|
| 700 | | - ret = iio_device_register(indio_dev); |
|---|
| 680 | + ret = devm_iio_device_register(&spi->dev, indio_dev); |
|---|
| 701 | 681 | if (ret) |
|---|
| 702 | | - goto error_free_gpios; |
|---|
| 682 | + return ret; |
|---|
| 703 | 683 | |
|---|
| 704 | 684 | st->fclkin = spi->max_speed_hz; |
|---|
| 705 | 685 | spi->mode = SPI_MODE_3; |
|---|
| .. | .. |
|---|
| 707 | 687 | ad2s1210_initial(st); |
|---|
| 708 | 688 | |
|---|
| 709 | 689 | return 0; |
|---|
| 710 | | - |
|---|
| 711 | | -error_free_gpios: |
|---|
| 712 | | - ad2s1210_free_gpios(st); |
|---|
| 713 | | - return ret; |
|---|
| 714 | 690 | } |
|---|
| 715 | 691 | |
|---|
| 716 | | -static int ad2s1210_remove(struct spi_device *spi) |
|---|
| 717 | | -{ |
|---|
| 718 | | - struct iio_dev *indio_dev = spi_get_drvdata(spi); |
|---|
| 719 | | - |
|---|
| 720 | | - iio_device_unregister(indio_dev); |
|---|
| 721 | | - ad2s1210_free_gpios(iio_priv(indio_dev)); |
|---|
| 722 | | - |
|---|
| 723 | | - return 0; |
|---|
| 724 | | -} |
|---|
| 692 | +static const struct of_device_id ad2s1210_of_match[] = { |
|---|
| 693 | + { .compatible = "adi,ad2s1210", }, |
|---|
| 694 | + { } |
|---|
| 695 | +}; |
|---|
| 696 | +MODULE_DEVICE_TABLE(of, ad2s1210_of_match); |
|---|
| 725 | 697 | |
|---|
| 726 | 698 | static const struct spi_device_id ad2s1210_id[] = { |
|---|
| 727 | 699 | { "ad2s1210" }, |
|---|
| .. | .. |
|---|
| 732 | 704 | static struct spi_driver ad2s1210_driver = { |
|---|
| 733 | 705 | .driver = { |
|---|
| 734 | 706 | .name = DRV_NAME, |
|---|
| 707 | + .of_match_table = of_match_ptr(ad2s1210_of_match), |
|---|
| 735 | 708 | }, |
|---|
| 736 | 709 | .probe = ad2s1210_probe, |
|---|
| 737 | | - .remove = ad2s1210_remove, |
|---|
| 738 | 710 | .id_table = ad2s1210_id, |
|---|
| 739 | 711 | }; |
|---|
| 740 | 712 | module_spi_driver(ad2s1210_driver); |
|---|