summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/ad7476.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-07-05 14:01:53 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-07-05 14:01:53 -0700
commita16d8644bad461bb073b92e812080ea6715ddf2b (patch)
tree2baa375527e57c0df2bf56d28e7cf36fb97a435c /drivers/iio/adc/ad7476.c
parentf5c13f1fdef9fed65b95c3c5f343d22c425ac1d7 (diff)
parent77ad1f0e99bd00af024e650b862cfda3137af660 (diff)
Merge tag 'staging-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging / IIO driver updates from Greg KH: "Here is the big set of IIO and staging driver patches for 5.14-rc1. Loads of IIO driver updates and additions in here, the shortlog has the full details. For the staging side, we moved a few drivers out of staging, and deleted the kpc2000 drivers as the original developer asked us to because no one was working on them anymore. Also in here are loads of coding style cleanups due to different intern projects focusing on the staging tree to try to get experience doing kernel development. All of these have been in the linux-next tree for a while with no reported problems" * tag 'staging-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (744 commits) staging: hi6421-spmi-pmic: cleanup some macros staging: hi6421-spmi-pmic: change identation of a table staging: hi6421-spmi-pmic: change a return code staging: hi6421-spmi-pmic: better name IRQs staging: hi6421-spmi-pmic: use devm_request_threaded_irq() staging: hisilicon,hi6421-spmi-pmic.yaml: cleanup descriptions spmi: hisi-spmi-controller: move driver from staging phy: phy-hi3670-usb3: move driver from staging into phy staging: rtl8188eu: remove include/rtw_debug.h header staging: rtl8188eu: remove GlobalDebugLevel variable staging: rtl8188eu: remove DRIVER_PREFIX preprocessor definition staging: rtl8188eu: remove RT_TRACE macro staging: rtl8188eu: remove all RT_TRACE calls from hal/rtl8188eu_recv.c staging: rtl8188eu: remove all RT_TRACE calls from hal/hal_intf.c staging: rtl8188eu: remove all RT_TRACE calls from hal/rtl8188eu_xmit.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_xmit.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_pwrctrl.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_recv.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_ioctl_set.c staging: rtl8188eu: remove all RT_TRACE calls from core/rtw_ieee80211.c ...
Diffstat (limited to 'drivers/iio/adc/ad7476.c')
-rw-r--r--drivers/iio/adc/ad7476.c120
1 files changed, 103 insertions, 17 deletions
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
index 9e9ff07cf972..a1e8b32671cf 100644
--- a/drivers/iio/adc/ad7476.c
+++ b/drivers/iio/adc/ad7476.c
@@ -32,12 +32,14 @@ struct ad7476_chip_info {
/* channels used when convst gpio is defined */
struct iio_chan_spec convst_channel[2];
void (*reset)(struct ad7476_state *);
+ bool has_vref;
+ bool has_vdrive;
};
struct ad7476_state {
struct spi_device *spi;
const struct ad7476_chip_info *chip_info;
- struct regulator *reg;
+ struct regulator *ref_reg;
struct gpio_desc *convst_gpio;
struct spi_transfer xfer;
struct spi_message msg;
@@ -52,13 +54,17 @@ struct ad7476_state {
};
enum ad7476_supported_device_ids {
+ ID_AD7091,
ID_AD7091R,
+ ID_AD7273,
+ ID_AD7274,
ID_AD7276,
ID_AD7277,
ID_AD7278,
ID_AD7466,
ID_AD7467,
ID_AD7468,
+ ID_AD7475,
ID_AD7495,
ID_AD7940,
ID_ADC081S,
@@ -145,8 +151,8 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- if (!st->chip_info->int_vref_uv) {
- scale_uv = regulator_get_voltage(st->reg);
+ if (st->ref_reg) {
+ scale_uv = regulator_get_voltage(st->ref_reg);
if (scale_uv < 0)
return scale_uv;
} else {
@@ -187,13 +193,32 @@ static int ad7476_read_raw(struct iio_dev *indio_dev,
BIT(IIO_CHAN_INFO_RAW))
static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
+ [ID_AD7091] = {
+ .channel[0] = AD7091R_CHAN(12),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .convst_channel[0] = AD7091R_CONVST_CHAN(12),
+ .convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .reset = ad7091_reset,
+ },
[ID_AD7091R] = {
.channel[0] = AD7091R_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.convst_channel[0] = AD7091R_CONVST_CHAN(12),
.convst_channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .int_vref_uv = 2500000,
+ .has_vref = true,
.reset = ad7091_reset,
},
+ [ID_AD7273] = {
+ .channel[0] = AD7940_CHAN(10),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .has_vref = true,
+ },
+ [ID_AD7274] = {
+ .channel[0] = AD7940_CHAN(12),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .has_vref = true,
+ },
[ID_AD7276] = {
.channel[0] = AD7940_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
@@ -218,10 +243,17 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
.channel[0] = AD7476_CHAN(8),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
+ [ID_AD7475] = {
+ .channel[0] = AD7476_CHAN(12),
+ .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .has_vref = true,
+ .has_vdrive = true,
+ },
[ID_AD7495] = {
.channel[0] = AD7476_CHAN(12),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
.int_vref_uv = 2500000,
+ .has_vdrive = true,
},
[ID_AD7940] = {
.channel[0] = AD7940_CHAN(14),
@@ -254,6 +286,7 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
[ID_LTC2314_14] = {
.channel[0] = AD7940_CHAN(14),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+ .has_vref = true,
},
};
@@ -263,15 +296,16 @@ static const struct iio_info ad7476_info = {
static void ad7476_reg_disable(void *data)
{
- struct ad7476_state *st = data;
+ struct regulator *reg = data;
- regulator_disable(st->reg);
+ regulator_disable(reg);
}
static int ad7476_probe(struct spi_device *spi)
{
struct ad7476_state *st;
struct iio_dev *indio_dev;
+ struct regulator *reg;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -282,27 +316,79 @@ static int ad7476_probe(struct spi_device *spi)
st->chip_info =
&ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- st->reg = devm_regulator_get(&spi->dev, "vcc");
- if (IS_ERR(st->reg))
- return PTR_ERR(st->reg);
+ reg = devm_regulator_get(&spi->dev, "vcc");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
- ret = regulator_enable(st->reg);
+ ret = regulator_enable(reg);
if (ret)
return ret;
- ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable,
- st);
+ ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, reg);
if (ret)
return ret;
+ /* Either vcc or vref (below) as appropriate */
+ if (!st->chip_info->int_vref_uv)
+ st->ref_reg = reg;
+
+ if (st->chip_info->has_vref) {
+
+ /* If a device has an internal reference vref is optional */
+ if (st->chip_info->int_vref_uv) {
+ reg = devm_regulator_get_optional(&spi->dev, "vref");
+ if (IS_ERR(reg) && (PTR_ERR(reg) != -ENODEV))
+ return PTR_ERR(reg);
+ } else {
+ reg = devm_regulator_get(&spi->dev, "vref");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ }
+
+ if (!IS_ERR(reg)) {
+ ret = regulator_enable(reg);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev,
+ ad7476_reg_disable,
+ reg);
+ if (ret)
+ return ret;
+ st->ref_reg = reg;
+ } else {
+ /*
+ * Can only get here if device supports both internal
+ * and external reference, but the regulator connected
+ * to the external reference is not connected.
+ * Set the reference regulator pointer to NULL to
+ * indicate this.
+ */
+ st->ref_reg = NULL;
+ }
+ }
+
+ if (st->chip_info->has_vdrive) {
+ reg = devm_regulator_get(&spi->dev, "vdrive");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ ret = regulator_enable(reg);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable,
+ reg);
+ if (ret)
+ return ret;
+ }
+
st->convst_gpio = devm_gpiod_get_optional(&spi->dev,
"adi,conversion-start",
GPIOD_OUT_LOW);
if (IS_ERR(st->convst_gpio))
return PTR_ERR(st->convst_gpio);
- spi_set_drvdata(spi, indio_dev);
-
st->spi = spi;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -333,17 +419,17 @@ static int ad7476_probe(struct spi_device *spi)
}
static const struct spi_device_id ad7476_id[] = {
- {"ad7091", ID_AD7091R},
+ {"ad7091", ID_AD7091},
{"ad7091r", ID_AD7091R},
- {"ad7273", ID_AD7277},
- {"ad7274", ID_AD7276},
+ {"ad7273", ID_AD7273},
+ {"ad7274", ID_AD7274},
{"ad7276", ID_AD7276},
{"ad7277", ID_AD7277},
{"ad7278", ID_AD7278},
{"ad7466", ID_AD7466},
{"ad7467", ID_AD7467},
{"ad7468", ID_AD7468},
- {"ad7475", ID_AD7466},
+ {"ad7475", ID_AD7475},
{"ad7476", ID_AD7466},
{"ad7476a", ID_AD7466},
{"ad7477", ID_AD7467},