* Re: [RFC PATCH 1/1] reset: add support the GPIO provider with #gpio-cells=3
[not found] <CAKNLDZOndyGxLSWgBDrq0Vfbt88Pa5S2MDHVcnkHzAH3TQDpaQ@mail.gmail.com>
@ 2026-11-04 7:16 ` Krzysztof Kozlowski
0 siblings, 0 replies; 3+ messages in thread
From: Krzysztof Kozlowski @ 2026-11-04 7:16 UTC (permalink / raw)
To: Marc Taylor, bigunclemax
Cc: p.zabel, brgl, linusw, andre.przywara, martin.botka, dlan,
linux-kernel, linux-gpio, linux-sunxi, linux-riscv, spacemit
On 04/11/2026 04:56, Marc Taylor wrote:
> Sorry, my mail client mangled the inline diff in my previous reply
> (indentation stripped, and it turned "
Then please switch to standard email clients. See also kernel docs for
helping to setup normal apps properly handling email.
> https://www.google.com/url?q=http://spec.np&source=gmail&ust=1793850929317000&sa=E"
> into a link). The
> attached reset-gpio-3cell-v7.2.15.patch is the correct version; it is
> re-attached here so this message stands on its own.
I have no clue what are you referring to to, but I am not opening any
attachments. I doubt other maintainers will.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC PATCH 1/1] reset: add support the GPIO provider with #gpio-cells=3
@ 2026-11-04 3:48 Marc Taylor
0 siblings, 0 replies; 3+ messages in thread
From: Marc Taylor @ 2026-11-04 3:48 UTC (permalink / raw)
To: bigunclemax
Cc: p.zabel, brgl, krzk, linusw, andre.przywara, martin.botka, dlan,
linux-kernel, linux-gpio, linux-sunxi, linux-riscv, spacemit
[-- Attachment #1: Type: text/plain, Size: 4667 bytes --]
Hi Maksim,
(Re: <20260423230338.442497-2-bigunclemax@gmail.com>. I'm not
subscribed, so this may not thread; sorry. Adding linux-sunxi.)
I hit the same bug on an Allwinner H700 board (Anbernic RG35XX Plus,
sun50i-h700-anbernic-rg35xx-plus.dts: RTL8821CS SDIO Wi-Fi behind
mmc-pwrseq-simple with reset-gpios = <&pio 6 18 GPIO_ACTIVE_LOW>) on
v7.2.15, and the code is unchanged in v7.4-rc1. With CONFIG_RESET_GPIO
enabled (arm64 defconfig has it =m):
pwrseq_simple pwrseq: error -ENOENT: reset control not ready
pwrseq_simple pwrseq: probe with driver pwrseq_simple failed with error -2
mmc@4021000 never probes, so there is no wlan0. With RESET_GPIO
disabled, pwrseq_simple falls back to plain GPIOs and Wi-Fi works.
Two notes on the RFC:
1. It no longer applies after the reset-gpio rework that landed in
v7.1/v7.2 (fwnode_reference_args, __reset_add_reset_gpio_device()
taking a fwnode, fwnode_reset_n_cells).
2. I think the 3-cell software node reference resolves to the wrong
line. gpiolib-swnode reads the reference with nargs = 2 and uses
args[0] as the chip offset and args[1] as the flags. With
<bank pin flags> stored in the swnode, PG18 would come out as
offset 6 (PA6) with flags 18. If the CB1 works with it, I suspect
the real reset line is simply left deasserted. (Code reading only;
I didn't run the RFC itself, since it doesn't apply here.)
Attached (and below) is a port to v7.2.15 that asks the provider's
of_xlate() for the chip offset, so the swnode stays <offset flags>, and
skips the reset-cells check for the GPIO fallback (reset-gpio says its
cell count "is not really used"). On the RG35XX Plus with
CONFIG_RESET_GPIO=y:
sunxi-mmc 4021000.mmc: allocated mmc-pwrseq
mmc2: new high speed SDIO card at address 0001
rtw88_8821cs mmc2:0001:1: Firmware version 24.11.0, H2C version 12
/sys/bus/auxiliary/devices/reset.gpio.0 exists, debugfs shows gpio-210
(PG18 = 6 * 32 + 18) requested as "reset", out hi ACTIVE LOW, and Wi-Fi
associates and gets a DHCP lease.
This isn't a formal submission. I'm happy to test a v2 of yours, or to
turn this into a proper patch if that's preferred. Philipp's earlier
suggestion (pwrseq_simple falling back to devm_gpiod_get_array() on
-ENOENT) would also fix this board.
For the approach below, on Anbernic RG35XX Plus (H700):
Tested-by: Marc Taylor <marctaylor700@gmail.com>
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -1019,12 +1019,13 @@
int ret, prop = 0;
/*
- * Currently only #gpio-cells=2 is supported with the meaning of:
- * args[0]: GPIO number
- * args[1]: GPIO flags
- * TODO: Handle other cases.
+ * Supported specifiers:
+ * #gpio-cells = 2: <offset flags>
+ * #gpio-cells = 3: provider-specific (e.g. Allwinner <bank pin flags>),
+ * translated to a chip offset by the chip's of_xlate
+ * The flags are always the last cell.
*/
- if (args->nargs != 2)
+ if (args->nargs != 2 && args->nargs != 3)
return -ENOENT;
/*
@@ -1034,8 +1035,7 @@
*/
lockdep_assert_not_held(&reset_list_mutex);
- offset = args->args[0];
- flags = args->args[1];
+ flags = args->args[args->nargs - 1];
/*
* Later we map GPIO flags between OF and Linux, however not all
@@ -1046,8 +1046,7 @@
* flags.
*/
if (flags > GPIO_ACTIVE_LOW) {
- pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
- flags, offset);
+ pr_err("reset-gpio code does not support GPIO flags %u\n", flags);
return -EINVAL;
}
@@ -1055,6 +1054,33 @@
gpio_device_find_by_fwnode(args->fwnode);
if (!gdev)
return -EPROBE_DEFER;
+
+ if (args->nargs == 2) {
+ offset = args->args[0];
+ } else {
+ /*
+ * The software node built below is resolved by gpiolib-swnode,
+ * which only understands <offset flags>. Let the provider turn
+ * its own multi-cell specifier into a chip offset.
+ */
+ struct gpio_chip *gc = gpio_device_get_chip(gdev);
+ struct of_phandle_args spec = { };
+ u32 of_flags;
+ int i;
+
+ if (!gc || !gc->of_xlate || !is_of_node(args->fwnode))
+ return -ENOENT;
+
+ https://www.google.com/url?q=http://spec.np&source=gmail&ust=1793850302384000&sa=E
= to_of_node(args->fwnode);
+ spec.args_count = args->nargs;
+ for (i = 0; i < args->nargs; i++)
+ spec.args[i] = args->args[i];
+
+ ret = gc->of_xlate(gc, &spec, &of_flags);
+ if (ret < 0)
+ return ret;
+ offset = ret;
+ }
guard(mutex)(&reset_gpio_lookup_mutex);
@@ -1193,7 +1219,11 @@
goto out_put;
}
- if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
+ /*
+ * For the reset-gpio fallback args is the GPIO specifier, whose cell
+ * count is the GPIO provider's, not the reset controller's.
+ */
+ if (!gpio_fallback && WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
rstc = ERR_PTR(-EINVAL);
goto out_put;
}
Thanks,
Marc Taylor
[-- Attachment #2: reset-gpio-3cell-v7.2.15.patch --]
[-- Type: text/x-patch, Size: 2368 bytes --]
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -1019,12 +1019,13 @@
int ret, prop = 0;
/*
- * Currently only #gpio-cells=2 is supported with the meaning of:
- * args[0]: GPIO number
- * args[1]: GPIO flags
- * TODO: Handle other cases.
+ * Supported specifiers:
+ * #gpio-cells = 2: <offset flags>
+ * #gpio-cells = 3: provider-specific (e.g. Allwinner <bank pin flags>),
+ * translated to a chip offset by the chip's of_xlate
+ * The flags are always the last cell.
*/
- if (args->nargs != 2)
+ if (args->nargs != 2 && args->nargs != 3)
return -ENOENT;
/*
@@ -1034,8 +1035,7 @@
*/
lockdep_assert_not_held(&reset_list_mutex);
- offset = args->args[0];
- flags = args->args[1];
+ flags = args->args[args->nargs - 1];
/*
* Later we map GPIO flags between OF and Linux, however not all
@@ -1046,8 +1046,7 @@
* flags.
*/
if (flags > GPIO_ACTIVE_LOW) {
- pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
- flags, offset);
+ pr_err("reset-gpio code does not support GPIO flags %u\n", flags);
return -EINVAL;
}
@@ -1055,6 +1054,33 @@
gpio_device_find_by_fwnode(args->fwnode);
if (!gdev)
return -EPROBE_DEFER;
+
+ if (args->nargs == 2) {
+ offset = args->args[0];
+ } else {
+ /*
+ * The software node built below is resolved by gpiolib-swnode,
+ * which only understands <offset flags>. Let the provider turn
+ * its own multi-cell specifier into a chip offset.
+ */
+ struct gpio_chip *gc = gpio_device_get_chip(gdev);
+ struct of_phandle_args spec = { };
+ u32 of_flags;
+ int i;
+
+ if (!gc || !gc->of_xlate || !is_of_node(args->fwnode))
+ return -ENOENT;
+
+ spec.np = to_of_node(args->fwnode);
+ spec.args_count = args->nargs;
+ for (i = 0; i < args->nargs; i++)
+ spec.args[i] = args->args[i];
+
+ ret = gc->of_xlate(gc, &spec, &of_flags);
+ if (ret < 0)
+ return ret;
+ offset = ret;
+ }
guard(mutex)(&reset_gpio_lookup_mutex);
@@ -1193,7 +1219,11 @@
goto out_put;
}
- if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
+ /*
+ * For the reset-gpio fallback args is the GPIO specifier, whose cell
+ * count is the GPIO provider's, not the reset controller's.
+ */
+ if (!gpio_fallback && WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
rstc = ERR_PTR(-EINVAL);
goto out_put;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* [RFC PATCH 1/1] reset: add support the GPIO provider with #gpio-cells=3
2026-04-23 23:03 [RFC PATCH 0/1] reset: gpio: Add support for GPIO providers " bigunclemax
@ 2026-04-23 23:03 ` bigunclemax
0 siblings, 0 replies; 3+ messages in thread
From: bigunclemax @ 2026-04-23 23:03 UTC (permalink / raw)
To: linux-kernel
Cc: Martin Botka, Andre Przywara, Krzysztof Kozlowski,
Maksim Kiselev, Philipp Zabel, Yixun Lan, Linus Walleij,
Bartosz Golaszewski, linux-riscv, spacemit, linux-gpio
From: Maksim Kiselev <bigunclemax@gmail.com>
The __reset_add_reset_gpio_device() function currently expects a GPIO
provider with #gpio-cells=2, which prevents using the GPIO from
controllers with #gpio-cells=3, such as the Allwinner pinctrl and others.
Extend the parsing to support the GPIO phandle with three args,
where:
args[0]: GPIO bank
args[1]: GPIO number
args[2]: GPIO flags
Signed-off-by: Maksim Kiselev <bigunclemax@gmail.com>
---
drivers/reset/core.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 352c2360603b..18fb50ca645f 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -868,7 +868,8 @@ static int reset_add_gpio_aux_device(struct device *parent,
static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
{
struct property_entry properties[3] = { };
- unsigned int offset, of_flags, lflags;
+ unsigned int offset[2], of_flags, lflags;
+ struct software_node_ref_args sw_ref[1];
struct reset_gpio_lookup *rgpio_dev;
struct device *parent;
int id, ret, prop = 0;
@@ -879,7 +880,7 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
* args[1]: GPIO flags
* TODO: Handle other cases.
*/
- if (args->args_count != 2)
+ if (args->args_count != 2 && args->args_count != 3)
return -ENOENT;
/*
@@ -889,8 +890,13 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
*/
lockdep_assert_not_held(&reset_list_mutex);
- offset = args->args[0];
- of_flags = args->args[1];
+ offset[0] = args->args[0];
+ if (args->args_count == 2) {
+ of_flags = args->args[1];
+ } else {
+ offset[1] = args->args[1];
+ of_flags = args->args[2];
+ }
/*
* Later we map GPIO flags between OF and Linux, however not all
@@ -902,7 +908,7 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
*/
if (of_flags > GPIO_ACTIVE_LOW) {
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
- of_flags, offset);
+ of_flags, offset[0]);
return -EINVAL;
}
@@ -923,7 +929,13 @@ static int __reset_add_reset_gpio_device(const struct of_phandle_args *args)
lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
parent = gpio_device_to_device(gdev);
properties[prop++] = PROPERTY_ENTRY_STRING("compatible", "reset-gpio");
- properties[prop++] = PROPERTY_ENTRY_GPIO("reset-gpios", parent->fwnode, offset, lflags);
+
+ if (args->args_count == 2)
+ sw_ref[0] = SOFTWARE_NODE_REFERENCE(parent->fwnode, offset[0], lflags);
+ else
+ sw_ref[0] = SOFTWARE_NODE_REFERENCE(parent->fwnode, offset[0], offset[1],
+ lflags);
+ properties[prop++] = PROPERTY_ENTRY_REF_ARRAY("reset-gpios", sw_ref);
id = ida_alloc(&reset_gpio_ida, GFP_KERNEL);
if (id < 0)
@@ -1048,10 +1060,11 @@ __of_reset_control_get(struct device_node *node, const char *id, int index,
goto out_unlock;
}
- if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
- rstc = ERR_PTR(-EINVAL);
- goto out_unlock;
- }
+ if (!(rcdev->dev && fwnode_device_is_compatible(dev_fwnode(rcdev->dev), "reset-gpio")))
+ if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
+ rstc = ERR_PTR(-EINVAL);
+ goto out_unlock;
+ }
rstc_id = rcdev->of_xlate(rcdev, &args);
if (rstc_id < 0) {
--
2.51.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-04 7:16 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <CAKNLDZOndyGxLSWgBDrq0Vfbt88Pa5S2MDHVcnkHzAH3TQDpaQ@mail.gmail.com>
2026-11-04 7:16 ` [RFC PATCH 1/1] reset: add support the GPIO provider with #gpio-cells=3 Krzysztof Kozlowski
2026-11-04 3:48 Marc Taylor
-- strict thread matches above, loose matches on Subject: below --
2026-04-23 23:03 [RFC PATCH 0/1] reset: gpio: Add support for GPIO providers " bigunclemax
2026-04-23 23:03 ` [RFC PATCH 1/1] reset: add support the GPIO provider " bigunclemax
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®