From patchwork Tue Jun 4 22:41:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13685955 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 9026E146D78; Tue, 4 Jun 2024 22:42:24 +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=1717540947; cv=none; b=uViDPWVRlwrBYmsOlQSX9tqzXX7hLInZua+QKgSUmzB1S5+oxxZg61Hc5ohXQVo48bGbVZe0pS87gKCLLgL3P8z3Ep84en09+IndFmj9wQEkJq1tz49gl9y9XEWMg89cmQcuXd/CnBIH26HU3tN9PBui7qdm/4Xa962f1d57ZAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717540947; c=relaxed/simple; bh=tPM2gR/fRiqfWScjHlUDfJRBNYSA6t7GX+yS+5VX99c=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gWXDSvXXmWJYhLMBntJVrbk80Naqs4bs8Z0Df1e1ge0ZpnKhogaYYsSEqJFUZ+LI1XcUZqIKSOcVrA4+NkV8ssmTop8Rqj36Opc9TKN6B3eURgAtSsvpS1Ow2qK/s8CK3WlEcbXt6bl/sdvUEtAOV8Z/WOh3a6/JHlYOQi97ALo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=fHO6d+0D; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="fHO6d+0D" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 454ItsG2030377; Tue, 4 Jun 2024 18:42:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=f8sF5 eYr6TUBHybAnubDqM770OQZifscgvyjnnqCi1U=; b=fHO6d+0DD+NAA/XTfL80g 32xWFo0TjV2rHrNdHthy4tuCwka1hgPl15xELfpJbSqel54Wj3inDvruRcm18Pp2 JKmbNC6ZaUH0H8kFRTQsQV4OfQLf2LqL2da6iykDGbECsKu2dxOUcluu4+o71qH3 Yq71SqMV34FmCofIzcfBcfStYQw7/BnTYBGBl3/T53uX1TYIeP0PhW2sov4/VEzf /MxRMNExxoyWRPrbrvg3MF0vNou7hDfJmRP8yx5+UidMH68HXQnog6xyefrvdb45 WWM1EzmXKkFoiMD1foto5AEN9oLgt5g6C++/jpAZpEpkgFJ3kr7w0yvnTG5LDYRg w== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3yg0j1mryn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 04 Jun 2024 18:42:06 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 454Mg5RZ010947 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2024 18:42:05 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:42:04 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 4 Jun 2024 18:42:04 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 454MfnSI001178; Tue, 4 Jun 2024 18:41:51 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 1/6] spi: Add SPI mode bit for MOSI idle state configuration Date: Tue, 4 Jun 2024 19:41:47 -0300 Message-ID: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: J3ZZmvyMtaD4KKJIAji8lRmcVa1x7xHH X-Proofpoint-GUID: J3ZZmvyMtaD4KKJIAji8lRmcVa1x7xHH X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-04_11,2024-06-04_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxlogscore=999 phishscore=0 malwarescore=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406040183 The behavior of an SPI controller data output line (SDO or MOSI or COPI (Controller Output Peripheral Input) for disambiguation) is not specified when the controller is not clocking out data on SCLK edges. However, there exist SPI peripherals that require specific COPI line state when data is not being clocked out of the controller. Add SPI mode bit to allow pheripherals to request explicit COPI idle behavior when needed. Signed-off-by: Marcelo Schmitt --- drivers/spi/spi.c | 6 ++++++ include/uapi/linux/spi/spi.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 289feccca376..6072b6e93bef 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3921,6 +3921,12 @@ int spi_setup(struct spi_device *spi) (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) return -EINVAL; + /* Check against conflicting MOSI idle configuration */ + if ((spi->mode & SPI_MOSI_IDLE_LOW) && (spi->mode & SPI_MOSI_IDLE_HIGH)) { + dev_warn(&spi->dev, + "setup: erratic MOSI idle configuration. Set to idle low\n"); + spi->mode &= ~SPI_MOSI_IDLE_HIGH; + } /* * Help drivers fail *cleanly* when they need options * that aren't supported with their current controller. diff --git a/include/uapi/linux/spi/spi.h b/include/uapi/linux/spi/spi.h index ca56e477d161..ba9adba25927 100644 --- a/include/uapi/linux/spi/spi.h +++ b/include/uapi/linux/spi/spi.h @@ -29,6 +29,7 @@ #define SPI_3WIRE_HIZ _BITUL(15) /* high impedance turnaround */ #define SPI_RX_CPHA_FLIP _BITUL(16) /* flip CPHA on Rx only xfer */ #define SPI_MOSI_IDLE_LOW _BITUL(17) /* leave mosi line low when idle */ +#define SPI_MOSI_IDLE_HIGH _BITUL(18) /* leave mosi line high when idle */ /* * All the bits defined above should be covered by SPI_MODE_USER_MASK. @@ -38,6 +39,6 @@ * These bits must not overlap. A static assert check should make sure of that. * If adding extra bits, make sure to increase the bit index below as well. */ -#define SPI_MODE_USER_MASK (_BITUL(18) - 1) +#define SPI_MODE_USER_MASK (_BITUL(19) - 1) #endif /* _UAPI_SPI_H */ From patchwork Tue Jun 4 22:42:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13685956 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 CE495146D78; Tue, 4 Jun 2024 22:42:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717540976; cv=none; b=J9ojv008vgrh5WJyhi0qi7rqeODiUX95Z59OTZLyyf6IhRg4UZ2WWKhE5w+E3y1W/rzGun1DBYUvI2DP3XS8jvKxblOwgLsDc88/fjN9wSE1B0n/RUS30LN2dWCB6nhCnflwWqYONUfw6UGmferAsbHEP6hQ6HRpYSxhUoMq1xs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717540976; c=relaxed/simple; bh=3tG0AJ54V/5Ge91oaKIU30K3m3EKpg0kyY8NFuqZLls=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=BwTO20XsW4I8oVJmxbnzSM7ITVBIf69BjPB5uslVO0tilHgkZCeq/GiCp6N1H1oFbZNV8Q/uJi6RlL2JoXA+7Shj3UnZ6ehUWMBg5bjhCSg/4NU2d3ZI5YLo0ZWYchmdIh3BXQ3ptBtV/tLWuavJx2gUqZMEcymMyyUmfqiNTiA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=Rh0W9/sD; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="Rh0W9/sD" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 454KLAGr030415; Tue, 4 Jun 2024 18:42:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=O9U8P JcD5IDk0qYWP994r3AXI1cEINGKghFuxXmAI2Y=; b=Rh0W9/sDOBSr8aq/cR+5y IZszR0KKxLlle4O5BGAfL+0Ie50gwHt741MJbMxD2o+rpODsNfV2dNxqipl/drB3 f58fG06UsxHQU+AsJNuAQhma3RIdkQ5htdcJMVEy9SbvMoiM65g9C0ptSB7hZvKe XAEzl9gJ/7XJ77jShHxK8dbvPKNRLLR1FN6rol/4nIEI1YXOsnzXrdpAuUgd9dmZ nPv+yi8LNnTVN4BSantLjI3p0JHL6jYlCaUs5RTAF9HAm3mgNtzdYfvayLmhimCg 2/A1V2d4n/JvfpQh7DbtPaSK7+YSNdftBS0qutkln1UGNFc7GFOSTBjdlffJuen1 Q== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3yg0j1ms0y-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 04 Jun 2024 18:42:39 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 454Mgcod011020 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2024 18:42:38 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:42:37 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:42:37 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 4 Jun 2024 18:42:36 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 454MgNiC001185; Tue, 4 Jun 2024 18:42:25 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 2/6] spi: bitbang: Implement support for MOSI idle state configuration Date: Tue, 4 Jun 2024 19:42:21 -0300 Message-ID: <811a2771d93c16b48fb37286e648a03171c8d2bc.1717539384.git.marcelo.schmitt@analog.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: 74Ay1pOxbiNWrZiqDog6XX2t6ko0SQaD X-Proofpoint-GUID: 74Ay1pOxbiNWrZiqDog6XX2t6ko0SQaD X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-04_11,2024-06-04_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxlogscore=999 phishscore=0 malwarescore=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406040183 Some SPI peripherals may require strict MOSI line state when the controller is not clocking out data. Implement support for MOSI idle state configuration (low or high) by setting the data output line level on controller setup and after transfers. Bitbang operations now call controller specific set_mosi_idle() call back to set MOSI to its idle state. The MOSI line is kept at its idle state if no tx buffer is provided. Signed-off-by: Marcelo Schmitt Acked-by: Nuno Sa --- drivers/spi/spi-bitbang.c | 24 ++++++++++++++++++++++++ include/linux/spi/spi_bitbang.h | 1 + 2 files changed, 25 insertions(+) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index ca5cc67555c5..3dee085d3570 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -63,21 +63,28 @@ static unsigned bitbang_txrx_8( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned count = t->len; const u8 *tx = t->tx_buf; u8 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 0)) { u8 word = 0; if (tx) word = *tx++; + else + word = (spi->mode & SPI_MOSI_IDLE_HIGH) ? 0xFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 1; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } @@ -92,21 +99,28 @@ static unsigned bitbang_txrx_16( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned count = t->len; const u16 *tx = t->tx_buf; u16 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 1)) { u16 word = 0; if (tx) word = *tx++; + else + word = (spi->mode & SPI_MOSI_IDLE_HIGH) ? 0xFFFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 2; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } @@ -121,21 +135,28 @@ static unsigned bitbang_txrx_32( unsigned flags ) { + struct spi_bitbang *bitbang; unsigned bits = t->bits_per_word; unsigned count = t->len; const u32 *tx = t->tx_buf; u32 *rx = t->rx_buf; + bitbang = spi_controller_get_devdata(spi->controller); while (likely(count > 3)) { u32 word = 0; if (tx) word = *tx++; + else + word = (spi->mode & SPI_MOSI_IDLE_HIGH) ? 0xFFFFFFFF : 0; word = txrx_word(spi, ns, word, bits, flags); if (rx) *rx++ = word; count -= 4; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + return t->len - count; } @@ -211,6 +232,9 @@ int spi_bitbang_setup(struct spi_device *spi) goto err_free; } + if (bitbang->set_mosi_idle) + bitbang->set_mosi_idle(spi); + dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs); return 0; diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index b930eca2ef7b..1a54b593c691 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -22,6 +22,7 @@ struct spi_bitbang { #define BITBANG_CS_ACTIVE 1 /* normally nCS, active low */ #define BITBANG_CS_INACTIVE 0 + void (*set_mosi_idle)(struct spi_device *spi); /* txrx_bufs() may handle dma mapping for transfers that don't * already have one (transfer.{tx,rx}_dma is zero), or use PIO */ From patchwork Tue Jun 4 22:42:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13685957 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 2F3B9A5F; Tue, 4 Jun 2024 22:43:34 +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=1717541016; cv=none; b=L5VT1dIH7h9vlUipsm0Sd9rkyCOpFDUbYaJEh6M7Dv2dk34R787FE1Uq2ay92ENzasbLixzZzElz4U6TDO8SCRGAGmQhDKUkNRfq9u5mNXRY5zDQvbXpm+MtMCWlXMvw7qiQzdPUcUvS1eanxOS0Y2T4nNzmo6QcDAaiw/I6Wl8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717541016; c=relaxed/simple; bh=xd9W2Uaq28uqseaO7Rty9ETXeULI54L/WJ0WeG+zeIg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ceLDvIQzr46hFOCMMiKovPCFA5B6rDDGYuyIvhF7OQPWbCWz7wDcOWBIDmMUQvZAJMvIo0+Glg4u4bHUuftB/XBpSEhWJc1YuO3Tj2VPX7udwtnJtp9HfTOJZtVgZ9UVOMj7zh2afu0hHOCsuQARXvOAdLvLBAClMm/VA5aEBKg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=SVUi8TNr; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="SVUi8TNr" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 454KwV4w030387; Tue, 4 Jun 2024 18:43:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=74Jf2 frvsqaSsOeTHOKorXh3HH5oIkv3eucaR50gD3A=; b=SVUi8TNrMtXapbBYjEgOC iWetApcliMJT1xABgH1LyY5iHLOHA4LXbXQoQKBoSzoSBGDAlHzV6EtTzURZubne qcPK6iwtMI51BK13gDTEFpXEoEAA6ShefluTByW8rP9O49bdOCo/h28Rb07GSPn+ jf50HfFi+5JsoVLjbohMfYsWPGXTsFkO5MiJ3HY5iEy+B9G9Hz6bI2WbcqsQydic zozJKU+aJLAz7ENC92KgtB3q7A+/pUXXZlU+rW/ONQqvbX9rZvU2cScJ2Jt4XxvH 7HYT9GMiKCinQw1ODxPYGH9qGspeP/uoPjNkgb2KARya6Q/JkDk5qdVtQMMCaBdT A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3yg0j1ms2m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 04 Jun 2024 18:43:20 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 454MhJBL011092 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2024 18:43:19 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:43:18 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 4 Jun 2024 18:43:18 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 454Mh0Ut001195; Tue, 4 Jun 2024 18:43:02 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 3/6] spi: spi-gpio: Add support for MOSI idle state configuration Date: Tue, 4 Jun 2024 19:42:58 -0300 Message-ID: <8dcce41a69a89cb8ace2587ca7ddb1c665f2d1cb.1717539384.git.marcelo.schmitt@analog.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: ysfdGX-dEfld29ZsW-GV6nDUznLZ9Php X-Proofpoint-GUID: ysfdGX-dEfld29ZsW-GV6nDUznLZ9Php X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-04_11,2024-06-04_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxlogscore=999 phishscore=0 malwarescore=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406040183 Implement MOSI idle low and MOSI idle high to better support peripherals that request specific MOSI behavior. Signed-off-by: Marcelo Schmitt Acked-by: Nuno Sa --- drivers/spi/spi-gpio.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 909cce109bba..d3b8c99f0cb4 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -236,6 +236,14 @@ static void spi_gpio_chipselect(struct spi_device *spi, int is_active) } } +static void spi_gpio_set_mosi_idle(struct spi_device *spi) +{ + struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi); + + gpiod_set_value_cansleep(spi_gpio->mosi, + !!(spi->mode & SPI_MOSI_IDLE_HIGH)); +} + static int spi_gpio_setup(struct spi_device *spi) { struct gpio_desc *cs; @@ -411,7 +419,8 @@ static int spi_gpio_probe(struct platform_device *pdev) host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); host->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | - SPI_CS_HIGH | SPI_LSB_FIRST; + SPI_CS_HIGH | SPI_LSB_FIRST | SPI_MOSI_IDLE_LOW | + SPI_MOSI_IDLE_HIGH; if (!spi_gpio->mosi) { /* HW configuration without MOSI pin * @@ -436,6 +445,7 @@ static int spi_gpio_probe(struct platform_device *pdev) host->flags |= SPI_CONTROLLER_GPIO_SS; bb->chipselect = spi_gpio_chipselect; bb->set_line_direction = spi_gpio_set_direction; + bb->set_mosi_idle = spi_gpio_set_mosi_idle; if (host->flags & SPI_CONTROLLER_NO_TX) { bb->txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; From patchwork Tue Jun 4 22:43:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13685958 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 0447414D280; Tue, 4 Jun 2024 22:44:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717541042; cv=none; b=a5YX3qPIrCWWw1KFe07xxJdW1LxcvIhwlKV8hGCqt0dPePgrUbDAGsJnRVZ4qJuvqvsmTOPvmnzYVxv1POsPNNLg/4zrrW2E+/MYGQMmzpfUjcAPlupr2srpwGJuA3b7/M+5XES5WLO7WGgJtX+oBNQ8bsIpEgKfv2yRvAQGAIE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717541042; c=relaxed/simple; bh=KPLFsuxbLJbSe0NAlvozvC6hvGT606LETzi95E7ckN0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kEly8k49AZa9MBtb04Qo+/s3WA393o7zvlA74ezockd+9hUuuF8l/OriVn4NQvSgsf3UsOKQSMsLoQ+2aG33aSLrAZkg5C8Yeh5vtUgx4Iv+kwVP9Ke2OQg19wrZ4/x1D/hcs8TAMhpufx1v56I7lQD3jVEFYmRsbV2x91hgdb0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=K3n3iQBJ; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="K3n3iQBJ" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 454KLAH2030415; Tue, 4 Jun 2024 18:43:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=xL97q +jQ4u3SlwDZQenxOlqwGsbI4/Nn3jT75ZtbLBc=; b=K3n3iQBJbCiS91Xgl4Md1 VGkMo1ptAjteIFj1cUoxqvoOb80ufaYxBMFpTyx4Mhk4OqJEe2SAmntKpkWS6s+l BxwylUrBbLLCN0kzSw/fIQd18ee67bYdmXbeTt8PDri8ZQJtf9rWhXtE1KUL6Js9 QGOBs7SPI1HSkfYIM5fd+A68l24ARaP6neBYkbiGSMnvdLBsZ0M+VarHwGu1iCzG fkaPwskLVJsDkyn/XNKChHrw06Sp50FdfESpP90Qg2x2lmyqUCW+XGJszSsc/Wmi Vfb8dKq36/VJ/+B4i9PYsJ0R4No99qwGUSwgqNf5QXe8cUafzvj75kKUtV7BMs/X Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3yg0j1ms3j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 04 Jun 2024 18:43:45 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 454Mhiun025156 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2024 18:43:44 -0400 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:43:43 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:43:43 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 4 Jun 2024 18:43:43 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 454MhRj4001211; Tue, 4 Jun 2024 18:43:30 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 4/6] spi: spi-axi-spi-engine: Add support for MOSI idle configuration Date: Tue, 4 Jun 2024 19:43:26 -0300 Message-ID: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-ORIG-GUID: TLJyh7FPKCr0rAg9zbE8pTozA5fyhcd_ X-Proofpoint-GUID: TLJyh7FPKCr0rAg9zbE8pTozA5fyhcd_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-04_11,2024-06-04_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 suspectscore=0 bulkscore=0 spamscore=0 clxscore=1015 mlxlogscore=999 phishscore=0 malwarescore=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406040183 Implement MOSI idle low and MOSI idle high to better support peripherals that request specific MOSI behavior. Signed-off-by: Marcelo Schmitt Reviewed-by: Nuno Sa --- drivers/spi/spi-axi-spi-engine.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 0aa31d745734..549f03069d0e 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -41,6 +41,7 @@ #define SPI_ENGINE_CONFIG_CPHA BIT(0) #define SPI_ENGINE_CONFIG_CPOL BIT(1) #define SPI_ENGINE_CONFIG_3WIRE BIT(2) +#define SPI_ENGINE_CONFIG_SDO_IDLE BIT(3) #define SPI_ENGINE_INST_TRANSFER 0x0 #define SPI_ENGINE_INST_ASSERT 0x1 @@ -132,6 +133,10 @@ static unsigned int spi_engine_get_config(struct spi_device *spi) config |= SPI_ENGINE_CONFIG_CPHA; if (spi->mode & SPI_3WIRE) config |= SPI_ENGINE_CONFIG_3WIRE; + if (spi->mode & SPI_MOSI_IDLE_HIGH) + config |= SPI_ENGINE_CONFIG_SDO_IDLE; + if (spi->mode & SPI_MOSI_IDLE_LOW) + config &= ~SPI_ENGINE_CONFIG_SDO_IDLE; return config; } @@ -645,7 +650,8 @@ static int spi_engine_probe(struct platform_device *pdev) return ret; host->dev.of_node = pdev->dev.of_node; - host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE | SPI_MOSI_IDLE_LOW + | SPI_MOSI_IDLE_HIGH; host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); host->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; host->transfer_one_message = spi_engine_transfer_one_message; From patchwork Tue Jun 4 22:43:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13685959 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 A0EF514C58A; Tue, 4 Jun 2024 22:44:27 +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=1717541069; cv=none; b=LsGyz4QmNknfB5kM3+G2e+C93Z83W531sLoH3l6Y2g4KYViMKKBEydAyqWdCqk8eFiHVJOROtEgzG/c29rshSFYVhw+CpMrw4kpbUUklU8VX7k+6nLl94fsTRnN1zrtNMFRQ1nJA3ZpGzdp/iuhr9GAzmuESyr22Rq4afz01qDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717541069; c=relaxed/simple; bh=ivPwrYTq+vRnj37RSY64wulzYjdkOp5wkXzYaqR7tDo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ceZ39YsKf4wtf+x7y0zmvSNMoEezjvTMLCwgZbOiKU4ibjqyAvvPu/SImvtGvrWuLrNA/2xzIA4hgiiv8HYsgJmdpjqf62+MoPUYjXo1Gn92GeTPhxZ/00dN7VL9jfc83GsoTHRvP5NyKC0VWOT2tHCfySls57OZE0F8MyhdCf0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=lkQdQptW; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="lkQdQptW" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 454LiBfo024201; Tue, 4 Jun 2024 18:44:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=zQbB8 yW5qEMo220BkUS6kkHP95TQWPMU57n41F7KHHA=; b=lkQdQptWWi9NdpK2nOdv5 7jGzGcAvW7Ez8R1jTEKd40OCxf8SDaoLOebMcySln24B1XhklIAlbSonH3xG1LZ1 VDSQK2nvi2/C8B5jYNZvocG78AlTXvi2RBp9rtpeevtSXcViaLpnUGFV4WFEsWlL 4X0EZuBvFn6sp4DKTigazXKhAo3kP4fkj7/NE6TVkIwfBYh3+uYihYs92cP27SWN QLfTBV/YlZwKbXtaPHUkg8mSJsOCRLebE7uDNlqmFWFfTGK7lmTDrvWcNrUSQ2Ld wUYjd9T71fMsa1+aovLUmHgryBsL4glkVYE+xHtTJoIrjAc7q0ejoj32f/IvPvtI w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 3yjb3r8597-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 04 Jun 2024 18:44:11 -0400 (EDT) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 454MiAbE025162 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 4 Jun 2024 18:44:10 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Tue, 4 Jun 2024 18:44:09 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Tue, 4 Jun 2024 18:44:09 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 454MhsHH001223; Tue, 4 Jun 2024 18:43:57 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 5/6] dt-bindings: iio: adc: Add AD4000 Date: Tue, 4 Jun 2024 19:43:53 -0300 Message-ID: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: P_svA2_nYsDNLd9ZknOvEw70YmgonR9t X-Proofpoint-ORIG-GUID: P_svA2_nYsDNLd9ZknOvEw70YmgonR9t X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-04_11,2024-06-04_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 clxscore=1015 mlxscore=0 phishscore=0 impostorscore=0 adultscore=0 malwarescore=0 spamscore=0 suspectscore=0 mlxlogscore=999 bulkscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406040184 Add device tree documentation for AD4000 series of ADC devices. Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ad4000-4004-4008.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ad4001-4005.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ad4002-4006-4010.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ad4003-4007-4011.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ad4020-4021-4022.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4001.pdf Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4003.pdf Suggested-by: David Lechner Signed-off-by: Marcelo Schmitt --- Even though didn't pick all suggestions to the dt-bindings, I did pick most them so kept David's Suggested-by tag. .../bindings/iio/adc/adi,ad4000.yaml | 207 ++++++++++++++++++ MAINTAINERS | 7 + 2 files changed, 214 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml new file mode 100644 index 000000000000..7470d386906b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml @@ -0,0 +1,207 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad4000.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD4000 and similar Analog to Digital Converters + +maintainers: + - Marcelo Schmitt + +description: | + Analog Devices AD4000 family of Analog to Digital Converters with SPI support. + Specifications can be found at: + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4000-4004-4008.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4001-4005.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4002-4006-4010.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4003-4007-4011.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/ad4020-4021-4022.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4001.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4003.pdf + +$ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - adi,ad4000 + - adi,ad4001 + - adi,ad4002 + - adi,ad4003 + - adi,ad4004 + - adi,ad4005 + - adi,ad4006 + - adi,ad4007 + - adi,ad4008 + - adi,ad4010 + - adi,ad4011 + - adi,ad4020 + - adi,ad4021 + - adi,ad4022 + - adi,adaq4001 + - adi,adaq4003 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 102040816 # for VIO > 2.7 V, 81300813 for VIO > 1.7 V + + adi,spi-mode: + $ref: /schemas/types.yaml#/definitions/string + enum: [ single, chain ] + description: | + This property indicates the SPI wiring configuration. + + When this property is omitted, it is assumed that the device is using what + the datasheet calls "4-wire mode". This is the conventional SPI mode used + when there are multiple devices on the same bus. In this mode, the CNV + line is used to initiate the conversion and the SDI line is connected to + CS on the SPI controller. + + When this property is present, it indicates that the device is using one + of the following alternative wiring configurations: + + * single: The datasheet calls this "3-wire mode". (NOTE: The datasheet's + definition of 3-wire mode is NOT at all related to the standard + spi-3wire property!) This mode is often used when the ADC is the only + device on the bus. In this mode, SDI is connected to MOSI or to VIO, and + the CNV line can be connected to the CS line of the SPI controller or to + a GPIO, in which case the CS line of the controller is unused. + * chain: The datasheet calls this "chain mode". This mode is used to save + on wiring when multiple ADCs are used. In this mode, the SDI line of + one chip is tied to the SDO of the next chip in the chain and the SDI of + the last chip in the chain is tied to GND. Only the first chip in the + chain is connected to the SPI bus. The CNV line of all chips are tied + together. The CS line of the SPI controller can be used as the CNV line + only if it is active high. + + '#daisy-chained-devices': true + + vdd-supply: + description: A 1.8V supply that powers the chip (VDD). + + vio-supply: + description: + A 1.8V to 5.5V supply for the digital inputs and outputs (VIO). + + ref-supply: + description: + A 2.5 to 5V supply for the external reference voltage (REF). + + cnv-gpios: + description: + The Convert Input (CNV). This input has multiple functions. It initiates + the conversions and selects the SPI mode of the device (chain or CS). In + 'single' mode, this property is omitted if the CNV pin is connected to the + CS line of the SPI controller. + maxItems: 1 + + adi,high-z-input: + type: boolean + description: + High-Z mode allows the amplifier and RC filter in front of the ADC to be + chosen based on the signal bandwidth of interest, rather than the settling + requirements of the switched capacitor SAR ADC inputs. + + adi,gain-milli: + description: | + The hardware gain applied to the ADC input (in milli units). + The gain provided by the ADC input scaler is defined by the hardware + connections between chip pins OUT+, R1K-, R1K1-, R1K+, R1K1+, and OUT-. + If not present, default to 1000 (no actual gain applied). + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [454, 909, 1000, 1900] + default: 1000 + + interrupts: + description: + The SDO pin can also function as a busy indicator. This node should be + connected to an interrupt that is triggered when the SDO line goes low + while the SDI line is high and the CNV line is low ('single' mode) or the + SDI line is low and the CNV line is high ('multi' mode); or when the SDO + line goes high while the SDI and CNV lines are high (chain mode), + maxItems: 1 + +required: + - compatible + - reg + - vdd-supply + - vio-supply + - ref-supply + +allOf: + # in '4-wire' mode, cnv-gpios is required, for other modes it is optional + - if: + not: + required: + - adi,spi-mode + then: + required: + - cnv-gpios + # chain mode has lower SCLK max rate + - if: + required: + - adi,spi-mode + properties: + adi,spi-mode: + const: chain + then: + properties: + spi-max-frequency: + maximum: 50000000 # for VIO > 2.7 V, 40000000 for VIO > 1.7 V + required: + - '#daisy-chained-devices' + else: + properties: + '#daisy-chained-devices': false + # Gain property only applies to ADAQ devices + - if: + properties: + compatible: + not: + contains: + enum: + - adi,adaq4001 + - adi,adaq4003 + then: + properties: + adi,gain-milli: false + +unevaluatedProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + /* Example for a AD devices */ + adc@0 { + compatible = "adi,ad4020"; + reg = <0>; + spi-max-frequency = <71000000>; + vdd-supply = <&supply_1_8V>; + vio-supply = <&supply_1_8V>; + ref-supply = <&supply_5V>; + cnv-gpios = <&gpio0 88 GPIO_ACTIVE_HIGH>; + }; + }; + - | + spi { + #address-cells = <1>; + #size-cells = <0>; + /* Example for a ADAQ devices */ + adc@0 { + compatible = "adi,adaq4003"; + reg = <0>; + adi,spi-mode = "single"; + spi-max-frequency = <80000000>; + vdd-supply = <&supply_1_8V>; + vio-supply = <&supply_1_8V>; + ref-supply = <&supply_5V>; + adi,high-z-input; + adi,gain-milli = <454>; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index bff979a507ba..1f052b9cd912 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1200,6 +1200,13 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml F: drivers/iio/dac/ad3552r.c +ANALOG DEVICES INC AD4000 DRIVER +M: Marcelo Schmitt +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml + ANALOG DEVICES INC AD4130 DRIVER M: Cosmin Tanislav L: linux-iio@vger.kernel.org From patchwork Wed Jun 5 11:14:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Schmitt X-Patchwork-Id: 13686668 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 A470E19148B; Wed, 5 Jun 2024 11:15:29 +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=1717586132; cv=none; b=SeICDbbc6oespMvlkXXOoeO+xQ6CYlvD8Qu39Nfe7TsVK6K4+Rsc8nQ2yCIv7mxUyp+T0VYYjjqfwLIYcYWlsiwXt/BB51Yohtx/apbh6Copwcnt7ICmL5l42bQDbsooJlYS3QQy8xmgcvHILMZ3aU+d0yOd3u6tNqeh5V0BKZg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717586132; c=relaxed/simple; bh=NaQUue2ZOUIMp14z7qeqQmhNcxu9qWz65kcHxbFP9H8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=N+1101IbuYqMKhthsECQHwtOw6ftHtKFKY+Pg06svxrNsKBg5pvuAN7RUrE2+SL4nA4PZQZr+BjodDwJEeTG37ufy2ikdvWznfORgngj6hGJubU8k89VHQBMMCN99d9HZ/q+sQzvYU8TiSz7tl5yODIpGEDsp7nPz6iSLc6QWbo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=VATbcuxk; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="VATbcuxk" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4558dQ3T014926; Wed, 5 Jun 2024 07:15:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=prdNk VhOnuep76eAECLUEqTdPb5agBMQHdOnn2LeGSA=; b=VATbcuxkCQlYfvXuQrs3B WhPAkbqfnqwdEyb9dfJ9yd+PXmmKcTb3PBrv2UtwoxPB45XuQiBUcjjg+MYpLbgi U7pp0wIjGzyt7vjqwy35qTW90uxnpdjA+fAt6Rm54YcIUdndo5oD/N+fVQ1682ba 7LlTtLal1PTNVJlo9rBCsREgSH4l+BA/JJ9+6s+gzVecQe0GpYK8VKsXTmnJbYhf PlrnkqnzV4phZ+rD98h0JMFSez8hdU6fjv4Hko+JU9U1k4kscq3yzwwN8QRd1X1W cJrWskjEIxD7EPFsKJJNX2XgZEC3tmgt2Thc60TghzVuQ0fhIJ2QnjA8fy6N4ZYP A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 3yj0hvcx36-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 05 Jun 2024 07:15:10 -0400 (EDT) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 455BF8c0010485 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 5 Jun 2024 07:15:08 -0400 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 5 Jun 2024 07:15:07 -0400 Received: from ASHBMBX9.ad.analog.com (10.64.17.10) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Wed, 5 Jun 2024 07:15:07 -0400 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 5 Jun 2024 07:15:07 -0400 Received: from work.ad.analog.com (HYB-hERzalRezfV.ad.analog.com [10.65.205.129]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 455BErwM020834; Wed, 5 Jun 2024 07:14:56 -0400 From: Marcelo Schmitt To: , , , , , , , , , CC: , , , Subject: [PATCH v3 6/6] iio: adc: Add support for AD4000 Date: Wed, 5 Jun 2024 08:14:50 -0300 Message-ID: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: cUYeOmut9t7Q1qnU3-sP4vnkFKb9Ap1P X-Proofpoint-ORIG-GUID: cUYeOmut9t7Q1qnU3-sP4vnkFKb9Ap1P X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-06-05_01,2024-06-05_02,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 clxscore=1015 mlxscore=0 spamscore=0 adultscore=0 bulkscore=0 phishscore=0 priorityscore=1501 malwarescore=0 mlxlogscore=999 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405170001 definitions=main-2406050084 Add support for AD4000 series of low noise, low power, high speed, successive aproximation register (SAR) ADCs. Signed-off-by: Marcelo Schmitt --- MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 12 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ad4000.c | 735 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 749 insertions(+) create mode 100644 drivers/iio/adc/ad4000.c diff --git a/MAINTAINERS b/MAINTAINERS index 1f052b9cd912..c732cf13f511 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1206,6 +1206,7 @@ L: linux-iio@vger.kernel.org S: Supported W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml +F: drivers/iio/adc/ad4000.c ANALOG DEVICES INC AD4130 DRIVER M: Cosmin Tanislav diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 5030319249c5..dcc49d9711a4 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -21,6 +21,18 @@ config AD_SIGMA_DELTA select IIO_BUFFER select IIO_TRIGGERED_BUFFER +config AD4000 + tristate "Analog Devices AD4000 ADC Driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices AD4000 high speed + SPI analog to digital converters (ADC). + + To compile this driver as a module, choose M here: the module will be + called ad4000. + config AD4130 tristate "Analog Device AD4130 ADC Driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 37ac689a0209..c32bd0ef6128 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -6,6 +6,7 @@ # When adding new entries keep the list in alphabetical order obj-$(CONFIG_AB8500_GPADC) += ab8500-gpadc.o obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o +obj-$(CONFIG_AD4000) += ad4000.o obj-$(CONFIG_AD4130) += ad4130.o obj-$(CONFIG_AD7091R) += ad7091r-base.o obj-$(CONFIG_AD7091R5) += ad7091r5.o diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c new file mode 100644 index 000000000000..55dc36fbd549 --- /dev/null +++ b/drivers/iio/adc/ad4000.c @@ -0,0 +1,735 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * AD4000 SPI ADC driver + * + * Copyright 2024 Analog Devices Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD4000_READ_COMMAND 0x54 +#define AD4000_WRITE_COMMAND 0x14 + +#define AD4000_CONFIG_REG_MSK 0xFF + +/* AD4000 Configuration Register programmable bits */ +#define AD4000_CFG_STATUS BIT(4) /* Status bits output */ +#define AD4000_CFG_SPAN_COMP BIT(3) /* Input span compression */ +#define AD4000_CFG_HIGHZ BIT(2) /* High impedance mode */ +#define AD4000_CFG_TURBO BIT(1) /* Turbo mode */ + +#define AD4000_TQUIET1_NS 190 +#define AD4000_TQUIET2_NS 60 +#define AD4000_TCONV_NS 320 + +#define AD4000_18BIT_MSK GENMASK(31, 14) +#define AD4000_20BIT_MSK GENMASK(31, 12) + +#define AD4000_DIFF_CHANNEL(_sign, _real_bits) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .differential = 1, \ + .channel = 0, \ + .channel2 = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),\ + .scan_type = { \ + .sign = _sign, \ + .realbits = _real_bits, \ + .storagebits = _real_bits > 16 ? 32 : 16, \ + .shift = _real_bits > 16 ? 32 - _real_bits : 0, \ + .endianness = IIO_BE, \ + }, \ + } \ + +#define AD4000_PSEUDO_DIFF_CHANNEL(_sign, _real_bits) \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE),\ + .scan_type = { \ + .sign = _sign, \ + .realbits = _real_bits, \ + .storagebits = _real_bits > 16 ? 32 : 16, \ + .shift = _real_bits > 16 ? 32 - _real_bits : 0, \ + .endianness = IIO_BE, \ + }, \ + } \ + +enum ad4000_ids { + ID_AD4000, + ID_AD4001, + ID_AD4002, + ID_AD4003, + ID_AD4004, + ID_AD4005, + ID_AD4006, + ID_AD4007, + ID_AD4008, + ID_AD4010, + ID_AD4011, + ID_AD4020, + ID_AD4021, + ID_AD4022, + ID_ADAQ4001, + ID_ADAQ4003, +}; + +enum ad4000_spi_mode { + /* datasheet calls this "4-wire mode" (controller CS goes to ADC SDI!) */ + AD4000_SPI_MODE_DEFAULT, + /* datasheet calls this "3-wire mode" (not related to SPI_3WIRE!) */ + AD4000_SPI_MODE_SINGLE, +}; + +/* maps adi,spi-mode property value to enum */ +static const char * const ad4000_spi_modes[] = { + [AD4000_SPI_MODE_DEFAULT] = "", + [AD4000_SPI_MODE_SINGLE] = "single", +}; + +struct ad4000_chip_info { + const char *dev_name; + struct iio_chan_spec chan_spec; +}; + +static const struct ad4000_chip_info ad4000_chips[] = { + [ID_AD4000] = { + .dev_name = "ad4000", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16), + }, + [ID_AD4001] = { + .dev_name = "ad4001", + .chan_spec = AD4000_DIFF_CHANNEL('s', 16), + }, + [ID_AD4002] = { + .dev_name = "ad4002", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18), + }, + [ID_AD4003] = { + .dev_name = "ad4003", + .chan_spec = AD4000_DIFF_CHANNEL('s', 18), + }, + [ID_AD4004] = { + .dev_name = "ad4004", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16), + }, + [ID_AD4005] = { + .dev_name = "ad4005", + .chan_spec = AD4000_DIFF_CHANNEL('s', 16), + }, + [ID_AD4006] = { + .dev_name = "ad4006", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18), + }, + [ID_AD4007] = { + .dev_name = "ad4007", + .chan_spec = AD4000_DIFF_CHANNEL('s', 18), + }, + [ID_AD4008] = { + .dev_name = "ad4008", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 16), + }, + [ID_AD4010] = { + .dev_name = "ad4010", + .chan_spec = AD4000_PSEUDO_DIFF_CHANNEL('u', 18), + }, + [ID_AD4011] = { + .dev_name = "ad4011", + .chan_spec = AD4000_DIFF_CHANNEL('s', 18), + }, + [ID_AD4020] = { + .dev_name = "ad4020", + .chan_spec = AD4000_DIFF_CHANNEL('s', 20), + }, + [ID_AD4021] = { + .dev_name = "ad4021", + .chan_spec = AD4000_DIFF_CHANNEL('s', 20), + }, + [ID_AD4022] = { + .dev_name = "ad4022", + .chan_spec = AD4000_DIFF_CHANNEL('s', 20), + }, + [ID_ADAQ4001] = { + .dev_name = "adaq4001", + .chan_spec = AD4000_DIFF_CHANNEL('s', 16), + }, + [ID_ADAQ4003] = { + .dev_name = "adaq4003", + .chan_spec = AD4000_DIFF_CHANNEL('s', 18), + }, +}; + +struct ad4000_state { + struct spi_device *spi; + struct gpio_desc *cnv_gpio; + struct spi_transfer xfers[2]; + struct spi_message msg; + int vref; + enum ad4000_spi_mode spi_mode; + bool span_comp; + bool turbo_mode; + int gain_milli; + int scale_tbl[2][2]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + struct { + union { + __be16 sample_buf16; + __be32 sample_buf32; + } data; + s64 timestamp __aligned(8); + } scan __aligned(IIO_DMA_MINALIGN); + __be16 tx_buf; + __be16 rx_buf; +}; + +static void ad4000_fill_scale_tbl(struct ad4000_state *st, int scale_bits, + const struct ad4000_chip_info *chip) +{ + int diff = chip->chan_spec.differential; + int val, val2, tmp0, tmp1; + u64 tmp2; + + val2 = scale_bits; + val = st->vref / 1000; + /* + * The gain is stored as a fraction of 1000 and, as we need to + * divide vref by gain, we invert the gain/1000 fraction. + * Also multiply by an extra MILLI to avoid losing precision. + */ + val = mult_frac(val, MILLI * MILLI, st->gain_milli); + /* Would multiply by NANO here but we multiplied by extra MILLI */ + tmp2 = shift_right((u64)val * MICRO, val2); + tmp0 = (int)div_s64_rem(tmp2, NANO, &tmp1); + /* Store scale for when span compression is disabled */ + st->scale_tbl[0][0] = tmp0; /* Integer part */ + st->scale_tbl[0][1] = abs(tmp1); /* Fractional part */ + /* Store scale for when span compression is enabled */ + st->scale_tbl[1][0] = tmp0; + /* The integer part is always zero so don't bother to divide it. */ + if (diff) + st->scale_tbl[1][1] = DIV_ROUND_CLOSEST(abs(tmp1) * 4, 5); + else + st->scale_tbl[1][1] = DIV_ROUND_CLOSEST(abs(tmp1) * 9, 10); +} + +static int ad4000_write_reg(struct ad4000_state *st, uint8_t val) +{ + st->tx_buf = cpu_to_be16(AD4000_WRITE_COMMAND << BITS_PER_BYTE | val); + return spi_write(st->spi, &st->tx_buf, 2); +} + +static int ad4000_read_reg(struct ad4000_state *st, unsigned int *val) +{ + struct spi_transfer t[] = { + { + .tx_buf = &st->tx_buf, + .rx_buf = &st->rx_buf, + .len = 2, + }, + }; + int ret; + + st->tx_buf = cpu_to_be16(AD4000_READ_COMMAND << BITS_PER_BYTE); + ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); + if (ret < 0) + return ret; + + *val = be16_to_cpu(st->rx_buf); + + return ret; +} + +static void ad4000_unoptimize_msg(void *msg) +{ + spi_unoptimize_message(msg); +} + +/* + * This executes a data sample transfer for when the device connections are + * in "3-wire" mode, selected by setting the adi,spi-mode device tree property + * to "single". In this connection mode, the ADC SDI pin is connected to MOSI or + * to VIO and ADC CNV pin is connected either to a SPI controller CS or to a GPIO. + * AD4000 series of devices initiate conversions on the rising edge of CNV pin. + * + * If the CNV pin is connected to an SPI controller CS line (which is by default + * active low), the ADC readings would have a latency (delay) of one read. + * Moreover, since we also do ADC sampling for filling the buffer on triggered + * buffer mode, the timestamps of buffer readings would be disarranged. + * To prevent the read latency and reduce the time discrepancy between the + * sample read request and the time of actual sampling by the ADC, do a + * preparatory transfer to pulse the CS/CNV line. + */ +static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st, + const struct iio_chan_spec *chan) +{ + unsigned int cnv_pulse_time = st->turbo_mode ? AD4000_TQUIET1_NS + : AD4000_TCONV_NS; + struct spi_transfer *xfers = st->xfers; + int ret; + + xfers[0].cs_change = 1; + xfers[0].cs_change_delay.value = cnv_pulse_time; + xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = &st->scan.data; + xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); + xfers[1].delay.value = AD4000_TQUIET2_NS; + xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS; + + spi_message_init_with_transfers(&st->msg, st->xfers, 2); + + ret = spi_optimize_message(st->spi, &st->msg); + if (ret) + return ret; + + return devm_add_action_or_reset(&st->spi->dev, ad4000_unoptimize_msg, + &st->msg); +} + +/* + * This executes a data sample transfer for when the device connections are + * in "4-wire" mode, selected when the adi,spi-mode device tree + * property is absent or empty. In this connection mode, the controller CS pin + * is connected to ADC SDI pin and a GPIO is connected to ADC CNV pin. + * The GPIO connected to ADC CNV pin is set outside of the SPI transfer. + */ +static int ad4000_prepare_4wire_mode_message(struct ad4000_state *st, + const struct iio_chan_spec *chan) +{ + unsigned int cnv_to_sdi_time = st->turbo_mode ? AD4000_TQUIET1_NS + : AD4000_TCONV_NS; + struct spi_transfer *xfers = st->xfers; + int ret; + + /* + * Dummy transfer to cause enough delay between CNV going high and SDI + * going low. + */ + xfers[0].cs_off = 1; + xfers[0].delay.value = cnv_to_sdi_time; + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + xfers[1].rx_buf = &st->scan.data; + xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); + + spi_message_init_with_transfers(&st->msg, st->xfers, 2); + + ret = spi_optimize_message(st->spi, &st->msg); + if (ret) + return ret; + + return devm_add_action_or_reset(&st->spi->dev, ad4000_unoptimize_msg, + &st->msg); +} + +static int ad4000_convert_and_acquire(struct ad4000_state *st) +{ + int ret; + + /* + * In 4-wire mode, the CNV line is held high for the entire conversion + * and acquisition process. In other modes st->cnv_gpio is NULL and is + * ignored (CS is wired to CNV in those cases). + */ + gpiod_set_value_cansleep(st->cnv_gpio, 1); + ret = spi_sync(st->spi, &st->msg); + gpiod_set_value_cansleep(st->cnv_gpio, 0); + + return ret; +} + +static int ad4000_single_conversion(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val) +{ + struct ad4000_state *st = iio_priv(indio_dev); + u32 sample; + int ret; + + ret = ad4000_convert_and_acquire(st); + + if (chan->scan_type.storagebits > 16) + sample = be32_to_cpu(st->scan.data.sample_buf32); + else + sample = be16_to_cpu(st->scan.data.sample_buf16); + + switch (chan->scan_type.realbits) { + case 16: + break; + case 18: + sample = FIELD_GET(AD4000_18BIT_MSK, sample); + break; + case 20: + sample = FIELD_GET(AD4000_20BIT_MSK, sample); + break; + default: + return -EINVAL; + } + + if (chan->scan_type.sign == 's') + *val = sign_extend32(sample, chan->scan_type.realbits - 1); + + return IIO_VAL_INT; +} + +static int ad4000_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long info) +{ + struct ad4000_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_RAW: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) + return ad4000_single_conversion(indio_dev, chan, val); + unreachable(); + case IIO_CHAN_INFO_SCALE: + *val = st->scale_tbl[st->span_comp][0]; + *val2 = st->scale_tbl[st->span_comp][1]; + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_OFFSET: + *val = 0; + if (st->span_comp) + *val = mult_frac(st->vref / 1000, 1, 10); + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad4000_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long info) +{ + struct ad4000_state *st = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SCALE: + *vals = (int *)st->scale_tbl; + *length = 2 * 2; + *type = IIO_VAL_INT_PLUS_NANO; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int ad4000_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + +static int ad4000_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, + long mask) +{ + struct ad4000_state *st = iio_priv(indio_dev); + unsigned int reg_val; + bool span_comp_en; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret = ad4000_read_reg(st, ®_val); + if (ret < 0) + return ret; + + span_comp_en = (val2 == st->scale_tbl[1][1]); + reg_val &= ~AD4000_CFG_SPAN_COMP; + reg_val |= FIELD_PREP(AD4000_CFG_SPAN_COMP, span_comp_en); + + ret = ad4000_write_reg(st, reg_val); + if (ret < 0) + return ret; + + st->span_comp = span_comp_en; + return 0; + } + unreachable(); + default: + return -EINVAL; + } +} + +static irqreturn_t ad4000_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad4000_state *st = iio_priv(indio_dev); + int ret; + + ret = ad4000_convert_and_acquire(st); + if (ret < 0) + goto err_out; + + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, + iio_get_time_ns(indio_dev)); + +err_out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static int ad4000_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct ad4000_state *st = iio_priv(indio_dev); + int ret; + + if (readval) + ret = ad4000_read_reg(st, readval); + else + ret = ad4000_write_reg(st, writeval); + + return ret; +} + +static const struct iio_info ad4000_info = { + .read_raw = &ad4000_read_raw, + .read_avail = &ad4000_read_avail, + .write_raw = &ad4000_write_raw, + .write_raw_get_fmt = &ad4000_write_raw_get_fmt, + .debugfs_reg_access = &ad4000_reg_access, + +}; + +static int ad4000_config(struct ad4000_state *st) +{ + unsigned int reg_val; + + if (device_property_present(&st->spi->dev, "adi,high-z-input")) + reg_val |= FIELD_PREP(AD4000_CFG_HIGHZ, 1); + + /* + * The ADC SDI pin might be connected to controller CS line in which + * case the write might fail. This, however, does not prevent the device + * from functioning even though in a configuration other than the + * requested one. + */ + return ad4000_write_reg(st, reg_val); +} + +static void ad4000_regulator_disable(void *reg) +{ + regulator_disable(reg); +} + +static int ad4000_probe(struct spi_device *spi) +{ + const struct ad4000_chip_info *chip; + struct regulator *vref_reg; + struct iio_dev *indio_dev; + struct ad4000_state *st; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + chip = spi_get_device_match_data(spi); + if (!chip) + return -EINVAL; + + st = iio_priv(indio_dev); + st->spi = spi; + + ret = devm_regulator_get_enable(&spi->dev, "vdd"); + if (ret) + return dev_err_probe(&spi->dev, ret, "Failed to enable VDD supply\n"); + + ret = devm_regulator_get_enable(&spi->dev, "vio"); + if (ret) + return dev_err_probe(&spi->dev, ret, "Failed to enable VIO supply\n"); + + vref_reg = devm_regulator_get(&spi->dev, "ref"); + if (IS_ERR(vref_reg)) + return dev_err_probe(&spi->dev, PTR_ERR(vref_reg), + "Failed to get vref regulator\n"); + + ret = regulator_enable(vref_reg); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "Failed to enable voltage regulator\n"); + + ret = devm_add_action_or_reset(&spi->dev, ad4000_regulator_disable, vref_reg); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to add regulator disable action\n"); + + st->vref = regulator_get_voltage(vref_reg); + if (st->vref < 0) + return dev_err_probe(&spi->dev, st->vref, "Failed to get vref\n"); + + st->cnv_gpio = devm_gpiod_get_optional(&spi->dev, "cnv", GPIOD_OUT_HIGH); + if (IS_ERR(st->cnv_gpio)) + return dev_err_probe(&spi->dev, PTR_ERR(st->cnv_gpio), + "Failed to get CNV GPIO"); + + ret = device_property_match_property_string(&spi->dev, "adi,spi-mode", + ad4000_spi_modes, + ARRAY_SIZE(ad4000_spi_modes)); + /* Default to 4-wire mode if adi,spi-mode property is not present */ + if (ret == -EINVAL) + st->spi_mode = AD4000_SPI_MODE_DEFAULT; + else if (ret < 0) + return dev_err_probe(&spi->dev, ret, + "getting adi,spi-mode property failed\n"); + else + st->spi_mode = ret; + + switch (st->spi_mode) { + case AD4000_SPI_MODE_DEFAULT: + ret = ad4000_prepare_4wire_mode_message(st, &chip->chan_spec); + if (ret) + return ret; + + break; + case AD4000_SPI_MODE_SINGLE: + ret = ad4000_prepare_3wire_mode_message(st, &chip->chan_spec); + if (ret) + return ret; + + /* + * In "3-wire mode", the ADC SDI line must be kept high when + * data is not being clocked out of the controller. + * Request the SPI controller to make MOSI idle high. + */ + spi->mode = SPI_MODE_0 | SPI_MOSI_IDLE_HIGH; + if (spi_setup(spi)) + dev_warn(&st->spi->dev, "SPI controller setup failed\n"); + + break; + } + + ret = ad4000_config(st); + if (ret < 0) + dev_dbg(&st->spi->dev, "Failed to config device\n"); + + indio_dev->name = chip->dev_name; + indio_dev->info = &ad4000_info; + indio_dev->channels = &chip->chan_spec; + indio_dev->num_channels = 1; + + /* Hardware gain only applies to ADAQ devices */ + st->gain_milli = 1000; + if (device_property_present(&spi->dev, "adi,gain-milli")) { + + ret = device_property_read_u32(&spi->dev, "adi,gain-milli", + &st->gain_milli); + if (ret) + return dev_err_probe(&spi->dev, ret, + "Failed to read gain property\n"); + } + + /* + * ADCs that output two's complement code have one less bit to express + * voltage magnitude. + */ + if (chip->chan_spec.scan_type.sign == 's') + ad4000_fill_scale_tbl(st, chip->chan_spec.scan_type.realbits - 1, + chip); + else + ad4000_fill_scale_tbl(st, chip->chan_spec.scan_type.realbits, + chip); + + ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, + &iio_pollfunc_store_time, + &ad4000_trigger_handler, NULL); + if (ret) + return ret; + + return devm_iio_device_register(&spi->dev, indio_dev); +} + +static const struct spi_device_id ad4000_id[] = { + { "ad4000", (kernel_ulong_t)&ad4000_chips[ID_AD4000] }, + { "ad4001", (kernel_ulong_t)&ad4000_chips[ID_AD4001] }, + { "ad4002", (kernel_ulong_t)&ad4000_chips[ID_AD4002] }, + { "ad4003", (kernel_ulong_t)&ad4000_chips[ID_AD4003] }, + { "ad4004", (kernel_ulong_t)&ad4000_chips[ID_AD4004] }, + { "ad4005", (kernel_ulong_t)&ad4000_chips[ID_AD4005] }, + { "ad4006", (kernel_ulong_t)&ad4000_chips[ID_AD4006] }, + { "ad4007", (kernel_ulong_t)&ad4000_chips[ID_AD4007] }, + { "ad4008", (kernel_ulong_t)&ad4000_chips[ID_AD4008] }, + { "ad4010", (kernel_ulong_t)&ad4000_chips[ID_AD4010] }, + { "ad4011", (kernel_ulong_t)&ad4000_chips[ID_AD4011] }, + { "ad4020", (kernel_ulong_t)&ad4000_chips[ID_AD4020] }, + { "ad4021", (kernel_ulong_t)&ad4000_chips[ID_AD4021] }, + { "ad4022", (kernel_ulong_t)&ad4000_chips[ID_AD4022] }, + { "adaq4001", (kernel_ulong_t)&ad4000_chips[ID_ADAQ4001] }, + { "adaq4003", (kernel_ulong_t)&ad4000_chips[ID_ADAQ4003] }, + { } +}; +MODULE_DEVICE_TABLE(spi, ad4000_id); + +static const struct of_device_id ad4000_of_match[] = { + { .compatible = "adi,ad4000", .data = &ad4000_chips[ID_AD4000] }, + { .compatible = "adi,ad4001", .data = &ad4000_chips[ID_AD4001] }, + { .compatible = "adi,ad4002", .data = &ad4000_chips[ID_AD4002] }, + { .compatible = "adi,ad4003", .data = &ad4000_chips[ID_AD4003] }, + { .compatible = "adi,ad4004", .data = &ad4000_chips[ID_AD4004] }, + { .compatible = "adi,ad4005", .data = &ad4000_chips[ID_AD4005] }, + { .compatible = "adi,ad4006", .data = &ad4000_chips[ID_AD4006] }, + { .compatible = "adi,ad4007", .data = &ad4000_chips[ID_AD4007] }, + { .compatible = "adi,ad4008", .data = &ad4000_chips[ID_AD4008] }, + { .compatible = "adi,ad4010", .data = &ad4000_chips[ID_AD4010] }, + { .compatible = "adi,ad4011", .data = &ad4000_chips[ID_AD4011] }, + { .compatible = "adi,ad4020", .data = &ad4000_chips[ID_AD4020] }, + { .compatible = "adi,ad4021", .data = &ad4000_chips[ID_AD4021] }, + { .compatible = "adi,ad4022", .data = &ad4000_chips[ID_AD4022] }, + { .compatible = "adi,adaq4001", .data = &ad4000_chips[ID_ADAQ4001] }, + { .compatible = "adi,adaq4003", .data = &ad4000_chips[ID_ADAQ4003] }, + { } +}; +MODULE_DEVICE_TABLE(of, ad4000_of_match); + +static struct spi_driver ad4000_driver = { + .driver = { + .name = "ad4000", + .of_match_table = ad4000_of_match, + }, + .probe = ad4000_probe, + .id_table = ad4000_id, +}; +module_spi_driver(ad4000_driver); + +MODULE_AUTHOR("Marcelo Schmitt "); +MODULE_DESCRIPTION("Analog Devices AD4000 ADC driver"); +MODULE_LICENSE("GPL");