From: Chris Packham <chris.packham@alliedtelesis.co.nz>
To: wsa@kernel.org, andi.shyti@kernel.org, robh+dt@kernel.org,
krzysztof.kozlowski+dt@linaro.org, conor+dt@kernel.org,
gregory.clement@bootlin.com
Cc: linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Chris Packham <chris.packham@alliedtelesis.co.nz>
Subject: [PATCH v6 2/2] i2c: add an optional bus-reset-gpios property
Date: Wed, 15 Nov 2023 16:57:53 +1300 [thread overview]
Message-ID: <20231115035753.925534-3-chris.packham@alliedtelesis.co.nz> (raw)
In-Reply-To: <20231115035753.925534-1-chris.packham@alliedtelesis.co.nz>
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. 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 v6:
- Retarget changes at the i2c core instead of an individual driver
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/i2c-core-base.c | 39 +++++++++++++++++++++++++++++++++++++
include/linux/i2c.h | 3 +++
2 files changed, 42 insertions(+)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 60746652fd52..d7f53272487b 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1468,6 +1468,39 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
}
EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
+static int i2c_setup_bus_reset_gpio(struct i2c_adapter *adap)
+{
+ int res;
+
+ adap->reset_gpios = devm_gpiod_get_array_optional(&adap->dev, "bus-reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(adap->reset_gpios))
+ return dev_err_probe(&adap->dev, PTR_ERR(adap->reset_gpios),
+ "Cannot get reset gpio\n");
+ res = device_property_read_u32(&adap->dev, "bus-reset-duration-us", &adap->reset_duration);
+ if (res)
+ adap->reset_duration = 1;
+
+ return 0;
+}
+
+static void i2c_deassert_bus_reset_gpio(struct i2c_adapter *adap)
+{
+ unsigned long *values;
+
+ if (!adap->reset_gpios)
+ return;
+
+ values = bitmap_zalloc(adap->reset_gpios->ndescs, GFP_KERNEL);
+ if (!values)
+ return;
+
+ gpiod_set_array_value_cansleep(adap->reset_gpios->ndescs,
+ adap->reset_gpios->desc, adap->reset_gpios->info,
+ values);
+
+ bitmap_free(values);
+}
+
static int i2c_register_adapter(struct i2c_adapter *adap)
{
int res = -EINVAL;
@@ -1521,6 +1554,10 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (res)
goto out_reg;
+ res = i2c_setup_bus_reset_gpio(adap);
+ if (res)
+ goto out_reg;
+
device_enable_async_suspend(&adap->dev);
pm_runtime_no_callbacks(&adap->dev);
pm_suspend_ignore_children(&adap->dev, true);
@@ -1539,6 +1576,8 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
dev_warn(&adap->dev,
"Failed to create compatibility class link\n");
#endif
+ /* bring downstream devices out of reset */
+ i2c_deassert_bus_reset_gpio(adap);
/* create pre-declared device nodes */
of_i2c_register_devices(adap);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 0dae9db27538..1110a49dcdaf 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -746,6 +746,9 @@ struct i2c_adapter {
struct irq_domain *host_notify_domain;
struct regulator *bus_regulator;
+
+ struct gpio_descs *reset_gpios;
+ u32 reset_duration;
};
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
--
2.42.0
prev parent reply other threads:[~2023-11-15 3:58 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-15 3:57 [PATCH v6 0/2] i2c: bus-reset-gpios Chris Packham
2023-11-15 3:57 ` [PATCH v6 1/2] dt-bindings: i2c: add bus-reset-gpios property Chris Packham
2023-11-15 21:29 ` Krzysztof Kozlowski
2023-11-15 21:53 ` Chris Packham
2023-11-16 11:37 ` Krzysztof Kozlowski
2023-12-19 17:02 ` wsa
2023-12-19 19:28 ` Chris Packham
2023-12-19 20:50 ` wsa
2023-12-19 23:25 ` Andi Shyti
2023-12-20 7:22 ` Krzysztof Kozlowski
2023-12-20 11:03 ` wsa
2023-12-20 11:29 ` Krzysztof Kozlowski
2023-12-20 11:52 ` wsa
2023-12-21 0:40 ` Andi Shyti
2023-11-15 3:57 ` Chris Packham [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231115035753.925534-3-chris.packham@alliedtelesis.co.nz \
--to=chris.packham@alliedtelesis.co.nz \
--cc=andi.shyti@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregory.clement@bootlin.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.org \
--cc=wsa@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).