From nobody Thu Apr 2 22:25:44 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 960273624B5; Fri, 13 Feb 2026 14:51:28 +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=1770994289; cv=none; b=aaM9c9w8dnLrrm40Jl69PuVGmWdfMhzYHXtDEDyddtWBthob2uSD2occVA3D1TzL58NlvNjoETmjDiA4DV3RVcWkm/Hgwa9oa5c8sai7vXwHuCphVQCd3k4F5CPO15NLd9jJAKdaZAlFc3cUdpGtJUUU553WSrlAnEvIydb2SrA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994289; c=relaxed/simple; bh=UGbI9BoloVjenYVbUNwNpVHMhG2aG+M2yP9nsGah+xk=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=piuC4shgsrEdHLpoIqKbjncRbeYxFuZFLaypMDKiE4z3ey81Qj9NTYzEbaOimNpz/umRh9MiKBY8eTNPgpL/4TI9JGKsDwk3lPqD3tGHVNUfeXRx7hFtyQXRdAvjDGqQTGcjDCdRy9rA7z46WpY6pEnlIm+l/nAGy3wbMhTKvXc= 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=EMgGfMdw; 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="EMgGfMdw" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61DE6eBD861524; Fri, 13 Feb 2026 09:51:09 -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=XlsoJ Zfx9kg1MnghywKRaY8hdY41t13YOn9Q3SPA8Oo=; b=EMgGfMdw9ZmeybNfHh5qY KE+mtGsh1rdA8fjA7gXFZxfFnZl7hzqkNg8Ec5om8JtKy6TAX9anUkQ1llThQN25 Y2y9hdOd6Z9cY6I14KH0w4ediBJ71zbJE4Msg0aH4wzJQAlev5DLJ9yuLaerHG7l 5hZgI1lwHZMWXohu36hwf6dnXVgpYr0IYFrRDWUZz8sSstOjagTkV/MygmYB8ibB X68wc0hLmFkGk1d20RyX4zE94GD0ZBEdoUTYFqFXLWIOp6x/WaJbpnvHKVrR3Ksx vuCZLEG5Wm7HuMJzcW5ajVQbfx38mpTxZ6FOM9U4b71O5JxNDsH3vrcd/S88MnG+ w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4c8hn342j1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 13 Feb 2026 09:51:09 -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 61DEp8MT041658 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 13 Feb 2026 09:51:08 -0500 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 13 Feb 2026 09:51:07 -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, 13 Feb 2026 09:51:07 -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 61DEop6H018676; Fri, 13 Feb 2026 09:51:03 -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 v3 1/5] spi: allow ancillary devices to share parent's chip selects Date: Fri, 13 Feb 2026 16:47:33 +0200 Message-ID: <20260213144742.16394-2-antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260213144742.16394-1-antoniu.miclaus@analog.com> References: <20260213144742.16394-1-antoniu.miclaus@analog.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: oXek3MgzP4zly1j36IM8KfiT8J07d1qB X-Authority-Analysis: v=2.4 cv=AdC83nXG c=1 sm=1 tr=0 ts=698f3a5d 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=IpJZQVW2AAAA:8 a=Brvx10Sw2QwnUvu3_sIA:9 a=IawgGOuG5U0WyFbmm1f5:22 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEzMDExNSBTYWx0ZWRfX1u+rDuvSOa4a Rx/+Iqv+yoOyBUq2mF0HTWtgZXp9/zoDTojsTA8iK2S7/EMTP+ZoJ3PZasbPfSoKIPEOP5oXHpS ZwIS6f0DpXkEqLBTQlzIUE2nLoDmlmNZ52C3mYVtK/yyhofJrpnf87ODWNe4MSuZTCteRX+Qxj0 ciwg+tIlLIVXKhs8VcVWV3xj1Sdk6I1a7FGieFojcmKYFJS2oMNGo0LzsRkHKnAVaxlPf4a+xvh mF7fS/uBMBCguDD6GaPco9RI6mOuMM5psPvT8lx/Bxp9YmpXSwjGacop132tOojrsbuBEffeACm lafJKuxDXqUxj044f+sNfg7lN6SACsLNaNKinKxzdFod47BjSD31smBJobQse/sROD/9Bp+5fz0 ZJ2kpps5QgOatiR+RBL6O0+qxG9/gvQdF2CvCAjU1A4ZuH/fGXoDmN8t44Tur58VIKgPXAm3Xjs /Xynz/Ovho4jBK95JiA== X-Proofpoint-GUID: oXek3MgzP4zly1j36IM8KfiT8J07d1qB 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-13_03,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 lowpriorityscore=0 bulkscore=0 malwarescore=0 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602130115 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 Reviewed-by: David Lechner Acked-by: Nuno S=C3=A1 --- Changes in v3: - Drop redundant NULL check for info->parent in spi_dev_check() 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..693bdcc5a12a 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 (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 Thu Apr 2 22:25:44 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 E17D83624C1; Fri, 13 Feb 2026 14:51:28 +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=1770994290; cv=none; b=Hup3BdqI9toK05Hdt4eC0UlBjOzilSvn6qO3ReIriQ7poafOyYPzc9lYJnahLdgKMG7mW/gR1n4PAgj49SvS0SxyvV8bJLtCNr+noIBQ1+/Sl9dJCEzsw0rVh7ACHn2Zfja/hzub2HD3ekNh7h2kRkrDnMDJrtLZlXLQ7vWFQRc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994290; c=relaxed/simple; bh=ZT4ZAOqyIG30taFH9S9au4OBNbx3wEjgRXdc/PpyFs4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NMpY4oYPEJuewhxK1+wf6Y31e3LN2oTxZxxeWrR9QW6DyPmaPYJOUGrNejAt0Feb+KggtrZalueG+P5XYXEHuEUJnPyzVXii7Ye28LDVTpRNgoO0ttHPKqz1247B/Wp93HDsjtkMpASGT+QQJ3VVag4pTGeIHCMvC3F7iG/Ia6g= 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=PTJTGhF0; 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="PTJTGhF0" 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 61DEEPLb2059642; Fri, 13 Feb 2026 09:51:12 -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=/v/Zo IRTTQ/8Px6ppUMgx+x7Mfdo7atR/p62S2i+eJc=; b=PTJTGhF0UJjg2T0Cjs/eG yY1/h3y24a0EeH41xdEQ+SjA0woodNGyLW1EioMnBFkba+i+d/gfmIqzbwXpxwx2 40XKrauFz1wmgyj5X/uFqpj+jaBcqRQOW9KCDC5il+HPRQhKLnrNOiliybK1jLo9 +UzxHwbJqck3PM6Wruy02KmJv+r0TCQwka7CKosb3Vl4VHU3AtjaaMI42v7TDIpP 7sgqBtEt2KHt3SdLGqcpcp4nePpd9qf16W0c5tvZVyhIuUlS3+LjAMpQ2UB1Zc9T H6/BO/+XqF4XphK00xprcsXV9ObU7LiJ8SMllt7fwRbGQg9BXE7GywDtomOFomzK A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 4c9ss6atat-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 13 Feb 2026 09:51:12 -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 61DEpBOw041662 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 13 Feb 2026 09:51:11 -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, 13 Feb 2026 09:51:11 -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, 13 Feb 2026 09:51:11 -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, 13 Feb 2026 09:51:11 -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 61DEop6I018676; Fri, 13 Feb 2026 09:51:06 -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 v3 2/5] spi: add devm_spi_new_ancillary_device() Date: Fri, 13 Feb 2026 16:47:34 +0200 Message-ID: <20260213144742.16394-3-antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260213144742.16394-1-antoniu.miclaus@analog.com> References: <20260213144742.16394-1-antoniu.miclaus@analog.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEzMDExNSBTYWx0ZWRfX7yI8YGBXOw23 j6lSMSIkBWmE4is7bgG0XjgagPPwyb2IJuKYVEhXJ9kJtSjjBaXpwKBgon41juv1s2IqJ7wnh1S 9xa9L9N8lYdf3LZSMOX/Ez9HRAfpQL5RJrWAJH3u4dWTzyHAI/XvDmFu0+N6023HQUaFh9z+ojU gaz/VcFjKNV7QkZuJIilDuvqiMlKBHJXuIYG6r3XcGh7OjIy775kgsboamSzGVYEWpE5Fae7Iu6 33SC2fQEjBIMsxux6QUnVxmxyLc4/oA+rnLBY/nP+ynn5fh6Zcrf+FXl3Ym5td3yKB9CVG67+0H cHbfzGxLwzTY7XZOTNA2nIPhmJFXidFN6p315rd9inT2IsYuY7rook+lFQN/frl/OAUdD8KJSR/ nlC/Wf9+j3rEG8HXk3XyGmw36KMwnU1JP0FfQ5Jxa5IaEDeYNKFApHqJTWxV6DOHmJLXs1+A2Uq aCkrcl7B4LJrAGpexIw== X-Proofpoint-ORIG-GUID: qpkNySJjeSSW96Q42z9JzUkF7tJLQLEn X-Authority-Analysis: v=2.4 cv=YJmSCBGx c=1 sm=1 tr=0 ts=698f3a60 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=8fGt7KVEpqQUrG_l--wA:9 X-Proofpoint-GUID: qpkNySJjeSSW96Q42z9JzUkF7tJLQLEn 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-13_03,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 priorityscore=1501 malwarescore=0 lowpriorityscore=0 clxscore=1015 adultscore=0 spamscore=0 impostorscore=0 suspectscore=0 bulkscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602130115 Content-Type: text/plain; charset="utf-8" Add a devres-managed version of spi_new_ancillary_device() that automatically unregisters the ancillary SPI device when the parent device is removed. This follows the same devm_add_action_or_reset() pattern used by the other managed SPI functions (devm_spi_optimize_message, devm_spi_register_controller, etc.) and eliminates the need for drivers to open-code their own devm cleanup callbacks for ancillary devices. Signed-off-by: Antoniu Miclaus Acked-by: Nuno S=C3=A1 --- Changes in v3: - New patch drivers/spi/spi.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 1 + 2 files changed, 41 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 693bdcc5a12a..1b48ec67b8e0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2612,6 +2612,46 @@ struct spi_device *spi_new_ancillary_device(struct s= pi_device *spi, } EXPORT_SYMBOL_GPL(spi_new_ancillary_device); =20 +static void devm_spi_unregister_device(void *spi) +{ + spi_unregister_device(spi); +} + +/** + * devm_spi_new_ancillary_device() - Register managed ancillary SPI device + * @spi: Pointer to the main SPI device registering the ancillary = device + * @chip_select: Chip Select of the ancillary device + * + * Register an ancillary SPI device; for example some chips have a chip-se= lect + * for normal device usage and another one for setup/firmware upload. + * + * This is the managed version of spi_new_ancillary_device(). The ancillary + * device will be unregistered automatically when the parent SPI device is + * unregistered. + * + * This may only be called from main SPI device's probe routine. + * + * Return: Pointer to new ancillary device on success; ERR_PTR on failure + */ +struct spi_device *devm_spi_new_ancillary_device(struct spi_device *spi, + u8 chip_select) +{ + struct spi_device *ancillary; + int ret; + + ancillary =3D spi_new_ancillary_device(spi, chip_select); + if (IS_ERR(ancillary)) + return ancillary; + + ret =3D devm_add_action_or_reset(&spi->dev, devm_spi_unregister_device, + ancillary); + if (ret) + return ERR_PTR(ret); + + return ancillary; +} +EXPORT_SYMBOL_GPL(devm_spi_new_ancillary_device); + #ifdef CONFIG_ACPI struct acpi_spi_lookup { struct spi_controller *ctlr; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index cb2c2df31089..9aef1987b12f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -374,6 +374,7 @@ static inline void spi_unregister_driver(struct spi_dri= ver *sdrv) } =20 extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi,= u8 chip_select); +extern struct spi_device *devm_spi_new_ancillary_device(struct spi_device = *spi, u8 chip_select); =20 /* Use a define to avoid include chaining to get THIS_MODULE */ #define spi_register_driver(driver) \ --=20 2.43.0 From nobody Thu Apr 2 22:25:44 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 11BE2363C50; Fri, 13 Feb 2026 14:51:32 +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=1770994294; cv=none; b=isDJ5VsZ2INmuAc3wkOYnt25eP50pN7yFPNsfRHN/UO4eREAg5zNfF5MOA+pUKXp1gpeUlOeLrZsyjpg+w83fygfyZ5NwoWmJGNqfd9nWt/ibbzYEDGqw2BYpLLH7GyWwB2Tn6AP3SsEA2ArmyXT9jLkUdIdvYhuuM8gq/DK5E0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994294; c=relaxed/simple; bh=VwmAMigC6xAaa8o0AvSl5/BWbUC3ynvJhG1eLuQ8bXw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Wj/vY/eWwABxkgRX/uqckfPd+wFj5AeceT5iOJ8I5wJm3MSABE1KkciLR7koU8pSM3nRJ+Z+VHhGmwZtA+ArtqG/x3TN6yCpEvEw/hKEfRbdAbFXOencvykXzjp9AJowRX13R4V8Li+mwmgqHMxD5N4Q7MMJYJxcpT+eXgDTSbg= 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=im7uBeHg; 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="im7uBeHg" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61DEEwDc1628471; Fri, 13 Feb 2026 09:51:15 -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=iNi2y yJGkEglasWu+SA+JVBk9HCkheX9kpCHjg3/tcY=; b=im7uBeHgOMl6sIZq+cBUJ jiG6dq0gBdUQWp6Hh7LuDmGQ9el7ypVCvqYQnA667OVjQLipqurstK5G+DPVHyM9 +MHHq/MY6whC6SjYQtAuuoBhRm60MM7Oa4+SWpmYLlF2jNmDXt3sqEcY/CZjTw6y oVtmn/8j59AFtf4Hp1Ai2H7KfYQ8HcEA9JhgJzipvhvPFOjQ4IP8DYCZYv5LFHcI SolWbaduabcFYmRtLaYiaDbw8CrSUfwBytI62r7GgR0QO+nSXTVAPj2l7iy3tWNG +i9Za6npOC/z7rJY4fSrjd/wUEoV5QGitQOrUQR4rRBYpCeq460MTbUvkjr3BcWq w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4ca5j504ge-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 13 Feb 2026 09:51:15 -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 61DEpEL1041670 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 13 Feb 2026 09:51:14 -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, 13 Feb 2026 09:51:14 -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, 13 Feb 2026 09:51:14 -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 61DEop6J018676; Fri, 13 Feb 2026 09:51:09 -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 v3 3/5] iio: backend: add devm_iio_backend_get_by_index() Date: Fri, 13 Feb 2026 16:47:35 +0200 Message-ID: <20260213144742.16394-4-antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260213144742.16394-1-antoniu.miclaus@analog.com> References: <20260213144742.16394-1-antoniu.miclaus@analog.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEzMDExNSBTYWx0ZWRfX5MI5JTEAFdbE YwRT6EAP+Jd9UNq6DOUu/4sJ3VykmWE0knvsVqVFpoBRlPEc07DPJYfJTkSMS63zqWSPXmBNYnr kz1pyc4dPvpVRXkwE//QUDvdF2IevG30KfdBe2fNEaArJDJGd0nqDKGtuX27bqXlAd4vJWtJXaE 6w/nywNCGa8yiz7Z2rI1FcSsjT5efKatSPTbfiXVvjf2YTe+7+pUBK2GmIEEJwYUfUyWjAT6JAV SYAhD6COQli/Wr80B3LaJlTrYNkSt0P1h6ZQFg1QVvzELNSgJwN+k4YLAGHQrgHmzLaFpuCdER8 fZskSnVqYwbGtdRzXx32u0e2y48KYVst/NNkY8n/iugBv/shUfJmarFrN/5S6nsd0/E6h1XRXrd lYW9DdAU9QPq7qseTYPh5EBmPjBV+wAkagUkWVkquKsQBTN3xszalgCMbYDwFljW+wE8GEIpdyn asoiFrpxdc0T4+Ee15w== X-Proofpoint-GUID: ZvGHo8pv9uZhsEOjORlJEgjW93W4sfyt X-Proofpoint-ORIG-GUID: ZvGHo8pv9uZhsEOjORlJEgjW93W4sfyt X-Authority-Analysis: v=2.4 cv=CPsnnBrD c=1 sm=1 tr=0 ts=698f3a63 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=2hSsElJEpLNoggoceKAA: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-13_03,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 spamscore=0 malwarescore=0 adultscore=0 phishscore=0 clxscore=1015 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602130115 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 Reviewed-by: Nuno S=C3=A1 --- Changes in v3: - Refactor __devm_iio_backend_fwnode_get() to reuse __devm_iio_backend_fwnode_get_by_index() instead of duplicating the lookup logic - Use __free(fwnode_handle) for automatic cleanup instead of manual fwnode_handle_put() - Set back->idx unconditionally in the by_index path drivers/iio/industrialio-backend.c | 61 ++++++++++++++++++++---------- include/linux/iio/backend.h | 2 + 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-= backend.c index 447b694d6d5f..d90a3a0b17c6 100644 --- a/drivers/iio/industrialio-backend.c +++ b/drivers/iio/industrialio-backend.c @@ -949,25 +949,16 @@ int iio_backend_data_transfer_addr(struct iio_backend= *back, u32 address) } EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND"); =20 -static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *de= v, const char *name, - struct fwnode_handle *fwnode) +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 fwnode_handle *fwnode_back __free(fwnode_handle) =3D + fwnode_find_reference(fwnode, "io-backends", index); struct iio_backend *back; - unsigned int index; int ret; =20 - if (name) { - ret =3D device_property_match_string(dev, "io-backend-names", - name); - if (ret < 0) - return ERR_PTR(ret); - index =3D ret; - } else { - index =3D 0; - } - - 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"); @@ -977,21 +968,35 @@ static struct iio_backend *__devm_iio_backend_fwnode_= get(struct device *dev, con if (!device_match_fwnode(back->dev, fwnode_back)) continue; =20 - fwnode_handle_put(fwnode_back); ret =3D __devm_iio_backend_get(dev, back); if (ret) return ERR_PTR(ret); =20 - if (name) - back->idx =3D index; + back->idx =3D index; =20 return back; } =20 - fwnode_handle_put(fwnode_back); return ERR_PTR(-EPROBE_DEFER); } =20 +static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *de= v, const char *name, + struct fwnode_handle *fwnode) +{ + unsigned int index =3D 0; + int ret; + + if (name) { + ret =3D device_property_match_string(dev, "io-backend-names", + name); + if (ret < 0) + return ERR_PTR(ret); + index =3D ret; + } + + return __devm_iio_backend_fwnode_get_by_index(dev, fwnode, index); +} + /** * devm_iio_backend_get - Device managed backend device get * @dev: Consumer device for the backend @@ -1008,6 +1013,24 @@ 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 +/** + * 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 Thu Apr 2 22:25:44 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 8B86C247295; Fri, 13 Feb 2026 14:51:37 +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=1770994304; cv=none; b=SsQf/f2C4LDXHkMnoxiN4phX6OnuSsvsPfsToiH7Yx9l4hCoJx2u0QFpJwhB5j1kexCytbB77yGYm8PxKiHP+dB7dkTixnY5J8maKINQtEIrwezP8sxNWYmCxmnsTamJPeVesDrN5gLJgBqhjrso6kybIHIz9CiqgZRzMGeNCp8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994304; c=relaxed/simple; bh=2R9stgj1I8uGe46/RsE0vCAq2lpe1smKGhJYUPlDxLM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EyUiXiTB9LEBUGiJucuY14mp2/A1zNZEvfCFGccj+UOKqT2BtaaO0sQhW9SzKFbwfGVkApLkOucaJ/3PHeROyP+PccUnpHlJjM4C9Hw8m2OLxBjZZwxUceyw3NGogWkL0AYO+GZA6whWkCFMc9alyc4khRqlqlztifpJEfz2mEg= 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=DSHt/eeu; 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="DSHt/eeu" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61DEEngh1628287; Fri, 13 Feb 2026 09:51:21 -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=+cHLZ zDbEZ0kxwYtWnelM3Qrb2UiIFflK1dYfWm6ii8=; b=DSHt/eeuyxX2OEFMg+98m YuHri0Jj21eBjJOr5CYKzi0xzo2U3IwLGkZENU7rYpUlaoMvHoJ/8VxhSL3jgKur ns37CaPpEIDHaOCLCM00qXQ1KgylQ2P46UJEIO28UduiUAZUfrwCTApQDQsp83ai Pri47yoEakJj9CQm80Xxt1l9llHQFD1K0n89zJrHfW41eOr7bn4U/ii2yVQSdwsJ H9x2TGgP0TCF8WVeq8HS5yJxO9AFyzDfJZKhvPXAn2jZd5RjAU9n2aRuDaxmkX3E 1c59D0nI3a3odc08mXIjtWtAvvkXgxdBqITnDS65LUvFCwTxrJTuywYnDDEQSgMu w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4ca5j504j7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 13 Feb 2026 09:51:21 -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 61DEpKia041679 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 13 Feb 2026 09:51:20 -0500 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1748.37; Fri, 13 Feb 2026 09:51:19 -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, 13 Feb 2026 09:51:19 -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, 13 Feb 2026 09:51:19 -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 61DEop6K018676; Fri, 13 Feb 2026 09:51:12 -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 v3 4/5] dt-bindings: iio: adc: ad4080: add AD4880 support Date: Fri, 13 Feb 2026 16:47:36 +0200 Message-ID: <20260213144742.16394-5-antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260213144742.16394-1-antoniu.miclaus@analog.com> References: <20260213144742.16394-1-antoniu.miclaus@analog.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEzMDExNSBTYWx0ZWRfX1Es5LUNdqdyE Ly2hGRwXjAgQ5hZf06LuPray/6GYyvMsbNarBVFUqFI1dtvamnRQozmJVPNbzssQ3AwmUUtD6zU kTyQ26adfubKKkg2y1uTm8xCaQaIRLLU6mIgwIFj0h7wPFBc8NWq8lGagpnxW/EGUmQWygsNm2t aiSz+w+bmzEhL1s86Cm1JHony4ziE8x4bqWs8RU78l8PEkOiBJVVqTjYrvE7E37kXDxFVZIYHVU 11LAilfnUjA7hLezTWGJ0M7T1dWcd+xmcI98eYnrTgw2hfvNqVQy1U5Bu/tSgVFM1LsNvA0BLZ0 ZhCNArXjK2VJyTLhgVpEDBabYt74JN82Nkl2eiCEAJXY/W/VQmjfd4f6o2geyfCR/mwpkG7lzFk D65TQz/KmQ8co3C0V5TUgoXzFYXPigsgBBp4yZuds+bOIofHPigzFBTlyc3ZxYz8ZbJJaTQXfOW tJ1C6pPGk9DK+L5+YVA== X-Proofpoint-GUID: 62J2WAGO4UIyVhFqFpY1AuVNdsuh_UvU X-Proofpoint-ORIG-GUID: 62J2WAGO4UIyVhFqFpY1AuVNdsuh_UvU X-Authority-Analysis: v=2.4 cv=CPsnnBrD c=1 sm=1 tr=0 ts=698f3a69 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=eYjWAXzLS8b0uuH4XOwA: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-13_03,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 spamscore=0 malwarescore=0 adultscore=0 phishscore=0 clxscore=1015 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602130115 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 v3: - Add items descriptions for io-backends entries - Fix reg example format: reg =3D <0 1> -> reg =3D <0>, <1> .../bindings/iio/adc/adi,ad4080.yaml | 54 ++++++++++++++++++- 1 file changed, 52 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..871bbdd7e1ce 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,11 @@ properties: vrefin-supply: true =20 io-backends: - maxItems: 1 + minItems: 1 + maxItems: 2 + items: + - description: Backend for channel A (primary) + - description: Backend for channel B (secondary) =20 adi,lvds-cnv-enable: description: Enable the LVDS signal type on the CNV pin. Default is CM= OS. @@ -78,6 +92,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 +131,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 Thu Apr 2 22:25:44 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 8A1147260D; Fri, 13 Feb 2026 14:51:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994304; cv=none; b=P1PjWTi48OdWCCUKwRPLcFQsNJFMnGuttH/JSyzBFqJEgNEBT/XTPVCP1sek62k6hB2CGgvqnDmiMONsiCJtR8TmxquR9U305nZjWmv0Ay+NsEzMJuihDrzPHu7Xsl0vQ/8AeCr2hDf3YLkE8kfZkIhiCu99e2yrPiig88QQOAU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770994304; c=relaxed/simple; bh=PcVJqA0ykpUN+FmN9JzfgLy0wKKE00PXf0D576flfOo=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HCDtC4SAUILvApGGChmdtINuqFX2VU+8z8S9KqIAuXk/pDOcUA1svSyBNLTLL9PZK48LgshhWDbnUTXuVheEfgrU8TvW2sHSQn5Xad34nTdeXRd0NLE8sgAYwiqpz4+PBpCcyVTu7W3EP2ZYMV2KeHjjshPYyVh1I3PwB/lBUcI= 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=inOE+5Sh; 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="inOE+5Sh" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 61DEEngi1628287; Fri, 13 Feb 2026 09:51:22 -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=vtnGI CUiAhEX9HhgSymiGFX2YovDP9xZYps7w2fh/z4=; b=inOE+5ShDPQKrEphIt1J8 K9tZ+XnRqOhc36uYUowfneqiX0V8I/DydYjj6DIXfQJ3wYJx8rLb8cPbFqLIg0Wg lbJPSgTniD7Fn4fHXzV+yceDYK13n7p4wV5GCrV0FE+1UrcOcuDqIDg+CUo7bT3m xwa5bCTAfhIZtbeXN1HCJbcyMTUIT4u5eaSpTXH2PpvFfisJ4MuAz9ddfFk3960l GcjtJFWdNcsskgJpRZ7F2X/fKEHdxcvlW9iR3nP9iXrjpDJMMRhKJ9C1CDtKwRq0 MSm9aRg1JDYUB6kqlll0s+nSDsFJK0IgkKrLiXSmhWm5aFbaz9HIz3rCgVZka2PD g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 4ca5j504jb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 13 Feb 2026 09:51:22 -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 61DEpLpp041682 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 13 Feb 2026 09:51:21 -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, 13 Feb 2026 09:51:21 -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, 13 Feb 2026 09:51:20 -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, 13 Feb 2026 09:51:20 -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 61DEop6L018676; Fri, 13 Feb 2026 09:51:15 -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 v3 5/5] iio: adc: ad4080: add support for AD4880 dual-channel ADC Date: Fri, 13 Feb 2026 16:47:37 +0200 Message-ID: <20260213144742.16394-6-antoniu.miclaus@analog.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260213144742.16394-1-antoniu.miclaus@analog.com> References: <20260213144742.16394-1-antoniu.miclaus@analog.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjEzMDExNSBTYWx0ZWRfXz8OHJp5lKL/P 4LA2x2w3Nit8Ij8Dq6Hbz8pPPzs2B78hs6oGDMibAq6TCcEbGzbewW9N/QDTmcfu1G2y1klGB1l pw5R8xAsmawyK8OsHcd/C/+wRZKcl6ZbsPqY2DACDj87umz7IyUCoxxC/JKog2x7x/tndUSi57K GfYh7vtFrStKof8roD1yedM8+Cd4ilInjUXfLquMo554O+343sbJbE/xIY3VuK/A2gvfK0FUPhh Xk1g17Z6uAlOUIkrVYMeKU/cN2ZLQxXpPnj6zyyybNoAI6GzdNkXewCqmyvFK/pvrLPyyetiPoy tpzQN7zt3kDMswa4NxjFzEo0jkW5g1Mke5+QmHhAeGBltGJUD31JHC6KAwaCBGKJuOcY2Aqlswy zVuaEckf+9tQFNxik9QUhPB53w2TybAWB17eOPfxF5ddVynXiitHWJTQrS/zX8mCG7jGAH4QbgN mfrGRUYwK1yo5SnWvGQ== X-Proofpoint-GUID: QYHH0fPcmgRggxNrvD-or22F20TYSuJo X-Proofpoint-ORIG-GUID: QYHH0fPcmgRggxNrvD-or22F20TYSuJo X-Authority-Analysis: v=2.4 cv=CPsnnBrD c=1 sm=1 tr=0 ts=698f3a6a cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=Mpw57Om8IfrbqaoTuvik:22 a=GgsMoib0sEa3-_RKJdDe:22 a=IpJZQVW2AAAA:8 a=gAnH3GRIAAAA:8 a=PfMWlQLGIS_dAahS8X8A:9 a=IawgGOuG5U0WyFbmm1f5:22 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-13_03,2026-02-12_03,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 bulkscore=0 priorityscore=1501 spamscore=0 malwarescore=0 adultscore=0 phishscore=0 clxscore=1015 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2601150000 definitions=main-2602130115 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. Reviewed-by: David Lechner Signed-off-by: Antoniu Miclaus Reviewed-by: Nuno S=C3=A1 --- Changes in v3: - Use devm_spi_new_ancillary_device() instead of manual spi_new_ancillary_device() + devm_add_action_or_reset() - Remove ad4080_unregister_ancillary() cleanup function - Generalize ancillary device setup with loop instead of hardcoding channel 1 drivers/iio/adc/ad4080.c | 248 +++++++++++++++++++++++++++++++-------- 1 file changed, 197 insertions(+), 51 deletions(-) diff --git a/drivers/iio/adc/ad4080.c b/drivers/iio/adc/ad4080.c index 7cf3b6ed7940..36a265ded80d 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,51 @@ 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), \ + .storagebits =3D (storage), \ + }, \ +} + +/* + * 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), \ @@ -438,17 +518,22 @@ 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); +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 @@ -602,6 +711,7 @@ static int ad4080_probe(struct spi_device *spi) 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 +720,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 +731,34 @@ 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 devices for additional channels */ + if (st->info->num_channels > 1) { + u32 reg[AD4080_MAX_CHANNELS]; + + ret =3D device_property_read_u32_array(dev, "reg", reg, + st->info->num_channels); + if (ret) + return dev_err_probe(dev, ret, + "missing reg entries for multi-channel device\n"); + + for (int i =3D 1; i < st->info->num_channels; i++) { + st->spi[i] =3D devm_spi_new_ancillary_device(spi, reg[i]); + if (IS_ERR(st->spi[i])) + return dev_err_probe(dev, PTR_ERR(st->spi[i]), + "failed to register ancillary device\n"); + + st->regmap[i] =3D devm_regmap_init_spi(st->spi[i], + &ad4080_regmap_config); + if (IS_ERR(st->regmap[i])) + return PTR_ERR(st->regmap[i]); + } + } =20 ret =3D devm_mutex_init(dev, &st->lock); if (ret) @@ -632,7 +767,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 +780,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 +814,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 +826,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