Skip to content

Commit

Permalink
iio:adc:ad7476: Handle the different regulators used by various parts.
Browse files Browse the repository at this point in the history
Not all of the parts supported by this driver use single supply.
Hence we add chip_info fields to say what additional supplies exist
and in the case of vref, ensure that is used for the reference voltage
rather than vcc.

One corner case is the ad7091r which has an internal reference that
can be over-driven by an external reference connected on the vref pin.
To handle that force_ext_vref is introduced and set if an optional
vref regulator is present.

Tested using really simple QEMU model and some fixed regulators.

The devm_add_action_or_reset() callback is changed to take the
regulator as it's parameter so we can use one callback for all the
different regulators without having to store pointers to them in
the iio_priv() structure.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Michael Hennerich <michael.hennerich@analog.com>
  • Loading branch information
jic23 authored and intel-lab-lkp committed Apr 5, 2021
1 parent 1b33dfa commit 0c18d05
Showing 1 changed file with 93 additions and 15 deletions.
108 changes: 93 additions & 15 deletions drivers/iio/adc/ad7476.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ 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;
bool force_ext_vref;
struct gpio_desc *convst_gpio;
struct spi_transfer xfer;
struct spi_message msg;
Expand All @@ -52,13 +55,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,
Expand Down Expand Up @@ -145,8 +152,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->chip_info->int_vref_uv || st->force_ext_vref) {
scale_uv = regulator_get_voltage(st->ref_reg);
if (scale_uv < 0)
return scale_uv;
} else {
Expand Down Expand Up @@ -187,13 +194,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),
Expand All @@ -218,10 +244,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),
Expand Down Expand Up @@ -254,6 +287,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,
},
};

Expand All @@ -263,15 +297,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));
Expand All @@ -282,19 +317,62 @@ 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 */
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");
} 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;
st->force_ext_vref = true;
}
}

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);
Expand Down Expand Up @@ -343,17 +421,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},
Expand Down

0 comments on commit 0c18d05

Please sign in to comment.