diff options
Diffstat (limited to 'chip')
-rw-r--r-- | chip/lm4/adc.c | 6 | ||||
-rw-r--r-- | chip/lm4/clock.c | 514 | ||||
-rw-r--r-- | chip/lm4/config_chip.h | 8 | ||||
-rw-r--r-- | chip/lm4/eeprom.c | 6 | ||||
-rw-r--r-- | chip/lm4/gpio.c | 62 | ||||
-rw-r--r-- | chip/lm4/hwtimer.c | 9 | ||||
-rw-r--r-- | chip/lm4/i2c.c | 4 | ||||
-rw-r--r-- | chip/lm4/jtag.c | 30 | ||||
-rw-r--r-- | chip/lm4/lpc.c | 6 | ||||
-rw-r--r-- | chip/lm4/peci.c | 22 | ||||
-rw-r--r-- | chip/lm4/pwm_fan.c | 4 | ||||
-rw-r--r-- | chip/lm4/registers.h | 50 | ||||
-rw-r--r-- | chip/lm4/spi.c | 8 | ||||
-rw-r--r-- | chip/lm4/system.c | 224 | ||||
-rw-r--r-- | chip/lm4/uart.c | 97 | ||||
-rw-r--r-- | chip/lm4/watchdog.c | 8 | ||||
-rw-r--r-- | chip/stm32/clock-stm32f.c | 44 | ||||
-rw-r--r-- | chip/stm32/clock-stm32l.c | 10 | ||||
-rw-r--r-- | chip/stm32/uart.c | 1 |
19 files changed, 184 insertions, 929 deletions
diff --git a/chip/lm4/adc.c b/chip/lm4/adc.c index 1456ba996b..17f3d26191 100644 --- a/chip/lm4/adc.c +++ b/chip/lm4/adc.c @@ -203,9 +203,9 @@ static void adc_init(void) */ clock_enable_pll(1, 0); - /* Enable ADC0 module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_ADC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable ADC0 module and delay a few clocks. */ + LM4_SYSTEM_RCGCADC = 1; + clock_wait_cycles(3); /* * Use external voltage references (VREFA+, VREFA-) instead of diff --git a/chip/lm4/clock.c b/chip/lm4/clock.c index 1d58e59e3d..02f955776e 100644 --- a/chip/lm4/clock.c +++ b/chip/lm4/clock.c @@ -11,46 +11,15 @@ #include "cpu.h" #include "gpio.h" #include "hooks.h" -#include "hwtimer.h" #include "registers.h" #include "system.h" #include "task.h" #include "timer.h" -#include "uart.h" #include "util.h" #include "watchdog.h" -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) - #define PLL_CLOCK 66666667 /* System clock = 200MHz PLL/3 = 66.667MHz */ -/* - * Length of time for the processor to wake up from deep sleep. Actual - * measurement gives anywhere up to 780us, depending on the mode it is coming - * out of. The datasheet gives a maximum of 846us, for coming out of deep - * sleep in our worst case deep sleep mode. - */ -#define DEEP_SLEEP_RECOVER_TIME_USEC 850 - -/* Low power idle statistics */ -#ifdef CONFIG_LOW_POWER_IDLE -static int idle_sleep_cnt; -static int idle_dsleep_cnt; -static uint64_t idle_dsleep_time_us; -static int dsleep_recovery_margin_us = 1000000; - -/* - * Fixed amount of time to keep the console in use flag true after boot in - * order to give a permanent window in which the low speed clock is not used. - */ -#define CONSOLE_IN_USE_ON_BOOT_TIME (15*SECOND) - -static int console_in_use_timeout_sec = 60; -static timestamp_t console_expire_time; -#endif - static int freq; /** @@ -64,17 +33,6 @@ static void disable_pll(void) LM4_SYSTEM_RCC_PWRDN | LM4_SYSTEM_RCC_OSCSRC(1) | LM4_SYSTEM_RCC_MOSCDIS; - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * If using the low power idle, then set the ACG bit, which specifies - * that the sleep and deep sleep modes are using their own clock gating - * registers SCGC and DCGS respectively instead of using the run mode - * clock gating registers RCGC. - */ - LM4_SYSTEM_RCC |= LM4_SYSTEM_RCC_ACG; -#endif - LM4_SYSTEM_RCC2 &= ~LM4_SYSTEM_RCC2_USERCC2; freq = INTERNAL_CLOCK; @@ -98,16 +56,6 @@ static void enable_pll(void) LM4_SYSTEM_RCC_OSCSRC(1) | LM4_SYSTEM_RCC_MOSCDIS; -#ifdef CONFIG_LOW_POWER_IDLE - /* - * If using the low power idle, then set the ACG bit, which specifies - * that the sleep and deep sleep modes are using their own clock gating - * registers SCGC and DCGS respectively instead of using the run mode - * clock gating registers RCGC. - */ - LM4_SYSTEM_RCC |= LM4_SYSTEM_RCC_ACG; -#endif - /* Wait for the PLL to lock */ clock_wait_cycles(1024); while (!(LM4_SYSTEM_PLLSTAT & 1)) @@ -180,212 +128,6 @@ void clock_init(void) disable_pll(); } -void clock_enable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) -{ - if (mode & CGC_MODE_RUN) - *(LM4_SYSTEM_RCGC_BASE + offset) |= mask; - - if (mode & CGC_MODE_SLEEP) - *(LM4_SYSTEM_SCGC_BASE + offset) |= mask; - - if (mode & CGC_MODE_DSLEEP) - *(LM4_SYSTEM_DCGC_BASE + offset) |= mask; - - /* Wait for clock change to take affect. */ - clock_wait_cycles(3); -} - -void clock_disable_peripheral(uint32_t offset, uint32_t mask, uint32_t mode) -{ - if (mode & CGC_MODE_RUN) - *(LM4_SYSTEM_RCGC_BASE + offset) &= ~mask; - - if (mode & CGC_MODE_SLEEP) - *(LM4_SYSTEM_SCGC_BASE + offset) &= ~mask; - - if (mode & CGC_MODE_DSLEEP) - *(LM4_SYSTEM_DCGC_BASE + offset) &= ~mask; -} - -/* - * The low power idle task does not support using the EEPROM, - * because it is dangerous to go to deep sleep while EEPROM - * transaction is in progress. To fix, LM4_EEPROM_EEDONE, should - * be checked before going in to deep sleep. - */ -#if defined(CONFIG_LOW_POWER_IDLE) && defined(CONFIG_EEPROM) -#error "Low power idle mode does not support use of EEPROM" -#endif - -#ifdef CONFIG_LOW_POWER_IDLE - -void clock_refresh_console_in_use(void) -{ - disable_sleep(SLEEP_MASK_CONSOLE); - - /* Set console in use expire time. */ - console_expire_time = get_time(); - console_expire_time.val += console_in_use_timeout_sec * SECOND; - -} - -/* Low power idle task. Executed when no tasks are ready to be scheduled. */ -void __idle(void) -{ - timestamp_t t0, t1, rtc_t0, rtc_t1; - int next_delay = 0; - int time_for_dsleep, margin_us; - int use_low_speed_clock; - - /* Enable the hibernate IRQ used to wake up from deep sleep */ - system_enable_hib_interrupt(); - - /* Set SRAM and flash power management to 'low power' in deep sleep. */ - LM4_SYSTEM_DSLPPWRCFG = 0x23; - - /* Enable JTAG interrupt which will notify us when JTAG is in use. */ - gpio_enable_interrupt(GPIO_JTAG_TCK); - - /* - * Initialize console in use to true and specify the console expire - * time in order to give a fixed window on boot in which the low speed - * clock will not be used in idle. - */ - disable_sleep(SLEEP_MASK_CONSOLE); - console_expire_time.val = get_time().val + CONSOLE_IN_USE_ON_BOOT_TIME; - - /* - * 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. - */ - CPRINTF("[%T low power idle task started]\n"); - - while (1) { - /* - * Disable interrupts before going to deep sleep in order to - * calculate the appropriate time to wake up. Note: the wfi - * instruction waits until an interrupt is pending, so it - * will still wake up even with interrupts disabled. - */ - interrupt_disable(); - - t0 = get_time(); - next_delay = __hw_clock_event_get() - t0.le.lo; - - /* Do we have enough time before next event to deep sleep. */ - time_for_dsleep = next_delay > (DEEP_SLEEP_RECOVER_TIME_USEC + - HIB_SET_RTC_MATCH_DELAY_USEC); - - if (DEEP_SLEEP_ALLOWED && time_for_dsleep) { - /* Deep-sleep in STOP mode. */ - idle_dsleep_cnt++; - - /* Check if the console use has expired. */ - if ((sleep_mask & SLEEP_MASK_CONSOLE) && - t0.val > console_expire_time.val) { - /* Enable low speed deep sleep. */ - enable_sleep(SLEEP_MASK_CONSOLE); - - /* - * Wait one clock before checking if low speed - * deep sleep is allowed to give time for - * sleep mask to update. - */ - clock_wait_cycles(1); - - if (LOW_SPEED_DEEP_SLEEP_ALLOWED) - CPRINTF("[%T Disabling console in " - "deep sleep]\n"); - } - - /* - * Determine if we should use a lower clock speed or - * keep the same (16MHz) clock in deep sleep. Use the - * lower speed only if the sleep mask specifies that low - * speed sleep is allowed, the console UART TX is not - * busy, and the console UART buffer is empty. - */ - use_low_speed_clock = LOW_SPEED_DEEP_SLEEP_ALLOWED && - !uart_tx_in_progress() && uart_buffer_empty(); - -#ifdef CONFIG_LOW_POWER_USE_LFIOSC - /* Set the deep sleep clock register. Use either the - * normal PIOSC (16MHz) or the LFIOSC (32kHz). */ - LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? - 0x32 : 0x10; -#else - /* - * Set the deep sleep clock register. Use either the - * PIOSC with no divider (16MHz) or the PIOSC with - * a /64 divider (250kHz). - */ - LM4_SYSTEM_DSLPCLKCFG = use_low_speed_clock ? - 0x1f800010 : 0x10; -#endif - - /* - * If using low speed clock, disable console. - * This will also convert the console RX pin to a GPIO - * and set an edge interrupt to wake us from deep sleep - * if any action occurs on console. - */ - if (use_low_speed_clock) - uart_enter_dsleep(); - - /* Set deep sleep bit. */ - CPU_SCB_SYSCTRL |= 0x4; - - /* Record real time before sleeping. */ - rtc_t0 = system_get_rtc(); - - /* - * Set RTC interrupt in time to wake up before - * next event. - */ - system_set_rtc_alarm(0, next_delay - - DEEP_SLEEP_RECOVER_TIME_USEC); - - /* Wait for interrupt: goes into deep sleep. */ - asm("wfi"); - - /* Clear deep sleep bit. */ - CPU_SCB_SYSCTRL &= ~0x4; - - /* Disable and clear RTC interrupt. */ - system_reset_rtc_alarm(); - - /* Fast forward timer according to RTC counter. */ - rtc_t1 = system_get_rtc(); - t1.val = t0.val + (rtc_t1.val - rtc_t0.val); - force_time(t1); - - /* If using low speed clock, re-enable the console. */ - if (use_low_speed_clock) - uart_exit_dsleep(); - - /* Record time spent in deep sleep. */ - idle_dsleep_time_us += (rtc_t1.val - rtc_t0.val); - - /* Calculate how close we were to missing deadline */ - margin_us = next_delay - (int)(rtc_t1.val - rtc_t0.val); - if (margin_us < 0) - CPRINTF("[%T overslept by %dus]\n", -margin_us); - - /* Record the closest to missing a deadline. */ - if (margin_us < dsleep_recovery_margin_us) - dsleep_recovery_margin_us = margin_us; - } else { - idle_sleep_cnt++; - - /* Normal idle : only CPU clock stopped. */ - asm("wfi"); - } - interrupt_enable(); - } -} -#endif /* CONFIG_LOW_POWER_IDLE */ - /*****************************************************************************/ /* Console commands */ @@ -400,56 +142,36 @@ void __idle(void) * 3 : CPU in sleep mode and peripherals gated * 4 : CPU in deep sleep mode * 5 : CPU in deep sleep mode and peripherals gated - * - * Clocks : - * 0 : No change - * 1 : 16MHz - * 2 : 1 MHz - * 3 : 30kHz - * - * SRAM Power Management: - * 0 : Active - * 1 : Standby - * 3 : Low Power - * - * Flash Power Management: - * 0 : Active - * 2 : Low Power */ static int command_sleep(int argc, char **argv) { int level = 0; int clock = 0; - int sram_pm = 0; - int flash_pm = 0; uint32_t uartibrd = 0; uint32_t uartfbrd = 0; - if (argc >= 2) + if (argc >= 2) { level = strtoi(argv[1], NULL, 10); - if (argc >= 3) + } + if (argc >= 3) { clock = strtoi(argv[2], NULL, 10); - if (argc >= 4) - sram_pm = strtoi(argv[3], NULL, 10); - if (argc >= 5) - flash_pm = strtoi(argv[4], NULL, 10); + } #ifdef BOARD_bds - /* Remove LED current sink. */ + /* remove LED current sink */ gpio_set_level(GPIO_DEBUG_LED, 0); #endif - ccprintf("Sleep : level %d, clock %d, sram pm %d, flash_pm %d...\n", - level, clock, sram_pm, flash_pm); + ccprintf("Going to sleep : level %d clock %d...\n", level, clock); cflush(); - /* Set clock speed. */ + /* clock setting */ if (clock) { /* Use ROM code function to set the clock */ void **func_table = (void **)*(uint32_t *)0x01000044; void (*rom_clock_set)(uint32_t rcc) = func_table[23]; - /* Disable interrupts. */ + /* disable interrupts */ asm volatile("cpsid i"); switch (clock) { @@ -470,20 +192,18 @@ static int command_sleep(int argc, char **argv) break; } - /* - * TODO: move this to the UART module; ugly to have - * UARTisms here. Also note this only fixes UART0, - * not UART1. - */ + /* TODO: move this to the UART module; ugly to have + UARTisms here. Also note this only fixes UART0, + not UART1. */ if (uartfbrd) { - /* Disable the port via UARTCTL and add HSE. */ + /* Disable the port via UARTCTL and add HSE */ LM4_UART_CTL(0) = 0x0320; - /* Set the baud rate divisor. */ + /* Set the baud rate divisor */ LM4_UART_IBRD(0) = uartibrd; LM4_UART_FBRD(0) = uartfbrd; /* Poke UARTLCRH to make the new divisor take effect. */ LM4_UART_LCRH(0) = LM4_UART_LCRH(0); - /* Enable the port. */ + /* Enable the port */ LM4_UART_CTL(0) |= 0x0001; } asm volatile("cpsie i"); @@ -494,50 +214,21 @@ static int command_sleep(int argc, char **argv) cflush(); } - /* Enable interrupts. */ asm volatile("cpsid i"); /* gate peripheral clocks */ if (level & 1) { - clock_disable_peripheral(CGC_OFFSET_WD, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_TIMER, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_GPIO, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_DMA, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_HIB, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_UART, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_SSI, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_I2C, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_ADC, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_LPC, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_PECI, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_FAN, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_EEPROM, 0xffffffff, - CGC_MODE_ALL); - clock_disable_peripheral(CGC_OFFSET_WTIMER, 0xffffffff, - CGC_MODE_ALL); + LM4_SYSTEM_RCGCTIMER = 0; + LM4_SYSTEM_RCGCGPIO = 0; + LM4_SYSTEM_RCGCDMA = 0; + LM4_SYSTEM_RCGCUART = 0; + LM4_SYSTEM_RCGCLPC = 0; + LM4_SYSTEM_RCGCWTIMER = 0; } - - /* Set deep sleep bit. */ + /* set deep sleep bit */ if (level >= 4) CPU_SCB_SYSCTRL |= 0x4; - - /* Set SRAM and flash PM for sleep and deep sleep. */ - LM4_SYSTEM_SLPPWRCFG = (flash_pm << 4) | sram_pm; - LM4_SYSTEM_DSLPPWRCFG = (flash_pm << 4) | sram_pm; - - /* Go to low power mode (forever ...) */ + /* go to low power mode (forever ...) */ if (level > 1) while (1) { asm("wfi"); @@ -550,7 +241,7 @@ static int command_sleep(int argc, char **argv) return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(sleep, command_sleep, - "[level [clock] [sram pm] [flash pm]]", + "[level [clock]]", "Drop into sleep", NULL); #endif /* CONFIG_CMD_SLEEP */ @@ -598,162 +289,3 @@ DECLARE_CONSOLE_COMMAND(pll, command_pll, NULL); #endif /* CONFIG_CMD_PLL */ - -#ifdef CONFIG_CMD_CLOCKGATES -/** - * Print all clock gating registers - */ -static int command_clock_gating(int argc, char **argv) -{ - ccprintf(" Run , Sleep , Deep Sleep\n"); - - ccprintf("WD: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_WD)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_WD)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_WD)); - - ccprintf("TIMER: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_TIMER)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_TIMER)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_TIMER)); - - ccprintf("GPIO: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_GPIO)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_GPIO)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_GPIO)); - - ccprintf("DMA: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_DMA)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_DMA)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_DMA)); - - ccprintf("HIB: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_HIB)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_HIB)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_HIB)); - - ccprintf("UART: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_UART)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_UART)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_UART)); - - ccprintf("SSI: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_SSI)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_SSI)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_SSI)); - - ccprintf("I2C: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_I2C)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_I2C)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_I2C)); - - ccprintf("ADC: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_ADC)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_ADC)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_ADC)); - - ccprintf("LPC: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_LPC)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_LPC)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_LPC)); - - ccprintf("PECI: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_PECI)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_PECI)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_PECI)); - - ccprintf("FAN: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_FAN)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_FAN)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_FAN)); - - ccprintf("EEPROM: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_EEPROM)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_EEPROM)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_EEPROM)); - - ccprintf("WTIMER: 0x%08x, ", - *(LM4_SYSTEM_RCGC_BASE + CGC_OFFSET_WTIMER)); - ccprintf("0x%08x, ", *(LM4_SYSTEM_SCGC_BASE + CGC_OFFSET_WTIMER)); - ccprintf("0x%08x\n", *(LM4_SYSTEM_DCGC_BASE + CGC_OFFSET_WTIMER)); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(clockgates, command_clock_gating, - "", - "Get state of the clock gating controls regs", - NULL); -#endif /* CONFIG_CMD_CLOCKGATES */ - -#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 sleep: %d\n", idle_sleep_cnt); - ccprintf("Num idle calls that deep-sleep: %d\n", idle_dsleep_cnt); - ccprintf("Time spent in deep-sleep: %.6lds\n", - idle_dsleep_time_us); - ccprintf("Total time on: %.6lds\n", ts.val); - ccprintf("Deep-sleep closest to wake deadline: %dus\n", - dsleep_recovery_margin_us); - - 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 low speed clock or - * allow it to use the low speed clock. - */ - if (v) - disable_sleep(SLEEP_MASK_FORCE_NO_LOW_SPEED); - else - 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); - ccprintf("DSLPCLKCFG register: 0x%08x\n", LM4_SYSTEM_DSLPCLKCFG); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(dsleep, command_dsleep, - "[ on | off | <timeout> sec]", - "Deep sleep clock settings:\nUse 'on' to force deep " - "sleep not to use low speed clock.\nUse 'off' to " - "allow deep sleep to auto-select using the low speed " - "clock.\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/lm4/config_chip.h b/chip/lm4/config_chip.h index ca785248b0..9fbda8d970 100644 --- a/chip/lm4/config_chip.h +++ b/chip/lm4/config_chip.h @@ -25,12 +25,6 @@ /* Number of I2C ports */ #define I2C_PORT_COUNT 6 -/* - * Time it takes to set the RTC match register. This value is conservatively - * set based on measurements around 200us. - */ -#define HIB_SET_RTC_MATCH_DELAY_USEC 300 - /****************************************************************************/ /* Memory mapping */ @@ -41,7 +35,7 @@ #define CONFIG_STACK_SIZE 4096 /* non-standard task stack sizes */ -#define IDLE_TASK_STACK_SIZE 512 +#define IDLE_TASK_STACK_SIZE 384 #define LARGER_TASK_STACK_SIZE 640 /* Default task stack size */ diff --git a/chip/lm4/eeprom.c b/chip/lm4/eeprom.c index 9cd1054f27..7b28712afd 100644 --- a/chip/lm4/eeprom.c +++ b/chip/lm4/eeprom.c @@ -240,9 +240,9 @@ DECLARE_CONSOLE_COMMAND(eehide, command_eeprom_hide, int eeprom_init(void) { - /* Enable the EEPROM module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_EEPROM, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable the EEPROM module and delay a few clocks */ + LM4_SYSTEM_RCGCEEPROM = 1; + clock_wait_cycles(6); /* Wait for internal EEPROM init to finish */ wait_for_done(); diff --git a/chip/lm4/gpio.c b/chip/lm4/gpio.c index b8dc0f6570..d3a060904d 100644 --- a/chip/lm4/gpio.c +++ b/chip/lm4/gpio.c @@ -50,10 +50,13 @@ void gpio_set_alternate_function(int port, int mask, int func) if (port_index < 0) return; /* TODO: assert */ - /* Enable the GPIO port in run and sleep. */ + /* Enable the GPIO port if necessary */ cgmask = 1 << port_index; - clock_enable_peripheral(CGC_OFFSET_GPIO, cgmask, - CGC_MODE_RUN | CGC_MODE_SLEEP); + if ((LM4_SYSTEM_RCGCGPIO & cgmask) != cgmask) { + LM4_SYSTEM_RCGCGPIO |= cgmask; + /* Delay a few clocks before accessing registers */ + clock_wait_cycles(3); + } if (func >= 0) { int pctlmask = 0; @@ -156,31 +159,6 @@ int gpio_enable_interrupt(enum gpio_signal signal) return EC_SUCCESS; } -int gpio_disable_interrupt(enum gpio_signal signal) -{ - const struct gpio_info *g = gpio_list + signal; - - /* Fail if no interrupt handler */ - if (!g->irq_handler) - return EC_ERROR_UNKNOWN; - - LM4_GPIO_IM(g->port) &= ~g->mask; - return EC_SUCCESS; -} - -#ifdef CONFIG_LOW_POWER_IDLE -/** - * Convert GPIO port to a mask that can be used to set the - * clock gate control register for GPIOs. - */ -static int gpio_port_to_clock_gate_mask(uint32_t gpio_port) -{ - int index = find_gpio_port_index(gpio_port); - - return index >= 0 ? (1 << index) : 0; -} -#endif - void gpio_pre_init(void) { const struct gpio_info *g = gpio_list; @@ -193,10 +171,10 @@ void gpio_pre_init(void) } else { /* * Enable clocks to all the GPIO blocks since we use all of - * them as GPIOs in run and sleep modes. + * them as GPIOs. */ - clock_enable_peripheral(CGC_OFFSET_GPIO, 0x7fff, - CGC_MODE_RUN | CGC_MODE_SLEEP); + LM4_SYSTEM_RCGCGPIO |= 0x7fff; + clock_wait_cycles(6); /* Delay a few clocks */ } /* @@ -224,18 +202,6 @@ void gpio_pre_init(void) if (flags & GPIO_DEFAULT) continue; -#ifdef CONFIG_LOW_POWER_IDLE - /* - * Enable board specific GPIO ports to interrupt deep sleep by - * providing a clock to that port in deep sleep mode. - */ - if (flags & GPIO_INT_DSLEEP) { - clock_enable_peripheral(CGC_OFFSET_GPIO, - gpio_port_to_clock_gate_mask(g->port), - CGC_MODE_ALL); - } -#endif - /* * If this is a warm reboot, don't set the output levels or * we'll shut off the main chipset. @@ -249,16 +215,6 @@ void gpio_pre_init(void) /* Use as GPIO, not alternate function */ gpio_set_alternate_function(g->port, g->mask, -1); } - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * Enable KB scan row to interrupt deep sleep by providing a clock - * signal to that port in deep sleep mode. - */ - clock_enable_peripheral(CGC_OFFSET_GPIO, - gpio_port_to_clock_gate_mask(KB_SCAN_ROW_GPIO), - CGC_MODE_ALL); -#endif } /* List of GPIO IRQs to enable. Don't automatically enable interrupts for diff --git a/chip/lm4/hwtimer.c b/chip/lm4/hwtimer.c index 088bd5713b..cbf28f5294 100644 --- a/chip/lm4/hwtimer.c +++ b/chip/lm4/hwtimer.c @@ -69,14 +69,17 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); int __hw_clock_source_init(uint32_t start_t) { + volatile uint32_t scratch __attribute__((unused)); + /* * Use WTIMER0 (timer 6) configured as a free running counter with 1 us * period. */ - /* Enable WTIMER0 clock in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_WTIMER, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable WTIMER0 clock */ + LM4_SYSTEM_RCGCWTIMER |= 1; + /* wait 3 clock cycles before using the module */ + scratch = LM4_SYSTEM_RCGCWTIMER; /* Ensure timer is disabled : TAEN = TBEN = 0 */ LM4_TIMER_CTL(6) &= ~0x101; diff --git a/chip/lm4/i2c.c b/chip/lm4/i2c.c index cee3e047af..8fc1591338 100644 --- a/chip/lm4/i2c.c +++ b/chip/lm4/i2c.c @@ -280,8 +280,8 @@ static void i2c_init(void) for (i = 0; i < I2C_PORTS_USED; i++) mask |= 1 << i2c_ports[i].port; - clock_enable_peripheral(CGC_OFFSET_I2C, mask, - CGC_MODE_RUN | CGC_MODE_SLEEP); + LM4_SYSTEM_RCGCI2C |= mask; + clock_wait_cycles(3); /* Configure GPIOs */ gpio_config_module(MODULE_I2C, 1); diff --git a/chip/lm4/jtag.c b/chip/lm4/jtag.c index a3867aa0f6..bfa9b1e7de 100644 --- a/chip/lm4/jtag.c +++ b/chip/lm4/jtag.c @@ -3,16 +3,13 @@ * found in the LICENSE file. */ -#include "clock.h" -#include "gpio.h" #include "jtag.h" #include "registers.h" -#include "system.h" void jtag_pre_init(void) { - /* Enable clocks to GPIO block C in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_GPIO, 0x0004, CGC_MODE_ALL); + /* Enable clocks to GPIO block C */ + LM4_SYSTEM_RCGCGPIO |= 0x0004; /* * Ensure PC0:3 are set to JTAG function. They should be set this way @@ -36,30 +33,7 @@ void jtag_pre_init(void) LM4_GPIO_DEN(LM4_GPIO_C) |= 0x0f; LM4_GPIO_PUR(LM4_GPIO_C) |= 0x0f; - /* Set interrupt on either edge of the JTAG signals */ - LM4_GPIO_IS(LM4_GPIO_C) &= ~0x0f; - LM4_GPIO_IBE(LM4_GPIO_C) |= 0x0f; - /* Re-lock commit register */ LM4_GPIO_CR(LM4_GPIO_C) &= ~0x0f; LM4_GPIO_LOCK(LM4_GPIO_C) = 0; } - -#ifdef CONFIG_LOW_POWER_IDLE -void jtag_interrupt(enum gpio_signal signal) -{ - /* - * This interrupt is the first sign someone is trying to use - * the JTAG. Disable slow speed sleep so that the JTAG action - * can take place. - */ - disable_sleep(SLEEP_MASK_JTAG); - - /* - * Once we get this interrupt, disable it from occurring again - * to avoid repeated interrupts when debugging via JTAG. - */ - gpio_disable_interrupt(GPIO_JTAG_TCK); -} -#endif /* CONFIG_LOW_POWER_IDLE */ - diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index 7ca4de1e41..04563caf66 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -656,9 +656,9 @@ static void lpc_post_sysjump(void) static void lpc_init(void) { - /* Enable LPC clock in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_LPC, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable RGCGLPC then delay a few clocks. */ + LM4_SYSTEM_RCGCLPC = 1; + clock_wait_cycles(6); LM4_LPC_LPCIM = 0; LM4_LPC_LPCCTL = 0; diff --git a/chip/lm4/peci.c b/chip/lm4/peci.c index 780ecd40b6..88e13d18c1 100644 --- a/chip/lm4/peci.c +++ b/chip/lm4/peci.c @@ -16,6 +16,10 @@ #include "temp_sensor.h" #include "util.h" +/* Max junction temperature for processor in degrees C */ +/* TODO: read TjMax from processor via PECI */ +#define PECI_TJMAX 105 + /* Initial PECI baud rate */ #define PECI_BAUD_RATE 100000 @@ -62,15 +66,7 @@ int peci_temp_sensor_get_val(int idx, int *temp_ptr) } } - /* - * Require at least two valid samples. When the AP transitions into S0, - * it is possible, depending on the timing of the PECI sample, to read - * an invalid temperature. This is very rare, but when it does happen - * the temperature returned is CONFIG_PECI_TJMAX. Requiring two valid - * samples here assures us that one bad maximum temperature reading - * when entering S0 won't cause us to trigger an over temperature. - */ - if (success_cnt < 2) + if (!success_cnt) return EC_ERROR_UNKNOWN; *temp_ptr = sum / success_cnt; @@ -104,7 +100,7 @@ static void peci_freq_changed(void) (PECI_POLL_INTERVAL_MS * (freq / 1000 / 4096)); /* Set up temperature monitoring to report in degrees K */ - LM4_PECI_CTL = ((CONFIG_PECI_TJMAX + 273) << 22) | 0x0001 | + LM4_PECI_CTL = ((PECI_TJMAX + 273) << 22) | 0x0001 | (PECI_RETRY_COUNT << 12) | (PECI_ERROR_BYPASS << 11); } @@ -114,9 +110,9 @@ static void peci_init(void) { int i; - /* Enable the PECI module in run and sleep modes. */ - clock_enable_peripheral(CGC_OFFSET_PECI, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable the PECI module and delay a few clocks */ + LM4_SYSTEM_RCGCPECI = 1; + clock_wait_cycles(3); /* Configure GPIOs */ gpio_config_module(MODULE_PECI, 1); diff --git a/chip/lm4/pwm_fan.c b/chip/lm4/pwm_fan.c index 99644eddb3..6309867dae 100644 --- a/chip/lm4/pwm_fan.c +++ b/chip/lm4/pwm_fan.c @@ -274,8 +274,8 @@ static void pwm_fan_init(void) int i; /* Enable the fan module and delay a few clocks */ - clock_enable_peripheral(CGC_OFFSET_FAN, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + LM4_SYSTEM_RCGCFAN = 1; + clock_wait_cycles(3); /* Configure GPIOs */ gpio_config_module(MODULE_PWM_FAN, 1); diff --git a/chip/lm4/registers.h b/chip/lm4/registers.h index b87a7b55ec..c463fe41cc 100644 --- a/chip/lm4/registers.h +++ b/chip/lm4/registers.h @@ -194,7 +194,6 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_HIBCTL_RTCEN (1 << 0) #define LM4_HIBERNATE_HIBIM REG32(0x400fc014) #define LM4_HIBERNATE_HIBRIS REG32(0x400fc018) -#define LM4_HIBERNATE_HIBMIS REG32(0x400fc01c) #define LM4_HIBERNATE_HIBIC REG32(0x400fc020) #define LM4_HIBERNATE_HIBRTCT REG32(0x400fc024) #define LM4_HIBERNATE_HIBRTCSS REG32(0x400fc028) @@ -228,7 +227,6 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_SYSTEM_MISC REG32(0x400fe058) #define LM4_SYSTEM_RESC REG32(0x400fe05c) #define LM4_SYSTEM_RCC REG32(0x400fe060) -#define LM4_SYSTEM_RCC_ACG (1 << 27) #define LM4_SYSTEM_RCC_SYSDIV(x) (((x) & 0xf) << 23) #define LM4_SYSTEM_RCC_USESYSDIV (1 << 22) #define LM4_SYSTEM_RCC_PWRDN (1 << 13) @@ -246,17 +244,9 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_SYSTEM_RCC2_BYPASS2 (1 << 11) #define LM4_SYSTEM_RCC2_OSCSRC2(x) (((x) & 0x7) << 4) #define LM4_SYSTEM_MOSCCTL REG32(0x400fe07c) -#define LM4_SYSTEM_DSLPCLKCFG REG32(0x400fe144) #define LM4_SYSTEM_PIOSCCAL REG32(0x400fe150) #define LM4_SYSTEM_PIOSCSTAT REG32(0x400fe154) #define LM4_SYSTEM_PLLSTAT REG32(0x400fe168) -#define LM4_SYSTEM_SLPPWRCFG REG32(0x400fe188) -#define LM4_SYSTEM_DSLPPWRCFG REG32(0x400fe18c) -#define LM4_SYSTEM_LDOSPCTL REG32(0x400fe1b4) -#define LM4_SYSTEM_LDOSPCAL REG32(0x400fe1b8) -#define LM4_SYSTEM_LDODPCTL REG32(0x400fe1bc) -#define LM4_SYSTEM_LDODPCAL REG32(0x400fe1c0) -#define LM4_SYSTEM_SPDMST REG32(0x400fe1cc) #define LM4_SYSTEM_BOOTCFG REG32(0x400fe1d0) #define LM4_SYSTEM_BOOTCFG_MASK 0x7fff00ec /* Reserved bits of BOOTCFG reg */ /* Note: USER_REG3 is used to hold pre-programming process data and should not @@ -264,34 +254,20 @@ static inline int lm4_fan_addr(int ch, int offset) #define LM4_SYSTEM_USER_REG3 REG32(0x400fe1ec) #define LM4_SYSTEM_SRI2C REG32(0x400fe520) #define LM4_SYSTEM_SREEPROM REG32(0x400fe558) - -#define LM4_SYSTEM_RCGC_BASE ((volatile uint32_t *)0x400fe600) +#define LM4_SYSTEM_RCGCWD REG32(0x400fe600) +#define LM4_SYSTEM_RCGCTIMER REG32(0x400fe604) #define LM4_SYSTEM_RCGCGPIO REG32(0x400fe608) -#define LM4_SYSTEM_SCGC_BASE ((volatile uint32_t *)0x400fe700) -#define LM4_SYSTEM_DCGC_BASE ((volatile uint32_t *)0x400fe800) - -/* - * Offsets from CGC_BASE registers for each peripheral. - * Note: these are in units of 32-bit words offset from - * the base address. - */ -enum clock_gate_offsets { - CGC_OFFSET_WD = 0, - CGC_OFFSET_TIMER = 1, - CGC_OFFSET_GPIO = 2, - CGC_OFFSET_DMA = 3, - CGC_OFFSET_HIB = 5, - CGC_OFFSET_UART = 6, - CGC_OFFSET_SSI = 7, - CGC_OFFSET_I2C = 8, - CGC_OFFSET_ADC = 14, - CGC_OFFSET_LPC = 18, - CGC_OFFSET_PECI = 20, - CGC_OFFSET_FAN = 21, - CGC_OFFSET_EEPROM = 22, - CGC_OFFSET_WTIMER = 23, -}; - +#define LM4_SYSTEM_RCGCDMA REG32(0x400fe60c) +#define LM4_SYSTEM_RCGCHIB REG32(0x400fe614) +#define LM4_SYSTEM_RCGCUART REG32(0x400fe618) +#define LM4_SYSTEM_RCGCSSI REG32(0x400fe61c) +#define LM4_SYSTEM_RCGCI2C REG32(0x400fe620) +#define LM4_SYSTEM_RCGCADC REG32(0x400fe638) +#define LM4_SYSTEM_RCGCLPC REG32(0x400fe648) +#define LM4_SYSTEM_RCGCPECI REG32(0x400fe650) +#define LM4_SYSTEM_RCGCFAN REG32(0x400fe654) +#define LM4_SYSTEM_RCGCEEPROM REG32(0x400fe658) +#define LM4_SYSTEM_RCGCWTIMER REG32(0x400fe65c) #define LM4_SYSTEM_PREEPROM REG32(0x400fea58) #define LM4_DMA_DMACFG REG32(0x400ff004) diff --git a/chip/lm4/spi.c b/chip/lm4/spi.c index 914e5f1c66..6526ded82c 100644 --- a/chip/lm4/spi.c +++ b/chip/lm4/spi.c @@ -99,9 +99,11 @@ int spi_transaction(const uint8_t *txdata, int txlen, static int spi_init(void) { - /* Enable the SPI module in run and sleep modes */ - clock_enable_peripheral(CGC_OFFSET_SSI, 0x1, - CGC_MODE_RUN | CGC_MODE_SLEEP); + volatile uint32_t scratch __attribute__((unused)); + + /* Enable the SPI module and delay a few clocks */ + LM4_SYSTEM_RCGCSSI = 1; + scratch = LM4_SYSTEM_RCGCSSI; LM4_SSI_CR1(0) = 0; /* Disable SSI */ LM4_SSI_CR0(0) = 0x0007; /* SCR=0, SPH=0, SPO=0, FRF=SPI, 8-bit */ diff --git a/chip/lm4/system.c b/chip/lm4/system.c index 02586bfab1..46d2fa68da 100644 --- a/chip/lm4/system.c +++ b/chip/lm4/system.c @@ -5,7 +5,6 @@ /* System module for Chrome EC : LM4 hardware specific implementation */ -#include "clock.h" #include "common.h" #include "console.h" #include "cpu.h" @@ -13,7 +12,6 @@ #include "registers.h" #include "system.h" #include "task.h" -#include "timer.h" #include "util.h" /* Indices for hibernate data registers */ @@ -29,20 +27,18 @@ enum hibdata_index { #define HIBDATA_WAKE_PIN (1 << 2) /* Wake pin */ /* + * Time it takes wait_for_hibctl_wc() to return. Experimentally verified to + * be ~200 us; the value below is somewhat conservative. + */ +#define HIB_WAIT_USEC 1000 + +/* * Time to hibernate to trigger a power-on reset. 50 ms is sufficient for the * EC itself, but we need a longer delay to ensure the rest of the components * on the same power rail are reset and 5VALW has dropped. */ #define HIB_RESET_USEC 1000000 -/* - * Convert between microseconds and the hibernation module RTC subsecond - * register which has 15-bit resolution. Divide down both numerator and - * denominator to avoid integer overflow while keeping the math accurate. - */ -#define HIB_RTC_USEC_TO_SUBSEC(us) ((us) * (32768/64) / (1000000/64)) -#define HIB_RTC_SUBSEC_TO_USEC(ss) ((ss) * (1000000/64) / (32768/64)) - /** * Wait for a write to commit to a hibernate register. * @@ -190,7 +186,7 @@ void __attribute__((section(".iram.text"))) __enter_hibernate(int hibctl) * * @return the real-time clock seconds value. */ -uint32_t system_get_rtc_sec_subsec(uint32_t *ss_ptr) +uint32_t system_get_rtc(uint32_t *ss_ptr) { uint32_t rtc, rtc2; uint32_t rtcss, rtcss2; @@ -212,17 +208,6 @@ uint32_t system_get_rtc_sec_subsec(uint32_t *ss_ptr) return rtc; } -timestamp_t system_get_rtc(void) -{ - uint32_t rtc, rtc_ss; - timestamp_t time; - - rtc = system_get_rtc_sec_subsec(&rtc_ss); - - time.val = ((uint64_t)rtc) * SECOND + HIB_RTC_SUBSEC_TO_USEC(rtc_ss); - return time; -} - /** * Set the real-time clock. * @@ -236,101 +221,6 @@ void system_set_rtc(uint32_t seconds) } /** - * Set the hibernate RTC match time at a given time from now - * - * @param seconds Number of seconds from now for RTC match - * @param microseconds Number of microseconds from now for RTC match - */ -static void set_hibernate_rtc_match_time(uint32_t seconds, - uint32_t microseconds) -{ - uint32_t rtc, rtcss; - - /* - * Make sure that the requested delay is not less then the - * amount of time it takes to set the RTC match registers, - * otherwise, the match event could be missed. - */ - if (seconds == 0 && microseconds < HIB_SET_RTC_MATCH_DELAY_USEC) - microseconds = HIB_SET_RTC_MATCH_DELAY_USEC; - - /* Calculate the wake match */ - rtc = system_get_rtc_sec_subsec(&rtcss) + seconds; - rtcss += HIB_RTC_USEC_TO_SUBSEC(microseconds); - if (rtcss > 0x7fff) { - rtc += rtcss >> 15; - rtcss &= 0x7fff; - } - - /* Set RTC alarm match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCM0 = rtc; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBRTCSS = rtcss << 16; - wait_for_hibctl_wc(); -} - -/** - * Use hibernate module to set up an RTC interrupt at a given - * time from now - * - * @param seconds Number of seconds before RTC interrupt - * @param microseconds Number of microseconds before RTC interrupt - */ -void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) -{ - /* Clear pending interrupt */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; - - /* Set match time */ - set_hibernate_rtc_match_time(seconds, microseconds); - - /* Enable RTC interrupt on match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 1; - - /* - * Wait for the write to commit. This ensures that the RTC interrupt - * actually gets enabled. This is important if we're about to switch - * the system to the 30 kHz oscillator, which might prevent the write - * from comitting. - */ - wait_for_hibctl_wc(); -} - -/** - * Disable and clear the RTC interrupt. - */ -void system_reset_rtc_alarm(void) -{ - /* Disable hibernate interrupts */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 0; - - /* Clear interrupts */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; -} - -/** - * Hibernate module interrupt - */ -static void __hibernate_irq(void) -{ - system_reset_rtc_alarm(); -} -DECLARE_IRQ(LM4_IRQ_HIBERNATE, __hibernate_irq, 1); - -/** - * Enable hibernate interrupt - */ -void system_enable_hib_interrupt(void) -{ - task_enable_irq(LM4_IRQ_HIBERNATE); -} - -/** * Internal hibernate function. * * @param seconds Number of seconds to sleep before RTC alarm @@ -339,6 +229,7 @@ void system_enable_hib_interrupt(void) */ static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags) { + uint32_t rtc, rtcss; uint32_t hibctl; /* Set up wake reasons and hibernate flags */ @@ -352,25 +243,46 @@ static void hibernate(uint32_t seconds, uint32_t microseconds, uint32_t flags) if (seconds || microseconds) { hibctl |= LM4_HIBCTL_RTCWEN; flags |= HIBDATA_WAKE_RTC; - - set_hibernate_rtc_match_time(seconds, microseconds); - - /* Enable RTC interrupt on match */ - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBIM = 1; } else { hibctl &= ~LM4_HIBCTL_RTCWEN; } wait_for_hibctl_wc(); LM4_HIBERNATE_HIBCTL = hibctl; + /* Store hibernate flags */ + hibdata_write(HIBDATA_INDEX_WAKE, flags); + /* Clear pending interrupt */ wait_for_hibctl_wc(); LM4_HIBERNATE_HIBIC = LM4_HIBERNATE_HIBRIS; - /* Store hibernate flags */ - hibdata_write(HIBDATA_INDEX_WAKE, flags); + /* Add expected overhead for hibernate register writes */ + microseconds += HIB_WAIT_USEC * 4; + + /* + * The code below must run uninterrupted to make sure we accurately + * calculate the RTC match value. + */ + interrupt_disable(); + /* + * Calculate the wake match, compensating for additional delays caused + * by writing to the hibernate register. + */ + rtc = system_get_rtc(&rtcss) + seconds; + rtcss += microseconds * (32768/64) / (1000000/64); + if (rtcss > 0x7fff) { + rtc += rtcss >> 15; + rtcss &= 0x7fff; + } + + /* Set RTC alarm match */ + wait_for_hibctl_wc(); + LM4_HIBERNATE_HIBRTCM0 = rtc; + wait_for_hibctl_wc(); + LM4_HIBERNATE_HIBRTCSS = rtcss << 16; + + wait_for_hibctl_wc(); __enter_hibernate(hibctl | LM4_HIBCTL_HIBREQ); } @@ -383,13 +295,12 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) void system_pre_init(void) { - uint32_t hibctl; + volatile uint32_t scratch __attribute__((unused)); - /* - * Enable clocks to the hibernation module in run, sleep, - * and deep sleep modes. - */ - clock_enable_peripheral(CGC_OFFSET_HIB, 0x1, CGC_MODE_ALL); + /* Enable clocks to the hibernation module */ + LM4_SYSTEM_RCGCHIB = 1; + /* Wait 3 clock cycles before using the module */ + scratch = LM4_SYSTEM_RCGCHIB; /* * Enable the hibernation oscillator, if it's not already enabled. @@ -420,16 +331,6 @@ void system_pre_init(void) } /* - * Set wake reasons to RTC match and WAKE pin by default. - * Before going in to hibernate, these may change. - */ - hibctl = LM4_HIBERNATE_HIBCTL; - hibctl |= LM4_HIBCTL_RTCWEN; - hibctl |= LM4_HIBCTL_PINWEN; - wait_for_hibctl_wc(); - LM4_HIBERNATE_HIBCTL = hibctl; - - /* * Initialize registers after reset to work around LM4 chip errata * (still present in A3 chip stepping). */ @@ -603,9 +504,9 @@ static int command_system_rtc(int argc, char **argv) return EC_ERROR_INVAL; } - rtc = system_get_rtc_sec_subsec(&rtcss); + rtc = system_get_rtc(&rtcss); ccprintf("RTC: 0x%08x.%04x (%d.%06d s)\n", - rtc, rtcss, rtc, HIB_RTC_SUBSEC_TO_USEC(rtcss)); + rtc, rtcss, rtc, (rtcss * (1000000/64)) / (32768/64)); return EC_SUCCESS; } @@ -614,41 +515,6 @@ DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, "Get/set real-time clock", NULL); -#ifdef CONFIG_CMD_RTC_ALARM -/** - * Test the RTC alarm by setting an interrupt on RTC match. - */ -static int command_rtc_alarm_test(int argc, char **argv) -{ - int s = 1, us = 0; - char *e; - - ccprintf("Setting RTC alarm\n"); - system_enable_hib_interrupt(); - - if (argc > 1) { - s = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - } - if (argc > 2) { - us = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - - } - - system_set_rtc_alarm(s, us); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test, - "[seconds [microseconds]]", - "Test alarm", - NULL); -#endif /* CONFIG_CMD_RTC_ALARM */ - /*****************************************************************************/ /* Host commands */ @@ -656,7 +522,7 @@ static int system_rtc_get_value(struct host_cmd_handler_args *args) { struct ec_response_rtc *r = args->response; - r->time = system_get_rtc_sec_subsec(NULL); + r->time = system_get_rtc(NULL); args->response_size = sizeof(*r); return EC_RES_SUCCESS; diff --git a/chip/lm4/uart.c b/chip/lm4/uart.c index 13cdee7f14..17443d9848 100644 --- a/chip/lm4/uart.c +++ b/chip/lm4/uart.c @@ -5,13 +5,11 @@ /* UART module for Chrome EC */ -#include "clock.h" #include "common.h" #include "console.h" #include "gpio.h" #include "lpc.h" #include "registers.h" -#include "system.h" #include "task.h" #include "uart.h" #include "util.h" @@ -27,12 +25,6 @@ int uart_init_done(void) void uart_tx_start(void) { - /* If interrupt is already enabled, nothing to do */ - if (LM4_UART_IM(0) & 0x20) - return; - - /* Do not allow deep sleep while transmit in progress */ - disable_sleep(SLEEP_MASK_UART); /* * Re-enable the transmit interrupt, then forcibly trigger the * interrupt. This works around a hardware problem with the @@ -46,9 +38,6 @@ void uart_tx_start(void) void uart_tx_stop(void) { LM4_UART_IM(0) &= ~0x20; - - /* Re-allow deep sleep */ - enable_sleep(SLEEP_MASK_UART); } int uart_tx_stopped(void) @@ -68,12 +57,6 @@ int uart_tx_ready(void) return !(LM4_UART_FR(0) & 0x20); } -int uart_tx_in_progress(void) -{ - /* Transmit is in progress if the TX busy bit is set. */ - return LM4_UART_FR(0) & 0x08; -} - int uart_rx_available(void) { return !(LM4_UART_FR(0) & 0x10); @@ -190,18 +173,11 @@ static void uart_config(int port) void uart_init(void) { - uint32_t mask = 0; + volatile uint32_t scratch __attribute__((unused)); - /* - * Enable UART0 in run, sleep, and deep sleep modes. Enable the Host - * UART in run and sleep modes. - */ - mask |= 1; - clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL); - - mask |= (1 << CONFIG_UART_HOST); - clock_enable_peripheral(CGC_OFFSET_UART, mask, - CGC_MODE_RUN | CGC_MODE_SLEEP); + /* Enable UART0 and Host UART and delay a few clocks */ + LM4_SYSTEM_RCGCUART |= (1 << CONFIG_UART_HOST) | 1; + scratch = LM4_SYSTEM_RCGCUART; gpio_config_module(MODULE_UART, 1); @@ -219,71 +195,6 @@ void uart_init(void) init_done = 1; } -#ifdef CONFIG_LOW_POWER_IDLE -void uart_enter_dsleep(void) -{ - const struct gpio_info g = gpio_list[GPIO_UART0_RX]; - - /* Disable the UART0 module interrupt. */ - task_disable_irq(LM4_IRQ_UART0); - - /* Disable UART0 peripheral in deep sleep. */ - clock_disable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP); - - /* - * Set the UART0 RX pin to be a generic GPIO with the flags defined - * in the board.c file. - */ - gpio_set_flags_by_mask(g.port, g.mask, g.flags); - gpio_set_alternate_function(g.port, g.mask, -1); - - /* Clear any pending GPIO interrupts on the UART0 RX pin. */ - LM4_GPIO_ICR(g.port) = g.mask; - - /* Enable GPIO interrupts on the UART0 RX pin. */ - gpio_enable_interrupt(GPIO_UART0_RX); -} - -void uart_exit_dsleep(void) -{ - const struct gpio_info g = gpio_list[GPIO_UART0_RX]; - - /* - * If the UART0 RX GPIO interrupt has not fired, then no edge has been - * detected. Disable the GPIO interrupt so that switching the pin over - * to a UART pin doesn't inadvertently cause a GPIO edge interrupt. - * Note: we can't disable this interrupt if it has already fired - * because then the IRQ will not get called. - */ - if (!(LM4_GPIO_MIS(g.port) & g.mask)) - gpio_disable_interrupt(GPIO_UART0_RX); - - /* Configure UART0 pins for use in UART peripheral. */ - gpio_config_module(MODULE_UART, 1); - - /* Clear pending interrupts on UART peripheral and enable interrupts. */ - uart_clear_rx_fifo(0); - task_enable_irq(LM4_IRQ_UART0); - - /* Enable UART0 peripheral in deep sleep */ - clock_enable_peripheral(CGC_OFFSET_UART, 0x1, CGC_MODE_DSLEEP); -} - -void uart_deepsleep_interrupt(enum gpio_signal signal) -{ - /* - * Activity seen on UART RX pin while UART was disabled for deep sleep. - * The console won't see that character because the UART is disabled, - * so we need to inform the clock module of UART activity ourselves. - */ - clock_refresh_console_in_use(); - - /* Disable interrupts on UART0 RX pin to avoid repeated interrupts. */ - gpio_disable_interrupt(GPIO_UART0_RX); -} -#endif /* CONFIG_LOW_POWER_IDLE */ - - /*****************************************************************************/ /* COMx functions */ diff --git a/chip/lm4/watchdog.c b/chip/lm4/watchdog.c index 56f051bcd8..ef817cf715 100644 --- a/chip/lm4/watchdog.c +++ b/chip/lm4/watchdog.c @@ -91,8 +91,12 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, watchdog_freq_changed, HOOK_PRIO_DEFAULT); int watchdog_init(void) { - /* Enable watchdog 0 clock in run, sleep, and deep sleep modes */ - clock_enable_peripheral(CGC_OFFSET_WD, 0x1, CGC_MODE_ALL); + volatile uint32_t scratch __attribute__((unused)); + + /* Enable watchdog 0 clock */ + LM4_SYSTEM_RCGCWD |= 0x1; + /* Wait 3 clock cycles before using the module */ + scratch = LM4_SYSTEM_RCGCWD; /* Set initial timeout period */ watchdog_freq_changed(); diff --git a/chip/stm32/clock-stm32f.c b/chip/stm32/clock-stm32f.c index 11b426a42f..e878d7856d 100644 --- a/chip/stm32/clock-stm32f.c +++ b/chip/stm32/clock-stm32f.c @@ -35,6 +35,19 @@ #define RTC_FREQ 40000 /* Hz */ #define US_PER_RTC_TICK (1000000 / RTC_FREQ) +/* On-going actions preventing to go into deep-sleep mode */ +static uint32_t sleep_mask; + +void enable_sleep(uint32_t mask) +{ + atomic_clear(&sleep_mask, mask); +} + +void disable_sleep(uint32_t mask) +{ + atomic_or(&sleep_mask, mask); +} + static void wait_rtc_ready(void) { /* wait for Registers Synchronized Flag */ @@ -177,10 +190,6 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds) #ifdef CONFIG_LOW_POWER_IDLE -void clock_refresh_console_in_use(void) -{ -} - #ifdef CONFIG_FORCE_CONSOLE_RESUME static void enable_serial_wakeup(int enable) { @@ -196,7 +205,7 @@ static void enable_serial_wakeup(int enable) } else { /* serial port wake up : don't go back to sleep */ if (STM32_EXTI_PR & (1 << 10)) - disable_sleep(SLEEP_MASK_FORCE_NO_DSLEEP); + disable_sleep(SLEEP_MASK_FORCE); /* restore keyboard external IT on PC10 */ STM32_AFIO_EXTICR(10 / 4) = save_exticr; } @@ -220,7 +229,7 @@ void __idle(void) t0 = get_time(); next_delay = __hw_clock_event_get() - t0.le.lo; - if (DEEP_SLEEP_ALLOWED && (next_delay > STOP_MODE_LATENCY)) { + if (!sleep_mask && (next_delay > STOP_MODE_LATENCY)) { /* deep-sleep in STOP mode */ enable_serial_wakeup(1); @@ -289,4 +298,27 @@ void clock_init(void) task_enable_irq(STM32_IRQ_RTC_ALARM); } +/*****************************************************************************/ +/* Console commands */ + +static int command_sleepmask(int argc, char **argv) +{ + int off; + + if (argc >= 2) { + off = strtoi(argv[1], NULL, 10); + if (off) + disable_sleep(SLEEP_MASK_FORCE); + else + enable_sleep(SLEEP_MASK_FORCE); + } + + ccprintf("sleep mask: %08x\n", sleep_mask); + + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(sleepmask, command_sleepmask, + "[0|1]", + "Display/force sleep mack", + NULL); diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c index 63805eedda..4d5b1babeb 100644 --- a/chip/stm32/clock-stm32l.c +++ b/chip/stm32/clock-stm32l.c @@ -32,6 +32,16 @@ enum clock_osc { static int freq; static int current_osc; +void enable_sleep(uint32_t mask) +{ + /* low power mode not implemented */ +} + +void disable_sleep(uint32_t mask) +{ + /* low power mode not implemented */ +} + int clock_get_freq(void) { return freq; diff --git a/chip/stm32/uart.c b/chip/stm32/uart.c index ec6a14c4d5..dab5231845 100644 --- a/chip/stm32/uart.c +++ b/chip/stm32/uart.c @@ -10,7 +10,6 @@ #include "gpio.h" #include "hooks.h" #include "registers.h" -#include "system.h" #include "task.h" #include "uart.h" #include "util.h" |