Re: [PATCH v2 13/14] reset: convert reset core to using firmware nodes

From: Philipp Zabel

Date: Wed Mar 04 2026 - 06:34:40 EST


On Mo, 2026-02-23 at 11:06 +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@xxxxxxxxxxxxxxxx>
> ---
> drivers/reset/core.c | 154 +++++++++++++++++++++++----------------
> include/linux/reset-controller.h | 14 +++-
> 2 files changed, 103 insertions(+), 65 deletions(-)
>
> diff --git a/drivers/reset/core.c b/drivers/reset/core.c
> index 1ac68371b77101b18db5a16c6471cfffee0dce7c..174b50eda01948bc697529a549cf38bfca7180f8 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
> + * This static translation function is used by default if fwnode_xlate in

... if neither fwnode_xlate nor of_xlate ... are set.

> * :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,17 @@ 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 = 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;

There should be no driver that does this, but if neither of_node nor
fwnode are set, this can leave fwnode_xlate == NULL and cause
reset_control_get() to always return -EINVAL. We could return -EINVAL
here if (!rcdev->of_node != !rcdev->fwnode).

regards
Philipp