From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-oi1-f175.google.com (mail-oi1-f175.google.com [209.85.167.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DC093A7829 for ; Fri, 10 Apr 2026 21:00:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.175 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775854849; cv=none; b=GpyNtNaMXHXgUnlWkKHDaE7W1NZcKFFxoivRBxpLq0aeiP2Gu7eSXhrU15isnq2omp1AV+DUlUlkX5tH0EnC7+XfIDLRH/l0hZR1mO4h8T8dnHQli0TveZlw98I4pdoDMOQiO8UPIox4Makt4SRMIzWymvFm+avfs7C6XHOEGVI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775854849; c=relaxed/simple; bh=6rP/2NeocjyaqMUftXzW/8uQUv6ELa/rQzdfz7/fRSg=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=qGdL2hIcmnUjyhNKSoZL+XraWCqwVoNocoRnNVZ6rOHsuS+R2+DCelcCgF5YCwh/97e6LvPL29KeZOcm13tjSz8gsJiNkEDQj6975L7XCcX6Vpv+4k47GCJTqO6M8tbABqUtOt/nwNA8EbAk9Qck3BuWtIAdzp15v7ouwRyFV+s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b=kfMDwnux; arc=none smtp.client-ip=209.85.167.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.b="kfMDwnux" Received: by mail-oi1-f175.google.com with SMTP id 5614622812f47-471618e20a5so1337535b6e.1 for ; Fri, 10 Apr 2026 14:00:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1775854846; x=1776459646; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=zjiDa43R9nZMxJdozPmDaP5r3lj4EBR+Ho5duYukD5Y=; b=kfMDwnuxX208vL6zZvAkBA23GL9w75AFNCa22xIW/a9zPHibIsn2cZeajisN6A4zyV hv0TPZOirjkRj/H8gG44ElTS3KhdKXkBG7nRfzJ/VLV3ZmyGsc4KWXijmLyGnu949MXm OEqM2Exi7tu5BUcmTDgGIiXKq+cWffJv/BCttYzL0TT2Xx+ifb4Vbj67kb0tYSQF/pm8 FbwO88DcDJh3A4VHBjQxQ/69Z3KgdCZHWUY05vPK+RSLvNIz3pfYwW9JGmvwJr9KynxG Bu/FCocUDT5NhJVrnib+MOmKNllCTDTeIRaUQQGjElWicxWKuWNdO8MZa3X5ULK0kQGK adgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775854846; x=1776459646; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=zjiDa43R9nZMxJdozPmDaP5r3lj4EBR+Ho5duYukD5Y=; b=hlhZAClpOrPrNDLYgLMGk4+9NzFUCf4WNvA0gxNE8tTHSDw/OU62IVH8jvLDH8qEKM LG03ZAcbaURXJKOfYx+2cUQ7fpRR5CSl35sLeizg2mZZ3TF2zep0w3ObnkBvR5HXmdmm rLOB6Spvk3MKWVP7CiIVOAHVhQrSoc8XAAFd5wgMS8TQdDLF2L+G2/5EXXmnb9GUrn6X 6RGzRGJxq8dFn48NCjD4iM/V8urYUeknMBxcHY1l6JqsdCRxI440AGRc7v+Jem577J9Y i85HNdFCoqB0q8zajEDy9NM/G5VHOEXxUHs92sliCp0cA47HPnKm1zyZfaRm4wGwWx/1 YdCA== X-Forwarded-Encrypted: i=1; AJvYcCVZv+1Yl0/VWPMSsarXLNb1V2BFk1Pt1JKXVqToMKa7NPpM1PEYm8+ZyzS6zn+EGxLp+Q8Rwx59m7lu@vger.kernel.org X-Gm-Message-State: AOJu0Yw1zqDWj2F5jZO2wJF17gnI//8E9B3mFWsckHNsZdILTocndPXi IAGiflWAyJagMbEm+rUzFbbHCB9MCO3fWmtggpzr2cVMYWjKobQbbEQgKUEwRdqmRvs= X-Gm-Gg: AeBDiesNsimK2NBLXV/b0/xn6uPpGiGHe9p4PLvdYCYqXYOzanKXXjjyJEhw/bIBMED HTN6VVDLdADWjdzVztmH39ONoQsUdd6V64wFsJrr876bQlUwd3oL86XgqEiI2I8N30mbnyv9uVf yvj0c703IZDwwwNbZa+fhEfZ6ssz6quP/9WpKuDXZLmSXDmfS2K3/XxF2GCBSmA/CrsyluHTpOJ cH+tSSPJoRoK8VOwDACGa8IEKA8t9sO3MKbEk9/iMhltKBsRUPF/AWy6qJjyKBzjz5XKJm2dNEC 7Anbg+dAMinopZtss9yn3TztbUVkZCHFLNYuAzR0tlBBUns4blTJ+kKOM/c/924xVqhRsqBk91b 1swMRkA0fneeS9VjaD3DD7hMJhn8jW15GksKW4sh9esWBvHvlDsmgT6xVcHku6gkCGerpF9nXwk PGw7NCeX2JGIRAsotUGFLRO1xMQxHzvcyTfTUCer+El1PA2dHIGNvAyUi5pt2bX/dnq6ug9rQ1z alY9kkGsrvi X-Received: by 2002:a05:6808:470b:b0:46c:cdf4:1bde with SMTP id 5614622812f47-4789ca3aaadmr2638671b6e.10.1775854846014; Fri, 10 Apr 2026 14:00:46 -0700 (PDT) Received: from ?IPV6:2600:8803:e7e4:500:b75d:2440:dc10:808b? ([2600:8803:e7e4:500:b75d:2440:dc10:808b]) by smtp.gmail.com with ESMTPSA id 5614622812f47-478a3a78204sm2094472b6e.18.2026.04.10.14.00.42 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 10 Apr 2026 14:00:44 -0700 (PDT) Message-ID: <1170956f-da05-4280-990f-64306ca905c2@baylibre.com> Date: Fri, 10 Apr 2026 16:00:42 -0500 Precedence: bulk X-Mailing-List: devicetree@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v7 4/6] iio: adc: ad4691: add SPI offload support To: radu.sabau@analog.com, Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , =?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 , Philipp Zabel , Jonathan Corbet , Shuah Khan 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, linux-doc@vger.kernel.org References: <20260409-ad4692-multichannel-sar-adc-driver-v7-0-be375d4df2c5@analog.com> <20260409-ad4692-multichannel-sar-adc-driver-v7-4-be375d4df2c5@analog.com> Content-Language: en-US From: David Lechner In-Reply-To: <20260409-ad4692-multichannel-sar-adc-driver-v7-4-be375d4df2c5@analog.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 4/9/26 10:28 AM, Radu Sabau via B4 Relay wrote: > From: Radu Sabau > > Add SPI offload support to enable DMA-based, CPU-independent data > acquisition using the SPI Engine offload framework. > > When an SPI offload is available (devm_spi_offload_get() succeeds), > the driver registers a DMA engine IIO buffer and uses dedicated buffer > setup operations. If no offload is available the existing software > triggered buffer path is used unchanged. > > Both CNV Burst Mode and Manual Mode support offload, but use different > trigger mechanisms: > > CNV Burst Mode: the SPI Engine is triggered by the ADC's DATA_READY > signal on the GP pin specified by the trigger-source consumer reference > in the device tree (one cell = GP pin number 0-3). For this mode the > driver acts as both an SPI offload consumer (DMA RX stream, message > optimization) and a trigger source provider: it registers the > GP/DATA_READY output via devm_spi_offload_trigger_register() so the > offload framework can match the '#trigger-source-cells' phandle and > automatically fire the SPI Engine DMA transfer at end-of-conversion. > > Manual Mode: the SPI Engine is triggered by a periodic trigger at > the configured sampling frequency. The pre-built SPI message uses > the pipelined CNV-on-CS protocol: N+1 16-bit transfers are issued > for N active channels (the first result is discarded as garbage from > the pipeline flush) and the remaining N results are captured by DMA. > > All offload transfers use 16-bit frames (bits_per_word=16, len=2). > The channel scan_type (storagebits=16, shift=0, IIO_BE) is shared > between the software triggered-buffer and offload paths; no separate > scan_type or channel array is needed for the offload case. The > ad4691_manual_channels[] array introduced in the triggered-buffer > commit is reused here: it hides the IIO_CHAN_INFO_OVERSAMPLING_RATIO > attribute, which is not applicable in Manual Mode. > > Kconfig gains a dependency on IIO_BUFFER_DMAENGINE. > > Signed-off-by: Radu Sabau > --- > drivers/iio/adc/Kconfig | 2 + > drivers/iio/adc/ad4691.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 395 insertions(+), 5 deletions(-) > > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig > index d498f16c0816..fdc6565933c5 100644 > --- a/drivers/iio/adc/Kconfig > +++ b/drivers/iio/adc/Kconfig > @@ -143,8 +143,10 @@ config AD4691 > tristate "Analog Devices AD4691 Family ADC Driver" > depends on SPI > select IIO_BUFFER > + select IIO_BUFFER_DMAENGINE > select IIO_TRIGGERED_BUFFER > select REGMAP > + select SPI_OFFLOAD > help > Say yes here to build support for Analog Devices AD4691 Family MuxSAR > SPI analog to digital converters (ADC). > diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c > index 3e5caa0972eb..839ea7f44c78 100644 > --- a/drivers/iio/adc/ad4691.c > +++ b/drivers/iio/adc/ad4691.c > @@ -22,6 +22,8 @@ > #include > #include > #include > +#include > +#include > #include > #include > > @@ -43,6 +45,11 @@ > > #define AD4691_CNV_DUTY_CYCLE_NS 380 > #define AD4691_CNV_HIGH_TIME_NS 430 > +/* > + * Conservative default for the manual offload periodic trigger. Low enough > + * to work safely out of the box across all OSR and channel count combinations. > + */ > +#define AD4691_OFFLOAD_INITIAL_TRIGGER_HZ (100 * HZ_PER_KHZ) > > #define AD4691_SPI_CONFIG_A_REG 0x000 > #define AD4691_SW_RESET (BIT(7) | BIT(0)) > @@ -95,6 +102,8 @@ > #define AD4691_ACC_IN(n) (0x252 + (3 * (n))) > #define AD4691_ACC_STS_DATA(n) (0x283 + (4 * (n))) > > +#define AD4691_OFFLOAD_BITS_PER_WORD 16 This is just the same as realbits in scan info. So could use that directly instead. > + > static const char * const ad4691_supplies[] = { "avdd", "vio" }; > > enum ad4691_ref_ctrl { > @@ -114,6 +123,7 @@ struct ad4691_chip_info { > const char *name; > unsigned int max_rate; > const struct ad4691_channel_info *sw_info; > + const struct ad4691_channel_info *offload_info; > }; > > #define AD4691_CHANNEL(ch) \ > @@ -177,6 +187,18 @@ static const struct ad4691_channel_info ad4693_sw_info = { > .num_channels = ARRAY_SIZE(ad4693_channels), > }; > > +static const struct ad4691_channel_info ad4691_offload_info = { > + .channels = ad4691_channels, > + /* No soft timestamp; num_channels caps access to 16. */ > + .num_channels = 16, `ARRAY_SIZE(ad4691_channels) - 1` would make sense too. > +}; > + > +static const struct ad4691_channel_info ad4693_offload_info = { > + .channels = ad4693_channels, > + /* No soft timestamp; num_channels caps access to 8. */ > + .num_channels = 8, > +}; > + > /* > * Internal oscillator frequency table. Index is the OSC_FREQ_REG[3:0] value. > * Index 0 (1 MHz) is only valid for AD4692/AD4694; AD4691/AD4693 support > @@ -207,24 +229,36 @@ static const struct ad4691_chip_info ad4691_chip_info = { > .name = "ad4691", > .max_rate = 500 * HZ_PER_KHZ, > .sw_info = &ad4691_sw_info, > + .offload_info = &ad4691_offload_info, > }; > > static const struct ad4691_chip_info ad4692_chip_info = { > .name = "ad4692", > .max_rate = 1 * HZ_PER_MHZ, > .sw_info = &ad4691_sw_info, > + .offload_info = &ad4691_offload_info, > }; > > static const struct ad4691_chip_info ad4693_chip_info = { > .name = "ad4693", > .max_rate = 500 * HZ_PER_KHZ, > .sw_info = &ad4693_sw_info, > + .offload_info = &ad4693_offload_info, > }; > > static const struct ad4691_chip_info ad4694_chip_info = { > .name = "ad4694", > .max_rate = 1 * HZ_PER_MHZ, > .sw_info = &ad4693_sw_info, > + .offload_info = &ad4693_offload_info, > +}; > + > +struct ad4691_offload_state { > + struct spi_offload *spi; I would call this "offload" or "instance". "spi" is usally the SPI device handle. > + struct spi_offload_trigger *trigger; > + u64 trigger_hz; > + u8 tx_cmd[17][2]; > + u8 tx_reset[4]; > }; > ... > + > +static int ad4691_cnv_burst_offload_buffer_predisable(struct iio_dev *indio_dev) > +{ > + struct ad4691_state *st = iio_priv(indio_dev); > + struct ad4691_offload_state *offload = st->offload; > + int ret; > + > + spi_offload_trigger_disable(offload->spi, offload->trigger); > + > + ret = ad4691_sampling_enable(st, false); > + if (ret) > + return ret; > + > + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG, > + AD4691_SEQ_ALL_CHANNELS_OFF); Why this extra step? We don't have it when unwinding in the error path of the postenable function. > + if (ret) > + return ret; > + > + spi_unoptimize_message(&st->scan_msg); > + > + return ad4691_exit_conversion_mode(st); > +} > + > +static const struct iio_buffer_setup_ops ad4691_cnv_burst_offload_buffer_setup_ops = { > + .postenable = &ad4691_cnv_burst_offload_buffer_postenable, > + .predisable = &ad4691_cnv_burst_offload_buffer_predisable, > +}; > + > static ssize_t sampling_frequency_show(struct device *dev, > struct device_attribute *attr, > char *buf)