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: ad9467: fix scale setting

When reading in_voltage_scale we can get something like:

root@analog:/sys/bus/iio/devices/iio:device2# cat in_voltage_scale
0.038146

However, when reading the available options:

root@analog:/sys/bus/iio/devices/iio:device2# cat
in_voltage_scale_available
2000.000000 2100.000006 2200.000007 2300.000008 2400.000009 2500.000010

which does not make sense. Moreover, when trying to set a new scale we
get an error because there's no call to __ad9467_get_scale() to give us
values as given when reading in_voltage_scale. Fix it by computing the
available scales during probe and properly pass the list when
.read_available() is called.

While at it, change to use .read_available() from iio_info. Also note
that to properly fix this, adi-axi-adc.c has to be changed accordingly.

Fixes: ad6797120238 ("iio: adc: ad9467: add support AD9467 ADC")
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Link: https://lore.kernel.org/r/20231207-iio-backend-prep-v2-4-a4a33bc4d70e@analog.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Nuno Sa and committed by
Jonathan Cameron
b73f08bb 73772019

+66 -59
+47
drivers/iio/adc/ad9467.c
··· 120 120 struct spi_device *spi; 121 121 struct clk *clk; 122 122 unsigned int output_mode; 123 + unsigned int (*scales)[2]; 123 124 124 125 struct gpio_desc *pwrdown_gpio; 125 126 /* ensure consistent state obtained on multiple related accesses */ ··· 217 216 .channel = _chan, \ 218 217 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 219 218 BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 219 + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ 220 220 .scan_index = _si, \ 221 221 .scan_type = { \ 222 222 .sign = _sign, \ ··· 372 370 } 373 371 } 374 372 373 + static int ad9467_read_avail(struct adi_axi_adc_conv *conv, 374 + struct iio_chan_spec const *chan, 375 + const int **vals, int *type, int *length, 376 + long mask) 377 + { 378 + const struct adi_axi_adc_chip_info *info = conv->chip_info; 379 + struct ad9467_state *st = adi_axi_adc_conv_priv(conv); 380 + 381 + switch (mask) { 382 + case IIO_CHAN_INFO_SCALE: 383 + *vals = (const int *)st->scales; 384 + *type = IIO_VAL_INT_PLUS_MICRO; 385 + /* Values are stored in a 2D matrix */ 386 + *length = info->num_scales * 2; 387 + return IIO_AVAIL_LIST; 388 + default: 389 + return -EINVAL; 390 + } 391 + } 392 + 375 393 static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) 376 394 { 377 395 int ret; ··· 402 380 403 381 return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, 404 382 AN877_ADC_TRANSFER_SYNC); 383 + } 384 + 385 + static int ad9467_scale_fill(struct adi_axi_adc_conv *conv) 386 + { 387 + const struct adi_axi_adc_chip_info *info = conv->chip_info; 388 + struct ad9467_state *st = adi_axi_adc_conv_priv(conv); 389 + unsigned int i, val1, val2; 390 + 391 + st->scales = devm_kmalloc_array(&st->spi->dev, info->num_scales, 392 + sizeof(*st->scales), GFP_KERNEL); 393 + if (!st->scales) 394 + return -ENOMEM; 395 + 396 + for (i = 0; i < info->num_scales; i++) { 397 + __ad9467_get_scale(conv, i, &val1, &val2); 398 + st->scales[i][0] = val1; 399 + st->scales[i][1] = val2; 400 + } 401 + 402 + return 0; 405 403 } 406 404 407 405 static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv) ··· 482 440 483 441 conv->chip_info = &info->axi_adc_info; 484 442 443 + ret = ad9467_scale_fill(conv); 444 + if (ret) 445 + return ret; 446 + 485 447 id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); 486 448 if (id != conv->chip_info->id) { 487 449 dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", ··· 496 450 conv->reg_access = ad9467_reg_access; 497 451 conv->write_raw = ad9467_write_raw; 498 452 conv->read_raw = ad9467_read_raw; 453 + conv->read_avail = ad9467_read_avail; 499 454 conv->preenable_setup = ad9467_preenable_setup; 500 455 501 456 st->output_mode = info->default_output_mode |
+15 -59
drivers/iio/adc/adi-axi-adc.c
··· 144 144 return conv->write_raw(conv, chan, val, val2, mask); 145 145 } 146 146 147 + static int adi_axi_adc_read_avail(struct iio_dev *indio_dev, 148 + struct iio_chan_spec const *chan, 149 + const int **vals, int *type, int *length, 150 + long mask) 151 + { 152 + struct adi_axi_adc_state *st = iio_priv(indio_dev); 153 + struct adi_axi_adc_conv *conv = &st->client->conv; 154 + 155 + if (!conv->read_avail) 156 + return -EOPNOTSUPP; 157 + 158 + return conv->read_avail(conv, chan, vals, type, length, mask); 159 + } 160 + 147 161 static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev, 148 162 const unsigned long *scan_mask) 149 163 { ··· 242 228 } 243 229 EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI); 244 230 245 - static ssize_t in_voltage_scale_available_show(struct device *dev, 246 - struct device_attribute *attr, 247 - char *buf) 248 - { 249 - struct iio_dev *indio_dev = dev_to_iio_dev(dev); 250 - struct adi_axi_adc_state *st = iio_priv(indio_dev); 251 - struct adi_axi_adc_conv *conv = &st->client->conv; 252 - size_t len = 0; 253 - int i; 254 - 255 - for (i = 0; i < conv->chip_info->num_scales; i++) { 256 - const unsigned int *s = conv->chip_info->scale_table[i]; 257 - 258 - len += scnprintf(buf + len, PAGE_SIZE - len, 259 - "%u.%06u ", s[0], s[1]); 260 - } 261 - buf[len - 1] = '\n'; 262 - 263 - return len; 264 - } 265 - 266 - static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0); 267 - 268 - enum { 269 - ADI_AXI_ATTR_SCALE_AVAIL, 270 - }; 271 - 272 - #define ADI_AXI_ATTR(_en_, _file_) \ 273 - [ADI_AXI_ATTR_##_en_] = &iio_dev_attr_##_file_.dev_attr.attr 274 - 275 - static struct attribute *adi_axi_adc_attributes[] = { 276 - ADI_AXI_ATTR(SCALE_AVAIL, in_voltage_scale_available), 277 - NULL 278 - }; 279 - 280 - static umode_t axi_adc_attr_is_visible(struct kobject *kobj, 281 - struct attribute *attr, int n) 282 - { 283 - struct device *dev = kobj_to_dev(kobj); 284 - struct iio_dev *indio_dev = dev_to_iio_dev(dev); 285 - struct adi_axi_adc_state *st = iio_priv(indio_dev); 286 - struct adi_axi_adc_conv *conv = &st->client->conv; 287 - 288 - switch (n) { 289 - case ADI_AXI_ATTR_SCALE_AVAIL: 290 - if (!conv->chip_info->num_scales) 291 - return 0; 292 - return attr->mode; 293 - default: 294 - return attr->mode; 295 - } 296 - } 297 - 298 - static const struct attribute_group adi_axi_adc_attribute_group = { 299 - .attrs = adi_axi_adc_attributes, 300 - .is_visible = axi_adc_attr_is_visible, 301 - }; 302 - 303 231 static const struct iio_info adi_axi_adc_info = { 304 232 .read_raw = &adi_axi_adc_read_raw, 305 233 .write_raw = &adi_axi_adc_write_raw, 306 - .attrs = &adi_axi_adc_attribute_group, 307 234 .update_scan_mode = &adi_axi_adc_update_scan_mode, 235 + .read_avail = &adi_axi_adc_read_avail, 308 236 }; 309 237 310 238 static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
+4
include/linux/iio/adc/adi-axi-adc.h
··· 41 41 * @reg_access IIO debugfs_reg_access hook for the client ADC 42 42 * @read_raw IIO read_raw hook for the client ADC 43 43 * @write_raw IIO write_raw hook for the client ADC 44 + * @read_avail IIO read_avail hook for the client ADC 44 45 */ 45 46 struct adi_axi_adc_conv { 46 47 const struct adi_axi_adc_chip_info *chip_info; ··· 55 54 int (*write_raw)(struct adi_axi_adc_conv *conv, 56 55 struct iio_chan_spec const *chan, 57 56 int val, int val2, long mask); 57 + int (*read_avail)(struct adi_axi_adc_conv *conv, 58 + struct iio_chan_spec const *chan, 59 + const int **val, int *type, int *length, long mask); 58 60 }; 59 61 60 62 struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,