summaryrefslogtreecommitdiff
path: root/chip/stm32/pwm.c
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-06-20 09:07:52 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-07-04 06:51:01 -0700
commite3336f4c8d4fb59137d35f87f4a42d22848aabcd (patch)
treebd4f65f658a76c2e80c3c868880cae24ecaa6dda /chip/stm32/pwm.c
parentd68b1ca803a200bc30c1baa0552f6e4a4fcf72fd (diff)
downloadchrome-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.c28
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);