aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c108
1 files changed, 107 insertions, 1 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d8e6a429e8ba..669d02160221 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -28,6 +28,7 @@
28#include <linux/regulator/consumer.h> 28#include <linux/regulator/consumer.h>
29#include <linux/regulator/driver.h> 29#include <linux/regulator/driver.h>
30#include <linux/regulator/machine.h> 30#include <linux/regulator/machine.h>
31#include <linux/module.h>
31 32
32#define CREATE_TRACE_POINTS 33#define CREATE_TRACE_POINTS
33#include <trace/events/regulator.h> 34#include <trace/events/regulator.h>
@@ -1425,7 +1426,7 @@ int regulator_enable(struct regulator *regulator)
1425 ret = _regulator_enable(rdev); 1426 ret = _regulator_enable(rdev);
1426 mutex_unlock(&rdev->mutex); 1427 mutex_unlock(&rdev->mutex);
1427 1428
1428 if (ret != 0) 1429 if (ret != 0 && rdev->supply)
1429 regulator_disable(rdev->supply); 1430 regulator_disable(rdev->supply);
1430 1431
1431 return ret; 1432 return ret;
@@ -1552,6 +1553,68 @@ int regulator_force_disable(struct regulator *regulator)
1552} 1553}
1553EXPORT_SYMBOL_GPL(regulator_force_disable); 1554EXPORT_SYMBOL_GPL(regulator_force_disable);
1554 1555
1556static void regulator_disable_work(struct work_struct *work)
1557{
1558 struct regulator_dev *rdev = container_of(work, struct regulator_dev,
1559 disable_work.work);
1560 int count, i, ret;
1561
1562 mutex_lock(&rdev->mutex);
1563
1564 BUG_ON(!rdev->deferred_disables);
1565
1566 count = rdev->deferred_disables;
1567 rdev->deferred_disables = 0;
1568
1569 for (i = 0; i < count; i++) {
1570 ret = _regulator_disable(rdev);
1571 if (ret != 0)
1572 rdev_err(rdev, "Deferred disable failed: %d\n", ret);
1573 }
1574
1575 mutex_unlock(&rdev->mutex);
1576
1577 if (rdev->supply) {
1578 for (i = 0; i < count; i++) {
1579 ret = regulator_disable(rdev->supply);
1580 if (ret != 0) {
1581 rdev_err(rdev,
1582 "Supply disable failed: %d\n", ret);
1583 }
1584 }
1585 }
1586}
1587
1588/**
1589 * regulator_disable_deferred - disable regulator output with delay
1590 * @regulator: regulator source
1591 * @ms: miliseconds until the regulator is disabled
1592 *
1593 * Execute regulator_disable() on the regulator after a delay. This
1594 * is intended for use with devices that require some time to quiesce.
1595 *
1596 * NOTE: this will only disable the regulator output if no other consumer
1597 * devices have it enabled, the regulator device supports disabling and
1598 * machine constraints permit this operation.
1599 */
1600int regulator_disable_deferred(struct regulator *regulator, int ms)
1601{
1602 struct regulator_dev *rdev = regulator->rdev;
1603 int ret;
1604
1605 mutex_lock(&rdev->mutex);
1606 rdev->deferred_disables++;
1607 mutex_unlock(&rdev->mutex);
1608
1609 ret = schedule_delayed_work(&rdev->disable_work,
1610 msecs_to_jiffies(ms));
1611 if (ret < 0)
1612 return ret;
1613 else
1614 return 0;
1615}
1616EXPORT_SYMBOL_GPL(regulator_disable_deferred);
1617
1555static int _regulator_is_enabled(struct regulator_dev *rdev) 1618static int _regulator_is_enabled(struct regulator_dev *rdev)
1556{ 1619{
1557 /* If we don't know then assume that the regulator is always on */ 1620 /* If we don't know then assume that the regulator is always on */
@@ -2622,6 +2685,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2622 INIT_LIST_HEAD(&rdev->consumer_list); 2685 INIT_LIST_HEAD(&rdev->consumer_list);
2623 INIT_LIST_HEAD(&rdev->list); 2686 INIT_LIST_HEAD(&rdev->list);
2624 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 2687 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
2688 INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
2625 2689
2626 /* preform any regulator specific init */ 2690 /* preform any regulator specific init */
2627 if (init_data->regulator_init) { 2691 if (init_data->regulator_init) {
@@ -2729,6 +2793,7 @@ void regulator_unregister(struct regulator_dev *rdev)
2729#ifdef CONFIG_DEBUG_FS 2793#ifdef CONFIG_DEBUG_FS
2730 debugfs_remove_recursive(rdev->debugfs); 2794 debugfs_remove_recursive(rdev->debugfs);
2731#endif 2795#endif
2796 flush_work_sync(&rdev->disable_work.work);
2732 WARN_ON(rdev->open_count); 2797 WARN_ON(rdev->open_count);
2733 unset_regulator_supplies(rdev); 2798 unset_regulator_supplies(rdev);
2734 list_del(&rdev->list); 2799 list_del(&rdev->list);
@@ -2907,6 +2972,43 @@ void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
2907} 2972}
2908EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 2973EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
2909 2974
2975#ifdef CONFIG_DEBUG_FS
2976static ssize_t supply_map_read_file(struct file *file, char __user *user_buf,
2977 size_t count, loff_t *ppos)
2978{
2979 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
2980 ssize_t len, ret = 0;
2981 struct regulator_map *map;
2982
2983 if (!buf)
2984 return -ENOMEM;
2985
2986 list_for_each_entry(map, &regulator_map_list, list) {
2987 len = snprintf(buf + ret, PAGE_SIZE - ret,
2988 "%s -> %s.%s\n",
2989 rdev_get_name(map->regulator), map->dev_name,
2990 map->supply);
2991 if (len >= 0)
2992 ret += len;
2993 if (ret > PAGE_SIZE) {
2994 ret = PAGE_SIZE;
2995 break;
2996 }
2997 }
2998
2999 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
3000
3001 kfree(buf);
3002
3003 return ret;
3004}
3005
3006static const struct file_operations supply_map_fops = {
3007 .read = supply_map_read_file,
3008 .llseek = default_llseek,
3009};
3010#endif
3011
2910static int __init regulator_init(void) 3012static int __init regulator_init(void)
2911{ 3013{
2912 int ret; 3014 int ret;
@@ -2919,6 +3021,10 @@ static int __init regulator_init(void)
2919 pr_warn("regulator: Failed to create debugfs directory\n"); 3021 pr_warn("regulator: Failed to create debugfs directory\n");
2920 debugfs_root = NULL; 3022 debugfs_root = NULL;
2921 } 3023 }
3024
3025 if (IS_ERR(debugfs_create_file("supply_map", 0444, debugfs_root,
3026 NULL, &supply_map_fops)))
3027 pr_warn("regulator: Failed to create supplies debugfs\n");
2922#endif 3028#endif
2923 3029
2924 regulator_dummy_init(); 3030 regulator_dummy_init();