提交 871f5650 编写于 作者: G Guodong Xu 提交者: Mark Brown

regulator: core: add guard delay between calling regulator_disable and _enable

Some regulator require a minimum delay between its disable and next enable.
This is to avoid damages when out-of-range frequent disable/enable of a
single regulator can bring to the regulator chip.

Add @off_on_delay to struct regulator_desc. Device drivers' can use this field
to set this guard time.

Add @last_off_jiffy to struct regulator_dev. When @off_on_delay is set by
driver, regulator core can store its last off (disable) time into this field.
Signed-off-by: NGuodong Xu <guodong.xu@linaro.org>
Signed-off-by: NMark Brown <broonie@linaro.org>
上级 79fd1141
...@@ -1813,6 +1813,31 @@ static int _regulator_do_enable(struct regulator_dev *rdev) ...@@ -1813,6 +1813,31 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
trace_regulator_enable(rdev_get_name(rdev)); trace_regulator_enable(rdev_get_name(rdev));
if (rdev->desc->off_on_delay) {
/* if needed, keep a distance of off_on_delay from last time
* this regulator was disabled.
*/
unsigned long start_jiffy = jiffies;
unsigned long intended, max_delay, remaining;
max_delay = usecs_to_jiffies(rdev->desc->off_on_delay);
intended = rdev->last_off_jiffy + max_delay;
if (time_before(start_jiffy, intended)) {
/* calc remaining jiffies to deal with one-time
* timer wrapping.
* in case of multiple timer wrapping, either it can be
* detected by out-of-range remaining, or it cannot be
* detected and we gets a panelty of
* _regulator_enable_delay().
*/
remaining = intended - start_jiffy;
if (remaining <= max_delay)
_regulator_enable_delay(
jiffies_to_usecs(remaining));
}
}
if (rdev->ena_pin) { if (rdev->ena_pin) {
ret = regulator_ena_gpio_ctrl(rdev, true); ret = regulator_ena_gpio_ctrl(rdev, true);
if (ret < 0) if (ret < 0)
...@@ -1925,6 +1950,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) ...@@ -1925,6 +1950,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
return ret; return ret;
} }
/* cares about last_off_jiffy only if off_on_delay is required by
* device.
*/
if (rdev->desc->off_on_delay)
rdev->last_off_jiffy = jiffies;
trace_regulator_disable_complete(rdev_get_name(rdev)); trace_regulator_disable_complete(rdev_get_name(rdev));
return 0; return 0;
......
...@@ -238,6 +238,7 @@ enum regulator_type { ...@@ -238,6 +238,7 @@ enum regulator_type {
* @bypass_val_off: Disabling value for control when using regmap set_bypass * @bypass_val_off: Disabling value for control when using regmap set_bypass
* *
* @enable_time: Time taken for initial enable of regulator (in uS). * @enable_time: Time taken for initial enable of regulator (in uS).
* @off_on_delay: guard time (in uS), before re-enabling a regulator
*/ */
struct regulator_desc { struct regulator_desc {
const char *name; const char *name;
...@@ -276,6 +277,8 @@ struct regulator_desc { ...@@ -276,6 +277,8 @@ struct regulator_desc {
unsigned int bypass_val_off; unsigned int bypass_val_off;
unsigned int enable_time; unsigned int enable_time;
unsigned int off_on_delay;
}; };
/** /**
...@@ -348,6 +351,9 @@ struct regulator_dev { ...@@ -348,6 +351,9 @@ struct regulator_dev {
struct regulator_enable_gpio *ena_pin; struct regulator_enable_gpio *ena_pin;
unsigned int ena_gpio_state:1; unsigned int ena_gpio_state:1;
/* time when this regulator was disabled last time */
unsigned long last_off_jiffy;
}; };
struct regulator_dev * struct regulator_dev *
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册