With everything else now in place, we can convert the remaining parts of
the reset subsystem to becoming fwnode-agnostic - meaning it will work
with all kinds of firmware nodes, not only devicetree.
To that end: extend struct reset_controller_dev with fields taking
information relevant for using firmware nodes (which mirrors what we
already do for OF-nodes) and limit using of_ APIs only to where it's
absolutely necessary (mostly around the of_xlate callback).
For backward compatibility of existing drivers we still support OF-nodes
but firmware nodes become the preferred method.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/reset/core.c | 166 +++++++++++++++++++++++----------------
include/linux/reset-controller.h | 14 +++-
2 files changed, 112 insertions(+), 68 deletions(-)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 0817afe72de75f795d62e02451520726da7c9844..e33a9bc9f94fc6867be6efd32178658d99fc088f 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -81,13 +81,13 @@ struct reset_control_array {
/**
* struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
- * @of_args: phandle to the reset controller with all the args like GPIO number
+ * @ref_args: Reference to the reset controller with all the args like GPIO number
* @swnode: Software node containing the reference to the GPIO provider
* @list: list entry for the reset_gpio_lookup_list
* @adev: Auxiliary device representing the reset controller
*/
struct reset_gpio_lookup {
- struct of_phandle_args of_args;
+ struct fwnode_reference_args ref_args;
struct fwnode_handle *swnode;
struct list_head list;
struct auxiliary_device adev;
@@ -98,24 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
if (rcdev->dev)
return dev_name(rcdev->dev);
- if (rcdev->of_node)
- return rcdev->of_node->full_name;
+ if (rcdev->fwnode)
+ return fwnode_get_name(rcdev->fwnode);
return NULL;
}
/**
- * of_reset_simple_xlate - translate reset_spec to the reset line number
+ * fwnode_reset_simple_xlate - translate reset_spec to the reset line number
* @rcdev: a pointer to the reset controller device
- * @reset_spec: reset line specifier as found in the device tree
+ * @reset_spec: reset line specifier as found in firmware
*
- * This static translation function is used by default if of_xlate in
- * :c:type:`reset_controller_dev` is not set. It is useful for all reset
- * controllers with 1:1 mapping, where reset lines can be indexed by number
- * without gaps.
+ * This static translation function is used by default if neither fwnode_xlate
+ * not of_xlate in :c:type:`reset_controller_dev` is not set. It is useful for
+ * all reset controllers with 1:1 mapping, where reset lines can be indexed by
+ * number without gaps.
*/
-static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
- const struct of_phandle_args *reset_spec)
+static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev,
+ const struct fwnode_reference_args *reset_spec)
{
if (reset_spec->args[0] >= rcdev->nr_resets)
return -EINVAL;
@@ -129,9 +129,23 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
*/
int reset_controller_register(struct reset_controller_dev *rcdev)
{
- if (!rcdev->of_xlate) {
- rcdev->of_reset_n_cells = 1;
- rcdev->of_xlate = of_reset_simple_xlate;
+ if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate))
+ return -EINVAL;
+
+ if (!rcdev->of_node && !rcdev->fwnode) {
+ rcdev->fwnode = dev_fwnode(rcdev->dev);
+ if (!rcdev->fwnode)
+ return -EINVAL;
+ }
+
+ if (rcdev->of_node) {
+ rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
+ rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
+ }
+
+ if (rcdev->fwnode && !rcdev->fwnode_xlate) {
+ rcdev->fwnode_reset_n_cells = 1;
+ rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
}
INIT_LIST_HEAD(&rcdev->reset_control_head);
@@ -931,7 +945,7 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
adev->id = id;
adev->name = "gpio";
adev->dev.parent = parent;
- adev->dev.platform_data = &rgpio_dev->of_args;
+ adev->dev.platform_data = &rgpio_dev->ref_args;
adev->dev.release = reset_gpio_aux_device_release;
device_set_node(&adev->dev, rgpio_dev->swnode);
@@ -951,18 +965,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
return 0;
}
-static void reset_gpio_add_devlink(struct device_node *np,
+static void reset_gpio_add_devlink(struct fwnode_handle *fwnode,
struct reset_gpio_lookup *rgpio_dev)
{
struct device *consumer;
/*
- * We must use get_dev_from_fwnode() and not of_find_device_by_node()
+ * We must use get_dev_from_fwnode() and not ref_find_device_by_node()
* because the latter only considers the platform bus while we want to
* get consumers of any kind that can be associated with firmware
* nodes: auxiliary, soundwire, etc.
*/
- consumer = get_dev_from_fwnode(of_fwnode_handle(np));
+ consumer = get_dev_from_fwnode(fwnode);
if (consumer) {
if (!device_link_add(consumer, &rgpio_dev->adev.dev,
DL_FLAG_AUTOREMOVE_CONSUMER))
@@ -982,15 +996,23 @@ static void reset_gpio_add_devlink(struct device_node *np,
*/
}
+/* TODO: move it out into drivers/base/ */
+static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left,
+ const struct fwnode_reference_args *right)
+{
+ return left->fwnode == right->fwnode && left->nargs == right->nargs &&
+ !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs);
+}
+
/*
* @np: OF-node associated with the consumer
- * @args: phandle to the GPIO provider with all the args like GPIO number
+ * @args: Reference to the GPIO provider with all the args like GPIO number
*/
-static int __reset_add_reset_gpio_device(struct device_node *np,
- const struct of_phandle_args *args)
+static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode,
+ const struct fwnode_reference_args *args)
{
struct property_entry properties[3] = { };
- unsigned int offset, of_flags, lflags;
+ unsigned int offset, flags, lflags;
struct reset_gpio_lookup *rgpio_dev;
struct device *parent;
int ret, prop = 0;
@@ -1001,7 +1023,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
* args[1]: GPIO flags
* TODO: Handle other cases.
*/
- if (args->args_count != 2)
+ if (args->nargs != 2)
return -ENOENT;
/*
@@ -1012,7 +1034,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
lockdep_assert_not_held(&reset_list_mutex);
offset = args->args[0];
- of_flags = args->args[1];
+ flags = args->args[1];
/*
* Later we map GPIO flags between OF and Linux, however not all
@@ -1022,33 +1044,31 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
* FIXME: Find a better way of translating OF flags to GPIO lookup
* flags.
*/
- if (of_flags > GPIO_ACTIVE_LOW) {
+ if (flags > GPIO_ACTIVE_LOW) {
pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
- of_flags, offset);
+ flags, offset);
return -EINVAL;
}
struct gpio_device *gdev __free(gpio_device_put) =
- gpio_device_find_by_fwnode(of_fwnode_handle(args->np));
+ gpio_device_find_by_fwnode(args->fwnode);
if (!gdev)
return -EPROBE_DEFER;
guard(mutex)(&reset_gpio_lookup_mutex);
list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
- if (args->np == rgpio_dev->of_args.np) {
- if (of_phandle_args_equal(args, &rgpio_dev->of_args)) {
- /*
- * Already on the list, create the device link
- * and stop here.
- */
- reset_gpio_add_devlink(np, rgpio_dev);
- return 0;
- }
+ if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) {
+ /*
+ * Already on the list, create the device link
+ * and stop here.
+ */
+ reset_gpio_add_devlink(fwnode, rgpio_dev);
+ return 0;
}
}
- lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
+ lflags = GPIO_PERSISTENT | (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);
@@ -1058,43 +1078,43 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
if (!rgpio_dev)
return -ENOMEM;
- rgpio_dev->of_args = *args;
+ rgpio_dev->ref_args = *args;
/*
- * We keep the device_node reference, but of_args.np is put at the end
- * of __fwnode_reset_control_get(), so get it one more time.
+ * We keep the fwnode_handle reference, but ref_args.fwnode is put at
+ * the end of __fwnode_reset_control_get(), so get it one more time.
* Hold reference as long as rgpio_dev memory is valid.
*/
- of_node_get(rgpio_dev->of_args.np);
+ fwnode_handle_get(rgpio_dev->ref_args.fwnode);
rgpio_dev->swnode = fwnode_create_software_node(properties, NULL);
if (IS_ERR(rgpio_dev->swnode)) {
ret = PTR_ERR(rgpio_dev->swnode);
- goto err_put_of_node;
+ goto err_put_fwnode;
}
ret = reset_create_gpio_aux_device(rgpio_dev, parent);
if (ret)
goto err_del_swnode;
- reset_gpio_add_devlink(np, rgpio_dev);
+ reset_gpio_add_devlink(fwnode, rgpio_dev);
list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
return 0;
err_del_swnode:
fwnode_remove_software_node(rgpio_dev->swnode);
-err_put_of_node:
- of_node_put(rgpio_dev->of_args.np);
+err_put_fwnode:
+ fwnode_handle_put(rgpio_dev->ref_args.fwnode);
kfree(rgpio_dev);
return ret;
}
-static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
- bool gpio_fallback)
+static struct reset_controller_dev *
+__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback)
{
+ struct fwnode_reference_args *rc_args;
struct reset_controller_dev *rcdev;
- struct of_phandle_args *rc_args;
lockdep_assert_held(&reset_list_mutex);
@@ -1103,10 +1123,10 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a
device_is_compatible(rcdev->dev, "reset-gpio")) {
rc_args = dev_get_platdata(rcdev->dev);
- if (of_phandle_args_equal(args, rc_args))
+ if (fwnode_reference_args_equal(args, rc_args))
return rcdev;
} else {
- if (args->np == rcdev->of_node)
+ if (args->fwnode == rcdev->fwnode)
return rcdev;
}
}
@@ -1120,27 +1140,26 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
{
bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
bool gpio_fallback = false;
- struct device_node *node = to_of_node(fwnode);
struct reset_control *rstc = ERR_PTR(-EINVAL);
struct reset_controller_dev *rcdev;
- struct of_phandle_args args;
- int rstc_id;
+ struct fwnode_reference_args args;
+ struct of_phandle_args of_args;
+ int rstc_id = -EINVAL;
int ret;
if (!fwnode)
return ERR_PTR(-EINVAL);
if (id) {
- index = of_property_match_string(node,
- "reset-names", id);
+ index = fwnode_property_match_string(fwnode, "reset-names", id);
if (index == -EILSEQ)
return ERR_PTR(index);
if (index < 0)
return optional ? NULL : ERR_PTR(-ENOENT);
}
- ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
- index, &args);
+ ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells",
+ 0, index, &args);
if (ret == -EINVAL)
return ERR_PTR(ret);
if (ret) {
@@ -1151,16 +1170,16 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
* There can be only one reset-gpio for regular devices, so
* don't bother with the "reset-gpios" phandle index.
*/
- ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
- 0, &args);
+ ret = fwnode_property_get_reference_args(fwnode, "reset-gpios",
+ "#gpio-cells", 0, 0, &args);
if (ret)
return optional ? NULL : ERR_PTR(ret);
gpio_fallback = true;
- ret = __reset_add_reset_gpio_device(node, &args);
+ ret = __reset_add_reset_gpio_device(fwnode, &args);
if (ret) {
- of_node_put(args.np);
+ fwnode_handle_put(args.fwnode);
return ERR_PTR(ret);
}
}
@@ -1173,15 +1192,30 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
goto out_put;
}
- if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
+ if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
rstc = ERR_PTR(-EINVAL);
goto out_put;
}
- rstc_id = rcdev->of_xlate(rcdev, &args);
+ if (rcdev->of_xlate && is_of_node(fwnode)) {
+ ret = of_parse_phandle_with_args(to_of_node(fwnode),
+ gpio_fallback ? "reset-gpios" : "resets",
+ gpio_fallback ? "#gpio-cells" : "#reset-cells",
+ gpio_fallback ? 0 : index,
+ &of_args);
+ if (ret) {
+ rstc = ERR_PTR(ret);
+ goto out_put;
+ }
+
+ rstc_id = rcdev->of_xlate(rcdev, &of_args);
+ of_node_put(of_args.np);
+ } else if (rcdev->fwnode_xlate) {
+ rstc_id = rcdev->fwnode_xlate(rcdev, &args);
+ }
if (rstc_id < 0) {
rstc = ERR_PTR(rstc_id);
- goto out_put;
+ goto out_put;
}
flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
@@ -1190,7 +1224,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
out_put:
- of_node_put(args.np);
+ fwnode_handle_put(args.fwnode);
return rstc;
}
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
index 185d2a9bd7cd381ddc51c0f1643c4e3cb196015e..52a5a4e81f1844075210339bf7ffa46ec5ca6edf 100644
--- a/include/linux/reset-controller.h
+++ b/include/linux/reset-controller.h
@@ -5,6 +5,8 @@
#include <linux/list.h>
#include <linux/mutex.h>
+struct fwnode_handle;
+struct fwnode_reference_args;
struct reset_controller_dev;
/**
@@ -38,8 +40,12 @@ struct of_phandle_args;
* @of_node: corresponding device tree node as phandle target
* @of_reset_n_cells: number of cells in reset line specifiers
* @of_xlate: translation function to translate from specifier as found in the
- * device tree to id as given to the reset control ops, defaults
- * to :c:func:`of_reset_simple_xlate`.
+ * device tree to id as given to the reset control ops
+ * @fwnode: firmware node associated with this device
+ * @fwnode_reset_n_cells: number of cells in reset line specifiers
+ * @fwnode_xlate: translation function to translate from firmware specifier to
+ * id as given to the reset control ops, defaults to
+ * :c:func:`fwnode_reset_simple_xlate`
* @nr_resets: number of reset controls in this reset controller device
* @lock: protects the reset control list from concurrent access
*/
@@ -53,6 +59,10 @@ struct reset_controller_dev {
int of_reset_n_cells;
int (*of_xlate)(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec);
+ struct fwnode_handle *fwnode;
+ int fwnode_reset_n_cells;
+ int (*fwnode_xlate)(struct reset_controller_dev *rcdev,
+ const struct fwnode_reference_args *reset_spec);
unsigned int nr_resets;
struct mutex lock;
};
--
2.47.3
Hi Bartosz,
Thanks for your patch.
On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote:
> With everything else now in place, we can convert the remaining parts of
> the reset subsystem to becoming fwnode-agnostic - meaning it will work
> with all kinds of firmware nodes, not only devicetree.
>
> To that end: extend struct reset_controller_dev with fields taking
> information relevant for using firmware nodes (which mirrors what we
> already do for OF-nodes) and limit using of_ APIs only to where it's
> absolutely necessary (mostly around the of_xlate callback).
>
> For backward compatibility of existing drivers we still support OF-nodes
> but firmware nodes become the preferred method.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Just to share I'm seeing the following on RZ/G3E (next-20260310):
[ 16.806538] ------------[ cut here ]------------
[ 16.806546] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x474/0x568, CPU#3: kworker/u16:0/11
[ 16.806566] Modules linked in: reset_rzv2h_usb2phy(+) rcar_canfd(+) rtc_isl1208 can_dev ecdh_generic ecc rfkill renesas_rpc_if fuse drm backlight ipv6
[ 16.806603] CPU: 3 UID: 0 PID: 11 Comm: kworker/u16:0 Not tainted 7.0.0-rc3-next-20260310-00016-g866b1999e3fc #17 PREEMPT
[ 16.806610] Hardware name: Renesas SMARC EVK version 2 based on r9a09g047e57 (DT)
[ 16.806615] Workqueue: events_unbound deferred_probe_work_func
[ 16.806627] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 16.806632] pc : __fwnode_reset_control_get+0x474/0x568
[ 16.806638] lr : __fwnode_reset_control_get+0x164/0x568
[ 16.806644] sp : ffff800083263930
[ 16.806646] x29: ffff800083263a30 x28: ffff0000ff8370a8 x27: ffff800081d8d590
[ 16.806655] x26: ffff800081e3a6c8 x25: ffff800082fec430 x24: ffff800082fec450
[ 16.806663] x23: 0000000000000000 x22: 0000000000000003 x21: ffff0000ff835940
[ 16.806671] x20: 0000000000000000 x19: ffff0000c0294e98 x18: 00000000ffffffff
[ 16.806679] x17: 6e6f637478652f79 x16: 68702d6273752e30 x15: 303230303835312f
[ 16.806687] x14: ffff8000831a6200 x13: 00363038343d4d55 x12: 0000000000000000
[ 16.806695] x11: 7478653d4d455453 x10: ffff8000827b0ab7 x9 : 0000000000000028
[ 16.806703] x8 : 0101010101010101 x7 : 00000000736c6c65 x6 : 000000000080a3f0
[ 16.806711] x5 : ffff800083263864 x4 : ffffffffff604034 x3 : 0000000000000000
[ 16.806719] x2 : ffff0000c0128fc0 x1 : 0000000000000000 x0 : 0000000000000001
[ 16.806727] Call trace:
[ 16.806731] __fwnode_reset_control_get+0x474/0x568 (P)
[ 16.806738] fwnode_reset_control_array_get+0x84/0x134
[ 16.806745] devm_reset_control_array_get+0x54/0xb4
[ 16.806751] rcar_gen3_phy_usb2_probe+0x108/0x5b8
[ 16.806762] platform_probe+0x5c/0x98
[ 16.806770] really_probe+0xbc/0x29c
[ 16.806776] __driver_probe_device+0x78/0x12c
[ 16.806782] driver_probe_device+0x3c/0x15c
[ 16.806789] __device_attach_driver+0xb8/0x134
[ 16.806795] bus_for_each_drv+0x88/0xe8
[ 16.806802] __device_attach+0xa0/0x190
[ 16.806808] device_initial_probe+0x50/0x54
[ 16.806814] bus_probe_device+0x38/0xa4
[ 16.806820] deferred_probe_work_func+0x88/0xc0
[ 16.806826] process_one_work+0x154/0x294
[ 16.806835] worker_thread+0x180/0x300
[ 16.806840] kthread+0x118/0x124
[ 16.806847] ret_from_fork+0x10/0x20
[ 16.806856] ---[ end trace 0000000000000000 ]---
[ 16.806867] phy_rcar_gen3_usb2 15800200.usb-phy: probe with driver phy_rcar_gen3_usb2 failed with error -22
Hope this help.
Thanks & Regards,
Tommaso
> ---
> drivers/reset/core.c | 166 +++++++++++++++++++++++----------------
> include/linux/reset-controller.h | 14 +++-
> 2 files changed, 112 insertions(+), 68 deletions(-)
>
> diff --git a/drivers/reset/core.c b/drivers/reset/core.c
> index 0817afe72de75f795d62e02451520726da7c9844..e33a9bc9f94fc6867be6efd32178658d99fc088f 100644
> --- a/drivers/reset/core.c
> +++ b/drivers/reset/core.c
> @@ -81,13 +81,13 @@ struct reset_control_array {
>
> /**
> * struct reset_gpio_lookup - lookup key for ad-hoc created reset-gpio devices
> - * @of_args: phandle to the reset controller with all the args like GPIO number
> + * @ref_args: Reference to the reset controller with all the args like GPIO number
> * @swnode: Software node containing the reference to the GPIO provider
> * @list: list entry for the reset_gpio_lookup_list
> * @adev: Auxiliary device representing the reset controller
> */
> struct reset_gpio_lookup {
> - struct of_phandle_args of_args;
> + struct fwnode_reference_args ref_args;
> struct fwnode_handle *swnode;
> struct list_head list;
> struct auxiliary_device adev;
> @@ -98,24 +98,24 @@ static const char *rcdev_name(struct reset_controller_dev *rcdev)
> if (rcdev->dev)
> return dev_name(rcdev->dev);
>
> - if (rcdev->of_node)
> - return rcdev->of_node->full_name;
> + if (rcdev->fwnode)
> + return fwnode_get_name(rcdev->fwnode);
>
> return NULL;
> }
>
> /**
> - * of_reset_simple_xlate - translate reset_spec to the reset line number
> + * fwnode_reset_simple_xlate - translate reset_spec to the reset line number
> * @rcdev: a pointer to the reset controller device
> - * @reset_spec: reset line specifier as found in the device tree
> + * @reset_spec: reset line specifier as found in firmware
> *
> - * This static translation function is used by default if of_xlate in
> - * :c:type:`reset_controller_dev` is not set. It is useful for all reset
> - * controllers with 1:1 mapping, where reset lines can be indexed by number
> - * without gaps.
> + * This static translation function is used by default if neither fwnode_xlate
> + * not of_xlate in :c:type:`reset_controller_dev` is not set. It is useful for
> + * all reset controllers with 1:1 mapping, where reset lines can be indexed by
> + * number without gaps.
> */
> -static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
> - const struct of_phandle_args *reset_spec)
> +static int fwnode_reset_simple_xlate(struct reset_controller_dev *rcdev,
> + const struct fwnode_reference_args *reset_spec)
> {
> if (reset_spec->args[0] >= rcdev->nr_resets)
> return -EINVAL;
> @@ -129,9 +129,23 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
> */
> int reset_controller_register(struct reset_controller_dev *rcdev)
> {
> - if (!rcdev->of_xlate) {
> - rcdev->of_reset_n_cells = 1;
> - rcdev->of_xlate = of_reset_simple_xlate;
> + if ((rcdev->of_node && rcdev->fwnode) || (rcdev->of_xlate && rcdev->fwnode_xlate))
> + return -EINVAL;
> +
> + if (!rcdev->of_node && !rcdev->fwnode) {
> + rcdev->fwnode = dev_fwnode(rcdev->dev);
> + if (!rcdev->fwnode)
> + return -EINVAL;
> + }
> +
> + if (rcdev->of_node) {
> + rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
> + rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
> + }
> +
> + if (rcdev->fwnode && !rcdev->fwnode_xlate) {
> + rcdev->fwnode_reset_n_cells = 1;
> + rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
> }
>
> INIT_LIST_HEAD(&rcdev->reset_control_head);
> @@ -931,7 +945,7 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
> adev->id = id;
> adev->name = "gpio";
> adev->dev.parent = parent;
> - adev->dev.platform_data = &rgpio_dev->of_args;
> + adev->dev.platform_data = &rgpio_dev->ref_args;
> adev->dev.release = reset_gpio_aux_device_release;
> device_set_node(&adev->dev, rgpio_dev->swnode);
>
> @@ -951,18 +965,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
> return 0;
> }
>
> -static void reset_gpio_add_devlink(struct device_node *np,
> +static void reset_gpio_add_devlink(struct fwnode_handle *fwnode,
> struct reset_gpio_lookup *rgpio_dev)
> {
> struct device *consumer;
>
> /*
> - * We must use get_dev_from_fwnode() and not of_find_device_by_node()
> + * We must use get_dev_from_fwnode() and not ref_find_device_by_node()
> * because the latter only considers the platform bus while we want to
> * get consumers of any kind that can be associated with firmware
> * nodes: auxiliary, soundwire, etc.
> */
> - consumer = get_dev_from_fwnode(of_fwnode_handle(np));
> + consumer = get_dev_from_fwnode(fwnode);
> if (consumer) {
> if (!device_link_add(consumer, &rgpio_dev->adev.dev,
> DL_FLAG_AUTOREMOVE_CONSUMER))
> @@ -982,15 +996,23 @@ static void reset_gpio_add_devlink(struct device_node *np,
> */
> }
>
> +/* TODO: move it out into drivers/base/ */
> +static bool fwnode_reference_args_equal(const struct fwnode_reference_args *left,
> + const struct fwnode_reference_args *right)
> +{
> + return left->fwnode == right->fwnode && left->nargs == right->nargs &&
> + !memcmp(left->args, right->args, sizeof(left->args[0]) * left->nargs);
> +}
> +
> /*
> * @np: OF-node associated with the consumer
> - * @args: phandle to the GPIO provider with all the args like GPIO number
> + * @args: Reference to the GPIO provider with all the args like GPIO number
> */
> -static int __reset_add_reset_gpio_device(struct device_node *np,
> - const struct of_phandle_args *args)
> +static int __reset_add_reset_gpio_device(struct fwnode_handle *fwnode,
> + const struct fwnode_reference_args *args)
> {
> struct property_entry properties[3] = { };
> - unsigned int offset, of_flags, lflags;
> + unsigned int offset, flags, lflags;
> struct reset_gpio_lookup *rgpio_dev;
> struct device *parent;
> int ret, prop = 0;
> @@ -1001,7 +1023,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
> * args[1]: GPIO flags
> * TODO: Handle other cases.
> */
> - if (args->args_count != 2)
> + if (args->nargs != 2)
> return -ENOENT;
>
> /*
> @@ -1012,7 +1034,7 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
> lockdep_assert_not_held(&reset_list_mutex);
>
> offset = args->args[0];
> - of_flags = args->args[1];
> + flags = args->args[1];
>
> /*
> * Later we map GPIO flags between OF and Linux, however not all
> @@ -1022,33 +1044,31 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
> * FIXME: Find a better way of translating OF flags to GPIO lookup
> * flags.
> */
> - if (of_flags > GPIO_ACTIVE_LOW) {
> + if (flags > GPIO_ACTIVE_LOW) {
> pr_err("reset-gpio code does not support GPIO flags %u for GPIO %u\n",
> - of_flags, offset);
> + flags, offset);
> return -EINVAL;
> }
>
> struct gpio_device *gdev __free(gpio_device_put) =
> - gpio_device_find_by_fwnode(of_fwnode_handle(args->np));
> + gpio_device_find_by_fwnode(args->fwnode);
> if (!gdev)
> return -EPROBE_DEFER;
>
> guard(mutex)(&reset_gpio_lookup_mutex);
>
> list_for_each_entry(rgpio_dev, &reset_gpio_lookup_list, list) {
> - if (args->np == rgpio_dev->of_args.np) {
> - if (of_phandle_args_equal(args, &rgpio_dev->of_args)) {
> - /*
> - * Already on the list, create the device link
> - * and stop here.
> - */
> - reset_gpio_add_devlink(np, rgpio_dev);
> - return 0;
> - }
> + if (fwnode_reference_args_equal(args, &rgpio_dev->ref_args)) {
> + /*
> + * Already on the list, create the device link
> + * and stop here.
> + */
> + reset_gpio_add_devlink(fwnode, rgpio_dev);
> + return 0;
> }
> }
>
> - lflags = GPIO_PERSISTENT | (of_flags & GPIO_ACTIVE_LOW);
> + lflags = GPIO_PERSISTENT | (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);
> @@ -1058,43 +1078,43 @@ static int __reset_add_reset_gpio_device(struct device_node *np,
> if (!rgpio_dev)
> return -ENOMEM;
>
> - rgpio_dev->of_args = *args;
> + rgpio_dev->ref_args = *args;
> /*
> - * We keep the device_node reference, but of_args.np is put at the end
> - * of __fwnode_reset_control_get(), so get it one more time.
> + * We keep the fwnode_handle reference, but ref_args.fwnode is put at
> + * the end of __fwnode_reset_control_get(), so get it one more time.
> * Hold reference as long as rgpio_dev memory is valid.
> */
> - of_node_get(rgpio_dev->of_args.np);
> + fwnode_handle_get(rgpio_dev->ref_args.fwnode);
>
> rgpio_dev->swnode = fwnode_create_software_node(properties, NULL);
> if (IS_ERR(rgpio_dev->swnode)) {
> ret = PTR_ERR(rgpio_dev->swnode);
> - goto err_put_of_node;
> + goto err_put_fwnode;
> }
>
> ret = reset_create_gpio_aux_device(rgpio_dev, parent);
> if (ret)
> goto err_del_swnode;
>
> - reset_gpio_add_devlink(np, rgpio_dev);
> + reset_gpio_add_devlink(fwnode, rgpio_dev);
> list_add(&rgpio_dev->list, &reset_gpio_lookup_list);
>
> return 0;
>
> err_del_swnode:
> fwnode_remove_software_node(rgpio_dev->swnode);
> -err_put_of_node:
> - of_node_put(rgpio_dev->of_args.np);
> +err_put_fwnode:
> + fwnode_handle_put(rgpio_dev->ref_args.fwnode);
> kfree(rgpio_dev);
>
> return ret;
> }
>
> -static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_args *args,
> - bool gpio_fallback)
> +static struct reset_controller_dev *
> +__reset_find_rcdev(const struct fwnode_reference_args *args, bool gpio_fallback)
> {
> + struct fwnode_reference_args *rc_args;
> struct reset_controller_dev *rcdev;
> - struct of_phandle_args *rc_args;
>
> lockdep_assert_held(&reset_list_mutex);
>
> @@ -1103,10 +1123,10 @@ static struct reset_controller_dev *__reset_find_rcdev(const struct of_phandle_a
> device_is_compatible(rcdev->dev, "reset-gpio")) {
> rc_args = dev_get_platdata(rcdev->dev);
>
> - if (of_phandle_args_equal(args, rc_args))
> + if (fwnode_reference_args_equal(args, rc_args))
> return rcdev;
> } else {
> - if (args->np == rcdev->of_node)
> + if (args->fwnode == rcdev->fwnode)
> return rcdev;
> }
> }
> @@ -1120,27 +1140,26 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
> {
> bool optional = flags & RESET_CONTROL_FLAGS_BIT_OPTIONAL;
> bool gpio_fallback = false;
> - struct device_node *node = to_of_node(fwnode);
> struct reset_control *rstc = ERR_PTR(-EINVAL);
> struct reset_controller_dev *rcdev;
> - struct of_phandle_args args;
> - int rstc_id;
> + struct fwnode_reference_args args;
> + struct of_phandle_args of_args;
> + int rstc_id = -EINVAL;
> int ret;
>
> if (!fwnode)
> return ERR_PTR(-EINVAL);
>
> if (id) {
> - index = of_property_match_string(node,
> - "reset-names", id);
> + index = fwnode_property_match_string(fwnode, "reset-names", id);
> if (index == -EILSEQ)
> return ERR_PTR(index);
> if (index < 0)
> return optional ? NULL : ERR_PTR(-ENOENT);
> }
>
> - ret = of_parse_phandle_with_args(node, "resets", "#reset-cells",
> - index, &args);
> + ret = fwnode_property_get_reference_args(fwnode, "resets", "#reset-cells",
> + 0, index, &args);
> if (ret == -EINVAL)
> return ERR_PTR(ret);
> if (ret) {
> @@ -1151,16 +1170,16 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
> * There can be only one reset-gpio for regular devices, so
> * don't bother with the "reset-gpios" phandle index.
> */
> - ret = of_parse_phandle_with_args(node, "reset-gpios", "#gpio-cells",
> - 0, &args);
> + ret = fwnode_property_get_reference_args(fwnode, "reset-gpios",
> + "#gpio-cells", 0, 0, &args);
> if (ret)
> return optional ? NULL : ERR_PTR(ret);
>
> gpio_fallback = true;
>
> - ret = __reset_add_reset_gpio_device(node, &args);
> + ret = __reset_add_reset_gpio_device(fwnode, &args);
> if (ret) {
> - of_node_put(args.np);
> + fwnode_handle_put(args.fwnode);
> return ERR_PTR(ret);
> }
> }
> @@ -1173,15 +1192,30 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
> goto out_put;
> }
>
> - if (WARN_ON(args.args_count != rcdev->of_reset_n_cells)) {
> + if (WARN_ON(args.nargs != rcdev->fwnode_reset_n_cells)) {
> rstc = ERR_PTR(-EINVAL);
> goto out_put;
> }
>
> - rstc_id = rcdev->of_xlate(rcdev, &args);
> + if (rcdev->of_xlate && is_of_node(fwnode)) {
> + ret = of_parse_phandle_with_args(to_of_node(fwnode),
> + gpio_fallback ? "reset-gpios" : "resets",
> + gpio_fallback ? "#gpio-cells" : "#reset-cells",
> + gpio_fallback ? 0 : index,
> + &of_args);
> + if (ret) {
> + rstc = ERR_PTR(ret);
> + goto out_put;
> + }
> +
> + rstc_id = rcdev->of_xlate(rcdev, &of_args);
> + of_node_put(of_args.np);
> + } else if (rcdev->fwnode_xlate) {
> + rstc_id = rcdev->fwnode_xlate(rcdev, &args);
> + }
> if (rstc_id < 0) {
> rstc = ERR_PTR(rstc_id);
> - goto out_put;
> + goto out_put;
> }
>
> flags &= ~RESET_CONTROL_FLAGS_BIT_OPTIONAL;
> @@ -1190,7 +1224,7 @@ __fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int ind
> rstc = __reset_control_get_internal(rcdev, rstc_id, flags);
>
> out_put:
> - of_node_put(args.np);
> + fwnode_handle_put(args.fwnode);
>
> return rstc;
> }
> diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
> index 185d2a9bd7cd381ddc51c0f1643c4e3cb196015e..52a5a4e81f1844075210339bf7ffa46ec5ca6edf 100644
> --- a/include/linux/reset-controller.h
> +++ b/include/linux/reset-controller.h
> @@ -5,6 +5,8 @@
> #include <linux/list.h>
> #include <linux/mutex.h>
>
> +struct fwnode_handle;
> +struct fwnode_reference_args;
> struct reset_controller_dev;
>
> /**
> @@ -38,8 +40,12 @@ struct of_phandle_args;
> * @of_node: corresponding device tree node as phandle target
> * @of_reset_n_cells: number of cells in reset line specifiers
> * @of_xlate: translation function to translate from specifier as found in the
> - * device tree to id as given to the reset control ops, defaults
> - * to :c:func:`of_reset_simple_xlate`.
> + * device tree to id as given to the reset control ops
> + * @fwnode: firmware node associated with this device
> + * @fwnode_reset_n_cells: number of cells in reset line specifiers
> + * @fwnode_xlate: translation function to translate from firmware specifier to
> + * id as given to the reset control ops, defaults to
> + * :c:func:`fwnode_reset_simple_xlate`
> * @nr_resets: number of reset controls in this reset controller device
> * @lock: protects the reset control list from concurrent access
> */
> @@ -53,6 +59,10 @@ struct reset_controller_dev {
> int of_reset_n_cells;
> int (*of_xlate)(struct reset_controller_dev *rcdev,
> const struct of_phandle_args *reset_spec);
> + struct fwnode_handle *fwnode;
> + int fwnode_reset_n_cells;
> + int (*fwnode_xlate)(struct reset_controller_dev *rcdev,
> + const struct fwnode_reference_args *reset_spec);
> unsigned int nr_resets;
> struct mutex lock;
> };
>
> --
> 2.47.3
>
On Wed, 11 Mar 2026 16:47:57 +0100, Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com> said: > Hi Bartosz, > Thanks for your patch. > > On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote: >> With everything else now in place, we can convert the remaining parts of >> the reset subsystem to becoming fwnode-agnostic - meaning it will work >> with all kinds of firmware nodes, not only devicetree. >> >> To that end: extend struct reset_controller_dev with fields taking >> information relevant for using firmware nodes (which mirrors what we >> already do for OF-nodes) and limit using of_ APIs only to where it's >> absolutely necessary (mostly around the of_xlate callback). >> >> For backward compatibility of existing drivers we still support OF-nodes >> but firmware nodes become the preferred method. >> >> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> > > Just to share I'm seeing the following on RZ/G3E (next-20260310): > > [ 16.806538] ------------[ cut here ]------------ > [ 16.806546] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x474/0x568, CPU#3: kworker/u16:0/11 > [ 16.806566] Modules linked in: reset_rzv2h_usb2phy(+) rcar_canfd(+) rtc_isl1208 can_dev ecdh_generic ecc rfkill renesas_rpc_if fuse drm backlight ipv6 > [ 16.806603] CPU: 3 UID: 0 PID: 11 Comm: kworker/u16:0 Not tainted 7.0.0-rc3-next-20260310-00016-g866b1999e3fc #17 PREEMPT > [ 16.806610] Hardware name: Renesas SMARC EVK version 2 based on r9a09g047e57 (DT) > [ 16.806615] Workqueue: events_unbound deferred_probe_work_func > [ 16.806627] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) > [ 16.806632] pc : __fwnode_reset_control_get+0x474/0x568 > [ 16.806638] lr : __fwnode_reset_control_get+0x164/0x568 > [ 16.806644] sp : ffff800083263930 > [ 16.806646] x29: ffff800083263a30 x28: ffff0000ff8370a8 x27: ffff800081d8d590 > [ 16.806655] x26: ffff800081e3a6c8 x25: ffff800082fec430 x24: ffff800082fec450 > [ 16.806663] x23: 0000000000000000 x22: 0000000000000003 x21: ffff0000ff835940 > [ 16.806671] x20: 0000000000000000 x19: ffff0000c0294e98 x18: 00000000ffffffff > [ 16.806679] x17: 6e6f637478652f79 x16: 68702d6273752e30 x15: 303230303835312f > [ 16.806687] x14: ffff8000831a6200 x13: 00363038343d4d55 x12: 0000000000000000 > [ 16.806695] x11: 7478653d4d455453 x10: ffff8000827b0ab7 x9 : 0000000000000028 > [ 16.806703] x8 : 0101010101010101 x7 : 00000000736c6c65 x6 : 000000000080a3f0 > [ 16.806711] x5 : ffff800083263864 x4 : ffffffffff604034 x3 : 0000000000000000 > [ 16.806719] x2 : ffff0000c0128fc0 x1 : 0000000000000000 x0 : 0000000000000001 > [ 16.806727] Call trace: > [ 16.806731] __fwnode_reset_control_get+0x474/0x568 (P) > [ 16.806738] fwnode_reset_control_array_get+0x84/0x134 > [ 16.806745] devm_reset_control_array_get+0x54/0xb4 > [ 16.806751] rcar_gen3_phy_usb2_probe+0x108/0x5b8 > [ 16.806762] platform_probe+0x5c/0x98 > [ 16.806770] really_probe+0xbc/0x29c > [ 16.806776] __driver_probe_device+0x78/0x12c > [ 16.806782] driver_probe_device+0x3c/0x15c > [ 16.806789] __device_attach_driver+0xb8/0x134 > [ 16.806795] bus_for_each_drv+0x88/0xe8 > [ 16.806802] __device_attach+0xa0/0x190 > [ 16.806808] device_initial_probe+0x50/0x54 > [ 16.806814] bus_probe_device+0x38/0xa4 > [ 16.806820] deferred_probe_work_func+0x88/0xc0 > [ 16.806826] process_one_work+0x154/0x294 > [ 16.806835] worker_thread+0x180/0x300 > [ 16.806840] kthread+0x118/0x124 > [ 16.806847] ret_from_fork+0x10/0x20 > [ 16.806856] ---[ end trace 0000000000000000 ]--- > [ 16.806867] phy_rcar_gen3_usb2 15800200.usb-phy: probe with driver phy_rcar_gen3_usb2 failed with error -22 > > Hope this help. > > Thanks & Regards, > Tommaso > Does [1] fix it? Bart [1] https://lore.kernel.org/all/20260310151515.34681-1-bartosz.golaszewski@oss.qualcomm.com/
Hi Bartosz, On Wed, Mar 11, 2026 at 08:54:52AM -0700, Bartosz Golaszewski wrote: > On Wed, 11 Mar 2026 16:47:57 +0100, Tommaso Merciai > <tommaso.merciai.xr@bp.renesas.com> said: > > Hi Bartosz, > > Thanks for your patch. > > > > On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote: > >> With everything else now in place, we can convert the remaining parts of > >> the reset subsystem to becoming fwnode-agnostic - meaning it will work > >> with all kinds of firmware nodes, not only devicetree. > >> > >> To that end: extend struct reset_controller_dev with fields taking > >> information relevant for using firmware nodes (which mirrors what we > >> already do for OF-nodes) and limit using of_ APIs only to where it's > >> absolutely necessary (mostly around the of_xlate callback). > >> > >> For backward compatibility of existing drivers we still support OF-nodes > >> but firmware nodes become the preferred method. > >> > >> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> > > > > Just to share I'm seeing the following on RZ/G3E (next-20260310): > > > > [ 16.806538] ------------[ cut here ]------------ > > [ 16.806546] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x474/0x568, CPU#3: kworker/u16:0/11 > > [ 16.806566] Modules linked in: reset_rzv2h_usb2phy(+) rcar_canfd(+) rtc_isl1208 can_dev ecdh_generic ecc rfkill renesas_rpc_if fuse drm backlight ipv6 > > [ 16.806603] CPU: 3 UID: 0 PID: 11 Comm: kworker/u16:0 Not tainted 7.0.0-rc3-next-20260310-00016-g866b1999e3fc #17 PREEMPT > > [ 16.806610] Hardware name: Renesas SMARC EVK version 2 based on r9a09g047e57 (DT) > > [ 16.806615] Workqueue: events_unbound deferred_probe_work_func > > [ 16.806627] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) > > [ 16.806632] pc : __fwnode_reset_control_get+0x474/0x568 > > [ 16.806638] lr : __fwnode_reset_control_get+0x164/0x568 > > [ 16.806644] sp : ffff800083263930 > > [ 16.806646] x29: ffff800083263a30 x28: ffff0000ff8370a8 x27: ffff800081d8d590 > > [ 16.806655] x26: ffff800081e3a6c8 x25: ffff800082fec430 x24: ffff800082fec450 > > [ 16.806663] x23: 0000000000000000 x22: 0000000000000003 x21: ffff0000ff835940 > > [ 16.806671] x20: 0000000000000000 x19: ffff0000c0294e98 x18: 00000000ffffffff > > [ 16.806679] x17: 6e6f637478652f79 x16: 68702d6273752e30 x15: 303230303835312f > > [ 16.806687] x14: ffff8000831a6200 x13: 00363038343d4d55 x12: 0000000000000000 > > [ 16.806695] x11: 7478653d4d455453 x10: ffff8000827b0ab7 x9 : 0000000000000028 > > [ 16.806703] x8 : 0101010101010101 x7 : 00000000736c6c65 x6 : 000000000080a3f0 > > [ 16.806711] x5 : ffff800083263864 x4 : ffffffffff604034 x3 : 0000000000000000 > > [ 16.806719] x2 : ffff0000c0128fc0 x1 : 0000000000000000 x0 : 0000000000000001 > > [ 16.806727] Call trace: > > [ 16.806731] __fwnode_reset_control_get+0x474/0x568 (P) > > [ 16.806738] fwnode_reset_control_array_get+0x84/0x134 > > [ 16.806745] devm_reset_control_array_get+0x54/0xb4 > > [ 16.806751] rcar_gen3_phy_usb2_probe+0x108/0x5b8 > > [ 16.806762] platform_probe+0x5c/0x98 > > [ 16.806770] really_probe+0xbc/0x29c > > [ 16.806776] __driver_probe_device+0x78/0x12c > > [ 16.806782] driver_probe_device+0x3c/0x15c > > [ 16.806789] __device_attach_driver+0xb8/0x134 > > [ 16.806795] bus_for_each_drv+0x88/0xe8 > > [ 16.806802] __device_attach+0xa0/0x190 > > [ 16.806808] device_initial_probe+0x50/0x54 > > [ 16.806814] bus_probe_device+0x38/0xa4 > > [ 16.806820] deferred_probe_work_func+0x88/0xc0 > > [ 16.806826] process_one_work+0x154/0x294 > > [ 16.806835] worker_thread+0x180/0x300 > > [ 16.806840] kthread+0x118/0x124 > > [ 16.806847] ret_from_fork+0x10/0x20 > > [ 16.806856] ---[ end trace 0000000000000000 ]--- > > [ 16.806867] phy_rcar_gen3_usb2 15800200.usb-phy: probe with driver phy_rcar_gen3_usb2 failed with error -22 > > > > Hope this help. > > > > Thanks & Regards, > > Tommaso > > > > Does [1] fix it? Yes, thanks for sharing. I will provide my Tested-by tag. Kind Regards, Tommaso > > Bart > > [1] https://lore.kernel.org/all/20260310151515.34681-1-bartosz.golaszewski@oss.qualcomm.com/ >
Hi Bartosz,
On Fri, 6 Mar 2026 at 18:30, Bartosz Golaszewski
<bartosz.golaszewski@oss.qualcomm.com> wrote:
> With everything else now in place, we can convert the remaining parts of
> the reset subsystem to becoming fwnode-agnostic - meaning it will work
> with all kinds of firmware nodes, not only devicetree.
>
> To that end: extend struct reset_controller_dev with fields taking
> information relevant for using firmware nodes (which mirrors what we
> already do for OF-nodes) and limit using of_ APIs only to where it's
> absolutely necessary (mostly around the of_xlate callback).
>
> For backward compatibility of existing drivers we still support OF-nodes
> but firmware nodes become the preferred method.
>
> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Thanks for your patch, which is now commit 9035073d0ef1de81 ("reset:
convert reset core to using firmware nodes") in reset/next.
> --- a/drivers/reset/core.c
> +++ b/drivers/reset/core.c
> @@ -951,18 +965,18 @@ static int reset_create_gpio_aux_device(struct reset_gpio_lookup *rgpio_dev,
> return 0;
> }
>
> -static void reset_gpio_add_devlink(struct device_node *np,
> +static void reset_gpio_add_devlink(struct fwnode_handle *fwnode,
> struct reset_gpio_lookup *rgpio_dev)
> {
> struct device *consumer;
>
> /*
> - * We must use get_dev_from_fwnode() and not of_find_device_by_node()
> + * We must use get_dev_from_fwnode() and not ref_find_device_by_node()
ref_find_device_by_node() does not exist. What should it be?
> * because the latter only considers the platform bus while we want to
> * get consumers of any kind that can be associated with firmware
> * nodes: auxiliary, soundwire, etc.
> */
> - consumer = get_dev_from_fwnode(of_fwnode_handle(np));
> + consumer = get_dev_from_fwnode(fwnode);
> if (consumer) {
> if (!device_link_add(consumer, &rgpio_dev->adev.dev,
> DL_FLAG_AUTOREMOVE_CONSUMER))
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote: > With everything else now in place, we can convert the remaining parts of > the reset subsystem to becoming fwnode-agnostic - meaning it will work > with all kinds of firmware nodes, not only devicetree. This patch is causing issues for me in yesterday's -next on a Toradax Mallow platform with a TI K3 AM625. Things start to go wrong with a WARN_ON(): [ 11.544610] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x488/0x580, CPU#0: (udev-worker)/129 ... [ 11.693583] __fwnode_reset_control_get+0x488/0x580 (P) [ 11.698802] __reset_control_get+0x64/0xa0 [ 11.702892] __devm_reset_control_get+0x74/0x110 [ 11.707502] k3_m4_rproc_probe+0xf8/0x3d0 [ti_k3_m4_remoteproc] [ 11.713421] platform_probe+0x5c/0xa4 and ends up not probing the relevant device due to: [ 12.155596] platform 78000000.r5f: error -EINVAL: failed to get reset handle Full log: https://lava.sirena.org.uk/scheduler/job/2545371#L1126 bisect log: # bad: [343f51842f4ed7143872f3aa116a214a5619a4b9] Add linux-next specific files for 20260309 # good: [7c426ecc244791791ec70ffb264e99bb5e158ef0] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git # good: [aa3d0c93a333182e887426366a4f3e5f06ee0d83] regulator: max20411: show failure on register # good: [b1ef855c62601ed4de2c4b0ff75a075877e3dac8] regmap: Simplify devres handling # good: [ef0b4783afc211a4b120e72b5a57f3d0340a9981] ASoC: cs35l56: KUnit tests for reading speaker ID from host GPIOs # good: [e7662bced2e98ffa2c572126677deb9cf55d43b3] regcache: Move HW readback after cache initialisation # good: [2adac914c72b6cb5aba2612f49050c82aecd498e] ASoC: cs35l56-test: Add test cases without onchip pulls defined # good: [96f06d055ca03d1dfb5830fd07ff6eadbd66264c] spi: dt-bindings: mpfs-spi: remove clock-names # good: [f48e7a246a567e3764112e2463274c479d95cd96] ASoC: soc-core: Use guard()/scoped_guard() for mutex lock # good: [9891b52ba12e9d5fed5901b6b5f6e0cdcd424390] regcache: Factor out regcache_hw_exit() helper # good: [e84141846decb77d2826e553318a608b256804e5] regulator: pf9453: Allow shared IRQ # good: [9ab637ac5d3826606947f4e861107da958eda324] regcache: Amend printf() specifiers when printing registers # good: [d3b693a13b39bce16e284e1c737874966b3a96de] spi: spi-mem: clean up kernel-doc in spi-mem.h # good: [da37bfe76b5b4ccc01ed8132215098e20d78e5f3] ASoC: cs42xx8: add error checks for constraints in TDM mode # good: [06dba254de95b16e7793224d29daa5195de2e581] ASoC: dt-bindings: nvidia,tegra-audio-max9808x: document additional board pins # good: [1696fad8b259a2d46e51cd6e17e4bcdbe02279fa] ASoC: sti: use managed regmap_field allocations # good: [17c6bf433742e0c1ff5ce175145877c0194e4a7a] ASoC: cs35l45: Hibernate wm_adsp on runtime suspend # good: [34b4fc44e4f904fbb81335d53163ffdcb0180000] ASoC: soc_sdw_utils: remove index from sdca codec name # good: [2974aa42e6696a1d95b727d677dc01a71af5b998] ASoC: remove snd_soc_pcm_subclass # good: [501efdcb3b3ab099fc0ce2f6e668b1c4095dd476] ASoC: SDCA: Pull the Q7.8 volume helpers out of soc-ops # good: [d90c0f78379454d51a428e312ac6db573060185c] regulator: cpcap-regulator: add support for Mot regulators # good: [5c74a008ffc62fc57a041602b4517519c8bf9436] firmware: cs_dsp: Mark KUnit test suites KUNIT_SPEED_SLOW # good: [260c3fff1fefc570d8f23e87953e181d7d248861] ASoC: cs-amp-lib-test: Stop including platform_device.h # good: [e02902dd493bf9c9b05353c761737ac514ad7a5c] spi: add devm_spi_new_ancillary_device() # good: [37983fad7f3ef296fa0504c8e945987459dc5487] regmap: define cleanup helper for regmap_field # good: [196b2b95fec447c2c4460f753b277d840633fbef] drm/nouveau: Add DRM_IOCTL_NOUVEAU_GET_ZCULL_INFO # good: [7c12f6ead4672cb08b74e6f6115eb04dca8ccfa4] spi: tegra210-quad: Add runtime autosuspend support # good: [ada32396f90951e12465224c04742607ca56a982] ASoC: SDCA: Add CS47L47 to class driver # good: [507a071d9868cb60e4e76f8a06fc8eb014f59ae4] spi: pxa2xx: use min() instead of min_t() # good: [5ebc20921b7fff9feb44de465448e17a382c9965] ASoC: tas2552: Allow audio enable GPIO to sleep # good: [5943243914b9fed8e26edcb9d45421721a5e3576] dma-buf: use inline lock for the dma-fence-array # good: [541c8f2468b933acc5d129e84bd264923675a66e] dma-buf: detach fence ops on signal v3 # good: [fed6e5084894373d76270cad4a32eb6479ad8247] spi: atcspi200: Remove redundant assignment to .owner # good: [171b3663f33e1efdc97f5112f49be10b47b20fa8] ASoC: codecs: aw88261: Add firmware-name support # good: [c2bcf62ca75c541ec4297e6ff02a68ddc2e02029] regcache: Split regcache_count_cacheable_registers() helper # good: [0556bb42a84ee391a2145ddba86756f9747bc27f] regulator: pf0900: Make regu_irqs variable static const # good: [a480f5c6f5fa14c954aa8c462302d34223947510] drm/mcde: dsi: convert to of_drm_find_and_get_bridge() # good: [8b85987d3cf50178f67618122d9f3bb202f62f42] Merge drm/drm-next into drm-misc-next # good: [d075cef4af6327a5de4bee7bf77591e3201e54f4] ASoC: simple-card-utils: add sysclk ordering support # good: [bf122191473e26a8f195308b1ba924c98424c8e1] ASoC: rt5677-spi: Add SPI device ID matching table # good: [78dfbd4ad0be9f51de7b9a19388809254aeccd26] ASoC: Add quirk for Lecoo Bellator N176 # good: [fbb4c52ccdcb4a612d2b7f800aa57090eeee16d7] regulator: spacemit-p1: Update supply names # good: [fe0b1b8269eba268a7dee293b32d6c008a6c3fec] drm/mcde: dsi: mcde_dsi_bind: break when a panel or bridge is found git bisect start '343f51842f4ed7143872f3aa116a214a5619a4b9' '7c426ecc244791791ec70ffb264e99bb5e158ef0' 'aa3d0c93a333182e887426366a4f3e5f06ee0d83' 'b1ef855c62601ed4de2c4b0ff75a075877e3dac8' 'ef0b4783afc211a4b120e72b5a57f3d0340a9981' 'e7662bced2e98ffa2c572126677deb9cf55d43b3' '2adac914c72b6cb5aba2612f49050c82aecd498e' '96f06d055ca03d1dfb5830fd07ff6eadbd66264c' 'f48e7a246a567e3764112e2463274c479d95cd96' '9891b52ba12e9d5fed5901b6b5f6e0cdcd424390' 'e84141846decb77d2826e553318a608b256804e5' '9ab637ac5d3826606947f4e861107da958eda324' 'd3b693a13b39bce16e284e1c737874966b3a96de' 'da37bfe76b5b4ccc01ed8132215098e20d78e5f3' '06dba254de95b16e7793224d29daa5195de2e581' '1696fad8b259a2d46e51cd6e17e4bcdbe02279fa' '17c6bf433742e0c1ff5ce175145877c0194e4a7a' '34b4fc44e4f904fbb81335d53163ffdcb0180000' '2974aa42e6696a1d95b727d677dc01a71af5b998' '501efdcb3b3ab099fc0ce2f6e668b1c4095dd476' 'd90c0f78379454d51a428e312ac6db573060185c' '5c74a008ffc62fc57a041602b4517519c8bf9436' '260c3fff1fefc570d8f23e87953e181d7d248861' 'e02902dd493bf9c9b05353c761737ac514ad7a5c' '37983fad7f3ef296fa0504c8e945987459dc5487' '196b2b95fec447c2c4460f753b277d840633fbef' '7c12f6ead4672cb08b74e6f6115eb04dca8ccfa4' 'ada32396f90951e12465224c04742607ca56a982' '507a071d9868cb60e4e76f8a06fc8eb014f59ae4' '5ebc20921b7fff9feb44de465448e17a382c9965' '5943243914b9fed8e26edcb9d45421721a5e3576' '541c8f2468b933acc5d129e84bd264923675a66e' 'fed6e5084894373d76270cad4a32eb6479ad8247' '171b3663f33e1efdc97f5112f49be10b47b20fa8' 'c2bcf62ca75c541ec4297e6ff02a68ddc2e02029' '0556bb42a84ee391a2145ddba86756f9747bc27f' 'a480f5c6f5fa14c954aa8c462302d34223947510' '8b85987d3cf50178f67618122d9f3bb202f62f42' 'd075cef4af6327a5de4bee7bf77591e3201e54f4' 'bf122191473e26a8f195308b1ba924c98424c8e1' '78dfbd4ad0be9f51de7b9a19388809254aeccd26' 'fbb4c52ccdcb4a612d2b7f800aa57090eeee16d7' 'fe0b1b8269eba268a7dee293b32d6c008a6c3fec' # test job: [aa3d0c93a333182e887426366a4f3e5f06ee0d83] https://lava.sirena.org.uk/scheduler/job/2531476 # test job: [b1ef855c62601ed4de2c4b0ff75a075877e3dac8] https://lava.sirena.org.uk/scheduler/job/2531902 # test job: [ef0b4783afc211a4b120e72b5a57f3d0340a9981] https://lava.sirena.org.uk/scheduler/job/2530824 # test job: [e7662bced2e98ffa2c572126677deb9cf55d43b3] https://lava.sirena.org.uk/scheduler/job/2530811 # test job: [2adac914c72b6cb5aba2612f49050c82aecd498e] https://lava.sirena.org.uk/scheduler/job/2523914 # test job: [96f06d055ca03d1dfb5830fd07ff6eadbd66264c] https://lava.sirena.org.uk/scheduler/job/2523382 # test job: [f48e7a246a567e3764112e2463274c479d95cd96] https://lava.sirena.org.uk/scheduler/job/2522152 # test job: [9891b52ba12e9d5fed5901b6b5f6e0cdcd424390] https://lava.sirena.org.uk/scheduler/job/2522265 # test job: [e84141846decb77d2826e553318a608b256804e5] https://lava.sirena.org.uk/scheduler/job/2516897 # test job: [9ab637ac5d3826606947f4e861107da958eda324] https://lava.sirena.org.uk/scheduler/job/2516463 # test job: [d3b693a13b39bce16e284e1c737874966b3a96de] https://lava.sirena.org.uk/scheduler/job/2511822 # test job: [da37bfe76b5b4ccc01ed8132215098e20d78e5f3] https://lava.sirena.org.uk/scheduler/job/2511897 # test job: [06dba254de95b16e7793224d29daa5195de2e581] https://lava.sirena.org.uk/scheduler/job/2513785 # test job: [1696fad8b259a2d46e51cd6e17e4bcdbe02279fa] https://lava.sirena.org.uk/scheduler/job/2514115 # test job: [17c6bf433742e0c1ff5ce175145877c0194e4a7a] https://lava.sirena.org.uk/scheduler/job/2513841 # test job: [34b4fc44e4f904fbb81335d53163ffdcb0180000] https://lava.sirena.org.uk/scheduler/job/2513660 # test job: [2974aa42e6696a1d95b727d677dc01a71af5b998] https://lava.sirena.org.uk/scheduler/job/2502250 # test job: [501efdcb3b3ab099fc0ce2f6e668b1c4095dd476] https://lava.sirena.org.uk/scheduler/job/2500570 # test job: [d90c0f78379454d51a428e312ac6db573060185c] https://lava.sirena.org.uk/scheduler/job/2500334 # test job: [5c74a008ffc62fc57a041602b4517519c8bf9436] https://lava.sirena.org.uk/scheduler/job/2496444 # test job: [260c3fff1fefc570d8f23e87953e181d7d248861] https://lava.sirena.org.uk/scheduler/job/2494135 # test job: [e02902dd493bf9c9b05353c761737ac514ad7a5c] https://lava.sirena.org.uk/scheduler/job/2489689 # test job: [37983fad7f3ef296fa0504c8e945987459dc5487] https://lava.sirena.org.uk/scheduler/job/2489177 # test job: [196b2b95fec447c2c4460f753b277d840633fbef] https://lava.sirena.org.uk/scheduler/job/2497877 # test job: [7c12f6ead4672cb08b74e6f6115eb04dca8ccfa4] https://lava.sirena.org.uk/scheduler/job/2488549 # test job: [ada32396f90951e12465224c04742607ca56a982] https://lava.sirena.org.uk/scheduler/job/2489110 # test job: [507a071d9868cb60e4e76f8a06fc8eb014f59ae4] https://lava.sirena.org.uk/scheduler/job/2486368 # test job: [5ebc20921b7fff9feb44de465448e17a382c9965] https://lava.sirena.org.uk/scheduler/job/2485121 # test job: [5943243914b9fed8e26edcb9d45421721a5e3576] https://lava.sirena.org.uk/scheduler/job/2498010 # test job: [541c8f2468b933acc5d129e84bd264923675a66e] https://lava.sirena.org.uk/scheduler/job/2498115 # test job: [fed6e5084894373d76270cad4a32eb6479ad8247] https://lava.sirena.org.uk/scheduler/job/2484678 # test job: [171b3663f33e1efdc97f5112f49be10b47b20fa8] https://lava.sirena.org.uk/scheduler/job/2482573 # test job: [c2bcf62ca75c541ec4297e6ff02a68ddc2e02029] https://lava.sirena.org.uk/scheduler/job/2483266 # test job: [0556bb42a84ee391a2145ddba86756f9747bc27f] https://lava.sirena.org.uk/scheduler/job/2483182 # test job: [a480f5c6f5fa14c954aa8c462302d34223947510] https://lava.sirena.org.uk/scheduler/job/2498343 # test job: [8b85987d3cf50178f67618122d9f3bb202f62f42] https://lava.sirena.org.uk/scheduler/job/2498190 # test job: [d075cef4af6327a5de4bee7bf77591e3201e54f4] https://lava.sirena.org.uk/scheduler/job/2483446 # test job: [bf122191473e26a8f195308b1ba924c98424c8e1] https://lava.sirena.org.uk/scheduler/job/2482807 # test job: [78dfbd4ad0be9f51de7b9a19388809254aeccd26] https://lava.sirena.org.uk/scheduler/job/2483097 # test job: [fbb4c52ccdcb4a612d2b7f800aa57090eeee16d7] https://lava.sirena.org.uk/scheduler/job/2482446 # test job: [fe0b1b8269eba268a7dee293b32d6c008a6c3fec] https://lava.sirena.org.uk/scheduler/job/2497744 # test job: [d9cc39c565935b634aed60237a0d9262efd703ef] https://lava.sirena.org.uk/scheduler/job/2545125 # bad: [d9cc39c565935b634aed60237a0d9262efd703ef] Merge branch 'xtensa-for-next' of https://github.com/jcmvbkbc/linux-xtensa.git git bisect bad d9cc39c565935b634aed60237a0d9262efd703ef # test job: [343f51842f4ed7143872f3aa116a214a5619a4b9] https://lava.sirena.org.uk/scheduler/job/2545371 # bad: [343f51842f4ed7143872f3aa116a214a5619a4b9] Add linux-next specific files for 20260309 git bisect bad 343f51842f4ed7143872f3aa116a214a5619a4b9 # test job: [601a8229b851e12ef5bb4fe12c034c342180df21] https://lava.sirena.org.uk/scheduler/job/2545813 # bad: [601a8229b851e12ef5bb4fe12c034c342180df21] Merge branch 'main' of https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git git bisect bad 601a8229b851e12ef5bb4fe12c034c342180df21 # test job: [d9cc39c565935b634aed60237a0d9262efd703ef] https://lava.sirena.org.uk/scheduler/job/2545125 # bad: [d9cc39c565935b634aed60237a0d9262efd703ef] Merge branch 'xtensa-for-next' of https://github.com/jcmvbkbc/linux-xtensa.git git bisect bad d9cc39c565935b634aed60237a0d9262efd703ef # test job: [68ade9d1ef86387fb7e6c50f0099d9685eebccfc] https://lava.sirena.org.uk/scheduler/job/2545938 # good: [68ade9d1ef86387fb7e6c50f0099d9685eebccfc] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/bmc/linux.git git bisect good 68ade9d1ef86387fb7e6c50f0099d9685eebccfc # test job: [5fc055700d1c1c44b455cbba097eb0456a8e7e80] https://lava.sirena.org.uk/scheduler/job/2546007 # good: [5fc055700d1c1c44b455cbba097eb0456a8e7e80] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git git bisect good 5fc055700d1c1c44b455cbba097eb0456a8e7e80 # test job: [759498ea498be7915fb7680db1b82ab24d2ea4a1] https://lava.sirena.org.uk/scheduler/job/2546151 # bad: [759498ea498be7915fb7680db1b82ab24d2ea4a1] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git git bisect bad 759498ea498be7915fb7680db1b82ab24d2ea4a1 # test job: [febe1d6bb4aedf5909524c9d2b7a0f951ff5b2cd] https://lava.sirena.org.uk/scheduler/job/2546362 # good: [febe1d6bb4aedf5909524c9d2b7a0f951ff5b2cd] Merge branch 'v7.1-armsoc/dts64' into for-next git bisect good febe1d6bb4aedf5909524c9d2b7a0f951ff5b2cd # test job: [ed463b91c8f535b0480177e7ca164852c6a8a222] https://lava.sirena.org.uk/scheduler/job/2546598 # bad: [ed463b91c8f535b0480177e7ca164852c6a8a222] Merge branch 'reset/next' of https://git.pengutronix.de/git/pza/linux git bisect bad ed463b91c8f535b0480177e7ca164852c6a8a222 # test job: [3a76b5326d67bbfe2bc81f834d2f21a5b4498b57] https://lava.sirena.org.uk/scheduler/job/2546759 # good: [3a76b5326d67bbfe2bc81f834d2f21a5b4498b57] Merge branches 'renesas-arm-defconfig-for-v7.1', 'renesas-drivers-for-v7.1', 'renesas-dt-bindings-for-v7.1' and 'renesas-dts-for-v7.1' into renesas-next git bisect good 3a76b5326d67bbfe2bc81f834d2f21a5b4498b57 # test job: [20adbf3b8f5c5787da29f8cdd7cfc4fa87854bd5] https://lava.sirena.org.uk/scheduler/job/2546854 # good: [20adbf3b8f5c5787da29f8cdd7cfc4fa87854bd5] reset: warn on reset-gpio release git bisect good 20adbf3b8f5c5787da29f8cdd7cfc4fa87854bd5 # test job: [8c91302a29bc1b710c7a164d4b81b5bb432f4eb5] https://lava.sirena.org.uk/scheduler/job/2546912 # good: [8c91302a29bc1b710c7a164d4b81b5bb432f4eb5] reset: protect struct reset_control with its own mutex git bisect good 8c91302a29bc1b710c7a164d4b81b5bb432f4eb5 # test job: [9035073d0ef1de813c6335239250248bfe0a64aa] https://lava.sirena.org.uk/scheduler/job/2546951 # bad: [9035073d0ef1de813c6335239250248bfe0a64aa] reset: convert reset core to using firmware nodes git bisect bad 9035073d0ef1de813c6335239250248bfe0a64aa # test job: [ba8dbbb14b7e6734afbb5ba37d0679831aa3d590] https://lava.sirena.org.uk/scheduler/job/2547005 # good: [ba8dbbb14b7e6734afbb5ba37d0679831aa3d590] reset: convert the core API to using firmware nodes git bisect good ba8dbbb14b7e6734afbb5ba37d0679831aa3d590 # first bad commit: [9035073d0ef1de813c6335239250248bfe0a64aa] reset: convert reset core to using firmware nodes
On Di, 2026-03-10 at 14:16 +0000, Mark Brown wrote:
> On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote:
> > With everything else now in place, we can convert the remaining parts of
> > the reset subsystem to becoming fwnode-agnostic - meaning it will work
> > with all kinds of firmware nodes, not only devicetree.
>
> This patch is causing issues for me in yesterday's -next on a Toradax
> Mallow platform with a TI K3 AM625. Things start to go wrong with a
> WARN_ON():
>
> [ 11.544610] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x488/0x580, CPU#0: (udev-worker)/129
Thank you, that's reset_controller_register() setting
fwnode_reset_n_cells to 2 since rcdev->of_node is set and rcdev-
>of_reset_n_cells == 2:
if (rcdev->of_node) {
rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
}
and then overwriting it with 1, because rcdev->fwnode is now set as
well, rcdev->fwnode_xlate is NULL, and rcdev->of_xlate is ignored:
if (rcdev->fwnode && !rcdev->fwnode_xlate) {
rcdev->fwnode_reset_n_cells = 1;
rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
}
That then fails because #reset-cells is <2> for k3_reset.
We also have to check !rcdev->of_xlate here. Could you check if this
fixes the issue?
----------8<----------
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index e625cf59cfb0..d52595db5f87 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -143,7 +143,7 @@ int reset_controller_register(struct reset_controller_dev *rcdev)
rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
}
- if (rcdev->fwnode && !rcdev->fwnode_xlate) {
+ if (rcdev->fwnode && !rcdev->fwnode_xlate && !rcdev->of_xlate) {
rcdev->fwnode_reset_n_cells = 1;
rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
}
---------->8----------
regards
Philipp
On Tue, Mar 10, 2026 at 3:49 PM Philipp Zabel <p.zabel@pengutronix.de> wrote:
>
> On Di, 2026-03-10 at 14:16 +0000, Mark Brown wrote:
> > On Fri, Mar 06, 2026 at 06:22:57PM +0100, Bartosz Golaszewski wrote:
> > > With everything else now in place, we can convert the remaining parts of
> > > the reset subsystem to becoming fwnode-agnostic - meaning it will work
> > > with all kinds of firmware nodes, not only devicetree.
> >
> > This patch is causing issues for me in yesterday's -next on a Toradax
> > Mallow platform with a TI K3 AM625. Things start to go wrong with a
> > WARN_ON():
> >
> > [ 11.544610] WARNING: drivers/reset/core.c:1195 at __fwnode_reset_control_get+0x488/0x580, CPU#0: (udev-worker)/129
>
> Thank you, that's reset_controller_register() setting
> fwnode_reset_n_cells to 2 since rcdev->of_node is set and rcdev-
> >of_reset_n_cells == 2:
>
> if (rcdev->of_node) {
> rcdev->fwnode = of_fwnode_handle(rcdev->of_node);
> rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
> }
>
> and then overwriting it with 1, because rcdev->fwnode is now set as
> well, rcdev->fwnode_xlate is NULL, and rcdev->of_xlate is ignored:
>
> if (rcdev->fwnode && !rcdev->fwnode_xlate) {
> rcdev->fwnode_reset_n_cells = 1;
> rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
> }
>
> That then fails because #reset-cells is <2> for k3_reset.
> We also have to check !rcdev->of_xlate here. Could you check if this
> fixes the issue?
>
> ----------8<----------
> diff --git a/drivers/reset/core.c b/drivers/reset/core.c
> index e625cf59cfb0..d52595db5f87 100644
> --- a/drivers/reset/core.c
> +++ b/drivers/reset/core.c
> @@ -143,7 +143,7 @@ int reset_controller_register(struct reset_controller_dev *rcdev)
> rcdev->fwnode_reset_n_cells = rcdev->of_reset_n_cells;
> }
>
> - if (rcdev->fwnode && !rcdev->fwnode_xlate) {
> + if (rcdev->fwnode && !rcdev->fwnode_xlate && !rcdev->of_xlate) {
> rcdev->fwnode_reset_n_cells = 1;
> rcdev->fwnode_xlate = fwnode_reset_simple_xlate;
> }
> ---------->8----------
>
Yeah, I just noticed the same. I'm fixing it and will send a patch shortly.
Bart
On Fr, 2026-03-06 at 18:22 +0100, Bartosz Golaszewski wrote: > With everything else now in place, we can convert the remaining parts of > the reset subsystem to becoming fwnode-agnostic - meaning it will work > with all kinds of firmware nodes, not only devicetree. > > To that end: extend struct reset_controller_dev with fields taking > information relevant for using firmware nodes (which mirrors what we > already do for OF-nodes) and limit using of_ APIs only to where it's > absolutely necessary (mostly around the of_xlate callback). > > For backward compatibility of existing drivers we still support OF-nodes > but firmware nodes become the preferred method. > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> regards Philipp
© 2016 - 2026 Red Hat, Inc.