summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscott worley <scott.worley@microchip.corp-partner.google.com>2018-05-10 13:59:52 -0400
committerchrome-bot <chrome-bot@chromium.org>2018-06-12 21:50:56 -0700
commitf83b350444ec7a543378589d7533be6514129288 (patch)
tree62a8cce69090048ed881a0a1a223bc5603779b98
parent201c5fb497d2c810eb95c9ddf05835adcde63b12 (diff)
downloadchrome-ec-f83b350444ec7a543378589d7533be6514129288.tar.gz
ec_chip_mchp: Fix hibernation timer and wake programming
Hibernation timer was not programmed to correct value for some cases and code was duplicated. Not all interrupt sources were properly configured in system hibernate. Remove debug only system pre-init board level call. BRANCH=none BUG=none TEST=Build all boards using chip mchp. Test with EC UART hibernate command. CQ-DEPEND=CL:1053576 Change-Id: I932443fa7a4e284168babdbb7f64033a55427fb2 Signed-off-by: scott worley <scott.worley@microchip.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/1053956 Commit-Ready: Randall Spangler <rspangler@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/mchp/clock.c100
-rw-r--r--chip/mchp/clock_chip.h17
-rw-r--r--chip/mchp/config_chip.h1
-rw-r--r--chip/mchp/system.c126
-rw-r--r--include/config.h5
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