From nobody Thu Apr 9 07:17:16 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E2822E5B09; Tue, 10 Mar 2026 14:32:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773153149; cv=none; b=svBWIAfrycXWCtA7HDWBoyyMFczp+LJFPIYpcDTYLj6M89hly0UsSfWIafSeX/XgXaTiu3UhIuiMJ77My1C8xG7h969Fj67zXXtJaTiwLFNNWvBr8ClQuVQ81TxJyHRczFeDRwIStX7GOtlLQk34s5AwLoMEUF6CVmnJAIQ8FG4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773153149; c=relaxed/simple; bh=bBF2rtekzvoQasSUpl7BEHEyiHLlTveAA6U1jsLWq5Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SzsNuPkOL9tkXRDw/JEZ9bNnpKHw9pCFDdxNQ1bEu7HEnEcqchF7beCv6Y5+H7EHCGzB8t7W6+eDnYj3/+th2e2DSPSQ41DxE+EfFneOODano0NQBOEZTBWlwGZqKBmUJWDSF4XSofmLBTDc6vBXxyPmq0Y26QrcmBd6qOEpxJc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I+f0V+Mm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I+f0V+Mm" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2503CC2BCB4; Tue, 10 Mar 2026 14:32:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773153149; bh=bBF2rtekzvoQasSUpl7BEHEyiHLlTveAA6U1jsLWq5Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=I+f0V+MmzgdhsI3bXVKlurI/jEfT1Wr7bsc45iScSa6U3wU8CPByvReMK0H4YE3SM 7OQoEXxw4FRg8+oa22RFtLTZYZZV8u5KWUZnQu9zmPZvwfdtxxDzSwH2WAnxeIMNcW PSdqE+Osa03Z7CnK8AA9VTSIaU2az9BIAGllORrufwpZlXOkXhwoXVm4lQHxNOHBij Aio4ekAOiez9qY51n//4p4OqRjNwTg4CPA5psz5up+tqnzNDN/SUuafNI4pkMR6r0H rMStqekcZRkhwyRU6oajmqLMwuIfDQaQIZMgi2u/bppquK5MQbsBr++nIcra6TTgXv lKxT8hHnPSQJQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16820EB1054; Tue, 10 Mar 2026 14:32:29 +0000 (UTC) From: Radu Sabau via B4 Relay Date: Tue, 10 Mar 2026 16:32:24 +0200 Subject: [PATCH v2 3/4] iio: adc: ad4691: add triggered buffer support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260310-ad4692-multichannel-sar-adc-driver-v2-3-d9bb8aeb5e17@analog.com> References: <20260310-ad4692-multichannel-sar-adc-driver-v2-0-d9bb8aeb5e17@analog.com> In-Reply-To: <20260310-ad4692-multichannel-sar-adc-driver-v2-0-d9bb8aeb5e17@analog.com> To: Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org, linux-gpio@vger.kernel.org, Radu Sabau X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1773153147; l=17111; i=radu.sabau@analog.com; s=20260220; h=from:subject:message-id; bh=8O0mQbD6rNXGpXxojq9wOKjwgwNr9Jd2ObpkjUzk0Ks=; b=8rQf21NJGtDw/WIw/edZpx7wwFdV43cHP5MMm1JrP7PINXCKdYnubWP1s1B5AaB/hqw+VnhiF bOGLtDtcxjKAA2u2EuWnkAhiwkK9Cman1zdwYh30jTowcl6TGq/h1bW X-Developer-Key: i=radu.sabau@analog.com; a=ed25519; pk=lDPQHgn9jTdt0vo58Na9lLxLaE2mb330if71Cn+EvFU= X-Endpoint-Received: by B4 Relay for radu.sabau@analog.com/20260220 with auth_id=642 X-Original-From: Radu Sabau Reply-To: radu.sabau@analog.com From: Radu Sabau Add buffered capture support using the IIO triggered buffer framework. Both operating modes share a single IIO trigger and trigger handler. The handler builds a complete scan =E2=80=94 one u32 slot per channel at its scan_index position, followed by a timestamp =E2=80=94 and pushes it to the IIO buffer in a single iio_push_to_buffers_with_ts() call. For CNV Clock Mode the GP0 pin is configured as DATA_READY output. The IRQ handler stops conversions and fires the IIO trigger; the trigger handler reads accumulated results from the AVG_IN registers via regmap and restarts conversions for the next cycle. For Manual Mode there is no DATA_READY signal; CNV is tied to SPI CS so conversions are triggered by CS assertion rather than by a dedicated pin. The standard iio-trig-hrtimer module is not used because the timer period must be derived from the SPI clock rate and the number of active channels: the pipelined protocol requires N+1 SPI transfers per scan (the first result is garbage and is discarded), so the minimum period depends on both the SPI speed and the live channel count at buffer enable time. A driver-private hrtimer whose period is recomputed by buffer_postenable is simpler and avoids requiring the user to configure an external trigger with the correct hardware-derived period. Manual mode channels use storagebits=3D32 (shift=3D8, realbits=3D16) so all channel slots in the scan buffer are uniformly sized regardless of the SPI wire format (24-bit transfer, 16-bit ADC data in bits[23:8]). Signed-off-by: Radu Sabau --- drivers/iio/adc/Kconfig | 2 + drivers/iio/adc/ad4691.c | 405 +++++++++++++++++++++++++++++++++++++++++++= +--- 2 files changed, 382 insertions(+), 25 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 3685a03aa8dc..d498f16c0816 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -142,6 +142,8 @@ config AD4170_4 config AD4691 tristate "Analog Devices AD4691 Family ADC Driver" depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER select REGMAP help Say yes here to build support for Analog Devices AD4691 Family MuxSAR diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c index 528c37a9a383..8b3caf0334ba 100644 --- a/drivers/iio/adc/ad4691.c +++ b/drivers/iio/adc/ad4691.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -25,8 +26,13 @@ #include #include =20 +#include #include =20 +#include +#include +#include + #include =20 #define AD4691_VREF_MIN 2400000 @@ -71,7 +77,7 @@ #define AD4691_ACC_MASK1_REG 0x184 #define AD4691_ACC_MASK2_REG 0x185 #define AD4691_ACC_COUNT_LIMIT(n) (0x186 + (n)) -#define AD4691_ACC_COUNT_VAL 0x3F +#define AD4691_ACC_COUNT_VAL 0x01 #define AD4691_GPIO_MODE1_REG 0x196 #define AD4691_GPIO_MODE2_REG 0x197 #define AD4691_GPIO_READ 0x1A0 @@ -161,33 +167,33 @@ static const struct iio_chan_spec ad4693_channels[] = =3D { }; =20 static const struct iio_chan_spec ad4691_manual_channels[] =3D { - AD4691_CHANNEL(0, 0, 16, 24, 8), - AD4691_CHANNEL(1, 1, 16, 24, 8), - AD4691_CHANNEL(2, 2, 16, 24, 8), - AD4691_CHANNEL(3, 3, 16, 24, 8), - AD4691_CHANNEL(4, 4, 16, 24, 8), - AD4691_CHANNEL(5, 5, 16, 24, 8), - AD4691_CHANNEL(6, 6, 16, 24, 8), - AD4691_CHANNEL(7, 7, 16, 24, 8), - AD4691_CHANNEL(8, 8, 16, 24, 8), - AD4691_CHANNEL(9, 9, 16, 24, 8), - AD4691_CHANNEL(10, 10, 16, 24, 8), - AD4691_CHANNEL(11, 11, 16, 24, 8), - AD4691_CHANNEL(12, 12, 16, 24, 8), - AD4691_CHANNEL(13, 13, 16, 24, 8), - AD4691_CHANNEL(14, 14, 16, 24, 8), - AD4691_CHANNEL(15, 15, 16, 24, 8) + AD4691_CHANNEL(0, 0, 16, 32, 8), + AD4691_CHANNEL(1, 1, 16, 32, 8), + AD4691_CHANNEL(2, 2, 16, 32, 8), + AD4691_CHANNEL(3, 3, 16, 32, 8), + AD4691_CHANNEL(4, 4, 16, 32, 8), + AD4691_CHANNEL(5, 5, 16, 32, 8), + AD4691_CHANNEL(6, 6, 16, 32, 8), + AD4691_CHANNEL(7, 7, 16, 32, 8), + AD4691_CHANNEL(8, 8, 16, 32, 8), + AD4691_CHANNEL(9, 9, 16, 32, 8), + AD4691_CHANNEL(10, 10, 16, 32, 8), + AD4691_CHANNEL(11, 11, 16, 32, 8), + AD4691_CHANNEL(12, 12, 16, 32, 8), + AD4691_CHANNEL(13, 13, 16, 32, 8), + AD4691_CHANNEL(14, 14, 16, 32, 8), + AD4691_CHANNEL(15, 15, 16, 32, 8) }; =20 static const struct iio_chan_spec ad4693_manual_channels[] =3D { - AD4691_CHANNEL(0, 0, 16, 24, 8), - AD4691_CHANNEL(1, 1, 16, 24, 8), - AD4691_CHANNEL(2, 2, 16, 24, 8), - AD4691_CHANNEL(3, 3, 16, 24, 8), - AD4691_CHANNEL(4, 4, 16, 24, 8), - AD4691_CHANNEL(5, 5, 16, 24, 8), - AD4691_CHANNEL(6, 6, 16, 24, 8), - AD4691_CHANNEL(7, 7, 16, 24, 8) + AD4691_CHANNEL(0, 0, 16, 32, 8), + AD4691_CHANNEL(1, 1, 16, 32, 8), + AD4691_CHANNEL(2, 2, 16, 32, 8), + AD4691_CHANNEL(3, 3, 16, 32, 8), + AD4691_CHANNEL(4, 4, 16, 32, 8), + AD4691_CHANNEL(5, 5, 16, 32, 8), + AD4691_CHANNEL(6, 6, 16, 32, 8), + AD4691_CHANNEL(7, 7, 16, 32, 8) }; =20 static const struct ad4691_chip_info ad4691_ad4691 =3D { @@ -230,6 +236,8 @@ struct ad4691_state { unsigned long ref_clk_rate; struct pwm_device *conv_trigger; =20 + struct iio_trigger *trig; + enum ad4691_adc_mode adc_mode; =20 int vref; @@ -239,6 +247,22 @@ struct ad4691_state { * atomicity of consecutive SPI operations. */ struct mutex lock; + + /* hrtimer for MANUAL_MODE triggered buffer (non-offload) */ + struct hrtimer sampling_timer; + ktime_t sampling_period; + + /* + * DMA (thus cache coherency maintenance) may require the + * transfer buffers to live in their own cache lines. + */ + unsigned char rx_data[ALIGN(3, sizeof(s64)) + sizeof(s64)] __aligned(IIO_= DMA_MINALIGN); + unsigned char tx_data[ALIGN(3, sizeof(s64)) + sizeof(s64)]; + /* Scan buffer: one slot per channel (u32) plus timestamp */ + struct { + u32 vals[16]; + s64 ts __aligned(8); + } scan __aligned(IIO_DMA_MINALIGN); }; =20 static void ad4691_disable_pwm(void *data) @@ -394,6 +418,27 @@ static const struct regmap_config ad4691_regmap_config= =3D { .cache_type =3D REGCACHE_RBTREE, }; =20 +static int ad4691_transfer(struct ad4691_state *st, int command, + unsigned int *val) +{ + struct spi_transfer xfer =3D { + .tx_buf =3D st->tx_data, + .rx_buf =3D st->rx_data, + .len =3D 3, + }; + int ret; + + memcpy(st->tx_data, &command, 3); + + ret =3D spi_sync_transfer(st->spi, &xfer, 1); + if (ret) + return ret; + + *val =3D get_unaligned_be24(st->rx_data); + + return 0; +} + static int ad4691_get_sampling_freq(struct ad4691_state *st) { if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) { @@ -478,6 +523,18 @@ static int ad4691_set_sampling_freq(struct iio_dev *in= dio_dev, unsigned int freq return __ad4691_set_sampling_freq(st, freq); } =20 +static int ad4691_sampling_enable(struct ad4691_state *st, bool enable) +{ + struct pwm_state conv_state =3D { }; + + conv_state.period =3D st->cnv_period; + conv_state.duty_cycle =3D AD4691_CNV_DUTY_CYCLE_NS; + conv_state.polarity =3D PWM_POLARITY_NORMAL; + conv_state.enabled =3D enable; + + return pwm_apply_might_sleep(st->conv_trigger, &conv_state); +} + static int ad4691_single_shot_read(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val) { @@ -592,6 +649,240 @@ static int ad4691_reg_access(struct iio_dev *indio_de= v, unsigned int reg, return regmap_write(st->regmap, reg, writeval); } =20 +/* + * ad4691_enter_conversion_mode - Switch the chip to its buffer conversion= mode. + * + * Configures the ADC hardware registers for the mode selected at probe + * (CNV_CLOCK or MANUAL). Called from buffer postenable before starting + * sampling. The chip is in AUTONOMOUS mode during idle (for read_raw). + */ +static int ad4691_enter_conversion_mode(struct ad4691_state *st) +{ + int ret; + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) + return regmap_write(st->regmap, AD4691_DEVICE_SETUP, + AD4691_DEVICE_MANUAL); + + ret =3D regmap_write(st->regmap, AD4691_ADC_SETUP, AD4691_CNV_CLOCK_MODE); + if (ret) + return ret; + + return regmap_write(st->regmap, AD4691_GPIO_MODE1_REG, + AD4691_DATA_READY); +} + +/* + * ad4691_exit_conversion_mode - Return the chip to AUTONOMOUS mode. + * + * Called from buffer postdisable/predisable to restore the chip to the + * idle state used by read_raw. Clears the sequencer and resets state. + */ +static int ad4691_exit_conversion_mode(struct ad4691_state *st) +{ + int ret; + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) { + ret =3D regmap_write(st->regmap, AD4691_DEVICE_SETUP, + AD4691_DEVICE_REGISTER); + if (ret) + return ret; + } + + ret =3D regmap_write(st->regmap, AD4691_ADC_SETUP, AD4691_AUTONOMOUS_MODE= _VAL); + if (ret) + return ret; + + /* Restore GP0 to ADC_BUSY for AUTONOMOUS idle (enter set it to DATA_READ= Y) */ + ret =3D regmap_write(st->regmap, AD4691_GPIO_MODE1_REG, AD4691_ADC_BUSY); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, + AD4691_SEQ_ALL_CHANNELS_OFF); + if (ret) + return ret; + + return regmap_write(st->regmap, AD4691_STATE_RESET_REG, + AD4691_STATE_RESET_ALL); +} + +static int ad4691_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st =3D iio_priv(indio_dev); + int n_active =3D hweight_long(*indio_dev->active_scan_mask); + unsigned int bit; + int ret; + + ret =3D ad4691_enter_conversion_mode(st); + if (ret) + return ret; + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) { + u64 min_period_ns; + + /* N+1 transfers needed for N channels, with 50% overhead */ + min_period_ns =3D div64_u64((u64)(n_active + 1) * AD4691_BITS_PER_XFER * + NSEC_PER_SEC * 3, + st->spi->max_speed_hz * 2); + + if (ktime_to_ns(st->sampling_period) < min_period_ns) { + dev_err(&st->spi->dev, + "Sampling period %lld ns too short for %d channels. Min: %llu ns\n", + ktime_to_ns(st->sampling_period), n_active, + min_period_ns); + return -EINVAL; + } + + hrtimer_start(&st->sampling_timer, st->sampling_period, + HRTIMER_MODE_REL); + return 0; + } + + /* CNV_CLOCK_MODE: configure sequencer and start PWM */ + ret =3D regmap_write(st->regmap, AD4691_STATE_RESET_REG, + AD4691_STATE_RESET_ALL); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, AD4691_ACC_MASK1_REG, + ~(*indio_dev->active_scan_mask) & 0xFF); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, AD4691_ACC_MASK2_REG, + ~(*indio_dev->active_scan_mask >> 8) & 0xFF); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, + *indio_dev->active_scan_mask); + if (ret) + return ret; + + iio_for_each_active_channel(indio_dev, bit) { + ret =3D regmap_write(st->regmap, AD4691_ACC_COUNT_LIMIT(bit), + AD4691_ACC_COUNT_VAL); + if (ret) + return ret; + } + + return ad4691_sampling_enable(st, true); +} + +static int ad4691_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ad4691_state *st =3D iio_priv(indio_dev); + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) + hrtimer_cancel_wait_running(&st->sampling_timer); + else + ad4691_sampling_enable(st, false); + + return ad4691_exit_conversion_mode(st); +} + +static const struct iio_buffer_setup_ops ad4691_buffer_setup_ops =3D { + .postenable =3D &ad4691_buffer_postenable, + .postdisable =3D &ad4691_buffer_postdisable, +}; + +static irqreturn_t ad4691_irq(int irq, void *private) +{ + struct iio_dev *indio_dev =3D private; + struct ad4691_state *st =3D iio_priv(indio_dev); + + /* + * DATA_READY has asserted: stop conversions before reading so the + * accumulator does not continue sampling while the trigger handler + * processes the data. Then fire the IIO trigger to push the sample + * to the buffer. + */ + ad4691_sampling_enable(st, false); + iio_trigger_poll(st->trig); + + return IRQ_HANDLED; +} + +static enum hrtimer_restart ad4691_sampling_timer_handler(struct hrtimer *= timer) +{ + struct ad4691_state *st =3D container_of(timer, struct ad4691_state, + sampling_timer); + + iio_trigger_poll(st->trig); + hrtimer_forward_now(timer, st->sampling_period); + + return HRTIMER_RESTART; +} + +static const struct iio_trigger_ops ad4691_trigger_ops =3D { + .validate_device =3D iio_trigger_validate_own_device, +}; + +static irqreturn_t ad4691_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf =3D p; + struct iio_dev *indio_dev =3D pf->indio_dev; + struct ad4691_state *st =3D iio_priv(indio_dev); + unsigned int val; + int ret, i; + + mutex_lock(&st->lock); + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) { + unsigned int prev_val; + int prev_chan =3D -1; + + /* + * MANUAL_MODE with CNV tied to CS: each transfer triggers a + * conversion AND returns the previous conversion's result. + * First transfer returns garbage, so we do N+1 transfers for + * N channels. Collect all results into scan.vals[], then push + * the complete scan once. + */ + iio_for_each_active_channel(indio_dev, i) { + ret =3D ad4691_transfer(st, AD4691_ADC_CHAN(i), &val); + if (ret) + goto done; + + if (prev_chan >=3D 0) + st->scan.vals[prev_chan] =3D prev_val; + prev_val =3D val; + prev_chan =3D i; + } + + /* Final NOOP transfer to retrieve last channel's result */ + ret =3D ad4691_transfer(st, AD4691_NOOP, &val); + if (ret) + goto done; + + st->scan.vals[prev_chan] =3D val; + } else { + for (i =3D 0; i < st->chip->num_channels; i++) { + if (BIT(i) & *indio_dev->active_scan_mask) { + ret =3D regmap_read(st->regmap, AD4691_AVG_IN(i), &val); + if (ret) + goto done; + + st->scan.vals[i] =3D val; + } + } + + regmap_write(st->regmap, AD4691_STATE_RESET_REG, AD4691_STATE_RESET_ALL); + + /* Restart conversions for the next trigger cycle. */ + ad4691_sampling_enable(st, true); + } + + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + pf->timestamp); + +done: + iio_trigger_notify_done(indio_dev->trig); + mutex_unlock(&st->lock); + return IRQ_HANDLED; +} + static const struct iio_info ad4691_info =3D { .read_raw =3D &ad4691_read_raw, .write_raw =3D &ad4691_write_raw, @@ -690,6 +981,66 @@ static int ad4691_config(struct ad4691_state *st) return regmap_write(st->regmap, AD4691_GPIO_MODE1_REG, AD4691_ADC_BUSY); } =20 +static int ad4691_setup_triggered_buffer(struct iio_dev *indio_dev, + struct ad4691_state *st) +{ + struct device *dev =3D &st->spi->dev; + int irq, ret; + + st->trig =3D devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + iio_device_id(indio_dev)); + if (!st->trig) + return dev_err_probe(dev, -ENOMEM, + "Failed to allocate IIO trigger\n"); + + st->trig->ops =3D &ad4691_trigger_ops; + iio_trigger_set_drvdata(st->trig, st); + + ret =3D devm_iio_trigger_register(dev, st->trig); + if (ret) + return dev_err_probe(dev, ret, "IIO trigger register failed\n"); + + indio_dev->trig =3D iio_trigger_get(st->trig); + + if (st->adc_mode =3D=3D AD4691_MANUAL_MODE) { + /* + * No DATA_READY signal in MANUAL_MODE; CNV is tied to CS so + * conversions start with each SPI transfer. Use an hrtimer to + * schedule periodic reads. + */ + hrtimer_setup(&st->sampling_timer, ad4691_sampling_timer_handler, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + st->sampling_period =3D ns_to_ktime(DIV_ROUND_CLOSEST_ULL( + NSEC_PER_SEC, + AD4691_MANUAL_MODE_STD_FREQ(st->chip->num_channels, + st->spi->max_speed_hz))); + } else { + /* + * DATA_READY asserts at end-of-conversion. The IRQ handler + * stops conversions and fires the IIO trigger so the trigger + * handler can read and push the sample to the buffer. + */ + irq =3D fwnode_irq_get(dev_fwnode(dev), 0); + if (irq <=3D 0) + return dev_err_probe(dev, irq ? irq : -ENOENT, + "failed to get DATA_READY interrupt\n"); + + ret =3D devm_request_threaded_irq(dev, irq, NULL, + &ad4691_irq, + IRQF_ONESHOT, + indio_dev->name, indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "request irq %d failed\n", irq); + } + + return devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, + &ad4691_trigger_handler, + &ad4691_buffer_setup_ops); +} + static int ad4691_probe(struct spi_device *spi) { struct device *dev =3D &spi->dev; @@ -737,6 +1088,10 @@ static int ad4691_probe(struct spi_device *spi) ? st->chip->manual_channels : st->chip->channels; indio_dev->num_channels =3D st->chip->num_channels; =20 + ret =3D ad4691_setup_triggered_buffer(indio_dev, st); + if (ret) + return ret; + return devm_iio_device_register(dev, indio_dev); } =20 --=20 2.43.0