diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2016-04-27 13:54:52 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-04-27 23:58:04 -0700 |
commit | ab27f42f5636af5fba50a871e391018cb1c885bf (patch) | |
tree | b3c6e464b0b8e5a44b61c6e814220ef4293b0c92 | |
parent | 8d742588ade84d45ce6fe7ca069d6087fac6928c (diff) | |
download | chrome-ec-ab27f42f5636af5fba50a871e391018cb1c885bf.tar.gz |
pwm: Add PWM_CONFIG_DSLEEP config flag
Add PWM_CONFIG_DSLEEP PWM config flag, which can be set to keep a
channel active during low-power idle / deep sleep. Currently it's
supported by npcx and mec1322.
BUG=chrome-os-partner:52783
BRANCH=glados
TEST=Manual on chell w/ subsequent commit + CONFIG_LOW_POWER_S0. Verify
KB backlight does not flicker during idle.
Change-Id: Ib9df5879aaa7dfa5764de1583496de84d40d2bb5
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/341002
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Todd Broch <tbroch@chromium.org>
-rw-r--r-- | board/kevin/board.c | 2 | ||||
-rw-r--r-- | board/npcx_evb/board.c | 2 | ||||
-rw-r--r-- | board/npcx_evb_arm/board.c | 2 | ||||
-rw-r--r-- | chip/lm4/fan.c | 5 | ||||
-rw-r--r-- | chip/mec1322/clock.c | 18 | ||||
-rw-r--r-- | chip/mec1322/pwm.c | 20 | ||||
-rw-r--r-- | chip/mec1322/pwm_chip.h | 5 | ||||
-rw-r--r-- | chip/mec1322/registers.h | 5 | ||||
-rw-r--r-- | chip/npcx/pwm.c | 10 | ||||
-rw-r--r-- | chip/npcx/pwm_chip.h | 8 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/pwm.h | 5 |
12 files changed, 60 insertions, 28 deletions
diff --git a/board/kevin/board.c b/board/kevin/board.c index 6578049fab..79346b9203 100644 --- a/board/kevin/board.c +++ b/board/kevin/board.c @@ -69,7 +69,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { [PWM_CH_BKLIGHT] = { 2, 0, 10000 }, - [PWM_CH_LED] = { 3, PWM_CONFIG_DSLEEP_CLK, 100 }, + [PWM_CH_LED] = { 3, PWM_CONFIG_DSLEEP, 100 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c index dd30fa8d97..8a3d1b8c5d 100644 --- a/board/npcx_evb/board.c +++ b/board/npcx_evb/board.c @@ -45,7 +45,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_DSLEEP_CLK, 100}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_DSLEEP, 100}, [PWM_CH_KBLIGHT] = { 1, 0, 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/board/npcx_evb_arm/board.c b/board/npcx_evb_arm/board.c index 65e9256f96..09657b0384 100644 --- a/board/npcx_evb_arm/board.c +++ b/board/npcx_evb_arm/board.c @@ -45,7 +45,7 @@ BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); /******************************************************************************/ /* PWM channels. Must be in the exactly same order as in enum pwm_channel. */ const struct pwm_t pwm_channels[] = { - [PWM_CH_FAN] = { 0, PWM_CONFIG_DSLEEP_CLK, 100}, + [PWM_CH_FAN] = { 0, PWM_CONFIG_DSLEEP, 100}, [PWM_CH_KBLIGHT] = { 1, 0, 10000 }, }; BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); diff --git a/chip/lm4/fan.c b/chip/lm4/fan.c index 01f561433d..0153b275fc 100644 --- a/chip/lm4/fan.c +++ b/chip/lm4/fan.c @@ -177,13 +177,10 @@ void fan_channel_setup(int ch, unsigned int flags) static void fan_init(void) { -#ifdef CONFIG_PWM_DSLEEP - +#ifdef CONFIG_FAN_DSLEEP /* Enable the fan module and delay a few clocks */ clock_enable_peripheral(CGC_OFFSET_FAN, 0x1, CGC_MODE_ALL); - #else - /* Enable the fan module and delay a few clocks */ clock_enable_peripheral(CGC_OFFSET_FAN, 0x1, CGC_MODE_RUN | CGC_MODE_SLEEP); diff --git a/chip/mec1322/clock.c b/chip/mec1322/clock.c index 6a1674891e..a49d2362aa 100644 --- a/chip/mec1322/clock.c +++ b/chip/mec1322/clock.c @@ -11,6 +11,8 @@ #include "cpu.h" #include "hooks.h" #include "hwtimer.h" +#include "pwm.h" +#include "pwm_chip.h" #include "registers.h" #include "shared_mem.h" #include "system.h" @@ -181,6 +183,9 @@ static void system_reset_htimer_alarm(void) */ static void prepare_for_deep_sleep(void) { + uint32_t ec_slp_en = MEC1322_PCR_EC_SLP_EN | + MEC1322_PCR_EC_SLP_EN_SLEEP; + /* sysTick timer */ CPU_NVIC_ST_CTRL &= ~ST_ENABLE; CPU_NVIC_ST_CTRL &= ~ST_COUNTFLAG; @@ -199,14 +204,21 @@ static void prepare_for_deep_sleep(void) MEC1322_TMR16_CTL(0) &= ~1; MEC1322_PCR_CHIP_SLP_EN |= 0x3; - MEC1322_PCR_EC_SLP_EN |= MEC1322_PCR_EC_SLP_EN_SLEEP; +#ifdef CONFIG_PWM + if (pwm_get_keep_awake_mask()) + ec_slp_en &= ~pwm_get_keep_awake_mask(); + else +#endif + /* Disable 100 Khz clock */ + MEC1322_PCR_SLOW_CLK_CTL &= 0xFFFFFC00; + + MEC1322_PCR_EC_SLP_EN = ec_slp_en; MEC1322_PCR_HOST_SLP_EN |= MEC1322_PCR_HOST_SLP_EN_SLEEP; MEC1322_PCR_EC_SLP_EN2 |= MEC1322_PCR_EC_SLP_EN2_SLEEP; #ifndef CONFIG_POWER_S0IX MEC1322_LPC_ACT = 0x0; #endif - MEC1322_PCR_SLOW_CLK_CTL &= 0xFFFFFC00; MEC1322_PCR_SYS_SLP_CTL = 0x2; /* heavysleep 2 */ @@ -242,8 +254,6 @@ static void resume_from_deep_sleep(void) /* Enable LPC */ MEC1322_LPC_ACT |= 1; #endif - - MEC1322_PCR_SLOW_CLK_CTL = 0x1E0; } diff --git a/chip/mec1322/pwm.c b/chip/mec1322/pwm.c index 1643664855..0c3f97baa3 100644 --- a/chip/mec1322/pwm.c +++ b/chip/mec1322/pwm.c @@ -11,14 +11,25 @@ #include "registers.h" #include "util.h" +/* + * PWMs that must remain active in low-power idle - MEC1322_PCR_EC_SLP_EN + * bit mask. + */ +static uint32_t pwm_keep_awake_mask; + void pwm_enable(enum pwm_channel ch, int enabled) { int id = pwm_channels[ch].channel; - if (enabled) + if (enabled) { MEC1322_PWM_CFG(id) |= 0x1; - else + if (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP) + pwm_keep_awake_mask |= + MEC1322_PCR_EC_SLP_EN_PWM(id); + } else { MEC1322_PWM_CFG(id) &= ~0x1; + pwm_keep_awake_mask &= ~MEC1322_PCR_EC_SLP_EN_PWM(id); + } } int pwm_get_enabled(enum pwm_channel ch) @@ -44,6 +55,11 @@ int pwm_get_duty(enum pwm_channel ch) return MEC1322_PWM_ON(pwm_channels[ch].channel); } +inline uint32_t pwm_get_keep_awake_mask(void) +{ + return pwm_keep_awake_mask; +} + static void pwm_configure(int ch, int active_low, int clock_low) { /* diff --git a/chip/mec1322/pwm_chip.h b/chip/mec1322/pwm_chip.h index 8ffdbef5b6..c52f586291 100644 --- a/chip/mec1322/pwm_chip.h +++ b/chip/mec1322/pwm_chip.h @@ -18,4 +18,9 @@ struct pwm_t { extern const struct pwm_t pwm_channels[]; +/* + * Returns PWMs that must remain active in low-power idle - + * MEC1322_PCR_EC_SLP_EN bit mask. + */ +inline uint32_t pwm_get_keep_awake_mask(void); #endif /* __CROS_EC_PWM_CHIP_H */ diff --git a/chip/mec1322/registers.h b/chip/mec1322/registers.h index b7a814cd8c..c36e72b089 100644 --- a/chip/mec1322/registers.h +++ b/chip/mec1322/registers.h @@ -27,6 +27,11 @@ #define MEC1322_PCR_EC_SLP_EN REG32(MEC1322_PCR_BASE + 0x8) /* Command all blocks to sleep */ #define MEC1322_PCR_EC_SLP_EN_SLEEP 0xe0700ff7 +#define MEC1322_PCR_EC_SLP_EN_PWM(n) (1 << ((n) ? (19 + (n)) : 4)) +#define MEC1322_PCR_EC_SLP_EN_PWM3 (1 << 22) +#define MEC1322_PCR_EC_SLP_EN_PWM2 (1 << 21) +#define MEC1322_PCR_EC_SLP_EN_PWM1 (1 << 20) +#define MEC1322_PCR_EC_SLP_EN_PWM0 (1 << 4) /* Allow all blocks to request clocks */ #define MEC1322_PCR_EC_SLP_EN_WAKE (~0xe0700ff7) #define MEC1322_PCR_EC_CLK_REQ REG32(MEC1322_PCR_BASE + 0xc) diff --git a/chip/npcx/pwm.c b/chip/npcx/pwm.c index 7d3a548382..e99ed039c2 100644 --- a/chip/npcx/pwm.c +++ b/chip/npcx/pwm.c @@ -63,8 +63,12 @@ void pwm_set_freq(enum pwm_channel ch, uint32_t freq, uint32_t res) /* Disable PWM for module configuration */ pwm_enable(ch, 0); - /* Get PWM clock frequency */ - if (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP_CLK) + /* + * Get PWM clock frequency. Use internal 32K as PWM clock source if + * the PWM must be active during low-power idle. + */ + + if (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP) clock = INT_32K_CLOCK; else clock = clock_get_apb2_freq(); @@ -205,7 +209,7 @@ void pwm_config(enum pwm_channel ch) /* Select PWM clock source */ UPDATE_BIT(NPCX_PWMCTL(mdl), NPCX_PWMCTL_CKSEL, - (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP_CLK)); + (pwm_channels[ch].flags & PWM_CONFIG_DSLEEP)); /* Set PWM operation frequency */ pwm_set_freq(ch, pwm_channels[ch].freq, DUTY_CYCLE_RESOLUTION); diff --git a/chip/npcx/pwm_chip.h b/chip/npcx/pwm_chip.h index 530e221a1d..c73855916f 100644 --- a/chip/npcx/pwm_chip.h +++ b/chip/npcx/pwm_chip.h @@ -8,14 +8,6 @@ #ifndef __CROS_EC_PWM_CHIP_H #define __CROS_EC_PWM_CHIP_H -/* Optional npcx flags for PWM config table */ - -/** - * Use internal 32K as PWM clock source. - * It can keep PWM is active during ec enter deep idle. - */ -#define PWM_CONFIG_DSLEEP_CLK (1 << 31) - /* Data structure to define PWM channels. */ struct pwm_t { /* PWM channel ID */ diff --git a/include/config.h b/include/config.h index 9db99d5ddc..aab9952def 100644 --- a/include/config.h +++ b/include/config.h @@ -761,6 +761,9 @@ /* Number of cooling fans. Undef if none. */ #undef CONFIG_FANS +/* Support fan control while in low-power idle */ +#undef CONFIG_FAN_DSLEEP + /* * Replace the default fan_percent_to_rpm() function with a board-specific * implementation in board.c @@ -1468,9 +1471,6 @@ /* Support PWM control */ #undef CONFIG_PWM -/* Support PWM control while in low-power idle */ -#undef CONFIG_PWM_DSLEEP - /* Define clock input to PWM module. */ #undef CONFIG_PWM_INPUT_LFCLK diff --git a/include/pwm.h b/include/pwm.h index 39835012e9..08cea7e43a 100644 --- a/include/pwm.h +++ b/include/pwm.h @@ -51,5 +51,8 @@ int pwm_get_duty(enum pwm_channel ch); * addition to the primary output. */ #define PWM_CONFIG_COMPLEMENTARY_OUTPUT (1 << 3) - +/** + * PWM channel must stay active in low-power idle, if enabled. + */ +#define PWM_CONFIG_DSLEEP (1 << 4) #endif /* __CROS_EC_PWM_H */ |