diff options
-rw-r--r-- | chip/npcx/build.mk | 4 | ||||
-rw-r--r-- | chip/npcx/config_chip-npcx9.h | 7 | ||||
-rw-r--r-- | chip/npcx/lct.c | 152 | ||||
-rw-r--r-- | chip/npcx/lct_chip.h | 22 | ||||
-rw-r--r-- | chip/npcx/registers-npcx9.h | 6 | ||||
-rw-r--r-- | chip/npcx/system-npcx7.c | 83 | ||||
-rw-r--r-- | chip/npcx/system.c | 127 | ||||
-rw-r--r-- | chip/npcx/system_chip.h | 19 | ||||
-rw-r--r-- | core/cortex-m/ec.lds.S | 2 | ||||
-rw-r--r-- | include/config.h | 22 | ||||
-rw-r--r-- | include/rtc.h | 5 |
11 files changed, 420 insertions, 29 deletions
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk index 61137f5856..4409c33c5d 100644 --- a/chip/npcx/build.mk +++ b/chip/npcx/build.mk @@ -43,6 +43,10 @@ chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o endif chip-$(CONFIG_PS2)+=ps2.o +# Only npcx9 or later chip family can support LCT module +ifneq ($(CHIP_FAMILY),$(filter $(CHIP_FAMILY),npcx5 npcx7)) +chip-y+=lct.o +endif # spi monitor program fw for openocd and UUT(UART Update Tool) npcx-monitor-fw=chip/npcx/spiflashfw/npcx_monitor diff --git a/chip/npcx/config_chip-npcx9.h b/chip/npcx/config_chip-npcx9.h index 597d334698..0f7f9ce179 100644 --- a/chip/npcx/config_chip-npcx9.h +++ b/chip/npcx/config_chip-npcx9.h @@ -46,6 +46,13 @@ /* Use SHI module version 2 supported by npcx7 and latter family */ #define NPCX_SHI_V2 +/* PSL_OUT optional configuration */ +/* Set PSL_OUT mode to pulse mode */ +#define NPCX_PSL_CFG_PSL_OUT_PULSE BIT(0) +/* set PSL_OUT to open-drain */ +#define NPCX_PSL_CFG_PSL_OUT_OD BIT(1) +#define CONFIG_HIBERNATE_PSL_OUT_FLAGS 0 + /*****************************************************************************/ /* Memory mapping */ diff --git a/chip/npcx/lct.c b/chip/npcx/lct.c new file mode 100644 index 0000000000..1df2628c4f --- /dev/null +++ b/chip/npcx/lct.c @@ -0,0 +1,152 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* LCT (Long Countdown Timer) module for Chrome EC */ +#include "lct_chip.h" +#include "console.h" +#include "hooks.h" +#include "registers.h" +#include "rtc.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +#define LCT_CLK_ENABLE_DELAY_USEC 150 +#define LCT_WEEKS_MAX 15 + +#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) +#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) + +void npcx_lct_sel_power_src(enum NPCX_LCT_PWR_SRC pwr_src) +{ + if (IS_BIT_SET(NPCX_LCTCONT, NPCX_LCTCONT_EN)) { + CPRINTS("Don't set power source when LCT is enabled"); + return; + } + + if (pwr_src == NPCX_LCT_PWR_SRC_VSBY) + SET_BIT(NPCX_LCTCONT, NPCX_LCTCONT_VSBY_PWR); + else + CLEAR_BIT(NPCX_LCTCONT, NPCX_LCTCONT_VSBY_PWR); +} + +void npcx_lct_enable_clk(uint8_t enable) +{ + if (IS_BIT_SET(NPCX_LCTCONT, NPCX_LCTCONT_EN)) { + CPRINTS("Don't set/unset clock when LCT is enabled"); + return; + } + + if (enable) { + SET_BIT(NPCX_LCTCONT, NPCX_LCTCONT_CLK_EN); + /* + * This bit must be set to 1 at least tLCTCKEN (150 us) + * before the LCT is enabled. + */ + udelay(LCT_CLK_ENABLE_DELAY_USEC); + } else { + CLEAR_BIT(NPCX_LCTCONT, NPCX_LCTCONT_CLK_EN); + } +} + +void npcx_lct_enable(uint8_t enable) +{ + enable = !!enable; + SET_FIELD(NPCX_LCTCONT, NPCX_LCTCONT_EN_FIELD, enable); + /* Wait until the bit value equals to what is set */ + while (IS_BIT_SET(NPCX_LCTCONT, NPCX_LCTCONT_EN) != enable) + ; +} + +void npcx_lct_config(int seconds, int psl_ena, int int_ena) +{ + if (IS_BIT_SET(NPCX_LCTCONT, NPCX_LCTCONT_EN)) { + CPRINTS("Don't config LCT when LCT is enabled"); + return; + } + + /* LCT can count max to (16 weeks - 1 second) */ + if (seconds >= (LCT_WEEKS_MAX + 1) * SECS_PER_WEEK) { + CPRINTS("LCT time is out of range"); + return; + } + + /* Clear pending LCT event first */ + NPCX_LCTSTAT = BIT(NPCX_LCTSTAT_EVST); + + NPCX_LCTWEEK = seconds / SECS_PER_WEEK; + seconds %= SECS_PER_WEEK; + NPCX_LCTDAY = seconds / SECS_PER_DAY; + seconds %= SECS_PER_DAY; + NPCX_LCTHOUR = seconds / SECS_PER_HOUR; + seconds %= SECS_PER_HOUR; + NPCX_LCTMINUTE = seconds / SECS_PER_MINUTE; + NPCX_LCTSECOND = seconds % SECS_PER_MINUTE; + + if (psl_ena) { + if (IS_BIT_SET(NPCX_LCTCONT, NPCX_LCTCONT_VSBY_PWR)) + SET_BIT(NPCX_LCTCONT, NPCX_LCTCONT_PSL_EN); + else + CPRINTS("LCT must source VSBY to support PSL wakeup"); + } + + if (int_ena) + SET_BIT(NPCX_LCTCONT, NPCX_LCTCONT_EVEN); + +} + +void npcx_lct_clear_event(void) +{ + NPCX_LCTSTAT = BIT(NPCX_LCTSTAT_EVST); +} + +int npcx_lct_is_event_set(void) +{ + return IS_BIT_SET(NPCX_LCTSTAT, NPCX_LCTSTAT_EVST); +} + +static void npcx_lct_init(void) +{ + /* Disable LCT */ + npcx_lct_enable(0); + /* Clear control and status registers */ + NPCX_LCTCONT = 0x0; + npcx_lct_clear_event(); + /* Clear all timer registers */ + NPCX_LCTSECOND = 0x0; + NPCX_LCTMINUTE = 0x0; + NPCX_LCTHOUR = 0x0; + NPCX_LCTDAY = 0x0; + NPCX_LCTWEEK = 0x0; +} +DECLARE_HOOK(HOOK_INIT, npcx_lct_init, HOOK_PRIO_DEFAULT); + +#ifdef CONFIG_CMD_RTC_ALARM +static int command_lctalarm(int argc, char **argv) +{ + char *e; + int seconds; + + seconds = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + + npcx_lct_enable(0); + npcx_lct_sel_power_src(NPCX_LCT_PWR_SRC_VSBY); + npcx_lct_enable_clk(1); + /* Enable LCT event interrupt and MIWU */ + npcx_lct_config(seconds, 0, 1); + task_disable_irq(NPCX_IRQ_LCT_WKINTF_2); + /* Enable wake-up input sources & clear pending bit */ + NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKINEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + task_enable_irq(NPCX_IRQ_LCT_WKINTF_2); + npcx_lct_enable(1); + + return 0; +} +DECLARE_CONSOLE_COMMAND(lctalarm, command_lctalarm, "", ""); +#endif diff --git a/chip/npcx/lct_chip.h b/chip/npcx/lct_chip.h new file mode 100644 index 0000000000..9e612f9e53 --- /dev/null +++ b/chip/npcx/lct_chip.h @@ -0,0 +1,22 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __CROS_EC_LCT_CHIP_H +#define __CROS_EC_LCT_CHIP_H +#include "registers.h" + +enum NPCX_LCT_PWR_SRC { + NPCX_LCT_PWR_SRC_VCC1, + NPCX_LCT_PWR_SRC_VSBY +}; + +void npcx_lct_config(int seconds, int psl_ena, int int_ena); +void npcx_lct_enable(uint8_t enable); +void npcx_lct_enable_clk(uint8_t enable); +void npcx_lct_sel_power_src(enum NPCX_LCT_PWR_SRC pwr_src); +void npcx_lct_clear_event(void); +int npcx_lct_is_event_set(void); + +#endif /* __CROS_EC_LCT_CHIP_H */ diff --git a/chip/npcx/registers-npcx9.h b/chip/npcx/registers-npcx9.h index bcbeed81ab..93236cb977 100644 --- a/chip/npcx/registers-npcx9.h +++ b/chip/npcx/registers-npcx9.h @@ -251,12 +251,6 @@ enum { #define NPCX_DEVALTG_PSL_OUT_SL 6 #define NPCX_DEVALTG_PSL_GPO_SL 7 -/* PSL optional flags */ -/* Set PSL_OUT mode to pulse mode */ -#define NPCX_PSL_PSL_OUT_PULSE BIT(0) -/* set PSL_OUT to open-drain */ -#define NPCX_PSL_PSL_OUT_OD BIT(1) - /* SMBus register fields */ #define NPCX_SMBSEL_SMB4SEL 4 #define NPCX_SMBSEL_SMB5SEL 5 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 diff --git a/chip/npcx/system.c b/chip/npcx/system.c index 91e7de8169..0930e8be0e 100644 --- a/chip/npcx/system.c +++ b/chip/npcx/system.c @@ -14,6 +14,7 @@ #include "hooks.h" #include "host_command.h" #include "hwtimer_chip.h" +#include "lct_chip.h" #include "registers.h" #include "rom_chip.h" #include "sib_chip.h" @@ -326,6 +327,38 @@ uint32_t chip_read_reset_flags(void) return bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS); } +static void chip_set_hib_flag(uint32_t *flags, uint32_t hib_wake_flags) +{ + /* Hibernate via PSL */ + if (hib_wake_flags & HIBERNATE_WAKE_PSL) { +#ifdef NPCX_LCT_SUPPORT + if (npcx_lct_is_event_set()) { + *flags |= EC_RESET_FLAG_RTC_ALARM | + EC_RESET_FLAG_HIBERNATE; + npcx_lct_clear_event(); + return; + } +#endif + *flags |= EC_RESET_FLAG_WAKE_PIN | + EC_RESET_FLAG_HIBERNATE; + } else { /* Hibernate via non-PSL */ +#ifdef NPCX_LCT_SUPPORT + if (hib_wake_flags & HIBERNATE_WAKE_LCT) { + *flags |= EC_RESET_FLAG_RTC_ALARM | + EC_RESET_FLAG_HIBERNATE; + return; + } +#endif + if (hib_wake_flags & HIBERNATE_WAKE_PIN) { + *flags |= EC_RESET_FLAG_WAKE_PIN | + EC_RESET_FLAG_HIBERNATE; + } else if (hib_wake_flags & HIBERNATE_WAKE_MTC) { + *flags |= EC_RESET_FLAG_RTC_ALARM | + EC_RESET_FLAG_HIBERNATE; + } + } +} + static void check_reset_cause(void) { uint32_t hib_wake_flags = bbram_data_read(BBRM_DATA_INDEX_WAKE); @@ -421,11 +454,7 @@ static void check_reset_cause(void) SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS); } - /* Reset by hibernate */ - if (hib_wake_flags & HIBERNATE_WAKE_PIN) - flags |= EC_RESET_FLAG_WAKE_PIN | EC_RESET_FLAG_HIBERNATE; - else if (hib_wake_flags & HIBERNATE_WAKE_MTC) - flags |= EC_RESET_FLAG_RTC_ALARM | EC_RESET_FLAG_HIBERNATE; + chip_set_hib_flag(&flags, hib_wake_flags); /* Watchdog Reset */ if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) { @@ -488,6 +517,32 @@ static void system_set_gpios_and_wakeup_inputs_hibernate(void) } } +#ifdef NPCX_LCT_SUPPORT +static void system_set_lct_alarm(uint32_t seconds, uint32_t microseconds) +{ + /* The min resolution of LCT is 1 seconds */ + if ((seconds == 0) && (microseconds != 0)) + seconds = 1; + + npcx_lct_enable(0); + npcx_lct_sel_power_src(NPCX_LCT_PWR_SRC_VSBY); +#ifdef CONFIG_HIBERNATE_PSL + /* Enable LCT event to PSL */ + npcx_lct_config(seconds, 1, 0); +#else + /* Enable LCT event interrupt and MIWU */ + npcx_lct_config(seconds, 0, 1); + task_disable_irq(NPCX_IRQ_LCT_WKINTF_2); + /* Enable wake-up input sources & clear pending bit */ + NPCX_WKPCL(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKINEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + NPCX_WKEN(MIWU_TABLE_2, LCT_WUI_GROUP) |= LCT_WUI_MASK; + task_enable_irq(NPCX_IRQ_LCT_WKINTF_2); +#endif + npcx_lct_enable(1); +} +#endif + /** * hibernate function for npcx ec. * @@ -502,6 +557,14 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) NPCX_ADCCNF = 0; usleep(1000); +#ifdef NPCX_LCT_SUPPORT + /* + * This function must be called before the ITIM (system tick) + * is disabled because it calls udelay inside this function + */ + npcx_lct_enable_clk(1); +#endif + /* Set SPI pins to be in Tri-State */ SET_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS); @@ -554,8 +617,11 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) * next event. */ if (seconds || microseconds) +#ifdef NPCX_LCT_SUPPORT + system_set_lct_alarm(seconds, microseconds); +#else system_set_rtc_alarm(seconds, microseconds); - +#endif /* execute hibernate func depend on chip series */ __hibernate_npcx_series(); @@ -792,6 +858,55 @@ void system_pre_init(void) #ifdef CONFIG_CHIP_PANIC_BACKUP chip_panic_data_restore(); #endif + +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 + if (IS_ENABLED(CONFIG_HIBERNATE_PSL)) { + uint8_t opt_flag = CONFIG_HIBERNATE_PSL_OUT_FLAGS; + + /* PSL Glitch Protection */ + SET_BIT(NPCX_GLUE_PSL_MCTL2, NPCX_GLUE_PSL_MCTL2_PSL_GP_EN); + + /* + * TODO: Remove this when NPCX9 A2 chip is available because A2 + * chip will enable VCC1_RST to PSL wakeup source and lock it in + * the booter. + */ + if (IS_ENABLED(CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP)) { + /* + * Enable VCC1_RST as the wake-up source from + * hibernation. + */ + SET_BIT(NPCX_GLUE_PSL_MCTL1, + NPCX_GLUE_PSL_MCTL1_VCC1_RST_PSL); + /* Disable VCC_RST Pull-Up */ + SET_BIT(NPCX_DEVALT(ALT_GROUP_G), + NPCX_DEVALTG_VCC1_RST_PUD); + /* + * Lock this bit itself and VCC1_RST_PSL in the + * PSL_MCTL1 register to read-only. + */ + SET_BIT(NPCX_GLUE_PSL_MCTL2, + NPCX_GLUE_PSL_MCTL2_VCC1_RST_PSL_LK); + } + + /* Don't set PSL_OUT to open-drain if it is the level mode */ + ASSERT((opt_flag & NPCX_PSL_CFG_PSL_OUT_PULSE) || + !(opt_flag & NPCX_PSL_CFG_PSL_OUT_OD)); + + if (opt_flag & NPCX_PSL_CFG_PSL_OUT_OD) + SET_BIT(NPCX_GLUE_PSL_MCTL1, NPCX_GLUE_PSL_MCTL1_OD_EN); + else + CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, + NPCX_GLUE_PSL_MCTL1_OD_EN); + + if (opt_flag & NPCX_PSL_CFG_PSL_OUT_PULSE) + SET_BIT(NPCX_GLUE_PSL_MCTL1, + NPCX_GLUE_PSL_MCTL1_PLS_EN); + else + CLEAR_BIT(NPCX_GLUE_PSL_MCTL1, + NPCX_GLUE_PSL_MCTL1_PLS_EN); + } +#endif } void system_reset(int flags) diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h index da98888787..db2351cf33 100644 --- a/chip/npcx/system_chip.h +++ b/chip/npcx/system_chip.h @@ -11,6 +11,13 @@ /* Flags for BBRM_DATA_INDEX_WAKE */ #define HIBERNATE_WAKE_MTC BIT(0) /* MTC alarm */ #define HIBERNATE_WAKE_PIN BIT(1) /* Wake pin */ +#define HIBERNATE_WAKE_LCT BIT(2) /* LCT alarm */ +/* + * Indicate that EC enters hibernation via PSL. When EC wakes up from + * hibernation and this flag is set, it will check the related status bit to + * know the actual wake up source. (From LCT or physical wakeup pins) + */ +#define HIBERNATE_WAKE_PSL BIT(3) /* Indices for battery-backed ram (BBRAM) data position */ enum bbram_data_index { @@ -30,6 +37,14 @@ enum bbram_data_index { BBRM_DATA_INDEX_PANIC_BKUP = 36, /* Panic data (index 35-63)*/ }; +enum psl_pin_t { + PSL_IN1, + PSL_IN2, + PSL_IN3, + PSL_IN4, + PSL_NONE, +}; + /* Issue a watchdog reset */ void system_watchdog_reset(void); @@ -79,4 +94,8 @@ extern unsigned int __after_init_end; #endif +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9 +void system_set_psl_gpo(int level); +#endif + #endif /* __CROS_EC_SYSTEM_CHIP_H */ diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S index 2314156294..fc24d181b5 100644 --- a/core/cortex-m/ec.lds.S +++ b/core/cortex-m/ec.lds.S @@ -161,7 +161,7 @@ SECTIONS . = ALIGN(4); STRINGIFY(OUTDIR/core/CORE/init.o) (.text) -#if defined(CHIP_FAMILY_NPCX7) && !defined(CONFIG_HIBERNATE_PSL) +#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7 && !defined(CONFIG_HIBERNATE_PSL) /* Keep hibernate utility in last code ram block */ . = ALIGN(4); KEEP(*(.after_init)) diff --git a/include/config.h b/include/config.h index 057046517d..2a5f86377d 100644 --- a/include/config.h +++ b/include/config.h @@ -2241,6 +2241,28 @@ /* Wake up pins have non-const configuration. */ #undef CONFIG_HIBERNATE_WAKE_PINS_DYNAMIC +/* In npcx9 and later chips, enhanced PSL features are supported including: + * (1) Pulse mode for PSL_OUT signal. + * (2) Open-drain for PSL_OUT signal (when Pulse mode is enabled.) + * These features can be enabled in board configuration file by adding + * the following bit masks to this flag: + * (1) NPCX_PSL_CFG_PSL_OUT_PULSE. + * (2) NPCX_PSL_CFG_PSL_OUT_OD. + * Ex: #define CONFIG_HIBERNATE_PSL_OUT_FLAGS \ + (NPCX_PSL_CFG_PSL_OUT_PULSE | NPCX_PSL_CFG_PSL_OUT_OD) + */ +#undef CONFIG_HIBERNATE_PSL_OUT_FLAGS + +/* + * Enable VCC1_RST pin as the input of PSL wakeup source. When Enabling this, + * the VCC1_RST pin must be connected to the VSBY supply via an external pull-up + * resistor of maximum 100K ohm . + * TODO: Remove this when NPCX9 A2 chip is available because A2 + * chip will enable VCC1_RST to PSL wakeup source and lock it in + * the booter. + */ +#undef CONFIG_HIBERNATE_PSL_VCC1_RST_WAKEUP + /* * Chip supports a 64-bit hardware timer and implements * __hw_clock_source_read64 and __hw_clock_source_set64. diff --git a/include/rtc.h b/include/rtc.h index c9909bbc48..cff1ee0f64 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -10,7 +10,10 @@ #include "common.h" -#define SECS_PER_DAY (60 * 60 * 24) +#define SECS_PER_MINUTE 60 +#define SECS_PER_HOUR (60 * SECS_PER_MINUTE) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) +#define SECS_PER_WEEK (7 * SECS_PER_DAY) #define SECS_PER_YEAR (365 * SECS_PER_DAY) /* The seconds elapsed from 01-01-1970 to 01-01-2000 */ #define SECS_TILL_YEAR_2K (946684800) |