* [PATCH v4 0/2] i2c: improve bus recovery for single-ended GPIOs
[not found] <afiNrr4Llm0LWw-5@ninjato>
@ 2026-05-09 9:12 ` Jie Li
2026-05-09 9:12 ` [PATCH v4 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
2026-05-09 9:12 ` [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
0 siblings, 2 replies; 13+ messages in thread
From: Jie Li @ 2026-05-09 9:12 UTC (permalink / raw)
To: wsa, linusw; +Cc: linux-i2c, linux-gpio, linux-kernel, Jie Li
Greetings,
This series addresses a limitation in the I2C bus recovery mechanism
where certain open-drain GPIOs are incorrectly identified as
input-only, preventing the recovery logic from functioning.
Following the suggestion from Linus Walleij, this version drops the
previously proposed "force-set-sda" DT property. Instead, it
introduces a generic helper in the GPIO subsystem to identify
single-ended configurations. This allows the I2C core to reliably
enable recovery for open-drain lines regardless of the
instantaneous hardware direction reporting.
As suggested by Wolfram, this series should go via the GPIO tree,
since patch 2/2 depends on the new gpiolib helper introduced in
patch 1/2.
Changes in v4:
- Patch 2:
- Use GPIO_LINE_DIRECTION_OUT instead of the literal '0' when
checking the return value of gpiod_get_direction(), and drop
the now-obsolete FIXME comment (suggested by Wolfram Sang).
- Added Acked-by: Wolfram Sang.
Changes in v3:
- Patch 1:
- Changed return type of gpiod_is_single_ended() from int to bool.
- Updated return values from 0/1 to false/true.
- Added Reviewed-by: Linus Walleij.
- Patch 2:
- Added Reviewed-by: Linus Walleij.
Changes in v2:
- Replaced DT-based "force-set-sda" with a gpiolib helper.
- Added gpiod_is_single_ended() to drivers/gpio/gpiolib.c.
- Updated i2c-core-base.c to use the new helper.
Jie Li (2):
gpiolib: add gpiod_is_single_ended() helper
i2c: core: support recovery for single-ended GPIOs
drivers/gpio/gpiolib.c | 22 ++++++++++++++++++++++
drivers/i2c/i2c-core-base.c | 4 ++--
include/linux/gpio/consumer.h | 5 +++++
3 files changed, 29 insertions(+), 2 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 1/2] gpiolib: add gpiod_is_single_ended() helper
2026-05-09 9:12 ` [PATCH v4 0/2] i2c: improve bus recovery for single-ended GPIOs Jie Li
@ 2026-05-09 9:12 ` Jie Li
2026-05-09 9:12 ` [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
1 sibling, 0 replies; 13+ messages in thread
From: Jie Li @ 2026-05-09 9:12 UTC (permalink / raw)
To: wsa, linusw; +Cc: linux-i2c, linux-gpio, linux-kernel, Jie Li
The direction of a single-ended (open-drain or open-source) GPIO line
cannot always be reliably determined by reading hardware registers.
In true open-drain implementations, the "high" state is achieved by
entering a high-impedance mode, which many hardware controllers report
as "input" even if the software intends to use it as an output.
This creates issues for consumer drivers (like I2C) that rely on
gpiod_get_direction() to decide if a line can be driven.
Introduce gpiod_is_single_ended() to allow consumers to check the
software configuration (GPIO_FLAG_OPEN_DRAIN/GPIO_FLAG_OPEN_SOURCE) of
a descriptor. This provides a robust way to identify lines that are
capable of being driven, regardless of their instantaneous hardware state.
Signed-off-by: Jie Li <jie.i.li@nokia.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
---
drivers/gpio/gpiolib.c | 22 ++++++++++++++++++++++
include/linux/gpio/consumer.h | 5 +++++
2 files changed, 27 insertions(+)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1e6dce430dca..69743d6deeaf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -491,6 +491,28 @@ int gpiod_get_direction(struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiod_get_direction);
+/**
+ * gpiod_is_single_ended - check if the GPIO is configured as single-ended
+ * @desc: the GPIO descriptor to check
+ *
+ * Returns true if the GPIO is configured as either Open Drain or Open Source.
+ * In these modes, the direction of the line cannot always be reliably
+ * determined by reading hardware registers, as the "off" state (High-Z)
+ * is physically indistinguishable from an input state.
+ */
+bool gpiod_is_single_ended(struct gpio_desc *desc)
+{
+ if (!desc)
+ return false;
+
+ if (test_bit(GPIOD_FLAG_OPEN_DRAIN, &desc->flags) ||
+ test_bit(GPIOD_FLAG_OPEN_SOURCE, &desc->flags))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(gpiod_is_single_ended);
+
/*
* Add a new chip to the global chips list, keeping the list of chips sorted
* by range(means [base, base + ngpio - 1]) order.
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 3efb5cb1e1d1..8fb27f9aa67f 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -111,6 +111,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc);
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
int gpiod_get_direction(struct gpio_desc *desc);
+bool gpiod_is_single_ended(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
int gpiod_direction_output(struct gpio_desc *desc, int value);
int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
@@ -337,6 +338,10 @@ static inline int gpiod_get_direction(const struct gpio_desc *desc)
WARN_ON(desc);
return -ENOSYS;
}
+static inline bool gpiod_is_single_ended(struct gpio_desc *desc)
+{
+ return false;
+}
static inline int gpiod_direction_input(struct gpio_desc *desc)
{
/* GPIO can never have been requested */
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-09 9:12 ` [PATCH v4 0/2] i2c: improve bus recovery for single-ended GPIOs Jie Li
2026-05-09 9:12 ` [PATCH v4 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
@ 2026-05-09 9:12 ` Jie Li
2026-05-09 10:10 ` Wolfram Sang
1 sibling, 1 reply; 13+ messages in thread
From: Jie Li @ 2026-05-09 9:12 UTC (permalink / raw)
To: wsa, linusw; +Cc: linux-i2c, linux-gpio, linux-kernel, Jie Li, Wolfram Sang
Currently, i2c_init_recovery() only assigns the set_sda/set_scl
hooks if gpiod_get_direction() returns GPIO_LINE_DIRECTION_OUT.
This logic fails on certain SoC controllers where open-drain lines
in a high-impedance state are physically reported as inputs. This
leads to a "deadlock" where the I2C core refuses to assign the
recovery hooks because it incorrectly assumes the pins are
input-only, even though they are fully capable of driving the bus
low for recovery.
Update the recovery initialization to use the new
gpiod_is_single_ended() helper. If a GPIO is configured as
open-drain or open-source in the firmware, it is safe to assume
it can be used for bus recovery, even if the current hardware
direction is reported as input.
Signed-off-by: Jie Li <jie.i.li@nokia.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
drivers/i2c/i2c-core-base.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 9c46147e3506..a3c33e804d47 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -445,8 +445,8 @@ static int i2c_init_recovery(struct i2c_adapter *adap)
bri->set_scl = set_scl_gpio_value;
if (bri->sda_gpiod) {
bri->get_sda = get_sda_gpio_value;
- /* FIXME: add proper flag instead of '0' once available */
- if (gpiod_get_direction(bri->sda_gpiod) == 0)
+ if (gpiod_get_direction(bri->sda_gpiod) == GPIO_LINE_DIRECTION_OUT ||
+ gpiod_is_single_ended(bri->sda_gpiod))
bri->set_sda = set_sda_gpio_value;
}
} else if (bri->recover_bus == i2c_generic_scl_recovery) {
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-09 9:12 ` [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
@ 2026-05-09 10:10 ` Wolfram Sang
2026-05-11 7:25 ` 李杰
0 siblings, 1 reply; 13+ messages in thread
From: Wolfram Sang @ 2026-05-09 10:10 UTC (permalink / raw)
To: Jie Li, Linus Walleij; +Cc: wsa, linux-i2c, linux-gpio, linux-kernel, Jie Li
[-- Attachment #1: Type: text/plain, Size: 1399 bytes --]
On Sat, May 09, 2026 at 11:12:08AM +0200, Jie Li wrote:
> Currently, i2c_init_recovery() only assigns the set_sda/set_scl
> hooks if gpiod_get_direction() returns GPIO_LINE_DIRECTION_OUT.
>
> This logic fails on certain SoC controllers where open-drain lines
> in a high-impedance state are physically reported as inputs. This
> leads to a "deadlock" where the I2C core refuses to assign the
> recovery hooks because it incorrectly assumes the pins are
> input-only, even though they are fully capable of driving the bus
> low for recovery.
>
> Update the recovery initialization to use the new
> gpiod_is_single_ended() helper. If a GPIO is configured as
> open-drain or open-source in the firmware, it is safe to assume
> it can be used for bus recovery, even if the current hardware
> direction is reported as input.
>
> Signed-off-by: Jie Li <jie.i.li@nokia.com>
> Reviewed-by: Linus Walleij <linusw@kernel.org>
> Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
I overlooked that the change with GPIO_LINE_DIRECTION_OUT I suggested
for this patch is at the same location as commit[1]. I already pushed
out said commit for -rc3 and it is, thus, already in -next, too. No big
harm, but there will be a little conflict when applying. Sorry, Linus!
[1] b47bc7c022dd ("i2c: Compare the return value of gpiod_get_direction against GPIO_LINE_DIRECTION_OUT")
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-09 10:10 ` Wolfram Sang
@ 2026-05-11 7:25 ` 李杰
2026-05-11 8:19 ` Linus Walleij
0 siblings, 1 reply; 13+ messages in thread
From: 李杰 @ 2026-05-11 7:25 UTC (permalink / raw)
To: Wolfram Sang
Cc: Linus Walleij, wsa, linux-i2c, linux-gpio, linux-kernel, Jie Li
Thanks for the heads-up, Wolfram.
No problem from my side. I can send a v5 rebased on top of
b47bc7c022dd if Linus prefers, or leave it to be resolved when
applying since the conflict should be trivial.
Thanks,
Jie Li
On Sat, May 9, 2026 at 12:10 PM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
>
> On Sat, May 09, 2026 at 11:12:08AM +0200, Jie Li wrote:
> > Currently, i2c_init_recovery() only assigns the set_sda/set_scl
> > hooks if gpiod_get_direction() returns GPIO_LINE_DIRECTION_OUT.
> >
> > This logic fails on certain SoC controllers where open-drain lines
> > in a high-impedance state are physically reported as inputs. This
> > leads to a "deadlock" where the I2C core refuses to assign the
> > recovery hooks because it incorrectly assumes the pins are
> > input-only, even though they are fully capable of driving the bus
> > low for recovery.
> >
> > Update the recovery initialization to use the new
> > gpiod_is_single_ended() helper. If a GPIO is configured as
> > open-drain or open-source in the firmware, it is safe to assume
> > it can be used for bus recovery, even if the current hardware
> > direction is reported as input.
> >
> > Signed-off-by: Jie Li <jie.i.li@nokia.com>
> > Reviewed-by: Linus Walleij <linusw@kernel.org>
> > Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
>
> I overlooked that the change with GPIO_LINE_DIRECTION_OUT I suggested
> for this patch is at the same location as commit[1]. I already pushed
> out said commit for -rc3 and it is, thus, already in -next, too. No big
> harm, but there will be a little conflict when applying. Sorry, Linus!
>
> [1] b47bc7c022dd ("i2c: Compare the return value of gpiod_get_direction against GPIO_LINE_DIRECTION_OUT")
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-11 7:25 ` 李杰
@ 2026-05-11 8:19 ` Linus Walleij
2026-05-11 10:28 ` Bartosz Golaszewski
0 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2026-05-11 8:19 UTC (permalink / raw)
To: 李杰, Bartosz Golaszewski
Cc: Wolfram Sang, wsa, linux-i2c, linux-gpio, linux-kernel, Jie Li
On Mon, May 11, 2026 at 9:25 AM 李杰 <lj29312931@gmail.com> wrote:
> Thanks for the heads-up, Wolfram.
>
> No problem from my side. I can send a v5 rebased on top of
> b47bc7c022dd if Linus prefers, or leave it to be resolved when
> applying since the conflict should be trivial.
Send a v3 based on v7.1-rc1 I'd say.
Bartosz can merge patch 1/2 and offer as an immutable
branch to Wolfram to merge and then Wolfram can queue
2/2 on top of that. This is usually the most bullet proof
merging strategy.
Make sure to put Bartosz on To: with clear intent per
above and he'll probably deal with it.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-11 8:19 ` Linus Walleij
@ 2026-05-11 10:28 ` Bartosz Golaszewski
2026-05-11 10:33 ` Wolfram Sang
0 siblings, 1 reply; 13+ messages in thread
From: Bartosz Golaszewski @ 2026-05-11 10:28 UTC (permalink / raw)
To: Linus Walleij
Cc: 李杰, Wolfram Sang, wsa, linux-i2c, linux-gpio,
linux-kernel, Jie Li
On Mon, May 11, 2026 at 10:19 AM Linus Walleij <linusw@kernel.org> wrote:
>
> On Mon, May 11, 2026 at 9:25 AM 李杰 <lj29312931@gmail.com> wrote:
>
> > Thanks for the heads-up, Wolfram.
> >
> > No problem from my side. I can send a v5 rebased on top of
> > b47bc7c022dd if Linus prefers, or leave it to be resolved when
> > applying since the conflict should be trivial.
>
> Send a v3 based on v7.1-rc1 I'd say.
>
> Bartosz can merge patch 1/2 and offer as an immutable
> branch to Wolfram to merge and then Wolfram can queue
> 2/2 on top of that. This is usually the most bullet proof
> merging strategy.
>
> Make sure to put Bartosz on To: with clear intent per
> above and he'll probably deal with it.
>
Am I missing something? Why does this need to go through the GPIO tree
if it doesn't seem to touch any GPIO file?
Bartosz
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-11 10:28 ` Bartosz Golaszewski
@ 2026-05-11 10:33 ` Wolfram Sang
2026-05-11 10:48 ` Bartosz Golaszewski
0 siblings, 1 reply; 13+ messages in thread
From: Wolfram Sang @ 2026-05-11 10:33 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Linus Walleij, 李杰, wsa, linux-i2c, linux-gpio,
linux-kernel, Jie Li
[-- Attachment #1: Type: text/plain, Size: 229 bytes --]
> Am I missing something? Why does this need to go through the GPIO tree
> if it doesn't seem to touch any GPIO file?
The new function this patch uses is only introduced in patch 1/2 (at
least it is not in -next as of today).
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-11 10:33 ` Wolfram Sang
@ 2026-05-11 10:48 ` Bartosz Golaszewski
2026-05-11 11:37 ` [PATCH v5 0/2] i2c: improve bus " Jie Li
0 siblings, 1 reply; 13+ messages in thread
From: Bartosz Golaszewski @ 2026-05-11 10:48 UTC (permalink / raw)
To: Wolfram Sang
Cc: Linus Walleij, 李杰, wsa, linux-i2c, linux-gpio,
linux-kernel, Jie Li
On Mon, May 11, 2026 at 12:33 PM Wolfram Sang
<wsa+renesas@sang-engineering.com> wrote:
>
>
> > Am I missing something? Why does this need to go through the GPIO tree
> > if it doesn't seem to touch any GPIO file?
>
> The new function this patch uses is only introduced in patch 1/2 (at
> least it is not in -next as of today).
>
You mean this one:
https://lore.kernel.org/all/20260509091208.18346-2-jie.i.li@nokia.com/
? Why do I have to look for it on lore?
It would have helped if I had been Cc'ed on this from the start, it's
the first time I'm seeing this. :/
Please combine the two series in a way that makes sense and resend it
with my address in Cc as per the MAINTAINERS file.
Thanks,
Bartosz
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 0/2] i2c: improve bus recovery for single-ended GPIOs
2026-05-11 10:48 ` Bartosz Golaszewski
@ 2026-05-11 11:37 ` Jie Li
2026-05-11 11:37 ` [PATCH v5 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Jie Li @ 2026-05-11 11:37 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij
Cc: Wolfram Sang, Wolfram Sang, linux-gpio, linux-i2c, linux-kernel,
Jie Li
Hi Bartosz, Wolfram,
This is a respin of the series rebased on v7.1-rc1, as requested by
Linus Walleij. No code changes versus v4; only the base has moved.
The series addresses a limitation in the I2C bus recovery mechanism
where certain open-drain GPIOs are incorrectly identified as
input-only, preventing the recovery logic from functioning.
Following the earlier suggestion from Linus Walleij, the previously
proposed "force-set-sda" DT property has been dropped in favor of a
generic helper in the GPIO subsystem to identify single-ended
configurations. This allows the I2C core to reliably enable recovery
for open-drain lines regardless of the instantaneous hardware
direction reporting.
Merging strategy (suggested by Linus Walleij)
=============================================
Patch 2/2 depends on the new gpiolib helper gpiod_is_single_ended()
introduced in patch 1/2. To keep this bisectable and avoid build
breakage, the recommended flow is:
1. Bartosz applies patch 1/2 to the GPIO tree and exposes it as an
immutable branch.
2. Wolfram pulls that immutable branch into the I2C tree and queues
patch 2/2 on top.
Bartosz: per Linus's note, please could you pick up patch 1/2 and
offer an immutable branch to Wolfram? Patch 2/2 does not touch any
GPIO file, but it is the sole user of the new helper, so it cannot
land via the I2C tree until 1/2 is available there.
Changes in v5:
- Rebased onto v7.1-rc1 (no code changes vs v4).
Changes in v4:
- Patch 2:
- Use GPIO_LINE_DIRECTION_OUT instead of the literal '0' when
checking the return value of gpiod_get_direction(), and drop
the now-obsolete FIXME comment (suggested by Wolfram Sang).
- Added Acked-by: Wolfram Sang.
Changes in v3:
- Patch 1:
- Changed return type of gpiod_is_single_ended() from int to bool.
- Updated return values from 0/1 to false/true.
- Added Reviewed-by: Linus Walleij.
- Patch 2:
- Added Reviewed-by: Linus Walleij.
Changes in v2:
- Replaced DT-based "force-set-sda" with a gpiolib helper.
- Added gpiod_is_single_ended() to drivers/gpio/gpiolib.c.
- Updated i2c-core-base.c to use the new helper.
Jie Li (2):
gpiolib: add gpiod_is_single_ended() helper
i2c: core: support recovery for single-ended GPIOs
drivers/gpio/gpiolib.c | 22 ++++++++++++++++++++++
drivers/i2c/i2c-core-base.c | 4 ++--
include/linux/gpio/consumer.h | 5 +++++
3 files changed, 29 insertions(+), 2 deletions(-)
base-commit: 254f49634ee16a731174d2ae34bc50bd5f45e731
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 1/2] gpiolib: add gpiod_is_single_ended() helper
2026-05-11 11:37 ` [PATCH v5 0/2] i2c: improve bus " Jie Li
@ 2026-05-11 11:37 ` Jie Li
2026-05-11 11:37 ` [PATCH v5 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
2026-05-11 12:27 ` (subset) [PATCH v5 0/2] i2c: improve bus " Bartosz Golaszewski
2 siblings, 0 replies; 13+ messages in thread
From: Jie Li @ 2026-05-11 11:37 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij
Cc: Wolfram Sang, Wolfram Sang, linux-gpio, linux-i2c, linux-kernel,
Jie Li
The direction of a single-ended (open-drain or open-source) GPIO line
cannot always be reliably determined by reading hardware registers.
In true open-drain implementations, the "high" state is achieved by
entering a high-impedance mode, which many hardware controllers report
as "input" even if the software intends to use it as an output.
This creates issues for consumer drivers (like I2C) that rely on
gpiod_get_direction() to decide if a line can be driven.
Introduce gpiod_is_single_ended() to allow consumers to check the
software configuration (GPIO_FLAG_OPEN_DRAIN/GPIO_FLAG_OPEN_SOURCE) of
a descriptor. This provides a robust way to identify lines that are
capable of being driven, regardless of their instantaneous hardware state.
Signed-off-by: Jie Li <jie.i.li@nokia.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
---
drivers/gpio/gpiolib.c | 22 ++++++++++++++++++++++
include/linux/gpio/consumer.h | 5 +++++
2 files changed, 27 insertions(+)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 1e6dce430dca..69743d6deeaf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -491,6 +491,28 @@ int gpiod_get_direction(struct gpio_desc *desc)
}
EXPORT_SYMBOL_GPL(gpiod_get_direction);
+/**
+ * gpiod_is_single_ended - check if the GPIO is configured as single-ended
+ * @desc: the GPIO descriptor to check
+ *
+ * Returns true if the GPIO is configured as either Open Drain or Open Source.
+ * In these modes, the direction of the line cannot always be reliably
+ * determined by reading hardware registers, as the "off" state (High-Z)
+ * is physically indistinguishable from an input state.
+ */
+bool gpiod_is_single_ended(struct gpio_desc *desc)
+{
+ if (!desc)
+ return false;
+
+ if (test_bit(GPIOD_FLAG_OPEN_DRAIN, &desc->flags) ||
+ test_bit(GPIOD_FLAG_OPEN_SOURCE, &desc->flags))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(gpiod_is_single_ended);
+
/*
* Add a new chip to the global chips list, keeping the list of chips sorted
* by range(means [base, base + ngpio - 1]) order.
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 3efb5cb1e1d1..8fb27f9aa67f 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -111,6 +111,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc);
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
int gpiod_get_direction(struct gpio_desc *desc);
+bool gpiod_is_single_ended(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
int gpiod_direction_output(struct gpio_desc *desc, int value);
int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
@@ -337,6 +338,10 @@ static inline int gpiod_get_direction(const struct gpio_desc *desc)
WARN_ON(desc);
return -ENOSYS;
}
+static inline bool gpiod_is_single_ended(struct gpio_desc *desc)
+{
+ return false;
+}
static inline int gpiod_direction_input(struct gpio_desc *desc)
{
/* GPIO can never have been requested */
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 2/2] i2c: core: support recovery for single-ended GPIOs
2026-05-11 11:37 ` [PATCH v5 0/2] i2c: improve bus " Jie Li
2026-05-11 11:37 ` [PATCH v5 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
@ 2026-05-11 11:37 ` Jie Li
2026-05-11 12:27 ` (subset) [PATCH v5 0/2] i2c: improve bus " Bartosz Golaszewski
2 siblings, 0 replies; 13+ messages in thread
From: Jie Li @ 2026-05-11 11:37 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij
Cc: Wolfram Sang, Wolfram Sang, linux-gpio, linux-i2c, linux-kernel,
Jie Li
Currently, i2c_init_recovery() only assigns the set_sda/set_scl
hooks if gpiod_get_direction() returns GPIO_LINE_DIRECTION_OUT.
This logic fails on certain SoC controllers where open-drain lines
in a high-impedance state are physically reported as inputs. This
leads to a "deadlock" where the I2C core refuses to assign the
recovery hooks because it incorrectly assumes the pins are
input-only, even though they are fully capable of driving the bus
low for recovery.
Update the recovery initialization to use the new
gpiod_is_single_ended() helper. If a GPIO is configured as
open-drain or open-source in the firmware, it is safe to assume
it can be used for bus recovery, even if the current hardware
direction is reported as input.
Signed-off-by: Jie Li <jie.i.li@nokia.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
drivers/i2c/i2c-core-base.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 9c46147e3506..a3c33e804d47 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -445,8 +445,8 @@ static int i2c_init_recovery(struct i2c_adapter *adap)
bri->set_scl = set_scl_gpio_value;
if (bri->sda_gpiod) {
bri->get_sda = get_sda_gpio_value;
- /* FIXME: add proper flag instead of '0' once available */
- if (gpiod_get_direction(bri->sda_gpiod) == 0)
+ if (gpiod_get_direction(bri->sda_gpiod) == GPIO_LINE_DIRECTION_OUT ||
+ gpiod_is_single_ended(bri->sda_gpiod))
bri->set_sda = set_sda_gpio_value;
}
} else if (bri->recover_bus == i2c_generic_scl_recovery) {
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: (subset) [PATCH v5 0/2] i2c: improve bus recovery for single-ended GPIOs
2026-05-11 11:37 ` [PATCH v5 0/2] i2c: improve bus " Jie Li
2026-05-11 11:37 ` [PATCH v5 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
2026-05-11 11:37 ` [PATCH v5 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
@ 2026-05-11 12:27 ` Bartosz Golaszewski
2 siblings, 0 replies; 13+ messages in thread
From: Bartosz Golaszewski @ 2026-05-11 12:27 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij, Jie Li
Cc: Bartosz Golaszewski, Wolfram Sang, Wolfram Sang, linux-gpio,
linux-i2c, linux-kernel, Jie Li
On Mon, 11 May 2026 13:37:24 +0200, Jie Li wrote:
> This is a respin of the series rebased on v7.1-rc1, as requested by
> Linus Walleij. No code changes versus v4; only the base has moved.
>
> The series addresses a limitation in the I2C bus recovery mechanism
> where certain open-drain GPIOs are incorrectly identified as
> input-only, preventing the recovery logic from functioning.
>
> [...]
Applied, thanks!
[1/2] gpiolib: add gpiod_is_single_ended() helper
https://git.kernel.org/brgl/c/b5fafa01bdaade5253bd39317f5455d13e6efc7d
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-11 12:27 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <afiNrr4Llm0LWw-5@ninjato>
2026-05-09 9:12 ` [PATCH v4 0/2] i2c: improve bus recovery for single-ended GPIOs Jie Li
2026-05-09 9:12 ` [PATCH v4 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
2026-05-09 9:12 ` [PATCH v4 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
2026-05-09 10:10 ` Wolfram Sang
2026-05-11 7:25 ` 李杰
2026-05-11 8:19 ` Linus Walleij
2026-05-11 10:28 ` Bartosz Golaszewski
2026-05-11 10:33 ` Wolfram Sang
2026-05-11 10:48 ` Bartosz Golaszewski
2026-05-11 11:37 ` [PATCH v5 0/2] i2c: improve bus " Jie Li
2026-05-11 11:37 ` [PATCH v5 1/2] gpiolib: add gpiod_is_single_ended() helper Jie Li
2026-05-11 11:37 ` [PATCH v5 2/2] i2c: core: support recovery for single-ended GPIOs Jie Li
2026-05-11 12:27 ` (subset) [PATCH v5 0/2] i2c: improve bus " Bartosz Golaszewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox