| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * AD5933 AD5934 Impedance Converter, Network Analyzer |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright 2011 Analog Devices Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * Licensed under the GPL-2. |
|---|
| 7 | 6 | */ |
|---|
| 8 | 7 | |
|---|
| 9 | | -#include <linux/interrupt.h> |
|---|
| 10 | | -#include <linux/device.h> |
|---|
| 11 | | -#include <linux/kernel.h> |
|---|
| 12 | | -#include <linux/sysfs.h> |
|---|
| 13 | | -#include <linux/i2c.h> |
|---|
| 14 | | -#include <linux/regulator/consumer.h> |
|---|
| 15 | | -#include <linux/types.h> |
|---|
| 16 | | -#include <linux/err.h> |
|---|
| 8 | +#include <linux/clk.h> |
|---|
| 17 | 9 | #include <linux/delay.h> |
|---|
| 10 | +#include <linux/device.h> |
|---|
| 11 | +#include <linux/err.h> |
|---|
| 12 | +#include <linux/i2c.h> |
|---|
| 13 | +#include <linux/interrupt.h> |
|---|
| 14 | +#include <linux/kernel.h> |
|---|
| 18 | 15 | #include <linux/module.h> |
|---|
| 16 | +#include <linux/regulator/consumer.h> |
|---|
| 17 | +#include <linux/sysfs.h> |
|---|
| 18 | +#include <linux/types.h> |
|---|
| 19 | 19 | |
|---|
| 20 | | -#include <linux/iio/iio.h> |
|---|
| 21 | | -#include <linux/iio/sysfs.h> |
|---|
| 22 | 20 | #include <linux/iio/buffer.h> |
|---|
| 21 | +#include <linux/iio/iio.h> |
|---|
| 23 | 22 | #include <linux/iio/kfifo_buf.h> |
|---|
| 23 | +#include <linux/iio/sysfs.h> |
|---|
| 24 | 24 | |
|---|
| 25 | 25 | /* AD5933/AD5934 Registers */ |
|---|
| 26 | 26 | #define AD5933_REG_CONTROL_HB 0x80 /* R/W, 1 byte */ |
|---|
| .. | .. |
|---|
| 82 | 82 | #define AD5933_POLL_TIME_ms 10 |
|---|
| 83 | 83 | #define AD5933_INIT_EXCITATION_TIME_ms 100 |
|---|
| 84 | 84 | |
|---|
| 85 | | -/** |
|---|
| 86 | | - * struct ad5933_platform_data - platform specific data |
|---|
| 87 | | - * @ext_clk_Hz: the external clock frequency in Hz, if not set |
|---|
| 88 | | - * the driver uses the internal clock (16.776 MHz) |
|---|
| 89 | | - * @vref_mv: the external reference voltage in millivolt |
|---|
| 90 | | - */ |
|---|
| 91 | | - |
|---|
| 92 | | -struct ad5933_platform_data { |
|---|
| 93 | | - unsigned long ext_clk_Hz; |
|---|
| 94 | | - unsigned short vref_mv; |
|---|
| 95 | | -}; |
|---|
| 96 | | - |
|---|
| 97 | 85 | struct ad5933_state { |
|---|
| 98 | 86 | struct i2c_client *client; |
|---|
| 99 | 87 | struct regulator *reg; |
|---|
| 88 | + struct clk *mclk; |
|---|
| 100 | 89 | struct delayed_work work; |
|---|
| 101 | 90 | struct mutex lock; /* Protect sensor state */ |
|---|
| 102 | 91 | unsigned long mclk_hz; |
|---|
| .. | .. |
|---|
| 110 | 99 | unsigned int freq_inc; |
|---|
| 111 | 100 | unsigned int state; |
|---|
| 112 | 101 | unsigned int poll_time_jiffies; |
|---|
| 113 | | -}; |
|---|
| 114 | | - |
|---|
| 115 | | -static struct ad5933_platform_data ad5933_default_pdata = { |
|---|
| 116 | | - .vref_mv = 3300, |
|---|
| 117 | 102 | }; |
|---|
| 118 | 103 | |
|---|
| 119 | 104 | #define AD5933_CHANNEL(_type, _extend_name, _info_mask_separate, _address, \ |
|---|
| .. | .. |
|---|
| 210 | 195 | u8 d8[4]; |
|---|
| 211 | 196 | } dat; |
|---|
| 212 | 197 | |
|---|
| 213 | | - freqreg = (u64) freq * (u64) (1 << 27); |
|---|
| 198 | + freqreg = (u64)freq * (u64)(1 << 27); |
|---|
| 214 | 199 | do_div(freqreg, st->mclk_hz / 4); |
|---|
| 215 | 200 | |
|---|
| 216 | 201 | switch (reg) { |
|---|
| .. | .. |
|---|
| 267 | 252 | |
|---|
| 268 | 253 | for (i = 0; i < 4; i++) |
|---|
| 269 | 254 | st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300; |
|---|
| 270 | | - |
|---|
| 271 | 255 | } |
|---|
| 272 | 256 | |
|---|
| 273 | 257 | /* |
|---|
| .. | .. |
|---|
| 299 | 283 | freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF; |
|---|
| 300 | 284 | |
|---|
| 301 | 285 | freqreg = (u64)freqreg * (u64)(st->mclk_hz / 4); |
|---|
| 302 | | - do_div(freqreg, 1 << 27); |
|---|
| 286 | + do_div(freqreg, BIT(27)); |
|---|
| 303 | 287 | |
|---|
| 304 | 288 | return sprintf(buf, "%d\n", (int)freqreg); |
|---|
| 305 | 289 | } |
|---|
| .. | .. |
|---|
| 331 | 315 | return ret ? ret : len; |
|---|
| 332 | 316 | } |
|---|
| 333 | 317 | |
|---|
| 334 | | -static IIO_DEVICE_ATTR(out_voltage0_freq_start, 0644, |
|---|
| 318 | +static IIO_DEVICE_ATTR(out_altvoltage0_frequency_start, 0644, |
|---|
| 335 | 319 | ad5933_show_frequency, |
|---|
| 336 | 320 | ad5933_store_frequency, |
|---|
| 337 | 321 | AD5933_REG_FREQ_START); |
|---|
| 338 | 322 | |
|---|
| 339 | | -static IIO_DEVICE_ATTR(out_voltage0_freq_increment, 0644, |
|---|
| 323 | +static IIO_DEVICE_ATTR(out_altvoltage0_frequency_increment, 0644, |
|---|
| 340 | 324 | ad5933_show_frequency, |
|---|
| 341 | 325 | ad5933_store_frequency, |
|---|
| 342 | 326 | AD5933_REG_FREQ_INC); |
|---|
| .. | .. |
|---|
| 435 | 419 | if (val > 1022) |
|---|
| 436 | 420 | val = (val >> 2) | (3 << 9); |
|---|
| 437 | 421 | else if (val > 511) |
|---|
| 438 | | - val = (val >> 1) | (1 << 9); |
|---|
| 422 | + val = (val >> 1) | BIT(9); |
|---|
| 439 | 423 | |
|---|
| 440 | 424 | dat = cpu_to_be16(val); |
|---|
| 441 | 425 | ret = ad5933_i2c_write(st->client, |
|---|
| .. | .. |
|---|
| 459 | 443 | return ret ? ret : len; |
|---|
| 460 | 444 | } |
|---|
| 461 | 445 | |
|---|
| 462 | | -static IIO_DEVICE_ATTR(out_voltage0_scale, 0644, |
|---|
| 446 | +static IIO_DEVICE_ATTR(out_altvoltage0_raw, 0644, |
|---|
| 463 | 447 | ad5933_show, |
|---|
| 464 | 448 | ad5933_store, |
|---|
| 465 | 449 | AD5933_OUT_RANGE); |
|---|
| 466 | 450 | |
|---|
| 467 | | -static IIO_DEVICE_ATTR(out_voltage0_scale_available, 0444, |
|---|
| 451 | +static IIO_DEVICE_ATTR(out_altvoltage0_scale_available, 0444, |
|---|
| 468 | 452 | ad5933_show, |
|---|
| 469 | 453 | NULL, |
|---|
| 470 | 454 | AD5933_OUT_RANGE_AVAIL); |
|---|
| .. | .. |
|---|
| 479 | 463 | NULL, |
|---|
| 480 | 464 | AD5933_IN_PGA_GAIN_AVAIL); |
|---|
| 481 | 465 | |
|---|
| 482 | | -static IIO_DEVICE_ATTR(out_voltage0_freq_points, 0644, |
|---|
| 466 | +static IIO_DEVICE_ATTR(out_altvoltage0_frequency_points, 0644, |
|---|
| 483 | 467 | ad5933_show, |
|---|
| 484 | 468 | ad5933_store, |
|---|
| 485 | 469 | AD5933_FREQ_POINTS); |
|---|
| 486 | 470 | |
|---|
| 487 | | -static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, 0644, |
|---|
| 471 | +static IIO_DEVICE_ATTR(out_altvoltage0_settling_cycles, 0644, |
|---|
| 488 | 472 | ad5933_show, |
|---|
| 489 | 473 | ad5933_store, |
|---|
| 490 | 474 | AD5933_OUT_SETTLING_CYCLES); |
|---|
| 491 | 475 | |
|---|
| 492 | | -/* note: |
|---|
| 476 | +/* |
|---|
| 477 | + * note: |
|---|
| 493 | 478 | * ideally we would handle the scale attributes via the iio_info |
|---|
| 494 | 479 | * (read|write)_raw methods, however this part is a untypical since we |
|---|
| 495 | 480 | * don't create dedicated sysfs channel attributes for out0 and in0. |
|---|
| 496 | 481 | */ |
|---|
| 497 | 482 | static struct attribute *ad5933_attributes[] = { |
|---|
| 498 | | - &iio_dev_attr_out_voltage0_scale.dev_attr.attr, |
|---|
| 499 | | - &iio_dev_attr_out_voltage0_scale_available.dev_attr.attr, |
|---|
| 500 | | - &iio_dev_attr_out_voltage0_freq_start.dev_attr.attr, |
|---|
| 501 | | - &iio_dev_attr_out_voltage0_freq_increment.dev_attr.attr, |
|---|
| 502 | | - &iio_dev_attr_out_voltage0_freq_points.dev_attr.attr, |
|---|
| 503 | | - &iio_dev_attr_out_voltage0_settling_cycles.dev_attr.attr, |
|---|
| 483 | + &iio_dev_attr_out_altvoltage0_raw.dev_attr.attr, |
|---|
| 484 | + &iio_dev_attr_out_altvoltage0_scale_available.dev_attr.attr, |
|---|
| 485 | + &iio_dev_attr_out_altvoltage0_frequency_start.dev_attr.attr, |
|---|
| 486 | + &iio_dev_attr_out_altvoltage0_frequency_increment.dev_attr.attr, |
|---|
| 487 | + &iio_dev_attr_out_altvoltage0_frequency_points.dev_attr.attr, |
|---|
| 488 | + &iio_dev_attr_out_altvoltage0_settling_cycles.dev_attr.attr, |
|---|
| 504 | 489 | &iio_dev_attr_in_voltage0_scale.dev_attr.attr, |
|---|
| 505 | 490 | &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, |
|---|
| 506 | 491 | NULL |
|---|
| .. | .. |
|---|
| 587 | 572 | { |
|---|
| 588 | 573 | struct ad5933_state *st = iio_priv(indio_dev); |
|---|
| 589 | 574 | |
|---|
| 590 | | - /* AD5933_CTRL_INIT_START_FREQ: |
|---|
| 575 | + /* |
|---|
| 576 | + * AD5933_CTRL_INIT_START_FREQ: |
|---|
| 591 | 577 | * High Q complex circuits require a long time to reach steady state. |
|---|
| 592 | 578 | * To facilitate the measurement of such impedances, this mode allows |
|---|
| 593 | 579 | * the user full control of the settling time requirement before |
|---|
| .. | .. |
|---|
| 616 | 602 | .postdisable = ad5933_ring_postdisable, |
|---|
| 617 | 603 | }; |
|---|
| 618 | 604 | |
|---|
| 619 | | -static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) |
|---|
| 605 | +static int ad5933_register_ring_funcs_and_init(struct device *dev, |
|---|
| 606 | + struct iio_dev *indio_dev) |
|---|
| 620 | 607 | { |
|---|
| 621 | 608 | struct iio_buffer *buffer; |
|---|
| 622 | 609 | |
|---|
| 623 | | - buffer = iio_kfifo_allocate(); |
|---|
| 610 | + buffer = devm_iio_kfifo_allocate(dev); |
|---|
| 624 | 611 | if (!buffer) |
|---|
| 625 | 612 | return -ENOMEM; |
|---|
| 626 | 613 | |
|---|
| .. | .. |
|---|
| 678 | 665 | } |
|---|
| 679 | 666 | |
|---|
| 680 | 667 | if (status & AD5933_STAT_SWEEP_DONE) { |
|---|
| 681 | | - /* last sample received - power down do |
|---|
| 668 | + /* |
|---|
| 669 | + * last sample received - power down do |
|---|
| 682 | 670 | * nothing until the ring enable is toggled |
|---|
| 683 | 671 | */ |
|---|
| 684 | 672 | ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); |
|---|
| .. | .. |
|---|
| 689 | 677 | } |
|---|
| 690 | 678 | } |
|---|
| 691 | 679 | |
|---|
| 680 | +static void ad5933_reg_disable(void *data) |
|---|
| 681 | +{ |
|---|
| 682 | + struct ad5933_state *st = data; |
|---|
| 683 | + |
|---|
| 684 | + regulator_disable(st->reg); |
|---|
| 685 | +} |
|---|
| 686 | + |
|---|
| 687 | +static void ad5933_clk_disable(void *data) |
|---|
| 688 | +{ |
|---|
| 689 | + struct ad5933_state *st = data; |
|---|
| 690 | + |
|---|
| 691 | + clk_disable_unprepare(st->mclk); |
|---|
| 692 | +} |
|---|
| 693 | + |
|---|
| 692 | 694 | static int ad5933_probe(struct i2c_client *client, |
|---|
| 693 | 695 | const struct i2c_device_id *id) |
|---|
| 694 | 696 | { |
|---|
| 695 | | - int ret, voltage_uv = 0; |
|---|
| 696 | | - struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); |
|---|
| 697 | + int ret; |
|---|
| 697 | 698 | struct ad5933_state *st; |
|---|
| 698 | 699 | struct iio_dev *indio_dev; |
|---|
| 700 | + unsigned long ext_clk_hz = 0; |
|---|
| 699 | 701 | |
|---|
| 700 | 702 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); |
|---|
| 701 | 703 | if (!indio_dev) |
|---|
| .. | .. |
|---|
| 707 | 709 | |
|---|
| 708 | 710 | mutex_init(&st->lock); |
|---|
| 709 | 711 | |
|---|
| 710 | | - if (!pdata) |
|---|
| 711 | | - pdata = &ad5933_default_pdata; |
|---|
| 712 | | - |
|---|
| 713 | 712 | st->reg = devm_regulator_get(&client->dev, "vdd"); |
|---|
| 714 | 713 | if (IS_ERR(st->reg)) |
|---|
| 715 | 714 | return PTR_ERR(st->reg); |
|---|
| .. | .. |
|---|
| 719 | 718 | dev_err(&client->dev, "Failed to enable specified VDD supply\n"); |
|---|
| 720 | 719 | return ret; |
|---|
| 721 | 720 | } |
|---|
| 722 | | - voltage_uv = regulator_get_voltage(st->reg); |
|---|
| 723 | 721 | |
|---|
| 724 | | - if (voltage_uv) |
|---|
| 725 | | - st->vref_mv = voltage_uv / 1000; |
|---|
| 726 | | - else |
|---|
| 727 | | - st->vref_mv = pdata->vref_mv; |
|---|
| 722 | + ret = devm_add_action_or_reset(&client->dev, ad5933_reg_disable, st); |
|---|
| 723 | + if (ret) |
|---|
| 724 | + return ret; |
|---|
| 728 | 725 | |
|---|
| 729 | | - if (pdata->ext_clk_Hz) { |
|---|
| 730 | | - st->mclk_hz = pdata->ext_clk_Hz; |
|---|
| 726 | + ret = regulator_get_voltage(st->reg); |
|---|
| 727 | + if (ret < 0) |
|---|
| 728 | + return ret; |
|---|
| 729 | + |
|---|
| 730 | + st->vref_mv = ret / 1000; |
|---|
| 731 | + |
|---|
| 732 | + st->mclk = devm_clk_get(&client->dev, "mclk"); |
|---|
| 733 | + if (IS_ERR(st->mclk) && PTR_ERR(st->mclk) != -ENOENT) |
|---|
| 734 | + return PTR_ERR(st->mclk); |
|---|
| 735 | + |
|---|
| 736 | + if (!IS_ERR(st->mclk)) { |
|---|
| 737 | + ret = clk_prepare_enable(st->mclk); |
|---|
| 738 | + if (ret < 0) |
|---|
| 739 | + return ret; |
|---|
| 740 | + |
|---|
| 741 | + ret = devm_add_action_or_reset(&client->dev, |
|---|
| 742 | + ad5933_clk_disable, |
|---|
| 743 | + st); |
|---|
| 744 | + if (ret) |
|---|
| 745 | + return ret; |
|---|
| 746 | + |
|---|
| 747 | + ext_clk_hz = clk_get_rate(st->mclk); |
|---|
| 748 | + } |
|---|
| 749 | + |
|---|
| 750 | + if (ext_clk_hz) { |
|---|
| 751 | + st->mclk_hz = ext_clk_hz; |
|---|
| 731 | 752 | st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; |
|---|
| 732 | 753 | } else { |
|---|
| 733 | 754 | st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; |
|---|
| .. | .. |
|---|
| 738 | 759 | INIT_DELAYED_WORK(&st->work, ad5933_work); |
|---|
| 739 | 760 | st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms); |
|---|
| 740 | 761 | |
|---|
| 741 | | - indio_dev->dev.parent = &client->dev; |
|---|
| 742 | 762 | indio_dev->info = &ad5933_info; |
|---|
| 743 | 763 | indio_dev->name = id->name; |
|---|
| 744 | 764 | indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE); |
|---|
| 745 | 765 | indio_dev->channels = ad5933_channels; |
|---|
| 746 | 766 | indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); |
|---|
| 747 | 767 | |
|---|
| 748 | | - ret = ad5933_register_ring_funcs_and_init(indio_dev); |
|---|
| 768 | + ret = ad5933_register_ring_funcs_and_init(&client->dev, indio_dev); |
|---|
| 749 | 769 | if (ret) |
|---|
| 750 | | - goto error_disable_reg; |
|---|
| 770 | + return ret; |
|---|
| 751 | 771 | |
|---|
| 752 | 772 | ret = ad5933_setup(st); |
|---|
| 753 | 773 | if (ret) |
|---|
| 754 | | - goto error_unreg_ring; |
|---|
| 774 | + return ret; |
|---|
| 755 | 775 | |
|---|
| 756 | | - ret = iio_device_register(indio_dev); |
|---|
| 757 | | - if (ret) |
|---|
| 758 | | - goto error_unreg_ring; |
|---|
| 759 | | - |
|---|
| 760 | | - return 0; |
|---|
| 761 | | - |
|---|
| 762 | | -error_unreg_ring: |
|---|
| 763 | | - iio_kfifo_free(indio_dev->buffer); |
|---|
| 764 | | -error_disable_reg: |
|---|
| 765 | | - regulator_disable(st->reg); |
|---|
| 766 | | - |
|---|
| 767 | | - return ret; |
|---|
| 768 | | -} |
|---|
| 769 | | - |
|---|
| 770 | | -static int ad5933_remove(struct i2c_client *client) |
|---|
| 771 | | -{ |
|---|
| 772 | | - struct iio_dev *indio_dev = i2c_get_clientdata(client); |
|---|
| 773 | | - struct ad5933_state *st = iio_priv(indio_dev); |
|---|
| 774 | | - |
|---|
| 775 | | - iio_device_unregister(indio_dev); |
|---|
| 776 | | - iio_kfifo_free(indio_dev->buffer); |
|---|
| 777 | | - regulator_disable(st->reg); |
|---|
| 778 | | - |
|---|
| 779 | | - return 0; |
|---|
| 776 | + return devm_iio_device_register(&client->dev, indio_dev); |
|---|
| 780 | 777 | } |
|---|
| 781 | 778 | |
|---|
| 782 | 779 | static const struct i2c_device_id ad5933_id[] = { |
|---|
| .. | .. |
|---|
| 787 | 784 | |
|---|
| 788 | 785 | MODULE_DEVICE_TABLE(i2c, ad5933_id); |
|---|
| 789 | 786 | |
|---|
| 787 | +static const struct of_device_id ad5933_of_match[] = { |
|---|
| 788 | + { .compatible = "adi,ad5933" }, |
|---|
| 789 | + { .compatible = "adi,ad5934" }, |
|---|
| 790 | + { }, |
|---|
| 791 | +}; |
|---|
| 792 | + |
|---|
| 793 | +MODULE_DEVICE_TABLE(of, ad5933_of_match); |
|---|
| 794 | + |
|---|
| 790 | 795 | static struct i2c_driver ad5933_driver = { |
|---|
| 791 | 796 | .driver = { |
|---|
| 792 | 797 | .name = "ad5933", |
|---|
| 798 | + .of_match_table = ad5933_of_match, |
|---|
| 793 | 799 | }, |
|---|
| 794 | 800 | .probe = ad5933_probe, |
|---|
| 795 | | - .remove = ad5933_remove, |
|---|
| 796 | 801 | .id_table = ad5933_id, |
|---|
| 797 | 802 | }; |
|---|
| 798 | 803 | module_i2c_driver(ad5933_driver); |
|---|
| 799 | 804 | |
|---|
| 800 | | -MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
|---|
| 805 | +MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); |
|---|
| 801 | 806 | MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer"); |
|---|
| 802 | 807 | MODULE_LICENSE("GPL v2"); |
|---|