Message ID | 20231027033104.1348921-3-chris.packham@alliedtelesis.co.nz |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp332939vqb; Thu, 26 Oct 2023 20:31:52 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEi3aq3KVjhhZOw1Ry99p0+jVpdKA5GzZ3oB055VHP19cODS5Ntw2ALP96ZmHxmhPpQO9OB X-Received: by 2002:a25:aaca:0:b0:d9b:90d2:aadf with SMTP id t68-20020a25aaca000000b00d9b90d2aadfmr1448402ybi.49.1698377512691; Thu, 26 Oct 2023 20:31:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698377512; cv=none; d=google.com; s=arc-20160816; b=UN6DJ3lHFOUUdNY6DSshNL1M986xnrM4mO4yECTK08QaoGdAQ4VN7LWG7sPPMY6Lvx ll77RxnKGe7np2Rrx7pzaQYWi3jyfcQOxY+nyu/xNZjkocaKvTCoGAaYAzrmr7fiG1rk MPEyDyALBepo7eXw/pMFj1TFvJIIzivN5SXxhJLzGSNlYMmbpSuZo98nXhFWax+FkVV6 oYjYXj5l+vjj2yI5s+tPSiPMbTwaPKy/GArmWEzzbyaAM0q2sAwADmEbG2dmXatAFLbp bpkXn68BCOurC+v6/URfJPFb8kgI2WSjXW98LWBQ3Uaif2ehWtvFDXBC8b2MzpIhmikp 6MfQ== 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=eKuOlH3mcTKwkcxUdBepoU2Jh55BslCIjozuw6RTt1Q=; fh=3tQj0XukzIaVVOd6lLPEALhtzKzMAG+0/N98Vq3ytYw=; b=NPyjo/uuLg9p7l3mLYApcHefHbEYotiyWcQ77AV8ad4TVlTKl7M2b3QQ2JlPf1q0FE G/pDLq4r5ziCEEyG5FGaW1H7RhrCNXWBBzQBqorCnJLjBpzkSTrMqtGy7WJvRmVBIevq X6N6dkoNg4yUUVtHsI+9jduFnQrtIt9E1qz0HJiua880zIYcuc/ACDnpiH28mZViC/Bl AAXEmSP43G1SwGjTl1oJqDuyN2kj7tZmbDnCFVJRFldic1D/ZtPdRocTDHq1xppEAn8X pbTfZx6r0HiVYs78SYdGlzLNtTGap8MDeqw1J0GHPTZSYOICwKcBKIwfoI+FjnjA+Mw1 WqdA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@alliedtelesis.co.nz header.s=mail181024 header.b=UHGTRAqk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=alliedtelesis.co.nz Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id h14-20020a25d00e000000b00da0ca27493esi1466653ybg.384.2023.10.26.20.31.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Oct 2023 20:31:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@alliedtelesis.co.nz header.s=mail181024 header.b=UHGTRAqk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=REJECT dis=NONE) header.from=alliedtelesis.co.nz Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id DEF35836E562; Thu, 26 Oct 2023 20:31:49 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345223AbjJ0DbV (ORCPT <rfc822;aposhian.dev@gmail.com> + 26 others); Thu, 26 Oct 2023 23:31:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44006 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233035AbjJ0DbP (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 26 Oct 2023 23:31:15 -0400 Received: from gate2.alliedtelesis.co.nz (gate2.alliedtelesis.co.nz [IPv6:2001:df5:b000:5::4]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3D6001A1 for <linux-kernel@vger.kernel.org>; Thu, 26 Oct 2023 20:31:12 -0700 (PDT) Received: from svr-chch-seg1.atlnz.lc (mmarshal3.atlnz.lc [10.32.18.43]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by gate2.alliedtelesis.co.nz (Postfix) with ESMTPS id 32C782C018E; Fri, 27 Oct 2023 16:31:09 +1300 (NZDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alliedtelesis.co.nz; s=mail181024; t=1698377469; bh=eKuOlH3mcTKwkcxUdBepoU2Jh55BslCIjozuw6RTt1Q=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UHGTRAqko+Q0b0WXRqZnJjtX6W3JwCDQH/zLSuA5oX7hJzut+1BPG6zaAj4HGmO6j fAM/rnMR60SAQhghD1ffROFIWIO25LOqQ4tIcZSoORNxUtu7lJTV1RhOM3Gpjt2bM6 b+9wSSykJWQCey0ap2xUM8sc6PL4HRfvtw2k8JdsdBR+mYrLUIJIwTmSDIfjyuLkpv vU3wRq/F4oKhQT6UBqcxckPDNnE9Sh0B9s8pfXUtqoMLu6XAGFexfrLvPZLcDwn0Gc fLp6qdjaJxdjxhvlbkS6tx5j1Fs1XF4gD934eB/mhyvr13216Y9Ygp9ybP6OjUAgO9 WLYzQ3W+qtt7g== Received: from pat.atlnz.lc (Not Verified[10.32.16.33]) by svr-chch-seg1.atlnz.lc with Trustwave SEG (v8,2,6,11305) id <B653b2efc0002>; Fri, 27 Oct 2023 16:31:08 +1300 Received: from chrisp-dl.ws.atlnz.lc (chrisp-dl.ws.atlnz.lc [10.33.22.30]) by pat.atlnz.lc (Postfix) with ESMTP id 6086313EE87; Fri, 27 Oct 2023 16:31:08 +1300 (NZDT) Received: by chrisp-dl.ws.atlnz.lc (Postfix, from userid 1030) id 5E956280347; Fri, 27 Oct 2023 16:31:08 +1300 (NZDT) From: Chris Packham <chris.packham@alliedtelesis.co.nz> To: gregory.clement@bootlin.com, andi.shyti@kernel.org, robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Packham <chris.packham@alliedtelesis.co.nz> Subject: [PATCH v5 2/2] i2c: mv64xxx: add an optional bus-reset-gpios property Date: Fri, 27 Oct 2023 16:31:04 +1300 Message-ID: <20231027033104.1348921-3-chris.packham@alliedtelesis.co.nz> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231027033104.1348921-1-chris.packham@alliedtelesis.co.nz> References: <20231027033104.1348921-1-chris.packham@alliedtelesis.co.nz> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SEG-SpamProfiler-Analysis: v=2.3 cv=L6ZjvNb8 c=1 sm=1 tr=0 a=KLBiSEs5mFS1a/PbTCJxuA==:117 a=bhdUkHdE2iEA:10 a=VsZq4EHS3crWG1I_hwYA:9 X-SEG-SpamProfiler-Score: 0 x-atlnz-ls: pat X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Thu, 26 Oct 2023 20:31:49 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780877898526753018 X-GMAIL-MSGID: 1780877898526753018 |
Series |
i2c: mv64xxx: bus-reset-gpios
|
|
Commit Message
Chris Packham
Oct. 27, 2023, 3:31 a.m. UTC
Some hardware designs have a GPIO used to control the reset of all the
devices on and I2C bus. It's not possible for every child node to
declare a reset-gpios property as only the first device probed would be
able to successfully request it (the others will get -EBUSY). Represent
this kind of hardware design by associating the bus-reset-gpios with the
parent I2C bus. The reset line will be released prior to the child I2C
devices being probed.
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
Notes:
Changes in v5:
- Rename reset-gpios and reset-duration-us to bus-reset-gpios and
bus-reset-duration-us as requested by Wolfram
Changes in v4:
- Add missing gpio/consumer.h
- use fsleep() for enforcing reset-duration
Changes in v3:
- Rename reset-delay to reset-duration
- Use reset-duration-us property to control the reset pulse rather than
delaying after the reset
Changes in v2:
- Add a property to cover the length of delay after releasing the reset
GPIO
- Use dev_err_probe() when requesing the GPIO fails
drivers/i2c/busses/i2c-mv64xxx.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
Comments
Hi Chris, On Fri, Oct 27, 2023 at 04:31:04PM +1300, Chris Packham wrote: > Some hardware designs have a GPIO used to control the reset of all the > devices on and I2C bus. It's not possible for every child node to > declare a reset-gpios property as only the first device probed would be > able to successfully request it (the others will get -EBUSY). Represent > this kind of hardware design by associating the bus-reset-gpios with the > parent I2C bus. The reset line will be released prior to the child I2C > devices being probed. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v5: > - Rename reset-gpios and reset-duration-us to bus-reset-gpios and > bus-reset-duration-us as requested by Wolfram for such change you could have kept my r-b: Reviewed-by: Andi Shyti <andi.shyti@kernel.org> Andi
On 27/10/2023 05:31, Chris Packham wrote: > Some hardware designs have a GPIO used to control the reset of all the > devices on and I2C bus. It's not possible for every child node to > declare a reset-gpios property as only the first device probed would be > able to successfully request it (the others will get -EBUSY). Represent > this kind of hardware design by associating the bus-reset-gpios with the > parent I2C bus. The reset line will be released prior to the child I2C > devices being probed. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v5: > - Rename reset-gpios and reset-duration-us to bus-reset-gpios and > bus-reset-duration-us as requested by Wolfram > Changes in v4: > - Add missing gpio/consumer.h > - use fsleep() for enforcing reset-duration > Changes in v3: > - Rename reset-delay to reset-duration > - Use reset-duration-us property to control the reset pulse rather than > delaying after the reset > Changes in v2: > - Add a property to cover the length of delay after releasing the reset > GPIO > - Use dev_err_probe() when requesing the GPIO fails > > drivers/i2c/busses/i2c-mv64xxx.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c > index efd28bbecf61..6e2762d22e5a 100644 > --- a/drivers/i2c/busses/i2c-mv64xxx.c > +++ b/drivers/i2c/busses/i2c-mv64xxx.c > @@ -13,6 +13,7 @@ > #include <linux/slab.h> > #include <linux/module.h> > #include <linux/spinlock.h> > +#include <linux/gpio/consumer.h> > #include <linux/i2c.h> > #include <linux/interrupt.h> > #include <linux/mv643xx_i2c.h> > @@ -160,6 +161,7 @@ struct mv64xxx_i2c_data { > bool clk_n_base_0; > struct i2c_bus_recovery_info rinfo; > bool atomic; > + struct gpio_desc *reset_gpio; > }; > > static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { > @@ -1036,6 +1038,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) > struct mv64xxx_i2c_data *drv_data; > struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); > struct resource *res; > + u32 reset_duration; > int rc; > > if ((!pdata && !pd->dev.of_node)) > @@ -1083,6 +1086,14 @@ mv64xxx_i2c_probe(struct platform_device *pd) > if (drv_data->irq < 0) > return drv_data->irq; > > + drv_data->reset_gpio = devm_gpiod_get_optional(&pd->dev, "bus-reset", GPIOD_OUT_HIGH); > + if (IS_ERR(drv_data->reset_gpio)) > + return dev_err_probe(&pd->dev, PTR_ERR(drv_data->reset_gpio), > + "Cannot get reset gpio\n"); > + rc = device_property_read_u32(&pd->dev, "bus-reset-duration-us", &reset_duration); > + if (rc) > + reset_duration = 1; No, this should be solved by core - for entire I2C at minimum. This is not specific to this device. Best regards, Krzysztof
On 27/10/2023 13:27, Krzysztof Kozlowski wrote: > On 27/10/2023 05:31, Chris Packham wrote: >> Some hardware designs have a GPIO used to control the reset of all the >> devices on and I2C bus. It's not possible for every child node to >> declare a reset-gpios property as only the first device probed would be >> able to successfully request it (the others will get -EBUSY). Represent Cc: Mark, Also this part is not true. If the bus is non-discoverable, then it is possible to have reset-gpios in each probed device. You can share GPIOs, so no problem with -EBUSY at all. The problem is doing reset: 1. in proper moment for all devices 2. without affecting other devices when one unbinds/remove() The (2) above is not solveable easy in kernel and we already had nice talks about it just few days ago: 1. Apple case: https://social.treehouse.systems/@marcan/111268780311634160 2. my WSA884x: https://lore.kernel.org/alsa-devel/84f9f1c4-0627-4986-8160-b4ab99469b81@linaro.org/ Last, I would like to apologize to you Chris. I understand that bringing such feedback at v5 is not that good. I had plenty of time to say something earlier, so this is not really professional from my side. I am sorry, just my brain did not connect all these topics together. I apologize. Best regards, Krzysztof >> this kind of hardware design by associating the bus-reset-gpios with the >> parent I2C bus. The reset line will be released prior to the child I2C >> devices being probed. >> >> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> >> --- >> >> Notes: >> Changes in v5: >> - Rename reset-gpios and reset-duration-us to bus-reset-gpios and >> bus-reset-duration-us as requested by Wolfram >> Changes in v4: >> - Add missing gpio/consumer.h >> - use fsleep() for enforcing reset-duration >> Changes in v3: >> - Rename reset-delay to reset-duration >> - Use reset-duration-us property to control the reset pulse rather than >> delaying after the reset >> Changes in v2: >> - Add a property to cover the length of delay after releasing the reset >> GPIO >> - Use dev_err_probe() when requesing the GPIO fails >> >> drivers/i2c/busses/i2c-mv64xxx.c | 16 ++++++++++++++++ >> 1 file changed, 16 insertions(+) >> >> diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c >> index efd28bbecf61..6e2762d22e5a 100644 >> --- a/drivers/i2c/busses/i2c-mv64xxx.c >> +++ b/drivers/i2c/busses/i2c-mv64xxx.c >> @@ -13,6 +13,7 @@ >> #include <linux/slab.h> >> #include <linux/module.h> >> #include <linux/spinlock.h> >> +#include <linux/gpio/consumer.h> >> #include <linux/i2c.h> >> #include <linux/interrupt.h> >> #include <linux/mv643xx_i2c.h> >> @@ -160,6 +161,7 @@ struct mv64xxx_i2c_data { >> bool clk_n_base_0; >> struct i2c_bus_recovery_info rinfo; >> bool atomic; >> + struct gpio_desc *reset_gpio; >> }; >> >> static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { >> @@ -1036,6 +1038,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) >> struct mv64xxx_i2c_data *drv_data; >> struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); >> struct resource *res; >> + u32 reset_duration; >> int rc; >> >> if ((!pdata && !pd->dev.of_node)) >> @@ -1083,6 +1086,14 @@ mv64xxx_i2c_probe(struct platform_device *pd) >> if (drv_data->irq < 0) >> return drv_data->irq; >> >> + drv_data->reset_gpio = devm_gpiod_get_optional(&pd->dev, "bus-reset", GPIOD_OUT_HIGH); >> + if (IS_ERR(drv_data->reset_gpio)) >> + return dev_err_probe(&pd->dev, PTR_ERR(drv_data->reset_gpio), >> + "Cannot get reset gpio\n"); >> + rc = device_property_read_u32(&pd->dev, "bus-reset-duration-us", &reset_duration); >> + if (rc) >> + reset_duration = 1; > > No, this should be solved by core - for entire I2C at minimum. This is > not specific to this device.
Hi Krzysztof, On Fri, Oct 27, 2023 at 01:37:05PM +0200, Krzysztof Kozlowski wrote: > On 27/10/2023 13:27, Krzysztof Kozlowski wrote: > > On 27/10/2023 05:31, Chris Packham wrote: > >> Some hardware designs have a GPIO used to control the reset of all the > >> devices on and I2C bus. It's not possible for every child node to > >> declare a reset-gpios property as only the first device probed would be > >> able to successfully request it (the others will get -EBUSY). Represent > > Cc: Mark, > > Also this part is not true. If the bus is non-discoverable, then it is > possible to have reset-gpios in each probed device. You can share GPIOs, > so no problem with -EBUSY at all. > > The problem is doing reset: > 1. in proper moment for all devices > 2. without affecting other devices when one unbinds/remove() yes, I thought that we could get to this point, but I did not object the patch as I didn't see an immediate better solution. I would still be OK to merge it until we develop something better. Let me mull this over and will be back to the topic. Thanks, Krzysztof! Andi > The (2) above is not solveable easy in kernel and we already had nice > talks about it just few days ago: > 1. Apple case: > https://social.treehouse.systems/@marcan/111268780311634160 > > 2. my WSA884x: > https://lore.kernel.org/alsa-devel/84f9f1c4-0627-4986-8160-b4ab99469b81@linaro.org/ > > Last, > I would like to apologize to you Chris. I understand that bringing such > feedback at v5 is not that good. I had plenty of time to say something > earlier, so this is not really professional from my side. I am sorry, > just my brain did not connect all these topics together. > > I apologize. > > Best regards, > Krzysztof
On Fri, Oct 27, 2023 at 01:37:05PM +0200, Krzysztof Kozlowski wrote: > The (2) above is not solveable easy in kernel and we already had nice > talks about it just few days ago: > 1. Apple case: > https://social.treehouse.systems/@marcan/111268780311634160 Note that the Apple case is not a reset, it's a low power mode for the device, though at the GPIO level the beheviour with tying together multiple devices that need to coordinate their usage looks very similar.
On 28/10/23 00:37, Krzysztof Kozlowski wrote: > On 27/10/2023 13:27, Krzysztof Kozlowski wrote: >> On 27/10/2023 05:31, Chris Packham wrote: >>> Some hardware designs have a GPIO used to control the reset of all the >>> devices on and I2C bus. It's not possible for every child node to >>> declare a reset-gpios property as only the first device probed would be >>> able to successfully request it (the others will get -EBUSY). Represent > Cc: Mark, > > Also this part is not true. If the bus is non-discoverable, then it is > possible to have reset-gpios in each probed device. You can share GPIOs, > so no problem with -EBUSY at all. Last time I checked you couldn't share GPIOs. If that's no longer the case then I can probably make what I need to happen work. It still creates an issue that I have multiple PCA954x muxes connected to a common reset GPIO so as each mux is probed the PCA954x driver will toggle the reset. That's probably OK as the PCA954x is sufficiently stateless that the extra resets won't do any harm but if it were a more complicated device then there would be issues. Having some kind of ref-counted reset controller that is implemented with GPIOs is probably the better solution. I was kind of surprised that nothing existed like that in drivers/reset. > The problem is doing reset: > 1. in proper moment for all devices > 2. without affecting other devices when one unbinds/remove() > > The (2) above is not solveable easy in kernel and we already had nice > talks about it just few days ago: > 1. Apple case: > https://scanmail.trustwave.com/?c=20988&d=6qC75SLs-9PNM1ZHpLa6reGv82R6opEUmyI62vCytQ&u=https%3a%2f%2fsocial%2etreehouse%2esystems%2f%40marcan%2f111268780311634160 > > 2. my WSA884x: > https://scanmail.trustwave.com/?c=20988&d=6qC75SLs-9PNM1ZHpLa6reGv82R6opEUmyJk3q3j7g&u=https%3a%2f%2flore%2ekernel%2eorg%2falsa-devel%2f84f9f1c4-0627-4986-8160-b4ab99469b81%40linaro%2eorg%2f Apologies for the mangled links (they're more secure now at least that's what our IS team have been sold). > Last, > I would like to apologize to you Chris. I understand that bringing such > feedback at v5 is not that good. I had plenty of time to say something > earlier, so this is not really professional from my side. I am sorry, > just my brain did not connect all these topics together. > > I apologize. Actually I kind of expected this feedback. I figured I could start with the driver that is currently causing me issues and once the dt-binding was considered good enough it might migrate to the i2c core. > > Best regards, > Krzysztof > >>> this kind of hardware design by associating the bus-reset-gpios with the >>> parent I2C bus. The reset line will be released prior to the child I2C >>> devices being probed. >>> >>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> >>> --- >>> >>> Notes: >>> Changes in v5: >>> - Rename reset-gpios and reset-duration-us to bus-reset-gpios and >>> bus-reset-duration-us as requested by Wolfram >>> Changes in v4: >>> - Add missing gpio/consumer.h >>> - use fsleep() for enforcing reset-duration >>> Changes in v3: >>> - Rename reset-delay to reset-duration >>> - Use reset-duration-us property to control the reset pulse rather than >>> delaying after the reset >>> Changes in v2: >>> - Add a property to cover the length of delay after releasing the reset >>> GPIO >>> - Use dev_err_probe() when requesing the GPIO fails >>> >>> drivers/i2c/busses/i2c-mv64xxx.c | 16 ++++++++++++++++ >>> 1 file changed, 16 insertions(+) >>> >>> diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c >>> index efd28bbecf61..6e2762d22e5a 100644 >>> --- a/drivers/i2c/busses/i2c-mv64xxx.c >>> +++ b/drivers/i2c/busses/i2c-mv64xxx.c >>> @@ -13,6 +13,7 @@ >>> #include <linux/slab.h> >>> #include <linux/module.h> >>> #include <linux/spinlock.h> >>> +#include <linux/gpio/consumer.h> >>> #include <linux/i2c.h> >>> #include <linux/interrupt.h> >>> #include <linux/mv643xx_i2c.h> >>> @@ -160,6 +161,7 @@ struct mv64xxx_i2c_data { >>> bool clk_n_base_0; >>> struct i2c_bus_recovery_info rinfo; >>> bool atomic; >>> + struct gpio_desc *reset_gpio; >>> }; >>> >>> static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { >>> @@ -1036,6 +1038,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) >>> struct mv64xxx_i2c_data *drv_data; >>> struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); >>> struct resource *res; >>> + u32 reset_duration; >>> int rc; >>> >>> if ((!pdata && !pd->dev.of_node)) >>> @@ -1083,6 +1086,14 @@ mv64xxx_i2c_probe(struct platform_device *pd) >>> if (drv_data->irq < 0) >>> return drv_data->irq; >>> >>> + drv_data->reset_gpio = devm_gpiod_get_optional(&pd->dev, "bus-reset", GPIOD_OUT_HIGH); >>> + if (IS_ERR(drv_data->reset_gpio)) >>> + return dev_err_probe(&pd->dev, PTR_ERR(drv_data->reset_gpio), >>> + "Cannot get reset gpio\n"); >>> + rc = device_property_read_u32(&pd->dev, "bus-reset-duration-us", &reset_duration); >>> + if (rc) >>> + reset_duration = 1; >> No, this should be solved by core - for entire I2C at minimum. This is >> not specific to this device.
On 28/10/23 01:55, Andi Shyti wrote: > Hi Krzysztof, > > On Fri, Oct 27, 2023 at 01:37:05PM +0200, Krzysztof Kozlowski wrote: >> On 27/10/2023 13:27, Krzysztof Kozlowski wrote: >>> On 27/10/2023 05:31, Chris Packham wrote: >>>> Some hardware designs have a GPIO used to control the reset of all the >>>> devices on and I2C bus. It's not possible for every child node to >>>> declare a reset-gpios property as only the first device probed would be >>>> able to successfully request it (the others will get -EBUSY). Represent >> Cc: Mark, >> >> Also this part is not true. If the bus is non-discoverable, then it is >> possible to have reset-gpios in each probed device. You can share GPIOs, >> so no problem with -EBUSY at all. >> >> The problem is doing reset: >> 1. in proper moment for all devices >> 2. without affecting other devices when one unbinds/remove() > yes, I thought that we could get to this point, but I did not > object the patch as I didn't see an immediate better solution. I > would still be OK to merge it until we develop something better. > > Let me mull this over and will be back to the topic. If we're happy with plain GPIOs I can move what I've done so far to somewhere in the I2C core. I know we've got other hardware designs with different controllers that also have muxes connected to a common reset GPIO so I would have ended up moving this code to I2C core eventually. If we're talking a proper reset driver implemented using GPIOs then that might be a bit of bigger task. > Thanks, Krzysztof! > Andi > >> The (2) above is not solveable easy in kernel and we already had nice >> talks about it just few days ago: >> 1. Apple case: >> https://scanmail.trustwave.com/?c=20988&d=1LO75R2nre1LP3TyEWMYg1Is4Mz-YROPQ8JxsJqwkg&u=https%3a%2f%2fsocial%2etreehouse%2esystems%2f%40marcan%2f111268780311634160 >> >> 2. my WSA884x: >> https://scanmail.trustwave.com/?c=20988&d=1LO75R2nre1LP3TyEWMYg1Is4Mz-YROPQ8IvtMfhyQ&u=https%3a%2f%2flore%2ekernel%2eorg%2falsa-devel%2f84f9f1c4-0627-4986-8160-b4ab99469b81%40linaro%2eorg%2f >> >> Last, >> I would like to apologize to you Chris. I understand that bringing such >> feedback at v5 is not that good. I had plenty of time to say something >> earlier, so this is not really professional from my side. I am sorry, >> just my brain did not connect all these topics together. >> >> I apologize. >> >> Best regards, >> Krzysztof
On 29/10/2023 21:48, Chris Packham wrote: > > On 28/10/23 00:37, Krzysztof Kozlowski wrote: >> On 27/10/2023 13:27, Krzysztof Kozlowski wrote: >>> On 27/10/2023 05:31, Chris Packham wrote: >>>> Some hardware designs have a GPIO used to control the reset of all the >>>> devices on and I2C bus. It's not possible for every child node to >>>> declare a reset-gpios property as only the first device probed would be >>>> able to successfully request it (the others will get -EBUSY). Represent >> Cc: Mark, >> >> Also this part is not true. If the bus is non-discoverable, then it is >> possible to have reset-gpios in each probed device. You can share GPIOs, >> so no problem with -EBUSY at all. > > Last time I checked you couldn't share GPIOs. If that's no longer the > case then I can probably make what I need to happen work. It still > creates an issue that I have multiple PCA954x muxes connected to a > common reset GPIO so as each mux is probed the PCA954x driver will > toggle the reset. That's probably OK as the PCA954x is sufficiently > stateless that the extra resets won't do any harm but if it were a more > complicated device then there would be issues. I know, but this is a broader problem, not really specific to this one device. I also argue that your I2C controller does not actually have this reset line. > > Having some kind of ref-counted reset controller that is implemented > with GPIOs is probably the better solution. I was kind of surprised that > nothing existed like that in drivers/reset. reset controller framework already supports this. The point is that GPIO reset is not a reset controller, so in terms of bindings "resets" property does not fit it. > >> The problem is doing reset: >> 1. in proper moment for all devices >> 2. without affecting other devices when one unbinds/remove() >> >> The (2) above is not solveable easy in kernel and we already had nice >> talks about it just few days ago: >> 1. Apple case: >> https://scanmail.trustwave.com/?c=20988&d=6qC75SLs-9PNM1ZHpLa6reGv82R6opEUmyI62vCytQ&u=https%3a%2f%2fsocial%2etreehouse%2esystems%2f%40marcan%2f111268780311634160 >> >> 2. my WSA884x: >> https://scanmail.trustwave.com/?c=20988&d=6qC75SLs-9PNM1ZHpLa6reGv82R6opEUmyJk3q3j7g&u=https%3a%2f%2flore%2ekernel%2eorg%2falsa-devel%2f84f9f1c4-0627-4986-8160-b4ab99469b81%40linaro%2eorg%2f > Apologies for the mangled links (they're more secure now at least that's > what our IS team have been sold). >> Last, >> I would like to apologize to you Chris. I understand that bringing such >> feedback at v5 is not that good. I had plenty of time to say something >> earlier, so this is not really professional from my side. I am sorry, >> just my brain did not connect all these topics together. >> >> I apologize. > > Actually I kind of expected this feedback. I figured I could start with > the driver that is currently causing me issues and once the dt-binding > was considered good enough it might migrate to the i2c core. > >> Best regards, Krzysztof
On 31/10/23 19:01, Krzysztof Kozlowski wrote: > On 29/10/2023 21:48, Chris Packham wrote: >> On 28/10/23 00:37, Krzysztof Kozlowski wrote: >>> On 27/10/2023 13:27, Krzysztof Kozlowski wrote: >>>> On 27/10/2023 05:31, Chris Packham wrote: >>>>> Some hardware designs have a GPIO used to control the reset of all the >>>>> devices on and I2C bus. It's not possible for every child node to >>>>> declare a reset-gpios property as only the first device probed would be >>>>> able to successfully request it (the others will get -EBUSY). Represent >>> Cc: Mark, >>> >>> Also this part is not true. If the bus is non-discoverable, then it is >>> possible to have reset-gpios in each probed device. You can share GPIOs, >>> so no problem with -EBUSY at all. >> Last time I checked you couldn't share GPIOs. If that's no longer the >> case then I can probably make what I need to happen work. It still >> creates an issue that I have multiple PCA954x muxes connected to a >> common reset GPIO so as each mux is probed the PCA954x driver will >> toggle the reset. That's probably OK as the PCA954x is sufficiently >> stateless that the extra resets won't do any harm but if it were a more >> complicated device then there would be issues. > I know, but this is a broader problem, not really specific to this one > device. I also argue that your I2C controller does not actually have > this reset line. Yes absolutely. Because the reset line is common to multiple pca954x muxes the only option I have (I think) is to associate the reset line with the controller. It happens to be true for my case that everything connected to that bus is affected by the reset line but I can completely see that there may be other designs where there are a mix of muxes and other devices on the root bus. So associating the reset line with the I2C controller is a pragmatic solution (or an egregious hack depending on your point of view) that works with this kind of hardware design. Another complete hack I've experimented with is adding the muxes defined with `status = "disabled";` in the dts and having a custom driver that requests the GPIO and manipulates the live device tree. It works but is quite a lot more code and will invariably break if I need to tweak the device tree. >> Having some kind of ref-counted reset controller that is implemented >> with GPIOs is probably the better solution. I was kind of surprised that >> nothing existed like that in drivers/reset. > reset controller framework already supports this. The point is that GPIO > reset is not a reset controller, so in terms of bindings "resets" > property does not fit it. So I need some way of representing a GPIO line associated with multiple devices that must be requested and driven appropriately before the devices are probed. In lieu of anything else a "bus-reset-gpios" property recognized by the generic I2C framework kind of sounds like the best solution so far. Unless maybe there's some kind of pinctrl type thing that would already work. >>> The problem is doing reset: >>> 1. in proper moment for all devices >>> 2. without affecting other devices when one unbinds/remove() >>> >>> The (2) above is not solveable easy in kernel and we already had nice >>> talks about it just few days ago: >>> 1. Apple case: >>> https://scanmail.trustwave.com/?c=20988&d=tZjA5R77ysliRyWfDvgX9JnmLZr-TqhRWpYjsNO-5A&u=https%3a%2f%2fsocial%2etreehouse%2esystems%2f%40marcan%2f111268780311634160 >>> >>> 2. my WSA884x: >>> https://scanmail.trustwave.com/?c=20988&d=tZjA5R77ysliRyWfDvgX9JnmLZr-TqhRWpZ9tI7vvw&u=https%3a%2f%2flore%2ekernel%2eorg%2falsa-devel%2f84f9f1c4-0627-4986-8160-b4ab99469b81%40linaro%2eorg%2f >> Apologies for the mangled links (they're more secure now at least that's >> what our IS team have been sold). >>> Last, >>> I would like to apologize to you Chris. I understand that bringing such >>> feedback at v5 is not that good. I had plenty of time to say something >>> earlier, so this is not really professional from my side. I am sorry, >>> just my brain did not connect all these topics together. >>> >>> I apologize. >> Actually I kind of expected this feedback. I figured I could start with >> the driver that is currently causing me issues and once the dt-binding >> was considered good enough it might migrate to the i2c core. >> > > Best regards, > Krzysztof >
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index efd28bbecf61..6e2762d22e5a 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -13,6 +13,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/spinlock.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/mv643xx_i2c.h> @@ -160,6 +161,7 @@ struct mv64xxx_i2c_data { bool clk_n_base_0; struct i2c_bus_recovery_info rinfo; bool atomic; + struct gpio_desc *reset_gpio; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -1036,6 +1038,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) struct mv64xxx_i2c_data *drv_data; struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); struct resource *res; + u32 reset_duration; int rc; if ((!pdata && !pd->dev.of_node)) @@ -1083,6 +1086,14 @@ mv64xxx_i2c_probe(struct platform_device *pd) if (drv_data->irq < 0) return drv_data->irq; + drv_data->reset_gpio = devm_gpiod_get_optional(&pd->dev, "bus-reset", GPIOD_OUT_HIGH); + if (IS_ERR(drv_data->reset_gpio)) + return dev_err_probe(&pd->dev, PTR_ERR(drv_data->reset_gpio), + "Cannot get reset gpio\n"); + rc = device_property_read_u32(&pd->dev, "bus-reset-duration-us", &reset_duration); + if (rc) + reset_duration = 1; + if (pdata) { drv_data->freq_m = pdata->freq_m; drv_data->freq_n = pdata->freq_n; @@ -1121,6 +1132,11 @@ mv64xxx_i2c_probe(struct platform_device *pd) goto exit_disable_pm; } + if (drv_data->reset_gpio) { + fsleep(reset_duration); + gpiod_set_value_cansleep(drv_data->reset_gpio, 0); + } + rc = request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, MV64XXX_I2C_CTLR_NAME, drv_data); if (rc) {