get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2216872/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2216872,
    "url": "http://patchwork.ozlabs.org/api/patches/2216872/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260327-ad4692-multichannel-sar-adc-driver-v5-4-11f789de47b8@analog.com/",
    "project": {
        "id": 38,
        "url": "http://patchwork.ozlabs.org/api/projects/38/?format=api",
        "name": "Linux PWM development",
        "link_name": "linux-pwm",
        "list_id": "linux-pwm.vger.kernel.org",
        "list_email": "linux-pwm@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260327-ad4692-multichannel-sar-adc-driver-v5-4-11f789de47b8@analog.com>",
    "list_archive_url": null,
    "date": "2026-03-27T11:08:00",
    "name": "[v5,4/4] iio: adc: ad4691: add SPI offload support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "28daae6cef44914b5d24af05e9a0f3d9ce3c70b9",
    "submitter": {
        "id": 92791,
        "url": "http://patchwork.ozlabs.org/api/people/92791/?format=api",
        "name": "Radu Sabau via B4 Relay",
        "email": "devnull+radu.sabau.analog.com@kernel.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260327-ad4692-multichannel-sar-adc-driver-v5-4-11f789de47b8@analog.com/mbox/",
    "series": [
        {
            "id": 497746,
            "url": "http://patchwork.ozlabs.org/api/series/497746/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/list/?series=497746",
            "date": "2026-03-27T11:07:56",
            "name": "iio: adc: ad4691: add driver for AD4691 multichannel SAR ADC family",
            "version": 5,
            "mbox": "http://patchwork.ozlabs.org/series/497746/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2216872/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2216872/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-pwm+bounces-8385-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-pwm@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=VrFeqYiE;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.105.105.114; helo=tor.lore.kernel.org;\n envelope-from=linux-pwm+bounces-8385-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"VrFeqYiE\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fhyml4gsXz1y1x\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 22:17:59 +1100 (AEDT)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 6265D30A88AD\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 11:08:37 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 846833E7145;\n\tFri, 27 Mar 2026 11:08:10 +0000 (UTC)",
            "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 531F83E868A;\n\tFri, 27 Mar 2026 11:08:08 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPS id 7E0F5C2BCB8;\n\tFri, 27 Mar 2026 11:08:07 +0000 (UTC)",
            "from aws-us-west-2-korg-lkml-1.web.codeaurora.org\n (localhost.localdomain [127.0.0.1])\n\tby smtp.lore.kernel.org (Postfix) with ESMTP id 6DF4710ED662;\n\tFri, 27 Mar 2026 11:08:07 +0000 (UTC)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1774609688; cv=none;\n b=uCpSfc8HgiRM2aa6cpJi4lKpVMeBU0lNq5wMZOkH9MJnFxLq9paE3smKdkQBIYfHWBnhK+kEif4hBc+DBQxt1RqOplOA/yP/Qf1er2eWrsZnHF7eLxNWRJhYYr31zaXc5eUitLaBTI5XQ5JPS031ShCI03FpkjchXCFTPnjfQrw=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1774609688; c=relaxed/simple;\n\tbh=P+Zm+SmRn0s9xo55fzBWsS41LD9ElxW967k1wf2Wzuo=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=SXxUSCb6OFKKTmUzo2MNfBXsHbmSMKKuy/EOiQtDGp2MIjRp2kLLtb9jQaIJQr1+G4wPgwRNC2Q3oEwHQpvrQhznXwhFtyYdoMGUbcrjotmvbnqRSh2+zCV6Niw43nf12dBlxiw00dKIgKPwuh7A4rTcPGJYH9bSH/Gfhp3u7Wc=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=VrFeqYiE; arc=none smtp.client-ip=10.30.226.201",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1774609687;\n\tbh=P+Zm+SmRn0s9xo55fzBWsS41LD9ElxW967k1wf2Wzuo=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=VrFeqYiEXBg/XOQU/6+PDKMDuugzUiTDmrBFG556haiETzzZkJ+kdRN/eqk1p6L3P\n\t ApguYuCdUht0EKj42jFlvHadDIH+lO3dUGSJFeGjee37cO3LrqsxBHA2zhCQvqmyJG\n\t r8BhNjar1ryOnDj/x3n8uWlRE2MzjlkC6+3xsuQe11PATZpPVdTvcCqfysQq+nAlkY\n\t ZBgU1fAydQmIIijnlAp9aqotwITdDFmr4s1OJ1/0n876RWopjjAHoPNiDcxWwRSFAj\n\t rDgwRdf4fUgdqrG5OVgPym6YOMOj6wjVAhCQjgOGAEEd6RazHZUW2eXPu47YZv/V3e\n\t 2a7L97SLhkTXg==",
        "From": "Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org>",
        "Date": "Fri, 27 Mar 2026 13:08:00 +0200",
        "Subject": "[PATCH v5 4/4] iio: adc: ad4691: add SPI offload support",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-pwm@vger.kernel.org",
        "List-Id": "<linux-pwm.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-pwm+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-pwm+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "8bit",
        "Message-Id": "\n <20260327-ad4692-multichannel-sar-adc-driver-v5-4-11f789de47b8@analog.com>",
        "References": "\n <20260327-ad4692-multichannel-sar-adc-driver-v5-0-11f789de47b8@analog.com>",
        "In-Reply-To": "\n <20260327-ad4692-multichannel-sar-adc-driver-v5-0-11f789de47b8@analog.com>",
        "To": "Lars-Peter Clausen <lars@metafoo.de>,\n  Michael Hennerich <Michael.Hennerich@analog.com>,\n  Jonathan Cameron <jic23@kernel.org>, David Lechner <dlechner@baylibre.com>,\n\t=?utf-8?q?Nuno_S=C3=A1?= <nuno.sa@analog.com>,\n  Andy Shevchenko <andy@kernel.org>, Rob Herring <robh@kernel.org>,\n  Krzysztof Kozlowski <krzk+dt@kernel.org>,\n  Conor Dooley <conor+dt@kernel.org>,\n =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= <ukleinek@kernel.org>,\n  Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>,\n  Linus Walleij <linusw@kernel.org>, Bartosz Golaszewski <brgl@kernel.org>,\n  Philipp Zabel <p.zabel@pengutronix.de>, Jonathan Corbet <corbet@lwn.net>,\n  Shuah Khan <skhan@linuxfoundation.org>",
        "Cc": "linux-iio@vger.kernel.org, devicetree@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org,\n linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,\n Radu Sabau <radu.sabau@analog.com>",
        "X-Mailer": "b4 0.14.3",
        "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1774609685; l=32387;\n i=radu.sabau@analog.com; s=20260220; h=from:subject:message-id;\n bh=HVvxhfntOfwEIL4KJ9uL6Zz32sgUEJJRlwRkRAlVLbM=;\n b=99dUKOJ8H2cpxKi1mXM2I6f1BxRVJxEVYfGka0tel4eeRbUCBytPSZV6bAAIsA5NCrWYoedNU\n H+st8SIx05oDtMhF7XtGVtZC1EdRTKWOxQB9yHprzJTTJiuDGMcyrCO",
        "X-Developer-Key": "i=radu.sabau@analog.com; a=ed25519;\n pk=lDPQHgn9jTdt0vo58Na9lLxLaE2mb330if71Cn+EvFU=",
        "X-Endpoint-Received": "by B4 Relay for radu.sabau@analog.com/20260220 with\n auth_id=642",
        "X-Original-From": "Radu Sabau <radu.sabau@analog.com>",
        "Reply-To": "radu.sabau@analog.com"
    },
    "content": "From: Radu Sabau <radu.sabau@analog.com>\n\nAdd SPI offload support to enable DMA-based, CPU-independent data\nacquisition using the SPI Engine offload framework.\n\nWhen an SPI offload is available (devm_spi_offload_get() succeeds),\nthe driver registers a DMA engine IIO buffer and uses dedicated buffer\nsetup operations. If no offload is available the existing software\ntriggered buffer path is used unchanged.\n\nBoth CNV Burst Mode and Manual Mode support offload, but use different\ntrigger mechanisms:\n\nCNV Burst Mode: the SPI Engine is triggered by the ADC's DATA_READY\nsignal on the GP pin specified by the trigger-source consumer reference\nin the device tree (one cell = GP pin number 0-3). For this mode the\ndriver acts as both an SPI offload consumer (DMA RX stream, message\noptimization) and a trigger source provider: it registers the\nGP/DATA_READY output via devm_spi_offload_trigger_register() so the\noffload framework can match the '#trigger-source-cells' phandle and\nautomatically fire the SPI Engine DMA transfer at end-of-conversion.\n\nManual Mode: the SPI Engine is triggered by a periodic trigger at\nthe configured sampling frequency. The pre-built SPI message uses\nthe pipelined CNV-on-CS protocol: N+1 4-byte transfers are issued\nfor N active channels (the first result is discarded as garbage from\nthe pipeline flush) and the remaining N results are captured by DMA.\n\nAll offload transfers use 32-bit frames (bits_per_word=32, len=4) for\nDMA word alignment. This patch promotes the channel scan_type from\nstoragebits=16 (triggered-buffer path) to storagebits=32 to match the\nDMA word size; the triggered-buffer paths are updated to the same layout\nfor consistency. CNV Burst Mode channel data arrives in the lower 16\nbits of the 32-bit word (shift=0); Manual Mode data arrives in the upper\n16 bits (shift=16), matching the 4-byte SPI transfer layout\n[data_hi, data_lo, 0, 0]. A separate ad4691_manual_channels[] array\nencodes the shift=16 scan type for manual mode.\n\nAdd driver documentation under Documentation/iio/ad4691.rst covering\noperating modes, oversampling, reference voltage, SPI offload paths,\nand buffer data layout; register in MAINTAINERS and index.rst\n\nKconfig gains a dependency on IIO_BUFFER_DMAENGINE.\n\nSigned-off-by: Radu Sabau <radu.sabau@analog.com>\n---\n Documentation/iio/ad4691.rst | 259 ++++++++++++++++++++++++++\n Documentation/iio/index.rst  |   1 +\n MAINTAINERS                  |   1 +\n drivers/iio/adc/Kconfig      |   1 +\n drivers/iio/adc/ad4691.c     | 426 ++++++++++++++++++++++++++++++++++++++++++-\n 5 files changed, 680 insertions(+), 8 deletions(-)",
    "diff": "diff --git a/Documentation/iio/ad4691.rst b/Documentation/iio/ad4691.rst\nnew file mode 100644\nindex 000000000000..36f0c841605a\n--- /dev/null\n+++ b/Documentation/iio/ad4691.rst\n@@ -0,0 +1,259 @@\n+.. SPDX-License-Identifier: GPL-2.0-only\n+\n+=============\n+AD4691 driver\n+=============\n+\n+ADC driver for Analog Devices Inc. AD4691 family of multichannel SAR ADCs.\n+The module name is ``ad4691``.\n+\n+\n+Supported devices\n+=================\n+\n+The following chips are supported by this driver:\n+\n+* `AD4691 <https://www.analog.com/en/products/ad4691.html>`_ — 16-channel, 500 kSPS\n+* `AD4692 <https://www.analog.com/en/products/ad4692.html>`_ — 16-channel, 1 MSPS\n+* `AD4693 <https://www.analog.com/en/products/ad4693.html>`_ — 8-channel, 500 kSPS\n+* `AD4694 <https://www.analog.com/en/products/ad4694.html>`_ — 8-channel, 1 MSPS\n+\n+\n+IIO channels\n+============\n+\n+Each physical ADC input maps to one IIO voltage channel. The AD4691 and AD4692\n+expose 16 channels (``voltage0`` through ``voltage15``); the AD4693 and AD4694\n+expose 8 channels (``voltage0`` through ``voltage7``).\n+\n+All channels share a common scale (``in_voltage_scale``), derived from the\n+reference voltage. Each channel independently exposes:\n+\n+* ``in_voltageN_raw`` — single-shot ADC result\n+* ``in_voltageN_sampling_frequency`` — internal oscillator frequency used for\n+  single-shot reads and CNV Burst Mode buffered captures\n+* ``in_voltageN_sampling_frequency_available`` — list of valid oscillator\n+  frequencies\n+* ``in_voltageN_oversampling_ratio`` — per-channel hardware accumulation depth\n+* ``in_voltageN_oversampling_ratio_available`` — list of valid ratios\n+\n+\n+Operating modes\n+===============\n+\n+The driver supports two operating modes, auto-detected from the device tree at\n+probe time. Both modes transition to and from an internal Autonomous Mode idle\n+state when the IIO buffer is enabled and disabled.\n+\n+Manual Mode\n+-----------\n+\n+Selected when no ``pwms`` property is present in the device tree. The CNV pin\n+is tied to the SPI chip-select: every CS assertion both triggers a new\n+conversion and returns the result of the previous one (pipelined N+1 scheme).\n+\n+To read N channels the driver issues N+1 SPI transfers in a single optimised\n+message:\n+\n+* Transfers 0 to N-1 each carry ``AD4691_ADC_CHAN(n)`` in the TX byte to\n+  select the next channel; the RX byte of transfer ``k+1`` contains the result\n+  of the channel selected in transfer ``k``.\n+* Transfer N is a NOOP (0x00) to flush the last conversion result out of the\n+  pipeline.\n+\n+The external IIO trigger (``pollfunc_store_time``) drives the trigger handler,\n+which executes the pre-built SPI message and pushes the scan to the buffer.\n+\n+CNV Burst Mode\n+--------------\n+\n+Selected when a ``pwms`` property is present in the device tree. The PWM drives\n+the CNV pin independently of SPI at the configured conversion rate, and a GP\n+pin (identified by ``interrupt-names``) asserts DATA_READY at end-of-burst to\n+signal that the AVG_IN result registers are ready to be read.\n+\n+The IRQ handler stops the PWM, fires the IIO trigger, and the trigger handler\n+reads all active ``AVG_IN(n)`` registers in a single optimised SPI message and\n+pushes the scan to the buffer.\n+\n+The buffer sampling frequency (i.e. the PWM rate) is controlled by the\n+``sampling_frequency`` attribute on the IIO buffer. Valid values span from the\n+chip's minimum oscillator rate up to its maximum conversion rate\n+(500 kSPS for AD4691/AD4693, 1 MSPS for AD4692/AD4694).\n+\n+Autonomous Mode (idle / single-shot)\n+-------------------------------------\n+\n+The chip idles in Autonomous Mode whenever the IIO buffer is disabled. In this\n+state, ``read_raw`` requests (``in_voltageN_raw``) use the internal oscillator\n+to perform a single conversion on the requested channel and read back the\n+result from the ``AVG_IN(N)`` register. The oscillator is started and stopped\n+for each read to save power.\n+\n+\n+Oversampling\n+============\n+\n+Each channel has an independent hardware accumulator (ACC_DEPTH_IN) that\n+averages a configurable number of successive conversions before DATA_READY\n+asserts. The result is always returned as a 16-bit mean from the ``AVG_IN``\n+register, so the IIO ``realbits`` and ``storagebits`` are unaffected by the\n+oversampling ratio.\n+\n+Valid ratios are 1, 2, 4, 8, 16 and 32. The default is 1 (no averaging).\n+\n+.. code-block:: bash\n+\n+    # Set oversampling ratio to 16 on channel 0\n+    echo 16 > /sys/bus/iio/devices/iio:device0/in_voltage0_oversampling_ratio\n+\n+When OSR > 1 the effective conversion rate for ``read_raw`` is reduced\n+accordingly, since the driver waits for 2 × OSR oscillator periods before\n+reading the result.\n+\n+\n+Reference voltage\n+=================\n+\n+The driver supports two reference configurations, mutually exclusive:\n+\n+* **External reference** (``ref-supply``): a voltage between 2.4 V and 5.25 V\n+  supplied externally. The internal reference buffer is disabled.\n+* **Buffered internal reference** (``refin-supply``): An internal reference\n+  buffer is used. The driver enables ``REFBUF_EN`` in the REF_CTRL register\n+  when this supply is used.\n+\n+Exactly one of ``ref-supply`` or ``refin-supply`` must be present in the\n+device tree.\n+\n+The reference voltage determines the full-scale range:\n+\n+.. code-block::\n+\n+    full-scale = Vref / 2^16  (per LSB)\n+\n+\n+LDO supply\n+==========\n+\n+The chip contains an internal LDO that powers part of the analog front-end.\n+The LDO input can be driven externally via the ``ldo-in-supply`` regulator. If\n+that supply is absent, the driver enables the internal LDO path (``LDO_EN``\n+bit in DEVICE_SETUP).\n+\n+\n+Reset\n+=====\n+\n+The driver supports two reset mechanisms:\n+\n+* **Hardware reset** (``reset-gpios`` in device tree): the GPIO is already\n+  asserted at driver probe by the reset controller framework. The driver waits\n+  for the required 300 µs reset pulse width and then deasserts.\n+* **Software reset** (fallback when ``reset-gpios`` is absent): the driver\n+  writes the software-reset pattern to the SPI_CONFIG_A register.\n+\n+\n+GP pins and interrupts\n+======================\n+\n+The chip exposes up to four general-purpose (GP) pins that can be configured as\n+interrupt outputs. In CNV Burst Mode (non-offload), one GP pin must be wired to\n+an interrupt-capable SoC input and declared in the device tree using the\n+``interrupts`` and ``interrupt-names`` properties.\n+\n+The ``interrupt-names`` value identifies which GP pin is used (``\"gp0\"``\n+through ``\"gp3\"``). The driver configures that pin as a DATA_READY output in\n+the GPIO_MODE register.\n+\n+Example device tree fragment::\n+\n+    adc@0 {\n+        compatible = \"adi,ad4692\";\n+        ...\n+        interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;\n+        interrupt-parent = <&gpio0>;\n+        interrupt-names = \"gp0\";\n+    };\n+\n+\n+SPI offload support\n+===================\n+\n+When a SPI offload engine (e.g. the AXI SPI Engine) is present, the driver\n+uses DMA-backed transfers for CPU-independent, high-throughput data capture.\n+SPI offload is detected automatically at probe via ``devm_spi_offload_get()``;\n+if no offload hardware is available the driver falls back to the software\n+triggered-buffer path.\n+\n+Two SPI offload sub-modes exist, corresponding to the two operating modes:\n+\n+CNV Burst offload\n+-----------------\n+\n+Used when a ``pwms`` property is present and SPI offload is available.\n+\n+The PWM drives CNV at the configured rate. On DATA_READY the SPI offload\n+engine automatically executes a pre-built message that reads all active\n+``AVG_IN`` registers and streams the data directly to an IIO DMA buffer with\n+no CPU involvement. A final state-reset transfer re-arms DATA_READY for the\n+next burst.\n+\n+The GP pin used as DATA_READY trigger is supplied by the trigger-source\n+consumer (via ``#trigger-source-cells``) at buffer enable time; no\n+``interrupt-names`` entry is required in this path.\n+\n+The buffer sampling frequency is controlled by the ``sampling_frequency``\n+attribute on the IIO buffer (same as the non-offload CNV Burst path).\n+\n+Manual offload\n+--------------\n+\n+Used when no ``pwms`` property is present and SPI offload is available.\n+\n+A periodic SPI offload trigger controls the conversion rate. On each trigger\n+period, the SPI engine executes an N+1 transfer message (same pipelined scheme\n+as software Manual Mode) and streams the data directly to the IIO DMA buffer.\n+\n+The ``sampling_frequency`` attribute on the IIO buffer controls the trigger\n+rate (in Hz). The default is the chip's maximum conversion rate.\n+\n+\n+Buffer data format\n+==================\n+\n+The IIO buffer data format (``in_voltageN_type``) depends on the active path:\n+\n++-------------------------+-------------+-------------+-------+\n+| Path                    | storagebits | realbits    | shift |\n++=========================+=============+=============+=======+\n+| Triggered buffer        | 16          | 16          | 0     |\n++-------------------------+-------------+-------------+-------+\n+| CNV Burst offload (DMA) | 32          | 16          | 0     |\n++-------------------------+-------------+-------------+-------+\n+| Manual offload (DMA)    | 32          | 16          | 16    |\n++-------------------------+-------------+-------------+-------+\n+\n+In the triggered-buffer path the driver unpacks the 16-bit result in software\n+before pushing to the buffer, so ``storagebits`` is 16.\n+\n+In the DMA offload paths the DMA engine writes 32-bit words directly into the\n+IIO DMA buffer:\n+\n+* **CNV Burst offload**: the SPI engine reads AVG_IN registers with a 2-byte\n+  address phase followed by a 2-byte data phase; the 16-bit result lands in\n+  the lower half of the 32-bit word (``shift=0``).\n+* **Manual offload**: each 32-bit SPI word carries the channel byte in the\n+  first byte; the 16-bit result is returned in the upper half of the 32-bit\n+  word (``shift=16``).\n+\n+The ``in_voltageN_type`` sysfs attribute reflects the active scan type.\n+\n+\n+Unimplemented features\n+======================\n+\n+* GPIO controller functionality of the GP pins\n+* Clamp status and overrange events\n+* Raw accumulator (ACC_IN) and accumulator status registers\n+* ADC_BUSY and overrun status interrupts\ndiff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst\nindex ba3e609c6a13..007e0a1fcc5a 100644\n--- a/Documentation/iio/index.rst\n+++ b/Documentation/iio/index.rst\n@@ -23,6 +23,7 @@ Industrial I/O Kernel Drivers\n    ad4000\n    ad4030\n    ad4062\n+   ad4691\n    ad4695\n    ad7191\n    ad7380\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex 24e4502b8292..875ea2455d91 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1490,6 +1490,7 @@ L:\tlinux-iio@vger.kernel.org\n S:\tSupported\n W:\thttps://ez.analog.com/linux-software-drivers\n F:\tDocumentation/devicetree/bindings/iio/adc/adi,ad4691.yaml\n+F:\tDocumentation/iio/ad4691.rst\n F:\tdrivers/iio/adc/ad4691.c\n \n ANALOG DEVICES INC AD4695 DRIVER\ndiff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig\nindex d498f16c0816..93f090e9a562 100644\n--- a/drivers/iio/adc/Kconfig\n+++ b/drivers/iio/adc/Kconfig\n@@ -144,6 +144,7 @@ config AD4691\n \tdepends on SPI\n \tselect IIO_BUFFER\n \tselect IIO_TRIGGERED_BUFFER\n+\tselect IIO_BUFFER_DMAENGINE\n \tselect REGMAP\n \thelp\n \t  Say yes here to build support for Analog Devices AD4691 Family MuxSAR\ndiff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c\nindex b5a7646b46ca..d24f06207a11 100644\n--- a/drivers/iio/adc/ad4691.c\n+++ b/drivers/iio/adc/ad4691.c\n@@ -9,6 +9,7 @@\n #include <linux/cleanup.h>\n #include <linux/delay.h>\n #include <linux/device.h>\n+#include <linux/dmaengine.h>\n #include <linux/err.h>\n #include <linux/interrupt.h>\n #include <linux/math.h>\n@@ -20,10 +21,14 @@\n #include <linux/regulator/consumer.h>\n #include <linux/reset.h>\n #include <linux/spi/spi.h>\n+#include <linux/spi/offload/consumer.h>\n+#include <linux/spi/offload/provider.h>\n #include <linux/units.h>\n #include <linux/unaligned.h>\n \n #include <linux/iio/buffer.h>\n+#include <linux/iio/buffer-dma.h>\n+#include <linux/iio/buffer-dmaengine.h>\n #include <linux/iio/iio.h>\n #include <linux/iio/sysfs.h>\n #include <linux/iio/trigger.h>\n@@ -38,6 +43,7 @@\n #define AD4691_VREF_4P096_uV_MAX\t\t4500000\n \n #define AD4691_CNV_DUTY_CYCLE_NS\t\t380\n+#define AD4691_CNV_HIGH_TIME_NS\t\t\t430\n \n #define AD4691_SPI_CONFIG_A_REG\t\t\t0x000\n #define AD4691_SW_RESET\t\t\t\t(BIT(7) | BIT(0))\n@@ -90,6 +96,8 @@\n #define AD4691_ACC_IN(n)\t\t\t(0x252 + (3 * (n)))\n #define AD4691_ACC_STS_DATA(n)\t\t\t(0x283 + (4 * (n)))\n \n+#define AD4691_OFFLOAD_BITS_PER_WORD\t\t32\n+\n enum ad4691_ref_ctrl {\n \tAD4691_VREF_2P5   = 0,\n \tAD4691_VREF_3P0   = 1,\n@@ -105,6 +113,31 @@ struct ad4691_chip_info {\n \tunsigned int max_rate;\n };\n \n+enum {\n+\tAD4691_SCAN_TYPE_NORMAL,         /* triggered buffer:  storagebits=16, shift=0  */\n+\tAD4691_SCAN_TYPE_OFFLOAD_CNV,    /* CNV burst offload: storagebits=32, shift=0  */\n+\tAD4691_SCAN_TYPE_OFFLOAD_MANUAL, /* manual offload:    storagebits=32, shift=16 */\n+};\n+\n+static const struct iio_scan_type ad4691_scan_types[] = {\n+\t[AD4691_SCAN_TYPE_NORMAL] = {\n+\t\t.sign = 'u',\n+\t\t.realbits = 16,\n+\t\t.storagebits = 16,\n+\t},\n+\t[AD4691_SCAN_TYPE_OFFLOAD_CNV] = {\n+\t\t.sign = 'u',\n+\t\t.realbits = 16,\n+\t\t.storagebits = 32,\n+\t},\n+\t[AD4691_SCAN_TYPE_OFFLOAD_MANUAL] = {\n+\t\t.sign = 'u',\n+\t\t.realbits = 16,\n+\t\t.storagebits = 32,\n+\t\t.shift = 16,\n+\t},\n+};\n+\n #define AD4691_CHANNEL(ch)\t\t\t\t\t\t\\\n \t{\t\t\t\t\t\t\t\t\\\n \t\t.type = IIO_VOLTAGE,\t\t\t\t\t\\\n@@ -118,11 +151,9 @@ struct ad4691_chip_info {\n \t\t.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),\t\\\n \t\t.channel = ch,\t\t\t\t\t\t\\\n \t\t.scan_index = ch,\t\t\t\t\t\\\n-\t\t.scan_type = {\t\t\t\t\t\t\\\n-\t\t\t.sign = 'u',\t\t\t\t\t\\\n-\t\t\t.realbits = 16,\t\t\t\t\t\\\n-\t\t\t.storagebits = 16,\t\t\t\t\\\n-\t\t},\t\t\t\t\t\t\t\\\n+\t\t.has_ext_scan_type = 1,\t\t\t\t\t\\\n+\t\t.ext_scan_type = ad4691_scan_types,\t\t\t\\\n+\t\t.num_ext_scan_type = ARRAY_SIZE(ad4691_scan_types),\t\\\n \t}\n \n static const struct iio_chan_spec ad4691_channels[] = {\n@@ -217,6 +248,17 @@ static const struct ad4691_chip_info ad4694_chip_info = {\n \t.max_rate = 1 * HZ_PER_MHZ,\n };\n \n+struct ad4691_offload_state {\n+\tstruct spi_offload *spi;\n+\tstruct spi_offload_trigger *trigger;\n+\tu64 trigger_hz;\n+\tstruct spi_message msg;\n+\t/* Max 16 channel xfers + 1 state-reset or NOOP */\n+\tstruct spi_transfer xfer[17];\n+\tu8 tx_cmd[17][4];\n+\tu8 tx_reset[4];\n+};\n+\n struct ad4691_state {\n \tconst struct ad4691_chip_info *info;\n \tstruct regmap *regmap;\n@@ -247,6 +289,8 @@ struct ad4691_state {\n \tstruct spi_transfer *scan_xfers;\n \t__be16 *scan_tx;\n \t__be16 *scan_rx;\n+\t/* NULL when no SPI offload hardware is present */\n+\tstruct ad4691_offload_state *offload;\n \t/* Scan buffer: one slot per channel plus timestamp */\n \tstruct {\n \t\tu16 vals[16];\n@@ -269,6 +313,46 @@ static int ad4691_gpio_setup(struct ad4691_state *st, unsigned int gp_num)\n \t\t\t\t  AD4691_GP_MODE_DATA_READY << shift);\n }\n \n+static const struct spi_offload_config ad4691_offload_config = {\n+\t.capability_flags = SPI_OFFLOAD_CAP_TRIGGER |\n+\t\t\t    SPI_OFFLOAD_CAP_RX_STREAM_DMA,\n+};\n+\n+static bool ad4691_offload_trigger_match(struct spi_offload_trigger *trigger,\n+\t\t\t\t\t enum spi_offload_trigger_type type,\n+\t\t\t\t\t u64 *args, u32 nargs)\n+{\n+\treturn type == SPI_OFFLOAD_TRIGGER_DATA_READY &&\n+\t       nargs == 1 && args[0] <= 3;\n+}\n+\n+static int ad4691_offload_trigger_request(struct spi_offload_trigger *trigger,\n+\t\t\t\t\t  enum spi_offload_trigger_type type,\n+\t\t\t\t\t  u64 *args, u32 nargs)\n+{\n+\tstruct ad4691_state *st = spi_offload_trigger_get_priv(trigger);\n+\n+\tif (nargs != 1)\n+\t\treturn -EINVAL;\n+\n+\treturn ad4691_gpio_setup(st, (unsigned int)args[0]);\n+}\n+\n+static int ad4691_offload_trigger_validate(struct spi_offload_trigger *trigger,\n+\t\t\t\t\t   struct spi_offload_trigger_config *config)\n+{\n+\tif (config->type != SPI_OFFLOAD_TRIGGER_DATA_READY)\n+\t\treturn -EINVAL;\n+\n+\treturn 0;\n+}\n+\n+static const struct spi_offload_trigger_ops ad4691_offload_trigger_ops = {\n+\t.match    = ad4691_offload_trigger_match,\n+\t.request  = ad4691_offload_trigger_request,\n+\t.validate = ad4691_offload_trigger_validate,\n+};\n+\n static int ad4691_reg_read(void *context, unsigned int reg, unsigned int *val)\n {\n \tstruct spi_device *spi = context;\n@@ -559,10 +643,17 @@ static int ad4691_read_raw(struct iio_dev *indio_dev,\n \tcase IIO_CHAN_INFO_OVERSAMPLING_RATIO:\n \t\t*val = st->osr[chan->scan_index];\n \t\treturn IIO_VAL_INT;\n-\tcase IIO_CHAN_INFO_SCALE:\n+\tcase IIO_CHAN_INFO_SCALE: {\n+\t\tconst struct iio_scan_type *scan_type;\n+\n+\t\tscan_type = iio_get_current_scan_type(indio_dev, chan);\n+\t\tif (IS_ERR(scan_type))\n+\t\t\treturn PTR_ERR(scan_type);\n+\n \t\t*val = st->vref_uV / (MICRO / MILLI);\n-\t\t*val2 = chan->scan_type.realbits;\n+\t\t*val2 = scan_type->realbits;\n \t\treturn IIO_VAL_FRACTIONAL_LOG2;\n+\t}\n \tdefault:\n \t\treturn -EINVAL;\n \t}\n@@ -866,6 +957,208 @@ static const struct iio_buffer_setup_ops ad4691_cnv_burst_buffer_setup_ops = {\n \t.postdisable = &ad4691_cnv_burst_buffer_postdisable,\n };\n \n+static int ad4691_manual_offload_buffer_postenable(struct iio_dev *indio_dev)\n+{\n+\tstruct ad4691_state *st = iio_priv(indio_dev);\n+\tstruct ad4691_offload_state *offload = st->offload;\n+\tstruct device *dev = regmap_get_device(st->regmap);\n+\tstruct spi_device *spi = to_spi_device(dev);\n+\tstruct spi_offload_trigger_config config = {\n+\t\t.type = SPI_OFFLOAD_TRIGGER_PERIODIC,\n+\t};\n+\tunsigned int bit, k;\n+\tint ret;\n+\n+\tret = ad4691_enter_conversion_mode(st);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmemset(offload->xfer, 0, sizeof(offload->xfer));\n+\n+\t/*\n+\t * N+1 transfers for N channels. Each CS-low period triggers\n+\t * a conversion AND returns the previous result (pipelined).\n+\t *   TX: [AD4691_ADC_CHAN(n), 0x00, 0x00, 0x00]\n+\t *   RX: [data_hi, data_lo, 0x00, 0x00]   (shift=16)\n+\t * Transfer 0 RX is garbage; transfers 1..N carry real data.\n+\t */\n+\tk = 0;\n+\tiio_for_each_active_channel(indio_dev, bit) {\n+\t\toffload->tx_cmd[k][0] = AD4691_ADC_CHAN(bit);\n+\t\toffload->xfer[k].tx_buf = offload->tx_cmd[k];\n+\t\toffload->xfer[k].len = sizeof(offload->tx_cmd[k]);\n+\t\toffload->xfer[k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;\n+\t\toffload->xfer[k].cs_change = 1;\n+\t\toffload->xfer[k].cs_change_delay.value = AD4691_CNV_HIGH_TIME_NS;\n+\t\toffload->xfer[k].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;\n+\t\t/* First transfer RX is garbage — skip it. */\n+\t\tif (k > 0)\n+\t\t\toffload->xfer[k].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;\n+\t\tk++;\n+\t}\n+\n+\t/* Final NOOP to flush pipeline and capture last channel. */\n+\toffload->tx_cmd[k][0] = AD4691_NOOP;\n+\toffload->xfer[k].tx_buf = offload->tx_cmd[k];\n+\toffload->xfer[k].len = sizeof(offload->tx_cmd[k]);\n+\toffload->xfer[k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;\n+\toffload->xfer[k].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;\n+\tk++;\n+\n+\tspi_message_init_with_transfers(&offload->msg, offload->xfer, k);\n+\toffload->msg.offload = offload->spi;\n+\n+\tret = spi_optimize_message(spi, &offload->msg);\n+\tif (ret)\n+\t\tgoto err_exit_conversion;\n+\n+\tconfig.periodic.frequency_hz = offload->trigger_hz;\n+\tret = spi_offload_trigger_enable(offload->spi, offload->trigger, &config);\n+\tif (ret)\n+\t\tgoto err_unoptimize;\n+\n+\treturn 0;\n+\n+err_unoptimize:\n+\tspi_unoptimize_message(&offload->msg);\n+err_exit_conversion:\n+\tad4691_exit_conversion_mode(st);\n+\treturn ret;\n+}\n+\n+static int ad4691_manual_offload_buffer_predisable(struct iio_dev *indio_dev)\n+{\n+\tstruct ad4691_state *st = iio_priv(indio_dev);\n+\tstruct ad4691_offload_state *offload = st->offload;\n+\n+\tspi_offload_trigger_disable(offload->spi, offload->trigger);\n+\tspi_unoptimize_message(&offload->msg);\n+\n+\treturn ad4691_exit_conversion_mode(st);\n+}\n+\n+static const struct iio_buffer_setup_ops ad4691_manual_offload_buffer_setup_ops = {\n+\t.postenable = &ad4691_manual_offload_buffer_postenable,\n+\t.predisable = &ad4691_manual_offload_buffer_predisable,\n+};\n+\n+static int ad4691_cnv_burst_offload_buffer_postenable(struct iio_dev *indio_dev)\n+{\n+\tstruct ad4691_state *st = iio_priv(indio_dev);\n+\tstruct ad4691_offload_state *offload = st->offload;\n+\tstruct device *dev = regmap_get_device(st->regmap);\n+\tstruct spi_device *spi = to_spi_device(dev);\n+\tstruct spi_offload_trigger_config config = {\n+\t\t.type = SPI_OFFLOAD_TRIGGER_DATA_READY,\n+\t};\n+\tunsigned int n_active = bitmap_weight(indio_dev->active_scan_mask,\n+\t\t\t\t\t      indio_dev->masklength);\n+\tunsigned int bit, k;\n+\tint ret;\n+\n+\tret = regmap_write(st->regmap, AD4691_ACC_MASK_REG,\n+\t\t\t   (u16)~bitmap_read(indio_dev->active_scan_mask, 0,\n+\t\t\t\t\t     indio_dev->masklength));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG,\n+\t\t\t   bitmap_read(indio_dev->active_scan_mask, 0,\n+\t\t\t\t       indio_dev->masklength));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tiio_for_each_active_channel(indio_dev, bit) {\n+\t\tret = regmap_write(st->regmap, AD4691_ACC_DEPTH_IN(bit),\n+\t\t\t\t   st->osr[bit]);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tret = ad4691_enter_conversion_mode(st);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmemset(offload->xfer, 0, sizeof(offload->xfer));\n+\n+\t/*\n+\t * N transfers to read N AVG_IN registers plus one state-reset\n+\t * transfer (no RX) to re-arm DATA_READY.\n+\t *   TX: [reg_hi | 0x80, reg_lo, 0x00, 0x00]\n+\t *   RX: [0x00, 0x00, data_hi, data_lo]   (shift=0)\n+\t */\n+\tk = 0;\n+\tiio_for_each_active_channel(indio_dev, bit) {\n+\t\tunsigned int reg = AD4691_AVG_IN(bit);\n+\n+\t\toffload->tx_cmd[k][0] = (reg >> 8) | 0x80;\n+\t\toffload->tx_cmd[k][1] = reg & 0xFF;\n+\t\toffload->xfer[k].tx_buf = offload->tx_cmd[k];\n+\t\toffload->xfer[k].len = sizeof(offload->tx_cmd[k]);\n+\t\toffload->xfer[k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;\n+\t\toffload->xfer[k].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;\n+\t\tif (k < n_active - 1)\n+\t\t\toffload->xfer[k].cs_change = 1;\n+\t\tk++;\n+\t}\n+\n+\t/* State reset to re-arm DATA_READY for the next scan. */\n+\toffload->tx_reset[0] = AD4691_STATE_RESET_REG >> 8;\n+\toffload->tx_reset[1] = AD4691_STATE_RESET_REG & 0xFF;\n+\toffload->tx_reset[2] = AD4691_STATE_RESET_ALL;\n+\toffload->xfer[k].tx_buf = offload->tx_reset;\n+\toffload->xfer[k].len = sizeof(offload->tx_reset);\n+\toffload->xfer[k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;\n+\tk++;\n+\n+\tspi_message_init_with_transfers(&offload->msg, offload->xfer, k);\n+\toffload->msg.offload = offload->spi;\n+\n+\tret = spi_optimize_message(spi, &offload->msg);\n+\tif (ret)\n+\t\tgoto err_exit_conversion;\n+\n+\tret = ad4691_sampling_enable(st, true);\n+\tif (ret)\n+\t\tgoto err_unoptimize;\n+\n+\tret = spi_offload_trigger_enable(offload->spi, offload->trigger, &config);\n+\tif (ret)\n+\t\tgoto err_sampling_disable;\n+\n+\treturn 0;\n+\n+err_sampling_disable:\n+\tad4691_sampling_enable(st, false);\n+err_unoptimize:\n+\tspi_unoptimize_message(&offload->msg);\n+err_exit_conversion:\n+\tad4691_exit_conversion_mode(st);\n+\treturn ret;\n+}\n+\n+static int ad4691_cnv_burst_offload_buffer_predisable(struct iio_dev *indio_dev)\n+{\n+\tstruct ad4691_state *st = iio_priv(indio_dev);\n+\tstruct ad4691_offload_state *offload = st->offload;\n+\tint ret;\n+\n+\tspi_offload_trigger_disable(offload->spi, offload->trigger);\n+\n+\tret = ad4691_sampling_enable(st, false);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tspi_unoptimize_message(&offload->msg);\n+\n+\treturn ad4691_exit_conversion_mode(st);\n+}\n+\n+static const struct iio_buffer_setup_ops ad4691_cnv_burst_offload_buffer_setup_ops = {\n+\t.postenable = &ad4691_cnv_burst_offload_buffer_postenable,\n+\t.predisable = &ad4691_cnv_burst_offload_buffer_predisable,\n+};\n+\n static ssize_t sampling_frequency_show(struct device *dev,\n \t\t\t\t       struct device_attribute *attr,\n \t\t\t\t       char *buf)\n@@ -873,6 +1166,9 @@ static ssize_t sampling_frequency_show(struct device *dev,\n \tstruct iio_dev *indio_dev = dev_to_iio_dev(dev);\n \tstruct ad4691_state *st = iio_priv(indio_dev);\n \n+\tif (st->manual_mode && st->offload)\n+\t\treturn sysfs_emit(buf, \"%llu\\n\", st->offload->trigger_hz);\n+\n \treturn sysfs_emit(buf, \"%u\\n\", (u32)(NSEC_PER_SEC / st->cnv_period_ns));\n }\n \n@@ -890,6 +1186,20 @@ static ssize_t sampling_frequency_store(struct device *dev,\n \n \tguard(mutex)(&st->lock);\n \n+\tif (st->manual_mode && st->offload) {\n+\t\tstruct spi_offload_trigger_config config = {\n+\t\t\t.type = SPI_OFFLOAD_TRIGGER_PERIODIC,\n+\t\t\t.periodic = { .frequency_hz = freq },\n+\t\t};\n+\n+\t\tret = spi_offload_trigger_validate(st->offload->trigger, &config);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tst->offload->trigger_hz = config.periodic.frequency_hz;\n+\t\treturn len;\n+\t}\n+\n \tret = ad4691_set_pwm_freq(st, freq);\n \tif (ret)\n \t\treturn ret;\n@@ -975,10 +1285,23 @@ static irqreturn_t ad4691_trigger_handler(int irq, void *p)\n \treturn IRQ_HANDLED;\n }\n \n+static int ad4691_get_current_scan_type(const struct iio_dev *indio_dev,\n+\t\t\t\t\t const struct iio_chan_spec *chan)\n+{\n+\tstruct ad4691_state *st = iio_priv(indio_dev);\n+\n+\tif (!st->offload)\n+\t\treturn AD4691_SCAN_TYPE_NORMAL;\n+\tif (st->manual_mode)\n+\t\treturn AD4691_SCAN_TYPE_OFFLOAD_MANUAL;\n+\treturn AD4691_SCAN_TYPE_OFFLOAD_CNV;\n+}\n+\n static const struct iio_info ad4691_info = {\n \t.read_raw = &ad4691_read_raw,\n \t.write_raw = &ad4691_write_raw,\n \t.read_avail = &ad4691_read_avail,\n+\t.get_current_scan_type = &ad4691_get_current_scan_type,\n \t.debugfs_reg_access = &ad4691_reg_access,\n };\n \n@@ -1130,6 +1453,15 @@ static int ad4691_config(struct ad4691_state *st)\n \tif (st->manual_mode)\n \t\treturn 0;\n \n+\t/*\n+\t * In the offload CNV Burst path the GP pin is supplied by the trigger\n+\t * consumer via #trigger-source-cells; gpio_setup is called from\n+\t * ad4691_offload_trigger_request() instead. For the non-offload path\n+\t * derive the pin from the first interrupt-names entry (e.g. \"gp0\").\n+\t */\n+\tif (device_property_present(dev, \"#trigger-source-cells\"))\n+\t\treturn 0;\n+\n \tfor (gp_num = 0; gp_num < ARRAY_SIZE(ad4691_gp_names); gp_num++) {\n \t\tif (fwnode_irq_get_byname(dev_fwnode(dev),\n \t\t\t\t\t  ad4691_gp_names[gp_num]) > 0)\n@@ -1210,9 +1542,75 @@ static int ad4691_setup_triggered_buffer(struct iio_dev *indio_dev,\n \t\t\t\t\t       &ad4691_manual_buffer_setup_ops);\n }\n \n+static int ad4691_setup_offload(struct iio_dev *indio_dev,\n+\t\t\t\tstruct ad4691_state *st,\n+\t\t\t\tstruct spi_offload *spi_offload)\n+{\n+\tstruct device *dev = regmap_get_device(st->regmap);\n+\tstruct ad4691_offload_state *offload;\n+\tstruct dma_chan *rx_dma;\n+\tint ret;\n+\n+\toffload = devm_kzalloc(dev, sizeof(*offload), GFP_KERNEL);\n+\tif (!offload)\n+\t\treturn -ENOMEM;\n+\n+\toffload->spi = spi_offload;\n+\tst->offload = offload;\n+\n+\tif (st->manual_mode) {\n+\t\toffload->trigger =\n+\t\t\tdevm_spi_offload_trigger_get(dev, offload->spi,\n+\t\t\t\t\t\t     SPI_OFFLOAD_TRIGGER_PERIODIC);\n+\t\tif (IS_ERR(offload->trigger))\n+\t\t\treturn dev_err_probe(dev, PTR_ERR(offload->trigger),\n+\t\t\t\t\t     \"Failed to get periodic offload trigger\\n\");\n+\n+\t\toffload->trigger_hz = st->info->max_rate;\n+\t} else {\n+\t\tstruct spi_offload_trigger_info trigger_info = {\n+\t\t\t.fwnode = dev_fwnode(dev),\n+\t\t\t.ops    = &ad4691_offload_trigger_ops,\n+\t\t\t.priv   = st,\n+\t\t};\n+\n+\t\tret = devm_spi_offload_trigger_register(dev, &trigger_info);\n+\t\tif (ret)\n+\t\t\treturn dev_err_probe(dev, ret,\n+\t\t\t\t\t     \"Failed to register offload trigger\\n\");\n+\n+\t\toffload->trigger =\n+\t\t\tdevm_spi_offload_trigger_get(dev, offload->spi,\n+\t\t\t\t\t\t     SPI_OFFLOAD_TRIGGER_DATA_READY);\n+\t\tif (IS_ERR(offload->trigger))\n+\t\t\treturn dev_err_probe(dev, PTR_ERR(offload->trigger),\n+\t\t\t\t\t     \"Failed to get DATA_READY offload trigger\\n\");\n+\t}\n+\n+\trx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, offload->spi);\n+\tif (IS_ERR(rx_dma))\n+\t\treturn dev_err_probe(dev, PTR_ERR(rx_dma),\n+\t\t\t\t     \"Failed to get offload RX DMA channel\\n\");\n+\n+\tif (st->manual_mode)\n+\t\tindio_dev->setup_ops = &ad4691_manual_offload_buffer_setup_ops;\n+\telse\n+\t\tindio_dev->setup_ops = &ad4691_cnv_burst_offload_buffer_setup_ops;\n+\n+\tret = devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma,\n+\t\t\t\t\t\t\t  IIO_BUFFER_DIRECTION_IN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tindio_dev->buffer->attrs = ad4691_buffer_attrs;\n+\n+\treturn 0;\n+}\n+\n static int ad4691_probe(struct spi_device *spi)\n {\n \tstruct device *dev = &spi->dev;\n+\tstruct spi_offload *spi_offload;\n \tstruct iio_dev *indio_dev;\n \tstruct ad4691_state *st;\n \tint ret;\n@@ -1247,6 +1645,13 @@ static int ad4691_probe(struct spi_device *spi)\n \tif (ret)\n \t\treturn ret;\n \n+\tspi_offload = devm_spi_offload_get(dev, spi, &ad4691_offload_config);\n+\tret = PTR_ERR_OR_ZERO(spi_offload);\n+\tif (ret == -ENODEV)\n+\t\tspi_offload = NULL;\n+\telse if (ret)\n+\t\treturn dev_err_probe(dev, ret, \"Failed to get SPI offload\\n\");\n+\n \tindio_dev->name = st->info->name;\n \tindio_dev->info = &ad4691_info;\n \tindio_dev->modes = INDIO_DIRECT_MODE;\n@@ -1254,7 +1659,10 @@ static int ad4691_probe(struct spi_device *spi)\n \tindio_dev->channels = st->info->channels;\n \tindio_dev->num_channels = st->info->num_channels;\n \n-\tret = ad4691_setup_triggered_buffer(indio_dev, st);\n+\tif (spi_offload)\n+\t\tret = ad4691_setup_offload(indio_dev, st, spi_offload);\n+\telse\n+\t\tret = ad4691_setup_triggered_buffer(indio_dev, st);\n \tif (ret)\n \t\treturn ret;\n \n@@ -1292,3 +1700,5 @@ module_spi_driver(ad4691_driver);\n MODULE_AUTHOR(\"Radu Sabau <radu.sabau@analog.com>\");\n MODULE_DESCRIPTION(\"Analog Devices AD4691 Family ADC Driver\");\n MODULE_LICENSE(\"GPL\");\n+MODULE_IMPORT_NS(\"IIO_DMA_BUFFER\");\n+MODULE_IMPORT_NS(\"IIO_DMAENGINE_BUFFER\");\n",
    "prefixes": [
        "v5",
        "4/4"
    ]
}