From patchwork Wed Feb 12 18:18:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Santos X-Patchwork-Id: 13972286 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 1E20726136C; Wed, 12 Feb 2025 18:18:35 +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=1739384317; cv=none; b=fQh2BKzcQgJVvu5akpPcYWOFnuiQJg4HbUVxGEFFlErdp8BanBO2QpVaW6N0x7nksOJG73+jy6oseO/2/dkiyHKPkAVDFuCg8lXUJvkXk86Y2g4DwTTRp0HHOKt7Z02CnwYrdv0tkRVg71+m7JZdy33xNPJRd1bHQF26r12F8yg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739384317; c=relaxed/simple; bh=+wUGfSEDC1uj1RlfacJHcy7PrGiMfbnSMxMNPOdoi6M=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=StZdPboQPhqpFD/u3vnTk45orxfDz28I+uj0IVGZbm30DsUBU1c7GEIfrEVxVP3SsBdl288b8HZE9nMPATTggvrdy6P579a/TOy0ykPc+Lrqb/2PsFYPx4EId0IsYVOOk9fRLFAzURJd5w1LVOCkAAV7cyvaviVqBKhFomZn1r4= 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=mfg4qkHJ; 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="mfg4qkHJ" 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 51CFjRsg023409; Wed, 12 Feb 2025 13:18:20 -0500 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=6tUGC hWuJXfm5zfHgLtaB0qU9qjWWpqZWcvSF+5ZQlc=; b=mfg4qkHJHFcICdYN5D5DR U6egnpvelr+SCKhxrEyikzHo+PG22vSS4bgn9g8xcRZ1dL2J1mZAzGHzIxBHyguy 6pnUsJ4BGSumCTG3aHAjS9E9SchBgXjBuX+yLnRYV205n/8prDNN3KAzRjd1gqKe ryOMSG+3ywR5exj9EtSDw5fg9eIpufRLxOFzDkZj0z6IRs1HNHi9tuV4zME9aIhr Zo1pa8bL9ein2F4h2ruRv76TEmOEVnotUZg20Kb+6B2opaJCPtl/W53G7Q5cOIjf zxpP12nR8O5bCDv3pTJeDshCMBq/2Qq8RmXi/dIhbhhTYB1MalI9VVfrkU1JIrPs Q== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 44rnspk2su-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 12 Feb 2025 13:18:20 -0500 (EST) 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 51CIIJhb046548 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 12 Feb 2025 13:18:19 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) 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, 12 Feb 2025 13:18:19 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Wed, 12 Feb 2025 13:18:19 -0500 Received: from JSANTO12-L01.ad.analog.com ([10.65.60.206]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51CII5TW017498; Wed, 12 Feb 2025 13:18:07 -0500 From: Jonathan Santos To: , , CC: Sergiu Cuciurean , , , , , , , , , , , Jonathan Santos Subject: [PATCH RESEND v3 12/17] iio: adc: ad7768-1: Add GPIO controller support Date: Wed, 12 Feb 2025 15:18:04 -0300 Message-ID: <62cb9786b02adde118db9349617cb796585ceb02.1739368121.git.Jonathan.Santos@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Authority-Analysis: v=2.4 cv=RZxqC0tv c=1 sm=1 tr=0 ts=67ace5ec cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=2YwxR-89tvQ4IDrCW4oA:9 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-GUID: he9NQr8gvk2-lkxNcEaMPz6f53ARg1C_ X-Proofpoint-ORIG-GUID: he9NQr8gvk2-lkxNcEaMPz6f53ARg1C_ X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-12_05,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 bulkscore=0 adultscore=0 suspectscore=0 malwarescore=0 priorityscore=1501 mlxlogscore=999 lowpriorityscore=0 phishscore=0 clxscore=1015 spamscore=0 impostorscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502120132 From: Sergiu Cuciurean The AD7768-1 has the ability to control other local hardware (such as gain stages),to power down other blocks in the signal chain, or read local status signals over the SPI interface. This change exports the AD7768-1's four gpios and makes them accessible at an upper layer. Signed-off-by: Sergiu Cuciurean Co-developed-by: Jonathan Santos Signed-off-by: Jonathan Santos --- v3 Changes: * Fixed SoB order. * Added mising iio_device_release_direct_mode(). * Simplified some regmap writes. * Removed ad7768_gpio_request() callback. * Fixed line wrapping. v2 Changes: * Replaced mutex for iio_device_claim_direct_mode(). * Use gpio-controller property to conditionally enable the GPIO support. * OBS: when the GPIO is configured as output, we should read the current state value from AD7768_REG_GPIO_WRITE. --- drivers/iio/adc/ad7768-1.c | 143 ++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c index a359cd8fceca..afcc8678cf83 100644 --- a/drivers/iio/adc/ad7768-1.c +++ b/drivers/iio/adc/ad7768-1.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -86,6 +88,16 @@ #define AD7768_REG_ANALOG2_VCM_MSK GENMASK(2, 0) #define AD7768_REG_ANALOG2_VCM(x) FIELD_PREP(AD7768_REG_ANALOG2_VCM_MSK, x) +/* AD7768_REG_GPIO_CONTROL */ +#define AD7768_GPIO_UNIVERSAL_EN BIT(7) +#define AD7768_GPIO_CONTROL_MSK GENMASK(3, 0) + +/* AD7768_REG_GPIO_WRITE */ +#define AD7768_GPIO_WRITE_MSK GENMASK(3, 0) + +/* AD7768_REG_GPIO_READ */ +#define AD7768_GPIO_READ_MSK GENMASK(3, 0) + #define AD7768_RD_FLAG_MSK(x) (BIT(6) | ((x) & 0x3F)) #define AD7768_WR_FLAG_MSK(x) ((x) & 0x3F) @@ -170,6 +182,7 @@ struct ad7768_state { struct regulator *vref; struct regulator_dev *vcm_rdev; struct clk *mclk; + struct gpio_chip gpiochip; unsigned int mclk_freq; unsigned int samp_freq; struct completion completion; @@ -349,6 +362,124 @@ static int ad7768_set_dig_fil(struct ad7768_state *st, return 0; } +static int ad7768_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + struct iio_dev *indio_dev = gpiochip_get_data(chip); + struct ad7768_state *st = iio_priv(indio_dev); + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = regmap_clear_bits(st->regmap, AD7768_REG_GPIO_CONTROL, + BIT(offset)); + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int ad7768_gpio_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct iio_dev *indio_dev = gpiochip_get_data(chip); + struct ad7768_state *st = iio_priv(indio_dev); + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = regmap_set_bits(st->regmap, AD7768_REG_GPIO_CONTROL, + BIT(offset)); + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static int ad7768_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct iio_dev *indio_dev = gpiochip_get_data(chip); + struct ad7768_state *st = iio_priv(indio_dev); + unsigned int val; + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + + ret = regmap_read(st->regmap, AD7768_REG_GPIO_CONTROL, &val); + if (ret) + goto err_release; + + /* + * If the GPIO is configured as an output, read the current value from + * AD7768_REG_GPIO_WRITE. Otherwise, read the input value from + * AD7768_REG_GPIO_READ. + */ + if (val & BIT(offset)) + ret = regmap_read(st->regmap, AD7768_REG_GPIO_WRITE, &val); + else + ret = regmap_read(st->regmap, AD7768_REG_GPIO_READ, &val); + if (ret) + goto err_release; + + ret = !!(val & BIT(offset)); +err_release: + iio_device_release_direct_mode(indio_dev); + + return ret; +} + +static void ad7768_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct iio_dev *indio_dev = gpiochip_get_data(chip); + struct ad7768_state *st = iio_priv(indio_dev); + unsigned int val; + int ret; + + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return; + + ret = regmap_read(st->regmap, AD7768_REG_GPIO_CONTROL, &val); + if (ret) + goto err_release; + + if (val & BIT(offset)) + regmap_update_bits(st->regmap, AD7768_REG_GPIO_WRITE, + BIT(offset), value << offset); + +err_release: + iio_device_release_direct_mode(indio_dev); +} + +static int ad7768_gpio_init(struct iio_dev *indio_dev) +{ + struct ad7768_state *st = iio_priv(indio_dev); + int ret; + + ret = regmap_write(st->regmap, AD7768_REG_GPIO_CONTROL, + AD7768_GPIO_UNIVERSAL_EN); + if (ret) + return ret; + + st->gpiochip = (struct gpio_chip) { + .label = "ad7768_1_gpios", + .base = -1, + .ngpio = 4, + .parent = &st->spi->dev, + .can_sleep = true, + .direction_input = ad7768_gpio_direction_input, + .direction_output = ad7768_gpio_direction_output, + .get = ad7768_gpio_get, + .set = ad7768_gpio_set, + .owner = THIS_MODULE, + }; + + return gpiochip_add_data(&st->gpiochip, indio_dev); +} + static int ad7768_set_freq(struct ad7768_state *st, unsigned int freq) { @@ -492,8 +623,9 @@ static const struct iio_info ad7768_info = { .debugfs_reg_access = &ad7768_reg_access, }; -static int ad7768_setup(struct ad7768_state *st) +static int ad7768_setup(struct iio_dev *indio_dev) { + struct ad7768_state *st = iio_priv(indio_dev); int ret; st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset", @@ -526,6 +658,13 @@ static int ad7768_setup(struct ad7768_state *st) if (IS_ERR(st->gpio_sync_in)) return PTR_ERR(st->gpio_sync_in); + /* Only create a Chip GPIO if flagged for it */ + if (device_property_read_bool(&st->spi->dev, "gpio-controller")) { + ret = ad7768_gpio_init(indio_dev); + if (ret < 0) + return ret; + } + /* Set the default sampling frequency to 32000 kSPS */ return ad7768_set_freq(st, 32000); } @@ -845,7 +984,7 @@ static int ad7768_probe(struct spi_device *spi) if (ret) return ret; - ret = ad7768_setup(st); + ret = ad7768_setup(indio_dev); if (ret < 0) { dev_err(&spi->dev, "AD7768 setup failed\n"); return ret;