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: ad4695: make ad4695_exit_conversion_mode() more robust

Ensure that conversion mode is successfully exited when the command is
issued by adding an extra transfer beforehand, matching the minimum CNV
high and low times from the AD4695 datasheet. The AD4695 has a quirk
where the exit command only works during a conversion, so guarantee this
happens by triggering a conversion in ad4695_exit_conversion_mode().
Then make this even more robust by ensuring that the exit command is run
at AD4695_REG_ACCESS_SCLK_HZ rather than the bus maximum.

Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Tested-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20241113-tgamblin-ad4695_improvements-v2-2-b6bb7c758fc4@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Trevor Gamblin and committed by
Jonathan Cameron
998d20e4 7ecbbb5b

+28 -6
+28 -6
drivers/iio/adc/ad4695.c
··· 92 92 #define AD4695_T_REFBUF_MS 100 93 93 #define AD4695_T_REGCONFIG_NS 20 94 94 #define AD4695_T_SCK_CNV_DELAY_NS 80 95 + #define AD4695_T_CNVL_NS 80 96 + #define AD4695_T_CNVH_NS 10 95 97 #define AD4695_REG_ACCESS_SCLK_HZ (10 * MEGA) 96 98 97 99 /* Max number of voltage input channels. */ ··· 366 364 */ 367 365 static int ad4695_exit_conversion_mode(struct ad4695_state *st) 368 366 { 369 - struct spi_transfer xfer = { 370 - .tx_buf = &st->cnv_cmd2, 371 - .len = 1, 372 - .delay.value = AD4695_T_REGCONFIG_NS, 373 - .delay.unit = SPI_DELAY_UNIT_NSECS, 367 + /* 368 + * An extra transfer is needed to trigger a conversion here so 369 + * that we can be 100% sure the command will be processed by the 370 + * ADC, rather than relying on it to be in the correct state 371 + * when this function is called (this chip has a quirk where the 372 + * command only works when reading a conversion, and if the 373 + * previous conversion was already read then it won't work). The 374 + * actual conversion command is then run at the slower 375 + * AD4695_REG_ACCESS_SCLK_HZ speed to guarantee this works. 376 + */ 377 + struct spi_transfer xfers[] = { 378 + { 379 + .delay.value = AD4695_T_CNVL_NS, 380 + .delay.unit = SPI_DELAY_UNIT_NSECS, 381 + .cs_change = 1, 382 + .cs_change_delay.value = AD4695_T_CNVH_NS, 383 + .cs_change_delay.unit = SPI_DELAY_UNIT_NSECS, 384 + }, 385 + { 386 + .speed_hz = AD4695_REG_ACCESS_SCLK_HZ, 387 + .tx_buf = &st->cnv_cmd2, 388 + .len = 1, 389 + .delay.value = AD4695_T_REGCONFIG_NS, 390 + .delay.unit = SPI_DELAY_UNIT_NSECS, 391 + }, 374 392 }; 375 393 376 394 /* ··· 399 377 */ 400 378 st->cnv_cmd2 = AD4695_CMD_EXIT_CNV_MODE << 3; 401 379 402 - return spi_sync_transfer(st->spi, &xfer, 1); 380 + return spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); 403 381 } 404 382 405 383 static int ad4695_set_ref_voltage(struct ad4695_state *st, int vref_mv)