Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Paul Cercueil and committed by
Jonathan Cameron
260442cc ca693001

+44
+38
drivers/iio/adc/ad7091r-base.c
··· 11 11 #include <linux/interrupt.h> 12 12 #include <linux/module.h> 13 13 #include <linux/regmap.h> 14 + #include <linux/regulator/consumer.h> 14 15 15 16 #include "ad7091r-base.h" 16 17 ··· 43 42 struct ad7091r_state { 44 43 struct device *dev; 45 44 struct regmap *map; 45 + struct regulator *vref; 46 46 const struct ad7091r_chip_info *chip_info; 47 47 enum ad7091r_mode mode; 48 48 struct mutex lock; /*lock to prevent concurent reads */ ··· 143 141 ret = IIO_VAL_INT; 144 142 break; 145 143 144 + case IIO_CHAN_INFO_SCALE: 145 + if (st->vref) { 146 + ret = regulator_get_voltage(st->vref); 147 + if (ret < 0) 148 + goto unlock; 149 + 150 + *val = ret / 1000; 151 + } else { 152 + *val = st->chip_info->vref_mV; 153 + } 154 + 155 + *val2 = chan->scan_type.realbits; 156 + ret = IIO_VAL_FRACTIONAL_LOG2; 157 + break; 158 + 146 159 default: 147 160 ret = -EINVAL; 148 161 break; ··· 200 183 return IRQ_HANDLED; 201 184 } 202 185 186 + static void ad7091r_remove(void *data) 187 + { 188 + struct ad7091r_state *st = data; 189 + 190 + regulator_disable(st->vref); 191 + } 192 + 203 193 int ad7091r_probe(struct device *dev, const char *name, 204 194 const struct ad7091r_chip_info *chip_info, 205 195 struct regmap *map, int irq) ··· 236 212 ret = devm_request_threaded_irq(dev, irq, NULL, 237 213 ad7091r_event_handler, 238 214 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, name, st); 215 + if (ret) 216 + return ret; 217 + } 218 + 219 + st->vref = devm_regulator_get_optional(dev, "vref"); 220 + if (IS_ERR(st->vref)) { 221 + if (PTR_ERR(st->vref) == -EPROBE_DEFER) 222 + return -EPROBE_DEFER; 223 + st->vref = NULL; 224 + } else { 225 + ret = regulator_enable(st->vref); 226 + if (ret) 227 + return ret; 228 + ret = devm_add_action_or_reset(dev, ad7091r_remove, st); 239 229 if (ret) 240 230 return ret; 241 231 }
+1
drivers/iio/adc/ad7091r-base.h
··· 14 14 struct ad7091r_chip_info { 15 15 unsigned int num_channels; 16 16 const struct iio_chan_spec *channels; 17 + unsigned int vref_mV; 17 18 }; 18 19 19 20 extern const struct regmap_config ad7091r_regmap_config;
+5
drivers/iio/adc/ad7091r5.c
··· 35 35 #define AD7091R_CHANNEL(idx, bits, ev, num_ev) { \ 36 36 .type = IIO_VOLTAGE, \ 37 37 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 38 + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 38 39 .indexed = 1, \ 39 40 .channel = idx, \ 40 41 .event_spec = ev, \ 41 42 .num_event_specs = num_ev, \ 43 + .scan_type.storagebits = 16, \ 44 + .scan_type.realbits = bits, \ 42 45 } 43 46 static const struct iio_chan_spec ad7091r5_channels_irq[] = { 44 47 AD7091R_CHANNEL(0, 12, ad7091r5_events, ARRAY_SIZE(ad7091r5_events)), ··· 60 57 static const struct ad7091r_chip_info ad7091r5_chip_info_irq = { 61 58 .channels = ad7091r5_channels_irq, 62 59 .num_channels = ARRAY_SIZE(ad7091r5_channels_irq), 60 + .vref_mV = 2500, 63 61 }; 64 62 65 63 static const struct ad7091r_chip_info ad7091r5_chip_info_noirq = { 66 64 .channels = ad7091r5_channels_noirq, 67 65 .num_channels = ARRAY_SIZE(ad7091r5_channels_noirq), 66 + .vref_mV = 2500, 68 67 }; 69 68 70 69 static int ad7091r5_i2c_probe(struct i2c_client *i2c,