summaryrefslogtreecommitdiff
path: root/zephyr/drivers/cros_system/cros_system_npcx.c
diff options
context:
space:
mode:
authorWealian Liao <whliao@nuvoton.corp-partner.google.com>2021-02-17 16:00:41 +0800
committerCommit Bot <commit-bot@chromium.org>2021-02-22 23:41:45 +0000
commita384e42b985225aaa20e60ce2574dc8b6d782fc8 (patch)
tree2bf0ddffc06fc8677613ec0c67481283a9e749ac /zephyr/drivers/cros_system/cros_system_npcx.c
parent400929c7d00bde06c1cc5668c5bececd045b3d1f (diff)
downloadchrome-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.c58
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,
};
/*