mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 10:31:02 +00:00
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>
This commit is contained in:
committed by
chrome-bot
parent
d68b1ca803
commit
e3336f4c8d
@@ -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);
|
||||
|
||||
@@ -388,6 +388,7 @@ enum {
|
||||
SLEEP_MASK_I2C_SLAVE = (1 << 7), /* I2C slave communication ongoing */
|
||||
SLEEP_MASK_FAN = (1 << 8), /* Fan control loop ongoing */
|
||||
SLEEP_MASK_USB_DEVICE = (1 << 9), /* Generic USB device in use */
|
||||
SLEEP_MASK_PWM = (1 << 10), /* PWM output is enabled */
|
||||
SLEEP_MASK_FORCE_NO_DSLEEP = (1 << 15), /* Force disable. */
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user