Message ID | 20221111143921.742194-6-linux@rasmusvillemoes.dk |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp785939wru; Fri, 11 Nov 2022 06:55:40 -0800 (PST) X-Google-Smtp-Source: AA0mqf6btP8UXJsiJyjRuJklP1oYmgS3+m2lKxfOJ56j+vagQtetwO/jCPq/FI0Grr3vxhJjZexE X-Received: by 2002:a17:907:8745:b0:78d:b4f1:1b29 with SMTP id qo5-20020a170907874500b0078db4f11b29mr2013907ejc.375.1668178540264; Fri, 11 Nov 2022 06:55:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668178540; cv=none; d=google.com; s=arc-20160816; b=Q7L2VtuGXOpTxnfONMoyVCl4JC3EzS5UixdZD5lEW0/ZddmBGPa5yCF0sCosatLZaV yu4pT/+MTpqtwJd4FjRLZoFlO66bO1FSVWGylmBXz12WaSg9+W+UiHaHjQ4CfO6GYe8z Rnl+LSiZ7Vy01+bEr3U8F+iarU8hvY8ZCwlyL73Waddf1C/303Jmju7FLXyPUrqBWkI/ f8vu3309cXknBrJUHYrV74s6lkW4fx6zBGWDxtZH8E0ws+ReuLEmBXmv7dq2yqeCChpL A/82wFhAOVdSrllvRPVdHJpkYs3Hw34v5PQ3UYXKFOQwhGqDfJ/NNwZLOf5eGJM9oXaa ruVw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=JAMGBaW4DNgnbxHPENr1NAw38Yk5iEpRnIys3RSCUnE=; b=o1fsOUSPpc+CJyxdL7m46CBIB8em/VWoGoJXXxe8F2ODf1z9gPsnjohYtZI2SuK0Jo GNyN8DL2RW3UucE/s4eR85C3Q+YSZLIgft/WsDbwiOzQil4nmDjInI5AX3j2py9aim5l YI5pLVmT8ZHl6/akxUYs+9WTl2gbDjJou2H0TMGZdQGZscZinL5QjYVhXwZaVkP2Bdro Qn2zKYCkNwc1gTq4FkiA7LtaICHFAaez0azO1r2K6y+ZyzFfILTxGx29PeFJHpe6URRy vU7yGATdOEHESB3/BqSmou7FmecFhpKuuZV2TSaur4xnL9tNiz3KUjDTPYpgyJivHg1m Q4CA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@rasmusvillemoes.dk header.s=google header.b=DVseHuqQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id dc26-20020a170906c7da00b0077b6ecac099si1537996ejb.287.2022.11.11.06.55.16; Fri, 11 Nov 2022 06:55:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@rasmusvillemoes.dk header.s=google header.b=DVseHuqQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234724AbiKKOk2 (ORCPT <rfc822;winker.wchi@gmail.com> + 99 others); Fri, 11 Nov 2022 09:40:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234684AbiKKOju (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 11 Nov 2022 09:39:50 -0500 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D378D5CD05 for <linux-kernel@vger.kernel.org>; Fri, 11 Nov 2022 06:39:31 -0800 (PST) Received: by mail-ej1-x634.google.com with SMTP id bj12so12909143ejb.13 for <linux-kernel@vger.kernel.org>; Fri, 11 Nov 2022 06:39:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rasmusvillemoes.dk; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JAMGBaW4DNgnbxHPENr1NAw38Yk5iEpRnIys3RSCUnE=; b=DVseHuqQ+fdeqFq/cg5i/yOGTG4qIR6mwKQlbApHL7hGPLZtwKD+3PuBn6DEtxZjzU SCj3NzZbHwsYr6cAIdX0AtIDt+EioB8psnFybSyTkN0Os88giBjtV7Je58ZV2J9NqiGM BK8t6Pl/+wsQ9rzJbLDdqP2UxZQGL4OEuiVos= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JAMGBaW4DNgnbxHPENr1NAw38Yk5iEpRnIys3RSCUnE=; b=hKFFEURWs/9vi4tV8E6fvLg6YR7cc3LeegBVSTwnWeeWvEgvDiZjF/R98hWwjNjNmb q2icrdku9gcCL81VQ0cipqnoefCifsuO/19BtbGLVxiOb06uHSk8BM3CGmca2/dUn+at niyA9+pNm3rrgWF+rM92THlpqT5SiHTWxVj4bwBZoyh6xvUqhdbZkUiMxyLjvPKH8C6i U8SBSfg/Pw4HKnTIYpwRTJdD69JtHBHig5WtNZddGcYiDwVmQ+Cq/6mAK7tCO9ACpgDd ZZS/FwRZoCZcrfvsbFczCBGswG0duo66V/T4kVvyhNHKw/bpyTa4ugMOYjvS5kxe66n3 u2Eg== X-Gm-Message-State: ANoB5plLetj7yIbP6p9XvzYO7EvFAlpBmb43hazDQhk9aVtXIcsER/vR oyW6loEUJvzkpJh/QE+ISw9J0oEK8qsQB1wjTvQ= X-Received: by 2002:a17:906:f113:b0:78d:addf:67c1 with SMTP id gv19-20020a170906f11300b0078daddf67c1mr2043542ejb.272.1668177569930; Fri, 11 Nov 2022 06:39:29 -0800 (PST) Received: from prevas-ravi.tritech.se ([80.208.71.65]) by smtp.gmail.com with ESMTPSA id jt4-20020a170906dfc400b007a1d4944d45sm945886ejc.142.2022.11.11.06.39.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Nov 2022 06:39:29 -0800 (PST) From: Rasmus Villemoes <linux@rasmusvillemoes.dk> To: Cosmin Tanislav <cosmin.tanislav@analog.com>, Lars-Peter Clausen <lars@metafoo.de>, Michael Hennerich <Michael.Hennerich@analog.com>, Jonathan Cameron <jic23@kernel.org> Cc: devicetree@vger.kernel.org, Rob Herring <robh+dt@kernel.org>, Rasmus Villemoes <linux@rasmusvillemoes.dk>, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 5/5] iio: addac: ad74413r: add support for reset-gpio Date: Fri, 11 Nov 2022 15:39:21 +0100 Message-Id: <20221111143921.742194-6-linux@rasmusvillemoes.dk> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221111143921.742194-1-linux@rasmusvillemoes.dk> References: <20221111143921.742194-1-linux@rasmusvillemoes.dk> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749211981022590176?= X-GMAIL-MSGID: =?utf-8?q?1749211981022590176?= |
Series |
iio: addac: ad74413r: various fixups
|
|
Commit Message
Rasmus Villemoes
Nov. 11, 2022, 2:39 p.m. UTC
We have a board where the reset pin of the ad74412 is connected to a
gpio, but also pulled low by default. Hence to get the chip out of
reset, the driver needs to know about that gpio and set it high before
attempting to communicate with it.
When a reset-gpio is given in device tree, use that instead of the
software reset. According to the data sheet, the two methods are
functionally equivalent.
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
drivers/iio/addac/ad74413r.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
Comments
On Fri, 11 Nov 2022 15:39:21 +0100 Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > We have a board where the reset pin of the ad74412 is connected to a > gpio, but also pulled low by default. Hence to get the chip out of > reset, the driver needs to know about that gpio and set it high before > attempting to communicate with it. I'm a little confused on polarity here. The pin is a !reset so we need to drive it low briefly to trigger a reset. I'm guessing for your board the pin is set to active low? (an example in the dt would have made that clearer) Hence the pulse in here to 1 is actually briefly driving it low before restoring to high? For a pin documented as !reset that seems backwards though you have called it reset so that is fine, but this description doesn't make that celar. Perhaps just add some more description here to make it clear the GPIO is active low, and then refer to setting it to true and false to avoid the confusing high / low terminology which are inverted... > > When a reset-gpio is given in device tree, use that instead of the > software reset. According to the data sheet, the two methods are > functionally equivalent. > > Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > --- > drivers/iio/addac/ad74413r.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c > index 9f77d2f514de..af09d43f921c 100644 > --- a/drivers/iio/addac/ad74413r.c > +++ b/drivers/iio/addac/ad74413r.c > @@ -71,6 +71,7 @@ struct ad74413r_state { > struct regmap *regmap; > struct device *dev; > struct iio_trigger *trig; > + struct gpio_desc *reset_gpio; > > size_t adc_active_channels; > struct spi_message adc_samples_msg; > @@ -393,6 +394,13 @@ static int ad74413r_reset(struct ad74413r_state *st) > { > int ret; > > + if (st->reset_gpio) { > + gpiod_set_value_cansleep(st->reset_gpio, 1); > + fsleep(50); > + gpiod_set_value_cansleep(st->reset_gpio, 0); > + return 0; > + } > + > ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY, > AD74413R_CMD_KEY_RESET1); > if (ret) > @@ -1316,6 +1324,10 @@ static int ad74413r_probe(struct spi_device *spi) > if (IS_ERR(st->regmap)) > return PTR_ERR(st->regmap); > > + st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); > + if (IS_ERR(st->reset_gpio)) > + return PTR_ERR(st->reset_gpio); > + > st->refin_reg = devm_regulator_get_optional(st->dev, "refin"); > if (IS_ERR(st->refin_reg)) { > ret = PTR_ERR(st->refin_reg);
On 12/11/2022 18.07, Jonathan Cameron wrote: > On Fri, 11 Nov 2022 15:39:21 +0100 > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > >> We have a board where the reset pin of the ad74412 is connected to a >> gpio, but also pulled low by default. Hence to get the chip out of >> reset, the driver needs to know about that gpio and set it high before >> attempting to communicate with it. > > I'm a little confused on polarity here. The pin is a !reset so > we need to drive it low briefly to trigger a reset. > I'm guessing for your board the pin is set to active low? (an example > in the dt would have made that clearer) Hence the pulse > in here to 1 is actually briefly driving it low before restoring to high? Yes. I actually thought that was pretty standard. I do indeed have something like reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; in my .dts, so setting the gpio value to 1 (logically asserting its function) will end up driving the signal low, and setting it to 0 (de-asserting reset) will set the signal high. I will add that line to the example in the binding. > For a pin documented as !reset that seems backwards Well, it depends on where the knowledge of the pin being active low belongs. In this case, the driver itself handles the gpio so it could be done both ways. But if, for example, the iio framework would handle an optional reset-gpio for each device, it couldn't possibly know whether to set it to 1 or 0 for a given device, it could only set it logic 1 to assert reset and then rely on DT gpio descriptor to include the active low/high info. Also, see the "The active low and open drain semantics" section in Documentation/driver-api/gpio/consumer.rst. Rasmus
> -----Original Message----- > From: Jonathan Cameron <jic23@kernel.org> > Sent: Saturday, November 12, 2022 7:07 PM > To: Rasmus Villemoes <linux@rasmusvillemoes.dk> > Cc: Tanislav, Cosmin <Cosmin.Tanislav@analog.com>; Lars-Peter Clausen > <lars@metafoo.de>; Hennerich, Michael <Michael.Hennerich@analog.com>; > devicetree@vger.kernel.org; Rob Herring <robh+dt@kernel.org>; linux- > iio@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH 5/5] iio: addac: ad74413r: add support for reset-gpio > > [External] > > On Fri, 11 Nov 2022 15:39:21 +0100 > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > > We have a board where the reset pin of the ad74412 is connected to a > > gpio, but also pulled low by default. Hence to get the chip out of > > reset, the driver needs to know about that gpio and set it high before > > attempting to communicate with it. > > I'm a little confused on polarity here. The pin is a !reset so > we need to drive it low briefly to trigger a reset. > I'm guessing for your board the pin is set to active low? (an example > in the dt would have made that clearer) Hence the pulse > in here to 1 is actually briefly driving it low before restoring to high? > > For a pin documented as !reset that seems backwards though you have > called it reset so that is fine, but this description doesn't make that > celar. My opinion is that the driver shouldn't exactly know the polarity of the reset, and just assume that setting the reset GPIO to 1 means putting it in reset, and setting it to 0 means bringing out of reset. > > Perhaps just add some more description here to make it clear the GPIO > is active low, and then refer to setting it to true and false to avoid > the confusing high / low terminology which are inverted... > > > > > When a reset-gpio is given in device tree, use that instead of the > > software reset. According to the data sheet, the two methods are > > functionally equivalent. > > > > Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > > --- > > drivers/iio/addac/ad74413r.c | 12 ++++++++++++ > > 1 file changed, 12 insertions(+) > > > > diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c > > index 9f77d2f514de..af09d43f921c 100644 > > --- a/drivers/iio/addac/ad74413r.c > > +++ b/drivers/iio/addac/ad74413r.c > > @@ -71,6 +71,7 @@ struct ad74413r_state { > > struct regmap *regmap; > > struct device *dev; > > struct iio_trigger *trig; > > + struct gpio_desc *reset_gpio; > > > > size_t adc_active_channels; > > struct spi_message adc_samples_msg; > > @@ -393,6 +394,13 @@ static int ad74413r_reset(struct ad74413r_state > *st) > > { > > int ret; > > > > + if (st->reset_gpio) { > > + gpiod_set_value_cansleep(st->reset_gpio, 1); > > + fsleep(50); > > + gpiod_set_value_cansleep(st->reset_gpio, 0); > > + return 0; > > + } > > + > > ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY, > > AD74413R_CMD_KEY_RESET1); > > if (ret) > > @@ -1316,6 +1324,10 @@ static int ad74413r_probe(struct spi_device *spi) > > if (IS_ERR(st->regmap)) > > return PTR_ERR(st->regmap); > > > > + st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", > GPIOD_OUT_LOW); > > + if (IS_ERR(st->reset_gpio)) > > + return PTR_ERR(st->reset_gpio); > > + > > st->refin_reg = devm_regulator_get_optional(st->dev, "refin"); > > if (IS_ERR(st->refin_reg)) { > > ret = PTR_ERR(st->refin_reg);
On Mon, 14 Nov 2022 09:37:59 +0100 Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > On 12/11/2022 18.07, Jonathan Cameron wrote: > > On Fri, 11 Nov 2022 15:39:21 +0100 > > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > > >> We have a board where the reset pin of the ad74412 is connected to a > >> gpio, but also pulled low by default. Hence to get the chip out of > >> reset, the driver needs to know about that gpio and set it high before > >> attempting to communicate with it. > > > > I'm a little confused on polarity here. The pin is a !reset so > > we need to drive it low briefly to trigger a reset. > > I'm guessing for your board the pin is set to active low? (an example > > in the dt would have made that clearer) Hence the pulse > > in here to 1 is actually briefly driving it low before restoring to high? > > Yes. I actually thought that was pretty standard. I do indeed have > something like > > reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; > > in my .dts, so setting the gpio value to 1 (logically asserting its > function) will end up driving the signal low, and setting it to 0 > (de-asserting reset) will set the signal high. I will add that line to > the example in the binding. > > > For a pin documented as !reset that seems backwards > > Well, it depends on where the knowledge of the pin being active low > belongs. In this case, the driver itself handles the gpio so it could be > done both ways. > > But if, for example, the iio framework would handle an optional > reset-gpio for each device, it couldn't possibly know whether to set it > to 1 or 0 for a given device, it could only set it logic 1 to assert > reset and then rely on DT gpio descriptor to include the active low/high > info. > > Also, see the "The active low and open drain semantics" section in > Documentation/driver-api/gpio/consumer.rst. Throw in an example in the dt-binding and I'm fine with this as it stands. Jonathan > > Rasmus >
On Mon, 14 Nov 2022 13:52:26 +0000 "Tanislav, Cosmin" <Cosmin.Tanislav@analog.com> wrote: > > -----Original Message----- > > From: Jonathan Cameron <jic23@kernel.org> > > Sent: Saturday, November 12, 2022 7:07 PM > > To: Rasmus Villemoes <linux@rasmusvillemoes.dk> > > Cc: Tanislav, Cosmin <Cosmin.Tanislav@analog.com>; Lars-Peter Clausen > > <lars@metafoo.de>; Hennerich, Michael <Michael.Hennerich@analog.com>; > > devicetree@vger.kernel.org; Rob Herring <robh+dt@kernel.org>; linux- > > iio@vger.kernel.org; linux-kernel@vger.kernel.org > > Subject: Re: [PATCH 5/5] iio: addac: ad74413r: add support for reset-gpio > > > > [External] > > > > On Fri, 11 Nov 2022 15:39:21 +0100 > > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > > > > We have a board where the reset pin of the ad74412 is connected to a > > > gpio, but also pulled low by default. Hence to get the chip out of > > > reset, the driver needs to know about that gpio and set it high before > > > attempting to communicate with it. > > > > I'm a little confused on polarity here. The pin is a !reset so > > we need to drive it low briefly to trigger a reset. > > I'm guessing for your board the pin is set to active low? (an example > > in the dt would have made that clearer) Hence the pulse > > in here to 1 is actually briefly driving it low before restoring to high? > > > > For a pin documented as !reset that seems backwards though you have > > called it reset so that is fine, but this description doesn't make that > > celar. > > My opinion is that the driver shouldn't exactly know the polarity of the reset, > and just assume that setting the reset GPIO to 1 means putting it in reset, > and setting it to 0 means bringing out of reset. Agreed. I'd just like a comment + example in the dt-binding to make the point that the pin is !reset. Preferably with an example in the dt binding of the common case of it being wired up to an active low pin. The main oddity here is the need to pulse it rather than request it directly as in the reset state and then just set that to off. Jonathan > > > > > Perhaps just add some more description here to make it clear the GPIO > > is active low, and then refer to setting it to true and false to avoid > > the confusing high / low terminology which are inverted... > > > > > > > > When a reset-gpio is given in device tree, use that instead of the > > > software reset. According to the data sheet, the two methods are > > > functionally equivalent. > > > > > > Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > > > --- > > > drivers/iio/addac/ad74413r.c | 12 ++++++++++++ > > > 1 file changed, 12 insertions(+) > > > > > > diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c > > > index 9f77d2f514de..af09d43f921c 100644 > > > --- a/drivers/iio/addac/ad74413r.c > > > +++ b/drivers/iio/addac/ad74413r.c > > > @@ -71,6 +71,7 @@ struct ad74413r_state { > > > struct regmap *regmap; > > > struct device *dev; > > > struct iio_trigger *trig; > > > + struct gpio_desc *reset_gpio; > > > > > > size_t adc_active_channels; > > > struct spi_message adc_samples_msg; > > > @@ -393,6 +394,13 @@ static int ad74413r_reset(struct ad74413r_state > > *st) > > > { > > > int ret; > > > > > > + if (st->reset_gpio) { > > > + gpiod_set_value_cansleep(st->reset_gpio, 1); > > > + fsleep(50); > > > + gpiod_set_value_cansleep(st->reset_gpio, 0); > > > + return 0; > > > + } > > > + > > > ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY, > > > AD74413R_CMD_KEY_RESET1); > > > if (ret) > > > @@ -1316,6 +1324,10 @@ static int ad74413r_probe(struct spi_device *spi) > > > if (IS_ERR(st->regmap)) > > > return PTR_ERR(st->regmap); > > > > > > + st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", > > GPIOD_OUT_LOW); > > > + if (IS_ERR(st->reset_gpio)) > > > + return PTR_ERR(st->reset_gpio); > > > + > > > st->refin_reg = devm_regulator_get_optional(st->dev, "refin"); > > > if (IS_ERR(st->refin_reg)) { > > > ret = PTR_ERR(st->refin_reg); >
On Mon, 2022-11-14 at 19:44 +0000, Jonathan Cameron wrote: > On Mon, 14 Nov 2022 13:52:26 +0000 > "Tanislav, Cosmin" <Cosmin.Tanislav@analog.com> wrote: > > > > -----Original Message----- > > > From: Jonathan Cameron <jic23@kernel.org> > > > Sent: Saturday, November 12, 2022 7:07 PM > > > To: Rasmus Villemoes <linux@rasmusvillemoes.dk> > > > Cc: Tanislav, Cosmin <Cosmin.Tanislav@analog.com>; Lars-Peter > > > Clausen > > > <lars@metafoo.de>; Hennerich, Michael > > > <Michael.Hennerich@analog.com>; > > > devicetree@vger.kernel.org; Rob Herring <robh+dt@kernel.org>; > > > linux- > > > iio@vger.kernel.org; linux-kernel@vger.kernel.org > > > Subject: Re: [PATCH 5/5] iio: addac: ad74413r: add support for > > > reset-gpio > > > > > > [External] > > > > > > On Fri, 11 Nov 2022 15:39:21 +0100 > > > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > > > > > > We have a board where the reset pin of the ad74412 is connected > > > > to a > > > > gpio, but also pulled low by default. Hence to get the chip out > > > > of > > > > reset, the driver needs to know about that gpio and set it high > > > > before > > > > attempting to communicate with it. > > > > > > I'm a little confused on polarity here. The pin is a !reset so > > > we need to drive it low briefly to trigger a reset. > > > I'm guessing for your board the pin is set to active low? (an > > > example > > > in the dt would have made that clearer) Hence the pulse > > > in here to 1 is actually briefly driving it low before restoring > > > to high? > > > > > > For a pin documented as !reset that seems backwards though you > > > have > > > called it reset so that is fine, but this description doesn't > > > make that > > > celar. > > > > My opinion is that the driver shouldn't exactly know the polarity > > of the reset, > > and just assume that setting the reset GPIO to 1 means putting it > > in reset, > > and setting it to 0 means bringing out of reset. > > Agreed. I'd just like a comment + example in the dt-binding to make > the point > that the pin is !reset. > > Preferably with an example in the dt binding of the common case of it > being wired > up to an active low pin. > > The main oddity here is the need to pulse it rather than request it > directly as > in the reset state and then just set that to off. > > Agreed... In theory we should be able to request the gpio with GPIOD_OUT_HIGH and then just bring the device out of reset - Nuno Sá
On Fri, 2022-11-11 at 15:39 +0100, Rasmus Villemoes wrote: > We have a board where the reset pin of the ad74412 is connected to a > gpio, but also pulled low by default. Hence to get the chip out of > reset, the driver needs to know about that gpio and set it high > before > attempting to communicate with it. > > When a reset-gpio is given in device tree, use that instead of the > software reset. According to the data sheet, the two methods are > functionally equivalent. > > Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > --- > drivers/iio/addac/ad74413r.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/drivers/iio/addac/ad74413r.c > b/drivers/iio/addac/ad74413r.c > index 9f77d2f514de..af09d43f921c 100644 > --- a/drivers/iio/addac/ad74413r.c > +++ b/drivers/iio/addac/ad74413r.c > @@ -71,6 +71,7 @@ struct ad74413r_state { > struct regmap *regmap; > struct device *dev; > struct iio_trigger *trig; > + struct gpio_desc *reset_gpio; > > size_t adc_active_channels; > struct spi_message adc_samples_msg; > @@ -393,6 +394,13 @@ static int ad74413r_reset(struct ad74413r_state > *st) > { > int ret; > > + if (st->reset_gpio) { > + gpiod_set_value_cansleep(st->reset_gpio, 1); > + fsleep(50); > + gpiod_set_value_cansleep(st->reset_gpio, 0); > + return 0; > + } > + > ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY, > AD74413R_CMD_KEY_RESET1); > if (ret) > @@ -1316,6 +1324,10 @@ static int ad74413r_probe(struct spi_device > *spi) > if (IS_ERR(st->regmap)) > return PTR_ERR(st->regmap); > > + st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", > GPIOD_OUT_LOW); > + if (IS_ERR(st->reset_gpio)) > + return PTR_ERR(st->reset_gpio); > + Minor thing but, I would move this into ad74413r_reset() as there's no real need to have the gpio_desc in struct ad74413r_state. - Nuno Sá
On 15/11/2022 17.10, Jonathan Cameron wrote: > On Tue, 15 Nov 2022 15:49:46 +0100 > Nuno Sá <noname.nuno@gmail.com> wrote: > >> On Mon, 2022-11-14 at 19:44 +0000, Jonathan Cameron wrote: >>> On Mon, 14 Nov 2022 13:52:26 +0000 >>> "Tanislav, Cosmin" <Cosmin.Tanislav@analog.com> wrote: >>> >>>>> >>>>> I'm a little confused on polarity here. The pin is a !reset so >>>>> we need to drive it low briefly to trigger a reset. >>>>> I'm guessing for your board the pin is set to active low? (an >>>>> example >>>>> in the dt would have made that clearer) Hence the pulse >>>>> in here to 1 is actually briefly driving it low before restoring >>>>> to high? >>>>> >>>>> For a pin documented as !reset that seems backwards though you >>>>> have >>>>> called it reset so that is fine, but this description doesn't >>>>> make that >>>>> celar. >>>> >>>> My opinion is that the driver shouldn't exactly know the polarity >>>> of the reset, >>>> and just assume that setting the reset GPIO to 1 means putting it >>>> in reset, >>>> and setting it to 0 means bringing out of reset. >>> >>> Agreed. I'd just like a comment + example in the dt-binding to make >>> the point >>> that the pin is !reset. >>> >>> Preferably with an example in the dt binding of the common case of it >>> being wired >>> up to an active low pin. >>> >>> The main oddity here is the need to pulse it rather than request it >>> directly as >>> in the reset state and then just set that to off. >>> >>> >> >> Agreed... In theory we should be able to request the gpio with >> GPIOD_OUT_HIGH and then just bring the device out of reset > > If I recall correctly the datasheet specifically calls out that a pulse > should be used. No idea if that's actually true, or if it was meant > to be there just to say it needs to be set for X nsecs. So the data sheet says The hardware reset is initiated by pulsing the RESET pin low. The RESET pulse width must comply with the specifications in Table 11. and table 11 says that the pulse must be min 50us, max 1ms. We don't really have any way whatsoever to ensure that we're not rescheduled right before pulling the gpio high again (deasserting the reset), so the pulse could effectively be much more than 1ms. But I have a hard time believing that that actually matters (i.e., what state would the chip be in if we happen to make a pulse 1234us wide?). But what might be relevant, and maybe where that 1ms figure really comes from, can perhaps be read in table 10, which lists a "device reset time" of 1ms, with the description Time taken for device reset and calibration memory upload to complete hardware or software reset events after the device is powered up so perhaps we should ensure a 1ms delay after the reset (whether we used the software or gpio method). But that would be a separate fix IMO (and I'm not sure we actually need it). I don't mind requesting the gpio with GPIOD_OUT_HIGH, but I'd still keep the gpiod_set_value(, 1) in the reset function, otherwise it's a bit too magic for my taste. Rasmus
On Wed, 2022-11-16 at 10:22 +0000, Jonathan Cameron wrote: > On Tue, 15 Nov 2022 20:10:53 +0100 > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > > > On 15/11/2022 17.10, Jonathan Cameron wrote: > > > On Tue, 15 Nov 2022 15:49:46 +0100 > > > Nuno Sá <noname.nuno@gmail.com> wrote: > > > > > > > On Mon, 2022-11-14 at 19:44 +0000, Jonathan Cameron wrote: > > > > > On Mon, 14 Nov 2022 13:52:26 +0000 > > > > > "Tanislav, Cosmin" <Cosmin.Tanislav@analog.com> wrote: > > > > > > > > > > > > > > > > > > > I'm a little confused on polarity here. The pin is a > > > > > > > !reset so > > > > > > > we need to drive it low briefly to trigger a reset. > > > > > > > I'm guessing for your board the pin is set to active low? > > > > > > > (an > > > > > > > example > > > > > > > in the dt would have made that clearer) Hence the pulse > > > > > > > in here to 1 is actually briefly driving it low before > > > > > > > restoring > > > > > > > to high? > > > > > > > > > > > > > > For a pin documented as !reset that seems backwards > > > > > > > though you > > > > > > > have > > > > > > > called it reset so that is fine, but this description > > > > > > > doesn't > > > > > > > make that > > > > > > > celar. > > > > > > > > > > > > My opinion is that the driver shouldn't exactly know the > > > > > > polarity > > > > > > of the reset, > > > > > > and just assume that setting the reset GPIO to 1 means > > > > > > putting it > > > > > > in reset, > > > > > > and setting it to 0 means bringing out of reset. > > > > > > > > > > Agreed. I'd just like a comment + example in the dt-binding > > > > > to make > > > > > the point > > > > > that the pin is !reset. > > > > > > > > > > Preferably with an example in the dt binding of the common > > > > > case of it > > > > > being wired > > > > > up to an active low pin. > > > > > > > > > > The main oddity here is the need to pulse it rather than > > > > > request it > > > > > directly as > > > > > in the reset state and then just set that to off. > > > > > > > > > > > > > > > > > > Agreed... In theory we should be able to request the gpio with > > > > GPIOD_OUT_HIGH and then just bring the device out of reset > > > > > > If I recall correctly the datasheet specifically calls out that a > > > pulse > > > should be used. No idea if that's actually true, or if it was > > > meant > > > to be there just to say it needs to be set for X nsecs. > > > > So the data sheet says > > > > The hardware reset is initiated by pulsing the RESET pin low. The > > RESET pulse width must comply with the specifications in Table 11. > > > > and table 11 says that the pulse must be min 50us, max 1ms. We > > don't > > really have any way whatsoever to ensure that we're not rescheduled > > right before pulling the gpio high again (deasserting the reset), > > so the > > pulse could effectively be much more than 1ms. But I have a hard > > time > > believing that that actually matters (i.e., what state would the > > chip be > > in if we happen to make a pulse 1234us wide?). > > Test it maybe? Otherwise we'd have to play games to do it again if > the > timing was too long to ensure after a couple of goes we do get a > suitable > width pulse. > > > But what might be > > relevant, and maybe where that 1ms figure really comes from, can > > perhaps > > be read in table 10, which lists a "device reset time" of 1ms, with > > the > > description > > > > Time taken for device reset and calibration memory upload to > > complete > > hardware or software reset events after the device is powered up > > > > so perhaps we should ensure a 1ms delay after the reset (whether we > > used > > the software or gpio method). But that would be a separate fix IMO > > (and > > I'm not sure we actually need it). > > > > I don't mind requesting the gpio with GPIOD_OUT_HIGH, but I'd still > > keep > > the gpiod_set_value(, 1) in the reset function, otherwise it's a > > bit too > > magic for my taste. > > Without testing I'd worry that it really does need a pulse so > probably better > to leave it doing so. > Yeah, without testing maybe better to play safe. But, FWIW, what I read from the datasheet is just another typical reset gpio usage with more (fancy/confusing) description. - Nuno Sá
On 16/11/2022 11.22, Jonathan Cameron wrote: > On Tue, 15 Nov 2022 20:10:53 +0100 > Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote: > >> On 15/11/2022 17.10, Jonathan Cameron wrote: >>> On Tue, 15 Nov 2022 15:49:46 +0100 >>> Nuno Sá <noname.nuno@gmail.com> wrote: >>> >>>> On Mon, 2022-11-14 at 19:44 +0000, Jonathan Cameron wrote: >>>>> On Mon, 14 Nov 2022 13:52:26 +0000 >>>>> "Tanislav, Cosmin" <Cosmin.Tanislav@analog.com> wrote: >>>>> >>>>>>> >>>>>>> I'm a little confused on polarity here. The pin is a !reset so >>>>>>> we need to drive it low briefly to trigger a reset. >>>>>>> I'm guessing for your board the pin is set to active low? (an >>>>>>> example >>>>>>> in the dt would have made that clearer) Hence the pulse >>>>>>> in here to 1 is actually briefly driving it low before restoring >>>>>>> to high? >>>>>>> >>>>>>> For a pin documented as !reset that seems backwards though you >>>>>>> have >>>>>>> called it reset so that is fine, but this description doesn't >>>>>>> make that >>>>>>> celar. >>>>>> >>>>>> My opinion is that the driver shouldn't exactly know the polarity >>>>>> of the reset, >>>>>> and just assume that setting the reset GPIO to 1 means putting it >>>>>> in reset, >>>>>> and setting it to 0 means bringing out of reset. >>>>> >>>>> Agreed. I'd just like a comment + example in the dt-binding to make >>>>> the point >>>>> that the pin is !reset. >>>>> >>>>> Preferably with an example in the dt binding of the common case of it >>>>> being wired >>>>> up to an active low pin. >>>>> >>>>> The main oddity here is the need to pulse it rather than request it >>>>> directly as >>>>> in the reset state and then just set that to off. >>>>> >>>>> >>>> >>>> Agreed... In theory we should be able to request the gpio with >>>> GPIOD_OUT_HIGH and then just bring the device out of reset >>> >>> If I recall correctly the datasheet specifically calls out that a pulse >>> should be used. No idea if that's actually true, or if it was meant >>> to be there just to say it needs to be set for X nsecs. >> >> So the data sheet says >> >> The hardware reset is initiated by pulsing the RESET pin low. The >> RESET pulse width must comply with the specifications in Table 11. >> >> and table 11 says that the pulse must be min 50us, max 1ms. We don't >> really have any way whatsoever to ensure that we're not rescheduled >> right before pulling the gpio high again (deasserting the reset), so the >> pulse could effectively be much more than 1ms. But I have a hard time >> believing that that actually matters (i.e., what state would the chip be >> in if we happen to make a pulse 1234us wide?). > > Test it maybe? Otherwise we'd have to play games to do it again if the > timing was too long to ensure after a couple of goes we do get a suitable > width pulse. So I've booted quite a number of times with various large sleep values (between 1 and 10ms), and never seen a problem. Our hardware guys also confirm that there should be no such thing as a "too long" pulse. So do you want me to respin, moving the gpio request into the reset function (i.e. not storing the descriptor in the ad74413r_state as Nuno pointed out), requesting it in asserted state, and then, if the gpio was found, just do the fsleep(50) and then deassert it? Rasmus
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index 9f77d2f514de..af09d43f921c 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -71,6 +71,7 @@ struct ad74413r_state { struct regmap *regmap; struct device *dev; struct iio_trigger *trig; + struct gpio_desc *reset_gpio; size_t adc_active_channels; struct spi_message adc_samples_msg; @@ -393,6 +394,13 @@ static int ad74413r_reset(struct ad74413r_state *st) { int ret; + if (st->reset_gpio) { + gpiod_set_value_cansleep(st->reset_gpio, 1); + fsleep(50); + gpiod_set_value_cansleep(st->reset_gpio, 0); + return 0; + } + ret = regmap_write(st->regmap, AD74413R_REG_CMD_KEY, AD74413R_CMD_KEY_RESET1); if (ret) @@ -1316,6 +1324,10 @@ static int ad74413r_probe(struct spi_device *spi) if (IS_ERR(st->regmap)) return PTR_ERR(st->regmap); + st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(st->reset_gpio)) + return PTR_ERR(st->reset_gpio); + st->refin_reg = devm_regulator_get_optional(st->dev, "refin"); if (IS_ERR(st->refin_reg)) { ret = PTR_ERR(st->refin_reg);