aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/core.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-11 04:53:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-09-14 05:58:23 -0400
commitda07ecd93b196819dcec488b7ebec69a71f3819e (patch)
treea4d9f7b306911bf7dfb692418c1ad82792d8c4ee /drivers/regulator/core.c
parent30ab1e78864ca5781de5b1fb501bed9df2c215f1 (diff)
regulator: Implement deferred disable support
It is a reasonably common pattern for hardware to require some delay after being quiesced before the disable has finalised, especially in mixed signal devices. For example, an active discharge may be required to ensure that the circuit starts up again in a known state. Avoid having to implement such delays in the regulator API by providing regulator_deferred_disable() which will do a regulator_disable() a specified number of milliseconds after it is called. Due to the reference counting done on regulators a deferred disable can be cancelled by doing another regulator_enable(). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'drivers/regulator/core.c')
-rw-r--r--drivers/regulator/core.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index d8e6a429e8b..d0bde70f346 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1552,6 +1552,63 @@ int regulator_force_disable(struct regulator *regulator)
1552} 1552}
1553EXPORT_SYMBOL_GPL(regulator_force_disable); 1553EXPORT_SYMBOL_GPL(regulator_force_disable);
1554 1554
1555static void regulator_disable_work(struct work_struct *work)
1556{
1557 struct regulator_dev *rdev = container_of(work, struct regulator_dev,
1558 disable_work.work);
1559 int count, i, ret;
1560
1561 mutex_lock(&rdev->mutex);
1562
1563 BUG_ON(!rdev->deferred_disables);
1564
1565 count = rdev->deferred_disables;
1566 rdev->deferred_disables = 0;
1567
1568 for (i = 0; i < count; i++) {
1569 ret = _regulator_disable(rdev);
1570 if (ret != 0)
1571 rdev_err(rdev, "Deferred disable failed: %d\n", ret);
1572 }
1573
1574 mutex_unlock(&rdev->mutex);
1575
1576 if (rdev->supply) {
1577 for (i = 0; i < count; i++) {
1578 ret = regulator_disable(rdev->supply);
1579 if (ret != 0) {
1580 rdev_err(rdev,
1581 "Supply disable failed: %d\n", ret);
1582 }
1583 }
1584 }
1585}
1586
1587/**
1588 * regulator_disable_deferred - disable regulator output with delay
1589 * @regulator: regulator source
1590 * @ms: miliseconds until the regulator is disabled
1591 *
1592 * Execute regulator_disable() on the regulator after a delay. This
1593 * is intended for use with devices that require some time to quiesce.
1594 *
1595 * NOTE: this will only disable the regulator output if no other consumer
1596 * devices have it enabled, the regulator device supports disabling and
1597 * machine constraints permit this operation.
1598 */
1599int regulator_disable_deferred(struct regulator *regulator, int ms)
1600{
1601 struct regulator_dev *rdev = regulator->rdev;
1602
1603 mutex_lock(&rdev->mutex);
1604 rdev->deferred_disables++;
1605 mutex_unlock(&rdev->mutex);
1606
1607 return schedule_delayed_work(&rdev->disable_work,
1608 msecs_to_jiffies(ms));
1609}
1610EXPORT_SYMBOL_GPL(regulator_disable_deferred);
1611
1555static int _regulator_is_enabled(struct regulator_dev *rdev) 1612static int _regulator_is_enabled(struct regulator_dev *rdev)
1556{ 1613{
1557 /* If we don't know then assume that the regulator is always on */ 1614 /* If we don't know then assume that the regulator is always on */
@@ -2622,6 +2679,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
2622 INIT_LIST_HEAD(&rdev->consumer_list); 2679 INIT_LIST_HEAD(&rdev->consumer_list);
2623 INIT_LIST_HEAD(&rdev->list); 2680 INIT_LIST_HEAD(&rdev->list);
2624 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 2681 BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
2682 INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work);
2625 2683
2626 /* preform any regulator specific init */ 2684 /* preform any regulator specific init */
2627 if (init_data->regulator_init) { 2685 if (init_data->regulator_init) {
@@ -2729,6 +2787,7 @@ void regulator_unregister(struct regulator_dev *rdev)
2729#ifdef CONFIG_DEBUG_FS 2787#ifdef CONFIG_DEBUG_FS
2730 debugfs_remove_recursive(rdev->debugfs); 2788 debugfs_remove_recursive(rdev->debugfs);
2731#endif 2789#endif
2790 flush_work_sync(&rdev->disable_work.work);
2732 WARN_ON(rdev->open_count); 2791 WARN_ON(rdev->open_count);
2733 unset_regulator_supplies(rdev); 2792 unset_regulator_supplies(rdev);
2734 list_del(&rdev->list); 2793 list_del(&rdev->list);