diff options
author | CHLin <CHLin56@nuvoton.com> | 2020-09-28 10:19:43 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-10-05 10:07:41 +0000 |
commit | e6ca724f8b5e15a18bccf14c5905b3f1d8baf7c2 (patch) | |
tree | b69ce7c30a19297c151202a977ff317f8a5c8666 /chip/npcx/system-npcx7.c | |
parent | fe6577ffb515ef35af32a109e2b0832ea6a24018 (diff) | |
download | chrome-ec-e6ca724f8b5e15a18bccf14c5905b3f1d8baf7c2.tar.gz |
npcx: support enhanced PSL functions in npcx9
1. In npcx7, the PSL (hibernation) wakeup source only can come from
physical PSL_IN pins. In npcx9, the LCT (Long Countdown Timer)
module is introduced to support wakeup from a configurable timeout.
2. support PSL wakeup from the VCC1_RST pin. This function is disabled
by default and enabled (and locked) in the firmware in the npcx9 A1
chip. In the npcx9 A2 chip, this function is enabled (and locked)
by booter.
3. Support pulse mode and open drain (if pulse mode is enabled) for
PSL_OUT pin.
4. support one PSL general-purpose output pin which is powered by VSBY.
BRANCH=none
BUG=b:165777478
TEST=pass "make buildall"
TEST="hibernate 10", check EC wakes up from hibernate after 10 seconds.
make sure the reset cause in the console is "power-on hibernate
rtc-alarm"
TEST="hibernate"; check EC wakes up from hibernate after pressing
VCC1_RST button on the internal test board.
Test=configure the PSL_OUT to pulse mode and "hibernate"; cut off VCC1
power; check EC can wake up from hibernate with any input event.
Test=configure the level of PSL_GPO before hibernation; check the level
is kept after entering hibernation.
Signed-off-by: Wealian Liao <whliao@nuvoton.corp-partner.google.com>
Signed-off-by: CHLin <CHLin56@nuvoton.com>
Change-Id: I98ad41da8557222cf3d09fef9524880731cecde1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2435164
Tested-by: CH Lin <chlin56@nuvoton.com>
Reviewed-by: caveh jalali <caveh@chromium.org>
Commit-Queue: CH Lin <chlin56@nuvoton.com>
Diffstat (limited to 'chip/npcx/system-npcx7.c')
-rw-r--r-- | chip/npcx/system-npcx7.c | 83 |
1 files changed, 68 insertions, 15 deletions
diff --git a/chip/npcx/system-npcx7.c b/chip/npcx/system-npcx7.c index ffc64bee41..abbb6755c3 100644 --- a/chip/npcx/system-npcx7.c +++ b/chip/npcx/system-npcx7.c @@ -11,6 +11,7 @@ #include "cpu.h" #include "ec_commands.h" #include "hooks.h" +#include "lct_chip.h" #include "registers.h" #include "system.h" #include "task.h" @@ -40,16 +41,56 @@ void system_mpu_config(void) #error "Do not enable CONFIG_HIBERNATE_PSL if npcx ec doesn't support PSL mode!" #endif +static enum psl_pin_t system_gpio_to_psl(enum gpio_signal signal) +{ + enum psl_pin_t psl_no; + const struct gpio_info *g = gpio_list + signal; + + if (g->port == GPIO_PORT_D && g->mask == MASK_PIN2) /* GPIOD2 */ + psl_no = PSL_IN1; + else if (g->port == GPIO_PORT_0 && (g->mask & 0x07)) /* GPIO00/01/02 */ + psl_no = GPIO_MASK_TO_NUM(g->mask) + 1; + else + psl_no = PSL_NONE; + + return psl_no; +} + +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 +void system_set_psl_gpo(int level) +{ + if (level) + SET_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL); + else + CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PSL_GPO_CTL); +} +#endif + void system_enter_psl_mode(void) { /* Configure pins from GPIOs to PSL which rely on VSBY power rail. */ gpio_config_module(MODULE_PMU, 1); /* - * Only PSL_IN events can pull PSL_OUT to high and reboot ec. - * We should treat it as wake-up pin reset. + * In npcx7, only physical PSL_IN pins can pull PSL_OUT to high and + * reboot ec. + * In npcx9, LCT timeout event can also pull PSL_OUT. + * We won't decide the wake cause now but only mark we are entering + * hibernation via PSL. + * The actual wakeup cause will be checked by the PSL input event bits + * when ec reboots. */ - NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN; + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PSL; + +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + /* + * If pulse mode is enabled, the VCC power is turned off by the + * external component (Ex: PMIC) but PSL_OUT. So we can just return + * here. + */ + if (IS_BIT_SET(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_PLS_EN)) + return; +#endif /* * Pull PSL_OUT (GPIO85) to low to cut off ec's VCC power rail by @@ -67,34 +108,32 @@ noreturn void __keep __enter_hibernate_in_psl(void) ; } -static void system_psl_type_sel(int psl_no, uint32_t flags) +static void system_psl_type_sel(enum psl_pin_t psl_pin, uint32_t flags) { /* Set PSL input events' type as level or edge trigger */ if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) - CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); - else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) - SET_BIT(NPCX_GLUE_PSL_CTS, psl_no + 4); + CLEAR_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); + else if ((flags & GPIO_INT_F_RISING) || + (flags & GPIO_INT_F_FALLING)) + SET_BIT(NPCX_GLUE_PSL_CTS, psl_pin + 4); /* * Set PSL input events' polarity is low (high-to-low) active or * high (low-to-high) active */ if (flags & GPIO_HIB_WAKE_HIGH) - SET_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); + SET_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_pin); else - CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_no); + CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_D), 2 * psl_pin); } int system_config_psl_mode(enum gpio_signal signal) { - int psl_no; + enum psl_pin_t psl_no; const struct gpio_info *g = gpio_list + signal; - if (g->port == GPIO_PORT_D && g->mask == MASK_PIN2) /* GPIOD2 */ - psl_no = 0; - else if (g->port == GPIO_PORT_0 && (g->mask & 0x07)) /* GPIO00/01/02 */ - psl_no = GPIO_MASK_TO_NUM(g->mask) + 1; - else + psl_no = system_gpio_to_psl(signal); + if (psl_no == PSL_NONE) return 0; system_psl_type_sel(psl_no, g->flags); @@ -115,7 +154,11 @@ __enter_hibernate_in_last_block(void) * for better power consumption. */ NPCX_RAM_PD(0) = RAM_PD_MASK & 0xFF; +#if defined(CHIP_FAMILY_NPCX7) NPCX_RAM_PD(1) = (RAM_PD_MASK >> 8) & 0x0F; +#elif defined(CHIP_FAMILY_NPCX9) + NPCX_RAM_PD(1) = (RAM_PD_MASK >> 8) & 0x7F; +#endif /* Set deep idle mode */ NPCX_PMCSR = 0x6; @@ -131,6 +174,13 @@ __enter_hibernate_in_last_block(void) * no stack. */ NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_MTC; +#ifdef NPCX_LCT_SUPPORT + else if (IS_BIT_SET(NPCX_LCTSTAT, NPCX_LCTSTAT_EVST)) { + NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_LCT; + /* Clear LCT event */ + NPCX_LCTSTAT = BIT(NPCX_LCTSTAT_EVST); + } +#endif else /* Otherwise, we treat it as GPIOs wake-up */ NPCX_BBRAM(BBRM_DATA_INDEX_WAKE) = HIBERNATE_WAKE_PIN; @@ -173,6 +223,9 @@ static void report_psl_wake_source(void) return; CPRINTS("PSL_CTS: 0x%x", NPCX_GLUE_PSL_CTS & 0xf); +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + CPRINTS("PSL_MCTL1 event: 0x%x", NPCX_GLUE_PSL_MCTL1 & 0x18); +#endif } DECLARE_HOOK(HOOK_INIT, report_psl_wake_source, HOOK_PRIO_DEFAULT); #endif |