Message ID | 20230609154200.3620-1-raymondhackley@protonmail.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp1042759vqr; Fri, 9 Jun 2023 09:00:48 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ7T3Yow+gfySrJ5dsQi6wEVsmHAYBOF3Q4NqApLuOlYwr6NXSsdBDsOrdgELz6xH032+FjP X-Received: by 2002:a05:6a21:99a5:b0:10c:62b3:7dc4 with SMTP id ve37-20020a056a2199a500b0010c62b37dc4mr1415263pzb.55.1686326447677; Fri, 09 Jun 2023 09:00:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1686326447; cv=none; d=google.com; s=arc-20160816; b=llphQORFi2hd9dVFmAdNiBG0pMwgaTta+nbwz07n4/KQnDGHwAtwXCXS8b09433YWq bmU+7HvDyCEpi4pblqE6zBgz2uW0YkVtwMMUIdtKbaLBklSsP8V4f84jaWrL3bfnHIIa aWZcfjJnu8z6WM3LweXvpyYqsJ4Iq8NkWOaAkc+qErn3Jg+S+h4KgQfxCnefG/QbEyzJ xJa250fKDM5Pw5f3Jz64vmVBa4hYPkkaEvHRUzTlK3Chm15mJgsyO4zIFL8H9IMztAjH YBW6kNbPx+6hkpOFPnFHo84twGlHsTLfBf3V+YRPBRKGOxIDlzu6ee+3SQRnE2+hCnqZ 8uvA== 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 :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :dkim-signature:date; bh=xadFqMnNfgl6gT0vaVLmkE//dImhTGrrvi/LgkS3A0c=; b=jzKLJwE/YDnNhKDqf4o2mgzRzAp9pxmLBGbWseSoM6ezLgYgMPldsB+Qod93mPtEX6 LRtihKP3P6Q9uu+IpNE8j3Qr67WGLcYBd5ef6G7IhF/QM179/slbEMuaJ2Z0+H0pFezz 7DnUDDT/o9xmJQDQ7BTjxaDF1TnfmzPYwhFXtVq2y0xlhnb4PqEz9KaT+ST2LHdbOBez eq0gsfukNIb4TwQbgVkPTKcw6Cleleb/svzAWhpVt4iYGseB750QXSO3LrJQ+HDLABjo 331yHl13f6vcJLZx+UNg7JAHAE6oqSksiq+peD01D5DTDqynZS0ffUsrmq38tAdxxqTV 5wMw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@protonmail.com header.s=protonmail3 header.b=eM8aZ7y+; 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; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b142-20020a621b94000000b0064f735aef04si2624999pfb.209.2023.06.09.09.00.23; Fri, 09 Jun 2023 09:00:47 -0700 (PDT) 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=@protonmail.com header.s=protonmail3 header.b=eM8aZ7y+; 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; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=protonmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241866AbjFIPmp (ORCPT <rfc822;liningstudo@gmail.com> + 99 others); Fri, 9 Jun 2023 11:42:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241900AbjFIPmc (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 9 Jun 2023 11:42:32 -0400 Received: from mail-40138.protonmail.ch (mail-40138.protonmail.ch [185.70.40.138]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A1CE30F7 for <linux-kernel@vger.kernel.org>; Fri, 9 Jun 2023 08:42:31 -0700 (PDT) Date: Fri, 09 Jun 2023 15:42:23 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com; s=protonmail3; t=1686325349; x=1686584549; bh=xadFqMnNfgl6gT0vaVLmkE//dImhTGrrvi/LgkS3A0c=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=eM8aZ7y+NM3rLwsevMhMxoeqKFgofaRbvBfA1ynKoGI8Oykbrfy6mIfE5ahu+SvWa xjwl76l4Bkqg6hiGtbDzfAJrnovcwfOFSTJugu/P9xK7W8QfKrc8Vw+mzFk6GvaIUR 91Dl98z0l7AAGCsKtC1OGNdv2tj48u+7LInVGv18OW+11cAo+SKAMB8esB9kD+XDuK 7Anic43oM4dz0RtpOnWpwksrVOrSvMvS6+6zjsQf6EWO4uLjGSzZVJ5LRCHouvaYz3 xF9Jk6wqpm+TeOUcF4DsyhyHMeGKhReUpAgEwPgFoGwVHylaEBkCJ3x2RcNAfsNng2 PtWc9X6Ru8UDg== To: linux-kernel@vger.kernel.org From: Raymond Hackley <raymondhackley@protonmail.com> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, "David S . Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Rob Herring <robh+dt@kernel.org>, Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>, Michael Walle <michael@walle.cc>, =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>, Jeremy Kerr <jk@codeconstruct.com.au>, Raymond Hackley <raymondhackley@protonmail.com>, netdev@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v2 2/2] NFC: nxp-nci: Add pad supply voltage pvdd-supply Message-ID: <20230609154200.3620-1-raymondhackley@protonmail.com> In-Reply-To: <20230609154033.3511-1-raymondhackley@protonmail.com> References: <20230609154033.3511-1-raymondhackley@protonmail.com> Feedback-ID: 49437091:user:proton MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,SPF_HELO_PASS, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED 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?1768241441435732038?= X-GMAIL-MSGID: =?utf-8?q?1768241441435732038?= |
Series |
NFC: nxp-nci: Add pad supply voltage pvdd-supply
|
|
Commit Message
Raymond Hackley
June 9, 2023, 3:42 p.m. UTC
PN547/553, QN310/330 chips on some devices require a pad supply voltage
(PVDD). Otherwise, the NFC won't power up.
Implement support for pad supply voltage pvdd-supply that is enabled by
the nxp-nci driver so that the regulator gets enabled when needed.
Signed-off-by: Raymond Hackley <raymondhackley@protonmail.com>
---
drivers/nfc/nxp-nci/i2c.c | 42 +++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
Comments
On 09/06/2023 17:42, Raymond Hackley wrote: > PN547/553, QN310/330 chips on some devices require a pad supply voltage > (PVDD). Otherwise, the NFC won't power up. > > Implement support for pad supply voltage pvdd-supply that is enabled by > the nxp-nci driver so that the regulator gets enabled when needed. > > Signed-off-by: Raymond Hackley <raymondhackley@protonmail.com> > --- > drivers/nfc/nxp-nci/i2c.c | 42 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 42 insertions(+) > > diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c > index d4c299be7949..1b8877757cee 100644 > --- a/drivers/nfc/nxp-nci/i2c.c > +++ b/drivers/nfc/nxp-nci/i2c.c > @@ -35,6 +35,7 @@ struct nxp_nci_i2c_phy { > > struct gpio_desc *gpiod_en; > struct gpio_desc *gpiod_fw; > + struct regulator *pvdd; > > int hard_fault; /* > * < 0 if hardware error occurred (e.g. i2c err) > @@ -263,6 +264,22 @@ static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { > { } > }; > > +static void nxp_nci_i2c_poweroff(void *data) > +{ > + struct nxp_nci_i2c_phy *phy = data; > + struct device *dev = &phy->i2c_dev->dev; > + struct regulator *pvdd = phy->pvdd; > + int r; > + > + if (!IS_ERR(pvdd) && regulator_is_enabled(pvdd)) { Why do you need these checks? This should be called in correct context, so when regulator is valid and enabled. If you have such checks it suggests that code is buggy and this is being called in wrong contexts. > + r = regulator_disable(pvdd); > + if (r < 0) > + dev_warn(dev, > + "Failed to disable regulator pvdd: %d\n", > + r); Weird wrapping. Why r is wrapped? > + } > +} > + > static int nxp_nci_i2c_probe(struct i2c_client *client) > { > struct device *dev = &client->dev; > @@ -298,6 +315,29 @@ static int nxp_nci_i2c_probe(struct i2c_client *client) > return PTR_ERR(phy->gpiod_fw); > } > > + phy->pvdd = devm_regulator_get_optional(dev, "pvdd"); > + if (IS_ERR(phy->pvdd)) { > + r = PTR_ERR(phy->pvdd); > + if (r != -ENODEV) > + return dev_err_probe(dev, r, > + "Failed to get regulator pvdd\n"); > + } else { > + r = regulator_enable(phy->pvdd); > + if (r < 0) { > + nfc_err(dev, > + "Failed to enable regulator pvdd: %d\n", > + r); Weird wrapping. Why r is wrapped? > + return r; > + } > + } > + > + r = devm_add_action_or_reset(dev, nxp_nci_i2c_poweroff, phy); > + if (r < 0) { > + nfc_err(dev, "Failed to install poweroff handler: %d\n", > + r); Weird wrapping. Why r is wrapped? Just move it to the success path of enabling regulator. > + return r; > + } > + > r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, > NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); > if (r < 0) > @@ -319,6 +359,8 @@ static void nxp_nci_i2c_remove(struct i2c_client *client) > > nxp_nci_remove(phy->ndev); > free_irq(client->irq, phy); > + > + nxp_nci_i2c_poweroff(phy); Why? This code is buggy... Best regards, Krzysztof
Hi Krzysztof, On Friday, June 9th, 2023 at 3:46 PM, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote: > On 09/06/2023 17:42, Raymond Hackley wrote: > > > PN547/553, QN310/330 chips on some devices require a pad supply voltage > > (PVDD). Otherwise, the NFC won't power up. > > > > Implement support for pad supply voltage pvdd-supply that is enabled by > > the nxp-nci driver so that the regulator gets enabled when needed. > > > > Signed-off-by: Raymond Hackley raymondhackley@protonmail.com > > --- > > drivers/nfc/nxp-nci/i2c.c | 42 +++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 42 insertions(+) > > > > diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c > > index d4c299be7949..1b8877757cee 100644 > > --- a/drivers/nfc/nxp-nci/i2c.c > > +++ b/drivers/nfc/nxp-nci/i2c.c > > @@ -35,6 +35,7 @@ struct nxp_nci_i2c_phy { > > > > struct gpio_desc *gpiod_en; > > struct gpio_desc *gpiod_fw; > > + struct regulator *pvdd; > > > > int hard_fault; /* > > * < 0 if hardware error occurred (e.g. i2c err) > > @@ -263,6 +264,22 @@ static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { > > { } > > }; > > > > +static void nxp_nci_i2c_poweroff(void *data) > > +{ > > + struct nxp_nci_i2c_phy *phy = data; > > + struct device *dev = &phy->i2c_dev->dev; > > + struct regulator *pvdd = phy->pvdd; > > + int r; > > + > > + if (!IS_ERR(pvdd) && regulator_is_enabled(pvdd)) { > > > Why do you need these checks? This should be called in correct context, > so when regulator is valid and enabled. If you have such checks it > suggests that code is buggy and this is being called in wrong contexts. > First condition !IS_ERR(pvdd) is to check if pvdd exists. Some devices, msm8916-samsung-serranove for example, doesn't need pvdd or have it bound in the device tree: https://github.com/torvalds/linux/commit/ab0f0987e035f908d670fed7d86efa6fac66c0bb Without !IS_ERR(pvdd), checking it with regulator_is_enabled(pvdd): [ 50.161882] 8<--- cut here --- [ 50.161906] Unable to handle kernel paging request at virtual address fffffff9 when read [ 50.161916] [fffffff9] *pgd=affff841, *pte=00000000, *ppte=00000000 [ 50.161938] Internal error: Oops: 27 [#1] PREEMPT SMP ARM Or disabling it directly with regulator_disable(pvdd): [ 69.439827] 8<--- cut here --- [ 69.439841] Unable to handle kernel NULL pointer dereference at virtual address 00000045 when read [ 69.439852] [00000045] *pgd=00000000 [ 69.439864] Internal error: Oops: 5 [#1] PREEMPT SMP ARM Second condition regulator_is_enabled(pvdd) is to make sure that pvdd is disabled with balance. Similar checks can be found here: https://elixir.bootlin.com/linux/v6.4-rc5/source/drivers/staging/greybus/arche-apb-ctrl.c#L208 > > + r = regulator_disable(pvdd); > > + if (r < 0) > > + dev_warn(dev, > > + "Failed to disable regulator pvdd: %d\n", > > + r); > > > Weird wrapping. Why r is wrapped? > > > + } > > +} > > + > > static int nxp_nci_i2c_probe(struct i2c_client *client) > > { > > struct device *dev = &client->dev; > > @@ -298,6 +315,29 @@ static int nxp_nci_i2c_probe(struct i2c_client *client) > > return PTR_ERR(phy->gpiod_fw); > > } > > > > + phy->pvdd = devm_regulator_get_optional(dev, "pvdd"); > > + if (IS_ERR(phy->pvdd)) { > > + r = PTR_ERR(phy->pvdd); > > + if (r != -ENODEV) > > + return dev_err_probe(dev, r, > > + "Failed to get regulator pvdd\n"); > > + } else { > > + r = regulator_enable(phy->pvdd); > > + if (r < 0) { > > + nfc_err(dev, > > + "Failed to enable regulator pvdd: %d\n", > > + r); > > > Weird wrapping. Why r is wrapped? > > > + return r; > > + } > > + } > > + > > + r = devm_add_action_or_reset(dev, nxp_nci_i2c_poweroff, phy); > > + if (r < 0) { > > + nfc_err(dev, "Failed to install poweroff handler: %d\n", > > + r); > > > Weird wrapping. Why r is wrapped? > > Just move it to the success path of enabling regulator. > Yes. This will be fixed in v3. > > + return r; > > + } > > + > > r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, > > NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); > > if (r < 0) > > @@ -319,6 +359,8 @@ static void nxp_nci_i2c_remove(struct i2c_client *client) > > > > nxp_nci_remove(phy->ndev); > > free_irq(client->irq, phy); > > + > > + nxp_nci_i2c_poweroff(phy); > > > Why? This code is buggy... > I don't have a good reason to keep it and will drop it in v3. Regards, Raymond > > > Best regards, > Krzysztof
On 09/06/2023 19:40, Raymond Hackley wrote: > Hi Krzysztof, > > On Friday, June 9th, 2023 at 3:46 PM, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote: > > >> On 09/06/2023 17:42, Raymond Hackley wrote: >> >>> PN547/553, QN310/330 chips on some devices require a pad supply voltage >>> (PVDD). Otherwise, the NFC won't power up. >>> >>> Implement support for pad supply voltage pvdd-supply that is enabled by >>> the nxp-nci driver so that the regulator gets enabled when needed. >>> >>> Signed-off-by: Raymond Hackley raymondhackley@protonmail.com >>> --- >>> drivers/nfc/nxp-nci/i2c.c | 42 +++++++++++++++++++++++++++++++++++++++ >>> 1 file changed, 42 insertions(+) >>> >>> diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c >>> index d4c299be7949..1b8877757cee 100644 >>> --- a/drivers/nfc/nxp-nci/i2c.c >>> +++ b/drivers/nfc/nxp-nci/i2c.c >>> @@ -35,6 +35,7 @@ struct nxp_nci_i2c_phy { >>> >>> struct gpio_desc *gpiod_en; >>> struct gpio_desc *gpiod_fw; >>> + struct regulator *pvdd; >>> >>> int hard_fault; /* >>> * < 0 if hardware error occurred (e.g. i2c err) >>> @@ -263,6 +264,22 @@ static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { >>> { } >>> }; >>> >>> +static void nxp_nci_i2c_poweroff(void *data) >>> +{ >>> + struct nxp_nci_i2c_phy *phy = data; >>> + struct device *dev = &phy->i2c_dev->dev; >>> + struct regulator *pvdd = phy->pvdd; >>> + int r; >>> + >>> + if (!IS_ERR(pvdd) && regulator_is_enabled(pvdd)) { >> >> >> Why do you need these checks? This should be called in correct context, >> so when regulator is valid and enabled. If you have such checks it >> suggests that code is buggy and this is being called in wrong contexts. >> > > First condition !IS_ERR(pvdd) is to check if pvdd exists. > Some devices, msm8916-samsung-serranove for example, doesn't need pvdd or > have it bound in the device tree: If regulator is missing you should get a dummy. But anyway the code will not be executed if you don't get proper regulator. > > https://github.com/torvalds/linux/commit/ab0f0987e035f908d670fed7d86efa6fac66c0bb > > Without !IS_ERR(pvdd), checking it with regulator_is_enabled(pvdd): > > [ 50.161882] 8<--- cut here --- > [ 50.161906] Unable to handle kernel paging request at virtual address fffffff9 when read > [ 50.161916] [fffffff9] *pgd=affff841, *pte=00000000, *ppte=00000000 > [ 50.161938] Internal error: Oops: 27 [#1] PREEMPT SMP ARM > > Or disabling it directly with regulator_disable(pvdd): > > [ 69.439827] 8<--- cut here --- > [ 69.439841] Unable to handle kernel NULL pointer dereference at virtual address 00000045 when read > [ 69.439852] [00000045] *pgd=00000000 > [ 69.439864] Internal error: Oops: 5 [#1] PREEMPT SMP ARM > > Second condition regulator_is_enabled(pvdd) is to make sure that pvdd is > disabled with balance. > So you have buggy code and to hide the bug you add checks? No, make the code correct so the check is not needed. > Similar checks can be found here: > > https://elixir.bootlin.com/linux/v6.4-rc5/source/drivers/staging/greybus/arche-apb-ctrl.c#L208 staging driver is not an example... > Best regards, Krzysztof
On Fri, Jun 09, 2023 at 09:29:51PM +0200, Krzysztof Kozlowski wrote: > On 09/06/2023 19:40, Raymond Hackley wrote: > > On Friday, June 9th, 2023 at 3:46 PM, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote: > > Second condition regulator_is_enabled(pvdd) is to make sure that pvdd is > > disabled with balance. > So you have buggy code and to hide the bug you add checks? No, make the > code correct so the check is not needed. Specifically your driver should only ever call regulator_disable() to balance out regulator_enable() calls it made itself and it should know how many of those it has done. regulator_is_enabled() should only ever be used during probe if for some reason it is important to figure out if the device is already powered for startup, this should be very unusual. If something else enabled the regualtor then whatever did that needs to undo those enables, not another driver.
Hi Krzysztof, On Friday, June 9th, 2023 at 7:29 PM, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> wrote: > > > Why do you need these checks? This should be called in correct context, > > > so when regulator is valid and enabled. If you have such checks it > > > suggests that code is buggy and this is being called in wrong contexts. > > > > First condition !IS_ERR(pvdd) is to check if pvdd exists. > > Some devices, msm8916-samsung-serranove for example, doesn't need pvdd or > > have it bound in the device tree: > > > If regulator is missing you should get a dummy. > > But anyway the code will not be executed if you don't get proper regulator. > The current patch set is using devm_regulator_get_optional() instead of devm_regulator_get(), which doesn't get a dummy regulator. > > https://github.com/torvalds/linux/commit/ab0f0987e035f908d670fed7d86efa6fac66c0bb > > > > Without !IS_ERR(pvdd), checking it with regulator_is_enabled(pvdd): > > > > [ 50.161882] 8<--- cut here --- > > [ 50.161906] Unable to handle kernel paging request at virtual address fffffff9 when read > > [ 50.161916] [fffffff9] *pgd=affff841, *pte=00000000, *ppte=00000000 > > [ 50.161938] Internal error: Oops: 27 [#1] PREEMPT SMP ARM > > > > Or disabling it directly with regulator_disable(pvdd): > > > > [ 69.439827] 8<--- cut here --- > > [ 69.439841] Unable to handle kernel NULL pointer dereference at virtual address 00000045 when read > > [ 69.439852] [00000045] *pgd=00000000 > > [ 69.439864] Internal error: Oops: 5 [#1] PREEMPT SMP ARM > > > > Second condition regulator_is_enabled(pvdd) is to make sure that pvdd is > > disabled with balance. > > > So you have buggy code and to hide the bug you add checks? No, make the > code correct so the check is not needed. > Do you mean that I should use devm_regulator_get() instead in order to get a dummy regulator, so that it can disable pvdd without unnecessary checks? Actually there is v4 with those buggy codes and checks dropped. Please do let me know if I am understanding and doing it correctly. I would send it after proper period of cooldown. Regards, Raymond
Hi Mark, On Friday, June 9th, 2023 at 7:34 PM, Mark Brown <broonie@kernel.org> wrote: > Specifically your driver should only ever call regulator_disable() to > balance out regulator_enable() calls it made itself and it should know > how many of those it has done. regulator_is_enabled() should only ever > be used during probe if for some reason it is important to figure out if > the device is already powered for startup, this should be very unusual. > If something else enabled the regualtor then whatever did that needs to > undo those enables, not another driver. Thnak you for explanation. I should drop regulator_is_enabled() here since it's misused. Regards, Raymond
diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index d4c299be7949..1b8877757cee 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -35,6 +35,7 @@ struct nxp_nci_i2c_phy { struct gpio_desc *gpiod_en; struct gpio_desc *gpiod_fw; + struct regulator *pvdd; int hard_fault; /* * < 0 if hardware error occurred (e.g. i2c err) @@ -263,6 +264,22 @@ static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = { { } }; +static void nxp_nci_i2c_poweroff(void *data) +{ + struct nxp_nci_i2c_phy *phy = data; + struct device *dev = &phy->i2c_dev->dev; + struct regulator *pvdd = phy->pvdd; + int r; + + if (!IS_ERR(pvdd) && regulator_is_enabled(pvdd)) { + r = regulator_disable(pvdd); + if (r < 0) + dev_warn(dev, + "Failed to disable regulator pvdd: %d\n", + r); + } +} + static int nxp_nci_i2c_probe(struct i2c_client *client) { struct device *dev = &client->dev; @@ -298,6 +315,29 @@ static int nxp_nci_i2c_probe(struct i2c_client *client) return PTR_ERR(phy->gpiod_fw); } + phy->pvdd = devm_regulator_get_optional(dev, "pvdd"); + if (IS_ERR(phy->pvdd)) { + r = PTR_ERR(phy->pvdd); + if (r != -ENODEV) + return dev_err_probe(dev, r, + "Failed to get regulator pvdd\n"); + } else { + r = regulator_enable(phy->pvdd); + if (r < 0) { + nfc_err(dev, + "Failed to enable regulator pvdd: %d\n", + r); + return r; + } + } + + r = devm_add_action_or_reset(dev, nxp_nci_i2c_poweroff, phy); + if (r < 0) { + nfc_err(dev, "Failed to install poweroff handler: %d\n", + r); + return r; + } + r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops, NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev); if (r < 0) @@ -319,6 +359,8 @@ static void nxp_nci_i2c_remove(struct i2c_client *client) nxp_nci_remove(phy->ndev); free_irq(client->irq, phy); + + nxp_nci_i2c_poweroff(phy); } static const struct i2c_device_id nxp_nci_i2c_id_table[] = {