iio: adc: ad7091r5: Add scale and external VREF support
The scale can now be obtained with the "in_voltage_scale" file. By default, the scale returned corresponds to the internal VREF of 2.5V. It is possible to use an external VREF (through the REFIN/REFOUT pin of the chip), by passing a regulator to the driver. The scale will then be calculated according to the voltage reported by the regulator. Signed-off-by: Paul Cercueil <paul.cercueil@analog.com> Co-developed-by: Beniamin Bia <beniamin.bia@analog.com> Signed-off-by: Beniamin Bia <beniamin.bia@analog.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Родитель
ca69300173
Коммит
260442cc5b
|
@ -11,6 +11,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include "ad7091r-base.h"
|
||||
|
||||
|
@ -42,6 +43,7 @@ enum ad7091r_mode {
|
|||
struct ad7091r_state {
|
||||
struct device *dev;
|
||||
struct regmap *map;
|
||||
struct regulator *vref;
|
||||
const struct ad7091r_chip_info *chip_info;
|
||||
enum ad7091r_mode mode;
|
||||
struct mutex lock; /*lock to prevent concurent reads */
|
||||
|
@ -141,6 +143,21 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev,
|
|||
ret = IIO_VAL_INT;
|
||||
break;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (st->vref) {
|
||||
ret = regulator_get_voltage(st->vref);
|
||||
if (ret < 0)
|
||||
goto unlock;
|
||||
|
||||
*val = ret / 1000;
|
||||
} else {
|
||||
*val = st->chip_info->vref_mV;
|
||||
}
|
||||
|
||||
*val2 = chan->scan_type.realbits;
|
||||
ret = IIO_VAL_FRACTIONAL_LOG2;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
@ -183,6 +200,13 @@ static irqreturn_t ad7091r_event_handler(int irq, void *private)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void ad7091r_remove(void *data)
|
||||
{
|
||||
struct ad7091r_state *st = data;
|
||||
|
||||
regulator_disable(st->vref);
|
||||
}
|
||||
|
||||
int ad7091r_probe(struct device *dev, const char *name,
|
||||
const struct ad7091r_chip_info *chip_info,
|
||||
struct regmap *map, int irq)
|
||||
|
@ -216,6 +240,20 @@ int ad7091r_probe(struct device *dev, const char *name,
|
|||
return ret;
|
||||
}
|
||||
|
||||
st->vref = devm_regulator_get_optional(dev, "vref");
|
||||
if (IS_ERR(st->vref)) {
|
||||
if (PTR_ERR(st->vref) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
st->vref = NULL;
|
||||
} else {
|
||||
ret = regulator_enable(st->vref);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_add_action_or_reset(dev, ad7091r_remove, st);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Use command mode by default to convert only desired channels*/
|
||||
ret = ad7091r_set_mode(st, AD7091R_MODE_COMMAND);
|
||||
if (ret)
|
||||
|
|
|
@ -14,6 +14,7 @@ struct ad7091r_state;
|
|||
struct ad7091r_chip_info {
|
||||
unsigned int num_channels;
|
||||
const struct iio_chan_spec *channels;
|
||||
unsigned int vref_mV;
|
||||
};
|
||||
|
||||
extern const struct regmap_config ad7091r_regmap_config;
|
||||
|
|
|
@ -35,10 +35,13 @@ static const struct iio_event_spec ad7091r5_events[] = {
|
|||
#define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
|
||||
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
|
||||
.indexed = 1, \
|
||||
.channel = idx, \
|
||||
.event_spec = ev, \
|
||||
.num_event_specs = num_ev, \
|
||||
.scan_type.storagebits = 16, \
|
||||
.scan_type.realbits = bits, \
|
||||
}
|
||||
static const struct iio_chan_spec ad7091r5_channels_irq[] = {
|
||||
AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)),
|
||||
|
@ -57,11 +60,13 @@ static const struct iio_chan_spec ad7091r5_channels_noirq[] = {
|
|||
static const struct ad7091r_chip_info ad7091r5_chip_info_irq = {
|
||||
.channels = ad7091r5_channels_irq,
|
||||
.num_channels = ARRAY_SIZE(ad7091r5_channels_irq),
|
||||
.vref_mV = 2500,
|
||||
};
|
||||
|
||||
static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = {
|
||||
.channels = ad7091r5_channels_noirq,
|
||||
.num_channels = ARRAY_SIZE(ad7091r5_channels_noirq),
|
||||
.vref_mV = 2500,
|
||||
};
|
||||
|
||||
static int ad7091r5_i2c_probe(struct i2c_client *i2c,
|
||||
|
|
Загрузка…
Ссылка в новой задаче