ANDROID: GKI: regulator: core: Add support for regulator providers with sync state
Regulator providers whose drivers have sync_state() implemented will disable their regulators once all their consumers have probed. So during late_initcall_sync(), don't disable unused regulators of these regulator providers. Also, provide a regulator_sync_state() API that regulator providers can use to disable all their unused regulators once the get their sync_state() callback. Bug: 144127090 Bug: 150508586 Signed-off-by: Saravana Kannan <saravanak@google.com> Change-Id: I5cc32730214c8e769c2a55cbe3b702cf6bb9016a
This commit is contained in:
parent
4bad67ba2a
commit
95b8a4b5b1
3 changed files with 32 additions and 5 deletions
|
@ -4490,6 +4490,30 @@ void regulator_unregister(struct regulator_dev *rdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_unregister);
|
||||
|
||||
static int regulator_sync_supply(struct device *dev, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = dev_to_rdev(dev);
|
||||
|
||||
if (rdev->dev.parent != data)
|
||||
return 0;
|
||||
|
||||
if (!rdev->proxy_consumer)
|
||||
return 0;
|
||||
|
||||
dev_dbg(data, "Removing regulator proxy consumer requests\n");
|
||||
regulator_proxy_consumer_unregister(rdev->proxy_consumer);
|
||||
rdev->proxy_consumer = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void regulator_sync_state(struct device *dev)
|
||||
{
|
||||
class_for_each_device(®ulator_class, NULL, dev,
|
||||
regulator_sync_supply);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_sync_state);
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
static int _regulator_suspend(struct device *dev, void *data)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ struct proxy_consumer *regulator_proxy_consumer_register(struct device *reg_dev,
|
|||
const char *reg_name = "";
|
||||
u32 voltage[2] = {0};
|
||||
int rc;
|
||||
bool no_sync_state = !reg_dev->driver->sync_state;
|
||||
|
||||
/* Return immediately if no proxy consumer properties are specified. */
|
||||
if (!of_find_property(reg_node, "qcom,proxy-consumer-enable", NULL)
|
||||
|
@ -60,7 +61,7 @@ struct proxy_consumer *regulator_proxy_consumer_register(struct device *reg_dev,
|
|||
mutex_lock(&proxy_consumer_list_mutex);
|
||||
|
||||
/* Do not register new consumers if they cannot be removed later. */
|
||||
if (proxy_consumers_removed) {
|
||||
if (proxy_consumers_removed && no_sync_state) {
|
||||
rc = -EPERM;
|
||||
goto unlock;
|
||||
}
|
||||
|
@ -74,6 +75,7 @@ struct proxy_consumer *regulator_proxy_consumer_register(struct device *reg_dev,
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&consumer->list);
|
||||
consumer->enable
|
||||
= of_property_read_bool(reg_node, "qcom,proxy-consumer-enable");
|
||||
of_property_read_u32(reg_node, "qcom,proxy-consumer-current",
|
||||
|
@ -125,7 +127,8 @@ struct proxy_consumer *regulator_proxy_consumer_register(struct device *reg_dev,
|
|||
}
|
||||
}
|
||||
|
||||
list_add(&consumer->list, &proxy_consumer_list);
|
||||
if (no_sync_state)
|
||||
list_add(&consumer->list, &proxy_consumer_list);
|
||||
mutex_unlock(&proxy_consumer_list_mutex);
|
||||
|
||||
return consumer;
|
||||
|
@ -190,8 +193,7 @@ int regulator_proxy_consumer_unregister(struct proxy_consumer *consumer)
|
|||
return 0;
|
||||
|
||||
mutex_lock(&proxy_consumer_list_mutex);
|
||||
if (!proxy_consumers_removed)
|
||||
rc = regulator_proxy_consumer_remove(consumer);
|
||||
rc = regulator_proxy_consumer_remove(consumer);
|
||||
mutex_unlock(&proxy_consumer_list_mutex);
|
||||
|
||||
return rc;
|
||||
|
@ -210,7 +212,7 @@ static int __init regulator_proxy_consumer_remove_all(void)
|
|||
proxy_consumers_removed = true;
|
||||
|
||||
if (!list_empty(&proxy_consumer_list))
|
||||
pr_info("removing regulator proxy consumer requests\n");
|
||||
pr_info("removing legacy regulator proxy consumer requests\n");
|
||||
|
||||
list_for_each_entry_safe(consumer, temp, &proxy_consumer_list, list) {
|
||||
regulator_proxy_consumer_remove(consumer);
|
||||
|
|
|
@ -487,6 +487,7 @@ devm_regulator_register(struct device *dev,
|
|||
const struct regulator_desc *regulator_desc,
|
||||
const struct regulator_config *config);
|
||||
void regulator_unregister(struct regulator_dev *rdev);
|
||||
void regulator_sync_state(struct device *dev);
|
||||
void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
|
||||
|
||||
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
||||
|
|
Loading…
Reference in a new issue