diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/core.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d8e6a429e8ba..d0bde70f3466 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1552,6 +1552,63 @@ int regulator_force_disable(struct regulator *regulator) | |||
1552 | } | 1552 | } |
1553 | EXPORT_SYMBOL_GPL(regulator_force_disable); | 1553 | EXPORT_SYMBOL_GPL(regulator_force_disable); |
1554 | 1554 | ||
1555 | static 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 | */ | ||
1599 | int 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 | } | ||
1610 | EXPORT_SYMBOL_GPL(regulator_disable_deferred); | ||
1611 | |||
1555 | static int _regulator_is_enabled(struct regulator_dev *rdev) | 1612 | static 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); |