From 95b8a4b5b185b931f20a87a20152d4d25c83a389 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Wed, 6 Nov 2019 12:21:35 -0800 Subject: [PATCH] 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 Change-Id: I5cc32730214c8e769c2a55cbe3b702cf6bb9016a --- drivers/regulator/core.c | 24 ++++++++++++++++++++++++ drivers/regulator/proxy-consumer.c | 12 +++++++----- include/linux/regulator/driver.h | 1 + 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ea429212672d..9554d25f7afe 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -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) { diff --git a/drivers/regulator/proxy-consumer.c b/drivers/regulator/proxy-consumer.c index 6ae1c7a03815..1e60c149ff47 100644 --- a/drivers/regulator/proxy-consumer.c +++ b/drivers/regulator/proxy-consumer.c @@ -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); diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 917d4287af97..682479690877 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -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,