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: ad7606: move scale_setup as function pointer on chip-info

Up until now, all ADCs were 16-bit precision.
With the addition of the AD7606C some things will change. For one thing,
we'll need to setup available-scales for each channel. Also for the 18-bit
precision variants, the scales will be different.

This change adds a function-pointer to the chip-info struct to be able to
set this up (differently) for the new parts. For the current parts, the
scales are the same (for all parts) between HW and SW modes.

Also creating a 'ad7606_sw_mode_setup()' function that must be called
before the scale_setup callback. This is needed in case SW mode is enabled
for some ADCs.

Signed-off-by: Alexandru Ardelean <aardelean@baylibre.com>
Link: https://patch.msgid.link/20240919130444.2100447-4-aardelean@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Alexandru Ardelean and committed by
Jonathan Cameron
e571c190 d2041446

+68 -22
+62 -22
drivers/iio/adc/ad7606.c
··· 32 32 * Scales are computed as 5000/32768 and 10000/32768 respectively, 33 33 * so that when applied to the raw values they provide mV values 34 34 */ 35 - static const unsigned int ad7606_scale_avail[2] = { 35 + static const unsigned int ad7606_16bit_hw_scale_avail[2] = { 36 36 152588, 305176 37 37 }; 38 38 39 39 40 - static const unsigned int ad7616_sw_scale_avail[3] = { 40 + static const unsigned int ad7606_16bit_sw_scale_avail[3] = { 41 41 76293, 152588, 305176 42 42 }; 43 43 ··· 61 61 return -ENODEV; 62 62 } 63 63 EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606); 64 + 65 + static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st, int ch) 66 + { 67 + if (!st->sw_mode_en) { 68 + /* tied to logic low, analog input range is +/- 5V */ 69 + st->range[ch] = 0; 70 + st->scale_avail = ad7606_16bit_hw_scale_avail; 71 + st->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail); 72 + return 0; 73 + } 74 + 75 + /* Scale of 0.076293 is only available in sw mode */ 76 + /* After reset, in software mode, ±10 V is set by default */ 77 + st->range[ch] = 2; 78 + st->scale_avail = ad7606_16bit_sw_scale_avail; 79 + st->num_scales = ARRAY_SIZE(ad7606_16bit_sw_scale_avail); 80 + 81 + return 0; 82 + } 64 83 65 84 static int ad7606_reg_access(struct iio_dev *indio_dev, 66 85 unsigned int reg, ··· 377 358 [ID_AD7605_4] = { 378 359 .channels = ad7605_channels, 379 360 .num_channels = 5, 361 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 380 362 }, 381 363 [ID_AD7606_8] = { 382 364 .channels = ad7606_channels_16bit, 383 365 .num_channels = 9, 366 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 384 367 .oversampling_avail = ad7606_oversampling_avail, 385 368 .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), 386 369 }, 387 370 [ID_AD7606_6] = { 388 371 .channels = ad7606_channels_16bit, 389 372 .num_channels = 7, 373 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 390 374 .oversampling_avail = ad7606_oversampling_avail, 391 375 .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), 392 376 }, 393 377 [ID_AD7606_4] = { 394 378 .channels = ad7606_channels_16bit, 395 379 .num_channels = 5, 380 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 396 381 .oversampling_avail = ad7606_oversampling_avail, 397 382 .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), 398 383 }, 399 384 [ID_AD7606B] = { 400 385 .channels = ad7606_channels_16bit, 401 386 .num_channels = 9, 387 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 402 388 .oversampling_avail = ad7606_oversampling_avail, 403 389 .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail), 404 390 }, 405 391 [ID_AD7616] = { 406 392 .channels = ad7616_channels, 407 393 .num_channels = 17, 394 + .scale_setup_cb = ad7606_16bit_chan_scale_setup, 408 395 .oversampling_avail = ad7616_oversampling_avail, 409 396 .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail), 410 397 .os_req_reset = true, ··· 548 523 .validate_device = iio_trigger_validate_own_device, 549 524 }; 550 525 526 + static int ad7606_sw_mode_setup(struct iio_dev *indio_dev) 527 + { 528 + struct ad7606_state *st = iio_priv(indio_dev); 529 + 530 + st->sw_mode_en = st->bops->sw_mode_config && 531 + device_property_present(st->dev, "adi,sw-mode"); 532 + if (!st->sw_mode_en) 533 + return 0; 534 + 535 + indio_dev->info = &ad7606_info_os_range_and_debug; 536 + 537 + return st->bops->sw_mode_config(indio_dev); 538 + } 539 + 540 + static int ad7606_chan_scales_setup(struct iio_dev *indio_dev) 541 + { 542 + unsigned int num_channels = indio_dev->num_channels - 1; 543 + struct ad7606_state *st = iio_priv(indio_dev); 544 + int ch, ret; 545 + 546 + for (ch = 0; ch < num_channels; ch++) { 547 + ret = st->chip_info->scale_setup_cb(st, ch); 548 + if (ret) 549 + return ret; 550 + } 551 + 552 + return 0; 553 + } 554 + 551 555 int ad7606_probe(struct device *dev, int irq, void __iomem *base_address, 552 556 const char *name, unsigned int id, 553 557 const struct ad7606_bus_ops *bops) ··· 596 542 mutex_init(&st->lock); 597 543 st->bops = bops; 598 544 st->base_address = base_address; 599 - /* tied to logic low, analog input range is +/- 5V */ 600 - st->range[0] = 0; 601 545 st->oversampling = 1; 602 - st->scale_avail = ad7606_scale_avail; 603 - st->num_scales = ARRAY_SIZE(ad7606_scale_avail); 604 546 605 547 ret = devm_regulator_get_enable(dev, "avcc"); 606 548 if (ret) ··· 645 595 st->write_scale = ad7606_write_scale_hw; 646 596 st->write_os = ad7606_write_os_hw; 647 597 648 - if (st->bops->sw_mode_config) 649 - st->sw_mode_en = device_property_present(st->dev, 650 - "adi,sw-mode"); 598 + ret = ad7606_sw_mode_setup(indio_dev); 599 + if (ret) 600 + return ret; 651 601 652 - if (st->sw_mode_en) { 653 - /* Scale of 0.076293 is only available in sw mode */ 654 - st->scale_avail = ad7616_sw_scale_avail; 655 - st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail); 656 - 657 - /* After reset, in software mode, ±10 V is set by default */ 658 - memset32(st->range, 2, ARRAY_SIZE(st->range)); 659 - indio_dev->info = &ad7606_info_os_range_and_debug; 660 - 661 - ret = st->bops->sw_mode_config(indio_dev); 662 - if (ret < 0) 663 - return ret; 664 - } 602 + ret = ad7606_chan_scales_setup(indio_dev); 603 + if (ret) 604 + return ret; 665 605 666 606 st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", 667 607 indio_dev->name,
+6
drivers/iio/adc/ad7606.h
··· 40 40 41 41 #define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16) 42 42 43 + struct ad7606_state; 44 + 45 + typedef int (*ad7606_scale_setup_cb_t)(struct ad7606_state *st, int ch); 46 + 43 47 /** 44 48 * struct ad7606_chip_info - chip specific information 45 49 * @channels: channel specification 46 50 * @num_channels: number of channels 51 + * @scale_setup_cb: callback to setup the scales for each channel 47 52 * @oversampling_avail pointer to the array which stores the available 48 53 * oversampling ratios. 49 54 * @oversampling_num number of elements stored in oversampling_avail array ··· 59 54 struct ad7606_chip_info { 60 55 const struct iio_chan_spec *channels; 61 56 unsigned int num_channels; 57 + ad7606_scale_setup_cb_t scale_setup_cb; 62 58 const unsigned int *oversampling_avail; 63 59 unsigned int oversampling_num; 64 60 bool os_req_reset;