From nobody Sat Feb 7 13:41:21 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 442CE30B515; Fri, 6 Feb 2026 16:08:05 +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=1770394085; cv=none; b=GSMJ9VrwSMZnDcD+pVvq1cxc/FOfMSgnksZgkxfaHCXYoQ7oTfuMU4ArmEircxutl9mQlFzadzSh9PGG66LPTQbqsYDsgMlAocDvYNr0EqAsFDCt81ejk795s4zMKDnV1yXtMrNfRMvk5DALZ6ZKhePLpzfQti+3j98GmvyiyFE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770394085; c=relaxed/simple; bh=112NwewjqgbtMoj2SSFq82/xqJDx/6QVkQ5u1fXAkcY=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=I0pBvE99B29QbFe4qheaUBV+XUHjriktj6T9pFGWmaGmW6iA66swuCWcbgTYQbt/SOTQbdDAEiOTuYT2R0mMuOBsOMhe88UbqXbU5JNxesnu41qjYS/+pJeah9oD3R0bPSpqMjQCOiR+SKwtBOi64oQ25O328NzuJ4Tzb3cMpcI= 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=T0GRh+1e; 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="T0GRh+1e" 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 6169skFw898157; Fri, 6 Feb 2026 11:07:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=j9iZO AvdPrymJ+lBxZCmFd7tXgQrCAjgxtPn/t1x1ug=; b=T0GRh+1ekO3BiXxOdOA+J +cv3XZEBRKxrdukagKPUTQ2QPXAwJ0fRNdz2nDjBiHB5R0qX+Bbef3Vmyl0IUGnQ /58hymKZoSoDIxF5qI3ytDZ2FJ3yEQqNFwIssRc+78qyzMdhYvdmfUEwBFCHAN5W qMBbQM38KAKKZymDr9KxHw/JIuhmo247kFOfbEVjHsPmRxyn1nhho1cWksogt4Qe ZABN4C2DDhsI1YSbITosa5ak4RoJVlZ4lEoSbYeBJRTOxNsK9NV/N3CKxzldW6Hf RJ5yjjk5+Omb8LBO3/ARdCKuNP+d8ww8lDfHmM4SmAytWKx/9+tAIwquydADHj8U A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4c5e32h4y4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Feb 2026 11:07:41 -0500 (EST) 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 616G7ela057139 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 6 Feb 2026 11:07:40 -0500 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; Fri, 6 Feb 2026 11:07:40 -0500 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; Fri, 6 Feb 2026 11:07:40 -0500 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; Fri, 6 Feb 2026 11:07:40 -0500 Received: from HYB-b1tGeUj4GP1.ad.analog.com (HYB-b1tGeUj4GP1.ad.analog.com [10.48.65.247]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 616G7MAl000370; Fri, 6 Feb 2026 11:07:33 -0500 From: Antoniu Miclaus To: Antoniu Miclaus , Lars-Peter Clausen , Michael Hennerich , "Jonathan Cameron" , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Olivier Moysan , Mark Brown , , , , Subject: [PATCH v2 1/4] spi: allow ancillary devices to share parent's chip selects Date: Fri, 6 Feb 2026 18:07:13 +0200 Message-ID: X-Mailer: git-send-email 2.43.0 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-GUID: 4jPEXfSFDyf0Wbqf1ombZa4X_Xekf8NQ X-Proofpoint-ORIG-GUID: 4jPEXfSFDyf0Wbqf1ombZa4X_Xekf8NQ X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjA2MDExNyBTYWx0ZWRfX5Jv4fedEQvtm C7VM4WeufDMwxATjeK9hZhkzoSyMsYCayxjk3tzW3nj7NPkYbVRocPFHylDzDuEg4fnvxUNpGiD LMq2sgRpwCJSsSdkNP/76yaluY2OLAi6msPtu7fQFIU1F+mWS0WDuwssOe4pAk5idfAy5e6OaOA uksHGC6hicaTEobwi8lzjYKeqAv5uppvGcPI+OEp0++3hwmzv0utu7f+1/SAO0bayTjN/Cb2lP5 Z7Z3A8M1faTK1PfYk0QV7gSbUVD7KcjT3ssQ1ftNFr5xg7n/xqjRNPHGZKKacot7yQSEFqPHHoB BSU3eGgmISWRQR3QvzXo7+xNy6AJ+aGJuGPj3NJdj9Fp4qA/sd5o6MpkWYTszutcp3ePVFoKPA/ wwtaBycO9m6BuWh0v5ulHWBMKje+tiHc7zYnf/VJBsLpNMJiCGTnS2wQq5U0GMA6nv82LV4QvfG zW495ToqvxWpg6iOraA== X-Authority-Analysis: v=2.4 cv=NPzYOk6g c=1 sm=1 tr=0 ts=698611cd cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=gAnH3GRIAAAA:8 a=Brvx10Sw2QwnUvu3_sIA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-06_04,2026-02-05_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1011 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 suspectscore=0 adultscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602060117 Content-Type: text/plain; charset="utf-8" When registering an ancillary SPI device, the current code flags a chip select conflict with the parent device. This happens because the ancillary device intentionally uses one of the parent's chip selects, but __spi_add_device() checks against all existing devices including the parent. Allow this by passing the parent device pointer to __spi_add_device() and skipping the conflict check when the existing device is the parent. Signed-off-by: Antoniu Miclaus --- drivers/spi/spi.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index e25df9990f82..18ca3c7bad6b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -641,12 +641,26 @@ static inline int spi_dev_check_cs(struct device *dev, return 0; } =20 +struct spi_dev_check_info { + struct spi_device *new_spi; + struct spi_device *parent; /* set for ancillary devices */ +}; + static int spi_dev_check(struct device *dev, void *data) { struct spi_device *spi =3D to_spi_device(dev); - struct spi_device *new_spi =3D data; + struct spi_dev_check_info *info =3D data; + struct spi_device *new_spi =3D info->new_spi; int status, idx; =20 + /* + * When registering an ancillary device, skip checking against the + * parent device since the ancillary is intentionally using one of + * the parent's chip selects. + */ + if (info->parent && spi =3D=3D info->parent) + return 0; + if (spi->controller =3D=3D new_spi->controller) { for (idx =3D 0; idx < spi->num_chipselect; idx++) { status =3D spi_dev_check_cs(dev, spi, idx, new_spi, 0); @@ -663,10 +677,11 @@ static void spi_cleanup(struct spi_device *spi) spi->controller->cleanup(spi); } =20 -static int __spi_add_device(struct spi_device *spi) +static int __spi_add_device(struct spi_device *spi, struct spi_device *par= ent) { struct spi_controller *ctlr =3D spi->controller; struct device *dev =3D ctlr->dev.parent; + struct spi_dev_check_info check_info; int status, idx; u8 cs; =20 @@ -710,7 +725,9 @@ static int __spi_add_device(struct spi_device *spi) * chipselect **BEFORE** we call setup(), else we'll trash * its configuration. */ - status =3D bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); + check_info.new_spi =3D spi; + check_info.parent =3D parent; + status =3D bus_for_each_dev(&spi_bus_type, NULL, &check_info, spi_dev_che= ck); if (status) return status; =20 @@ -772,7 +789,7 @@ int spi_add_device(struct spi_device *spi) spi_dev_set_name(spi); =20 mutex_lock(&ctlr->add_lock); - status =3D __spi_add_device(spi); + status =3D __spi_add_device(spi, NULL); mutex_unlock(&ctlr->add_lock); return status; } @@ -2580,8 +2597,8 @@ struct spi_device *spi_new_ancillary_device(struct sp= i_device *spi, =20 WARN_ON(!mutex_is_locked(&ctlr->add_lock)); =20 - /* Register the new device */ - rc =3D __spi_add_device(ancillary); + /* Register the new device, passing the parent to skip CS conflict check = */ + rc =3D __spi_add_device(ancillary, spi); if (rc) { dev_err(&spi->dev, "failed to register ancillary device\n"); goto err_out; --=20 2.43.0 From nobody Sat Feb 7 13:41:21 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 83969318BA5; Fri, 6 Feb 2026 16:08:08 +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=1770394088; cv=none; b=mO+kRM93cMWrUHHBMkWxhh8GC9ib2OhXVJ7IhbNR1zjBHiUXsjyGtNxKP/hiTPtVgrXfn7gtEQjBLerD4OoSoRcfzKUd75A5bjpJzzkol/Ow1G5xnIZIm4kx6MouDz63UOD4us8HPfykRUrNf/rELtvAqzxdq9DjrrMaElLrPrg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770394088; c=relaxed/simple; bh=gUFNeiRe8VlWcTt7/ZpjKDl9rspSkpeHKX+epwrPkMY=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=mYm+RkSqU8BFltXa0rMeyRf12Dtyz3tkcg7YylAJ0SrQsc22pzLlNLWDCxGkSShLnWUmMHtJiZHwwsuLu5QBdHJuzs3iqtwKA2dlJixt0P9WPf9nSOA0DCleipMIMUhnWEabDGw/tNUOgtm8acCetZXJ1Ygr8kHBUUWKhzjlw20= 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=RBjayxo5; 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="RBjayxo5" 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 6169sMkQ897366; Fri, 6 Feb 2026 11:07:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=VFbCV GNdv2yThIeAGDi2mdyQ+gW2WPqNqQTksbU/6Jk=; b=RBjayxo5bFhvJpUZuW+8F 3OusLlJcF4aVQ4Fh+Rda9kYjggb6hOCvVsx1KF3ROCOD3F7htRUVPYMMJVJpjvZS vKtLtL516MZrDI4BRKhY2oSHq2U4ulpE9KEMmUZxh0IMujpOTC63YEYJrZ90veSq tqWz8216GmcOG3I07eKv8mzZi0BqtprBXO4fn202iYV33DrpvKNjTEgyEtjms8A/ pq9Gnnqcg1RLw8LRoOKeR+WWgNHnDc3BjecDOsUhxDKPsM0n1idRbdKIHSmPbK+p awb+F4CszLhGzbFXyDeT3GyT151+I/GIev3xPpyGzlzpnczmIiri1Co6XGldaBvh w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4c5e32h4ya-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Feb 2026 11:07:44 -0500 (EST) 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 616G7h3P057147 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 6 Feb 2026 11:07:43 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 6 Feb 2026 11:07:43 -0500 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 6 Feb 2026 11:07:43 -0500 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; Fri, 6 Feb 2026 11:07:43 -0500 Received: from HYB-b1tGeUj4GP1.ad.analog.com (HYB-b1tGeUj4GP1.ad.analog.com [10.48.65.247]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 616G7MAm000370; Fri, 6 Feb 2026 11:07:36 -0500 From: Antoniu Miclaus To: Antoniu Miclaus , Lars-Peter Clausen , Michael Hennerich , "Jonathan Cameron" , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Olivier Moysan , Mark Brown , , , , Subject: [PATCH v2 2/4] iio: backend: add devm_iio_backend_get_by_index() Date: Fri, 6 Feb 2026 18:07:14 +0200 Message-ID: <550323d752213f177b7673bdd42e667f1d2228cb.1770393792.git.antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 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-GUID: JJ-AgCM_M_qyH0cFBrszPr9GlaYrv-wB X-Proofpoint-ORIG-GUID: JJ-AgCM_M_qyH0cFBrszPr9GlaYrv-wB X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjA2MDExNyBTYWx0ZWRfXyGfleE23ghY6 dWOwcRS4F75XVjwfFjOSUCfoYSaB/9OENdQmH6+nvf2EZORgcihnZvdDbz5CFh6lMo7W9NM0wfq ern4XD6cqU/li2OuU5DcbfwPpfLgRCKjaMvrmvyZEla5tX2ZQ5imfaqkg1qFYrfR3B63YgKJgku 8CZs2MWwiWF2n4QXZYtDM/LHjTg1Kez8BD5lkXizi+qq72+xfzrmLdwdefOQv2VvSpn7jN0bVvp VngA8dbFbF4+l+le224lBJsJeHjQ7rKNKvgxrnNKfq8ZXcrReeyp/GCC7E2NtRG/Z7f4LxF8O5o R5+YNJEks+upnIKGYQi89g1rotkUZ9ZhXDBVwFllyGXjzyDyvVsYYGHaMNVRxxp3R8UK/MakO62 ej+h5RIG8jUp0FYbr1orhJWnPhoQYAngmVO/rDIPp1avACjT/3SIMrsFMAbl/HK99xwjxSm99Uc JP/ewpu1h1SCAfwRTYg== X-Authority-Analysis: v=2.4 cv=NPzYOk6g c=1 sm=1 tr=0 ts=698611d0 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=gAnH3GRIAAAA:8 a=uDLBfjgilch4dD8VpdgA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-06_04,2026-02-05_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 suspectscore=0 adultscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602060117 Content-Type: text/plain; charset="utf-8" Add a new function to get an IIO backend by its index in the io-backends device tree property. This is useful for multi-channel devices that have multiple backends, where looking up by index is more straightforward than using named backends. The new function directly uses the index to find the backend reference in the io-backends property, avoiding the need for io-backend-names. Signed-off-by: Antoniu Miclaus --- drivers/iio/industrialio-backend.c | 51 ++++++++++++++++++++++++++++++ include/linux/iio/backend.h | 2 ++ 2 files changed, 53 insertions(+) diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-= backend.c index 447b694d6d5f..3b692d48481e 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -1008,6 +1008,57 @@ struct iio_backend *devm_iio_backend_get(struct devi= ce *dev, const char *name) } EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, "IIO_BACKEND"); =20 +static struct iio_backend * +__devm_iio_backend_fwnode_get_by_index(struct device *dev, + struct fwnode_handle *fwnode, + unsigned int index) +{ + struct fwnode_handle *fwnode_back; + struct iio_backend *back; + int ret; + + fwnode_back =3D fwnode_find_reference(fwnode, "io-backends", index); + if (IS_ERR(fwnode_back)) + return dev_err_cast_probe(dev, fwnode_back, + "Cannot get Firmware reference\n"); + + guard(mutex)(&iio_back_lock); + list_for_each_entry(back, &iio_back_list, entry) { + if (!device_match_fwnode(back->dev, fwnode_back)) + continue; + + fwnode_handle_put(fwnode_back); + ret =3D __devm_iio_backend_get(dev, back); + if (ret) + return ERR_PTR(ret); + + back->idx =3D index; + + return back; + } + + fwnode_handle_put(fwnode_back); + return ERR_PTR(-EPROBE_DEFER); +} + +/** + * devm_iio_backend_get_by_index - Device managed backend device get by in= dex + * @dev: Consumer device for the backend + * @index: Index of the backend in the io-backends property + * + * Get's the backend at @index associated with @dev. + * + * RETURNS: + * A backend pointer, negative error pointer otherwise. + */ +struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, + unsigned int index) +{ + return __devm_iio_backend_fwnode_get_by_index(dev, dev_fwnode(dev), + index); +} +EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get_by_index, "IIO_BACKEND"); + /** * devm_iio_backend_fwnode_get - Device managed backend firmware node get * @dev: Consumer device for the backend diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h index 7f815f3fed6a..8f18df0ca896 100644 --- a/include/linux/iio/backend.h +++ b/include/linux/iio/backend.h @@ -237,6 +237,8 @@ int iio_backend_extend_chan_spec(struct iio_backend *ba= ck, struct iio_chan_spec *chan); void *iio_backend_get_priv(const struct iio_backend *conv); struct iio_backend *devm_iio_backend_get(struct device *dev, const char *n= ame); +struct iio_backend *devm_iio_backend_get_by_index(struct device *dev, + unsigned int index); struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev, const char *name, struct fwnode_handle *fwnode); --=20 2.43.0 From nobody Sat Feb 7 13:41:21 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 4434A30B52E; Fri, 6 Feb 2026 16:08:05 +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=1770394085; cv=none; b=Tg276KvVqrcWDpRUaGo2YSdWUvYMUBfU+G4PaK0vXjQtb+S/30Z9Js76Fw2qer19/4F4nlO290PB6YDhGhcR+tpK5lmhig8qgb0UR6KvxcNHTpYm+fE9YSsO/p+VlycLYy6k200pD21158KO9/5vAsdloVpBdYnuvQZsbj3pnh0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770394085; c=relaxed/simple; bh=YEKxHtEP1kS3eg3xHPo8FCioLbnANi4HQA5PAqhiUS0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UjJZXzrwVp4JYqoR8RoK5QSaJFpQuQwQNrD6Gr314hPTjP+b7vk/jIESYDott+pCY3KiMQUMYSk5iUDy6o1hPAq6kpVbJ8DCDvwhGnXDSMB4PI6M2EZzhnASPMYHCyn6KJt9iIjbWCVkUr8+OlF3zDsh3gMW4zV+fyaVlz9z7XQ= 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=MXnmQhMi; 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="MXnmQhMi" 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 6169sNQ6897382; Fri, 6 Feb 2026 11:07:48 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=4O9cc LHwpwxRMocBE3L5W8Ebd6hFMX23Ud8XJUuC0SM=; b=MXnmQhMibnJAolOUR7kub X8hO7aKkw5/Y9DTjJCrsXu7wnpGp9ZbzjybdBiIsCfm7IQJGfbkrx+glWziP412E bTCGmSV0I9LmNd+tlWGlRv0ctg+v+c2JF4VpAh5nqOK/NMHbCR084336oL5ajSBT ew9LDVxM3G+G5mvb0KfzOP2qdzTfVMavcvCKRrtvPgxeUc5RSXGXQJLFQlK1FPsq LYZHgCAC35vzu95azDH1holy8fRTk4/IDxlyODBhl1i8Cj744sDUlU8O2jyTwCUl kGnv7T7H+3Z+LyngVn4NJpG1An50GbtRO5GVcAwe3XVpq9iDOrCVxZp6qn0zQG0N w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4c5e32h4yk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Feb 2026 11:07:47 -0500 (EST) 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 616G7k6H057150 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 6 Feb 2026 11:07:46 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 6 Feb 2026 11:07:46 -0500 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 6 Feb 2026 11:07:46 -0500 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; Fri, 6 Feb 2026 11:07:46 -0500 Received: from HYB-b1tGeUj4GP1.ad.analog.com (HYB-b1tGeUj4GP1.ad.analog.com [10.48.65.247]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 616G7MAn000370; Fri, 6 Feb 2026 11:07:40 -0500 From: Antoniu Miclaus To: Lars-Peter Clausen , Michael Hennerich , Antoniu Miclaus , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Olivier Moysan , Mark Brown , , , , Subject: [PATCH v2 3/4] dt-bindings: iio: adc: ad4080: add AD4880 support Date: Fri, 6 Feb 2026 18:07:15 +0200 Message-ID: <290f35bcbd2f1ee68333ff65f89b54ec7fbb9c53.1770393792.git.antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 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-GUID: 2Bxct58a9d_N3GsV5wxljvUO8_6-8cIm X-Proofpoint-ORIG-GUID: 2Bxct58a9d_N3GsV5wxljvUO8_6-8cIm X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjA2MDExNyBTYWx0ZWRfX7S6m+cq9VKnG obFWXfW9/fOCog7+WKX/YxTFdp6MR2RPSbzSFPz+kq/JW/+NqOzdUVYFx8jtWtGJCSWTcd1SyCd E4ZDiNK8nw/YOy2ibMOPU8ejv5UDKzO/s0r9pXja2YcJS1/Hoj9z4xIuyyaCkn6DcVH4qxjU2sV D4q3i8wNTxWsUc1gOXtQ+WsesXNaS8Fy7ZI8W7i33iYswPOgK09s3EQ5wsWkSqe4ToBnVGEXTkt 7M13rne6Foghy9BVChTNZAHOmclxO+wIotQEk286GbamPnrRmcbnJTwlM7yUi7uqk3yotUx4rh2 QspZbDEgYZuiMy4Z6y6Ed/Ba8aj5nz5olB4YRrRq4Kg9lImoVUUVCTBVnFMjxpk/YHtnC+QQnlu BFFzgg3vydiu0uEfoj72i8OvIYG6VJ0C9dG7L/TLwKb8cVF27as1A8kaMpiUFT8yeGgR+9SJB35 9yjeifGRyMO8PGs7bfw== X-Authority-Analysis: v=2.4 cv=NPzYOk6g c=1 sm=1 tr=0 ts=698611d3 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=gAnH3GRIAAAA:8 a=VPyHybxGR0euwXT8RmoA:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-06_04,2026-02-05_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1011 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 suspectscore=0 adultscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602060117 Content-Type: text/plain; charset="utf-8" Add support for the AD4880, a dual-channel 20-bit 40MSPS SAR ADC with integrated fully differential amplifiers (FDA). The AD4880 has two independent ADC channels, each with its own SPI configuration interface. This requires: - Two entries in reg property for primary and secondary channel chip selects - Two io-backends entries for the two data channels Signed-off-by: Antoniu Miclaus --- Changes in v2: - Replace custom adi,aux-spi-cs property with standard reg property containing two entries for multi-channel devices - Add conditional schema validation for reg and io-backends based on compatible string - Update example to use reg =3D <0 1> instead of adi,aux-spi-cs - Add AD4880 datasheet link .../bindings/iio/adc/adi,ad4080.yaml | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml b/Do= cumentation/devicetree/bindings/iio/adc/adi,ad4080.yaml index ccd6a0ac1539..7108a91bb0bf 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4080.yaml @@ -18,7 +18,11 @@ description: | service a wide variety of precision, wide bandwidth data acquisition applications. =20 + The AD4880 is a dual-channel variant with two independent ADC channels, + each with its own SPI configuration interface. + https://www.analog.com/media/en/technical-documentation/data-sheets/ad40= 80.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad48= 80.pdf =20 $ref: /schemas/spi/spi-peripheral-props.yaml# =20 @@ -31,9 +35,15 @@ properties: - adi,ad4084 - adi,ad4086 - adi,ad4087 + - adi,ad4880 =20 reg: - maxItems: 1 + minItems: 1 + maxItems: 2 + description: + SPI chip select(s). For single-channel devices, one chip select. + For multi-channel devices like AD4880, two chip selects are required + as each channel has its own SPI configuration interface. =20 spi-max-frequency: description: Configuration of the SPI bus. @@ -57,7 +67,8 @@ properties: vrefin-supply: true =20 io-backends: - maxItems: 1 + minItems: 1 + maxItems: 2 =20 adi,lvds-cnv-enable: description: Enable the LVDS signal type on the CNV pin. Default is CM= OS. @@ -78,6 +89,25 @@ required: - vdd33-supply - vrefin-supply =20 +allOf: + - if: + properties: + compatible: + contains: + const: adi,ad4880 + then: + properties: + reg: + minItems: 2 + io-backends: + minItems: 2 + else: + properties: + reg: + maxItems: 1 + io-backends: + maxItems: 1 + additionalProperties: false =20 examples: @@ -98,4 +128,21 @@ examples: io-backends =3D <&iio_backend>; }; }; + - | + spi { + #address-cells =3D <1>; + #size-cells =3D <0>; + + adc@0 { + compatible =3D "adi,ad4880"; + reg =3D <0 1>; + spi-max-frequency =3D <10000000>; + vdd33-supply =3D <&vdd33>; + vddldo-supply =3D <&vddldo>; + vrefin-supply =3D <&vrefin>; + clocks =3D <&cnv>; + clock-names =3D "cnv"; + io-backends =3D <&iio_backend_cha>, <&iio_backend_chb>; + }; + }; ... --=20 2.43.0 From nobody Sat Feb 7 13:41:22 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 D06FE314B63; Fri, 6 Feb 2026 16:08:06 +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=1770394087; cv=none; b=r3p+zUtiflDBP40VSApW/C/Fvbjt9GjII7f8JM2X8CSYbmsrbOBBmBIWsvUSqBOCUe3nHp25D7TS0kOW2zkTNPsyUxV1wnIXwIzm0cxfzDYlibk82MkR0hLvRVTLClEVuceBoh3Ec2fL9wWL1XbYNSJJMjmmOFNqxzN4+TekLl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770394087; c=relaxed/simple; bh=GYBOstQg15WF2M2bSAT462iisu+N/TIUneRNKaLgE/8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MlEAsnu4UYtOkZztERQcocRvLEEGj0h9t7vodXeDFJq3745CKYGmUGxRjdX4eaocbA6bDxE9HiwJqEWHqf6FKwyT19XBSckFgRexKQbYBMDRn5EuljevA8G7yesSvFGivMXB5xOlpcshUrNMJjlMeAXyL9dbYfv+K6x/J0brmLg= 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=1HQvL3r2; 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="1HQvL3r2" 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 6169sOjg897386; Fri, 6 Feb 2026 11:07:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=3s3hl 61NME1B0N9SkLmuw92TkabS3QrI2yBqtI8I1xs=; b=1HQvL3r2jUeTN1ypPHh4M NQzbsFCt0MAm6VWYNCwpIsysyPMQ6HLnKPoup2e0UlTc0sHC5Z71VIJDUHPwiecS B/NEbSdn2cg/Su4uNFL87xINHFhzICgDA0T4FFMzEluvPtafG2gLVBF8rNL9wHMk qFW/cMZtmNhaNNMX+7vgVsZWjYFafJ/PXr13eoAJkA/OSvnxZRsJrsHLHHwmmkMZ ZNZtm99jesXKq6phVb/6sb/f5TBr53Mpss+tKECleeGSWK3yDebKSCKYwamWjMsr fUk+dkAL+pMMswjjg0FWD2wtH/IVRHaXqY47JqyG4UzhqV6ylH2l1wVZBEUNtwtb w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4c5e32h4yr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 06 Feb 2026 11:07:48 -0500 (EST) 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 616G7lvU057153 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 6 Feb 2026 11:07:47 -0500 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; Fri, 6 Feb 2026 11:07:47 -0500 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; Fri, 6 Feb 2026 11:07:47 -0500 Received: from HYB-b1tGeUj4GP1.ad.analog.com (HYB-b1tGeUj4GP1.ad.analog.com [10.48.65.247]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 616G7MAo000370; Fri, 6 Feb 2026 11:07:43 -0500 From: Antoniu Miclaus To: Antoniu Miclaus , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , David Lechner , =?UTF-8?q?Nuno=20S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Olivier Moysan , Mark Brown , , , , Subject: [PATCH v2 4/4] iio: adc: ad4080: add support for AD4880 dual-channel ADC Date: Fri, 6 Feb 2026 18:07:16 +0200 Message-ID: <8685e3e53667e82c7cdfd66ee6fb1ec3d3c009cd.1770393792.git.antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 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-GUID: hGdSoBkT1-M-fer-tmF_ciO4GbbWZxwN X-Proofpoint-ORIG-GUID: hGdSoBkT1-M-fer-tmF_ciO4GbbWZxwN X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjA2MDExNyBTYWx0ZWRfXxEHHSw2Or82K 7BW9yrDxpRp0Ipf7vQ2/OdsTnXtA21JADvwK8MV2tHbE6wFZqOzsYlJthiKL1WhTx15SOs8jLaF 7h7rnzWAbNxix7XjfeLQ3ef25nm8LmrZEFns8J1AvzO7hzrgMN7lAgr/hq8RkqCcWiFTAZsJSeM fo2J2Yo6zydz2Oq7DnZng5DkoDz8eIWccNxi5+kKdymEIOBrkoG6T8VNui2XCTWDZfWabj9hhPO XujQ5M1M9ArBsGlhi9Md/N1066bmeuRL4Caoq/z8L4sfVAiZQdXvRBaZsQcp42mexahRfVxmtb9 bGgNL3qz1Ke75bR2wKRoz/etRDuw8o/sShWU2DlmtKPi0aaTYkVfyH+gT6QP1/SV5nCwPibXy3M Patab87cvgpj7T2vL7WPLWywUaJfAF9kNhoIdc9VKbs+83leWMRQTjFAfTcqbyqOvohzwPpjUk5 Yga4+3y2ygmXUuqGW8g== X-Authority-Analysis: v=2.4 cv=NPzYOk6g c=1 sm=1 tr=0 ts=698611d4 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=gAnH3GRIAAAA:8 a=1TNaxu5aMze5YuMPDZ4A:9 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-06_04,2026-02-05_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1011 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 suspectscore=0 adultscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602060117 Content-Type: text/plain; charset="utf-8" Add support for the AD4880, a dual-channel 20-bit 40MSPS SAR ADC with integrated fully differential amplifiers (FDA). The AD4880 has two independent ADC channels, each with its own SPI configuration interface. The driver uses spi_new_ancillary_device() to create an additional SPI device for the second channel, allowing both channels to share the same SPI bus with different chip selects. Signed-off-by: Antoniu Miclaus --- Changes in v2: - Use second reg entry instead of custom adi,aux-spi-cs property for secondary channel chip select - Use devm_iio_backend_get_by_index() instead of named backends for multi-channel backend lookup - Separate iio_info structures for single-channel (ad4080) and multi-channel (ad4880) devices - Keep filter_type as shared attribute for single-channel devices, use per-channel only for AD4880 - Add separate AD4880_CHANNEL_DEFINE macro with per-channel attributes drivers/iio/adc/ad4080.c | 256 +++++++++++++++++++++++++++++++-------- 1 file changed, 205 insertions(+), 51 deletions(-) diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c index 7cf3b6ed7940..2b26f8a4d548 100644 --- a/drivers/iio/adc/ad4080.c +++ b/drivers/iio/adc/ad4080.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -131,6 +132,9 @@ #define AD4084_CHIP_ID 0x0054 #define AD4086_CHIP_ID 0x0056 #define AD4087_CHIP_ID 0x0057 +#define AD4880_CHIP_ID 0x0750 + +#define AD4080_MAX_CHANNELS 2 =20 #define AD4080_LVDS_CNV_CLK_CNT_MAX 7 =20 @@ -176,8 +180,9 @@ struct ad4080_chip_info { }; =20 struct ad4080_state { - struct regmap *regmap; - struct iio_backend *back; + struct spi_device *spi[AD4080_MAX_CHANNELS]; + struct regmap *regmap[AD4080_MAX_CHANNELS]; + struct iio_backend *back[AD4080_MAX_CHANNELS]; const struct ad4080_chip_info *info; /* * Synchronize access to members the of driver state, and ensure @@ -203,10 +208,11 @@ static int ad4080_reg_access(struct iio_dev *indio_de= v, unsigned int reg, { struct ad4080_state *st =3D iio_priv(indio_dev); =20 + /* Use channel 0 regmap for debugfs access */ if (readval) - return regmap_read(st->regmap, reg, readval); + return regmap_read(st->regmap[0], reg, readval); =20 - return regmap_write(st->regmap, reg, writeval); + return regmap_write(st->regmap[0], reg, writeval); } =20 static int ad4080_get_scale(struct ad4080_state *st, int *val, int *val2) @@ -227,8 +233,9 @@ static unsigned int ad4080_get_dec_rate(struct iio_dev = *dev, struct ad4080_state *st =3D iio_priv(dev); int ret; unsigned int data; + unsigned int ch =3D chan->channel; =20 - ret =3D regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data); + ret =3D regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data); if (ret) return ret; =20 @@ -240,13 +247,14 @@ static int ad4080_set_dec_rate(struct iio_dev *dev, unsigned int mode) { struct ad4080_state *st =3D iio_priv(dev); + unsigned int ch =3D chan->channel; =20 guard(mutex)(&st->lock); =20 if ((st->filter_type >=3D SINC_5 && mode >=3D 512) || mode < 2) return -EINVAL; =20 - return regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG, + return regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG, AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK, FIELD_PREP(AD4080_FILTER_CONFIG_SINC_DEC_RATE_MSK, (ilog2(mode) - 1))); @@ -304,23 +312,23 @@ static int ad4080_write_raw(struct iio_dev *indio_dev, } } =20 -static int ad4080_lvds_sync_write(struct ad4080_state *st) +static int ad4080_lvds_sync_write(struct ad4080_state *st, unsigned int ch) { - struct device *dev =3D regmap_get_device(st->regmap); + struct device *dev =3D regmap_get_device(st->regmap[ch]); int ret; =20 - ret =3D regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + ret =3D regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_A, AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN); if (ret) return ret; =20 - ret =3D iio_backend_interface_data_align(st->back, 10000); + ret =3D iio_backend_interface_data_align(st->back[ch], 10000); if (ret) return dev_err_probe(dev, ret, "Data alignment process failed\n"); =20 dev_dbg(dev, "Success: Pattern correct and Locked!\n"); - return regmap_clear_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + return regmap_clear_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_= A, AD4080_ADC_DATA_INTF_CONFIG_A_INTF_CHK_EN); } =20 @@ -329,9 +337,10 @@ static int ad4080_get_filter_type(struct iio_dev *dev, { struct ad4080_state *st =3D iio_priv(dev); unsigned int data; + unsigned int ch =3D chan->channel; int ret; =20 - ret =3D regmap_read(st->regmap, AD4080_REG_FILTER_CONFIG, &data); + ret =3D regmap_read(st->regmap[ch], AD4080_REG_FILTER_CONFIG, &data); if (ret) return ret; =20 @@ -343,6 +352,7 @@ static int ad4080_set_filter_type(struct iio_dev *dev, unsigned int mode) { struct ad4080_state *st =3D iio_priv(dev); + unsigned int ch =3D chan->channel; int dec_rate; int ret; =20 @@ -355,11 +365,11 @@ static int ad4080_set_filter_type(struct iio_dev *dev, if (mode >=3D SINC_5 && dec_rate >=3D 512) return -EINVAL; =20 - ret =3D iio_backend_filter_type_set(st->back, mode); + ret =3D iio_backend_filter_type_set(st->back[ch], mode); if (ret) return ret; =20 - ret =3D regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG, + ret =3D regmap_update_bits(st->regmap[ch], AD4080_REG_FILTER_CONFIG, AD4080_FILTER_CONFIG_FILTER_SEL_MSK, FIELD_PREP(AD4080_FILTER_CONFIG_FILTER_SEL_MSK, mode)); @@ -399,6 +409,29 @@ static int ad4080_read_avail(struct iio_dev *indio_dev, } } =20 +static int ad4880_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct ad4080_state *st =3D iio_priv(indio_dev); + unsigned int ch; + int ret; + + for (ch =3D 0; ch < st->info->num_channels; ch++) { + /* + * Each backend has a single channel (channel 0 from the + * backend's perspective), so always use channel index 0. + */ + if (test_bit(ch, scan_mask)) + ret =3D iio_backend_chan_enable(st->back[ch], 0); + else + ret =3D iio_backend_chan_disable(st->back[ch], 0); + if (ret) + return ret; + } + + return 0; +} + static const struct iio_info ad4080_iio_info =3D { .debugfs_reg_access =3D ad4080_reg_access, .read_raw =3D ad4080_read_raw, @@ -406,6 +439,19 @@ static const struct iio_info ad4080_iio_info =3D { .read_avail =3D ad4080_read_avail, }; =20 +/* + * AD4880 needs update_scan_mode to enable/disable individual backend chan= nels. + * Single-channel devices don't need this as their backends may not implem= ent + * chan_enable/chan_disable operations. + */ +static const struct iio_info ad4880_iio_info =3D { + .debugfs_reg_access =3D ad4080_reg_access, + .read_raw =3D ad4080_read_raw, + .write_raw =3D ad4080_write_raw, + .read_avail =3D ad4080_read_avail, + .update_scan_mode =3D ad4880_update_scan_mode, +}; + static const struct iio_enum ad4080_filter_type_enum =3D { .items =3D ad4080_filter_type_iio_enum, .num_items =3D ARRAY_SIZE(ad4080_filter_type_iio_enum), @@ -420,17 +466,28 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[= ] =3D { { } }; =20 -#define AD4080_CHANNEL_DEFINE(bits, storage) { \ +/* + * AD4880 needs per-channel filter configuration since each channel has + * its own independent ADC with separate SPI interface. + */ +static struct iio_chan_spec_ext_info ad4880_ext_info[] =3D { + IIO_ENUM("filter_type", IIO_SEPARATE, &ad4080_filter_type_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SEPARATE, + &ad4080_filter_type_enum), + { } +}; + +#define AD4080_CHANNEL_DEFINE(bits, storage, idx) { \ .type =3D IIO_VOLTAGE, \ .indexed =3D 1, \ - .channel =3D 0, \ + .channel =3D (idx), \ .info_mask_separate =3D BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_all =3D BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .info_mask_shared_by_all_available =3D \ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .ext_info =3D ad4080_ext_info, \ - .scan_index =3D 0, \ + .scan_index =3D (idx), \ .scan_type =3D { \ .sign =3D 's', \ .realbits =3D (bits), \ @@ -438,17 +495,45 @@ static struct iio_chan_spec_ext_info ad4080_ext_info[= ] =3D { }, \ } =20 -static const struct iio_chan_spec ad4080_channel =3D AD4080_CHANNEL_DEFINE= (20, 32); +/* + * AD4880 has per-channel attributes (filter_type, oversampling_ratio, + * sampling_frequency) since each channel has its own independent ADC + * with separate SPI configuration interface. + */ +#define AD4880_CHANNEL_DEFINE(bits, storage, idx) { \ + .type =3D IIO_VOLTAGE, \ + .indexed =3D 1, \ + .channel =3D (idx), \ + .info_mask_separate =3D BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_separate_available =3D \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .ext_info =3D ad4880_ext_info, \ + .scan_index =3D (idx), \ + .scan_type =3D { \ + .sign =3D 's', \ + .realbits =3D (bits), \ + .storagebits =3D (storage), \ + }, \ +} + +static const struct iio_chan_spec ad4080_channel =3D AD4080_CHANNEL_DEFINE= (20, 32, 0); =20 -static const struct iio_chan_spec ad4081_channel =3D AD4080_CHANNEL_DEFINE= (20, 32); +static const struct iio_chan_spec ad4081_channel =3D AD4080_CHANNEL_DEFINE= (20, 32, 0); =20 -static const struct iio_chan_spec ad4083_channel =3D AD4080_CHANNEL_DEFINE= (16, 16); +static const struct iio_chan_spec ad4083_channel =3D AD4080_CHANNEL_DEFINE= (16, 16, 0); =20 -static const struct iio_chan_spec ad4084_channel =3D AD4080_CHANNEL_DEFINE= (16, 16); +static const struct iio_chan_spec ad4084_channel =3D AD4080_CHANNEL_DEFINE= (16, 16, 0); =20 -static const struct iio_chan_spec ad4086_channel =3D AD4080_CHANNEL_DEFINE= (14, 16); +static const struct iio_chan_spec ad4086_channel =3D AD4080_CHANNEL_DEFINE= (14, 16, 0); =20 -static const struct iio_chan_spec ad4087_channel =3D AD4080_CHANNEL_DEFINE= (14, 16); +static const struct iio_chan_spec ad4087_channel =3D AD4080_CHANNEL_DEFINE= (14, 16, 0); + +static const struct iio_chan_spec ad4880_channels[] =3D { + AD4880_CHANNEL_DEFINE(20, 32, 0), + AD4880_CHANNEL_DEFINE(20, 32, 1), +}; =20 static const struct ad4080_chip_info ad4080_chip_info =3D { .name =3D "ad4080", @@ -510,25 +595,34 @@ static const struct ad4080_chip_info ad4087_chip_info= =3D { .lvds_cnv_clk_cnt_max =3D 1, }; =20 -static int ad4080_setup(struct iio_dev *indio_dev) +static const struct ad4080_chip_info ad4880_chip_info =3D { + .name =3D "ad4880", + .product_id =3D AD4880_CHIP_ID, + .scale_table =3D ad4080_scale_table, + .num_scales =3D ARRAY_SIZE(ad4080_scale_table), + .num_channels =3D 2, + .channels =3D ad4880_channels, + .lvds_cnv_clk_cnt_max =3D AD4080_LVDS_CNV_CLK_CNT_MAX, +}; + +static int ad4080_setup_channel(struct ad4080_state *st, unsigned int ch) { - struct ad4080_state *st =3D iio_priv(indio_dev); - struct device *dev =3D regmap_get_device(st->regmap); + struct device *dev =3D regmap_get_device(st->regmap[ch]); __le16 id_le; u16 id; int ret; =20 - ret =3D regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A, + ret =3D regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A, AD4080_INTERFACE_CONFIG_A_SW_RESET); if (ret) return ret; =20 - ret =3D regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A, + ret =3D regmap_write(st->regmap[ch], AD4080_REG_INTERFACE_CONFIG_A, AD4080_INTERFACE_CONFIG_A_SDO_ENABLE); if (ret) return ret; =20 - ret =3D regmap_bulk_read(st->regmap, AD4080_REG_PRODUCT_ID_L, &id_le, + ret =3D regmap_bulk_read(st->regmap[ch], AD4080_REG_PRODUCT_ID_L, &id_le, sizeof(id_le)); if (ret) return ret; @@ -537,18 +631,18 @@ static int ad4080_setup(struct iio_dev *indio_dev) if (id !=3D st->info->product_id) dev_info(dev, "Unrecognized CHIP_ID 0x%X\n", id); =20 - ret =3D regmap_set_bits(st->regmap, AD4080_REG_GPIO_CONFIG_A, + ret =3D regmap_set_bits(st->regmap[ch], AD4080_REG_GPIO_CONFIG_A, AD4080_GPIO_CONFIG_A_GPO_1_EN); if (ret) return ret; =20 - ret =3D regmap_write(st->regmap, AD4080_REG_GPIO_CONFIG_B, + ret =3D regmap_write(st->regmap[ch], AD4080_REG_GPIO_CONFIG_B, FIELD_PREP(AD4080_GPIO_CONFIG_B_GPIO_1_SEL_MSK, AD4080_GPIO_CONFIG_B_GPIO_FILTER_RES_RDY)); if (ret) return ret; =20 - ret =3D iio_backend_num_lanes_set(st->back, st->num_lanes); + ret =3D iio_backend_num_lanes_set(st->back[ch], st->num_lanes); if (ret) return ret; =20 @@ -556,7 +650,7 @@ static int ad4080_setup(struct iio_dev *indio_dev) return 0; =20 /* Set maximum LVDS Data Transfer Latency */ - ret =3D regmap_update_bits(st->regmap, + ret =3D regmap_update_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_B, AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK, FIELD_PREP(AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK, @@ -565,24 +659,39 @@ static int ad4080_setup(struct iio_dev *indio_dev) return ret; =20 if (st->num_lanes > 1) { - ret =3D regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A, + ret =3D regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_= A, AD4080_ADC_DATA_INTF_CONFIG_A_SPI_LVDS_LANES); if (ret) return ret; } =20 - ret =3D regmap_set_bits(st->regmap, + ret =3D regmap_set_bits(st->regmap[ch], AD4080_REG_ADC_DATA_INTF_CONFIG_B, AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_EN); if (ret) return ret; =20 - return ad4080_lvds_sync_write(st); + return ad4080_lvds_sync_write(st, ch); +} + +static int ad4080_setup(struct iio_dev *indio_dev) +{ + struct ad4080_state *st =3D iio_priv(indio_dev); + unsigned int ch; + int ret; + + for (ch =3D 0; ch < st->info->num_channels; ch++) { + ret =3D ad4080_setup_channel(st, ch); + if (ret) + return ret; + } + + return 0; } =20 static int ad4080_properties_parse(struct ad4080_state *st) { - struct device *dev =3D regmap_get_device(st->regmap); + struct device *dev =3D regmap_get_device(st->regmap[0]); =20 st->lvds_cnv_en =3D device_property_read_bool(dev, "adi,lvds-cnv-enable"); =20 @@ -596,12 +705,18 @@ static int ad4080_properties_parse(struct ad4080_stat= e *st) return 0; } =20 +static void ad4080_unregister_ancillary(void *data) +{ + spi_unregister_device(data); +} + static int ad4080_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct device *dev =3D &spi->dev; struct ad4080_state *st; struct clk *clk; + unsigned int ch; int ret; =20 indio_dev =3D devm_iio_device_alloc(&spi->dev, sizeof(*st)); @@ -610,6 +725,10 @@ static int ad4080_probe(struct spi_device *spi) =20 st =3D iio_priv(indio_dev); =20 + st->info =3D spi_get_device_match_data(spi); + if (!st->info) + return -ENODEV; + ret =3D devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4080_power_supplies), ad4080_power_supplies); @@ -617,13 +736,37 @@ static int ad4080_probe(struct spi_device *spi) return dev_err_probe(dev, ret, "failed to get and enable supplies\n"); =20 - st->regmap =3D devm_regmap_init_spi(spi, &ad4080_regmap_config); - if (IS_ERR(st->regmap)) - return PTR_ERR(st->regmap); + /* Setup primary SPI device (channel 0) */ + st->spi[0] =3D spi; + st->regmap[0] =3D devm_regmap_init_spi(spi, &ad4080_regmap_config); + if (IS_ERR(st->regmap[0])) + return PTR_ERR(st->regmap[0]); =20 - st->info =3D spi_get_device_match_data(spi); - if (!st->info) - return -ENODEV; + /* Setup ancillary SPI device for additional channel (AD4880) */ + if (st->info->num_channels > 1) { + u32 reg[2]; + + ret =3D device_property_read_u32_array(dev, "reg", reg, + ARRAY_SIZE(reg)); + if (ret) + return dev_err_probe(dev, ret, + "missing second reg entry for multi-channel device\n"); + + st->spi[1] =3D spi_new_ancillary_device(spi, reg[1]); + if (IS_ERR(st->spi[1])) + return dev_err_probe(dev, PTR_ERR(st->spi[1]), + "failed to register ancillary device\n"); + + ret =3D devm_add_action_or_reset(dev, ad4080_unregister_ancillary, + st->spi[1]); + if (ret) + return ret; + + st->regmap[1] =3D devm_regmap_init_spi(st->spi[1], + &ad4080_regmap_config); + if (IS_ERR(st->regmap[1])) + return PTR_ERR(st->regmap[1]); + } =20 ret =3D devm_mutex_init(dev, &st->lock); if (ret) @@ -632,7 +775,8 @@ static int ad4080_probe(struct spi_device *spi) indio_dev->name =3D st->info->name; indio_dev->channels =3D st->info->channels; indio_dev->num_channels =3D st->info->num_channels; - indio_dev->info =3D &ad4080_iio_info; + indio_dev->info =3D st->info->num_channels > 1 ? + &ad4880_iio_info : &ad4080_iio_info; =20 ret =3D ad4080_properties_parse(st); if (ret) @@ -644,15 +788,23 @@ static int ad4080_probe(struct spi_device *spi) =20 st->clk_rate =3D clk_get_rate(clk); =20 - st->back =3D devm_iio_backend_get(dev, NULL); - if (IS_ERR(st->back)) - return PTR_ERR(st->back); + /* Get backends for all channels */ + for (ch =3D 0; ch < st->info->num_channels; ch++) { + st->back[ch] =3D devm_iio_backend_get_by_index(dev, ch); + if (IS_ERR(st->back[ch])) + return PTR_ERR(st->back[ch]); =20 - ret =3D devm_iio_backend_request_buffer(dev, st->back, indio_dev); - if (ret) - return ret; + ret =3D devm_iio_backend_enable(dev, st->back[ch]); + if (ret) + return ret; + } =20 - ret =3D devm_iio_backend_enable(dev, st->back); + /* + * Request buffer from the first backend only. For multi-channel + * devices (e.g., AD4880), all backends share a single IIO buffer + * as data from all ADC channels is interleaved into one stream. + */ + ret =3D devm_iio_backend_request_buffer(dev, st->back[0], indio_dev); if (ret) return ret; =20 @@ -670,6 +822,7 @@ static const struct spi_device_id ad4080_id[] =3D { { "ad4084", (kernel_ulong_t)&ad4084_chip_info }, { "ad4086", (kernel_ulong_t)&ad4086_chip_info }, { "ad4087", (kernel_ulong_t)&ad4087_chip_info }, + { "ad4880", (kernel_ulong_t)&ad4880_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad4080_id); @@ -681,6 +834,7 @@ static const struct of_device_id ad4080_of_match[] =3D { { .compatible =3D "adi,ad4084", &ad4084_chip_info }, { .compatible =3D "adi,ad4086", &ad4086_chip_info }, { .compatible =3D "adi,ad4087", &ad4087_chip_info }, + { .compatible =3D "adi,ad4880", &ad4880_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad4080_of_match); --=20 2.43.0