Re: [PATCH v3 07/12] reset: Add reset_control_get_from_provider_exclusive()
From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: 2026-09-02 11:44:37
Also in:
arm-scmi, linux-clk, linux-devicetree, linux-pm, linux-renesas-soc, lkml
On Wed, 2 Sept 2026 at 13:30, Geert Uytterhoeven [off-list ref] wrote:
quoted hunk ↗ jump to hunk
When stacking two reset controllers, the upper one should go through the proper channels: request exclusive reset controls and use them via the reset_control_*() APIs. However, unlike the clock subsystem, which has of_clk_get_from_provider(), the reset subsystem does not offer a way to lookup and obtain a reset from a reset provider. Hence add a public helper reset_control_get_from_provider_exclusive() to lookup and obtain an exclusive reference to a reset controller, based on the recently introduced __reset_control_get_from_provider() helper. This will be used by the R-Car X5H Module Controller driver. Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> --- v3: - Replace reset_controller_get_provider() by reset_control_get_from_provider_exclusive(), - Add kerneldoc, v2: - No changes. --- drivers/reset/core.c | 37 ++++++++++++++++++++++++++++++++----- include/linux/reset.h | 8 ++++++++ 2 files changed, 40 insertions(+), 5 deletions(-)diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 8af7cd2e8a5029df..6d4c95b3edb18248 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c@@ -1141,6 +1141,7 @@ __reset_control_get_from_provider(const struct fwnode_reference_args *args, bool gpio_fallback, enum reset_control_flags flags) { + struct fwnode_handle *fwnode = consumer ?: args->fwnode; struct reset_control *rstc = ERR_PTR(-EINVAL); struct reset_controller_dev *rcdev; int rstc_id = -EINVAL;@@ -1154,18 +1155,26 @@ __reset_control_get_from_provider(const struct fwnode_reference_args *args, if (WARN_ON(args->nargs != rcdev->fwnode_reset_n_cells)) return ERR_PTR(-EINVAL); - if (rcdev->of_xlate && is_of_node(consumer)) { - struct device_node *np = to_of_node(consumer); + if (rcdev->of_xlate && is_of_node(fwnode)) { + struct device_node *np = to_of_node(fwnode); struct of_phandle_args of_args; int ret; - ret = of_parse_phandle_with_args(np, + if (consumer) { + ret = of_parse_phandle_with_args(np, gpio_fallback ? "reset-gpios" : "resets", gpio_fallback ? "#gpio-cells" : "#reset-cells", gpio_fallback ? 0 : index, &of_args); - if (ret) - return ERR_PTR(ret); + if (ret) + return ERR_PTR(ret); + } else { + of_args.np = of_node_get(np); + of_args.args_count = args->nargs; + + for (unsigned int i = 0; i < args->nargs; i++) + of_args.args[i] = args->args[i]; + } rstc_id = rcdev->of_xlate(rcdev, &of_args); of_node_put(of_args.np);@@ -1257,6 +1266,24 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, } EXPORT_SYMBOL_GPL(__reset_control_get); +/** + * reset_control_get_from_provider_exclusive - Lookup and obtain an exclusive + * reference to a reset controller. + * @args: Reference to the reset controller provider with all the args like + * reset number + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * If this function is called more than once for the same reset control it will + * return -EBUSY. + */ +struct reset_control * +reset_control_get_from_provider_exclusive(const struct fwnode_reference_args *args) +{ + return __reset_control_get_from_provider(args, NULL, 0, false, + RESET_CONTROL_EXCLUSIVE); +} +EXPORT_SYMBOL_GPL(reset_control_get_from_provider_exclusive); + int __reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs, enum reset_control_flags flags)diff --git a/include/linux/reset.h b/include/linux/reset.h index 9c391cf0c82298a0..09ee47b27f88d3b1 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h@@ -90,6 +90,8 @@ struct reset_control *__fwnode_reset_control_get(struct fwnode_handle *fwnode, const char *id, int index, enum reset_control_flags flags); struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, enum reset_control_flags flags); +struct reset_control *reset_control_get_from_provider_exclusive( + const struct fwnode_reference_args *args); void reset_control_put(struct reset_control *rstc); int __reset_control_bulk_get(struct device *dev, int num_rstcs, struct reset_control_bulk_data *rstcs,@@ -173,6 +175,12 @@ static inline struct reset_control *__reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); } +static inline struct reset_control *reset_control_get_from_provider_exclusive( + const struct fwnode_reference_args *args) +{ + return NULL;
As reported by Sashiko, this dummy should return ERR_PTR(-ENOTSUPP) instead.
+}
+
static inline int
reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs)
{
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