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:
Saravana Kannan 2019-11-06 12:21:35 -08:00
parent 4bad67ba2a
commit 95b8a4b5b1
3 changed files with 32 additions and 5 deletions

View file

@ -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(&regulator_class, NULL, dev,
regulator_sync_supply);
}
EXPORT_SYMBOL_GPL(regulator_sync_state);
#ifdef CONFIG_SUSPEND
static int _regulator_suspend(struct device *dev, void *data)
{

View file

@ -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);

View file

@ -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,