From nobody Fri Jul 24 04:44:02 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 57F553932C3; Thu, 23 Jul 2026 19:52:36 +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=1784836359; cv=none; b=uKfp4QewhXNRBReNHqvkavl/L8z+EI6U8He0PDBT/+4E9xvt305cQrN+/+2IVVQMAisa2eyuGfpuuOZetVj5GZfy1RXQ1/U2d4txig6RgNHFqoZlvfQHIyRFgEAJ7igyvtNYJ24NP4Qw1Itbdye8NREC4KTR9QHQmgjB+PufySE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784836359; c=relaxed/simple; bh=FlT2vaL7SBqliJ1L9MSGdhf3AWig/m7nAvMJuusjOb0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tWnAFtn3ixAdn4rOvTdj3jtT/ePEMdNAVZuMlXoEpZJseykirhh1QZx/9fdgmBETKtGcpz001qH2zh8F945zs6s7347PFVrgHWpatN6QR+4SX5xgdMYmhhCirG+IO7+0+mx02T1zuNA0ITZrJMlHskQ9FOh4jR9w04XpCMEVPsI= 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=vlV761lD; 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="vlV761lD" 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 66NImK2W2486576; Thu, 23 Jul 2026 15:52:31 -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=lub1L +bPFv0E47taXdJiupT7F0fyP/C0wAsg2VAYTmI=; b=vlV761lDzos2DXwL5VqJA 7QhQfAyXphTqdSr1PL2K4Qogak9BG6KaGp/KeUYvAgQjDrDMzMvGHa6JV7XM9deC ZP2f7UGjFI500GfshY+m4KpbMXyZfXASIXYhuS9hg3zw8fJL/0AhQv/w7R6vxOcK yyYBHx2h8bKnj/VVU90iLbscY5gkTODYpFqz+ZJghUc/LzQ8UHS2Zx3JLNnOrj8y 13+4DCdIm1H9Y2HGCVtcvEI07KzaSQOT/59MO1Jwlp5yPymCdHdijuolAAG1dakv e8YoFVB3BWu77TvVpKWX8ANk4vZEXHMxsN8zRQjMLEyFpGvOMc95fgCqTzxspaZe w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4fkrgnr61w-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 23 Jul 2026 15:52:31 -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 66NJqUQX049470 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 15:52:30 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) 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; Thu, 23 Jul 2026 15:52: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; Thu, 23 Jul 2026 15:52: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 66NJqEuC030717; Thu, 23 Jul 2026 15:52:17 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , , Conor Dooley Subject: [PATCH v8 1/5] dt-bindings: iio: adc: Add ltc2378 Date: Thu, 23 Jul 2026 16:52:09 -0300 Message-ID: <090b3b5e9ca1c44e5ccd06a710ee71c569c33a0c.1784835663.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: CPS3ZrEQELIhdoWW4XvetkWAESkqkXvR X-Proofpoint-GUID: CPS3ZrEQELIhdoWW4XvetkWAESkqkXvR X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX9a/BVSm61IWR U4jUFMryJ/cRxg8FHZPsIvX/CaoPVkX6PNRkCQQc5RiatIxDcAGjeyFhc/TeC4tIDwuRv3DDzZx SpDv1kkzWP5yRpK6hsdr+a1MAsKgWE/qSH23lx3hLUrjeHveCPyS8xqJ+/Z8ScBlruCv7nfVJFR plTZ4X4nEOpkJdcgi9bG1CdCQdF5ZfqUZO80pJzmJoF9brVT9lcZlrsnfyrjK8cKXfzpRG8PopQ mNf0to0j+nsQN6r2DYranaJVjtDvi1stYGbuzZyOWljg0hXKoLTbtj6/jUIzX4FtHuEQUrmLH92 l/FA1rkMmzReRhI3a/PbZee2PuXtMDkBII+WOXXfwJnQMUqU3UdomGvDB0GWuRopUjOpRyGJLT8 2Rw7VnvAvp8tBs90JNoxjTSLpmy2rHIw4sYhp2m39M+2HFVdq/xxrbcirzvDx/YdFWWtCowH/JH 00YcnFFkITPqAaMTIuQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX4XCjsdI0+DHy 9FDK9ORNtaJparsb9Jo10oult/u7WXmVVkBAmMhitypeTTIX31Rh0m1GMlpSKYaCUL3P2BS3AUm ikwvU18zNcYfujdEe6rklhRc6pYzZR5NqM5eSlMYAyfYM1cYJXbb X-Authority-Analysis: v=2.4 cv=CfM4Irrl c=1 sm=1 tr=0 ts=6a6270ff cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=RAioF0-LDSMA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=N--XFCr6TIEc_64PeIT2:22 a=gEfo2CItAAAA:8 a=gAnH3GRIAAAA:8 a=IpJZQVW2AAAA:8 a=XYAwZIGsAAAA:8 a=VwQbUJbxAAAA:8 a=zHdOwAC9n8DEQaShn0QA:9 a=sptkURWiP4Gy88Gu7hUp:22 a=IawgGOuG5U0WyFbmm1f5:22 a=E8ToXWR_bxluHZ7gmE-Z:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-23_06,2026-07-22_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 malwarescore=0 spamscore=0 lowpriorityscore=0 adultscore=0 suspectscore=0 clxscore=1015 phishscore=0 bulkscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607230193 Content-Type: text/plain; charset="utf-8" Document how to describe LTC2378-20 and similar ADCs in device tree. Reviewed-by: David Lechner Reviewed-by: Conor Dooley Signed-off-by: Marcelo Schmitt --- No changes in device tree doc since v6. .../bindings/iio/adc/adi,ltc2378.yaml | 170 ++++++++++++++++++ MAINTAINERS | 7 + 2 files changed, 177 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..33de1dc4c256 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml @@ -0,0 +1,170 @@ +# 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,ltc2376-16 + - adi,ltc2376-18 + - adi,ltc2376-20 + + # 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,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: + Voltage reference input that determines the scale of ADC conversions. + + refin-supply: + description: + Alternative voltage reference input. + + cnv-gpios: + description: + When provided, this property indicates the GPIO that is connected to= the + CNV pin. + maxItems: 1 + + pwms: + description: PWM signal 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 + +allOf: + # Except for LTC2338, all designs require a voltage reference input + - if: + properties: + compatible: + not: + contains: + enum: + - adi,ltc2338-18 + then: + required: + - ref-supply + properties: + refin-supply: false + else: + properties: + ref-supply: false + +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 2b1ec46c5919..f0ae26699c99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15343,6 +15343,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 Fri Jul 24 04:44:02 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 C95C129994B; Thu, 23 Jul 2026 19:53:00 +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=1784836382; cv=none; b=b1ZAeXCM2XUf2rWgSZIfsml/8EtHYuDW1IoQkz+fO6BEGTeIeIM2gulrEBjXIG13TVeRLwkBdSKjyzLkjVI/UzUTrWR9Cj6lt8GuuV1YJ5QuG04cIJh9eH6HyTrztDhKAmab+qXSnuev6PS/DB7+9QF3ntGpz8rvaCAcwPlMw5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784836382; c=relaxed/simple; bh=JPPOghq6gpTWfgySId2miuPtfAsENfFx1uun7MY8cyo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=u8MSMdQO4ALaka9nlsFk7jfC9QGok4liMcgGjTvgDiLKQyHPlCxYYnftY7irq6YFW9cDHJvmDQW2Ep2ONqcfXvrdseNWK4vWou6Vyz31LCzDEXn43MQX0yXJKQexkZBNzaRyqid9EUmWP/UM7fimX0SetlRgBOEeky62O8MBAFc= 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=u+ZEqpZy; 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="u+ZEqpZy" 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 66NImkdR2938259; Thu, 23 Jul 2026 15:52:54 -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=JfgHl /jthsj9CnABR30LsCGuxU8Z0HmtgktlFdqLKn4=; b=u+ZEqpZy9SlY5a3WZzNwy klSA/KKVH79pAHzW20UDkAFVBGAX13L06LoLchtNJPSlxrRnvi1Aibtn0ikElQmN 8jzhEt1UFhkOTZPdJi2QGiir/OuD/zSClRlqsxJ+6vyhTZxkWqfSlUnPgbB3rMbh /InmlBhtPNOw/gmGEhlFvM2ja+M4TsDY545cgjP9OTw6T/FP+nD7sP23tiAbV3Yn dmfgBgs4oSoY5moOILgC85HcdeB1N6qZHinY4JLbEovaBooIRnl1s0+6Fc766y4J Ji9ig2mo+AEWqy9ojLR5DvVMqg/s3DntSHR5lGIZtZQ1FigHNtNYRLubHd6C375R A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4fj6v4vh2r-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 23 Jul 2026 15:52:54 -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 66NJqreu049520 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 15:52:53 -0400 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) 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; Thu, 23 Jul 2026 15:52:53 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Thu, 23 Jul 2026 15:52:53 -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; Thu, 23 Jul 2026 15:52:53 -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 66NJqZ2t030722; Thu, 23 Jul 2026 15:52:37 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , , Andy Shevchenko Subject: [PATCH v8 2/5] iio: adc: ltc2378: Add support for LTC2378-20 and similar ADCs Date: Thu, 23 Jul 2026 16:52:29 -0300 Message-ID: <1c12e37f273d4f99916768e1a9b44dbae30f9d0c.1784835663.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=DYknbPtW c=1 sm=1 tr=0 ts=6a627116 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=RAioF0-LDSMA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=uXIjobp8t2wMuQ0fPvqm:22 a=gAnH3GRIAAAA:8 a=QyXUC8HyAAAA:8 a=IpJZQVW2AAAA:8 a=VwQbUJbxAAAA:8 a=ZZGAMBLAlkmGxc5ICUcA:9 a=IawgGOuG5U0WyFbmm1f5:22 X-Proofpoint-ORIG-GUID: XqSIFQbRli_6CRMTVG1dzgbsC-vGdLAL X-Proofpoint-Spam-Info: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfXxBa8eqPyIGFF EPio54HcSCBdioFLxH8E5kIpUSlD+0W/KVRMYgArbsbK+K535CYh0W8v82SHR4zomrvRJnucH1M XxEdV0pF41gD5V+sHgxqRkB5CSrjispkfreRcXXaBEy4HGvoLYyF X-Proofpoint-GUID: XqSIFQbRli_6CRMTVG1dzgbsC-vGdLAL X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX3ijXlgeZm/Ga OvEbe8DLUZiMUf7Cor98A21FZ7maVarXewgP/A0s6tgKBzkK34sMVn/1YtXf3Cs5puFVM9YC3dS RBKzjKvPfmPvJ1ZjRJHamRhEiBvQrcCG6Bh5s4d3MH3zAc7wmL1ORM15ffFWWbQYS/oTHtQozvh O8vqmvPaAc+a4CFW3Htyemi5c5vA8v8ITAymkoGM2jngNXkUkYeBLpvIeK0CeW6IH/scBvHUgyg RDSh/jJOAgeOq3aUHVrN6B6bhJMaUU3TKRXD4D9nFugsSTuINi7IdqlFvab1GOCPakqM9bhBfJc Vi9ES9bRHG/tkzPEveXdf+WtQwG4otw/xoQifeSnTm9VUVGcYmPNxqPy4MucXN2FnVQO7VGkB25 peP6OyTWcM8lwJRUO3N2d4yrGu1RBzz/jO/KyCyrPk8Ri3YqcEdAjUydVQED7byjpd+7neG0ay4 MjDG842jf2YaXL2JxVg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-23_06,2026-07-22_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 clxscore=1011 lowpriorityscore=0 adultscore=0 priorityscore=1501 bulkscore=0 spamscore=0 malwarescore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607230193 Content-Type: text/plain; charset="utf-8" Support for LTC2378-20 and similar analog-to-digital converters. Reviewed-by: Andy Shevchenko Reviewed-by: David Lechner Signed-off-by: Marcelo Schmitt --- Change log v7 -> v8: - Updated channel macros to make up indexed IIO channels. - Simplified if/else to consecutive if statements on ltc2378_refin_setup(). MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 12 ++ drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ltc2378.c | 421 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 435 insertions(+) create mode 100644 drivers/iio/adc/ltc2378.c diff --git a/MAINTAINERS b/MAINTAINERS index f0ae26699c99..25821b771692 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15349,6 +15349,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.c =20 LTC2664 IIO DAC DRIVER M: Michael Hennerich diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d1b198cb8a80..220c6739a8f2 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -943,6 +943,18 @@ 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 REGULATOR || COMPILE_TEST + 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 0f90b75577ff..6058a8be6ccd 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..107388f87062 --- /dev/null +++ b/drivers/iio/adc/ltc2378.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Analog Devices LTC2378 ADC series driver + * + * Copyright (C) 2026 Analog Devices Inc. + * Author: Marcelo Schmitt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LTC2378_MAX_DATA_WAIT_US 4 /* max(TBUSYLH + TCONV + TDSDOBUSYL) */ + +#define LTC2378_CHANNEL(_sign, _real_bits, _storage_bits) \ +{ \ + .type =3D IIO_VOLTAGE, \ + .indexed =3D 1, \ + .differential =3D _sign, \ + .channel =3D 0, \ + .channel2 =3D _sign ? 1 : 0, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index =3D 0, \ + .scan_type =3D { \ + .format =3D _sign ? IIO_SCAN_FORMAT_SIGNED_INT : \ + IIO_SCAN_FORMAT_UNSIGNED_INT, \ + .realbits =3D _real_bits, \ + .storagebits =3D _storage_bits, \ + .shift =3D _storage_bits - _real_bits, \ + .endianness =3D IIO_BE, \ + }, \ +} + +#define LTC2378_DIFF_CHANNEL(_real_bits) \ + LTC2378_CHANNEL(1, _real_bits, (((_real_bits) > 16) ? 32 : 16)) + +#define LTC2378_PSEUDO_DIFF_CHANNEL(_real_bits) \ + LTC2378_CHANNEL(0, _real_bits, (((_real_bits) > 16) ? 32 : 16)) + +struct ltc2378_chip_info { + const char *name; + unsigned int internal_ref_uV; + struct iio_chan_spec chan; +}; + +struct ltc2378_state { + const struct ltc2378_chip_info *info; + struct gpio_desc *cnv_gpio; + struct spi_device *spi; + struct mutex lock; /* Protect data acquisition cycle */ + int ref_uV; + struct spi_transfer xfer; + + /* + * DMA (thus cache coherency maintenance) requires the transfer buffers + * to live in their own cache lines. + */ + struct { + union { + __be16 sample_buf16_be; + __be32 sample_buf32_be; + u16 sample_buf16; + u32 sample_buf32; + } data; + aligned_s64 timestamp; + } scan __aligned(IIO_DMA_MINALIGN); +}; + +static const struct ltc2378_chip_info ltc2338_18_chip_info =3D { + .name =3D "ltc2338-18", + .internal_ref_uV =3D 2048000, + .chan =3D LTC2378_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2364_16_chip_info =3D { + .name =3D "ltc2364-16", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2364_18_chip_info =3D { + .name =3D "ltc2364-18", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2367_16_chip_info =3D { + .name =3D "ltc2367-16", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2367_18_chip_info =3D { + .name =3D "ltc2367-18", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2368_16_chip_info =3D { + .name =3D "ltc2368-16", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2368_18_chip_info =3D { + .name =3D "ltc2368-18", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2369_18_chip_info =3D { + .name =3D "ltc2369-18", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2370_16_chip_info =3D { + .name =3D "ltc2370-16", + .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2376_16_chip_info =3D { + .name =3D "ltc2376-16", + .chan =3D LTC2378_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2376_18_chip_info =3D { + .name =3D "ltc2376-18", + .chan =3D LTC2378_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2376_20_chip_info =3D { + .name =3D "ltc2376-20", + .chan =3D LTC2378_DIFF_CHANNEL(20), +}; + +static const struct ltc2378_chip_info ltc2377_16_chip_info =3D { + .name =3D "ltc2377-16", + .chan =3D LTC2378_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2377_18_chip_info =3D { + .name =3D "ltc2377-18", + .chan =3D LTC2378_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2377_20_chip_info =3D { + .name =3D "ltc2377-20", + .chan =3D LTC2378_DIFF_CHANNEL(20), +}; + +static const struct ltc2378_chip_info ltc2378_16_chip_info =3D { + .name =3D "ltc2378-16", + .chan =3D LTC2378_DIFF_CHANNEL(16), +}; + +static const struct ltc2378_chip_info ltc2378_18_chip_info =3D { + .name =3D "ltc2378-18", + .chan =3D LTC2378_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2378_20_chip_info =3D { + .name =3D "ltc2378-20", + .chan =3D LTC2378_DIFF_CHANNEL(20), +}; + +static const struct ltc2378_chip_info ltc2379_18_chip_info =3D { + .name =3D "ltc2379-18", + .chan =3D LTC2378_DIFF_CHANNEL(18), +}; + +static const struct ltc2378_chip_info ltc2380_16_chip_info =3D { + .name =3D "ltc2380-16", + .chan =3D LTC2378_DIFF_CHANNEL(16), +}; + +static 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(LTC2378_MAX_DATA_WAIT_US); + ret =3D spi_sync_transfer(st->spi, &st->xfer, 1); + gpiod_set_value_cansleep(st->cnv_gpio, 0); + + return ret; +} + +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; + + guard(mutex)(&st->lock); + ret =3D ltc2378_convert_and_acquire(st); + if (ret) + return ret; + + if (chan->scan_type.endianness =3D=3D IIO_BE) { + if (chan->scan_type.realbits > 16) + sample =3D be32_to_cpu(st->scan.data.sample_buf32_be); + else + sample =3D be16_to_cpu(st->scan.data.sample_buf16_be); + } else { /* IIO_CPU */ + if (chan->scan_type.realbits > 16) + sample =3D st->scan.data.sample_buf32; + else + sample =3D st->scan.data.sample_buf16; + } + + sample >>=3D chan->scan_type.shift; + + 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 mask) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + int ret; + + switch (mask) { + 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 (chan->scan_type.format =3D=3D IIO_SCAN_FORMAT_SIGNED_INT) + *val2 =3D chan->scan_type.realbits - 1; + else + *val2 =3D chan->scan_type.realbits; + + 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_refin_setup(struct device *dev, struct ltc2378_state *s= t) +{ + int ret; + + /* + * The internal reference buffer amplifies both the internal reference + * and REFIN by a factor of 2. + */ + ret =3D devm_regulator_get_enable_read_voltage(dev, "refin"); + if (ret =3D=3D -ENODEV) { /* refin is optional */ + st->ref_uV =3D st->info->internal_ref_uV * 2; + return 0; + } + + if (ret < 0) + return dev_err_probe(dev, ret, "failed to read refin regulator\n"); + + st->ref_uV =3D ret * 2; + + return 0; +} + +static int ltc2378_ref_setup(struct device *dev, struct ltc2378_state *st) +{ + int ret; + + 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; + + return 0; +} + +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_mutex_init(dev, &st->lock); + if (ret) + return ret; + + st->info =3D spi_get_device_match_data(spi); + if (!st->info) + return -EINVAL; + + if (st->info->internal_ref_uV) + ret =3D ltc2378_refin_setup(dev, st); + else + ret =3D ltc2378_ref_setup(dev, st); + if (ret) + return ret; + + 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"); + + indio_dev->channels =3D &st->info->chan; + indio_dev->num_channels =3D 1; + + st->xfer.rx_buf =3D &st->scan.data; + st->xfer.len =3D spi_bpw_to_bytes(indio_dev->channels[0].scan_type.realbi= ts); + + 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("Marcelo Schmitt "); +MODULE_DESCRIPTION("Analog Devices LTC2378 ADC series driver"); +MODULE_LICENSE("GPL"); --=20 2.53.0 From nobody Fri Jul 24 04:44:02 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 228B5625; Thu, 23 Jul 2026 19:53: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=1784836398; cv=none; b=A52ntaz3NsPF7oJwTHAcNSDRe0D55oK3LtpSdcSPGfKxnPR8rIZvjaBqKjnUjoENOn5x/DXHREGpX5/fZAJB7/3ObJptiuPmQiSKvxaz1KXvmpqdTrFk+eR71vSiZPe2E5dGkPtrJOrvPpVxA9nRqZE7eWfIpdCUEIM8ObxOxRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784836398; c=relaxed/simple; bh=SGpbeQv15yY4MuLxvdkmLyUUbm73VYn829J75elBHYU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hlJqkq2Pe7oUFGBdJ2i26PeIJxcn3zRmv7wzvAxShY5D3JiLWOHnMGoJq0STyZbmGp7cgguwyoR5RbZwOAhyHnLWQywGM5fFtEA2VFgByrLwXSGy5GPSzeGyYLwusCXwmT97kaCNKNFejgGSJc/xC/OPT18jEU1eW3Mo6EV5c68= 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=b48KFOa8; 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="b48KFOa8" 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 66NImkYH2938255; Thu, 23 Jul 2026 15:53:11 -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=LzgUm OlJJ5EXBfgWk1sCefwpD0YqbNL59zDuwFaBgwY=; b=b48KFOa8Y6ZWrXOpq25tK vCrusBCd/Ww05TGn4CUnIEyyDxYlUEpFB0XdbGq+0AbVoIUtGbjY6pMQjelSqR4c XYuKM4b7fdAU3ls3RZgYU6Uy+8DfPaN7XxTLR8CIFx0pQVCjcmcJVdLzTnpcxKe8 N6ogWamMJGkvQVJLhBug3GXT/anlvUbR0+yFBhg+dHxdo92uGSr4jjSD0U7pvFYB 0ccv2KrPdrZjXrxklxE8Naj5L72KWljCR8QKV89s4+p6ezZPEvUGqy1a5wEnsL3z WwKINla8iF6z5edWdTtKr6QawilsYIwB8cn1ZpyuOHamfq7H0M6PJwKBY5XhJlrC A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4fj6v4vh3d-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 23 Jul 2026 15:53:11 -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 66NJrAdF049550 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 15:53:10 -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; Thu, 23 Jul 2026 15:53: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; Thu, 23 Jul 2026 15:53: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 66NJqsS6030727; Thu, 23 Jul 2026 15:52:57 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , , Andy Shevchenko Subject: [PATCH v8 3/5] iio: adc: ltc2378: Enable high-speed data capture Date: Thu, 23 Jul 2026 16:52:49 -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=DYknbPtW c=1 sm=1 tr=0 ts=6a627127 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=RAioF0-LDSMA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=uXIjobp8t2wMuQ0fPvqm:22 a=QyXUC8HyAAAA:8 a=IpJZQVW2AAAA:8 a=gAnH3GRIAAAA:8 a=hZRmmEfSnIYLazgqY2MA:9 a=IawgGOuG5U0WyFbmm1f5:22 X-Proofpoint-ORIG-GUID: 1Ji1teEy4nIhHcYOzPSwQwhLS7zrwALB X-Proofpoint-Spam-Info: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX23X1DhUmVaSO dmDcBus55NjJfxi+l7mZ2Vul97M7ZiuRtwkmgYKHF6F5DF3zHt9vZpPhwZMJVVcAUhUYZZTEkoi 7HfYgfZZ5HkurZNkf6IPjhwwqWDXb55ymwhWPB91rn8fPJusLhEb X-Proofpoint-GUID: 1Ji1teEy4nIhHcYOzPSwQwhLS7zrwALB X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX/LUJcnw5UEKY 2g72CPkdbJ4WwNgum6p+ldNzkXzHDbKu+xRiFPc6sh7bptcSDm0JoTi0I3J4fPTEyfF2wP6Qtm6 NregccO3KP7Sq2uHrtWqq2PMWdhjtHLaM3xecPgmMQhR7KwVfHb8leb60qVpMcnHlHDeVb9zp9d i1Y9U+L3SfYgRg5ACFaquaHjmqKWlwsKVAUphF9vYUC4R/mLmBu1InyUYc+sOgXxGMGnyOZLN9a 2YRBGKu70WFdXjcIMsrKrI3LiJQ/XhPnFPYeyOMRVXHgmhH0/aYRyEZdB5YIDrrVZ0X0dgaRB8S EESeyHu0t7PY9JcOKrQg3YyHQ2z6l70NAb+MKy+fTIZxNRlge0WDrHxhlbYaZGW+ieoFFCbZvOp fVdPE6K6DgrQPXFBbt8Dq1k4rFNBfecyMhwZwS0ftdG3v6sfKvc3qFeNoYlVTk0WTsDuSu7ejSH XxXb/0PCqDETvT/ECHA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-23_06,2026-07-22_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 clxscore=1015 lowpriorityscore=0 adultscore=0 priorityscore=1501 bulkscore=0 spamscore=0 malwarescore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607230193 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). Reviewed-by: Andy Shevchenko Reviewed-by: David Lechner Signed-off-by: Marcelo Schmitt --- Change log v7 -> v8: - Updated channel macros to make up indexed IIO channels. drivers/iio/adc/Kconfig | 6 + drivers/iio/adc/ltc2378.c | 407 +++++++++++++++++++++++++++++++++++++- 2 files changed, 410 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 220c6739a8f2..96df8453b826 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -948,6 +948,12 @@ config LTC2378 depends on SPI depends on REGULATOR || COMPILE_TEST depends on GPIOLIB + depends on PWM + select IIO_BUFFER + select IIO_BUFFER_DMA + select IIO_BUFFER_DMAENGINE + select SPI_OFFLOAD + select SPI_OFFLOAD_TRIGGER_PWM help Say yes here to build support for Analog Devices LTC2378-20 and similar analog to digital converters. diff --git a/drivers/iio/adc/ltc2378.c b/drivers/iio/adc/ltc2378.c index 107388f87062..7baee02450d3 100644 --- a/drivers/iio/adc/ltc2378.c +++ b/drivers/iio/adc/ltc2378.c @@ -16,16 +16,27 @@ #include #include #include +#include +#include #include #include #include +#include #include +#include +#include +#include #include #include =20 +#include +#include #include #include =20 +#define LTC2378_TDSDOBUSYL_NS 5 +#define LTC2378_TBUSYLH_NS 13 +#define LTC2378_TCNV_HIGH_NS 20 #define LTC2378_MAX_DATA_WAIT_US 4 /* max(TBUSYLH + TCONV + TDSDOBUSYL) */ =20 #define LTC2378_CHANNEL(_sign, _real_bits, _storage_bits) \ @@ -54,10 +65,50 @@ #define LTC2378_PSEUDO_DIFF_CHANNEL(_real_bits) \ LTC2378_CHANNEL(0, _real_bits, (((_real_bits) > 16) ? 32 : 16)) =20 +#define LTC2378_OFFLOAD_CHANNEL(_sign, _real_bits, _storage_bits) \ +{ \ + .type =3D IIO_VOLTAGE, \ + .indexed =3D 1, \ + .differential =3D _sign, \ + .channel =3D 0, \ + .channel2 =3D _sign ? 1 : 0, \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index =3D 0, \ + .scan_type =3D { \ + .format =3D _sign ? IIO_SCAN_FORMAT_SIGNED_INT : \ + IIO_SCAN_FORMAT_UNSIGNED_INT, \ + .realbits =3D _real_bits, \ + .storagebits =3D _storage_bits, \ + .shift =3D 0, \ + .endianness =3D IIO_CPU, \ + }, \ +} + +/* + * Currently, the available offload hardware + DMA configuration only supp= orts + * pushing 32-bit data elements to DMA IIO buffers in CPU endianness. For = 16-bit + * precision parts, those 32-bit elements (in CPU endianness) contain 2 by= tes + * with data and 2 bytes always zeroed out. Nevertheless, for the offload = use + * case, the IIO buffer is configured for 32 storage bits in CPU endiannes= s so + * data is correctly aligned in user space despite 2 out of the 4 bytes be= ing + * zeros. + */ +#define LTC2378_OFFLOAD_DIFF_CHANNEL(_real_bits) \ + LTC2378_OFFLOAD_CHANNEL(1, (_real_bits), 32) + +#define LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(_real_bits) \ + LTC2378_OFFLOAD_CHANNEL(0, (_real_bits), 32) + struct ltc2378_chip_info { const char *name; unsigned int internal_ref_uV; struct iio_chan_spec chan; + struct iio_chan_spec offload_chan; + unsigned int max_sample_rate_Hz; + unsigned int tconv_ns; }; =20 struct ltc2378_state { @@ -67,6 +118,15 @@ struct ltc2378_state { struct mutex lock; /* Protect data acquisition cycle */ int ref_uV; struct spi_transfer xfer; + struct spi_transfer offload_xfer; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct pwm_waveform cnv_wf; + struct spi_message offload_msg; + struct spi_offload_trigger_config offload_trigger_config; + struct pwm_device *cnv_trigger; + unsigned int cnv_Hz; + unsigned int sample_freq_range[3]; =20 /* * DMA (thus cache coherency maintenance) requires the transfer buffers @@ -87,101 +147,161 @@ static const struct ltc2378_chip_info ltc2338_18_chi= p_info =3D { .name =3D "ltc2338-18", .internal_ref_uV =3D 2048000, .chan =3D LTC2378_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 527, }; =20 static const struct ltc2378_chip_info ltc2364_16_chip_info =3D { .name =3D "ltc2364-16", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, }; =20 static const struct ltc2378_chip_info ltc2364_18_chip_info =3D { .name =3D "ltc2364-18", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, }; =20 static const struct ltc2378_chip_info ltc2367_16_chip_info =3D { .name =3D "ltc2367-16", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, }; =20 static const struct ltc2378_chip_info ltc2367_18_chip_info =3D { .name =3D "ltc2367-18", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, }; =20 static const struct ltc2378_chip_info ltc2368_16_chip_info =3D { .name =3D "ltc2368-16", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 527, }; =20 static const struct ltc2378_chip_info ltc2368_18_chip_info =3D { .name =3D "ltc2368-18", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 527, }; =20 static const struct ltc2378_chip_info ltc2369_18_chip_info =3D { .name =3D "ltc2369-18", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 1600 * HZ_PER_KHZ, + .tconv_ns =3D 412, }; =20 static const struct ltc2378_chip_info ltc2370_16_chip_info =3D { .name =3D "ltc2370-16", .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 2 * HZ_PER_MHZ, + .tconv_ns =3D 322, }; =20 static const struct ltc2378_chip_info ltc2376_16_chip_info =3D { .name =3D "ltc2376-16", .chan =3D LTC2378_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, }; =20 static const struct ltc2378_chip_info ltc2376_18_chip_info =3D { .name =3D "ltc2376-18", .chan =3D LTC2378_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, }; =20 static const struct ltc2378_chip_info ltc2376_20_chip_info =3D { .name =3D "ltc2376-20", .chan =3D LTC2378_DIFF_CHANNEL(20), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), + .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, + .tconv_ns =3D 3000, }; =20 static const struct ltc2378_chip_info ltc2377_16_chip_info =3D { .name =3D "ltc2377-16", .chan =3D LTC2378_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, }; =20 static const struct ltc2378_chip_info ltc2377_18_chip_info =3D { .name =3D "ltc2377-18", .chan =3D LTC2378_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, }; =20 static const struct ltc2378_chip_info ltc2377_20_chip_info =3D { .name =3D "ltc2377-20", .chan =3D LTC2378_DIFF_CHANNEL(20), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), + .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, + .tconv_ns =3D 1500, }; =20 static const struct ltc2378_chip_info ltc2378_16_chip_info =3D { .name =3D "ltc2378-16", .chan =3D LTC2378_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 527, }; =20 static const struct ltc2378_chip_info ltc2378_18_chip_info =3D { .name =3D "ltc2378-18", .chan =3D LTC2378_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 527, }; =20 static const struct ltc2378_chip_info ltc2378_20_chip_info =3D { .name =3D "ltc2378-20", .chan =3D LTC2378_DIFF_CHANNEL(20), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), + .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, + .tconv_ns =3D 675, }; =20 static const struct ltc2378_chip_info ltc2379_18_chip_info =3D { .name =3D "ltc2379-18", .chan =3D LTC2378_DIFF_CHANNEL(18), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), + .max_sample_rate_Hz =3D 1600 * HZ_PER_KHZ, + .tconv_ns =3D 412, }; =20 static const struct ltc2378_chip_info ltc2380_16_chip_info =3D { .name =3D "ltc2380-16", .chan =3D LTC2378_DIFF_CHANNEL(16), + .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), + .max_sample_rate_Hz =3D 2 * HZ_PER_MHZ, + .tconv_ns =3D 322, }; =20 static int ltc2378_convert_and_acquire(struct ltc2378_state *st) @@ -264,7 +384,137 @@ static int ltc2378_read_raw(struct iio_dev *indio_dev, *val2 =3D chan->scan_type.realbits; =20 return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_SAMP_FREQ: + *val =3D st->cnv_Hz; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} =20 +static int ltc2378_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long mask) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals =3D st->sample_freq_range; + *type =3D IIO_VAL_INT; + return IIO_AVAIL_RANGE; + default: + return -EINVAL; + } +} + +/* + * 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; + u64 offload_offset_ns; + int ret; + + if (freq_Hz =3D=3D 0) + return -EINVAL; + + if (!in_range(freq_Hz, 1, 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 (or reach a try count limit). + */ + count =3D 100; + 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-- && cnv_wf.duty_length_ns < LTC2378_TCNV_HIGH_NS); + + /* Check the minimum CNV high time is met */ + if (cnv_wf.duty_length_ns < LTC2378_TCNV_HIGH_NS) + return -EDOM; + + /* + * 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_u64(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 100; + 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-- && config.periodic.offset_ns < min_read_offset); + + /* Check the minimum CNV to SCLK delay is met */ + if (config.periodic.offset_ns < min_read_offset) + return -EDOM; + + /* Check the PWM periods remain the same */ + offload_period_ns =3D div64_u64(HZ_PER_GHZ, config.periodic.frequency_hz); + if (cnv_wf.period_length_ns !=3D offload_period_ns) + return -EDOM; + + st->offload_trigger_config =3D config; + 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 int ltc2378_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct ltc2378_state *st =3D iio_priv(indio_dev); + + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim); + if (IIO_DEV_ACQUIRE_FAILED(claim)) + return -EBUSY; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return ltc2378_update_conversion_rate(st, val); default: return -EINVAL; } @@ -274,6 +524,111 @@ static const struct iio_info ltc2378_iio_info =3D { .read_raw =3D <c2378_read_raw, }; =20 +static const struct iio_info ltc2378_offload_iio_info =3D { + .read_raw =3D <c2378_read_raw, + .read_avail =3D <c2378_read_avail, + .write_raw =3D <c2378_write_raw, +}; + +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, true); + 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_prepare_offload_message(struct device *dev, + struct ltc2378_state *st) +{ + unsigned int resolution =3D st->info->offload_chan.scan_type.realbits; + + st->offload_xfer.bits_per_word =3D resolution; + st->offload_xfer.len =3D spi_bpw_to_bytes(resolution); + 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_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); +} + +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_refin_setup(struct device *dev, struct ltc2378_state *s= t) { int ret; @@ -339,7 +694,6 @@ static int ltc2378_probe(struct spi_device *spi) return ret; =20 indio_dev->name =3D st->info->name; - indio_dev->info =3D <c2378_iio_info; indio_dev->modes =3D INDIO_DIRECT_MODE; =20 st->cnv_gpio =3D devm_gpiod_get(dev, "cnv", GPIOD_OUT_LOW); @@ -347,8 +701,53 @@ static int ltc2378_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(st->cnv_gpio), "failed to get CNV GPIO"); =20 - indio_dev->channels =3D &st->info->chan; - indio_dev->num_channels =3D 1; + st->offload =3D devm_spi_offload_get(dev, spi, <c2378_offload_config); + ret =3D PTR_ERR_OR_ZERO(st->offload); + /* Fall back to low speed usage when no SPI offload is available. */ + if (ret =3D=3D -ENODEV) { + indio_dev->info =3D <c2378_iio_info; + indio_dev->channels =3D &st->info->chan; + indio_dev->num_channels =3D 1; + } else if (ret) { + return dev_err_probe(dev, ret, "failed to get offload\n"); + } else { + indio_dev->info =3D <c2378_offload_iio_info; + indio_dev->channels =3D &st->info->offload_chan; + indio_dev->num_channels =3D 1; + 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 dev_err_probe(dev, ret, "failed to get PWM\n"); + + st->sample_freq_range[0] =3D 1; /* min */ + st->sample_freq_range[1] =3D 1; /* step */ + st->sample_freq_range[2] =3D st->info->max_sample_rate_Hz; /* max */ + + /* + * Start with a slower sampling rate so there is some room for + * adjusting the sample averaging and 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 set offload samp freq\n"); + + ret =3D ltc2378_prepare_offload_message(&spi->dev, st); + if (ret) + return dev_err_probe(dev, ret, "failed to optimize SPI message\n"); + + /* + * Set single-read transfer bits_per_word so the SPI subsystem + * rearranges data to CPU endianness, enabling us to reuse + * offload_chan specifications for single-shot reads. + */ + st->xfer.bits_per_word =3D st->info->offload_chan.scan_type.realbits; + } =20 st->xfer.rx_buf =3D &st->scan.data; st->xfer.len =3D spi_bpw_to_bytes(indio_dev->channels[0].scan_type.realbi= ts); @@ -419,3 +818,5 @@ module_spi_driver(ltc2378_driver); MODULE_AUTHOR("Marcelo Schmitt "); MODULE_DESCRIPTION("Analog Devices LTC2378 ADC series driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); +MODULE_IMPORT_NS("SPI_OFFLOAD"); --=20 2.53.0 From nobody Fri Jul 24 04:44:02 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 7F190308F26; Thu, 23 Jul 2026 19:53:40 +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=1784836422; cv=none; b=n40oUTz5TttWyNuj1xFJ7stvK84YKRTm9FtRq1mF3m9wColYnnj6c+OTtGlSbgWcHSVojh3gKuyzEJXzdQgC7Imow7WaqJPeld6TcoMOvtQRhZG+WHzuogVqC7apUdLcOj8d8glw7XPDs2SMCMx0RzY1/p+KrQ2ZrpIP19Cmqbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784836422; c=relaxed/simple; bh=NF3TMR/L2N64I4DYhyzp1m6HOVICaVfBzLk8VImaOkY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dj02d50Y+GYEAWl9kQWZRPq+lm5yUVnT+PiFqhrXrc6/x0Mvxq5gEijbDAvO8O4Pyya3kO5lVL8mb3a6BO8h95JFX7cjcKOrlpuUsHrZY3LmIRyTq76M1qbkm4r0CZyP3CpK6Qg2AbSvakgNZNY2voNH+4MtZwEkyiu6x545cfg= 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=Ana6Mopn; 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="Ana6Mopn" Received: from pps.filterd (m0516787.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 66NIlxhB2810467; Thu, 23 Jul 2026 15:53:36 -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=XxTjm njcjD0dDrPfjGQ/C7tkUG63ZLptUOcqHpvUJCg=; b=Ana6Mopn5S7RxXE/3Mgmx UwoVHsyMW+MHAD+ZxoCPFqsdtFTBKSvftSOaADdzkF0z5iUkUCsN+qyLmyV30/e6 IHMEP2qgjt+iKfX3kk14vXsEKNK2Oq0hEB4LZllp4hfgIa+5Kyq2QwaRa2ads6R6 5E+0jgP/JyGYPU68omzBdNDbFUn4maA8KpLoa/+SpM7EE/QlYWyna/HCo5/6R25r JAAte5PzUlPG8K+wbfg1F0Z+uZl3OWhjA67tFjrjZ949l17/cv9W9uVjaFNYcNBo a7tYitchZX/tVlgH5INc1PDodu5bmthNwqCHu8QQM2Ff7Vl49MDzXhQv/ls1Wz1y g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4fkh3g1xkp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 23 Jul 2026 15:53:35 -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 66NJrYQr049558 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 15:53:34 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) 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; Thu, 23 Jul 2026 15:53:34 -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; Thu, 23 Jul 2026 15:53:34 -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 66NJrJCW030732; Thu, 23 Jul 2026 15:53:21 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , , Andy Shevchenko Subject: [PATCH v8 4/5] iio: adc: ltc2378: Enable triggered buffer data capture Date: Thu, 23 Jul 2026 16:53: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-Proofpoint-ORIG-GUID: oHNkQMhljhoYIZGrckFG7gx7bpx8n8CM X-Proofpoint-GUID: oHNkQMhljhoYIZGrckFG7gx7bpx8n8CM X-Authority-Analysis: v=2.4 cv=DvNmPm/+ c=1 sm=1 tr=0 ts=6a62713f cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=RAioF0-LDSMA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=OmVn7CZJonkx5R5zMQLL:22 a=QyXUC8HyAAAA:8 a=IpJZQVW2AAAA:8 a=gAnH3GRIAAAA:8 a=LKWNKb2UafNwrDgNmc4A:9 a=IawgGOuG5U0WyFbmm1f5:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX3JVnPfCSyrQh GjmxgcNPH0cZjCBOf0u7XxtmzvZoHK4IsVw01GBgworvvZ6XwCmqaH5ZNs1zacnjaXp3pskcxaE qzjjkdoCthBCPFZaV9EaUUWS8dlc/lPDs7+V9xUJz50C8E+iQRDiaE5m4EX3lL/KG5TGB13l5PV X9KHqHV6Xb/c/NBEJPBybh7tp5KS5Iu7MYlsaMfkfIjHyNE3YJJ3+djTCJZ3BHPwvHihaJIb3Us c5VDc3BDjlMKaImGO4akcmm8B+CHhzMtUL/kCH5E6qJa8bP4b9p6WUZWyl3rMwVbYS9Asb8RO9g joHtOGp4c8knF/YW/rP/b69I12Wam15N046bv5tofQiDOl5B8kvcjLnEEc2buyPZ5XZ1RsnnI8x zp3/WA35PEMxBngFIpbc0gDrzdVxbj5C1ASiK3sVb2zHk7BVFY8GNIdGy0yu16ZEldHD3dpvtgq jnup4kO5FH/1QoI90Dg== X-Proofpoint-Spam-Info: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX1w/sTxdYTFeq oT6LiU83ukLwMy/vaIidNrNSOUkbuKnHjb4KUAQp6+5WOmmqH1tNBhDTCXQIjmcGHtTdYPlIOEP kE5nvMNu/jqdb4X8EkO8d+n9VoCyj3xSRtp9ursOPrPaltzqa5bP X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-23_06,2026-07-22_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 suspectscore=0 phishscore=0 impostorscore=0 bulkscore=0 priorityscore=1501 spamscore=0 clxscore=1015 malwarescore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607230193 Content-Type: text/plain; charset="utf-8" Enable users to run triggered data captures with LTC2378 and similar ADCs. Reviewed-by: Andy Shevchenko Reviewed-by: David Lechner Signed-off-by: Marcelo Schmitt --- No changes in v8. drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ltc2378.c | 75 +++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 96df8453b826..6cf67f7a6eed 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -952,6 +952,7 @@ config LTC2378 select IIO_BUFFER select IIO_BUFFER_DMA select IIO_BUFFER_DMAENGINE + select IIO_TRIGGERED_BUFFER select SPI_OFFLOAD select SPI_OFFLOAD_TRIGGER_PWM help diff --git a/drivers/iio/adc/ltc2378.c b/drivers/iio/adc/ltc2378.c index 7baee02450d3..5128c2a23f75 100644 --- a/drivers/iio/adc/ltc2378.c +++ b/drivers/iio/adc/ltc2378.c @@ -6,6 +6,7 @@ * Author: Marcelo Schmitt */ =20 +#include #include #include #include @@ -32,6 +33,8 @@ #include #include #include +#include +#include #include =20 #define LTC2378_TDSDOBUSYL_NS 5 @@ -105,7 +108,7 @@ struct ltc2378_chip_info { const char *name; unsigned int internal_ref_uV; - struct iio_chan_spec chan; + struct iio_chan_spec chan[2]; /* 1 physical chan + 1 timestamp chan */ struct iio_chan_spec offload_chan; unsigned int max_sample_rate_Hz; unsigned int tconv_ns; @@ -146,7 +149,7 @@ struct ltc2378_state { static const struct ltc2378_chip_info ltc2338_18_chip_info =3D { .name =3D "ltc2338-18", .internal_ref_uV =3D 2048000, - .chan =3D LTC2378_DIFF_CHANNEL(18), + .chan =3D { LTC2378_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 527, @@ -154,7 +157,7 @@ static const struct ltc2378_chip_info ltc2338_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2364_16_chip_info =3D { .name =3D "ltc2364-16", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, .tconv_ns =3D 3000, @@ -162,7 +165,7 @@ static const struct ltc2378_chip_info ltc2364_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2364_18_chip_info =3D { .name =3D "ltc2364-18", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, .tconv_ns =3D 3000, @@ -170,7 +173,7 @@ static const struct ltc2378_chip_info ltc2364_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2367_16_chip_info =3D { .name =3D "ltc2367-16", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, .tconv_ns =3D 1500, @@ -178,7 +181,7 @@ static const struct ltc2378_chip_info ltc2367_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2367_18_chip_info =3D { .name =3D "ltc2367-18", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, .tconv_ns =3D 1500, @@ -186,7 +189,7 @@ static const struct ltc2378_chip_info ltc2367_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2368_16_chip_info =3D { .name =3D "ltc2368-16", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 527, @@ -194,7 +197,7 @@ static const struct ltc2378_chip_info ltc2368_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2368_18_chip_info =3D { .name =3D "ltc2368-18", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 527, @@ -202,7 +205,7 @@ static const struct ltc2378_chip_info ltc2368_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2369_18_chip_info =3D { .name =3D "ltc2369-18", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(18), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 1600 * HZ_PER_KHZ, .tconv_ns =3D 412, @@ -210,7 +213,7 @@ static const struct ltc2378_chip_info ltc2369_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2370_16_chip_info =3D { .name =3D "ltc2370-16", - .chan =3D LTC2378_PSEUDO_DIFF_CHANNEL(16), + .chan =3D { LTC2378_PSEUDO_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_PSEUDO_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 2 * HZ_PER_MHZ, .tconv_ns =3D 322, @@ -218,7 +221,7 @@ static const struct ltc2378_chip_info ltc2370_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2376_16_chip_info =3D { .name =3D "ltc2376-16", - .chan =3D LTC2378_DIFF_CHANNEL(16), + .chan =3D { LTC2378_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, .tconv_ns =3D 3000, @@ -226,7 +229,7 @@ static const struct ltc2378_chip_info ltc2376_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2376_18_chip_info =3D { .name =3D "ltc2376-18", - .chan =3D LTC2378_DIFF_CHANNEL(18), + .chan =3D { LTC2378_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, .tconv_ns =3D 3000, @@ -234,7 +237,7 @@ static const struct ltc2378_chip_info ltc2376_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2376_20_chip_info =3D { .name =3D "ltc2376-20", - .chan =3D LTC2378_DIFF_CHANNEL(20), + .chan =3D { LTC2378_DIFF_CHANNEL(20), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), .max_sample_rate_Hz =3D 250 * HZ_PER_KHZ, .tconv_ns =3D 3000, @@ -242,7 +245,7 @@ static const struct ltc2378_chip_info ltc2376_20_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2377_16_chip_info =3D { .name =3D "ltc2377-16", - .chan =3D LTC2378_DIFF_CHANNEL(16), + .chan =3D { LTC2378_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, .tconv_ns =3D 1500, @@ -250,7 +253,7 @@ static const struct ltc2378_chip_info ltc2377_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2377_18_chip_info =3D { .name =3D "ltc2377-18", - .chan =3D LTC2378_DIFF_CHANNEL(18), + .chan =3D { LTC2378_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, .tconv_ns =3D 1500, @@ -258,7 +261,7 @@ static const struct ltc2378_chip_info ltc2377_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2377_20_chip_info =3D { .name =3D "ltc2377-20", - .chan =3D LTC2378_DIFF_CHANNEL(20), + .chan =3D { LTC2378_DIFF_CHANNEL(20), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), .max_sample_rate_Hz =3D 500 * HZ_PER_KHZ, .tconv_ns =3D 1500, @@ -266,7 +269,7 @@ static const struct ltc2378_chip_info ltc2377_20_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2378_16_chip_info =3D { .name =3D "ltc2378-16", - .chan =3D LTC2378_DIFF_CHANNEL(16), + .chan =3D { LTC2378_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 527, @@ -274,7 +277,7 @@ static const struct ltc2378_chip_info ltc2378_16_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2378_18_chip_info =3D { .name =3D "ltc2378-18", - .chan =3D LTC2378_DIFF_CHANNEL(18), + .chan =3D { LTC2378_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 527, @@ -282,7 +285,7 @@ static const struct ltc2378_chip_info ltc2378_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2378_20_chip_info =3D { .name =3D "ltc2378-20", - .chan =3D LTC2378_DIFF_CHANNEL(20), + .chan =3D { LTC2378_DIFF_CHANNEL(20), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(20), .max_sample_rate_Hz =3D 1 * HZ_PER_MHZ, .tconv_ns =3D 675, @@ -290,7 +293,7 @@ static const struct ltc2378_chip_info ltc2378_20_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2379_18_chip_info =3D { .name =3D "ltc2379-18", - .chan =3D LTC2378_DIFF_CHANNEL(18), + .chan =3D { LTC2378_DIFF_CHANNEL(18), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(18), .max_sample_rate_Hz =3D 1600 * HZ_PER_KHZ, .tconv_ns =3D 412, @@ -298,7 +301,7 @@ static const struct ltc2378_chip_info ltc2379_18_chip_i= nfo =3D { =20 static const struct ltc2378_chip_info ltc2380_16_chip_info =3D { .name =3D "ltc2380-16", - .chan =3D LTC2378_DIFF_CHANNEL(16), + .chan =3D { LTC2378_DIFF_CHANNEL(16), IIO_CHAN_SOFT_TIMESTAMP(1) }, .offload_chan =3D LTC2378_OFFLOAD_DIFF_CHANNEL(16), .max_sample_rate_Hz =3D 2 * HZ_PER_MHZ, .tconv_ns =3D 322, @@ -317,6 +320,25 @@ static int ltc2378_convert_and_acquire(struct ltc2378_= state *st) return ret; } =20 +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_channel_single_read(const struct iio_chan_spec *chan, struct ltc2378_state *st, int *val) { @@ -706,8 +728,15 @@ static int ltc2378_probe(struct spi_device *spi) /* Fall back to low speed usage when no SPI offload is available. */ if (ret =3D=3D -ENODEV) { indio_dev->info =3D <c2378_iio_info; - indio_dev->channels =3D &st->info->chan; - indio_dev->num_channels =3D 1; + indio_dev->channels =3D st->info->chan; + indio_dev->num_channels =3D ARRAY_SIZE(st->info->chan); + + ret =3D devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ltc2378_trigger_handler, + NULL); + if (ret) + return ret; } else if (ret) { return dev_err_probe(dev, ret, "failed to get offload\n"); } else { --=20 2.53.0 From nobody Fri Jul 24 04:44:02 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 CBD233B83E8; Thu, 23 Jul 2026 19:53:56 +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=1784836438; cv=none; b=H1gn9KiDXDS9pM5grr033oADy62K/mUoACQhgwUlgYs8ykm7lXcQLnm4tsb2k8zJcF2PLTbyKA6KPGEc17m4otic1gQnKysj4m82KkLHXLqjUArbzk9iMRj/4Dvvh7yy65waFGvE/EPz7fLNdzaWghvM/APAorktS5H/Ky9BKqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784836438; c=relaxed/simple; bh=xV74dqSO6y09UvkWdLgQqWpAE0g0hXZqw6+MJYpmQD8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oAz1hXqRZtSuGfs3oZizXkRo6sJmDNU7trHP3nH2+uxo6dsU7E1zr0zmoRynfLieqIi3MkTLTwfG7pA4D5lMeJiPSYELikBOEyOKOCaoMJ2ntHrSXht/OB8SQtfKriyUWvfWhznvkU7LAqfdZOLC0ggjyQPItQiu0LSCf2GBhHQ= 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=wcsWMMm9; 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="wcsWMMm9" 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 66NImI0q2703474; Thu, 23 Jul 2026 15:53:53 -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=/r/sI t3CGJT9LVAFlwseZkP+dIpiZQwViwYClAgcccY=; b=wcsWMMm9bw380aEclEYXs LGnXCKifh1SflGY9F6ZMufEHhB9ANm4QbHCdwjt1V002smsQpfnXHl9aqq4LZPkK IxELmHX9jkPfpw22NgHtHLDytcuLgAetq2cbniQ0oo/6nz9gZVadhg4K0DeSI8Jq 3/DvNUR8YOMJEs9EyvKHbDoMC36fNieI1DYuI/B+/nmZsUt42yB/wMo80B5mdj+P bIVE2MUyBXtFfEYuhA9DVGtIAIxf2N8c36eZtXzuRQvgVr7xFNVaPP+VCJR9/Ddb j0H210/COktUyP8KGvhQV4fVNZ2hg3Jz12e+s2OqkWube13sfWNOnysQa0cD3uAu A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4fjgp0su29-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 23 Jul 2026 15:53:53 -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 66NJrpsx049576 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 23 Jul 2026 15:53:52 -0400 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) 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; Thu, 23 Jul 2026 15:53:51 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Thu, 23 Jul 2026 15:53:51 -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; Thu, 23 Jul 2026 15:53:51 -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 66NJreO8030737; Thu, 23 Jul 2026 15:53:43 -0400 From: Marcelo Schmitt To: , , CC: , , , , , , , , , Subject: [PATCH v8 5/5] iio: ABI: Encourage differential voltage ABI usage Date: Thu, 23 Jul 2026 16:53:35 -0300 Message-ID: <9f47e67f188a910c3e025255dcd1354ef2dc026a.1784835663.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-Info: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX0DiA0/2uVZhZ rcmnXche3PF4FLR100KvYX5ob38Yj+RcdhE9xVTKTp4W5icIL1qQouql1MjTsB98PGa/aROaIDn exlsyOrOZCIFLiQP8al31DIIlVeZk/Xa1YXB+b3s1II7ocL6alRU X-Proofpoint-GUID: n8DqUgbiDn-1gwohYNvDGfKUdFsuZEnb X-Proofpoint-ORIG-GUID: n8DqUgbiDn-1gwohYNvDGfKUdFsuZEnb X-Authority-Analysis: v=2.4 cv=cPXQdFeN c=1 sm=1 tr=0 ts=6a627151 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=RAioF0-LDSMA:10 a=VkNPw1HP01LnGYTKEx00:22 a=0sLvza09kfJOxVLZPwjg:22 a=Z0pTeXoby7EwIRygza74:22 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=iGya_9aoYPPjgpMbcYQA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNzIzMDE5MyBTYWx0ZWRfX0sWZnA+tnUPF gfe91rSw8Bluu9n9gaTh1aXe0Bb6OL23yJxVv1IL5nCt9mi/F5qqNCwxd0AXo4o1cG+vxc6MVhC oydFoUQ43GIWnr+yOEor1+wzSJrEf+v7drzXPqrgktrkPqEK8FnNSN17MlmpM1Pw5nGguEm7Wq0 TT7K/GmSi/HBFI6SgJ5Hg89TfqUX+3ZaJqbcsQQc3gl0wCXZeXIfO25x9DFlaOpOxJNMqVueJqy FA95iEuM5a/PL8L2sV8tBiSgaqOEZGajCxcjbx5q98r2dxH7wae+PL5qs1eJEPrkKPNdpXA9ISW YzNOE/a9ThgyjnLuTJcX31MBwMLyvloXQrS/+oFppR01e1E0N0UXb2siuQF/iva5mdOpBALhzdV eWxmGd7QLxTOvh6mfQba8ktwnH4H/+K1vBPKxUX+p/bCKA6AoawaVL98x6wS124V36P3TFUX2Xx fBfwIM20kiHhOyQypbQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-07-23_06,2026-07-22_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 phishscore=0 spamscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 clxscore=1015 impostorscore=0 adultscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2607230193 Content-Type: text/plain; charset="utf-8" So far, parts that could only do differential voltage measurements were only required to have a consistent labeling of their channels by complying either to voltageY or to voltageY-voltageZ ABI. Over time, code maintainers came to the conclusion that the voltageY-voltageZ ABI is better suited for differential-only chips as it provides a simple indication to users that the channels measure the difference of two inputs. Adjust the ABI documentation to recommend using the voltageY-voltageZ ABI for chips that do only differential voltage measurements. Signed-off-by: Marcelo Schmitt --- New patch in v8. The updated ABI doc might not have gotten very clear, so I'm completely fine with any modifications to this patch. Also, since the documentation update = is minimal, doesn't add any new ABI, and might be picked up through Jonathan's tree, I'm not CCing the documentaion mailing list. Documentation/ABI/testing/sysfs-bus-iio | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index 5cc2e82c4997..7446e07b9ab2 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -162,10 +162,11 @@ Contact: linux-iio@vger.kernel.org Description: Raw (unscaled) differential voltage measurement equivalent to channel Y - channel Z where these channel numbers apply to the - physically equivalent inputs when non differential readings are - separately available. In differential only parts, then all that - is required is a consistent labeling. Units after application - of scale and offset are millivolts. + physically equivalent inputs when non-differential readings are + separately available. Even though differential-only parts had + been merely required to have consistent channel labeling, this + ABI is preferred over the non-differential one for those chips. + Units after application of scale and offset are millivolts. =20 What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_rms_raw KernelVersion: 6.18 --=20 2.53.0