diff options
author | Wealian Liao <whliao@nuvoton.corp-partner.google.com> | 2021-02-17 16:00:41 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-02-22 23:41:45 +0000 |
commit | a384e42b985225aaa20e60ce2574dc8b6d782fc8 (patch) | |
tree | 2bf0ddffc06fc8677613ec0c67481283a9e749ac /zephyr/drivers/cros_system/cros_system_npcx.c | |
parent | 400929c7d00bde06c1cc5668c5bececd045b3d1f (diff) | |
download | chrome-ec-a384e42b985225aaa20e60ce2574dc8b6d782fc8.tar.gz |
zephyr: npcx: add system reset driver
This CL include the following:
1. Add cros_system_soc_reset() API for system reset.
2. Add NPCX soc reset driver. NPCX chip doesn't have the specific
system reset functionality. Use watchdog reset as the system reset.
BUG=b:176523207
BRANCH=None.
TEST=reset EC by 'reboot' console command
Signed-off-by: Wealian Liao <whliao@nuvoton.corp-partner.google.com>
Change-Id: Ia86bfac548ef48e18e501a29f3cbb632f33a3e8a
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2698739
Reviewed-by: Simon Glass <sjg@chromium.org>
Commit-Queue: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'zephyr/drivers/cros_system/cros_system_npcx.c')
-rw-r--r-- | zephyr/drivers/cros_system/cros_system_npcx.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c index 87db955e4a..b63743a13d 100644 --- a/zephyr/drivers/cros_system/cros_system_npcx.c +++ b/zephyr/drivers/cros_system/cros_system_npcx.c @@ -4,6 +4,7 @@ */ #include <drivers/cros_system.h> +#include <drivers/watchdog.h> #include <logging/log.h> #include <soc.h> @@ -29,6 +30,16 @@ struct cros_system_npcx_data { #define DRV_DATA(dev) ((struct cros_system_npcx_data *)(dev)->data) +/* + * For cortex-m we cannot use irq_lock() for disabling all the interrupts + * because it leaves some (NMI and faults) still enabled. Use "cpsid i" to + * replace it. + */ +static inline void interrupt_disable_all(void) +{ + __asm__("cpsid i"); +} + static int cros_system_npcx_get_reset_cause(const struct device *dev) { struct cros_system_npcx_data *data = DRV_DATA(dev); @@ -58,6 +69,52 @@ static int cros_system_npcx_init(const struct device *dev) return 0; } +static int cros_system_npcx_soc_reset(const struct device *dev) +{ + struct twd_reg *const inst_twd = HAL_TWD_INST(dev); + + /* Disable interrupts to avoid task swaps during reboot */ + interrupt_disable_all(); + + /* + * NPCX chip doesn't have the specific system reset functionality. Use + * watchdog reset as a system reset. + */ + + /* Stop the watchdog */ + if (IS_ENABLED(CONFIG_WATCHDOG)) { + const struct device *wdt_dev = device_get_binding( + DT_LABEL(DT_INST(0, nuvoton_npcx_watchdog))); + + if (!wdt_dev) { + LOG_ERR("wdt_dev get binding failed"); + return -ENODEV; + } + + wdt_disable(wdt_dev); + } + + /* Enable early touch */ + inst_twd->T0CSR &= ~BIT(NPCX_T0CSR_TESDIS); + inst_twd->TWCFG |= BIT(NPCX_TWCFG_WDSDME); + + /* + * The trigger of a watchdog event by a "too early service" condition. + * When the watchdog is written more than once during three watchdog + * clock cycle. + */ + inst_twd->WDSDM = 0x5C; + inst_twd->WDSDM = 0x5C; + + /* Wait for the soc reset. */ + while (1) { + ; + } + + /* should never return */ + return 0; +} + static struct cros_system_npcx_data cros_system_npcx_dev_data; static const struct cros_system_npcx_config cros_system_dev_cfg = { @@ -67,6 +124,7 @@ static const struct cros_system_npcx_config cros_system_dev_cfg = { static const struct cros_system_driver_api cros_system_driver_npcx_api = { .get_reset_cause = cros_system_npcx_get_reset_cause, + .soc_reset = cros_system_npcx_soc_reset, }; /* |