From nobody Sun Feb 8 22:59:49 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 355F527CB06; Tue, 22 Apr 2025 11:35: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=1745321738; cv=none; b=XS+XQ8KAHARUFixsccnZoKryQen9ZbLnshZDd2hC+M1zD622n7NDBW92fLev7tg6/lFynL9wi08sSK7GQEabToSPU/4vCLQLMkhC+/Aa7dvt2BsHeP/W2UjMqJkHp8j8o7YWAl7+YdSxWm1f++qi3Hw2K6Y4LkR1a8GGUG76Wq0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745321738; c=relaxed/simple; bh=TlMA7ZQBOxvUdaio2NjH92P0I3iyaKZuK2JKBu/xeiA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=A7dl1OqslkskiFSLLoxRpMKb2DT3MaGtzNkcOtNo9wbav/4AxHqj0fAmsLIIaniKHEnakZTPbMWbVi35IrYtLnikU3AgJ7IbwxfU2Arfr3mG73ZCVImSIU1JzDIE7GYabEZ70n5VbtdjhJllkQShDuw9fKX0AN0u9sOmh/lItBw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 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=WI6sbVc2; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none 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="WI6sbVc2" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 53MAEb7D029954; Tue, 22 Apr 2025 07:35:21 -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=mvA9/ LerFIFIqbFyGdykheft533sEC6KvAJoBSyow3g=; b=WI6sbVc2ahfnvScUhrWEv bmiUvgyhinbbn2xO5mJSVOrkjrGAPqOS+UpThgFykmAXsdgPp0Fe5+3k5WS/dUVt OBZWCLaAKntF3GV0Pgl6Wx67Gl7+rBDSwyh9o7P/1GQeva0GNfMJaEXekHwXGqYa lvjdvZ33mrc/xC7qXhLT1ZswkL7eW0wkkHtgd4+QTJNjr9xTtb3FdzLcOaW5PaOl 7XpSuejoZorDVlABGtx9wTW38wB5w5NKQliBJRItr5ob/6t52Hxk6Md8zeJAZAmf DtmjyKUVlu9zxgzXryD6tSPRoo/o6bDaw6UnSCNc+ZqpowClhD77Xfq/AQNVBYU7 g== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 464t5gm6nf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 22 Apr 2025 07:35:21 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 53MBZJvH057901 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 Apr 2025 07:35:19 -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.986.14; Tue, 22 Apr 2025 07:35:19 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) 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.986.14; Tue, 22 Apr 2025 07:35:19 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 22 Apr 2025 07:35:19 -0400 Received: from HYB-DlYm71t3hSl.ad.analog.com (HYB-DlYm71t3hSl.ad.analog.com [10.44.3.55]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 53MBZ4Qo024350; Tue, 22 Apr 2025 07:35:12 -0400 From: Jorge Marques Date: Tue, 22 Apr 2025 13:34:46 +0200 Subject: [PATCH v2 1/5] Documentation: ABI: add oversampling frequency in sysfs-bus-iio Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250422-iio-driver-ad4052-v2-1-638af47e9eb3@analog.com> References: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> In-Reply-To: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> To: Jonathan Cameron , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , "Andy Shevchenko" , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= CC: , , , , , Jorge Marques X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745321704; l=2624; i=jorge.marques@analog.com; s=20250303; h=from:subject:message-id; bh=TlMA7ZQBOxvUdaio2NjH92P0I3iyaKZuK2JKBu/xeiA=; b=0pCZNbtOxqcI8P1XCmBQu5TndIG1zwR9YnNlRa3plSj10lJyZXs0HaiUhiDq19xMQBT3jw7z5 1kBNvAnWNTyDtWuuqn3GvE+fY2tQX5wZOUNewpALF5Kqu6xQoyb09Id X-Developer-Key: i=jorge.marques@analog.com; a=ed25519; pk=NUR1IZZMH0Da3QbJ2tBSznSPVfRpuoWdhBzKGSpAdbg= X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=RaiQC0tv c=1 sm=1 tr=0 ts=68077ef9 cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=IkcTkHD0fZMA:10 a=XR8D0OoHHMoA:10 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=RBIExvWx9eVdLZ2BeXAA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-GUID: agFd13OU1QOm8CGJvNC_Ia7fIFqPl-3o X-Proofpoint-ORIG-GUID: agFd13OU1QOm8CGJvNC_Ia7fIFqPl-3o X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1095,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-04-22_05,2025-04-21_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 bulkscore=0 spamscore=0 lowpriorityscore=0 mlxlogscore=999 impostorscore=0 malwarescore=0 priorityscore=1501 suspectscore=0 clxscore=1011 phishscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2504220087 Some devices have an internal clock used to space out the conversion trigger for the oversampling filter, Consider an ADC with conversion and data ready pins topology: Sampling trigger | | | | | ADC conversion ++++ ++++ ++++ ++++ ++++ ADC data ready * * * * * With the oversampling frequency, conversions are spaced: Sampling trigger | | | | | ADC conversion + + + + + + + + + + + + + + + + + + + + ADC data ready * * * * * In some devices and ranges, this internal clock can be used to evenly space the conversions between the sampling edge. In other devices the oversampling frequency is fixed or is computed based on the sampling frequency parameter, and the parameter is read only. Devices with this feature are max1363, ad7606, ad799x, and ad4052. The max1363 driver included the events/sampling_frequency in commit 168c9d95a940 ("iio:adc:max1363 move from staging.") and ad799x in commit ba1d79613df3 ("staging:iio:ad799x: Use event spec for threshold hysteresis") but went undocumented so far. Signed-off-by: Jorge Marques --- Documentation/ABI/testing/sysfs-bus-iio | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/te= sting/sysfs-bus-iio index 33c09c4ac60a4feec82308461643134f5ba84b66..129061befb21b82a51142a01a94= d96fcf1b60072 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -139,6 +139,23 @@ Contact: linux-iio@vger.kernel.org Description: Hardware dependent values supported by the oversampling filter. =20 +What: /sys/bus/iio/devices/iio:deviceX/oversampling_frequency +KernelVersion: 6.15 +Contact: linux-iio@vger.kernel.org +Description: + Some devices have internal clocks for oversampling. + Sets the resulting frequency in Hz to trigger a conversion used by + the oversampling filter. + If the device has a fixed internal clock or is computed based on + the sampling frequency parameter, the parameter is read only. + +What: /sys/bus/iio/devices/iio:deviceX/oversampling_frequency_available +KernelVersion: 6.15 +Contact: linux-iio@vger.kernel.org +Description: + Hardware dependent values supported by the oversampling + frequency. + What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_raw --=20 2.49.0 From nobody Sun Feb 8 22:59:49 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 187DE27CB01; Tue, 22 Apr 2025 11:35: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=1745321738; cv=none; b=G9Hvd2+eP1m+y5QWGbblsqR5F0bFGE5urZW0TZASehSJrZQPhsSrY1EJam3+jLIQqtuDADkc7DT9RsAnW/EYh4/q2JgpLOXK7xOPhA6FiVm7msBUfPlB+c+1oWKK1qYLbSv2m2reCETXKf3QvacAJHHJC9iPYoon13/6j+U3OnI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745321738; c=relaxed/simple; bh=TPF6Yw0kE744Z7BBYS2QEDueGGJOuHShE1E+wwdptnY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=c8zy716eZ6Iqg8UyQ9hAKEkznu85EaIyOceDuST5xiog8Pl+UK8hiCTdsDKsQc9klhCu/dWN0AqJKBA+U0LVvZ8qZrazDTrQ1TCsx6B5xfLZLLLSeyrFUqrxgqU40wZS+O/IRTK8K7sIlsXb7C0mubwkaHum7fXTliew2bkK8Wc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 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=06pw2mYZ; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none 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="06pw2mYZ" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 53MAHnTa021966; Tue, 22 Apr 2025 07:35:23 -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=xCYWF yld7moiL86cRB/FqLC/2Ow1Lj7odmKSjlXGeow=; b=06pw2mYZQWofbKGV6AU2H 2Q2uemP3wjrkY1RkhFE5eXeD5I53wUgDNr0Gwah0THn7736NIJzC0LcR1oC1lqAL +gK05/BCkJ3ey9Ffh+iXkVrm9axIwU6mVvqCnuSPJRocxpZ5mUQxH+6I/S3J7hto /wWFdQbA88dZ7BzzCUpFKhc1IKoM7NX3VV03qsLbj8ZHTVvZTtcwbK9pH6mfnMJc +Hpg0+cnPqmstpdO/+zsuyNyp2l9YXMW2r4lWKdJbI1qn8xUHtAL9Oc9NEWPY2dv mvj7AMUajY+xmf8niDbXDKQ3jS4vpDMdG9d+CPHn4hza5njlFIMOfS49eFKwPIh5 Q== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4645p7q8rq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 22 Apr 2025 07:35:22 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 53MBZLoC057912 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 Apr 2025 07:35:21 -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.986.14; Tue, 22 Apr 2025 07:35:21 -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.986.14 via Frontend Transport; Tue, 22 Apr 2025 07:35:21 -0400 Received: from HYB-DlYm71t3hSl.ad.analog.com (HYB-DlYm71t3hSl.ad.analog.com [10.44.3.55]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 53MBZ4Qp024350; Tue, 22 Apr 2025 07:35:14 -0400 From: Jorge Marques Date: Tue, 22 Apr 2025 13:34:47 +0200 Subject: [PATCH v2 2/5] iio: code: mark iio_dev as const in iio_buffer_enabled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250422-iio-driver-ad4052-v2-2-638af47e9eb3@analog.com> References: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> In-Reply-To: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> To: Jonathan Cameron , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= CC: , , , , , Jorge Marques X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745321704; l=1550; i=jorge.marques@analog.com; s=20250303; h=from:subject:message-id; bh=TPF6Yw0kE744Z7BBYS2QEDueGGJOuHShE1E+wwdptnY=; b=SHB/YIAswwLn6uqAO1+GKmRhhkFuy4bRiKdJGIArBOnTzWKr43CUWt1Mp62RHJBFMp8DMrsmT Uw9hAFNUmN8AEi3qraBY/iTerNC+spMmRcVnoY/bCiDCvmffD1cvJeX X-Developer-Key: i=jorge.marques@analog.com; a=ed25519; pk=NUR1IZZMH0Da3QbJ2tBSznSPVfRpuoWdhBzKGSpAdbg= X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=D4VHKuRj c=1 sm=1 tr=0 ts=68077efa cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=IkcTkHD0fZMA:10 a=XR8D0OoHHMoA:10 a=gAnH3GRIAAAA:8 a=5tS4fjQXojCEwv7GM0AA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-GUID: nymIAMSUyUu96HZzJV-UL5mSho6dDLZT X-Proofpoint-ORIG-GUID: nymIAMSUyUu96HZzJV-UL5mSho6dDLZT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1095,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-04-22_05,2025-04-21_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 phishscore=0 impostorscore=0 suspectscore=0 spamscore=0 clxscore=1011 priorityscore=1501 adultscore=0 mlxlogscore=999 bulkscore=0 mlxscore=0 lowpriorityscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2504220087 The iio_dev struct is never modified inside the method, mark it as const. This allows to be called from get_current_scan_type, and is useful when the scan_type depends on the buffer state. Signed-off-by: Jorge Marques Reviewed-by: Andy Shevchenko --- drivers/iio/industrialio-core.c | 2 +- include/linux/iio/iio.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-cor= e.c index 178e99b111debc59a247fcc3a6037e429db3bebf..bc6a2ac6415eccf201e148ea98c= 0b5982787eb6d 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(iio_device_id); * * Returns: True, if the buffer is enabled. */ -bool iio_buffer_enabled(struct iio_dev *indio_dev) +bool iio_buffer_enabled(const struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque =3D to_iio_dev_opaque(indio_dev); =20 diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 638cf2420fbd85cf2924d09d061df601d1d4bb2a..88569e1a888bde4d2bfb5b9f030= 096af1c15d68d 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -629,7 +629,7 @@ struct iio_dev { =20 int iio_device_id(struct iio_dev *indio_dev); int iio_device_get_current_mode(struct iio_dev *indio_dev); -bool iio_buffer_enabled(struct iio_dev *indio_dev); +bool iio_buffer_enabled(const struct iio_dev *indio_dev); =20 const struct iio_chan_spec *iio_find_channel_from_si(struct iio_dev *indio_dev, int si); --=20 2.49.0 From nobody Sun Feb 8 22:59:49 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 08E6727D76A; Tue, 22 Apr 2025 11:35:39 +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=1745321741; cv=none; b=Dg16+DoWyLI4toj0zezk1F5VRErfIBY8xpiyov/v6r5O0DFVKTTdUGHJTFlni8ohV61m/3u2IrY+rao9i9O11CYHSUXBao22Eiedb1JmJRAEzmrJiUk44GnaSlMvy0a+KcPSEfVApMZJDmAl6HsxRN+ZSHqa+UlLqHhmY49jaSM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745321741; c=relaxed/simple; bh=AXR9N1DwB389eApnJDPbeMf/BZ2AAWFC+CnUCOCV5jk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=DC9IGOMG98rUoC45LiofT+CmUoS/Pjoony8ypZowq9Ek651fHLzs+t6NJSOPN4SAG75dZDIEqfQm+xJRRFdf/l3wwD/yk8BVxMazC5Bl9d48BjYO56grDZ9tq/BptS0cZ8j1pDDlInXboMSDyfskAr5kQHe1vUymFn65+Oh/u/A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 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=i0QhnsdU; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none 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="i0QhnsdU" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 53MA4Fod029132; Tue, 22 Apr 2025 07:35:25 -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=5qmEA umP8Ir40WoPF7pfQtOdDlZrPv3CfeSg7p9S74Q=; b=i0QhnsdUzGf7wznZ1PT0z mUnRRHpOegcKiyonMid+BULvMv5bRaX0SyM+Crsxf36CS/+kbTjUWQLNF0MbEkop Hu8NFEifKQKHZBq7Xkih+/8Welc+0h5pVXXiZqH2i39NFduyLlbu3BJIQBdiAEKo r3K7F7naKjGSsIyh0UYRoM4y7AzSAUIJkmvpFkiUcgRAOrw0dfEbzie7s4+SklKC wIppk5gMORH7tOBcBOhCeQBSYsg0SEcXzA91SjEqEzja8wDj6FkpiZ5lG6PWhoVS dE+cnjuWhXBHfcP7eQ/mUykhYUGeVmUM4Lfd1tAUSkehufCoGOn/gqC1kWYfTlOF A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 464t5gm6p3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 22 Apr 2025 07:35:24 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 53MBZNw4057917 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 Apr 2025 07:35:23 -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.986.14; Tue, 22 Apr 2025 07:35:23 -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.986.14 via Frontend Transport; Tue, 22 Apr 2025 07:35:23 -0400 Received: from HYB-DlYm71t3hSl.ad.analog.com (HYB-DlYm71t3hSl.ad.analog.com [10.44.3.55]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 53MBZ4Qq024350; Tue, 22 Apr 2025 07:35:16 -0400 From: Jorge Marques Date: Tue, 22 Apr 2025 13:34:48 +0200 Subject: [PATCH v2 3/5] dt-bindings: iio: adc: Add adi,ad4052 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250422-iio-driver-ad4052-v2-3-638af47e9eb3@analog.com> References: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> In-Reply-To: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> To: Jonathan Cameron , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= CC: , , , , , Jorge Marques X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745321704; l=4091; i=jorge.marques@analog.com; s=20250303; h=from:subject:message-id; bh=AXR9N1DwB389eApnJDPbeMf/BZ2AAWFC+CnUCOCV5jk=; b=SDTsaLgNLjArAs32s0DRL2AwpM6fgZXRPfdZPUMFHws+8wcyKyV8faKwIkQt98cYO6j/G9eLl oF3VbFvav//BvHg06LrWDetxVr9ZyBsvIIUUUQQsWMnF6CiCHHK3FIv X-Developer-Key: i=jorge.marques@analog.com; a=ed25519; pk=NUR1IZZMH0Da3QbJ2tBSznSPVfRpuoWdhBzKGSpAdbg= X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=RaiQC0tv c=1 sm=1 tr=0 ts=68077efc cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=IkcTkHD0fZMA:10 a=XR8D0OoHHMoA:10 a=gEfo2CItAAAA:8 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=0CypkOm7ba8rlrjfvoEA:9 a=QEXdDO2ut3YA:10 a=sptkURWiP4Gy88Gu7hUp:22 X-Proofpoint-GUID: mRpUd89L8WEq0XLBKrng9lPHuSxz0ebR X-Proofpoint-ORIG-GUID: mRpUd89L8WEq0XLBKrng9lPHuSxz0ebR X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1095,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-04-22_05,2025-04-21_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 bulkscore=0 spamscore=0 lowpriorityscore=0 mlxlogscore=999 impostorscore=0 malwarescore=0 priorityscore=1501 suspectscore=0 clxscore=1011 phishscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2504220087 Add dt-bindings for AD4052 family, devices AD4050/AD4052/AD4056/AD4058, low-power with monitor capabilities SAR ADCs. Each variant of the family differs in speed and resolution, resulting in different scan types and spi word sizes, that are matched by the compatible with the chip_info. The device contains one input (cnv) and two outputs (gp0, gp1). Signed-off-by: Jorge Marques Reviewed-by: Rob Herring (Arm) --- .../devicetree/bindings/iio/adc/adi,ad4052.yaml | 98 ++++++++++++++++++= ++++ MAINTAINERS | 6 ++ 2 files changed, 104 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4052.yaml b/Do= cumentation/devicetree/bindings/iio/adc/adi,ad4052.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a0510d485f130ceec15b887e8f8= deeb2cf6562c8 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4052.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright 2025 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad4052.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD4052 ADC family device driver + +maintainers: + - Jorge Marques + +description: | + Analog Devices AD4052 Single Channel Precision SAR ADC family + + https://www.analog.com/media/en/technical-documentation/data-sheets/ad40= 50-ad4056.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad40= 52-ad4058.pdf + +properties: + compatible: + enum: + - adi,ad4050 + - adi,ad4052 + - adi,ad4056 + - adi,ad4058 + + reg: + maxItems: 1 + + interrupts: + items: + - description: Signal coming from the GP0 pin (threshold). + - description: Signal coming from the GP1 pin (data ready). + + interrupt-names: + items: + - const: gp0 + - const: gp1 + + gpio-controller: true + + "#gpio-cells": + const: 2 + description: | + The first cell is the GPn number: 0 to 1. + The second cell takes standard GPIO flags. + + cnv-gpios: + description: The Convert Input (CNV). If omitted, CNV is tied to SPI C= S. + maxItems: 1 + + spi-max-frequency: + maximum: 62500000 + + vdd-supply: + description: Analog power supply. + + vio-supply: + description: Digital interface logic power supply. + + vref-supply: + description: Reference voltage to set the ADC full-scale range. + +required: + - compatible + - reg + - vdd-supply + - vio-supply + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + spi { + #address-cells =3D <1>; + #size-cells =3D <0>; + + adc@0 { + compatible =3D "adi,ad4052"; + reg =3D <0>; + vdd-supply =3D <&adc_vdd>; + vio-supply =3D <&adc_vio>; + spi-max-frequency =3D <25000000>; + + interrupt-parent =3D <&gpio>; + interrupts =3D <0 0 IRQ_TYPE_EDGE_RISING>, + <0 1 IRQ_TYPE_EDGE_FALLING>; + interrupt-names =3D "gp0", "gp1"; + cnv-gpios =3D <&gpio 2 GPIO_ACTIVE_HIGH>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 01079a189c93697c1db6b0ca4e54212d25589974..81fbe7176475c48eae03ab04115= d4ef5b6299fac 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1329,6 +1329,12 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad4= 030.yaml F: Documentation/iio/ad4030.rst F: drivers/iio/adc/ad4030.c =20 +ANALOG DEVICES INC AD4052 DRIVER +M: Jorge Marques +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ad4052.yaml + ANALOG DEVICES INC AD4130 DRIVER M: Cosmin Tanislav L: linux-iio@vger.kernel.org --=20 2.49.0 From nobody Sun Feb 8 22:59:49 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 195AA27EC69; Tue, 22 Apr 2025 11:35:42 +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=1745321744; cv=none; b=JNfjj6et6G6CDoSikXgLT07dkwIcqFwCM1+CZuwsp6UQCBztRPejjBhOCRgi0kSaMoosJuI8Ydhf7aLkivFHsHRvIzTaYoy3+aq1sbqsGHze8NAH30JQpqeQiEDTNeygH01mP9AliUWVipbQcsq/al+Iq4gcmTMW+38ZhJl4GU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745321744; c=relaxed/simple; bh=QtEocJy/CJth/1vVDY0oG1mV878r2tNjKt4aQLtRDb4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=RsMtvEJyQfaAtMFMri91rYK9G56xkT1N6uMWZ5nsSjq6gvqzZfnYGFbYPr/BtcfC4CkJZ58sFJC9AXNLqIXJwSUEDdKes9jM+0BsiZnDVbJeOF+QYb7JtBuav6yHUgbLsj99vONdJ0zP9tSoOqhUTna0j5Wd4dqzBalLK4Uc5bM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 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=d7KVxezB; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none 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="d7KVxezB" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 53MAWq8W022389; Tue, 22 Apr 2025 07:35:29 -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=VGzu1 GLzxd8b4H7qPy2W9Zq0LtV9JQ9yF0J8aNtLXlM=; b=d7KVxezB4EkDzSlCkGDCJ CWD1PUE31UVF36EGGRhN3lIG5TfaJI7Sz2lsZu8+ZdIzVGl8qN04FFAELjAOrP9B VIijvG/klwKHaf3fZVG64fXn3vZT++snLs7ANFOWZtOVJo6OwxD4T19+89lWy4Sa 1ClJUdhkVppl7ZKiDFKqHTIqz7+PFO4Z0ndM1y0Hmg8VwSBa1ZfFstu+lJMISPER AN+Em2nqYafjJ431NOWPtiyLffvFAp/BrNx+VaJicE5j6Aq/RNkxr13aB+uELTZg anSxLybAHgGeK0QUT1ckWdxDXB4+HkEkkPk/9tTT+N+MQERnvQ7VN4eTj+l5odmC g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4645p7q8s7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 22 Apr 2025 07:35:28 -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 53MBZR24050191 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 Apr 2025 07:35:27 -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.986.14; Tue, 22 Apr 2025 07:35:27 -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.986.14 via Frontend Transport; Tue, 22 Apr 2025 07:35:27 -0400 Received: from HYB-DlYm71t3hSl.ad.analog.com (HYB-DlYm71t3hSl.ad.analog.com [10.44.3.55]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 53MBZ4Qr024350; Tue, 22 Apr 2025 07:35:18 -0400 From: Jorge Marques Date: Tue, 22 Apr 2025 13:34:49 +0200 Subject: [PATCH v2 4/5] docs: iio: new docs for ad4052 driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250422-iio-driver-ad4052-v2-4-638af47e9eb3@analog.com> References: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> In-Reply-To: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> To: Jonathan Cameron , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= CC: , , , , , Jorge Marques X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745321704; l=4091; i=jorge.marques@analog.com; s=20250303; h=from:subject:message-id; bh=QtEocJy/CJth/1vVDY0oG1mV878r2tNjKt4aQLtRDb4=; b=edCYEFEQRHzRG8szj7sKRBqMYYjAWY6eZHgvizquSjlrdVZFBbgBtLzEYWM1HUCEtL7Sjyb8e MeD8GkZvy3rA0dhYoh0hGomA25MthK5Dg26t3fvh19qGV+gj0gooBIb X-Developer-Key: i=jorge.marques@analog.com; a=ed25519; pk=NUR1IZZMH0Da3QbJ2tBSznSPVfRpuoWdhBzKGSpAdbg= X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=D4VHKuRj c=1 sm=1 tr=0 ts=68077f00 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=XR8D0OoHHMoA:10 a=gAnH3GRIAAAA:8 a=wI1k2SEZAAAA:8 a=qLcM2r4-lCJhFG8HUqIA:9 a=QEXdDO2ut3YA:10 a=6HWbV-4b7c7AdzY24d_u:22 X-Proofpoint-GUID: sTDtT0KOgEK6r3YGHrK0QDGQU6FcCT_m X-Proofpoint-ORIG-GUID: sTDtT0KOgEK6r3YGHrK0QDGQU6FcCT_m X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1095,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-04-22_05,2025-04-21_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 phishscore=0 impostorscore=0 suspectscore=0 spamscore=0 clxscore=1015 priorityscore=1501 adultscore=0 mlxlogscore=999 bulkscore=0 mlxscore=0 lowpriorityscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2504220087 This adds a new page to document how to use the ad4052 ADC driver. Signed-off-by: Jorge Marques --- Documentation/iio/ad4052.rst | 95 ++++++++++++++++++++++++++++++++++++++++= ++++ MAINTAINERS | 1 + 2 files changed, 96 insertions(+) diff --git a/Documentation/iio/ad4052.rst b/Documentation/iio/ad4052.rst new file mode 100644 index 0000000000000000000000000000000000000000..410aaa437ed5fea6a2924d374fa= 5f816f5754e22 --- /dev/null +++ b/Documentation/iio/ad4052.rst @@ -0,0 +1,95 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +AD4052 driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +ADC driver for Analog Devices Inc. AD4052 and similar devices. +The module name is ``ad4052``. + +Supported devices +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The following chips are supported by this driver: + +* `AD4050 `_ +* `AD4052 `_ +* `AD4056 `_ +* `AD4058 `_ + +Wiring modes +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The ADC uses SPI 4-wire mode, and contain two programmable GPIOs and +a CNV pin. + +The CNV pin is exposed as the ``cnv-gpios`` and triggers a ADC conversion. +GP1 is ADC conversion ready signal and GP0 Threshold event interrupt, both +exposed as interrupts. + +Omit ``cnv-gpios`` and tie CNV and CS together to use the rising edge +of the CS as the CNV signal. + +Device attributes +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The ADC contain only one channels, and the following attributes: + +.. list-table:: Driver attributes + :header-rows: 1 + + * - Attribute + - Description + * - ``in_voltage0_raw`` + - Raw ADC voltage value + * - ``in_voltage0_oversampling_ratio`` + - Enable the device's burst averaging mode to over sample using + the internal sample rate. + * - ``in_voltage0_oversampling_ratio_available`` + - List of available oversampling values. Value 0 disable the burst + averaging mode. + * - ``conversion_frequency`` + - Device internal sample rate used in the burst averaging mode. + * - ``conversion_frequency_available`` + - List of available sample rates. + +Threshold events +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The ADC supports a monitoring mode to raise threshold events. +The driver supports a single interrupt for both rising and falling +readings. + +The feature is enabled/disabled by setting ``thresh_either_en``. +During monitor mode, the device continuously operates in autonomous mode u= ntil +put back in configuration mode, due to this, the device returns busy until= the +feature is disabled. + +Low-power mode +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The device enters low-power mode on idle to save power. +Enabling an event puts the device out of the low-power since the ADC +autonomously samples to assert the event condition. + +SPI offload support +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +To be able to achieve the maximum sample rate, the driver can be used with= the +`AXI SPI Engine`_ to provide SPI offload support. + +.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/ad4052_= ardz/index.html + +When SPI offload is being used, additional attributes are present: + +.. list-table:: Additional attributes + :header-rows: 1 + + * - Attribute + - Description + * - ``in_voltage0_sampling_frequency`` + - Set the sampling frequency. + * - ``in_voltage0_sampling_frequency_available`` + - Get the sampling frequency range. + +The scan type is different when the buffer with offload support is enabled. diff --git a/MAINTAINERS b/MAINTAINERS index 81fbe7176475c48eae03ab04115d4ef5b6299fac..04aa8db44bee418382a2e74cb6b= 1d03a810bd781 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1334,6 +1334,7 @@ M: Jorge Marques S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad4052.yaml +F: Documentation/iio/ad4052.rst =20 ANALOG DEVICES INC AD4130 DRIVER M: Cosmin Tanislav --=20 2.49.0 From nobody Sun Feb 8 22:59:49 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 A4CC927F4F4; Tue, 22 Apr 2025 11:35:45 +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=1745321748; cv=none; b=LfUtZvXx46obiO8rsGnfZljcav8OjKPHEcWAwluL+IC0fH6As0tjXTf9C3Fl9uWviOgcPTytMh0TruzvkQeZfEqcKhkkDQxYsNdLPXWWBKv/dmJWyc/jPlBjTURB3VLRxJ1oF+Y7eQfyhIREElvgqfNT3jCpEv3D+1YApXIBeOQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745321748; c=relaxed/simple; bh=K7JLIEnlHd7CNNSx9ePnmyljb9yiC3gssm9WKJzSCHY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-ID:References: In-Reply-To:To:CC; b=OSRWpLjAKUZgdWH4v2qRhHH5Rzf6tHBqSFnzoWTS39QKpyscPQjTv2E1ZNzJyTcvCf1jtVa5SMfJwPXKtJZex7Pha7shoGPuVekPVyV3FpVKzRlz4sqAPgR8LbuN3eg5TrWrtCu1n+2449Pfg5jHSyZU/ZXAc3WJE1DgJR2Wnu4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none 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=fLg5fbxe; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none 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="fLg5fbxe" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 53MBCH8i026301; Tue, 22 Apr 2025 07:35:29 -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=Fn/Kp Yn3kbdXSSrfdMoKuKRzO8mK51xUucwNMJ5EM+8=; b=fLg5fbxeyVGyqs6f6SAKs CYIVZ0NO1Wb9KXXecdXIUFG0IFKkdWrpGu61WNuWkfaWzBS9zqDDXXMT/fxdLvDO BplJ03hXheNOJ+7eqh9DOdAwPDPFEpwi96IUHVlZbuKFMACvjEAjOP0XvcCtsK3x 32a/XkzyrULkOTu1/lW6A0Na7acLw79eqrSAH9vwcZsR7HRI0g1sl3HCKHv8vSr0 emVCVYJaANv837d6xnT4QHtcdgRsNtcPtFzzB+wnKNPNJ1Su+3j3RsjRFZMJAoxQ ADJFpHLVKevYhYdsbp7KYXeK+wu0cDJSDvHHc8pO+KFNz+k//IVW3cGwUtriGi8F Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4648r6et60-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 22 Apr 2025 07:35:29 -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 53MBZR23050191 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 22 Apr 2025 07:35:27 -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.986.14; Tue, 22 Apr 2025 07:35:27 -0400 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) 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.986.14; Tue, 22 Apr 2025 07:35:27 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 22 Apr 2025 07:35:27 -0400 Received: from HYB-DlYm71t3hSl.ad.analog.com (HYB-DlYm71t3hSl.ad.analog.com [10.44.3.55]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 53MBZ4Qs024350; Tue, 22 Apr 2025 07:35:20 -0400 From: Jorge Marques Date: Tue, 22 Apr 2025 13:34:50 +0200 Subject: [PATCH v2 5/5] iio: adc: add support for ad4052 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID: <20250422-iio-driver-ad4052-v2-5-638af47e9eb3@analog.com> References: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> In-Reply-To: <20250422-iio-driver-ad4052-v2-0-638af47e9eb3@analog.com> To: Jonathan Cameron , Lars-Peter Clausen , Michael Hennerich , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , "Andy Shevchenko" , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= CC: , , , , , Jorge Marques X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1745321704; l=42151; i=jorge.marques@analog.com; s=20250303; h=from:subject:message-id; bh=K7JLIEnlHd7CNNSx9ePnmyljb9yiC3gssm9WKJzSCHY=; b=AfXtVZgCMFXQp+pJlMeox6HxDdW62qrJ/KPwFVY2gGm9o/ht7XB3+rRO9FcqqkH9KYavwGjwO 32ptq9V7tZ5DTAWs9o36BOO3wZxlQABrsSji2CY+9LMmlWizHJEoLaU X-Developer-Key: i=jorge.marques@analog.com; a=ed25519; pk=NUR1IZZMH0Da3QbJ2tBSznSPVfRpuoWdhBzKGSpAdbg= X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: JNUunqnmcRxN1eKvbZzkr0tDJkNG21vT X-Proofpoint-ORIG-GUID: JNUunqnmcRxN1eKvbZzkr0tDJkNG21vT X-Authority-Analysis: v=2.4 cv=d6z1yQjE c=1 sm=1 tr=0 ts=68077f01 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=XR8D0OoHHMoA:10 a=gAnH3GRIAAAA:8 a=rtu05Q2co9eftUu8wvQA:9 a=QEXdDO2ut3YA:10 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1095,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-04-22_05,2025-04-21_02,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1011 mlxscore=0 mlxlogscore=999 impostorscore=0 phishscore=0 bulkscore=0 priorityscore=1501 adultscore=0 lowpriorityscore=0 spamscore=0 suspectscore=0 malwarescore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2502280000 definitions=main-2504220087 The AD4052/AD4058/AD4050/AD4056 are versatile, 16-bit/12-bit, successive approximation register (SAR) analog-to-digital converter (ADC) that enables low-power, high-density data acquisition solutions without sacrificing precision. This ADC offers a unique balance of performance and power efficiency, plus innovative features for seamlessly switching between high-resolution and low-power modes tailored to the immediate needs of the system. The AD4052/AD4058/AD4050/AD4056 are ideal for battery-powered, compact data acquisition and edge sensing applications. Signed-off-by: Jorge Marques --- MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 14 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad4052.c | 1425 ++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 1441 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 04aa8db44bee418382a2e74cb6b1d03a810bd781..56adb540fa172d5729735acbeae= e6c576132cddd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1335,6 +1335,7 @@ S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad4052.yaml F: Documentation/iio/ad4052.rst +F: drivers/iio/adc/ad4052.c =20 ANALOG DEVICES INC AD4130 DRIVER M: Cosmin Tanislav diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ad06cf5567851ee71f1211ec69d59fd5c1857ee5..68f8ce91320ea6db9377b344240= 8598a863ab428 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -55,6 +55,20 @@ config AD4030 To compile this driver as a module, choose M here: the module will be called ad4030. =20 +config AD4052 + tristate "Analog Devices AD4052 Driver" + depends on SPI + select SPI_OFFLOAD + select IIO_BUFFER + select IIO_BUFFER_DMAENGINE + select REGMAP_SPI + help + Say yes here to build support for Analog Devices AD4052 SPI analog + to digital converters (ADC). + + To compile this driver as a module, choose M here: the module will be + called ad4052. + config AD4130 tristate "Analog Device AD4130 ADC Driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 07d4b832c42e6352f2a4c956295308f007af0f45..edc0d1809f0cf9fcd65ee2cf722= 18d0dc3ecacbf 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_AB8500_GPADC) +=3D ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) +=3D ad_sigma_delta.o obj-$(CONFIG_AD4000) +=3D ad4000.o obj-$(CONFIG_AD4030) +=3D ad4030.o +obj-$(CONFIG_AD4052) +=3D ad4052.o obj-$(CONFIG_AD4130) +=3D ad4130.o obj-$(CONFIG_AD4695) +=3D ad4695.o obj-$(CONFIG_AD4851) +=3D ad4851.o diff --git a/drivers/iio/adc/ad4052.c b/drivers/iio/adc/ad4052.c new file mode 100644 index 0000000000000000000000000000000000000000..f412f0884bab4f500091f6c7ca7= 61967c8f6e3b6 --- /dev/null +++ b/drivers/iio/adc/ad4052.c @@ -0,0 +1,1425 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices AD4052 SPI ADC driver + * + * Copyright 2025 Analog Devices Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD4052_REG_INTERFACE_CONFIG_A 0x00 +#define AD4052_REG_DEVICE_CONFIG 0x02 +#define AD4052_REG_PROD_ID_1 0x05 +#define AD4052_REG_DEVICE_GRADE 0x06 +#define AD4052_REG_SCRATCH_PAD 0x0A +#define AD4052_REG_VENDOR_H 0x0D +#define AD4052_REG_STREAM_MODE 0x0E +#define AD4052_REG_INTERFACE_STATUS 0x11 +#define AD4052_REG_MODE_SET 0x20 +#define AD4052_REG_ADC_MODES 0x21 +#define AD4052_REG_AVG_CONFIG 0x23 +#define AD4052_REG_GP_CONF 0x24 +#define AD4052_REG_INTR_CONF 0x25 +#define AD4052_REG_TIMER_CONFIG 0x27 +#define AD4052_REG_MAX_LIMIT 0x29 +#define AD4052_REG_MIN_LIMIT 0x2B +#define AD4052_REG_MAX_HYST 0x2C +#define AD4052_REG_MIN_HYST 0x2D +#define AD4052_REG_MON_VAL 0x2F +#define AD4052_REG_FUSE_CRC 0x40 +#define AD4052_REG_DEVICE_STATUS 0x41 +#define AD4052_REG_MIN_SAMPLE 0x45 +#define AD4052_MAX_REG 0x45 +#define AD4052_ADC_MODES_MODE_MSK GENMASK(1, 0) +#define AD4052_GP_CONF_MODE_MSK_0 GENMASK(2, 0) +#define AD4052_GP_CONF_MODE_MSK_1 GENMASK(6, 4) +#define AD4052_INTR_CONF_EN_MSK_0 GENMASK(1, 0) +#define AD4052_INTR_CONF_EN_MSK_1 GENMASK(5, 4) +#define AD4052_MODE_SET_ENTER_ADC BIT(0) +#define AD4052_ADC_MODES_DATA_FORMAT BIT(7) +#define AD4052_DEVICE_CONFIG_POWER_MODE_MSK GENMASK(1, 0) +#define AD4052_DEVICE_CONFIG_LOW_POWER_MODE 3 +#define AD4052_DEVICE_STATUS_DEVICE_RESET BIT(6) +#define AD4052_TIMER_CONFIG_FS_MASK GENMASK(7, 4) +#define AD4052_TIMER_CONFIG_300KSPS 0x2 + +#define AD4052_SPI_VENDOR 0x0456 + +#define AD4050_MAX_AVG 0x7 +#define AD4052_MAX_AVG 0xB +#define AD4052_MAX_RATE(x) ((x) =3D=3D AD4052_500KSPS ? 500000 : 2000000) +#define AD4052_FS_OFFSET(g) ((g) =3D=3D AD4052_500KSPS ? 2 : 0) +#define AD4052_FS(g) ((&ad4052_conversion_freqs[AD4052_FS_OFFSET(g)])) +#define AD4052_FS_LEN(g) (ARRAY_SIZE(ad4052_conversion_freqs) - (AD4052_FS= _OFFSET(g))) +#define AD4052_T_CNVH_NS 10 + +enum ad4052_grade { + AD4052_2MSPS, + AD4052_500KSPS, +}; + +enum ad4052_operation_mode { + AD4052_SAMPLE_MODE =3D 0, + AD4052_BURST_AVERAGING_MODE =3D 1, + AD4052_MONITOR_MODE =3D 3, +}; + +enum ad4052_gp_mode { + AD4052_GP_DISABLED, + AD4052_GP_INTR, + AD4052_GP_DRDY, +}; + +enum ad4052_interrupt_en { + AD4052_INTR_EN_NEITHER, + AD4052_INTR_EN_MIN, + AD4052_INTR_EN_MAX, + AD4052_INTR_EN_EITHER, +}; + +struct ad4052_chip_info { + const struct iio_chan_spec channels[1]; + const struct iio_chan_spec offload_channels[1]; + const char *name; + u16 prod_id; + u8 max_avg; +}; + +enum { + AD4052_SCAN_TYPE_SAMPLE, + AD4052_SCAN_TYPE_BURST_AVG, + AD4052_SCAN_TYPE_OFFLOAD_SAMPLE, + AD4052_SCAN_TYPE_OFFLOAD_BURST_AVG, +}; + +static const struct iio_scan_type ad4052_scan_type_12_s[] =3D { + [AD4052_SCAN_TYPE_SAMPLE] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_BURST_AVG] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_OFFLOAD_SAMPLE] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_OFFLOAD_BURST_AVG] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, +}; + +static const struct iio_scan_type ad4052_scan_type_16_s[] =3D { + [AD4052_SCAN_TYPE_SAMPLE] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_BURST_AVG] =3D { + .sign =3D 's', + .realbits =3D 24, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_OFFLOAD_SAMPLE] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, + [AD4052_SCAN_TYPE_OFFLOAD_BURST_AVG] =3D { + .sign =3D 's', + .realbits =3D 24, + .storagebits =3D 32, + .endianness =3D IIO_CPU, + }, +}; + +struct ad4052_state { + const struct ad4052_bus_ops *ops; + const struct ad4052_chip_info *chip; + enum ad4052_operation_mode mode; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + struct spi_device *spi; + struct spi_transfer offload_xfer; + struct spi_message offload_msg; + struct pwm_device *cnv_pwm; + struct spi_transfer xfer; + struct spi_message msg; + struct gpio_desc *cnv_gp; + struct completion completion; + struct regmap *regmap; + u16 oversampling_frequency; + u16 events_frequency; + bool wait_event; + int gp1_irq; + u8 data_format; + u8 grade; + union { + __be16 d16; + __be32 d32; + } __aligned(IIO_DMA_MINALIGN); + u8 buf_reset_pattern[18]; +}; + +static const struct regmap_range ad4052_regmap_rd_ranges[] =3D { + regmap_reg_range(AD4052_REG_INTERFACE_CONFIG_A, AD4052_REG_DEVICE_GRADE), + regmap_reg_range(AD4052_REG_SCRATCH_PAD, AD4052_REG_INTERFACE_STATUS), + regmap_reg_range(AD4052_REG_MODE_SET, AD4052_REG_MON_VAL), + regmap_reg_range(AD4052_REG_FUSE_CRC, AD4052_REG_MIN_SAMPLE), +}; + +static const struct regmap_access_table ad4052_regmap_rd_table =3D { + .yes_ranges =3D ad4052_regmap_rd_ranges, + .n_yes_ranges =3D ARRAY_SIZE(ad4052_regmap_rd_ranges), +}; + +static const struct regmap_range ad4052_regmap_wr_ranges[] =3D { + regmap_reg_range(AD4052_REG_INTERFACE_CONFIG_A, AD4052_REG_DEVICE_CONFIG), + regmap_reg_range(AD4052_REG_SCRATCH_PAD, AD4052_REG_SCRATCH_PAD), + regmap_reg_range(AD4052_REG_STREAM_MODE, AD4052_REG_INTERFACE_STATUS), + regmap_reg_range(AD4052_REG_MODE_SET, AD4052_REG_MON_VAL), + regmap_reg_range(AD4052_REG_FUSE_CRC, AD4052_REG_DEVICE_STATUS), +}; + +static const struct regmap_access_table ad4052_regmap_wr_table =3D { + .yes_ranges =3D ad4052_regmap_wr_ranges, + .n_yes_ranges =3D ARRAY_SIZE(ad4052_regmap_wr_ranges), +}; + +static const struct iio_event_spec ad4052_events[] =3D { + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_EITHER, + .mask_shared_by_all =3D BIT(IIO_EV_INFO_ENABLE) + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_RISING, + .mask_shared_by_all =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_HYSTERESIS) + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_FALLING, + .mask_shared_by_all =3D BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_HYSTERESIS) + } +}; + +static const char *const ad4052_conversion_freqs[] =3D { + "2000000", "1000000", "300000", "100000", "33300", + "10000", "3000", "500", "333", "250", "200", + "166", "140", "124", "111", +}; + +static int ad4052_conversion_frequency_set(struct ad4052_state *st, u8 val) +{ + val +=3D AD4052_FS_OFFSET(st->grade); + return regmap_write(st->regmap, AD4052_REG_TIMER_CONFIG, + FIELD_PREP(AD4052_TIMER_CONFIG_FS_MASK, val)); +} + +static int ad4052_oversampling_frequency_get(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + + return st->oversampling_frequency - AD4052_FS_OFFSET(st->grade); +} + +static int ad4052_oversampling_frequency_set(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int val) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + val +=3D AD4052_FS_OFFSET(st->grade); + st->oversampling_frequency =3D val; + + iio_device_release_direct(indio_dev); + return 0; +} + +static ssize_t ad4052_events_frequency_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ad4052_state *st =3D iio_priv(dev_to_iio_dev(dev)); + + return sprintf(buf, "%s\n", ad4052_conversion_freqs[st->events_frequency]= ); +} + +static ssize_t ad4052_events_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 ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + ret =3D __sysfs_match_string(AD4052_FS(st->grade), + AD4052_FS_LEN(st->grade), buf); + if (ret >=3D 0) + st->events_frequency =3D ret; + + iio_device_release_direct(indio_dev); + + return ret < 0 ? ret : len; +} + +static ssize_t ad4052_events_frequency_available_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ad4052_state *st =3D iio_priv(dev_to_iio_dev(dev)); + int len =3D 0; + + for (u8 i =3D AD4052_FS_OFFSET(st->grade); + i < AD4052_FS_LEN(st->grade); i++) + len +=3D sprintf(buf + len, "%s ", ad4052_conversion_freqs[i]); + + return sprintf(buf + len, "\n") + len; +} + +static IIO_DEVICE_ATTR(sampling_frequency, 0644, + ad4052_events_frequency_show, + ad4052_events_frequency_store, 0); + +static IIO_DEVICE_ATTR(sampling_frequency_available, 0444, + ad4052_events_frequency_available_show, + NULL, 0); + +static struct attribute *ad4052_event_attributes[] =3D { + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ad4052_event_attribute_group =3D { + .attrs =3D ad4052_event_attributes, +}; + +static const struct iio_enum AD4052_500KSPS_conversion_freq_enum =3D { + .items =3D AD4052_FS(AD4052_500KSPS), + .num_items =3D AD4052_FS_LEN(AD4052_500KSPS), + .set =3D ad4052_oversampling_frequency_set, + .get =3D ad4052_oversampling_frequency_get, +}; + +static const struct iio_enum AD4052_2MSPS_conversion_freq_enum =3D { + .items =3D AD4052_FS(AD4052_2MSPS), + .num_items =3D AD4052_FS_LEN(AD4052_2MSPS), + .set =3D ad4052_oversampling_frequency_set, + .get =3D ad4052_oversampling_frequency_get, +}; + +#define AD4052_EXT_INFO(grade) \ +static struct iio_chan_spec_ext_info grade##_ext_info[] =3D { \ + IIO_ENUM("oversampling_frequency", IIO_SHARED_BY_ALL, \ + &grade##_conversion_freq_enum), \ + IIO_ENUM_AVAILABLE("oversampling_frequency", IIO_SHARED_BY_ALL, \ + &grade##_conversion_freq_enum), \ + { } \ +} + +AD4052_EXT_INFO(AD4052_2MSPS); +AD4052_EXT_INFO(AD4052_500KSPS); + +#define AD4052_CHAN(bits, grade) { \ + .type =3D IIO_VOLTAGE, \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), \ + .indexed =3D 1, \ + .channel =3D 0, \ + .event_spec =3D ad4052_events, \ + .num_event_specs =3D ARRAY_SIZE(ad4052_events), \ + .has_ext_scan_type =3D 1, \ + .ext_scan_type =3D ad4052_scan_type_##bits##_s, \ + .num_ext_scan_type =3D ARRAY_SIZE(ad4052_scan_type_##bits##_s), \ + .ext_info =3D grade##_ext_info, \ +} + +#define AD4052_OFFLOAD_CHAN(bits, grade) { \ + .type =3D IIO_VOLTAGE, \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_type_available =3D BIT(IIO_CHAN_INFO_OVERSAMPLING_RA= TIO), \ + .indexed =3D 1, \ + .channel =3D 0, \ + .event_spec =3D ad4052_events, \ + .num_event_specs =3D ARRAY_SIZE(ad4052_events), \ + .has_ext_scan_type =3D 1, \ + .ext_scan_type =3D ad4052_scan_type_##bits##_s, \ + .num_ext_scan_type =3D ARRAY_SIZE(ad4052_scan_type_##bits##_s), \ + .ext_info =3D grade##_ext_info, \ +} + +static const struct ad4052_chip_info ad4050_chip_info =3D { + .name =3D "ad4050", + .channels =3D { AD4052_CHAN(12, AD4052_2MSPS) }, + .offload_channels =3D { AD4052_OFFLOAD_CHAN(12, AD4052_2MSPS) }, + .prod_id =3D 0x70, + .max_avg =3D AD4050_MAX_AVG, +}; + +static const struct ad4052_chip_info ad4052_chip_info =3D { + .name =3D "ad4052", + .channels =3D { AD4052_CHAN(16, AD4052_2MSPS) }, + .offload_channels =3D { AD4052_OFFLOAD_CHAN(16, AD4052_2MSPS) }, + .prod_id =3D 0x72, + .max_avg =3D AD4052_MAX_AVG, +}; + +static const struct ad4052_chip_info ad4056_chip_info =3D { + .name =3D "ad4056", + .channels =3D { AD4052_CHAN(12, AD4052_500KSPS) }, + .offload_channels =3D { AD4052_OFFLOAD_CHAN(12, AD4052_500KSPS) }, + .prod_id =3D 0x76, + .max_avg =3D AD4050_MAX_AVG, +}; + +static const struct ad4052_chip_info ad4058_chip_info =3D { + .name =3D "ad4058", + .channels =3D { AD4052_CHAN(16, AD4052_500KSPS) }, + .offload_channels =3D { AD4052_OFFLOAD_CHAN(16, AD4052_500KSPS) }, + .prod_id =3D 0x78, + .max_avg =3D AD4052_MAX_AVG, +}; + +static void ad4052_update_xfer_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + struct spi_transfer *xfer =3D &st->xfer; + + scan_type =3D iio_get_current_scan_type(indio_dev, chan); + + if (IS_ERR(scan_type)) + return; + + xfer->bits_per_word =3D scan_type->realbits; + xfer->len =3D BITS_TO_BYTES(scan_type->storagebits); +} + +static int ad4052_update_xfer_offload(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + struct spi_transfer *xfer =3D &st->xfer; + + scan_type =3D iio_get_current_scan_type(indio_dev, chan); + + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + xfer =3D &st->offload_xfer; + xfer->bits_per_word =3D scan_type->realbits; + xfer->len =3D BITS_TO_BYTES(scan_type->storagebits); + + spi_message_init_with_transfers(&st->offload_msg, &st->offload_xfer, 1); + st->offload_msg.offload =3D st->offload; + + return spi_optimize_message(st->spi, &st->offload_msg); +} + +static int ad4052_set_oversampling_ratio(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + unsigned int val) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + if ((val) < 1 || (val) > BIT(st->chip->max_avg + 1)) + return -EINVAL; + + /* 1 disables oversampling */ + if (val =3D=3D 1) { + st->mode =3D AD4052_SAMPLE_MODE; + } else { + val =3D ilog2(val); + st->mode =3D AD4052_BURST_AVERAGING_MODE; + ret =3D regmap_write(st->regmap, AD4052_REG_AVG_CONFIG, val - 1); + if (ret) + return ret; + } + + ad4052_update_xfer_raw(indio_dev, chan); + + return 0; +} + +static int ad4052_get_oversampling_ratio(struct ad4052_state *st, + unsigned int *val) +{ + int ret; + + if (st->mode =3D=3D AD4052_SAMPLE_MODE) { + *val =3D 1; + return 0; + } + + ret =3D regmap_read(st->regmap, AD4052_REG_AVG_CONFIG, val); + if (ret) + return ret; + + *val =3D BIT(*val + 1); + + return 0; +} + +static int ad4052_check_ids(struct ad4052_state *st) +{ + int ret; + u16 val; + + ret =3D regmap_bulk_read(st->regmap, AD4052_REG_PROD_ID_1, &st->d16, + sizeof(st->d16)); + if (ret) + return ret; + + val =3D be16_to_cpu(st->d16); + if (val !=3D st->chip->prod_id) + dev_info(&st->spi->dev, + "Production ID x%x does not match known values", val); + + ret =3D regmap_bulk_read(st->regmap, AD4052_REG_VENDOR_H, &st->d16, + sizeof(st->d16)); + if (ret) + return ret; + + val =3D be16_to_cpu(st->d16); + if (val !=3D AD4052_SPI_VENDOR) + return -ENODEV; + + return 0; +} + +static int ad4052_exit_command(struct ad4052_state *st) +{ + struct spi_device *spi =3D st->spi; + const u8 val =3D 0xA8; + + return spi_write(spi, &val, 1); +} + +static int ad4052_set_operation_mode(struct ad4052_state *st, + enum ad4052_operation_mode mode) +{ + int ret; + + if (mode =3D=3D AD4052_BURST_AVERAGING_MODE) { + ret =3D ad4052_conversion_frequency_set(st, st->oversampling_frequency); + if (ret) + return ret; + } + + ret =3D regmap_update_bits(st->regmap, AD4052_REG_ADC_MODES, + AD4052_ADC_MODES_MODE_MSK, mode); + if (ret) + return ret; + + return regmap_write(st->regmap, AD4052_REG_MODE_SET, + AD4052_MODE_SET_ENTER_ADC); +} + +static int ad4052_set_sampling_freq(struct ad4052_state *st, unsigned int = freq) +{ + struct pwm_state pwm_st; + + if (freq <=3D 0 || freq > AD4052_MAX_RATE(st->grade)) + return -EINVAL; + + pwm_get_state(st->cnv_pwm, &pwm_st); + pwm_st.period =3D DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq); + return pwm_apply_might_sleep(st->cnv_pwm, &pwm_st); +} + +static int ad4052_soft_reset(struct ad4052_state *st) +{ + int ret; + + memset(st->buf_reset_pattern, 0xFF, sizeof(st->buf_reset_pattern)); + for (int i =3D 0; i < 3; i++) + st->buf_reset_pattern[6 * (i + 1) - 1] =3D 0xFE; + + ret =3D spi_write(st->spi, st->buf_reset_pattern, + sizeof(st->buf_reset_pattern)); + if (ret) + return ret; + + /* Wait AD4052 reset delay */ + fsleep(5000); + + return 0; +} + +static int ad4052_setup(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + + scan_type =3D iio_get_current_scan_type(indio_dev, chan); + + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + u8 val =3D FIELD_PREP(AD4052_GP_CONF_MODE_MSK_0, AD4052_GP_INTR) | + FIELD_PREP(AD4052_GP_CONF_MODE_MSK_1, AD4052_GP_DRDY); + int ret; + + ret =3D regmap_update_bits(st->regmap, AD4052_REG_GP_CONF, + AD4052_GP_CONF_MODE_MSK_1 | AD4052_GP_CONF_MODE_MSK_0, + val); + if (ret) + return ret; + + val =3D FIELD_PREP(AD4052_INTR_CONF_EN_MSK_0, (AD4052_INTR_EN_EITHER)) | + FIELD_PREP(AD4052_INTR_CONF_EN_MSK_1, (AD4052_INTR_EN_NEITHER)); + + ret =3D regmap_update_bits(st->regmap, AD4052_REG_INTR_CONF, + AD4052_INTR_CONF_EN_MSK_0 | AD4052_INTR_CONF_EN_MSK_1, + val); + if (ret) + return ret; + + val =3D 0; + if (scan_type->sign =3D=3D 's') + val |=3D AD4052_ADC_MODES_DATA_FORMAT; + + st->data_format =3D val; + + if (st->grade =3D=3D AD4052_500KSPS) { + ret =3D regmap_write(st->regmap, AD4052_REG_TIMER_CONFIG, + FIELD_PREP(AD4052_TIMER_CONFIG_FS_MASK, + AD4052_TIMER_CONFIG_300KSPS)); + if (ret) + return ret; + } + + return regmap_write(st->regmap, AD4052_REG_ADC_MODES, val); +} + +static irqreturn_t ad4052_irq_handler_thresh(int irq, void *private) +{ + struct iio_dev *indio_dev =3D private; + + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_EITHER), + iio_get_time_ns(indio_dev)); + + return IRQ_HANDLED; +} + +static irqreturn_t ad4052_irq_handler_drdy(int irq, void *private) +{ + struct ad4052_state *st =3D private; + + complete(&st->completion); + + return IRQ_HANDLED; +} + +static int ad4052_request_irq(struct iio_dev *indio_dev) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + struct device *dev =3D &st->spi->dev; + int ret =3D 0; + + ret =3D fwnode_irq_get_byname(dev_fwnode(&st->spi->dev), "gp0"); + if (ret <=3D 0) + return ret ? ret : -EINVAL; + + ret =3D devm_request_threaded_irq(dev, ret, NULL, + ad4052_irq_handler_thresh, + IRQF_ONESHOT, indio_dev->name, + indio_dev); + if (ret) + return ret; + + ret =3D fwnode_irq_get_byname(dev_fwnode(&st->spi->dev), "gp1"); + if (ret <=3D 0) + return ret ? ret : -EINVAL; + + st->gp1_irq =3D ret; + return devm_request_threaded_irq(dev, ret, NULL, + ad4052_irq_handler_drdy, + IRQF_ONESHOT, indio_dev->name, + st); +} + +static const int ad4052_oversampling_avail[] =3D { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, +}; + +static int ad4052_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, const int **vals, + int *type, int *len, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals =3D ad4052_oversampling_avail; + *len =3D ARRAY_SIZE(ad4052_oversampling_avail); + *type =3D IIO_VAL_INT; + + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int __ad4052_read_chan_raw(struct ad4052_state *st, int *val) +{ + struct spi_device *spi =3D st->spi; + int ret; + struct spi_transfer t_cnv =3D { + .len =3D 0 + }; + + reinit_completion(&st->completion); + + if (st->cnv_gp) { + gpiod_set_value_cansleep(st->cnv_gp, 1); + gpiod_set_value_cansleep(st->cnv_gp, 0); + } else { + ret =3D spi_sync_transfer(spi, &t_cnv, 1); + if (ret) + return ret; + } + /* + * Single sample read should be used only for oversampling and + * sampling frequency pairs that take less than 1 sec. + */ + ret =3D wait_for_completion_timeout(&st->completion, + msecs_to_jiffies(1000)); + if (!ret) + return -ETIMEDOUT; + + ret =3D spi_sync_transfer(spi, &st->xfer, 1); + if (ret) + return ret; + + if (st->xfer.len =3D=3D 2) { + *val =3D be16_to_cpu(st->d16); + if (st->data_format & AD4052_ADC_MODES_DATA_FORMAT) + *val =3D sign_extend32(*val, 15); + } else { + *val =3D be32_to_cpu(st->d32); + if (st->data_format & AD4052_ADC_MODES_DATA_FORMAT) + *val =3D sign_extend32(*val, 23); + } + + return ret; +} + +static int ad4052_read_chan_raw(struct iio_dev *indio_dev, int *val) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + ret =3D pm_runtime_resume_and_get(&st->spi->dev); + if (ret) + return ret; + + ret =3D ad4052_set_operation_mode(st, st->mode); + if (ret) + goto out_error; + + ret =3D __ad4052_read_chan_raw(st, val); + if (ret) + goto out_error; + + ret =3D ad4052_exit_command(st); + +out_error: + pm_runtime_mark_last_busy(&st->spi->dev); + pm_runtime_put_autosuspend(&st->spi->dev); + return ret; +} + +static int ad4052_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + struct pwm_state pwm_st; + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret =3D ad4052_read_chan_raw(indio_dev, val); + if (ret) + goto out_release; + ret =3D IIO_VAL_INT; + break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + ret =3D ad4052_get_oversampling_ratio(st, val); + if (ret) + goto out_release; + ret =3D IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret =3D pwm_get_state_hw(st->cnv_pwm, &pwm_st); + if (ret) + goto out_release; + + if (!pwm_st.enabled) + pwm_get_state(st->cnv_pwm, &pwm_st); + + *val =3D DIV_ROUND_UP_ULL(NSEC_PER_SEC, pwm_st.period); + + ret =3D IIO_VAL_INT; + break; + default: + ret =3D -EINVAL; + } + +out_release: + iio_device_release_direct(indio_dev); + return ret; +} + +static int ad4052_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long info) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + switch (info) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + ret =3D ad4052_set_oversampling_ratio(indio_dev, chan, val); + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret =3D ad4052_set_sampling_freq(st, val); + break; + default: + ret =3D -EINVAL; + } + + iio_device_release_direct(indio_dev); + return ret; +} + +static int ad4052_monitor_mode_enable(struct ad4052_state *st) +{ + int ret; + + ret =3D pm_runtime_resume_and_get(&st->spi->dev); + if (ret) + return ret; + + ret =3D ad4052_conversion_frequency_set(st, st->events_frequency); + if (ret) + goto out_error; + + ret =3D ad4052_set_operation_mode(st, AD4052_MONITOR_MODE); + if (ret) + goto out_error; + + return ret; +out_error: + pm_runtime_mark_last_busy(&st->spi->dev); + pm_runtime_put_autosuspend(&st->spi->dev); + return ret; +} + +static int ad4052_monitor_mode_disable(struct ad4052_state *st) +{ + int ret; + + pm_runtime_mark_last_busy(&st->spi->dev); + pm_runtime_put_autosuspend(&st->spi->dev); + + ret =3D ad4052_exit_command(st); + + if (ret) + pm_runtime_resume_and_get(&st->spi->dev); + + return ret; +} + +static int ad4052_read_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + + return st->wait_event; +} + +static int ad4052_write_event_config(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + bool state) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret =3D -EBUSY; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event =3D=3D state) { + iio_device_release_direct(indio_dev); + return 0; + } + + if (state) + ret =3D ad4052_monitor_mode_enable(st); + else + ret =3D ad4052_monitor_mode_disable(st); + + if (!ret) + st->wait_event =3D state; + + iio_device_release_direct(indio_dev); + return ret; +} + +static int ad4052_read_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int *val, + int *val2) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + u8 reg, size =3D 1; + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + switch (info) { + case IIO_EV_INFO_VALUE: + if (dir =3D=3D IIO_EV_DIR_RISING) + reg =3D AD4052_REG_MAX_LIMIT; + else + reg =3D AD4052_REG_MIN_LIMIT; + size =3D 2; + break; + case IIO_EV_INFO_HYSTERESIS: + if (dir =3D=3D IIO_EV_DIR_RISING) + reg =3D AD4052_REG_MAX_HYST; + else + reg =3D AD4052_REG_MIN_HYST; + break; + default: + ret =3D -EINVAL; + goto out_release; + } + + ret =3D regmap_bulk_read(st->regmap, reg, &st->d32, size); + if (ret) + goto out_release; + + if (reg =3D=3D AD4052_REG_MAX_LIMIT || reg =3D=3D AD4052_REG_MIN_LIMIT) { + *val =3D be16_to_cpu(st->d16); + if (st->data_format & AD4052_ADC_MODES_DATA_FORMAT) + *val =3D sign_extend32(*val, 11); + } else { + *val =3D be32_to_cpu(st->d32); + } + +out_release: + iio_device_release_direct(indio_dev); + return ret ? ret : IIO_VAL_INT; +} + +static int ad4052_write_event_value(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, int val, + int val2) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret =3D -EINVAL; + u8 reg, size =3D 1; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + switch (type) { + case IIO_EV_TYPE_THRESH: + switch (info) { + case IIO_EV_INFO_VALUE: + if (st->data_format & AD4052_ADC_MODES_DATA_FORMAT) { + if (val > 2047 || val < -2048) + goto out_release; + } else if (val > 4095 || val < 0) { + goto out_release; + } + if (dir =3D=3D IIO_EV_DIR_RISING) + reg =3D AD4052_REG_MAX_LIMIT; + else + reg =3D AD4052_REG_MIN_LIMIT; + size =3D 2; + st->d16 =3D cpu_to_be16(val); + break; + case IIO_EV_INFO_HYSTERESIS: + if (val & BIT(7)) + goto out_release; + if (dir =3D=3D IIO_EV_DIR_RISING) + reg =3D AD4052_REG_MAX_HYST; + else + reg =3D AD4052_REG_MIN_HYST; + st->d16 =3D cpu_to_be16(val >> 8); + break; + default: + goto out_release; + } + break; + default: + goto out_release; + } + + ret =3D regmap_bulk_write(st->regmap, reg, &st->d16, size); + +out_release: + iio_device_release_direct(indio_dev); + return ret; +} + +static int ad4052_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + struct spi_offload_trigger_config config =3D { + .type =3D SPI_OFFLOAD_TRIGGER_DATA_READY, + }; + int ret; + + if (st->wait_event) + return -EBUSY; + + ret =3D pm_runtime_resume_and_get(&st->spi->dev); + if (ret) + return ret; + + ret =3D ad4052_set_operation_mode(st, st->mode); + if (ret) + goto out_error; + + ret =3D ad4052_update_xfer_offload(indio_dev, indio_dev->channels); + if (ret) + goto out_error; + + /* SPI Offload handles the data ready irq */ + disable_irq(st->gp1_irq); + + ret =3D spi_offload_trigger_enable(st->offload, st->offload_trigger, + &config); + if (ret) + goto out_offload_error; + + ret =3D pwm_enable(st->cnv_pwm); + if (ret) + goto out_pwm_error; + + return 0; + +out_pwm_error: + spi_offload_trigger_disable(st->offload, st->offload_trigger); +out_offload_error: + enable_irq(st->gp1_irq); + spi_unoptimize_message(&st->offload_msg); + ad4052_exit_command(st); +out_error: + pm_runtime_mark_last_busy(&st->spi->dev); + pm_runtime_put_autosuspend(&st->spi->dev); + + return ret; +} + +static int ad4052_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + pwm_disable(st->cnv_pwm); + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + spi_unoptimize_message(&st->offload_msg); + enable_irq(st->gp1_irq); + + ret =3D ad4052_exit_command(st); + + pm_runtime_mark_last_busy(&st->spi->dev); + pm_runtime_put_autosuspend(&st->spi->dev); + + return ret; +} + +static const struct iio_buffer_setup_ops ad4052_buffer_setup_ops =3D { + .postenable =3D &ad4052_buffer_postenable, + .predisable =3D &ad4052_buffer_predisable, +}; + +static int ad4052_debugfs_reg_access(struct iio_dev *indio_dev, unsigned i= nt reg, + unsigned int writeval, unsigned int *readval) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + int ret; + + if (!iio_device_claim_direct(indio_dev)) + return -EBUSY; + + if (st->wait_event) { + iio_device_release_direct(indio_dev); + return -EBUSY; + } + + if (readval) + ret =3D regmap_read(st->regmap, reg, readval); + else + ret =3D regmap_write(st->regmap, reg, writeval); + + iio_device_release_direct(indio_dev); + return ret; +} + +static int ad4052_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + + if (iio_buffer_enabled(indio_dev)) + return st->mode =3D=3D AD4052_BURST_AVERAGING_MODE ? + AD4052_SCAN_TYPE_OFFLOAD_BURST_AVG : + AD4052_SCAN_TYPE_OFFLOAD_SAMPLE; + + return st->mode =3D=3D AD4052_BURST_AVERAGING_MODE ? + AD4052_SCAN_TYPE_BURST_AVG : + AD4052_SCAN_TYPE_SAMPLE; +} + +static const struct iio_info ad4052_info =3D { + .read_raw =3D ad4052_read_raw, + .write_raw =3D ad4052_write_raw, + .read_avail =3D ad4052_read_avail, + .read_event_config =3D &ad4052_read_event_config, + .write_event_config =3D &ad4052_write_event_config, + .read_event_value =3D &ad4052_read_event_value, + .write_event_value =3D &ad4052_write_event_value, + .event_attrs =3D &ad4052_event_attribute_group, + .get_current_scan_type =3D &ad4052_get_current_scan_type, + .debugfs_reg_access =3D &ad4052_debugfs_reg_access, +}; + +static const struct regmap_config ad4052_regmap_config =3D { + .name =3D "ad4052", + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D AD4052_MAX_REG, + .rd_table =3D &ad4052_regmap_rd_table, + .wr_table =3D &ad4052_regmap_wr_table, + .read_flag_mask =3D BIT(7), + .can_sleep =3D true, +}; + +static const struct spi_offload_config ad4052_offload_config =3D { + .capability_flags =3D SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + +static void ad4052_pwm_disable(void *pwm) +{ + pwm_disable(pwm); +} + +static bool ad4052_offload_trigger_match(struct spi_offload_trigger *trigg= er, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + return type =3D=3D SPI_OFFLOAD_TRIGGER_DATA_READY; +} + +static const struct spi_offload_trigger_ops ad4052_offload_trigger_ops =3D= { + .match =3D ad4052_offload_trigger_match, +}; + +static int ad4052_request_offload(struct iio_dev *indio_dev) +{ + struct ad4052_state *st =3D iio_priv(indio_dev); + struct device *dev =3D &st->spi->dev; + struct dma_chan *rx_dma; + struct spi_offload_trigger_info trigger_info =3D { + .fwnode =3D dev_fwnode(dev), + .ops =3D &ad4052_offload_trigger_ops, + .priv =3D st, + }; + struct pwm_state pwm_st; + int ret; + + indio_dev->setup_ops =3D &ad4052_buffer_setup_ops; + + ret =3D devm_spi_offload_trigger_register(dev, &trigger_info); + if (ret) + return dev_err_probe(dev, ret, + "failed to register offload trigger\n"); + + st->offload_trigger =3D devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_DATA_READY); + if (IS_ERR(st->offload_trigger)) + return PTR_ERR(st->offload_trigger); + + st->cnv_pwm =3D devm_pwm_get(dev, NULL); + if (IS_ERR(st->cnv_pwm)) + return dev_err_probe(dev, PTR_ERR(st->cnv_pwm), + "failed to get CNV PWM\n"); + + pwm_init_state(st->cnv_pwm, &pwm_st); + + pwm_st.enabled =3D false; + pwm_st.duty_cycle =3D AD4052_T_CNVH_NS * 2; + pwm_st.period =3D DIV_ROUND_UP_ULL(NSEC_PER_SEC, + AD4052_MAX_RATE(st->grade)); + + ret =3D pwm_apply_might_sleep(st->cnv_pwm, &pwm_st); + if (ret) + return dev_err_probe(dev, ret, "failed to apply CNV PWM\n"); + + ret =3D devm_add_action_or_reset(dev, ad4052_pwm_disable, st->cnv_pwm); + if (ret) + return ret; + + rx_dma =3D devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return PTR_ERR(rx_dma); + + return devm_iio_dmaengine_buffer_setup_with_handle(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); +} + +static int ad4052_probe(struct spi_device *spi) +{ + const struct ad4052_chip_info *chip; + struct device *dev =3D &spi->dev; + struct iio_dev *indio_dev; + struct ad4052_state *st; + int ret =3D 0; + + chip =3D spi_get_device_match_data(spi); + if (!chip) + return dev_err_probe(dev, -ENODEV, + "Could not find chip info data\n"); + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st =3D iio_priv(indio_dev); + st->spi =3D spi; + spi_set_drvdata(spi, st); + init_completion(&st->completion); + + st->regmap =3D devm_regmap_init_spi(spi, &ad4052_regmap_config); + if (IS_ERR(st->regmap)) + return dev_err_probe(dev, PTR_ERR(st->regmap), + "Failed to initialize regmap\n"); + + st->mode =3D AD4052_SAMPLE_MODE; + st->wait_event =3D false; + st->chip =3D chip; + st->grade =3D chip->prod_id <=3D 0x75 ? AD4052_2MSPS : AD4052_500KSPS; + st->oversampling_frequency =3D AD4052_FS_OFFSET(st->grade); + st->events_frequency =3D AD4052_FS_OFFSET(st->grade); + + st->cnv_gp =3D devm_gpiod_get_optional(dev, "cnv", GPIOD_OUT_LOW); + if (IS_ERR(st->cnv_gp)) + return dev_err_probe(dev, PTR_ERR(st->cnv_gp), + "Failed to get cnv gpio\n"); + + indio_dev->modes =3D INDIO_BUFFER_HARDWARE | INDIO_DIRECT_MODE; + indio_dev->num_channels =3D 1; + indio_dev->info =3D &ad4052_info; + indio_dev->name =3D chip->name; + + st->offload =3D devm_spi_offload_get(dev, spi, &ad4052_offload_config); + if (IS_ERR(st->offload)) + return PTR_ERR(st->offload); + + if (ret && ret !=3D -ENODEV) + return dev_err_probe(dev, ret, "Failed to get offload\n"); + + if (ret =3D=3D -ENODEV) { + st->offload_trigger =3D NULL; + indio_dev->channels =3D chip->channels; + } else { + indio_dev->channels =3D chip->offload_channels; + ret =3D ad4052_request_offload(indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to configure offload\n"); + } + + st->xfer.rx_buf =3D &st->d32; + + ret =3D ad4052_soft_reset(st); + if (ret) + return dev_err_probe(dev, ret, "AD4052 failed to soft reset\n"); + + ret =3D ad4052_check_ids(st); + if (ret) + return dev_err_probe(dev, ret, + "AD4052 fields assertions failed\n"); + + ret =3D ad4052_setup(indio_dev, indio_dev->channels); + if (ret) + return ret; + + ret =3D regmap_write(st->regmap, AD4052_REG_DEVICE_STATUS, + AD4052_DEVICE_STATUS_DEVICE_RESET); + if (ret) + return ret; + + ret =3D ad4052_request_irq(indio_dev); + if (ret) + return ret; + + ad4052_update_xfer_raw(indio_dev, indio_dev->channels); + + pm_runtime_set_active(dev); + ret =3D devm_pm_runtime_enable(dev); + if (ret) + return dev_err_probe(dev, ret, + "Failed to enable pm_runtime\n"); + + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + + return devm_iio_device_register(dev, indio_dev); +} + +static int ad4052_runtime_suspend(struct device *dev) +{ + struct ad4052_state *st =3D dev_get_drvdata(dev); + + return regmap_write(st->regmap, AD4052_REG_DEVICE_CONFIG, + FIELD_PREP(AD4052_DEVICE_CONFIG_POWER_MODE_MSK, + AD4052_DEVICE_CONFIG_LOW_POWER_MODE)); +} + +static int ad4052_runtime_resume(struct device *dev) +{ + struct ad4052_state *st =3D dev_get_drvdata(dev); + int ret; + + ret =3D regmap_write(st->regmap, AD4052_REG_DEVICE_CONFIG, + FIELD_PREP(AD4052_DEVICE_CONFIG_POWER_MODE_MSK, 0)); + return ret; +} + +static DEFINE_RUNTIME_DEV_PM_OPS(ad4052_pm_ops, ad4052_runtime_suspend, + ad4052_runtime_resume, NULL); + +static const struct spi_device_id ad4052_id_table[] =3D { + {"ad4050", (kernel_ulong_t)&ad4050_chip_info }, + {"ad4052", (kernel_ulong_t)&ad4052_chip_info }, + {"ad4056", (kernel_ulong_t)&ad4056_chip_info }, + {"ad4058", (kernel_ulong_t)&ad4058_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad4052_id_table); + +static const struct of_device_id ad4052_of_match[] =3D { + { .compatible =3D "adi,ad4050", .data =3D &ad4050_chip_info }, + { .compatible =3D "adi,ad4052", .data =3D &ad4052_chip_info }, + { .compatible =3D "adi,ad4056", .data =3D &ad4056_chip_info }, + { .compatible =3D "adi,ad4058", .data =3D &ad4058_chip_info }, + { } +}; +MODULE_DEVICE_TABLE(of, ad4052_of_match); + +static struct spi_driver ad4052_driver =3D { + .driver =3D { + .name =3D "ad4052", + .of_match_table =3D ad4052_of_match, + .pm =3D pm_ptr(&ad4052_pm_ops), + }, + .probe =3D ad4052_probe, + .id_table =3D ad4052_id_table, +}; +module_spi_driver(ad4052_driver); + +MODULE_AUTHOR("Jorge Marques "); +MODULE_DESCRIPTION("Analog Devices AD4052"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER"); --=20 2.49.0