diff options
-rw-r--r-- | chip/mchp/clock.c | 100 | ||||
-rw-r--r-- | chip/mchp/clock_chip.h | 17 | ||||
-rw-r--r-- | chip/mchp/config_chip.h | 1 | ||||
-rw-r--r-- | chip/mchp/system.c | 126 | ||||
-rw-r--r-- | include/config.h | 5 |
5 files changed, 127 insertions, 122 deletions
diff --git a/chip/mchp/clock.c b/chip/mchp/clock.c index 123e26e851..59731830cf 100644 --- a/chip/mchp/clock.c +++ b/chip/mchp/clock.c @@ -143,7 +143,6 @@ DECLARE_HOOK(HOOK_INIT, clock_turbo_disable, HOOK_PRIO_INIT_VBOOT_HASH + 1); -#ifdef CONFIG_LOW_POWER_IDLE /** * initialization of Hibernation timer0 * Clear PCR sleep enable. @@ -152,12 +151,14 @@ DECLARE_HOOK(HOOK_INIT, * (exception GPIO's) then the MCHP_INT_BLK_EN GIRQ bit should not be * set. */ -static void htimer_init(void) +void htimer_init(void) { MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_HTMR0); + MCHP_HTIMER_PRELOAD(0) = 0; /* disable at beginning */ + MCHP_INT_SOURCE(MCHP_HTIMER_GIRQ) = + MCHP_HTIMER_GIRQ_BIT(0); MCHP_INT_ENABLE(MCHP_HTIMER_GIRQ) = MCHP_HTIMER_GIRQ_BIT(0); - MCHP_HTIMER_PRELOAD(0) = 0; /* disable at beginning */ task_enable_irq(MCHP_IRQ_HTIMER0); } @@ -168,52 +169,57 @@ static void htimer_init(void) * * @param seconds Number of seconds before htimer interrupt * @param microseconds Number of microseconds before htimer interrupt - * @note hibernation timer input clock is 32.768KHz and has two - * divider values. + * @note hibernation timer input clock is 32.768KHz. * Control register bit[0] selects the divider. - * 0 is divide by 1 for 30.5us per LSB for a maximum of ~2 seconds. + * 0 is divide by 1 for 30.5us per LSB for a maximum of + * 65535 * 30.5us = 1998817.5 us or 32.786 counts per second * 1 is divide by 4096 for 0.125s per LSB for a maximum of ~2 hours. + * 65535 * 0.125s ~ 8192 s = 2.27 hours */ -static void system_set_htimer_alarm(uint32_t seconds, +void system_set_htimer_alarm(uint32_t seconds, uint32_t microseconds) { - uint32_t hcnt; - - if (microseconds >= 1000000) { - seconds += microseconds / 1000000; - microseconds -= (microseconds / 1000000) * 1000000; - } + uint32_t hcnt, ns; + uint8_t hctrl; - if (seconds || microseconds) { - - /* if (seconds > 2) { */ - if (seconds > 1) { - /* count from 2 sec to 2 hrs, mec1322 sec 18.10.2 */ - ASSERT(seconds <= 0xffff / 8); - /* 0.125(=1/8) per clock */ - MCHP_HTIMER_CONTROL(0) = 1; - /* (number of counts to be loaded) - * = seconds * ( 8 clocks per second ) - * + microseconds / 125000 - * ---> (0 if (microseconds < 125000) - */ - hcnt = (seconds * 8 + microseconds / 125000); + MCHP_HTIMER_PRELOAD(0) = 0; /* disable */ - } else { /* count up to 2 sec. */ - /* 30.5(= 2/61) usec */ - MCHP_HTIMER_CONTROL(0) = 0; + trace12(0, SLP, 0, "sys set htimer: sec=%d us=%d", + seconds, microseconds); - /* (number of counts to be loaded) - * = (total microseconds) / 30.5; - */ - hcnt = (seconds * 1000000 + microseconds) * - 2 / 61; - } + if (microseconds > 1000000ul) { + ns = (microseconds / 1000000ul); + microseconds %= 1000000ul; + if ((0xfffffffful - seconds) > ns) + seconds += ns; + else + seconds = 0xfffffffful; + } - MCHP_HTIMER_PRELOAD(0) = hcnt; + if (seconds > 1) { + hcnt = (seconds << 3); /* divide by 0.125 */ + if (hcnt > 0xfffful) + hcnt = 0xfffful; + hctrl = 1; + } else { + /* + * approximate(~2% error) as seconds is 0 or 1 + * seconds / 30.5e-6 + microseonds / 30.5 + */ + hcnt = (seconds << 15) + (microseconds >> 5) + + (microseconds >> 10); + hctrl = 0; } + + trace12(0, SLP, 0, + "sys set htimer: ctrl=0x%0x preload=0x%0x", + hctrl, hcnt); + MCHP_HTIMER_CONTROL(0) = hctrl; + MCHP_HTIMER_PRELOAD(0) = hcnt; } +#ifdef CONFIG_LOW_POWER_IDLE + /** * return time slept in micro-seconds */ @@ -340,17 +346,19 @@ static void prepare_for_deep_sleep(void) /* Stop timers */ MCHP_TMR32_CTL(0) &= ~1; MCHP_TMR32_CTL(1) &= ~1; +#ifdef CONFIG_WATCHDOG_HELP MCHP_TMR16_CTL(0) &= ~1; + MCHP_INT_DISABLE(MCHP_TMR16_GIRQ) = + MCHP_TMR16_GIRQ_BIT(0); + MCHP_INT_SOURCE(MCHP_TMR16_GIRQ) = + MCHP_TMR16_GIRQ_BIT(0); +#endif MCHP_INT_DISABLE(MCHP_TMR32_GIRQ) = MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); MCHP_INT_SOURCE(MCHP_TMR32_GIRQ) = MCHP_TMR32_GIRQ_BIT(0) + MCHP_TMR32_GIRQ_BIT(1); - MCHP_INT_DISABLE(MCHP_TMR16_GIRQ) = - MCHP_TMR16_GIRQ_BIT(0); - MCHP_INT_SOURCE(MCHP_TMR16_GIRQ) = - MCHP_TMR16_GIRQ_BIT(0); #ifdef CONFIG_WATCHDOG /* Stop watchdog */ @@ -359,19 +367,11 @@ static void prepare_for_deep_sleep(void) #ifdef CONFIG_HOSTCMD_ESPI - #ifdef CONFIG_POWER_S0IX MCHP_INT_SOURCE(22) = MCHP_INT22_WAKE_ONLY_ESPI; MCHP_INT_ENABLE(22) = MCHP_INT22_WAKE_ONLY_ESPI; - #else - MCHP_ESPI_ACTIVATE &= ~1; - #endif #else - #ifdef CONFIG_POWER_S0IX MCHP_INT_SOURCE(22) = MCHP_INT22_WAKE_ONLY_LPC; MCHP_INT_ENABLE(22) = MCHP_INT22_WAKE_ONLY_LPC; - #else - MCHP_LPC_ACT |= 1; - #endif #endif #ifdef CONFIG_ADC @@ -402,7 +402,7 @@ static void prepare_for_deep_sleep(void) #ifdef CONFIG_CHIPSET_DEBUG /* Disable JTAG and preserve mode */ - /* MCHP_EC_JTAG_EN &= ~(MCHP_JTAG_ENABLE); */ + MCHP_EC_JTAG_EN &= ~(MCHP_JTAG_ENABLE); #endif /* call board level */ diff --git a/chip/mchp/clock_chip.h b/chip/mchp/clock_chip.h new file mode 100644 index 0000000000..2e7de60358 --- /dev/null +++ b/chip/mchp/clock_chip.h @@ -0,0 +1,17 @@ +/* Copyright 2017 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. + */ + +/* Microchip MEC1701 specific module for Chrome EC */ + +#ifndef __CROS_EC_CLOCK_CHIP_H +#define __CROS_EC_CLOCK_CHIP_H + +#include <stdint.h> + +void htimer_init(void); +void system_set_htimer_alarm(uint32_t seconds, + uint32_t microseconds); + +#endif /* __CROS_EC_I2C_CLOCK_H */ diff --git a/chip/mchp/config_chip.h b/chip/mchp/config_chip.h index 183440a8c4..8c1cab81a5 100644 --- a/chip/mchp/config_chip.h +++ b/chip/mchp/config_chip.h @@ -27,7 +27,6 @@ */ #define CONFIG_CHIP_PRE_INIT - /* * MCHP EC's have I2C master/slave * controllers and multiple I2C ports. Any diff --git a/chip/mchp/system.c b/chip/mchp/system.c index fa844a2304..689675716d 100644 --- a/chip/mchp/system.c +++ b/chip/mchp/system.c @@ -19,6 +19,7 @@ #include "timer.h" #include "util.h" #include "spi.h" +#include "clock_chip.h" #include "lpc_chip.h" #include "tfdp_chip.h" @@ -51,7 +52,6 @@ static void check_reset_cause(void) MCHP_VBAT_STS |= status; MCHP_PCR_PWR_RST_STS |= rst_sts; - trace0(0, MEC, 0, "check_reset_cause: after clear"); trace11(0, MEC, 0, " VBAT_PFR = 0x%08X", MCHP_VBAT_STS); trace11(0, MEC, 0, " PCR PWRST = 0x%08X", MCHP_PCR_PWR_RST_STS); @@ -133,16 +133,35 @@ static void chip_periph_sleep_control(void) #ifdef CONFIG_CHIP_PRE_INIT void chip_pre_init(void) { +#ifdef CONFIG_MCHP_TFDP + uint8_t imgtype; +#endif chip_periph_sleep_control(); + +#ifdef CONFIG_MCHP_TFDP + /* + * MCHP Enable TFDP for fast debug messages + * If not defined then traceN() and TRACEN() macros are empty + */ + tfdp_power(1); + tfdp_enable(1, 1); + imgtype = MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX); + CPRINTS("chip_pre_init: Image type = 0x%02x", imgtype); + trace1(0, MEC, 0, + "chip_pre_init: Image type = 0x%02x", imgtype); + + trace11(0, MEC, 0, + "chip_pre_init: MCHP_VBAT_STS = 0x%0x", + MCHP_VBAT_STS); + trace11(0, MEC, 0, + "chip_pre_init: MCHP_PCR_PWR_RST_STS = 0x%0x", + MCHP_VBAT_STS); +#endif } #endif void system_pre_init(void) { -#ifdef CONFIG_MCHP_TFDP - uint8_t imgtype; -#endif - /* * Make sure AHB Error capture is enabled. * Signals bus fault to Cortex-M4 core if an address presented @@ -178,37 +197,6 @@ void system_pre_init(void) MCHP_INT_BLK_EN = (0x1Ful << 8) + (0x07ul << 24); spi_enable(CONFIG_SPI_FLASH_PORT, 1); - -#ifdef CONFIG_MCHP_TFDP - /* - * MCHP Enable TFDP for fast debug messages - * If not defined then traceN() and TRACEN() macros are empty - */ - tfdp_power(1); - tfdp_enable(1, 1); - imgtype = MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX); - CPRINTS("system_pre_init. Image type = 0x%02x", imgtype); - trace1(0, MEC, 0, "System pre-init. Image type = 0x%02x", imgtype); - - /* Debug: dump some signals */ - imgtype = gpio_get_level(GPIO_PCH_RSMRST_L); - trace1(0, MEC, 0, "PCH_RSMRST_L = %d", imgtype); - - imgtype = gpio_get_level(GPIO_RSMRST_L_PGOOD); - trace1(0, MEC, 0, "RSMRST_L_PGOOD = %d", imgtype); - imgtype = gpio_get_level(GPIO_POWER_BUTTON_L); - trace1(0, MEC, 0, "POWER_BUTTON_L = %d", imgtype); - imgtype = gpio_get_level(GPIO_PMIC_DPWROK); - trace1(0, MEC, 0, "PMIC_DPWROK = %d", imgtype); - imgtype = gpio_get_level(GPIO_ALL_SYS_PWRGD); - trace1(0, MEC, 0, "ALL_SYS_PWRGD = %d", imgtype); - imgtype = gpio_get_level(GPIO_AC_PRESENT); - trace1(0, MEC, 0, "AC_PRESENT = %d", imgtype); - imgtype = gpio_get_level(GPIO_PCH_SLP_SUS_L); - trace1(0, MEC, 0, "PCH_SLP_SUS_L = %d", imgtype); - imgtype = gpio_get_level(GPIO_PMIC_INT_L); - trace1(0, MEC, 0, "PCH_PMIC_INT_L = %d", imgtype); -#endif } void chip_save_reset_flags(int flags) @@ -249,7 +237,8 @@ void __attribute__((noreturn)) _system_reset(int flags, /* * Trigger chip reset */ -#ifndef CONFIG_CHIPSET_DEBUG +#if defined(CONFIG_CHIPSET_DEBUG) +#else MCHP_PCR_SYS_RST |= MCHP_PCR_SYS_SOFT_RESET; #endif /* Spin and wait for reboot; should never return */ @@ -364,33 +353,34 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) /* Disable interrupts */ interrupt_disable(); - for (i = 0; i <= 92; ++i) { + for (i = 0; i < MCHP_IRQ_MAX; ++i) { task_disable_irq(i); task_clear_pending_irq(i); } - for (i = 8; i <= 26; ++i) + for (i = MCHP_INT_GIRQ_FIRST; i <= MCHP_INT_GIRQ_LAST; ++i) { MCHP_INT_DISABLE(i) = 0xffffffff; - - MCHP_INT_BLK_DIS |= 0xffff00; + MCHP_INT_SOURCE(i) = 0xffffffff; + } /* Disable UART */ MCHP_UART_ACT(0) &= ~0x1; +#ifdef CONFIG_HOSTCMD_ESPI + MCHP_ESPI_ACTIVATE &= ~0x01; +#else MCHP_LPC_ACT &= ~0x1; - +#endif /* Disable JTAG */ MCHP_EC_JTAG_EN &= ~1; - /* Disable 32KHz clock */ - MCHP_VBAT_CE &= ~0x2; - /* Stop watchdog */ MCHP_WDG_CTL &= ~1; /* Stop timers */ MCHP_TMR32_CTL(0) &= ~1; MCHP_TMR32_CTL(1) &= ~1; - MCHP_TMR16_CTL(0) &= ~1; + for (i = 0; i < MCHP_TMR16_MAX; i++) + MCHP_TMR16_CTL(i) &= ~1; /* Power down ADC */ /* @@ -401,14 +391,6 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) /* Disable blocks */ MCHP_PCR_SLOW_CLK_CTL &= ~(MCHP_PCR_SLOW_CLK_CTL_MASK); - /* - * Set sleep state - * arm sleep state to trigger on next WFI - */ - CPU_SCB_SYSCTRL |= 0x4; - MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_HEAVY; - MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_ALL; - /* Setup GPIOs for hibernate */ if (board_hibernate_late) board_hibernate_late(); @@ -427,34 +409,36 @@ void system_hibernate(uint32_t seconds, uint32_t microseconds) task_enable_irq(MCHP_IRQ_GIRQ10); task_enable_irq(MCHP_IRQ_GIRQ11); task_enable_irq(MCHP_IRQ_GIRQ12); + task_enable_irq(MCHP_IRQ_GIRQ26); } if (seconds || microseconds) { - /* - * Not needed when using direct mode interrupts. - * MCHP_INT_BLK_EN |= 1 << MCHP_HTIMER_GIRQ; - */ - MCHP_INT_ENABLE(MCHP_HTIMER_GIRQ) = - MCHP_HTIMER_GIRQ_BIT(0); + htimer_init(); + system_set_htimer_alarm(seconds, microseconds); interrupt_enable(); - task_enable_irq(MCHP_IRQ_HTIMER0); - if (seconds > 2) { - ASSERT(seconds <= 0xffff / 8); - MCHP_HTIMER_CONTROL(0) = 1; - MCHP_HTIMER_PRELOAD(0) = - (seconds * 8 + microseconds / 125000); - } else { - MCHP_HTIMER_CONTROL(0) = 0; - MCHP_HTIMER_PRELOAD(0) = - (seconds * 1000000 + microseconds) * 2 / 71; - } + } else { + /* Not using hibernation timer. Disable 32KHz clock */ + MCHP_VBAT_CE &= ~0x2; } + /* + * Set sleep state + * arm sleep state to trigger on next WFI + */ + CPU_SCB_SYSCTRL |= 0x4; + MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_HEAVY; + MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_ALL; + + asm("dsb"); asm("wfi"); + asm("isb"); + asm("nop"); /* Use 48MHz clock to speed through wake-up */ MCHP_PCR_PROC_CLK_CTL = 1; + trace0(0, SYS, 0, "Wake from hibernate: _system_reset[0,1]"); + /* Reboot */ _system_reset(0, 1); diff --git a/include/config.h b/include/config.h index b42a6e54d1..6ad80d77e5 100644 --- a/include/config.h +++ b/include/config.h @@ -459,6 +459,11 @@ */ #undef CONFIG_BOARD_FORCE_RESET_PIN +/* + * Call board level configuration at the end of chip level system pre-init. + */ +#undef CONFIG_BOARD_SYS_PRE_INIT + /* Permanent LM4 boot configuration */ #undef CONFIG_BOOTCFG_VALUE |