From 304f5784e97281f18ef4bed574cbe5fcf6ce2f2e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20Draszik?= Date: Fri, 9 Jan 2026 08:38:43 +0000 Subject: [PATCH] regulator: core: reresolve unresolved supplies when available MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When a regulator A and its supply B are provided by different devices, the driver implementing B might be last to probe (with A still pending resolution of its supply B). While we try to resolve all pending supplies for all regulators (including A) during regulator_register() of B via regulator_register_resolve_supply(), supply resolution will still not work for A as the driver for B hasn't finished binding to the PMIC device corresponding to B at that stage yet. The regulator core explicitly only allows supplies from other devices to be used once the relevant driver has fully bound, mainly to avoid having to deal with cases where B itself might -EPROBE_DEFER. In this case, A's supply will only be resolved as part of the core's regulator_init_complete_work_function(), which currently is scheduled to run after 30s. This was added as a work-around in commit 3827b64dba27 ("regulator: core: Resolve supplies before disabling unused regulators") to cover this situation. There are two problems with that approach: * it potentially runs long after all our consumers have probed * an upcoming change will allow regulator_register() to complete successfully even when required supplies (e.g. due to always-on or boot-on) are missing at register time, deferring full configuration of the regulator (and usability by consumers, i.e. usually consumer probe) until the supply becomes available. Resolving supplies in the late work func can therefore make it impossible for consumers to probe at all, as the driver core will not know to reprobe consumers when supplies have resolved. We could schedule an earlier work to try to resolve supplies sooner, but that'd be racy as consumers of A might try to probe before A's supply gets fully resolved via this extra work. Instead, add a very simple regulator bus and add a dummy device with a corresponding driver to it for each regulator that is missing its supply during regulator_register(). This way, the driver core will call our bus' probe whenever a new (regulator) device was successfully bound, allowing us to retry resolving the supply during (our bus) probe and to bind this dummy device if successful. In turn this means the driver core will see a newly bound device and retry probing of all pending consumers, if any. With that in place, we can avoid walking the full list of all known regulators to try resolve missing supplies during regulator_register(), as the driver core will invoke the bus probe for regulators that are still pending their supplies. We can also drop the code trying to resolve supplies one last time before unused regulators get disabled, as all supplies should have resolved at that point in time, and if they haven't then there's no point in trying again, as the outcome won't change. Note: We can not reuse the existing struct device created for each rail, as a device can not be part of a class and a bus simultaneously. Signed-off-by: André Draszik Link: https://patch.msgid.link/20260109-regulators-defer-v2-7-1a25dc968e60@linaro.org Signed-off-by: Mark Brown --- drivers/regulator/core.c | 121 +++++++++++++++++++++++++------ include/linux/regulator/driver.h | 1 + 2 files changed, 98 insertions(+), 24 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 86dbee3ffda0b..08e92b1ba2dc2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -44,6 +44,8 @@ static LIST_HEAD(regulator_supply_alias_list); static LIST_HEAD(regulator_coupler_list); static bool has_full_constraints; +static const struct bus_type regulator_bus; + static struct dentry *debugfs_root; /* @@ -5694,17 +5696,6 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->bypass_count); } -static int regulator_register_resolve_supply(struct device *dev, void *data) -{ - struct regulator_dev *rdev = dev_to_rdev(dev); - - if (regulator_resolve_supply(rdev)) - rdev_dbg(rdev, "unable to resolve supply '%s'\n", - rdev->supply_name); - - return 0; -} - int regulator_coupler_register(struct regulator_coupler *coupler) { mutex_lock(®ulator_list_mutex); @@ -5923,6 +5914,7 @@ regulator_register(struct device *dev, struct regulator_config *config = NULL; static atomic_t regulator_no = ATOMIC_INIT(-1); struct regulator_dev *rdev; + bool tried_supply_resolve = false; bool dangling_cfg_gpiod = false; bool dangling_of_gpiod = false; int ret, i; @@ -6093,6 +6085,7 @@ regulator_register(struct device *dev, else rdev_dbg(rdev, "unable to resolve supply early: %pe\n", ERR_PTR(ret)); + tried_supply_resolve = true; } if (ret < 0) goto wash; @@ -6124,6 +6117,37 @@ regulator_register(struct device *dev, if (ret != 0) goto unset_supplies; + if (!tried_supply_resolve) { + /* + * As an optimisation, try to resolve our supply (if any) now to + * avoid adding the bus device. Errors are not fatal at this + * stage, we'll simply try again later. + */ + ret = regulator_resolve_supply(rdev); + if (ret) + rdev_dbg(rdev, + "unable to resolve supply (ignoring): %pe\n", + ERR_PTR(ret)); + } + + /* + * If we have a supply but couldn't resolve it yet, register a device + * with our bus, so that the bus probe gets called whenever any new + * driver binds, allowing us to retry matching supplies and which then + * triggers (re)probe of consumers if successful. + */ + if (rdev->supply_name && !rdev->supply) { + device_initialize(&rdev->bdev); + rdev->bdev.bus = ®ulator_bus; + rdev->bdev.parent = &rdev->dev; + device_set_pm_not_required(&rdev->dev); + dev_set_name(&rdev->bdev, "%s.bdev", dev_name(&rdev->dev)); + + ret = device_add(&rdev->bdev); + if (ret) + goto del_cdev_and_bdev; + } + rdev_init_debugfs(rdev); /* try to resolve regulators coupling since a new one was registered */ @@ -6131,12 +6155,13 @@ regulator_register(struct device *dev, regulator_resolve_coupling(rdev); mutex_unlock(®ulator_list_mutex); - /* try to resolve regulators supply since a new one was registered */ - class_for_each_device(®ulator_class, NULL, NULL, - regulator_register_resolve_supply); kfree(config); return rdev; +del_cdev_and_bdev: + if (rdev->bdev.bus == ®ulator_bus) + put_device(&rdev->bdev); + device_del(&rdev->dev); unset_supplies: mutex_lock(®ulator_list_mutex); unset_regulator_supplies(rdev); @@ -6189,6 +6214,9 @@ void regulator_unregister(struct regulator_dev *rdev) unset_regulator_supplies(rdev); list_del(&rdev->list); regulator_ena_gpio_free(rdev); + if (rdev->bdev.bus == ®ulator_bus) + /* only if the device was added in the first place */ + device_unregister(&rdev->bdev); device_unregister(&rdev->dev); mutex_unlock(®ulator_list_mutex); @@ -6269,6 +6297,45 @@ const struct class regulator_class = { .pm = ®ulator_pm_ops, #endif }; + +#define bdev_to_rdev(__bdev) container_of_const(__bdev, struct regulator_dev, bdev) + +static int regulator_bus_match(struct device *bdev, + const struct device_driver *drv) +{ + /* Match always succeeds, we only have one driver */ + return 1; +} + +static int regulator_bus_probe(struct device *bdev) +{ + struct regulator_dev *rdev = bdev_to_rdev(bdev); + int ret; + + ret = regulator_resolve_supply(rdev); + if (ret) + rdev_dbg(rdev, + "unable to resolve supply or constraints '%s': %pe\n", + rdev->supply_name, ERR_PTR(ret)); + else + rdev_dbg(rdev, "resolved supply '%s'\n", rdev->supply_name); + + return ret; +} + +static const struct bus_type regulator_bus = { + .name = "regulator", + .match = regulator_bus_match, + .probe = regulator_bus_probe, +}; + +static struct device_driver regulator_bus_driver = { + .name = "regulator-bus-drv", + .bus = ®ulator_bus, + .suppress_bind_attrs = true, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, +}; + /** * regulator_has_full_constraints - the system has fully specified constraints * @@ -6602,7 +6669,17 @@ static int __init regulator_init(void) { int ret; + ret = bus_register(®ulator_bus); + if (ret) + return ret; + ret = class_register(®ulator_class); + if (ret) + goto err_class; + + ret = driver_register(®ulator_bus_driver); + if (ret) + goto err_driver; debugfs_root = debugfs_create_dir("regulator", NULL); if (IS_ERR(debugfs_root)) @@ -6619,6 +6696,12 @@ static int __init regulator_init(void) regulator_coupler_register(&generic_regulator_coupler); + return 0; + +err_driver: + class_unregister(®ulator_class); +err_class: + bus_unregister(®ulator_bus); return ret; } @@ -6679,16 +6762,6 @@ __setup("regulator_ignore_unused", regulator_ignore_unused_setup); static void regulator_init_complete_work_function(struct work_struct *work) { - /* - * Regulators may had failed to resolve their input supplies - * when were registered, either because the input supply was - * not registered yet or because its parent device was not - * bound yet. So attempt to resolve the input supplies for - * pending regulators before trying to disable unused ones. - */ - class_for_each_device(®ulator_class, NULL, NULL, - regulator_register_resolve_supply); - /* * For debugging purposes, it may be useful to prevent unused * regulators from being disabled. diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 978cf593b6624..d38353f2b56f8 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -635,6 +635,7 @@ struct regulator_dev { int ref_cnt; struct module *owner; struct device dev; + struct device bdev; struct regulation_constraints *constraints; struct regulator *supply; /* for tree */ const char *supply_name; -- 2.47.3