diff --git a/src/board/system76/common/include/board/smfi.h b/src/board/system76/common/include/board/smfi.h index 56b4a119d..8335b1c28 100644 --- a/src/board/system76/common/include/board/smfi.h +++ b/src/board/system76/common/include/board/smfi.h @@ -6,7 +6,6 @@ #include void smfi_init(void); -void smfi_watchdog(void); void smfi_event(void); void smfi_debug(uint8_t byte); diff --git a/src/board/system76/common/main.c b/src/board/system76/common/main.c index c5b0194ca..b47a0a7fc 100644 --- a/src/board/system76/common/main.c +++ b/src/board/system76/common/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef PARALLEL_DEBUG #include @@ -96,6 +97,8 @@ void main(void) { gpio_debug(); #endif + wdt_init(); + INFO("System76 EC board '%s', version '%s'\n", board(), version()); systick_t last_time_battery = 0; @@ -164,6 +167,9 @@ void main(void) { pmc_event(&PMC_1); // AP/EC communication over SMFI smfi_event(); + + wdt_kick(); + // Idle until next timer interrupt //Disabled until interrupts used: PCON |= 1; } diff --git a/src/board/system76/common/scratch.c b/src/board/system76/common/scratch.c index 6ea515ffc..fb7cc26ec 100644 --- a/src/board/system76/common/scratch.c +++ b/src/board/system76/common/scratch.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -24,8 +25,8 @@ void scratch_trampoline(void) { //TODO: Clear keyboard presses - // Start watchdog timer - smfi_watchdog(); + // Restart WDT before entry to scratch ROM + wdt_kick(); // Disable interrupts EA = 0; diff --git a/src/board/system76/common/smfi.c b/src/board/system76/common/smfi.c index f33166f30..f3532fccd 100644 --- a/src/board/system76/common/smfi.c +++ b/src/board/system76/common/smfi.c @@ -337,26 +337,17 @@ static enum Result cmd_reset(void) { #endif // !defined(__SCRATCH__) - // Attempt to trigger watchdog reset - ETWCFG |= BIT(5); - EWDKEYR = 0; + wdt_trigger(); // Failed if it got this far return RES_ERR; } -// Set a watchdog timer of 10 seconds -void smfi_watchdog(void) { - ET1CNTLLR = 0xFF; - EWDCNTLLR = 0xFF; - EWDCNTLHR = 0x04; -} - void smfi_event(void) { if (smfi_cmd[SMFI_CMD_CMD]) { #if defined(__SCRATCH__) // If in scratch ROM, restart watchdog timer when command received - smfi_watchdog(); + wdt_kick(); #endif switch (smfi_cmd[SMFI_CMD_CMD]) { diff --git a/src/ec/ite/ec.mk b/src/ec/ite/ec.mk index d61fa25ef..048008009 100644 --- a/src/ec/ite/ec.mk +++ b/src/ec/ite/ec.mk @@ -2,6 +2,7 @@ ec-y += ec.c ec-$(CONFIG_BUS_ESPI) += espi.c +ec-y += etwd.c ec-y += gpio.c ec-y += i2c.c ec-y += intc.c diff --git a/src/ec/ite/etwd.c b/src/ec/ite/etwd.c new file mode 100644 index 000000000..dd9417514 --- /dev/null +++ b/src/ec/ite/etwd.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-only + +// External Timer and External Watchdog (ETWD) + +#include +#include + +enum EwtCfg { + // Lock EWTCFG register + LETWCFG = BIT(0), + // Lock ET1PS register + LETPS1 = BIT(1), + // Lock ET1CNTLx registers + LET1CNTL = BIT(2), + // Lock EWDCNTLx registers + LEWDCNTL = BIT(3), + // External WDT clock source + EWDSRC = BIT(4), + // Enable key match function to touch the WDT + EWDKEYEN = BIT(5), + // Lock ET1 and EWDT registers + LOCK_ALL = LETWCFG | LETPS1 | LET1CNTL | LEWDCNTL, +}; + +enum EtwdPrescaler { + ETWD_PRESCALER_32768_HZ = 0, + ETWD_PRESCALER_1024_HZ = 1, + ETWD_PRESCALER_32_HZ = 2, + ETWD_PRESCALER_EC_CLK = 3, // Not available for ET1PS +}; + +void wdt_init(void) { + ET1PSR = ETWD_PRESCALER_1024_HZ; + ETWCFG = EWDKEYEN | EWDSRC; + + // Start ET1 so EWDT can be started + ET1CNTLLR = 0xFF; + + // Start EWDT with timeout of 8s + // TODO: Determine time based on system performance + EWDCNTLHR = 0x20; + EWDCNTLLR = 0; + + ETWCFG |= LOCK_ALL; +} diff --git a/src/ec/ite/include/ec/etwd.h b/src/ec/ite/include/ec/etwd.h index bfc75616f..467d7ac17 100644 --- a/src/ec/ite/include/ec/etwd.h +++ b/src/ec/ite/include/ec/etwd.h @@ -1,7 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only -#ifndef _EC_ECWD_H -#define _EC_ECWD_H +// External Timer and External Watchdog (ETWD) + +#ifndef _EC_ETWD_H +#define _EC_ETWD_H #include @@ -27,4 +29,22 @@ volatile uint8_t __xdata __at(0x1F13) ET3CNTLH2R; volatile uint8_t __xdata __at(0x1F16) ET4CNTLLR; #endif -#endif // _EC_ECWD_H +// When the key match function of EWD is enabled (EWTCFG[5]), writing this +// value to EWDKEY will restart the WDT. +#define WDT_KEY 0x5C + +void wdt_init(void); + +// Restart WDT +// NOTE: Must be inlined for compiling in Scratch ROM +static inline void wdt_kick(void) { + EWDKEYR = WDT_KEY; +} + +// Trigger EC reset by WDT key mismatch +// NOTE: Must be inlined for compiling in Scratch ROM +static inline void wdt_trigger(void) { + EWDKEYR = 0; +} + +#endif // _EC_ETWD_H