summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2016-04-27 13:54:52 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-04-27 23:58:04 -0700
commitab27f42f5636af5fba50a871e391018cb1c885bf (patch)
treeb3c6e464b0b8e5a44b61c6e814220ef4293b0c92
parent8d742588ade84d45ce6fe7ca069d6087fac6928c (diff)
downloadchrome-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.c2
-rw-r--r--board/npcx_evb/board.c2
-rw-r--r--board/npcx_evb_arm/board.c2
-rw-r--r--chip/lm4/fan.c5
-rw-r--r--chip/mec1322/clock.c18
-rw-r--r--chip/mec1322/pwm.c20
-rw-r--r--chip/mec1322/pwm_chip.h5
-rw-r--r--chip/mec1322/registers.h5
-rw-r--r--chip/npcx/pwm.c10
-rw-r--r--chip/npcx/pwm_chip.h8
-rw-r--r--include/config.h6
-rw-r--r--include/pwm.h5
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 */