summaryrefslogtreecommitdiffstats
path: root/drivers/iio/dac/ltc2632.c
diff options
context:
space:
mode:
authorSilvan Murer <silvan.murer@gmail.com>2018-05-21 14:21:28 +0200
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2018-05-22 19:24:48 +0200
commit9ff1d5009fc4b47ac0e6d7818dac0158e1804c3e (patch)
tree63cea06624a2346e69f43497a4eba1eb402acc15 /drivers/iio/dac/ltc2632.c
parentiio: dac: fix missing of_match_table assignment in the LTC 2632 device (diff)
downloadlinux-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.c70
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);