regulator: Allow regulators to verify enabled during enable()
Some regulators might need to verify that they have indeed been enabled after the enable() call is made and enable_time delay has passed. This is implemented by repeatedly checking is_enabled() upto poll_enabled_time, waiting for the already calculated enable delay in each iteration. Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> Link: https://lore.kernel.org/r/20200622124110.20971-2-sumit.semwal@linaro.org Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
308e65ad06
commit
f7d7ad42a9
|
@ -2347,6 +2347,37 @@ static void _regulator_enable_delay(unsigned int delay)
|
|||
udelay(us);
|
||||
}
|
||||
|
||||
/**
|
||||
* _regulator_check_status_enabled
|
||||
*
|
||||
* A helper function to check if the regulator status can be interpreted
|
||||
* as 'regulator is enabled'.
|
||||
* @rdev: the regulator device to check
|
||||
*
|
||||
* Return:
|
||||
* * 1 - if status shows regulator is in enabled state
|
||||
* * 0 - if not enabled state
|
||||
* * Error Value - as received from ops->get_status()
|
||||
*/
|
||||
static inline int _regulator_check_status_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret = rdev->desc->ops->get_status(rdev);
|
||||
|
||||
if (ret < 0) {
|
||||
rdev_info(rdev, "get_status returned error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case REGULATOR_STATUS_OFF:
|
||||
case REGULATOR_STATUS_ERROR:
|
||||
case REGULATOR_STATUS_UNDEFINED:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int _regulator_do_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret, delay;
|
||||
|
@ -2407,7 +2438,37 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
|
|||
* together. */
|
||||
trace_regulator_enable_delay(rdev_get_name(rdev));
|
||||
|
||||
/* If poll_enabled_time is set, poll upto the delay calculated
|
||||
* above, delaying poll_enabled_time uS to check if the regulator
|
||||
* actually got enabled.
|
||||
* If the regulator isn't enabled after enable_delay has
|
||||
* expired, return -ETIMEDOUT.
|
||||
*/
|
||||
if (rdev->desc->poll_enabled_time) {
|
||||
unsigned int time_remaining = delay;
|
||||
|
||||
while (time_remaining > 0) {
|
||||
_regulator_enable_delay(rdev->desc->poll_enabled_time);
|
||||
|
||||
if (rdev->desc->ops->get_status) {
|
||||
ret = _regulator_check_status_enabled(rdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret)
|
||||
break;
|
||||
} else if (rdev->desc->ops->is_enabled(rdev))
|
||||
break;
|
||||
|
||||
time_remaining -= rdev->desc->poll_enabled_time;
|
||||
}
|
||||
|
||||
if (time_remaining <= 0) {
|
||||
rdev_err(rdev, "Enabled check timed out\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
} else {
|
||||
_regulator_enable_delay(delay);
|
||||
}
|
||||
|
||||
trace_regulator_enable_complete(rdev_get_name(rdev));
|
||||
|
||||
|
|
|
@ -305,6 +305,9 @@ enum regulator_type {
|
|||
* @enable_time: Time taken for initial enable of regulator (in uS).
|
||||
* @off_on_delay: guard time (in uS), before re-enabling a regulator
|
||||
*
|
||||
* @poll_enabled_time: The polling interval (in uS) to use while checking that
|
||||
* the regulator was actually enabled. Max upto enable_time.
|
||||
*
|
||||
* @of_map_mode: Maps a hardware mode defined in a DeviceTree to a standard mode
|
||||
*/
|
||||
struct regulator_desc {
|
||||
|
@ -372,6 +375,8 @@ struct regulator_desc {
|
|||
|
||||
unsigned int off_on_delay;
|
||||
|
||||
unsigned int poll_enabled_time;
|
||||
|
||||
unsigned int (*of_map_mode)(unsigned int mode);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue