static LIST_HEAD(regulator_coupler_list);
static bool has_full_constraints;
+static const struct bus_type regulator_bus;
+
static struct dentry *debugfs_root;
/*
&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);
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;
else
rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
ERR_PTR(ret));
+ tried_supply_resolve = true;
}
if (ret < 0)
goto wash;
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 */
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);
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);
.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
*
{
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))
regulator_coupler_register(&generic_regulator_coupler);
+ return 0;
+
+err_driver:
+ class_unregister(®ulator_class);
+err_class:
+ bus_unregister(®ulator_bus);
return ret;
}
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.