From nobody Thu Jun 18 19:22:45 2026 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 C19A22DAFB0; Wed, 17 Jun 2026 02:03:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661817; cv=none; b=OebZbfBi0pFyEEU/u0A0qwPFi+BhpudD9x7vKwZg2jm+iXUAWOci4i7FkmPN4xaOZxnkmp+o2YJ/tHZl3Y8A+o6NXlNGXE1jOfEOoI5mgTr3/MP7qcohlflMzZ9SsYpjx359EQRugOr94/XmdrkOowdcRp1dlYqStkX9pS3whSc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661817; c=relaxed/simple; bh=LAa5L1nzj9Lm4QkMoa22RXaQfalIsleKN9YqTFrP9h8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Y8nto5z5kpAX/7aH2k9jaTseZDxvoEAsP8EWEQDTT4vPaDHvOptwy30N4P7LAzsFsEQy3Bs7QV9h5G557ItPv//gx2jFzU4n/ZY8oU5MLVBsg4S1UBxD8yrqGg1SHekFwrLHpyKg1JZyOmL4QL3j6cQczNwmZL98sz7VVabFSTQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=SgCigRJ0; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="SgCigRJ0" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65GLWpeM868794; Tue, 16 Jun 2026 22:03:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=kD5gH DHrRDodEGmztmom1FySarI7uXEJeG+ZzztLC20=; b=SgCigRJ0ULM/OHElEg9KA UUiQZRke2P07PP12qdyQa7ZnCscP4MKt50P/QY5/OHzwPUv0V1zIrgmegpDcmS7G 5WRRRhfg3ZTcS1cxzLwE9eNolIZ6/CjNu+vAYtbtaGz2u6PHIWVMac+/jcRr+Woh cu7lzmfw2g5NJAFAk3gv63EszyZACQUFR7Jmavj3qbxas3pPrMPi9MtP3bq/+Yxs nJ1sp3KFg0Mms2xqfelO00hT5FUAsEQNrTxKO2AFF2nsyatrblXNw0z72RGeo8XO 8mExsYLqG7e0LSL0nOvkJZFGRYdHnjKgahNjMHBsIj17+H/Vo7oZCAjJJqL0FaV/ Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4euegf0rky-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 16 Jun 2026 22:03:31 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 65H23UOm013966 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 16 Jun 2026 22:03:30 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:03:30 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:03:30 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.1748.37 via Frontend Transport; Tue, 16 Jun 2026 22:03:30 -0400 Received: from work.maxim-ic.internal ([10.66.6.192]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 65H23Hi4006709; Tue, 16 Jun 2026 22:03:19 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [PATCH v3 1/5] dt-bindings: iio: adc: Add ltc2378 Date: Tue, 16 Jun 2026 23:03:11 -0300 Message-ID: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=SaHHsPRu c=1 sm=1 tr=0 ts=6a320073 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=uXIjobp8t2wMuQ0fPvqm:22 a=gEfo2CItAAAA:8 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=Ke00WKluzF3GlLJr-2EA:9 a=sptkURWiP4Gy88Gu7hUp:22 X-Proofpoint-GUID: cZ7lm1xqEIEvt_4VLo_TSHJ_-O_Yya4g X-Proofpoint-ORIG-GUID: cZ7lm1xqEIEvt_4VLo_TSHJ_-O_Yya4g X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX4WK3ha1lDera o43jF0V3Nr9D1xypj9uuccL/kUcsXeFRFjksTMdNj+cPogpkowEwkAcMu2GEj0JiomoFYfnUsTN z0TuyaoQTowkJ8UtCcthQkP9/wLo/3N2KUenjBS85NOmEr6j24iPkcCf79KOx3tTD/Ijv8n9IzE U8EHHqQMqs+YDOy6CvIhSHOuqCItIGsHgnzUK2EXNzCT6A6aq4qacOClDbq2HfAntlbueMbPafM 0Nt9f5AdJZhevSkkkG5UfjM7WcTepRsr4Pk8BrUkeEdH6cZuMvq36QbahfebVWLrCokWHe7rYMW 9qrj6/OUSKrtpynwJd/7lgQrMtZmKDZeYQ0oRCsSsIKenJKJ8OWBh+f9bB4FlWxBBG1nYT7wFgI 5FTw2gznQrAqA024efyRw5b3aT2QAxeLoYbGl2bSQEgEx2rK7jOyJy1pW5z0xkUgVTlOTaWkHcI R4pFxKUpSpeXaUYA9UA== X-Proofpoint-Spam-Info: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfXzpNmXeAYJ9md WZR7z2f6MNhsJ2hDR6ZE3umQilAjFjZyulhIdGzLDlzxHFsBvzAhgsyn2Zj6mRoxnwIBzHNxRTc d7VDDvUHtSDX/XJ1XMipy5C8AAfT1lMJBipWptLZ6is9Rqh7dXs8 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-16_05,2026-06-16_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 adultscore=0 bulkscore=0 phishscore=0 lowpriorityscore=0 suspectscore=0 priorityscore=1501 impostorscore=0 clxscore=1015 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2606170017 Content-Type: text/plain; charset="utf-8" Document how to describe LTC2378-20 and similar ADCs in device tree. Signed-off-by: Marcelo Schmitt --- Change log v2 -> v3: - Re-added device tree fallback compatibles for LTC2378 chips, now with opt= ions to provide a single compatible string or a pair of single compatible stri= ng plus a fallback string to a slower sample rate spec in case a driver for = the specific part is not found. .../bindings/iio/adc/adi,ltc2378.yaml | 160 ++++++++++++++++++ MAINTAINERS | 7 + 2 files changed, 167 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ltc2378.y= aml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml b/D= ocumentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml new file mode 100644 index 000000000000..7d30a2cade8f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml @@ -0,0 +1,160 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ltc2378.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices LTC2378 and similar Analog to Digital Converters + +maintainers: + - Marcelo Schmitt + +description: | + Analog Devices LTC2378 series of ADCs. + Specifications can be found at: + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 3818fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6416fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6418f.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6716fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6718f.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6816f.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6818f.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 6918fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7016fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7616fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7618fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7620fb.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7716fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7718fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7720fb.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7816fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7818fa.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7820fb.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 7918fb.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/23= 8016fb.pdf + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + oneOf: + # Single compatible string match. + - enum: + - adi,ltc2338-18 + - adi,ltc2364-16 + - adi,ltc2364-18 + - adi,ltc2367-16 + - adi,ltc2367-18 + - adi,ltc2368-16 + - adi,ltc2368-18 + - adi,ltc2369-18 + - adi,ltc2370-16 + - adi,ltc2376-16 + - adi,ltc2376-18 + - adi,ltc2376-20 + - adi,ltc2377-16 + - adi,ltc2377-18 + - adi,ltc2377-20 + - adi,ltc2378-16 + - adi,ltc2378-18 + - adi,ltc2378-20 + - adi,ltc2379-18 + - adi,ltc2380-16 + + # Low sample rate fallback for 16-bit unipolar sensors. + - items: + - enum: + - adi,ltc2370-16 # 2 MSPS + - adi,ltc2368-16 # 1 MSPS + - adi,ltc2367-16 # 500 kSPS + - const: adi,ltc2364-16 # fallback (250 kSPS) + + # Low sample rate fallback for 18-bit unipolar sensors. + - items: + - enum: + - adi,ltc2369-18 # 1.6 MSPS + - adi,ltc2368-18 # 1 MSPS + - adi,ltc2367-18 # 500 kSPS + - const: adi,ltc2364-18 # fallback (250 kSPS) + + # Low sample rate fallback for 16-bit bipolar sensors. + - items: + - enum: + - adi,ltc2380-16 # 2 MSPS + - adi,ltc2378-16 # 1 MSPS + - adi,ltc2377-16 # 500 kSPS + - const: adi,ltc2376-16 # fallback (250 kSPS) + + # Low sample rate fallback for 18-bit bipolar sensors. + - items: + - enum: + - adi,ltc2379-18 # 1.6 MSPS + - adi,ltc2338-18 # 1 MSPS + - adi,ltc2378-18 # 1 MSPS + - adi,ltc2377-18 # 500 kSPS + - const: adi,ltc2376-18 # fallback (250 kSPS) + + # Low sample rate fallback for 20-bit bipolar sensors. + - items: + - enum: + - adi,ltc2378-20 # 1 MSPS + - adi,ltc2377-20 # 500 kSPS + - const: adi,ltc2376-20 # fallback (250 kSPS) + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 100000000 + + vdd-supply: + description: A 2.5V supply that powers the chip (VDD). + + ovdd-supply: + description: + A 1.71V to 5.25V supply that sets the logic level for digital interf= ace. + + ref-supply: + description: + A 2.5V to 5.1V supply for the reference input (REF). + + cnv-gpios: + description: + When provided, this property indicates the GPIO that is connected to= the + CNV pin. + maxItems: 1 + + interrupts: + description: + Interrupt for signaling the completion of conversion results. The ac= tive + low signal provided on the BUSY pin asserts when ADC conversions fin= ish. + maxItems: 1 + +required: + - compatible + - reg + - vdd-supply + - ovdd-supply + - ref-supply + +unevaluatedProperties: false + +examples: + - | + #include + #include + spi { + #address-cells =3D <1>; + #size-cells =3D <0>; + adc@0 { + compatible =3D "adi,ltc2378-20", "adi,ltc2376-20"; + reg =3D <0>; + spi-max-frequency =3D <71000000>; + vdd-supply =3D <&supply_2_5V>; + ovdd-supply =3D <&supply_3_3V>; + ref-supply =3D <&supply_5V>; + cnv-gpios =3D <&gpio0 88 GPIO_ACTIVE_HIGH>; + interrupts =3D <7 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent =3D <&gpio>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index b051eccafa60..205acb4b0789 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15220,6 +15220,13 @@ S: Maintained F: Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml F: drivers/iio/dac/ltc1660.c =20 +LTC2378 IIO ADC DRIVER +M: Marcelo Schmitt +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml + LTC2664 IIO DAC DRIVER M: Michael Hennerich M: Kim Seer Paller --=20 2.53.0 From nobody Thu Jun 18 19:22:45 2026 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 094EC2652A2; Wed, 17 Jun 2026 02:03:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661836; cv=none; b=iuGtdGP6LmkYXUCMs9F4CQ79MfenFXU7egWay6TbvCZQm1zSfTLShlLWkDHLUYk+oGXs484RCuDBNyEVR7fYzHCCPds6OFTP1M6+8PUDuYcCfDxscXWnMK+u7IZJGWtMhN3OOOFsvkx/x6CczpGZRjdoHs7updowHOiYRrFCWeI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661836; c=relaxed/simple; bh=D4gVNwovZaPYXAwkN1O0a7WBiqHCZUCXeXQQ0KtVdWo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=a2x4cX9yNqLMigyaB1PO7ROLTASrZYe3VsDiwGV1W1KcVfNI6/y3QbyR0qBck9QsgYPp9jYMr8S2ldiNjtY6LSu2UpN9u+Bra/tmfMaEdapmCeCDXnqcYyRMNGXeboWmvdYgVAPjfm5JK+y2OqH6Ux117kq0crDEQBPdMlKiP7Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=tHi3NNAp; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="tHi3NNAp" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65GLXMj21546962; Tue, 16 Jun 2026 22:03:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=eR9GH NhJEDBF2hA6hp/8upw1b6WjU1oXkwGAVZpBX2M=; b=tHi3NNAprQ1Bd7n7XhPjE d6h5rOoAo2ke9Cc39t6kzmwGJsjZjnyVzIDFtLeF0cbYVBa5ykM0AQJZyGXleynq UrTSOghavs5I+liRHsQMncEKG6+9mNjQO7/smyCeGoayYkjq7em5bysQ+xz5ZwdW 3NW+XFHEL9Sm1G9wITcxblIH23d6btrSJMNm5gAWXThqmHy9jSpXMMN66XvWcPnm IOEeWrNwb4atKZidxDBqdtA3SWZgSoY/CYzqKm/bPsHfcb/Wq/5+OU0iuxbUyBgL XYs5u4K6ZSKFSUCDuKTi+k1piOxrE8bGd3+GsCMTSlfE8VgU3whIBbTVKrvldI1y w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4euegr0rjr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 16 Jun 2026 22:03:50 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 65H23nkf014024 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 16 Jun 2026 22:03:49 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:03:49 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:03:49 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.1748.37 via Frontend Transport; Tue, 16 Jun 2026 22:03:49 -0400 Received: from work.maxim-ic.internal ([10.66.6.192]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 65H23c0L006720; Tue, 16 Jun 2026 22:03:40 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [PATCH v3 2/5] iio: adc: ltc2378: Add support for LTC2378-20 and similar ADCs Date: Tue, 16 Jun 2026 23:03:31 -0300 Message-ID: <5c18e7a370119ddfd5faefe147b294b39f78894a.1781661028.git.marcelo.schmitt@analog.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: rVIUQdk0W5YY2JLjMTvVEB3qBQwGrZuz X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX7SYT7TQDhElV pqdEnaxRnMVzjvrYHxfDf+Hul+GpGZipJXdc7bXuozdhmwPmdozH7FuOQfRIIYndBqYybQuPVMW ZGLdOBSXEx3rZopL4xJbCAJD6vpDuPPBTS+6n+ryG/RrVaMICP5d11KQIZKR7T0Kpoh0aqoCNTo 59TpfupG4Bywtawy2WjxCIkBFgKBvMEYPnPgTaL4U6axZ3KekE4VkFVyo7OchobZBeyL6dVOCEA L0IZCiETP6LditUJ6dvXL2BZj37e1p4MbJySXoXHwyJ7YuDcvqazBfPsu/zQgcI2ucKtT2n/gqY ZtIkELV7hf2mOrhSC4u0e25cxhz5CUwRl3Ho4NEmGjhFhGfW3A+7THIhe2bycT29mX495wYfCYx MnUtPIHlFBcAM/inUMCtg+wSLCc+7ZJTiCrT4bQchsNXAZpVeBep551e3UeU7JrXVUc9l46T9NK 6KnAcVdfWR+BnIuI21w== X-Proofpoint-GUID: rVIUQdk0W5YY2JLjMTvVEB3qBQwGrZuz X-Proofpoint-Spam-Info: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX20AbJHxbB0hl KtWBeeKfsJxH+qCgzZ5DgSANh3jPb+sHlnbkdShpZYcEybgitVJBUN9AdtVYXDYpnjEzTHzodf8 xSWD/K13rjIBX5A4CgG8GvURHEjGfG4I+UzD240I6snizBnxTgzr X-Authority-Analysis: v=2.4 cv=B+6JFutM c=1 sm=1 tr=0 ts=6a320087 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=Z0pTeXoby7EwIRygza74:22 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=ir6pry_9mBCdi5gbn5AA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-16_05,2026-06-16_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 lowpriorityscore=0 adultscore=0 bulkscore=0 clxscore=1015 phishscore=0 suspectscore=0 priorityscore=1501 impostorscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2606170017 Content-Type: text/plain; charset="utf-8" Support for LTC2378-20 and similar analog-to-digital converters. Co-developed-by: Ioan-Daniel Pop Signed-off-by: Ioan-Daniel Pop Signed-off-by: Marcelo Schmitt --- Change log v2 -> v3: - Restricted LTC2378 dependency list to require GPIO - Use datasheet terminology to indicate polarity/output code. - Added missing block scope to IIO_DEV_ACQUIRE_DIRECT_MODE. MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 11 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ltc2378.c | 338 ++++++++++++++++++++++++++++++++++++++ drivers/iio/adc/ltc2378.h | 63 +++++++ 5 files changed, 414 insertions(+) create mode 100644 drivers/iio/adc/ltc2378.c create mode 100644 drivers/iio/adc/ltc2378.h diff --git a/MAINTAINERS b/MAINTAINERS index 205acb4b0789..a11c00a78c13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15226,6 +15226,7 @@ L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml +F: drivers/iio/adc/ltc2378* =20 LTC2664 IIO DAC DRIVER M: Michael Hennerich diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a3a93a47b43d..2b8203451367 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -940,6 +940,17 @@ config LTC2309 This driver can also be built as a module. If so, the module will be called ltc2309. =20 +config LTC2378 + tristate "Analog Devices LTC2378 ADC driver" + depends on SPI + depends on GPIOLIB + help + Say yes here to build support for Analog Devices LTC2378-20 and + similar analog to digital converters. + + This driver can also be built as a module. If so, the module will + be called ltc2378. + config LTC2471 tristate "Linear Technology LTC2471 and LTC2473 ADC driver" depends on I2C diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 707dd708912f..1814fb78dde3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_LP8788_ADC) +=3D lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) +=3D lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) +=3D lpc32xx_adc.o obj-$(CONFIG_LTC2309) +=3D ltc2309.o +obj-$(CONFIG_LTC2378) +=3D ltc2378.o obj-$(CONFIG_LTC2471) +=3D ltc2471.o obj-$(CONFIG_LTC2485) +=3D ltc2485.o obj-$(CONFIG_LTC2496) +=3D ltc2496.o ltc2497-core.o diff --git a/drivers/iio/adc/ltc2378.c b/drivers/iio/adc/ltc2378.c new file mode 100644 index 000000000000..88582bdcd6a6 --- /dev/null +++ b/drivers/iio/adc/ltc2378.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Analog Devices LTC2378 ADC series driver + * + * Copyright (C) 2026 Analog Devices Inc. + * Author: Ioan-Daniel Pop + * Author: Marcelo Schmitt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ltc2378.h" + +static const struct ltc2378_chip_info ltc2338_18_chip_info =3D { + .name =3D "ltc2338-18", + .resolution =3D 18, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2364_16_chip_info =3D { + .name =3D "ltc2364-16", + .resolution =3D 16, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2364_18_chip_info =3D { + .name =3D "ltc2364-18", + .resolution =3D 18, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2367_16_chip_info =3D { + .name =3D "ltc2367-16", + .resolution =3D 16, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2367_18_chip_info =3D { + .name =3D "ltc2367-18", + .resolution =3D 18, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2368_16_chip_info =3D { + .name =3D "ltc2368-16", + .resolution =3D 16, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2368_18_chip_info =3D { + .name =3D "ltc2368-18", + .resolution =3D 18, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2369_18_chip_info =3D { + .name =3D "ltc2369-18", + .resolution =3D 18, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2370_16_chip_info =3D { + .name =3D "ltc2370-16", + .resolution =3D 16, + .bipolar =3D false, +}; + +static const struct ltc2378_chip_info ltc2376_16_chip_info =3D { + .name =3D "ltc2376-16", + .resolution =3D 16, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2376_18_chip_info =3D { + .name =3D "ltc2376-18", + .resolution =3D 18, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2376_20_chip_info =3D { + .name =3D "ltc2376-20", + .resolution =3D 20, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2377_16_chip_info =3D { + .name =3D "ltc2377-16", + .resolution =3D 16, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2377_18_chip_info =3D { + .name =3D "ltc2377-18", + .resolution =3D 18, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2377_20_chip_info =3D { + .name =3D "ltc2377-20", + .resolution =3D 20, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2378_16_chip_info =3D { + .name =3D "ltc2378-16", + .resolution =3D 16, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2378_18_chip_info =3D { + .name =3D "ltc2378-18", + .resolution =3D 18, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2378_20_chip_info =3D { + .name =3D "ltc2378-20", + .resolution =3D 20, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2379_18_chip_info =3D { + .name =3D "ltc2379-18", + .resolution =3D 18, + .bipolar =3D true, +}; + +static const struct ltc2378_chip_info ltc2380_16_chip_info =3D { + .name =3D "ltc2380-16", + .resolution =3D 16, + .bipolar =3D true, +}; + +static int ltc2378_channel_single_read(const struct iio_chan_spec *chan, + struct ltc2378_state *st, int *val) +{ + const struct iio_scan_type *scan_type =3D &chan->scan_type; + u32 sample; + int ret; + + ret =3D ltc2378_convert_and_acquire(st); + if (ret) + return ret; + + if (scan_type->realbits > 16) + sample =3D st->scan.data.sample_buf32; + else + sample =3D st->scan.data.sample_buf16; + + if (scan_type->format =3D=3D IIO_SCAN_FORMAT_SIGNED_INT) + *val =3D sign_extend32(sample, scan_type->realbits - 1); + else + *val =3D sample; + + return 0; +} + +static int ltc2378_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long info) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + int ret; + + switch (info) { + case IIO_CHAN_INFO_RAW: { + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + ret =3D ltc2378_channel_single_read(chan, st, val); + if (ret) + return ret; + + return IIO_VAL_INT; + } + case IIO_CHAN_INFO_SCALE: + *val =3D st->ref_uV / MILLI; + /* + * For all LTC2378-like devices, the amount of bits that express + * voltage magnitude depend on the polarity / output code format: + * - straight binary: All precision/resolution bits are used. + * - 2's complement: One of the precision bits is used for sign. + */ + if (st->info->bipolar) + *val2 =3D st->info->resolution - 1; + else + *val2 =3D st->info->resolution; + + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +static const struct iio_info ltc2378_iio_info =3D { + .read_raw =3D <c2378_read_raw, +}; + +static int ltc2378_probe(struct spi_device *spi) +{ + struct device *dev =3D &spi->dev; + struct iio_dev *indio_dev; + struct ltc2378_state *st; + int ret; + + indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st =3D iio_priv(indio_dev); + st->spi =3D spi; + + ret =3D devm_regulator_get_enable_read_voltage(dev, "ref"); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read ref regulator\n"); + + st->ref_uV =3D ret; + st->info =3D spi_get_device_match_data(spi); + if (!st->info) + return -EINVAL; + + indio_dev->name =3D st->info->name; + indio_dev->info =3D <c2378_iio_info; + indio_dev->modes =3D INDIO_DIRECT_MODE; + + st->cnv_gpio =3D devm_gpiod_get(dev, "cnv", GPIOD_OUT_LOW); + if (IS_ERR(st->cnv_gpio)) + return dev_err_probe(dev, PTR_ERR(st->cnv_gpio), + "failed to get CNV GPIO"); + + st->num_iio_chans =3D 0; + st->chans[st->num_iio_chans++] =3D (struct iio_chan_spec) { + .type =3D IIO_VOLTAGE, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .scan_index =3D 0, + .scan_type =3D { + .format =3D st->info->bipolar ? IIO_SCAN_FORMAT_SIGNED_INT : + IIO_SCAN_FORMAT_UNSIGNED_INT, + .realbits =3D st->info->resolution, + /* + * Buffer elements could be 16-bit for low precision + * parts. Though, using more storage bits allows keeping + * the same scan_type configuration for both types of + * buffer support. + */ + .storagebits =3D 32, + }, + }; + + st->xfer.rx_buf =3D &st->scan.data; + st->xfer.len =3D st->info->resolution > 16 ? 4 : 2; + st->xfer.bits_per_word =3D st->info->resolution; + + indio_dev->channels =3D st->chans; + indio_dev->num_channels =3D st->num_iio_chans; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct of_device_id ltc2378_of_match[] =3D { + { .compatible =3D "adi,ltc2338-18", .data =3D <c2338_18_chip_info }, + { .compatible =3D "adi,ltc2364-16", .data =3D <c2364_16_chip_info }, + { .compatible =3D "adi,ltc2364-18", .data =3D <c2364_18_chip_info }, + { .compatible =3D "adi,ltc2367-16", .data =3D <c2367_16_chip_info }, + { .compatible =3D "adi,ltc2367-18", .data =3D <c2367_18_chip_info }, + { .compatible =3D "adi,ltc2368-16", .data =3D <c2368_16_chip_info }, + { .compatible =3D "adi,ltc2368-18", .data =3D <c2368_18_chip_info }, + { .compatible =3D "adi,ltc2369-18", .data =3D <c2369_18_chip_info }, + { .compatible =3D "adi,ltc2370-16", .data =3D <c2370_16_chip_info }, + { .compatible =3D "adi,ltc2376-16", .data =3D <c2376_16_chip_info }, + { .compatible =3D "adi,ltc2376-18", .data =3D <c2376_18_chip_info }, + { .compatible =3D "adi,ltc2376-20", .data =3D <c2376_20_chip_info }, + { .compatible =3D "adi,ltc2377-16", .data =3D <c2377_16_chip_info }, + { .compatible =3D "adi,ltc2377-18", .data =3D <c2377_18_chip_info }, + { .compatible =3D "adi,ltc2377-20", .data =3D <c2377_20_chip_info }, + { .compatible =3D "adi,ltc2378-16", .data =3D <c2378_16_chip_info }, + { .compatible =3D "adi,ltc2378-18", .data =3D <c2378_18_chip_info }, + { .compatible =3D "adi,ltc2378-20", .data =3D <c2378_20_chip_info }, + { .compatible =3D "adi,ltc2379-18", .data =3D <c2379_18_chip_info }, + { .compatible =3D "adi,ltc2380-16", .data =3D <c2380_16_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ltc2378_of_match); + +static const struct spi_device_id ltc2378_spi_id[] =3D { + { .name =3D "ltc2338-18", .driver_data =3D (kernel_ulong_t)<c2338_18_ch= ip_info }, + { .name =3D "ltc2364-16", .driver_data =3D (kernel_ulong_t)<c2364_16_ch= ip_info }, + { .name =3D "ltc2364-18", .driver_data =3D (kernel_ulong_t)<c2364_18_ch= ip_info }, + { .name =3D "ltc2367-16", .driver_data =3D (kernel_ulong_t)<c2367_16_ch= ip_info }, + { .name =3D "ltc2367-18", .driver_data =3D (kernel_ulong_t)<c2367_18_ch= ip_info }, + { .name =3D "ltc2368-16", .driver_data =3D (kernel_ulong_t)<c2368_16_ch= ip_info }, + { .name =3D "ltc2368-18", .driver_data =3D (kernel_ulong_t)<c2368_18_ch= ip_info }, + { .name =3D "ltc2369-18", .driver_data =3D (kernel_ulong_t)<c2369_18_ch= ip_info }, + { .name =3D "ltc2370-16", .driver_data =3D (kernel_ulong_t)<c2370_16_ch= ip_info }, + { .name =3D "ltc2376-16", .driver_data =3D (kernel_ulong_t)<c2376_16_ch= ip_info }, + { .name =3D "ltc2376-18", .driver_data =3D (kernel_ulong_t)<c2376_18_ch= ip_info }, + { .name =3D "ltc2376-20", .driver_data =3D (kernel_ulong_t)<c2376_20_ch= ip_info }, + { .name =3D "ltc2377-16", .driver_data =3D (kernel_ulong_t)<c2377_16_ch= ip_info }, + { .name =3D "ltc2377-18", .driver_data =3D (kernel_ulong_t)<c2377_18_ch= ip_info }, + { .name =3D "ltc2377-20", .driver_data =3D (kernel_ulong_t)<c2377_20_ch= ip_info }, + { .name =3D "ltc2378-16", .driver_data =3D (kernel_ulong_t)<c2378_16_ch= ip_info }, + { .name =3D "ltc2378-18", .driver_data =3D (kernel_ulong_t)<c2378_18_ch= ip_info }, + { .name =3D "ltc2378-20", .driver_data =3D (kernel_ulong_t)<c2378_20_ch= ip_info }, + { .name =3D "ltc2379-18", .driver_data =3D (kernel_ulong_t)<c2379_18_ch= ip_info }, + { .name =3D "ltc2380-16", .driver_data =3D (kernel_ulong_t)<c2380_16_ch= ip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ltc2378_spi_id); + +static struct spi_driver ltc2378_driver =3D { + .driver =3D { + .name =3D "ltc2378", + .of_match_table =3D ltc2378_of_match + }, + .probe =3D ltc2378_probe, + .id_table =3D ltc2378_spi_id, +}; +module_spi_driver(ltc2378_driver); + +MODULE_AUTHOR("Ioan-Daniel Pop "); +MODULE_AUTHOR("Marcelo Schmitt "); +MODULE_DESCRIPTION("Analog Devices LTC2378 ADC series driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ltc2378.h b/drivers/iio/adc/ltc2378.h new file mode 100644 index 000000000000..a3a69351de6c --- /dev/null +++ b/drivers/iio/adc/ltc2378.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Analog Devices LTC2378 and similar ADCs common definitions and properti= es + * Copyright (C) 2026 Analog Devices, Inc. + * Author: Marcelo Schmitt + */ + +#ifndef __DRIVERS_IIO_ADC_LTC2378_H__ +#define __DRIVERS_IIO_ADC_LTC2378_H__ + +#include +#include +#include +#include +#include +#include + +#define LTC2378_TDSDOBUSYL_NS 5 +#define LTC2378_TBUSYLH_NS 13 +#define LTC2378_TCNV_HIGH_NS 20 + +struct ltc2378_chip_info { + const char *name; + int resolution; + bool bipolar; +}; + +struct ltc2378_state { + const struct ltc2378_chip_info *info; + struct gpio_desc *cnv_gpio; + struct spi_device *spi; + struct spi_transfer xfer; + unsigned int num_iio_chans; + struct iio_chan_spec chans[2]; /* 1 physical chan + 1 timestamp chan */ + int ref_uV; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + struct { + union { + u16 sample_buf16; + u32 sample_buf32; + } data; + aligned_s64 timestamp; + } scan __aligned(IIO_DMA_MINALIGN); +}; + +static inline int ltc2378_convert_and_acquire(struct ltc2378_state *st) +{ + int ret; + + /* Cause a rising edge of CNV to initiate a new ADC conversion */ + gpiod_set_value_cansleep(st->cnv_gpio, 1); + fsleep(4); + ret =3D spi_sync_transfer(st->spi, &st->xfer, 1); + gpiod_set_value_cansleep(st->cnv_gpio, 0); + + return ret; +} + +#endif /* __DRIVERS_IIO_ADC_LTC2378_H__ */ --=20 2.53.0 From nobody Thu Jun 18 19:22:45 2026 Received: from mx0b-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 BD4232DAFB0; Wed, 17 Jun 2026 02:04:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661857; cv=none; b=nf7RZ+9Nhaj+0QXTJkbWMdmWuk+P9sd/FeoAfHe1AiWNiS01BChuYjwli+unTp82yZfaDKQePLm00o7Q77eoEWRFkAwI39/QpR0wRUFMrbCcYyuhF0zHqMeqLV4RammzazqjLSn/z/q96/xuVXHJSULftU8Skx4p6eKxU4H1H0A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661857; c=relaxed/simple; bh=FhfSYVm3F0bLH5URDUwkddaTqy8yOatFVx3dTmfls6g=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BV9g9FpRyTy/WafoflOjVipoZ8A5mlEMcQ5Xc0u4x/Ky3nKRhH64B4wBrUMf3YKkJFt0FJ7dKcUZRYawj+f1/zeXWiONhUs4dr/IHuCEmT72DrDawaAKJ4H/SJ/4sNyddEqHwmK9rHbgb0rX9M74I0Ysr+C4mQX2JkiSsQDsZJs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=Aqp8g4rV; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="Aqp8g4rV" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65GLWngg878691; Tue, 16 Jun 2026 22:04:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=nWF6F 6ntQyewEsS7eA4VlYeGjRHpfU4y+XRxCuGPYBA=; b=Aqp8g4rVXmk2o39YLEtdx bOEv3s6NGQO4ohzZbthNtovJ+5jnqrgRTY1Os4p6jcj8nrZxgKEtt62HF4+WlFNN KvRQi+bnBnkE6sgw/BXYelFtlsGV+SH/OW5zU2N5Ds8WmQi5mpaN63VWh3NQXX2S UBgeAUbGM8UeETcBju4RZKY6iDOe4evUtqEBk8LT9/shXNLQpAjn5QnQOcGskwaC AHzxrWkq3m+GCxMQRNq/uq9obQhAIXfrLprjcXPKj3flBfiTVG0g57rcfqiCDfgc Qjhm10qGgqujTzXF0ynismN2Sb0FdAwVLklH1FtjdjPD3/C+gwb4PGCgLWpjQmTz A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4euegdrs95-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 16 Jun 2026 22:04:12 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 65H24BrC014056 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 16 Jun 2026 22:04:11 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:04:11 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:04:10 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.1748.37 via Frontend Transport; Tue, 16 Jun 2026 22:04:10 -0400 Received: from work.maxim-ic.internal ([10.66.6.192]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 65H23xlA006741; Tue, 16 Jun 2026 22:04:01 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [RFC PATCH v3 3/5] iio: buffer: Extend DMAengine buffer interfaces to take extra sysfs attributes Date: Tue, 16 Jun 2026 23:03:54 -0300 Message-ID: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX8u2wxR34PnJ3 71NNxhgcBeU2rhdpKqOwXNDoZ+DxJZ6JbnQ28MCsYZRCI+LF69bbQTI5PvzAthrtm27H09MAncx w54Fp0WCwU1s/iVidAzZjaJ+CLkgsAH78/qZrcBNeNAv6jdtvK8GecVWnljWmC3QyXSbxV4QO4Z NwTCpsUzJgx4UozsqvUJz9XVAN9rpRXD41PmXizwXhAfPKInu7i9JXnLl5DjbAG/ggJw4f/IqQf j4frWK/WgE8uL4eSmd8w20YBairJnVVvRTOZSWeYZQTMR8nFNWTpaW+t0fbS+XvmRgvlv0acdr+ GW3gXYUM6wBhv5U8P2XRi8ZkaAt/DeQqKwDErEE1xzQ4OtXI7fua2uqJheCVnKS7n5v93L8ETDV vT00NgbU8XpR11tCtZW3zauN1wAw4vsi2xgOoKMmrqZkdS/8JObOEISSSbUgyiba3hUPZQyyIHn GdTtMbymxq+zlIbRLGQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfXz5kH6ph4GSO8 CYO3aYon+FnCvN7wrrmsPc2wOL+qf+l33Q4qTDGkFHaz6fp1+oOxLzfn1qGDrIf0cQXD1EOCjUh xq7EZFODlLrxm44AvrXu8nojh2fGo7iLXeyUc/zlQn2bNdXFuBc1 X-Authority-Analysis: v=2.4 cv=BbvoFLt2 c=1 sm=1 tr=0 ts=6a32009c cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=N--XFCr6TIEc_64PeIT2:22 a=gAnH3GRIAAAA:8 a=hDpiA95YCBQlF3wP6JkA:9 X-Proofpoint-GUID: TUJsY0GfnoyWZCTV_dsF7OcdivoKBFgJ X-Proofpoint-ORIG-GUID: TUJsY0GfnoyWZCTV_dsF7OcdivoKBFgJ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-16_05,2026-06-16_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 malwarescore=0 suspectscore=0 impostorscore=0 adultscore=0 priorityscore=1501 lowpriorityscore=0 spamscore=0 phishscore=0 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2606170017 Content-Type: text/plain; charset="utf-8" Some devices using DMAengine buffers are connected to extra hardware that allows setting how fast data is transferred to/from the buffer. However, those extra pieces of harwdware are external to the sensor chip such that supporting the transfer speed as a sensor property is a bit of an inaccuracy. Expand IIO DMAengine buffer interfaces to take arguments for extra sysfs attributes, enabling the transfer speed to be configured through the buffer interface. Signed-off-by: Marcelo Schmitt --- New patch. Now that I've come to this buffer "solution", I have pretty much convinced myself it would be better to instead have some sort of IIO trigger to contr= ol the signal source connected to SPI offloading trigger module. drivers/iio/adc/ad4000.c | 3 ++- drivers/iio/adc/ad4030.c | 3 ++- drivers/iio/adc/ad4691.c | 3 ++- drivers/iio/adc/ad4695.c | 2 +- drivers/iio/adc/ad7380.c | 2 +- drivers/iio/adc/ad7606_spi.c | 2 +- drivers/iio/adc/ad7768-1.c | 3 ++- drivers/iio/adc/ad7944.c | 2 +- drivers/iio/adc/ad_sigma_delta.c | 2 +- .../buffer/industrialio-buffer-dmaengine.c | 19 ++++++++++++------- drivers/iio/dac/ad5791.c | 2 +- drivers/iio/dac/ad8460.c | 2 +- drivers/iio/dac/adi-axi-dac.c | 2 +- include/linux/iio/buffer-dmaengine.h | 16 ++++++++++------ 14 files changed, 38 insertions(+), 25 deletions(-) diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c index fd3d79fca785..b79b627310af 100644 --- a/drivers/iio/adc/ad4000.c +++ b/drivers/iio/adc/ad4000.c @@ -871,7 +871,8 @@ static int ad4000_spi_offload_setup(struct iio_dev *ind= io_dev, "Failed to get offload RX DMA\n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dm= a, - IIO_BUFFER_DIRECTION_IN); + IIO_BUFFER_DIRECTION_IN, + NULL); if (ret) return dev_err_probe(dev, ret, "Failed to setup DMA buffer\n"); =20 diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c index 9c5f19321e3b..713fe95176c0 100644 --- a/drivers/iio/adc/ad4030.c +++ b/drivers/iio/adc/ad4030.c @@ -1400,7 +1400,8 @@ static int ad4030_spi_offload_setup(struct iio_dev *i= ndio_dev, "failed to get offload RX DMA\n"); =20 return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, - IIO_BUFFER_DIRECTION_IN); + IIO_BUFFER_DIRECTION_IN, + NULL); } =20 static int ad4030_setup_pga(struct device *dev, struct iio_dev *indio_dev, diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c index 548678adc2a4..9845fe9c4725 100644 --- a/drivers/iio/adc/ad4691.c +++ b/drivers/iio/adc/ad4691.c @@ -1980,7 +1980,8 @@ static int ad4691_setup_offload(struct iio_dev *indio= _dev, indio_dev->setup_ops =3D &ad4691_cnv_burst_offload_buffer_setup_ops; =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dm= a, - IIO_BUFFER_DIRECTION_IN); + IIO_BUFFER_DIRECTION_IN, + NULL); if (ret) return ret; =20 diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 53642de7330d..78faeade19f5 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -1779,7 +1779,7 @@ static int ad4695_probe_spi_offload(struct iio_dev *i= ndio_dev, } =20 return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, - rx_dma, IIO_BUFFER_DIRECTION_IN); + rx_dma, IIO_BUFFER_DIRECTION_IN, NULL); } =20 static const struct spi_offload_config ad4695_spi_offload_config =3D { diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 9f77990a03f9..415b8e1be920 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -1874,7 +1874,7 @@ static int ad7380_probe_spi_offload(struct iio_dev *i= ndio_dev, "failed to get offload RX DMA\n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, - rx_dma, IIO_BUFFER_DIRECTION_IN); + rx_dma, IIO_BUFFER_DIRECTION_IN, NULL); if (ret) return dev_err_probe(dev, ret, "cannot setup dma buffer\n"); =20 diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c index 7e17ccbcedd0..760b54bfe208 100644 --- a/drivers/iio/adc/ad7606_spi.c +++ b/drivers/iio/adc/ad7606_spi.c @@ -317,7 +317,7 @@ static int ad7606_spi_offload_probe(struct device *dev, "failed to get offload RX DMA\n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, - rx_dma, IIO_BUFFER_DIRECTION_IN); + rx_dma, IIO_BUFFER_DIRECTION_IN, NULL); if (ret) return dev_err_probe(dev, ret, "failed to setup offload RX DMA\n"); diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index 598936e47fd2..a13ac31281d8 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -1792,7 +1792,8 @@ static int ad7768_spi_offload_probe(struct iio_dev *i= ndio_dev, return dev_err_probe(dev, PTR_ERR(rx_dma), "failed to get offload RX DMA= \n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dm= a, - IIO_BUFFER_DIRECTION_IN); + IIO_BUFFER_DIRECTION_IN, + NULL); if (ret) return dev_err_probe(dev, ret, "failed to setup offload RX DMA\n"); =20 diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 7722cf9e8214..63852a6c2acc 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -843,7 +843,7 @@ static int ad7944_probe(struct spi_device *spi) */ =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, - indio_dev, rx_dma, IIO_BUFFER_DIRECTION_IN); + indio_dev, rx_dma, IIO_BUFFER_DIRECTION_IN, NULL); if (ret) return ret; =20 diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_de= lta.c index a955556f9ec8..4b88e1c72c87 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -820,7 +820,7 @@ int devm_ad_sd_setup_buffer_and_trigger(struct device *= dev, struct iio_dev *indi "Failed to get RX DMA channel\n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, - rx_dma, IIO_BUFFER_DIRECTION_IN); + rx_dma, IIO_BUFFER_DIRECTION_IN, NULL); if (ret) return dev_err_probe(dev, ret, "Cannot setup DMA buffer\n"); =20 diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/i= io/buffer/industrialio-buffer-dmaengine.c index 98acce909854..343dbb6d1446 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -289,7 +289,8 @@ EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_teardown, "II= O_DMAENGINE_BUFFER"); static struct iio_buffer *__iio_dmaengine_buffer_setup_ext(struct iio_dev *indio_dev, struct dma_chan *chan, - enum iio_buffer_direction dir) + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs) { struct iio_buffer *buffer; int ret; @@ -301,6 +302,7 @@ static struct iio_buffer indio_dev->modes |=3D INDIO_BUFFER_HARDWARE; =20 buffer->direction =3D dir; + buffer->attrs =3D buffer_attrs; =20 ret =3D iio_device_attach_buffer(indio_dev, buffer); if (ret) { @@ -329,7 +331,8 @@ static struct iio_buffer struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, - enum iio_buffer_direction dir) + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs) { struct dma_chan *chan; struct iio_buffer *buffer; @@ -338,7 +341,7 @@ struct iio_buffer *iio_dmaengine_buffer_setup_ext(struc= t device *dev, if (IS_ERR(chan)) return ERR_CAST(chan); =20 - buffer =3D __iio_dmaengine_buffer_setup_ext(indio_dev, chan, dir); + buffer =3D __iio_dmaengine_buffer_setup_ext(indio_dev, chan, dir, buffer_= attrs); if (IS_ERR(buffer)) dma_release_channel(chan); =20 @@ -366,11 +369,12 @@ static void devm_iio_dmaengine_buffer_teardown(void *= buffer) int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, - enum iio_buffer_direction dir) + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs) { struct iio_buffer *buffer; =20 - buffer =3D iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, dir); + buffer =3D iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, dir, b= uffer_attrs); if (IS_ERR(buffer)) return PTR_ERR(buffer); =20 @@ -403,11 +407,12 @@ static void devm_iio_dmaengine_buffer_free(void *buff= er) int devm_iio_dmaengine_buffer_setup_with_handle(struct device *dev, struct iio_dev *indio_dev, struct dma_chan *chan, - enum iio_buffer_direction dir) + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs) { struct iio_buffer *buffer; =20 - buffer =3D __iio_dmaengine_buffer_setup_ext(indio_dev, chan, dir); + buffer =3D __iio_dmaengine_buffer_setup_ext(indio_dev, chan, dir, buffer_= attrs); if (IS_ERR(buffer)) return PTR_ERR(buffer); =20 diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index ae7297f08398..024607adb915 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -448,7 +448,7 @@ static int ad5791_offload_setup(struct iio_dev *indio_d= ev) "failed to get offload TX DMA\n"); =20 ret =3D devm_iio_dmaengine_buffer_setup_with_handle(&spi->dev, - indio_dev, tx_dma, IIO_BUFFER_DIRECTION_OUT); + indio_dev, tx_dma, IIO_BUFFER_DIRECTION_OUT, NULL); if (ret) return ret; =20 diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c index 6e45686902dd..3c5fd71d5add 100644 --- a/drivers/iio/dac/ad8460.c +++ b/drivers/iio/dac/ad8460.c @@ -921,7 +921,7 @@ static int ad8460_probe(struct spi_device *spi) indio_dev->setup_ops =3D &ad8460_buffer_setup_ops; =20 ret =3D devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, "tx", - IIO_BUFFER_DIRECTION_OUT); + IIO_BUFFER_DIRECTION_OUT, NULL); if (ret) return dev_err_probe(dev, ret, "Failed to get DMA buffer\n"); diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 451fad34e7ee..23028a92ceba 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -162,7 +162,7 @@ static struct iio_buffer *axi_dac_request_buffer(struct= iio_backend *back, dma_name =3D "tx"; =20 return iio_dmaengine_buffer_setup_ext(st->dev, indio_dev, dma_name, - IIO_BUFFER_DIRECTION_OUT); + IIO_BUFFER_DIRECTION_OUT, NULL); } =20 static void axi_dac_free_buffer(struct iio_backend *back, diff --git a/include/linux/iio/buffer-dmaengine.h b/include/linux/iio/buffe= r-dmaengine.h index 37f27545f69f..bb7a348db72d 100644 --- a/include/linux/iio/buffer-dmaengine.h +++ b/include/linux/iio/buffer-dmaengine.h @@ -10,6 +10,7 @@ #include =20 struct iio_dev; +struct iio_dev_attr; struct device; struct dma_chan; =20 @@ -17,23 +18,26 @@ void iio_dmaengine_buffer_teardown(struct iio_buffer *b= uffer); struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, - enum iio_buffer_direction dir); + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs); =20 #define iio_dmaengine_buffer_setup(dev, indio_dev, channel) \ - iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, \ - IIO_BUFFER_DIRECTION_IN) + iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, \ + IIO_BUFFER_DIRECTION_IN, NULL) =20 int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, - enum iio_buffer_direction dir); + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs); int devm_iio_dmaengine_buffer_setup_with_handle(struct device *dev, struct iio_dev *indio_dev, struct dma_chan *chan, - enum iio_buffer_direction dir); + enum iio_buffer_direction dir, + const struct iio_dev_attr **buffer_attrs); =20 #define devm_iio_dmaengine_buffer_setup(dev, indio_dev, channel) \ devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, \ - IIO_BUFFER_DIRECTION_IN) + IIO_BUFFER_DIRECTION_IN, NULL) =20 #endif --=20 2.53.0 From nobody Thu Jun 18 19:22:45 2026 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 C893E2E7363; Wed, 17 Jun 2026 02:04:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661883; cv=none; b=TwmFPzyuY5t9jBNAE0yPNPz0GXjFOFLkJt0MSItZqb2wNOsjyWvac2otRjOnkb+A7hRa+tuhafDoKa69Gs/a3lAEpY3m2AJ2KuQmwX5eS5jk3yxXgV3dvZk5F6egCPhIXSx34A8llvdQBdZkEcGhG1EYII0vzruneIJjFtlHqp0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661883; c=relaxed/simple; bh=k9tMFRw0NReHYdwrlFkEFBCI9fT9X7g406/5x21Dx8A=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oqHj8oTXr14VxMMMZxPrF1vi97mIVqfiXXkt/QAUrlarhd7+2dmpOLD29jW5OXjn2JVrGfFxjKdwG+grbqoUFueiRWERNSVXS4HCk/qdDE2yr3HqOJeyzjXrS2HwS6B4ZVeMuHxoQr5/C3L2jPD4Bdo9tr92mpcSDrpZonnmfiM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=FTqRulK4; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="FTqRulK4" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65GLWmcE868546; Tue, 16 Jun 2026 22:04:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=F/tVO vQDqDOCHvuleOi0YljzHBdUmBPMzvaQSN0Tx3s=; b=FTqRulK4u133G8fo7Z07B WN2evYJ2hIU55BZg8G0tQlaziq0XovxM3vjzQXbT3RYx2m9+njhsuCFKQoZPDKOa +2Y1KwXtxS/plgWgbcbU2YnHRpUpt3e1Scpf4wtrCokHuQI+xgiUav86J+PW+T3w hP9LrHZse3VijpCJALPXBhRrs71lWOIe+ui+B09h7SVfV0ZuUcxY28vaM08vEAXb X2H1l0+fhCXS0WrinQmuRMMN0CeslC9pyOWT1O0EIYki7XKVbF0q/kZE1zNuI5dF L40ZCeX/VlxuJZH3CbBbFmiAReOnGunYjjQW3iz5D/LepTXClRPbWj8Hma8NNdMr Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4euegf0rps-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 16 Jun 2026 22:04:38 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 65H24awX014091 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 16 Jun 2026 22:04:36 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:04:36 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.1748.37 via Frontend Transport; Tue, 16 Jun 2026 22:04:36 -0400 Received: from work.maxim-ic.internal ([10.66.6.192]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 65H24PZt006750; Tue, 16 Jun 2026 22:04:27 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [PATCH v3 4/5] iio: adc: ltc2378: Enable high-speed data capture Date: Tue, 16 Jun 2026 23:04:20 -0300 Message-ID: <9f173c47928446aa3e900cf0becb6130dd76846b.1781661028.git.marcelo.schmitt@analog.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=SaHHsPRu c=1 sm=1 tr=0 ts=6a3200b6 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=uXIjobp8t2wMuQ0fPvqm:22 a=gAnH3GRIAAAA:8 a=I7Ct1wI2BZskGqBcPl8A:9 X-Proofpoint-GUID: _zj4BpYz6Id94jMSZ0mv6ygf7ij_RoUT X-Proofpoint-ORIG-GUID: _zj4BpYz6Id94jMSZ0mv6ygf7ij_RoUT X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX3EZbHL7nDLTt WTobsdp8Sq6O7ke/tImJs3/bu7tsIJ7Z1ThqtJesuPnYkcFupFDKebYpQqZvDpXMHi8UOkp6KNC PVxNxqUV7v4pbKJs5CY+3HsXwzW8r6bpTCE5mLB5dTK1KJc90e7I16WBFLFmcVxq33UmkG/wi/D yMNZRhds/Qz2PNnh79g7HtHLpPEPFkDEommQxqFl5YEm448hel0qmbrs8Xc/w996uvrNFhFmoLd n1S6EfIJX9m4vRFc4/I2rVHVlWl8AXHiDluN0mkrpWgoN6vLLwVqRCcP6ZjxV0xkyy9QRGAh0Nm Qv10zKlZBTo5rLIDyxDb0J+0tT0QqjNw4OxLcalc6NSLN5E8m1kjX468SGen/+GnzZWngIg6gy7 CSs/X7dL+u4vY0Y0lrBnCjkd7+ioNUYK87zpyr4mgz+59nYRr5oEWe2JHJfxEUyE8//8/H0gjA1 8fO6GmoUEQ2bQRvbPpw== X-Proofpoint-Spam-Info: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX1pj4TTB+oxB7 xgSx7OXyfN9F8IfnWF6vfRK61hbhQ5maLZL5gRi15pY18hUv3RrD+tM35JoQEyHYjUtieU7VsVo 4y4eGJ/Pps8byXBw8kL8JkpNnrbhJzj5S3OjnGErJh8FNMMNtEIy X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-16_05,2026-06-16_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 adultscore=0 bulkscore=0 phishscore=0 lowpriorityscore=0 suspectscore=0 priorityscore=1501 impostorscore=0 clxscore=1015 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2606170017 Content-Type: text/plain; charset="utf-8" Make use of SPI transfer offloading to speed up data capture, enabling data acquisition at faster sample rates (up to 2 MSPS). Signed-off-by: Marcelo Schmitt --- Change log v2 -> v3: - Fixed the evaluation loop conditions for CNV PWM and SPI Engine trigger P= WM, avoiding potential infinite loop if and CPU stall. - Added comment to about initial PWM disable. - Adjusted SPI offload setup initialization to not print error on a valid c= ondition. - Fully initialize IIO channel scan_type. - Reworked to make offload support not imply all dependencies to be built i= n. - Made sampling_frequency a buffer attribute. - Made offload support not require DMA and other features to be built in. - Now using same scan_type configuration for all use cases. drivers/iio/adc/Kconfig | 19 ++ drivers/iio/adc/Makefile | 6 + drivers/iio/adc/ltc2378-lib-core.c | 35 +++ drivers/iio/adc/ltc2378-offload-buffer.c | 305 +++++++++++++++++++++++ drivers/iio/adc/ltc2378.c | 46 ++++ drivers/iio/adc/ltc2378.h | 42 ++++ 6 files changed, 453 insertions(+) create mode 100644 drivers/iio/adc/ltc2378-lib-core.c create mode 100644 drivers/iio/adc/ltc2378-offload-buffer.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2b8203451367..f96d9262b891 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -944,6 +944,9 @@ config LTC2378 tristate "Analog Devices LTC2378 ADC driver" depends on SPI depends on GPIOLIB + select LTC2378_LIB + select LTC2378_LIB_OFFLOAD_BUFFER if SPI_OFFLOAD && PWM && SPI_OFFLOAD_TR= IGGER_PWM && IIO_BUFFER && IIO_BUFFER_DMAENGINE + select LTC2378_LIB_TRIGGERED_BUFFER if IIO_BUFFER help Say yes here to build support for Analog Devices LTC2378-20 and similar analog to digital converters. @@ -2027,3 +2030,19 @@ config XILINX_AMS xilinx-ams. =20 endmenu + +config LTC2378_LIB + tristate + help + Say yes here to build support for buffered data capture with LTC2378 + +config LTC2378_LIB_OFFLOAD_BUFFER + bool + help + Say yes here to build support for high speed data capture with LTC2378 + +config LTC2378_LIB_TRIGGERED_BUFFER + bool + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for buffered data capture with LTC2378 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 1814fb78dde3..109cd39237c9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -82,6 +82,12 @@ obj-$(CONFIG_LPC18XX_ADC) +=3D lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) +=3D lpc32xx_adc.o obj-$(CONFIG_LTC2309) +=3D ltc2309.o obj-$(CONFIG_LTC2378) +=3D ltc2378.o + +ltc2378_lib-y +=3D ltc2378-lib-core.o +ltc2378_lib-$(CONFIG_LTC2378_LIB_OFFLOAD_BUFFER) +=3D ltc2378-offload-buff= er.o +ltc2378_lib-$(CONFIG_LTC2378_LIB_TRIGGERED_BUFFER) +=3D ltc2378-triggered-= buffer.o +obj-$(CONFIG_LTC2378_LIB) +=3D ltc2378_lib.o + obj-$(CONFIG_LTC2471) +=3D ltc2471.o obj-$(CONFIG_LTC2485) +=3D ltc2485.o obj-$(CONFIG_LTC2496) +=3D ltc2496.o ltc2497-core.o diff --git a/drivers/iio/adc/ltc2378-lib-core.c b/drivers/iio/adc/ltc2378-l= ib-core.c new file mode 100644 index 000000000000..1160f4324d01 --- /dev/null +++ b/drivers/iio/adc/ltc2378-lib-core.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Analog Devices LTC2378 ADC series driver + * + * Copyright (C) 2026 Analog Devices Inc. + * Author: Marcelo Schmitt + */ + +#include +#include + +#include "ltc2378.h" + +int ltc2378_lib_buffer_setup(struct iio_dev *indio_dev, struct ltc2378_sta= te *st) +{ + struct device *dev =3D &st->spi->dev; + int ret; + + ret =3D __ltc2378_set_offload_ops(st); + if (ret =3D=3D -EOPNOTSUPP) + return 0; /* Let device setup complete without buffer support */ + + if (!ret) + ret =3D st->ops->buffer_setup(indio_dev, st); + + if (ret) + return dev_err_probe(dev, ret, "error on SPI offload setup\n"); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(ltc2378_lib_buffer_setup, "IIO_LTC2378"); + +MODULE_AUTHOR("Marcelo Schmitt "); +MODULE_DESCRIPTION("Analog Devices LTC2378 ADC series driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/ltc2378-offload-buffer.c b/drivers/iio/adc/ltc= 2378-offload-buffer.c new file mode 100644 index 000000000000..3e8c7ab64a54 --- /dev/null +++ b/drivers/iio/adc/ltc2378-offload-buffer.c @@ -0,0 +1,305 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2026 Analog Devices, Inc. + * Author: Marcelo Schmitt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ltc2378.h" + +/* + * SPI offload wiring schema + * + * +-------------+ +-------------+ + * | CNV |<-----+--| GPIO | + * | | +--| PWM0 | + * | | | | + * | | +--| PWM1 | + * | | | +-------------+ + * | | +->| TRIGGER | + * | | | | + * | ADC | | SPI | + * | | | controller | + * | | | | + * | SDI |<--------| SDO | + * | SDO |-------->| SDI | + * | SCLK |<--------| SCLK | + * +-------------+ +-------------+ + * + */ +static int ltc2378_update_conversion_rate(struct ltc2378_state *st, int fr= eq_Hz) +{ + struct spi_offload_trigger_config *config =3D &st->offload_trigger_config; + unsigned int min_read_offset, offload_period_ns; + struct pwm_waveform cnv_wf =3D { }; + u64 target =3D LTC2378_TCNV_HIGH_NS; + unsigned int count =3D 0; + u64 offload_offset_ns; + int ret; + + if (freq_Hz =3D=3D 0) + return -EINVAL; + + if (freq_Hz < 1 || freq_Hz > st->info->max_sample_rate_hz) + return -ERANGE; + + /* Configure CNV PWM waveform */ + cnv_wf.period_length_ns =3D DIV_ROUND_CLOSEST(NSEC_PER_SEC, freq_Hz); + + /* + * Ensure CNV high time meets minimum requirement (20ns). The PWM + * hardware may round the duty cycle, so iterate until we get at least + * the minimum required high time. + */ + do { + cnv_wf.duty_length_ns =3D target; + ret =3D pwm_round_waveform_might_sleep(st->cnv_trigger, &cnv_wf); + if (ret) + return ret; + target +=3D 10; /* Increment by PWM duty cycle period */ + } while (count++ < 100 && cnv_wf.duty_length_ns < LTC2378_TCNV_HIGH_NS); + + /* Double check the minimum CNV high time is met */ + if (cnv_wf.duty_length_ns < LTC2378_TCNV_HIGH_NS) + return -EIO; + + /* + * Configure SPI offload PWM trigger. + * The trigger should fire after tBUSYLH + tCONV + tDSDOBUSYL. + * Minimum time needed: TBUSYLH (13ns) + TCONV (part-specific) + TDSDOBUS= YL (5ns) + * + * Use the same period as CNV PWM to avoid timing issues. + * Convert back from period to frequency for the SPI offload API. + */ + offload_period_ns =3D cnv_wf.period_length_ns; + config->periodic.frequency_hz =3D DIV_ROUND_UP(HZ_PER_GHZ, offload_period= _ns); + min_read_offset =3D LTC2378_TBUSYLH_NS + st->info->tconv_ns + LTC2378_TDS= DOBUSYL_NS; + offload_offset_ns =3D min_read_offset; + count =3D 0; + do { + config->periodic.offset_ns =3D offload_offset_ns; + ret =3D spi_offload_trigger_validate(st->offload_trigger, config); + if (ret) + return ret; + offload_offset_ns +=3D 10; + } while (count++ < 100 && config->periodic.offset_ns < min_read_offset); + + st->cnv_wf =3D cnv_wf; + st->cnv_Hz =3D DIV_ROUND_CLOSEST_ULL(HZ_PER_GHZ, cnv_wf.period_length_ns); + + return 0; +} + +static ssize_t sampling_frequency_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ltc2378_state *st =3D iio_priv(dev_to_iio_dev(dev)); + + return sysfs_emit(buf, "%u\n", st->cnv_Hz); +} + +static ssize_t sampling_frequency_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev =3D dev_to_iio_dev(dev); + struct ltc2378_state *st =3D iio_priv(indio_dev); + unsigned int val; + int ret; + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + ret =3D kstrtouint(buf, 10, &val); + if (ret) + return ret; + + ret =3D ltc2378_update_conversion_rate(st, val); + + return ret ?: len; +} + +static ssize_t sampling_frequency_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev =3D dev_to_iio_dev(dev); + struct ltc2378_state *st =3D iio_priv(indio_dev); + + return sysfs_emit(buf, "[%u %u %u]\n", + 1, 1, st->info->max_sample_rate_hz); +} + +static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0); +static IIO_DEVICE_ATTR(sampling_frequency, 0644, + sampling_frequency_show, sampling_frequency_store, 0); + +static const struct iio_dev_attr *ltc2378_offload_buffer_attrs[] =3D { + &iio_dev_attr_sampling_frequency_available, + &iio_dev_attr_sampling_frequency, + NULL +}; + +static int ltc2378_prepare_offload_message(struct device *dev, + struct ltc2378_state *st) +{ + st->offload_xfer.bits_per_word =3D st->info->resolution; + st->offload_xfer.len =3D st->info->resolution > 16 ? 4 : 2; + st->offload_xfer.offload_flags =3D SPI_OFFLOAD_XFER_RX_STREAM; + + /* Initialize message with offload */ + spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1); + st->offload_msg.offload =3D st->offload; + + return devm_spi_optimize_message(dev, st->spi, &st->offload_msg); +} + +static int ltc2378_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + int ret; + + ret =3D pwm_set_waveform_might_sleep(st->cnv_trigger, &st->cnv_wf, false); + if (ret) + return ret; + + ret =3D spi_offload_trigger_enable(st->offload, st->offload_trigger, + &st->offload_trigger_config); + if (ret) + goto out_pwm_disable; + + return 0; + +out_pwm_disable: + pwm_disable(st->cnv_trigger); + return ret; +} + +static int ltc2378_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + pwm_disable(st->cnv_trigger); + + return 0; +} + +static const struct iio_buffer_setup_ops ltc2378_offload_buffer_ops =3D { + .postenable =3D <c2378_offload_buffer_postenable, + .predisable =3D <c2378_offload_buffer_predisable, +}; + +static int ltc2378_spi_offload_setup(struct iio_dev *indio_dev, + struct ltc2378_state *st) +{ + struct device *dev =3D &st->spi->dev; + struct dma_chan *rx_dma; + + indio_dev->setup_ops =3D <c2378_offload_buffer_ops; + + st->offload_trigger =3D devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "failed to get offload trigger\n"); + + st->offload_trigger_config.type =3D SPI_OFFLOAD_TRIGGER_PERIODIC; + + rx_dma =3D devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), "failed to get offload RX DMA= \n"); + + return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN, + ltc2378_offload_buffer_attrs); +} + +static int ltc2378_pwm_get(struct ltc2378_state *st) +{ + struct device *dev =3D &st->spi->dev; + + st->cnv_trigger =3D devm_pwm_get(dev, NULL); + if (IS_ERR(st->cnv_trigger)) + return dev_err_probe(dev, PTR_ERR(st->cnv_trigger), + "failed to get cnv pwm\n"); + + /* + * Disable the PWM connected to CNV in case it was left running by + * something else. + */ + pwm_disable(st->cnv_trigger); + + return 0; +} + +static const struct spi_offload_config ltc2378_offload_config =3D { + .capability_flags =3D SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static int ltc2378_offload_buffer_setup(struct iio_dev *indio_dev, + struct ltc2378_state *st) +{ + struct spi_device *spi =3D st->spi; + struct device *dev =3D &spi->dev; + int ret; + + st->offload =3D devm_spi_offload_get(dev, spi, <c2378_offload_config); + ret =3D PTR_ERR_OR_ZERO(st->offload); + if (ret) + return ret; + + ret =3D ltc2378_spi_offload_setup(indio_dev, st); + if (ret) + return dev_err_probe(dev, ret, + "failed to setup SPI offload\n"); + + ret =3D ltc2378_pwm_get(st); + if (ret) + return ret; + + /* + * Start with a slower sampling rate so there is some room for + * adjusting the sampling frequency without hitting the maximum + * conversion rate. + */ + ret =3D ltc2378_update_conversion_rate(st, st->info->max_sample_rate_hz >= > 4); + if (ret) + return dev_err_probe(dev, ret, "failed to sampling frequency\n"); + + ret =3D ltc2378_prepare_offload_message(&spi->dev, st); + if (ret) + return dev_err_probe(dev, ret, "failed to optimize SPI message\n"); + + return 0; +} + +static const struct ltc2378_ops ltc2378_offload_ops =3D { + .buffer_setup =3D ltc2378_offload_buffer_setup, +}; + +int ltc2378_set_offload_ops(struct ltc2378_state *st) +{ + st->ops =3D <c2378_offload_ops; + return 0; +} +EXPORT_SYMBOL_NS_GPL(ltc2378_set_offload_ops, "IIO_LTC2378"); + +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); diff --git a/drivers/iio/adc/ltc2378.c b/drivers/iio/adc/ltc2378.c index 88582bdcd6a6..bf17b202230b 100644 --- a/drivers/iio/adc/ltc2378.c +++ b/drivers/iio/adc/ltc2378.c @@ -17,6 +17,7 @@ #include #include #include +#include =20 #include #include @@ -26,120 +27,160 @@ static const struct ltc2378_chip_info ltc2338_18_chip_info =3D { .name =3D "ltc2338-18", .resolution =3D 18, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 527, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2364_16_chip_info =3D { .name =3D "ltc2364-16", .resolution =3D 16, + .max_sample_rate_hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2364_18_chip_info =3D { .name =3D "ltc2364-18", .resolution =3D 18, + .max_sample_rate_hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2367_16_chip_info =3D { .name =3D "ltc2367-16", .resolution =3D 16, + .max_sample_rate_hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2367_18_chip_info =3D { .name =3D "ltc2367-18", .resolution =3D 18, + .max_sample_rate_hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2368_16_chip_info =3D { .name =3D "ltc2368-16", .resolution =3D 16, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 527, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2368_18_chip_info =3D { .name =3D "ltc2368-18", .resolution =3D 18, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 527, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2369_18_chip_info =3D { .name =3D "ltc2369-18", .resolution =3D 18, + .max_sample_rate_hz =3D 1600 * HZ_PER_KHZ, + .tconv_ns =3D 412, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2370_16_chip_info =3D { .name =3D "ltc2370-16", .resolution =3D 16, + .max_sample_rate_hz =3D 2 * HZ_PER_MHZ, + .tconv_ns =3D 322, .bipolar =3D false, }; =20 static const struct ltc2378_chip_info ltc2376_16_chip_info =3D { .name =3D "ltc2376-16", .resolution =3D 16, + .max_sample_rate_hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2376_18_chip_info =3D { .name =3D "ltc2376-18", .resolution =3D 18, + .max_sample_rate_hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2376_20_chip_info =3D { .name =3D "ltc2376-20", .resolution =3D 20, + .max_sample_rate_hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2377_16_chip_info =3D { .name =3D "ltc2377-16", .resolution =3D 16, + .max_sample_rate_hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2377_18_chip_info =3D { .name =3D "ltc2377-18", .resolution =3D 18, + .max_sample_rate_hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2377_20_chip_info =3D { .name =3D "ltc2377-20", .resolution =3D 20, + .max_sample_rate_hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2378_16_chip_info =3D { .name =3D "ltc2378-16", .resolution =3D 16, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 527, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2378_18_chip_info =3D { .name =3D "ltc2378-18", .resolution =3D 18, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 527, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2378_20_chip_info =3D { .name =3D "ltc2378-20", .resolution =3D 20, + .max_sample_rate_hz =3D HZ_PER_MHZ, + .tconv_ns =3D 675, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2379_18_chip_info =3D { .name =3D "ltc2379-18", .resolution =3D 18, + .max_sample_rate_hz =3D 1600 * HZ_PER_KHZ, + .tconv_ns =3D 412, .bipolar =3D true, }; =20 static const struct ltc2378_chip_info ltc2380_16_chip_info =3D { .name =3D "ltc2380-16", .resolution =3D 16, + .max_sample_rate_hz =3D 2 * HZ_PER_MHZ, + .tconv_ns =3D 322, .bipolar =3D true, }; =20 @@ -266,6 +307,10 @@ static int ltc2378_probe(struct spi_device *spi) st->xfer.len =3D st->info->resolution > 16 ? 4 : 2; st->xfer.bits_per_word =3D st->info->resolution; =20 + ret =3D ltc2378_lib_buffer_setup(indio_dev, st); + if (ret) + return ret; + indio_dev->channels =3D st->chans; indio_dev->num_channels =3D st->num_iio_chans; =20 @@ -336,3 +381,4 @@ MODULE_AUTHOR("Ioan-Daniel Pop "); MODULE_AUTHOR("Marcelo Schmitt "); MODULE_DESCRIPTION("Analog Devices LTC2378 ADC series driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_LTC2378"); diff --git a/drivers/iio/adc/ltc2378.h b/drivers/iio/adc/ltc2378.h index a3a69351de6c..f6e10f9a83e0 100644 --- a/drivers/iio/adc/ltc2378.h +++ b/drivers/iio/adc/ltc2378.h @@ -8,10 +8,14 @@ #ifndef __DRIVERS_IIO_ADC_LTC2378_H__ #define __DRIVERS_IIO_ADC_LTC2378_H__ =20 +#include #include #include #include +#include #include +#include +#include #include #include =20 @@ -19,12 +23,24 @@ #define LTC2378_TBUSYLH_NS 13 #define LTC2378_TCNV_HIGH_NS 20 =20 +struct ltc2378_state; + struct ltc2378_chip_info { const char *name; int resolution; + unsigned int max_sample_rate_hz; + unsigned int tconv_ns; bool bipolar; }; =20 +/** + * struct ltc2378_ops: Setup specific procedures for ltc2378 devices. + * @ltc2378_buffer_setup: Custom buffer setup implementation. + */ +struct ltc2378_ops { + int (*buffer_setup)(struct iio_dev *indio_dev, struct ltc2378_state *st); +}; + struct ltc2378_state { const struct ltc2378_chip_info *info; struct gpio_desc *cnv_gpio; @@ -33,6 +49,15 @@ struct ltc2378_state { unsigned int num_iio_chans; struct iio_chan_spec chans[2]; /* 1 physical chan + 1 timestamp chan */ int ref_uV; + const struct ltc2378_ops *ops; + unsigned int cnv_Hz; + struct pwm_waveform cnv_wf; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct spi_message offload_msg; + struct spi_transfer offload_xfer; + struct spi_offload_trigger_config offload_trigger_config; + struct pwm_device *cnv_trigger; =20 /* * DMA (thus cache coherency maintenance) requires the @@ -60,4 +85,21 @@ static inline int ltc2378_convert_and_acquire(struct ltc= 2378_state *st) return ret; } =20 +int ltc2378_lib_buffer_setup(struct iio_dev *indio_dev, struct ltc2378_sta= te *st); + +#define __ltc2378_set_offload_ops(st) ltc2378_set_offload_ops((st)) + +#ifdef CONFIG_LTC2378_LIB_OFFLOAD_BUFFER + +int ltc2378_set_offload_ops(struct ltc2378_state *st); + +#else + +static inline int ltc2378_set_offload_ops(struct ltc2378_state *st) +{ + return -EOPNOTSUPP; +} + +#endif /* CONFIG_LTC2378_LIB_OFFLOAD_BUFFER */ + #endif /* __DRIVERS_IIO_ADC_LTC2378_H__ */ --=20 2.53.0 From nobody Thu Jun 18 19:22:45 2026 Received: from mx0b-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (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 D36E22E7363; Wed, 17 Jun 2026 02:05:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661905; cv=none; b=Rc7HNbV6TL6L+V/qk23T1CtvzCBy5CnLNyLw4FKRTFB+hF3vfkOt/0mcO7Pof1LUED0ZpvD/fSxFMblNEgB+P1UiWezdywL3WFfBn3HMs2aApQfmkuptKKpHqOzTldc3Q67iZuFllH9VFctn9T7jSdY9m/0ZJwTFUnVCms7I9Og= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781661905; c=relaxed/simple; bh=QxSMfBGp2rgFGnkix5Cv05pJimlb250xpzuaD7aPBNY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dxXGz7qhT1cOTtlUI/j5+w47HuNIgIIOCtUkYsZgPOCvnoMaCWRHfsF0jfZ1tjGScYxOdAaf/KeFmGjEGZ+hnWoY79XB4X7jlwofSuGVD5LqZQPfLVsGnaAGusCLLKGmIUNmDmh5UyAvp7NKhNUoqS+LA81m1oCVuHZ4USPE5uc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=erBBQdq1; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="erBBQdq1" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 65GLWjKV878652; Tue, 16 Jun 2026 22:05:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=GiPeQ O+FPXHsho8SrYHrVt3dhMAUnZ3Rs7kiBMNwkf4=; b=erBBQdq11vUoEwT4IqF4i BCCqqkoBfo1hwMiqUuhK4sZwMYTtDXyIsRNnvC9ZT3CnbHhpRagK0SwRBlIj4N9r e0y/EIrjT6EvU9UPuQbJXl9EvqVczzQ02y90J0XZ6U7FAhtEu+14PPsXfuSHEvPj lFolyj4AzO6+AZB9ELGss1fg4X4Zy+v2sLp77YRh5BaPiZFZhZ3Tq/Is//yRxeew doYgIEL4HkctXZBzVoyOBok37PjSBSt0PmepeIma2ezajOAUAvGDm5epVyUdfdTa hl/Tcfrvxa9TOl4cxhKtbQ/liUgItIsUL1bsdi/8Nimx/pkRXPkDO9fVII2p8QME A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4euegdrsbg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 16 Jun 2026 22:05:00 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 65H24xDW014166 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 16 Jun 2026 22:04:59 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:04:59 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Tue, 16 Jun 2026 22:04:58 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.1748.37 via Frontend Transport; Tue, 16 Jun 2026 22:04:58 -0400 Received: from work.maxim-ic.internal ([10.66.6.192]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 65H24kK5006756; Tue, 16 Jun 2026 22:04:48 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [PATCH v3 5/5] iio: adc: ltc2378: Enable triggered buffer data capture Date: Tue, 16 Jun 2026 23:04:40 -0300 Message-ID: <22248e8ba646fbe8edfc87e2b9be527632d5b48c.1781661028.git.marcelo.schmitt@analog.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfXwWPmmVK0xAOe j1KFYVdZTWtwfEpD14VWj8sDN8ZfxnfFH7YNOThly0q1Eavy01sA1omta4m2qa+vKhgCs0UaSgA 7jxur3++AuvIb1df25qRBLZlNINxHd0kC7jUWp9yPo6QjpUl30VYjUNwVTP5EFzQ6uE+sunBiX2 iARyl9OBkaR4vVpi5FdtTeyoi/NByGwr8rV5RbGY7uGC1wodHj5mKSakvXrcPaJt3NQsveSVOj3 9/vTGnnfcVrLX2itC4AkJyMuAs3l0fFrKjkGF2YELnZNev+MF+l/RrM+zEgeOH8nmfSpD4bE9jJ o8T4HdWHMqhyqWvntIM/8YnJdFbqa1QQwx1GCZ95YnAed6BpdTA5dtSCbM0X6OBm3WO/Ku7DM9q XopGZkV2Iin1YJQzfZFuQ825mySgE9x4vdfQ11Bcg9gMc1SLzrllYqMsGuQzH16eIfBry8RGWFx HOve8unU6O7LUpT9yNw== X-Proofpoint-Spam-Info: AW1haW4tMjYwNjE3MDAxNyBTYWx0ZWRfX1jzSWjs3r8iV dmDYfTUDqfP7mhuPvS72jFmvgEKAyxHfQrrbUmsPOLWqsg0JmnAFawK1h64nLlkeFPCz4ka2pRW cg71bFF+jmNcV9F532e98nwXLkT0t1+12L5rPevsv7ZXCBaH2HWV X-Authority-Analysis: v=2.4 cv=BbvoFLt2 c=1 sm=1 tr=0 ts=6a3200cc cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=FelO9ux0wxsA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=N--XFCr6TIEc_64PeIT2:22 a=gAnH3GRIAAAA:8 a=yG7T9kLISj94RV_eT-gA:9 X-Proofpoint-GUID: VvkxPUoGS7WRpPhZAMMenyX5LKIi9sCT X-Proofpoint-ORIG-GUID: VvkxPUoGS7WRpPhZAMMenyX5LKIi9sCT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.125,FMLib:17.12.100.49 definitions=2026-06-16_05,2026-06-16_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 malwarescore=0 suspectscore=0 impostorscore=0 adultscore=0 priorityscore=1501 lowpriorityscore=0 spamscore=0 phishscore=0 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2606170017 Content-Type: text/plain; charset="utf-8" Enable users to run triggered data captures with LTC2378 and similar ADCs. Signed-off-by: Marcelo Schmitt --- Change log v2 -> v3: - Extracted from main driver file into a separate buffer-specific containme= nt. drivers/iio/adc/ltc2378-lib-core.c | 17 +++++++- drivers/iio/adc/ltc2378-triggered-buffer.c | 49 ++++++++++++++++++++++ drivers/iio/adc/ltc2378.h | 15 +++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 drivers/iio/adc/ltc2378-triggered-buffer.c diff --git a/drivers/iio/adc/ltc2378-lib-core.c b/drivers/iio/adc/ltc2378-l= ib-core.c index 1160f4324d01..ec83e9f2ae81 100644 --- a/drivers/iio/adc/ltc2378-lib-core.c +++ b/drivers/iio/adc/ltc2378-lib-core.c @@ -18,7 +18,7 @@ int ltc2378_lib_buffer_setup(struct iio_dev *indio_dev, s= truct ltc2378_state *st =20 ret =3D __ltc2378_set_offload_ops(st); if (ret =3D=3D -EOPNOTSUPP) - return 0; /* Let device setup complete without buffer support */ + goto trigger_buf_setup; =20 if (!ret) ret =3D st->ops->buffer_setup(indio_dev, st); @@ -27,6 +27,21 @@ int ltc2378_lib_buffer_setup(struct iio_dev *indio_dev, = struct ltc2378_state *st return dev_err_probe(dev, ret, "error on SPI offload setup\n"); =20 return 0; + +trigger_buf_setup: + ret =3D __ltc2378_set_triggered_buf_ops(st); + if (ret =3D=3D -EOPNOTSUPP) + return 0; /* Let device setup complete without buffer support */ + + if (!ret) + ret =3D st->ops->buffer_setup(indio_dev, st); + + if (ret) + return dev_err_probe(dev, ret, "error on buffer setup\n"); + + st->chans[st->num_iio_chans++] =3D IIO_CHAN_SOFT_TIMESTAMP(1); + + return 0; } EXPORT_SYMBOL_NS_GPL(ltc2378_lib_buffer_setup, "IIO_LTC2378"); =20 diff --git a/drivers/iio/adc/ltc2378-triggered-buffer.c b/drivers/iio/adc/l= tc2378-triggered-buffer.c new file mode 100644 index 000000000000..d1d788fb5cb4 --- /dev/null +++ b/drivers/iio/adc/ltc2378-triggered-buffer.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2026 Analog Devices, Inc. + * Author: Marcelo Schmitt + */ + +#include +#include +#include + +#include + +static irqreturn_t ltc2378_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf =3D p; + struct iio_dev *indio_dev =3D pf->indio_dev; + struct ltc2378_state *st =3D iio_priv(indio_dev); + int ret; + + ret =3D ltc2378_convert_and_acquire(st); + if (ret < 0) + goto err_out; + + iio_push_to_buffers_with_ts(indio_dev, &st->scan, sizeof(st->scan), + pf->timestamp); + +err_out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int ltc2378_triggered_buffer_setup(struct iio_dev *indio_dev, struc= t ltc2378_state *st) +{ + return devm_iio_triggered_buffer_setup(&st->spi->dev, indio_dev, + &iio_pollfunc_store_time, + <c2378_trigger_handler, + NULL); +} + +static const struct ltc2378_ops ltc2378_triggered_buf_ops =3D { + .buffer_setup =3D ltc2378_triggered_buffer_setup, +}; + +int ltc2378_set_triggered_buf_ops(struct ltc2378_state *st) +{ + st->ops =3D <c2378_triggered_buf_ops; + return 0; +} +EXPORT_SYMBOL_NS_GPL(ltc2378_set_triggered_buf_ops, "IIO_LTC2378"); diff --git a/drivers/iio/adc/ltc2378.h b/drivers/iio/adc/ltc2378.h index f6e10f9a83e0..4241b1e79ac0 100644 --- a/drivers/iio/adc/ltc2378.h +++ b/drivers/iio/adc/ltc2378.h @@ -89,6 +89,8 @@ int ltc2378_lib_buffer_setup(struct iio_dev *indio_dev, s= truct ltc2378_state *st =20 #define __ltc2378_set_offload_ops(st) ltc2378_set_offload_ops((st)) =20 +#define __ltc2378_set_triggered_buf_ops(st) ltc2378_set_triggered_buf_ops(= (st)) + #ifdef CONFIG_LTC2378_LIB_OFFLOAD_BUFFER =20 int ltc2378_set_offload_ops(struct ltc2378_state *st); @@ -102,4 +104,17 @@ static inline int ltc2378_set_offload_ops(struct ltc23= 78_state *st) =20 #endif /* CONFIG_LTC2378_LIB_OFFLOAD_BUFFER */ =20 +#ifdef CONFIG_LTC2378_LIB_TRIGGERED_BUFFER + +int ltc2378_set_triggered_buf_ops(struct ltc2378_state *st); + +#else + +static inline int ltc2378_set_triggered_buf_ops(struct ltc2378_state *st) +{ + return -EOPNOTSUPP; +} + +#endif /* CONFIG_LTC2378_LIB_TRIGGERED_BUFFER */ + #endif /* __DRIVERS_IIO_ADC_LTC2378_H__ */ --=20 2.53.0