diff options
author | Silvan Murer <silvan.murer@gmail.com> | 2018-05-21 14:21:28 +0200 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2018-05-22 19:24:48 +0200 |
commit | 9ff1d5009fc4b47ac0e6d7818dac0158e1804c3e (patch) | |
tree | 63cea06624a2346e69f43497a4eba1eb402acc15 /drivers/iio/dac/ltc2632.c | |
parent | iio: dac: fix missing of_match_table assignment in the LTC 2632 device (diff) | |
download | linux-9ff1d5009fc4b47ac0e6d7818dac0158e1804c3e.tar.xz linux-9ff1d5009fc4b47ac0e6d7818dac0158e1804c3e.zip |
iio: dac: Add support for external reference voltage through the regulator framework.
Signed-off-by: Silvan Murer <silvan.murer@gmail.com>
Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/dac/ltc2632.c')
-rw-r--r-- | drivers/iio/dac/ltc2632.c | 70 |
1 files changed, 61 insertions, 9 deletions
diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index 08a78f08a2ba..cca278eaa138 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -2,6 +2,7 @@ * LTC2632 Digital to analog convertors spi driver * * Copyright 2017 Maxime Roussin-Bélanger + * expanded by Silvan Murer <silvan.murer@gmail.com> * * Licensed under the GPL-2. */ @@ -10,6 +11,7 @@ #include <linux/spi/spi.h> #include <linux/module.h> #include <linux/iio/iio.h> +#include <linux/regulator/consumer.h> #define LTC2632_DAC_CHANNELS 2 @@ -28,7 +30,7 @@ /** * struct ltc2632_chip_info - chip specific information * @channels: channel spec for the DAC - * @vref_mv: reference voltage + * @vref_mv: internal reference voltage */ struct ltc2632_chip_info { const struct iio_chan_spec *channels; @@ -39,10 +41,14 @@ struct ltc2632_chip_info { * struct ltc2632_state - driver instance specific data * @spi_dev: pointer to the spi_device struct * @powerdown_cache_mask used to show current channel powerdown state + * @vref_mv used reference voltage (internal or external) + * @vref_reg regulator for the reference voltage */ struct ltc2632_state { struct spi_device *spi_dev; unsigned int powerdown_cache_mask; + int vref_mv; + struct regulator *vref_reg; }; enum ltc2632_supported_device_ids { @@ -90,7 +96,7 @@ static int ltc2632_read_raw(struct iio_dev *indio_dev, switch (m) { case IIO_CHAN_INFO_SCALE: - *val = chip_info->vref_mv; + *val = st->vref_mv; *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; } @@ -246,6 +252,45 @@ static int ltc2632_probe(struct spi_device *spi) chip_info = (struct ltc2632_chip_info *) spi_get_device_id(spi)->driver_data; + st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref"); + if (PTR_ERR(st->vref_reg) == -ENODEV) { + /* use internal reference voltage */ + st->vref_reg = NULL; + st->vref_mv = chip_info->vref_mv; + + ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, + 0, 0, 0); + if (ret) { + dev_err(&spi->dev, + "Set internal reference command failed, %d\n", + ret); + return ret; + } + } else if (IS_ERR(st->vref_reg)) { + dev_err(&spi->dev, + "Error getting voltage reference regulator\n"); + return PTR_ERR(st->vref_reg); + } else { + /* use external reference voltage */ + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(&spi->dev, + "enable reference regulator failed, %d\n", + ret); + return ret; + } + st->vref_mv = regulator_get_voltage(st->vref_reg) / 1000; + + ret = ltc2632_spi_write(spi, LTC2632_CMD_EXTERNAL_REFER, + 0, 0, 0); + if (ret) { + dev_err(&spi->dev, + "Set external reference command failed, %d\n", + ret); + return ret; + } + } + indio_dev->dev.parent = &spi->dev; indio_dev->name = dev_of_node(&spi->dev) ? dev_of_node(&spi->dev)->name : spi_get_device_id(spi)->name; @@ -254,14 +299,20 @@ static int ltc2632_probe(struct spi_device *spi) indio_dev->channels = chip_info->channels; indio_dev->num_channels = LTC2632_DAC_CHANNELS; - ret = ltc2632_spi_write(spi, LTC2632_CMD_INTERNAL_REFER, 0, 0, 0); - if (ret) { - dev_err(&spi->dev, - "Set internal reference command failed, %d\n", ret); - return ret; - } + return iio_device_register(indio_dev); +} + +static int ltc2632_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct ltc2632_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + if (st->vref_reg) + regulator_disable(st->vref_reg); - return devm_iio_device_register(&spi->dev, indio_dev); + return 0; } static const struct spi_device_id ltc2632_id[] = { @@ -305,6 +356,7 @@ static struct spi_driver ltc2632_driver = { .of_match_table = of_match_ptr(ltc2632_of_match), }, .probe = ltc2632_probe, + .remove = ltc2632_remove, .id_table = ltc2632_id, }; module_spi_driver(ltc2632_driver); |