diff options
author | Dino Li <dino.li@ite.com.tw> | 2015-10-20 16:55:43 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2015-10-25 04:34:36 -0700 |
commit | 19c1e9905db46b0a669d0af8848be3f28dcedf41 (patch) | |
tree | 865aa1fbaf88bf4ca44d31c040c6f1484cbef526 /chip | |
parent | 9acd84460e953dd793c9594b141ca7e38568820d (diff) | |
download | chrome-ec-19c1e9905db46b0a669d0af8848be3f28dcedf41.tar.gz |
it8380dev: fix clock module
1. Implement deep doze mode for CONFIG_LOW_POWER_IDLE.
Signed-off-by: Dino Li <dino.li@ite.com.tw>
BRANCH=none
BUG=none
TEST=test the following items in deep doze mode.
1. WUI interrupts wake-up OK. (For example, power button, lid,
uart rx, keyboard ksi, and so on)
2. LPC access interrupt wake-up OK.
3. Enabled Hook debug, no warning message received (48hrs).
Change-Id: I8702a112632cb6c1c0fa75d682badf272130a7d4
Reviewed-on: https://chromium-review.googlesource.com/307060
Commit-Ready: Dino Li <dino.li@ite.com.tw>
Tested-by: Dino Li <dino.li@ite.com.tw>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r-- | chip/it83xx/clock.c | 266 | ||||
-rw-r--r-- | chip/it83xx/config_chip.h | 1 | ||||
-rw-r--r-- | chip/it83xx/gpio.c | 12 | ||||
-rw-r--r-- | chip/it83xx/hwtimer.c | 43 | ||||
-rw-r--r-- | chip/it83xx/hwtimer_chip.h | 23 | ||||
-rw-r--r-- | chip/it83xx/intc.h | 2 | ||||
-rw-r--r-- | chip/it83xx/registers.h | 6 | ||||
-rw-r--r-- | chip/it83xx/uart.c | 22 |
8 files changed, 346 insertions, 29 deletions
diff --git a/chip/it83xx/clock.c b/chip/it83xx/clock.c index 4fe72245da..25c5dffd1b 100644 --- a/chip/it83xx/clock.c +++ b/chip/it83xx/clock.c @@ -8,15 +8,42 @@ #include "clock.h" #include "common.h" #include "console.h" +#include "hwtimer.h" +#include "hwtimer_chip.h" #include "registers.h" +#include "system.h" #include "task.h" #include "timer.h" +#include "uart.h" #include "util.h" /* Console output macros. */ #define CPUTS(outstr) cputs(CC_CLOCK, outstr) #define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) +#ifdef CONFIG_LOW_POWER_IDLE +#define SLEEP_SET_HTIMER_DELAY_USEC 250 +#define SLEEP_FTIMER_SKIP_USEC (HOOK_TICK_INTERVAL * 2) + +static timestamp_t sleep_mode_t0; +static timestamp_t sleep_mode_t1; +static int idle_doze_cnt; +static int idle_sleep_cnt; +static uint64_t total_idle_sleep_time_us; +static int allow_sleep; +/* + * Fixed amount of time to keep the console in use flag true after boot in + * order to give a permanent window in which the heavy sleep mode is not used. + */ +#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) +static int console_in_use_timeout_sec = 5; +static timestamp_t console_expire_time; + +/* clock source is 32.768KHz */ +#define TIMER_32P768K_CNT_TO_US(cnt) ((cnt) * 32768 / 1000) +#define TIMER_CNT_8M_32P768K(cnt) (((cnt) / 262) + 1) +#endif /*CONFIG_LOW_POWER_IDLE */ + static int freq; struct clock_gate_ctrl { @@ -49,6 +76,9 @@ void clock_init(void) /* Turn off auto clock gating. */ IT83XX_ECPM_AUTOCG = 0x00; + + /* Default doze mode */ + IT83XX_ECPM_PLLCTRL = EC_PLL_DOZE; } int clock_get_freq(void) @@ -100,3 +130,239 @@ void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) *reg |= reg_mask | tmp_mask; } + +#ifdef CONFIG_LOW_POWER_IDLE +void clock_refresh_console_in_use(void) +{ + /* Set console in use expire time. */ + console_expire_time = get_time(); + console_expire_time.val += console_in_use_timeout_sec * SECOND; +} + +static void clock_event_timer_clock_change(enum ext_timer_clock_source clock, + uint32_t count) +{ + IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) &= ~(1 << 0); + IT83XX_ETWD_ETXPSR(EVENT_EXT_TIMER) = clock; + IT83XX_ETWD_ETXCNTLR(EVENT_EXT_TIMER) = count; + IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) |= 0x3; +} + +static void clock_htimer_enable(void) +{ + uint32_t c; + + /* disable free running interrupt */ + task_disable_irq(et_ctrl_regs[FREE_EXT_TIMER_H].irq); + task_disable_irq(et_ctrl_regs[FREE_EXT_TIMER_L].irq); + /* change event timer clock source to 32.768 KHz */ + c = TIMER_CNT_8M_32P768K(IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER)); + clock_event_timer_clock_change(EXT_PSR_32P768K_HZ, c); +} + +static int clock_allow_low_power_idle(void) +{ + if (!(IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) & (1 << 0))) + return 0; + + if (*et_ctrl_regs[EVENT_EXT_TIMER].isr & + et_ctrl_regs[EVENT_EXT_TIMER].mask) + return 0; + + if (EVENT_TIMER_COUNT_TO_US(IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER)) < + SLEEP_SET_HTIMER_DELAY_USEC) + return 0; + + if (TIMER_L_COUNT_TO_US(IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_L)) < + SLEEP_SET_HTIMER_DELAY_USEC) + return 0; + + sleep_mode_t0 = get_time(); + if ((sleep_mode_t0.le.lo > (0xffffffff - SLEEP_FTIMER_SKIP_USEC)) || + (sleep_mode_t0.le.lo < SLEEP_FTIMER_SKIP_USEC)) + return 0; + + if (sleep_mode_t0.val < console_expire_time.val) + return 0; + + return 1; +} + +static void clock_ec_pll_ctrl(enum ec_pll_ctrl mode) +{ + IT83XX_ECPM_PLLCTRL = mode; +#ifdef CHIP_FAMILY_IT839X + /* for deep doze / sleep mode */ + IT83XX_ECPM_PLLCTRL = mode; +#endif + asm volatile ("dsb"); +} + +void clock_sleep_mode_wakeup_isr(void) +{ + uint32_t st_us, c; + + if (IT83XX_ECPM_PLLCTRL != EC_PLL_DOZE) { + clock_ec_pll_ctrl(EC_PLL_DOZE); + + /* update free running timer */ + c = 0xffffffff - IT83XX_ETWD_ETXCNTOR(LOW_POWER_EXT_TIMER); + st_us = TIMER_32P768K_CNT_TO_US(c); + sleep_mode_t1.val = sleep_mode_t0.val + st_us; + /* + * When TIMER_L underflow, and because the observation value + * equals to counter setting register, we need a window of + * 64us (at minimum) to reset the value of TIMER_L back to + * 0xfffff8(TIMER_L_COUNT_TO_US(0xffffffff)) + */ + c = TIMER_L_US_TO_COUNT(0xffffffff - sleep_mode_t1.le.lo); + if (TIMER_L_COUNT_TO_US(c) < 64) { + sleep_mode_t1.le.lo |= 0x3F; + sleep_mode_t1.le.lo &= ~(1 << 6); + } + __hw_clock_source_set(sleep_mode_t1.le.lo); + + /* reset event timer and clock source is 8 MHz */ + clock_event_timer_clock_change(EXT_PSR_8M_HZ, 0xffffffff); + task_clear_pending_irq(et_ctrl_regs[EVENT_EXT_TIMER].irq); + process_timers(0); + /* disable uart wui */ + uart_exit_dsleep(); + /* Record time spent in sleep. */ + total_idle_sleep_time_us += st_us; + } +} + +/** + * Low power idle task. Executed when no tasks are ready to be scheduled. + */ +void __idle(void) +{ + console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; + /* init hw timer and clock source is 32.768 KHz */ + ext_timer_ms(LOW_POWER_EXT_TIMER, EXT_PSR_32P768K_HZ, 1, 0, + 0xffffffff, 1, 1); + +#if defined(CONFIG_LPC) && defined(CONFIG_IT83XX_LPC_ACCESS_INT) + IT83XX_WUC_WUESR4 = 0xff; + task_clear_pending_irq(IT83XX_IRQ_WKINTAD); + /* bit2, wake-up enable for LPC access */ + IT83XX_WUC_WUENR4 |= (1 << 2); +#endif + /* + * Print when the idle task starts. This is the lowest priority task, + * so this only starts once all other tasks have gotten a chance to do + * their task inits and have gone to sleep. + */ + CPRINTS("low power idle task started"); + + while (1) { +#if defined(CONFIG_LPC) && defined(CONFIG_IT83XX_LPC_ACCESS_INT) + BRAM_LPC_ACCESS = LPC_ACCESS_INT_BUSY; + /* LPC access interrupt pending. */ + if (IT83XX_WUC_WUESR4 & (1 << 2)) { + task_enable_irq(IT83XX_IRQ_WKINTAD); + continue; + } + BRAM_LPC_ACCESS = 0; + task_enable_irq(IT83XX_IRQ_WKINTAD); +#endif + allow_sleep = 0; + if (DEEP_SLEEP_ALLOWED) + allow_sleep = clock_allow_low_power_idle(); + + if (allow_sleep) { + interrupt_disable(); + /* reset low power mode hw timer */ + IT83XX_ETWD_ETXCTRL(LOW_POWER_EXT_TIMER) |= (1 << 1); + sleep_mode_t0 = get_time(); + /* enable uart wui */ + uart_enter_dsleep(); + /* enable hw timer for deep doze / sleep mode wake-up */ + clock_htimer_enable(); + /* deep doze mode */ + clock_ec_pll_ctrl(EC_PLL_DEEP_DOZE); + interrupt_enable(); + /* standby instruction */ + asm("standby wake_grant"); + idle_sleep_cnt++; + } else { + /* doze mode */ + clock_ec_pll_ctrl(EC_PLL_DOZE); + /* standby instruction */ + asm("standby wake_grant"); + idle_doze_cnt++; + } + } +} +#endif /* CONFIG_LOW_POWER_IDLE */ + +#ifdef CONFIG_LOW_POWER_IDLE +/** + * Print low power idle statistics + */ +static int command_idle_stats(int argc, char **argv) +{ + timestamp_t ts = get_time(); + + ccprintf("Num idle calls that doze: %d\n", idle_doze_cnt); + ccprintf("Num idle calls that sleep: %d\n", idle_sleep_cnt); + + ccprintf("Total Time spent in sleep(sec): %.6ld(s)\n", + total_idle_sleep_time_us); + ccprintf("Total time on: %.6lds\n\n", ts.val); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, + "", + "Print last idle stats", + NULL); + +/** + * Configure deep sleep clock settings. + */ +static int command_dsleep(int argc, char **argv) +{ + int v; + + if (argc > 1) { + if (parse_bool(argv[1], &v)) { + /* + * Force deep sleep not to use heavy sleep mode or + * allow it to use the heavy sleep mode. + */ + if (v) /* 'on' */ + disable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); + else /* 'off' */ + enable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); + } else { + /* Set console in use timeout. */ + char *e; + + v = strtoi(argv[1], &e, 10); + if (*e) + return EC_ERROR_PARAM1; + + console_in_use_timeout_sec = v; + + /* Refresh console in use to use new timeout. */ + clock_refresh_console_in_use(); + } + } + + ccprintf("Sleep mask: %08x\n", sleep_mask); + ccprintf("Console in use timeout: %d sec\n", + console_in_use_timeout_sec); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, + "[ on | off | <timeout> sec]", + "Deep sleep clock settings:\n" + "Use 'on' to force deep sleep NOT to enter heavysleep mode.\n" + "Use 'off' to allow deep sleep to use heavysleep whenever\n" + "conditions allow.\n" + "Give a timeout value for the console in use timeout.\n" + "See also 'sleepmask'.", + NULL); +#endif /* CONFIG_LOW_POWER_IDLE */ diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h index 1e2d5c747a..4e43540a76 100644 --- a/chip/it83xx/config_chip.h +++ b/chip/it83xx/config_chip.h @@ -91,6 +91,7 @@ #define CONFIG_FW_RESET_VECTOR /* Optional features present on this chip */ +#define CHIP_FAMILY_IT83XX #define CONFIG_ADC #define CONFIG_EC2I #define CONFIG_I2C diff --git a/chip/it83xx/gpio.c b/chip/it83xx/gpio.c index b3d4d11945..063ed222fb 100644 --- a/chip/it83xx/gpio.c +++ b/chip/it83xx/gpio.c @@ -378,6 +378,18 @@ int gpio_disable_interrupt(enum gpio_signal signal) return EC_SUCCESS; } +int gpio_clear_pending_interrupt(enum gpio_signal signal) +{ + int irq = gpio_to_irq(gpio_list[signal].port, gpio_list[signal].mask); + + if (irq == -1) + return EC_ERROR_UNKNOWN; + + *(wuesr(gpio_irqs[irq].wuc_group)) = gpio_irqs[irq].wuc_mask; + task_clear_pending_irq(irq); + return EC_SUCCESS; +} + void gpio_pre_init(void) { const struct gpio_info *g = gpio_list; diff --git a/chip/it83xx/hwtimer.c b/chip/it83xx/hwtimer.c index 77354702b4..c0a3c29bba 100644 --- a/chip/it83xx/hwtimer.c +++ b/chip/it83xx/hwtimer.c @@ -56,52 +56,36 @@ * 8 MHz 32-bit timer to handle events. */ -#define TIMER_COUNT_1US_SHIFT 3 - -/* Combinational mode, microseconds to timer counter setting register */ -#define TIMER_H_US_TO_COUNT(us) ((us) >> (24 - TIMER_COUNT_1US_SHIFT)) -#define TIMER_L_US_TO_COUNT(us) (((us) << TIMER_COUNT_1US_SHIFT) & 0x00ffffff) - -/* Free running timer counter observation value to microseconds */ -#define TIMER_H_COUNT_TO_US(cnt) ((~(cnt)) << (24 - TIMER_COUNT_1US_SHIFT)) -#define TIMER_L_COUNT_TO_US(cnt) (((cnt) & 0x00ffffff) >> TIMER_COUNT_1US_SHIFT) - -/* Microseconds to event timer counter setting register */ -#define EVENT_TIMER_US_TO_COUNT(us) ((us) << TIMER_COUNT_1US_SHIFT) -/* Event timer counter observation value to microseconds */ -#define EVENT_TIMER_COUNT_TO_US(cnt) ((cnt) >> TIMER_COUNT_1US_SHIFT) - -#define TIMER_H_CNT_COMP TIMER_H_US_TO_COUNT(0xffffffff) -#define TIMER_L_CNT_COMP TIMER_L_US_TO_COUNT(0xffffffff) - #define MS_TO_COUNT(hz, ms) ((hz) * (ms) / 1000) const struct ext_timer_ctrl_t et_ctrl_regs[] = { - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, 0x08, + {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x08, IT83XX_IRQ_EXT_TIMER3}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, 0x10, + {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x10, IT83XX_IRQ_EXT_TIMER4}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, 0x20, + {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x20, IT83XX_IRQ_EXT_TIMER5}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, 0x40, + {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x40, IT83XX_IRQ_EXT_TIMER6}, - {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, 0x80, + {&IT83XX_INTC_IELMR19, &IT83XX_INTC_IPOLR19, &IT83XX_INTC_ISR19, 0x80, IT83XX_IRQ_EXT_TIMER7}, - {&IT83XX_INTC_IELMR10, &IT83XX_INTC_IPOLR10, 0x01, + {&IT83XX_INTC_IELMR10, &IT83XX_INTC_IPOLR10, &IT83XX_INTC_ISR10, 0x01, IT83XX_IRQ_EXT_TMR8}, }; BUILD_ASSERT(ARRAY_SIZE(et_ctrl_regs) == EXT_TIMER_COUNT); static void free_run_timer_config_counter(uint32_t us) { + /* bit0, timer stop */ + IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) &= ~(1 << 0); /* * microseconds to timer counter, * timer 3(TIMER_L) and 4(TIMER_H) combinational mode */ IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_H) = TIMER_H_US_TO_COUNT(us); IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_L) = TIMER_L_US_TO_COUNT(us); - /* bit1, timer re-start */ - IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) |= (1 << 1); + /* bit[0,1], timer start and reset */ + IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) |= 3; } static void free_run_timer_clear_pending_isr(void) @@ -174,9 +158,9 @@ void __hw_clock_source_set(uint32_t ts) ext_timer_ms(FREE_EXT_TIMER_L, EXT_PSR_8M_HZ, 1, 1, TIMER_L_US_TO_COUNT(start_us), 1, 1); } else { - free_run_timer_clear_pending_isr(); /* set timer counter only */ free_run_timer_config_counter(start_us); + free_run_timer_clear_pending_isr(); task_enable_irq(et_ctrl_regs[FREE_EXT_TIMER_H].irq); task_enable_irq(et_ctrl_regs[FREE_EXT_TIMER_L].irq); } @@ -282,10 +266,13 @@ static void __hw_clock_source_irq(void) * 0xfffff8(TIMER_L_COUNT_TO_US(0xffffffff)). */ if (IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_H)) { + /* bit0, timer stop */ + IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) &= ~(1 << 0); IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_L) = TIMER_L_US_TO_COUNT(0xffffffff); IT83XX_ETWD_ETXCNTLR(FREE_EXT_TIMER_H) -= 1; - IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) |= (1 << 1); + /* bit[0,1], timer start and reset */ + IT83XX_ETWD_ETXCTRL(FREE_EXT_TIMER_L) |= 3; update_exc_start_time(); } else { free_run_timer_overflow(); diff --git a/chip/it83xx/hwtimer_chip.h b/chip/it83xx/hwtimer_chip.h index 690505dcb1..18ee3f0f13 100644 --- a/chip/it83xx/hwtimer_chip.h +++ b/chip/it83xx/hwtimer_chip.h @@ -8,11 +8,30 @@ #ifndef __CROS_EC_HWTIMER_CHIP_H #define __CROS_EC_HWTIMER_CHIP_H +#define TIMER_COUNT_1US_SHIFT 3 + +/* Combinational mode, microseconds to timer counter setting register */ +#define TIMER_H_US_TO_COUNT(us) ((us) >> (24 - TIMER_COUNT_1US_SHIFT)) +#define TIMER_L_US_TO_COUNT(us) (((us) << TIMER_COUNT_1US_SHIFT) & 0x00ffffff) + +/* Free running timer counter observation value to microseconds */ +#define TIMER_H_COUNT_TO_US(cnt) ((~(cnt)) << (24 - TIMER_COUNT_1US_SHIFT)) +#define TIMER_L_COUNT_TO_US(cnt) (((cnt) & 0x00ffffff) >> TIMER_COUNT_1US_SHIFT) + +/* Microseconds to event timer counter setting register */ +#define EVENT_TIMER_US_TO_COUNT(us) ((us) << TIMER_COUNT_1US_SHIFT) +/* Event timer counter observation value to microseconds */ +#define EVENT_TIMER_COUNT_TO_US(cnt) ((cnt) >> TIMER_COUNT_1US_SHIFT) + +#define TIMER_H_CNT_COMP TIMER_H_US_TO_COUNT(0xffffffff) +#define TIMER_L_CNT_COMP TIMER_L_US_TO_COUNT(0xffffffff) + #define FREE_EXT_TIMER_L EXT_TIMER_3 #define FREE_EXT_TIMER_H EXT_TIMER_4 #define FAN_CTRL_EXT_TIMER EXT_TIMER_5 #define EVENT_EXT_TIMER EXT_TIMER_6 #define WDT_EXT_TIMER EXT_TIMER_7 +#define LOW_POWER_EXT_TIMER EXT_TIMER_8 enum ext_timer_clock_source { EXT_PSR_32P768K_HZ = 0, @@ -35,7 +54,7 @@ enum ext_timer_sel { EXT_TIMER_6, /* For WDT capture important state information before being reset */ EXT_TIMER_7, - /* reserved */ + /* HW timer for low power mode */ EXT_TIMER_8, EXT_TIMER_COUNT, }; @@ -43,6 +62,7 @@ enum ext_timer_sel { struct ext_timer_ctrl_t { volatile uint8_t *mode; volatile uint8_t *polarity; + volatile uint8_t *isr; uint8_t mask; uint8_t irq; }; @@ -52,6 +72,7 @@ void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq); void ext_timer_stop(enum ext_timer_sel ext_timer, int dis_irq); void fan_ext_timer_interrupt(void); void update_exc_start_time(void); + /** * Config a external timer. * diff --git a/chip/it83xx/intc.h b/chip/it83xx/intc.h index 6734436fdc..39d8653819 100644 --- a/chip/it83xx/intc.h +++ b/chip/it83xx/intc.h @@ -18,5 +18,7 @@ void pm5_ibf_interrupt(void); void lpcrst_interrupt(enum gpio_signal signal); void peci_interrupt(void); void i2c_interrupt(int port); +int gpio_clear_pending_interrupt(enum gpio_signal signal); +void clock_sleep_mode_wakeup_isr(void); #endif /* __CROS_EC_INTC_H */ diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index e8a5821ad5..df1339b241 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -581,6 +581,12 @@ enum { #define IT83XX_ECPM_CGCTRL4R_OFF 0x09 #define IT83XX_ECPM_PLLCTRL REG8(IT83XX_ECPM_BASE+0x03) +enum ec_pll_ctrl { + EC_PLL_DOZE = 0, + EC_PLL_SLEEP = 1, + EC_PLL_DEEP_DOZE = 3, +}; + #define IT83XX_ECPM_AUTOCG REG8(IT83XX_ECPM_BASE+0x04) #define IT83XX_ECPM_PLLFREQR REG8(IT83XX_ECPM_BASE+0x06) #define IT83XX_ECPM_PLLCSS REG8(IT83XX_ECPM_BASE+0x08) diff --git a/chip/it83xx/uart.c b/chip/it83xx/uart.c index a396e76316..4d8f9cbe98 100644 --- a/chip/it83xx/uart.c +++ b/chip/it83xx/uart.c @@ -9,6 +9,7 @@ #include "common.h" #include "console.h" #include "gpio.h" +#include "intc.h" #include "registers.h" #include "system.h" #include "task.h" @@ -178,6 +179,27 @@ static void host_uart_config(void) } #endif +#ifdef CONFIG_LOW_POWER_IDLE +void uart_enter_dsleep(void) +{ + gpio_clear_pending_interrupt(GPIO_UART1_RX); + gpio_enable_interrupt(GPIO_UART1_RX); +} + +void uart_exit_dsleep(void) +{ + gpio_disable_interrupt(GPIO_UART1_RX); + gpio_clear_pending_interrupt(GPIO_UART1_RX); +} + +void uart_deepsleep_interrupt(enum gpio_signal signal) +{ + clock_refresh_console_in_use(); + /* Disable interrupts on UART1 RX pin to avoid repeated interrupts. */ + gpio_disable_interrupt(GPIO_UART1_RX); +} +#endif /* CONFIG_LOW_POWER_IDLE */ + void uart_init(void) { /* reset uart before config it */ |