summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2019-09-06 11:33:48 -0600
committerCommit Bot <commit-bot@chromium.org>2019-09-12 05:04:17 +0000
commit031c5d2d62dd891622ded885756c03021e934ef2 (patch)
treebddaeeeb33e89134f538795d050d5874649ef90f
parent8d9ddb34ed3465e5172c6d950a155c83dd6d5aa9 (diff)
downloadchrome-ec-031c5d2d62dd891622ded885756c03021e934ef2.tar.gz
npcx: ensure we don't unlock watchdog too soon
We cannot unlock the watchdog timer with 3 watch dog ticks of touching it per the datasheet. This is actually around 100ms so we should protect against this. BRANCH=none BUG=b:140207603 TEST=eliminates cold reset issue. Change-Id: Iaef59dad9f5640d64d5d430aea87bd16c2efd30d Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1790302 Reviewed-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Reviewed-by: ML Chao <mlchao@nuvoton.corp-partner.google.com> Reviewed-by: Furquan Shaikh <furquan@chromium.org> Tested-by: Furquan Shaikh <furquan@chromium.org> Commit-Queue: Furquan Shaikh <furquan@chromium.org>
-rw-r--r--chip/npcx/spiflashfw/npcx_monitor.c4
-rw-r--r--chip/npcx/system.c8
-rw-r--r--chip/npcx/system_chip.h5
-rw-r--r--chip/npcx/watchdog.c28
4 files changed, 32 insertions, 13 deletions
diff --git a/chip/npcx/spiflashfw/npcx_monitor.c b/chip/npcx/spiflashfw/npcx_monitor.c
index a0b011476d..cc327e3440 100644
--- a/chip/npcx/spiflashfw/npcx_monitor.c
+++ b/chip/npcx/spiflashfw/npcx_monitor.c
@@ -287,9 +287,7 @@ sspi_flash_upload(int spi_offset, int spi_size)
}
/* Unlock & stop watchdog */
- NPCX_WDSDM = 0x87;
- NPCX_WDSDM = 0x61;
- NPCX_WDSDM = 0x63;
+ watchdog_stop_and_unlock();
/* UMA Unlock */
CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index ff18334533..e7895dc3dc 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -44,9 +44,7 @@
void system_watchdog_reset(void)
{
/* Unlock & stop watchdog registers */
- NPCX_WDSDM = 0x87;
- NPCX_WDSDM = 0x61;
- NPCX_WDSDM = 0x63;
+ watchdog_stop_and_unlock();
/* Reset TWCFG */
NPCX_TWCFG = 0;
@@ -500,9 +498,7 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN);
/* Unlock & stop watchdog */
- NPCX_WDSDM = 0x87;
- NPCX_WDSDM = 0x61;
- NPCX_WDSDM = 0x63;
+ watchdog_stop_and_unlock();
/* Initialize watchdog */
NPCX_TWCFG = 0; /* Select T0IN clock as watchdog prescaler clock */
diff --git a/chip/npcx/system_chip.h b/chip/npcx/system_chip.h
index 5ca686a86f..2836a1e4f7 100644
--- a/chip/npcx/system_chip.h
+++ b/chip/npcx/system_chip.h
@@ -30,9 +30,12 @@ enum bbram_data_index {
BBRM_DATA_INDEX_PANIC_BKUP = 36, /* Panic data (index 35-63)*/
};
-/* Issue a watchdog reset*/
+/* Issue a watchdog reset */
void system_watchdog_reset(void);
+/* Stops the watchdog timer and unlocks configuration. */
+void watchdog_stop_and_unlock(void);
+
/*
* Configure the specific memory addresses in the the MPU
* (Memory Protection Unit) for Nuvoton different chip series.
diff --git a/chip/npcx/watchdog.c b/chip/npcx/watchdog.c
index 44a980326b..233c875643 100644
--- a/chip/npcx/watchdog.c
+++ b/chip/npcx/watchdog.c
@@ -58,6 +58,27 @@ static uint8_t watchdog_count(void)
return cnt;
}
+static timestamp_t last_watchdog_touch;
+void watchdog_stop_and_unlock(void)
+{
+ /*
+ * Ensure we have waited at least 3 watchdog ticks since touching WD
+ * timer. 3 / (32768 / 1024) HZ = 93.75ms
+ */
+ while (time_since32(last_watchdog_touch) < (100 * MSEC))
+ continue;
+
+ NPCX_WDSDM = 0x87;
+ NPCX_WDSDM = 0x61;
+ NPCX_WDSDM = 0x63;
+}
+
+static void touch_watchdog_count(void)
+{
+ NPCX_WDSDM = 0x5C;
+ last_watchdog_touch = get_time();
+}
+
void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
{
int wd_cnt;
@@ -75,7 +96,8 @@ void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
* Touch watchdog to let UART have enough time
* to print panic info
*/
- NPCX_WDSDM = 0x5C;
+ touch_watchdog_count();
+
/* Print panic info */
watchdog_trace(excep_lr, excep_sp);
cflush();
@@ -112,7 +134,7 @@ void watchdog_reload(void)
#if 1 /* mark this for testing watchdog */
/* Touch watchdog & reset software counter */
- NPCX_WDSDM = 0x5C;
+ touch_watchdog_count();
#endif
/* Enable watchdog interrupt */
@@ -125,7 +147,7 @@ int watchdog_init(void)
#if SUPPORT_WDG
/* Touch watchdog before init if it is already running */
if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WD_RUN))
- NPCX_WDSDM = 0x5C;
+ touch_watchdog_count();
/* Keep prescaler ratio timer0 clock to 1:1024 */
NPCX_TWCP = 0x0A;