diff options
author | Nicolas Boichat <drinkcat@google.com> | 2017-06-20 09:07:52 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-07-04 06:51:01 -0700 |
commit | e3336f4c8d4fb59137d35f87f4a42d22848aabcd (patch) | |
tree | bd4f65f658a76c2e80c3c868880cae24ecaa6dda /chip/stm32/pwm.c | |
parent | d68b1ca803a200bc30c1baa0552f6e4a4fcf72fd (diff) | |
download | chrome-ec-e3336f4c8d4fb59137d35f87f4a42d22848aabcd.tar.gz |
chip/stm32/pwm: Prevent sleeping while PWM output is active
STM32F0 cannot keep PWM output active when chip is in deep sleep.
The only other board that uses both CONFIG_LOW_POWER_IDLE
and CONFIG_PWM on stm32 is jerry, and this logic should also apply
to it.
Also, switch using_pwm from array to bitmask to simplify handling.
BRANCH=none
BUG=b:36173380
TEST=On AP, tell it to autosuspend hammer:
echo auto > /sys/bus/usb/devices/1-2/power/control
Then see, using idlestats, that hammer does to deep sleep.
In hammer console: pwm 0 50, see that PWM output is stable,
idlestats shows EC does not sleep.
In hammer console: pwm 0 -1, idlestats shows EC sleeps again.
Change-Id: Ic74c1905364fe4335239da95a99193d0e3e979f7
Reviewed-on: https://chromium-review.googlesource.com/541115
Commit-Ready: Nicolas Boichat <drinkcat@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'chip/stm32/pwm.c')
-rw-r--r-- | chip/stm32/pwm.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/chip/stm32/pwm.c b/chip/stm32/pwm.c index aa5149b074..ce2f8636f6 100644 --- a/chip/stm32/pwm.c +++ b/chip/stm32/pwm.c @@ -12,9 +12,11 @@ #include "pwm.h" #include "pwm_chip.h" #include "registers.h" +#include "system.h" #include "util.h" -static int using_pwm[PWM_CH_COUNT]; +/* Bitmap of currently active PWM channels. 1 bit per channel. */ +static uint32_t using_pwm; void pwm_set_duty(enum pwm_channel ch, int percent) { @@ -41,7 +43,7 @@ static void pwm_configure(enum pwm_channel ch) int frequency = pwm->frequency ? pwm->frequency : 100; uint16_t ccer; - if (using_pwm[ch]) + if (using_pwm & (1 << ch)) return; /* Enable timer */ @@ -96,7 +98,10 @@ static void pwm_configure(enum pwm_channel ch) /* Enable auto-reload preload, start counting */ tim->cr1 |= (1 << 7) | (1 << 0); - using_pwm[ch] = 1; + atomic_or(&using_pwm, 1 << ch); + + /* Prevent sleep */ + disable_sleep(SLEEP_MASK_PWM); } static void pwm_disable(enum pwm_channel ch) @@ -104,7 +109,7 @@ static void pwm_disable(enum pwm_channel ch) const struct pwm_t *pwm = pwm_channels + ch; timer_ctlr_t *tim = (timer_ctlr_t *)(pwm->tim.base); - if (using_pwm[ch] == 0) + if ((using_pwm & (1 << ch)) == 0) return; /* Main output disable */ @@ -116,7 +121,14 @@ static void pwm_disable(enum pwm_channel ch) /* Disable timer clock */ __hw_timer_enable_clock(pwm->tim.id, 0); - using_pwm[ch] = 0; + /* Allow sleep */ + enable_sleep(SLEEP_MASK_PWM); + + atomic_clear(&using_pwm, 1 << ch); + + /* Unless another PWM is active... Then prevent sleep */ + if (using_pwm) + disable_sleep(SLEEP_MASK_PWM); } void pwm_enable(enum pwm_channel ch, int enabled) @@ -129,12 +141,12 @@ void pwm_enable(enum pwm_channel ch, int enabled) int pwm_get_enabled(enum pwm_channel ch) { - return using_pwm[ch]; + return using_pwm & (1 << ch); } static void pwm_reconfigure(enum pwm_channel ch) { - using_pwm[ch] = 0; + atomic_clear(&using_pwm, 1 << ch); pwm_configure(ch); } @@ -145,7 +157,7 @@ static void pwm_freq_change(void) { int i; for (i = 0; i < PWM_CH_COUNT; ++i) - if (using_pwm[i]) + if (pwm_get_enabled(i)) pwm_reconfigure(i); } DECLARE_HOOK(HOOK_FREQ_CHANGE, pwm_freq_change, HOOK_PRIO_DEFAULT); |