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

Configure Feed

Select the types of activity you want to include in your feed.

iio: adc: ad7476: Simplify scale handling

The ad7476 driver supports variants with different amount of supply
regulators. On some variants there is only VCC, which is used as a
reference voltage. Others have separate VREF regulator, and some rely on
internal VREF. Some have both internal VREF and option to connect
external one.

The ad7476 driver reads the regulator voltage only when the user asks to
get the scale. This means the driver needs to do some dancing while
picking the correct reference regulator (or internal reference), and
store it for the later use.

According to the discussion [1] variable voltage references are rare,
making it hard to justify the added complexity for supporting those.

Drop the support for the variable voltage references and simplify things
by using the managed regulator get and enable interfaces.

Link: https://lore.kernel.org/linux-iio/20250331122247.05c6b09d@jic23-huawei/ #1
Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: $URL #1
Link: https://patch.msgid.link/4a497cc5ac0f6506c1c94d10849e0ae1cacf1191.1754901948.git.mazziesaccount@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Matti Vaittinen and committed by
Jonathan Cameron
72e42b48 79ca9bf9

+21 -63
+21 -63
drivers/iio/adc/ad7476.c
··· 39 39 struct ad7476_state { 40 40 struct spi_device *spi; 41 41 const struct ad7476_chip_info *chip_info; 42 - struct regulator *ref_reg; 43 42 struct gpio_desc *convst_gpio; 44 43 struct spi_transfer xfer; 45 44 struct spi_message msg; 45 + int scale_mv; 46 46 /* 47 47 * DMA (thus cache coherency maintenance) may require the 48 48 * transfer buffers to live in their own cache lines. ··· 111 111 { 112 112 int ret; 113 113 struct ad7476_state *st = iio_priv(indio_dev); 114 - int scale_uv; 115 114 116 115 switch (m) { 117 116 case IIO_CHAN_INFO_RAW: ··· 125 126 GENMASK(st->chip_info->channel[0].scan_type.realbits - 1, 0); 126 127 return IIO_VAL_INT; 127 128 case IIO_CHAN_INFO_SCALE: 128 - if (st->ref_reg) { 129 - scale_uv = regulator_get_voltage(st->ref_reg); 130 - if (scale_uv < 0) 131 - return scale_uv; 132 - } else { 133 - scale_uv = st->chip_info->int_vref_uv; 134 - } 135 - *val = scale_uv / 1000; 129 + *val = st->scale_mv; 136 130 *val2 = chan->scan_type.realbits; 137 131 return IIO_VAL_FRACTIONAL_LOG2; 138 132 } ··· 278 286 .read_raw = &ad7476_read_raw, 279 287 }; 280 288 281 - static void ad7476_reg_disable(void *data) 282 - { 283 - struct regulator *reg = data; 284 - 285 - regulator_disable(reg); 286 - } 287 - 288 289 static int ad7476_probe(struct spi_device *spi) 289 290 { 290 291 struct ad7476_state *st; 291 292 struct iio_dev *indio_dev; 292 - struct regulator *reg; 293 293 int ret; 294 294 295 295 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); ··· 294 310 if (!st->chip_info) 295 311 return -ENODEV; 296 312 297 - reg = devm_regulator_get(&spi->dev, "vcc"); 298 - if (IS_ERR(reg)) 299 - return PTR_ERR(reg); 300 - 301 - ret = regulator_enable(reg); 302 - if (ret) 303 - return ret; 304 - 305 - ret = devm_add_action_or_reset(&spi->dev, ad7476_reg_disable, reg); 306 - if (ret) 307 - return ret; 308 - 309 - /* Either vcc or vref (below) as appropriate */ 310 - if (!st->chip_info->int_vref_uv) 311 - st->ref_reg = reg; 313 + /* Use VCC for reference voltage if vref / internal vref aren't used */ 314 + if (!st->chip_info->int_vref_uv && !st->chip_info->has_vref) { 315 + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc"); 316 + if (ret < 0) 317 + return ret; 318 + st->scale_mv = ret / 1000; 319 + } else { 320 + ret = devm_regulator_get_enable(&spi->dev, "vcc"); 321 + if (ret < 0) 322 + return ret; 323 + } 312 324 313 325 if (st->chip_info->has_vref) { 314 - 315 - /* If a device has an internal reference vref is optional */ 316 - if (st->chip_info->int_vref_uv) { 317 - reg = devm_regulator_get_optional(&spi->dev, "vref"); 318 - if (IS_ERR(reg) && (PTR_ERR(reg) != -ENODEV)) 319 - return PTR_ERR(reg); 320 - } else { 321 - reg = devm_regulator_get(&spi->dev, "vref"); 322 - if (IS_ERR(reg)) 323 - return PTR_ERR(reg); 324 - } 325 - 326 - if (!IS_ERR(reg)) { 327 - ret = regulator_enable(reg); 328 - if (ret) 326 + ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref"); 327 + if (ret < 0) { 328 + /* Vref is optional if a device has an internal reference */ 329 + if (!st->chip_info->int_vref_uv || ret != -ENODEV) 329 330 return ret; 330 - 331 - ret = devm_add_action_or_reset(&spi->dev, 332 - ad7476_reg_disable, 333 - reg); 334 - if (ret) 335 - return ret; 336 - st->ref_reg = reg; 337 331 } else { 338 - /* 339 - * Can only get here if device supports both internal 340 - * and external reference, but the regulator connected 341 - * to the external reference is not connected. 342 - * Set the reference regulator pointer to NULL to 343 - * indicate this. 344 - */ 345 - st->ref_reg = NULL; 332 + st->scale_mv = ret / 1000; 346 333 } 347 334 } 335 + 336 + if (!st->scale_mv) 337 + st->scale_mv = st->chip_info->int_vref_uv / 1000; 348 338 349 339 if (st->chip_info->has_vdrive) { 350 340 ret = devm_regulator_get_enable(&spi->dev, "vdrive");