summaryrefslogtreecommitdiff
path: root/zephyr
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr')
-rw-r--r--zephyr/Kconfig2
-rw-r--r--zephyr/Kconfig.system18
-rw-r--r--zephyr/drivers/cros_bbram/Kconfig16
-rw-r--r--zephyr/drivers/cros_bbram/cros_bbram_npcx.c8
-rw-r--r--zephyr/drivers/cros_system/Kconfig13
-rw-r--r--zephyr/drivers/cros_system/cros_system_npcx.c5
-rw-r--r--zephyr/shim/chip/npcx/Kconfig.npcx18
-rw-r--r--zephyr/shim/chip/npcx/system.c78
-rw-r--r--zephyr/shim/src/system.c173
9 files changed, 288 insertions, 43 deletions
diff --git a/zephyr/Kconfig b/zephyr/Kconfig
index b054d85372..4c3dc5849a 100644
--- a/zephyr/Kconfig
+++ b/zephyr/Kconfig
@@ -31,6 +31,7 @@ menuconfig PLATFORM_EC
if PLATFORM_EC
+rsource "shim/chip/npcx/Kconfig.npcx"
rsource "Kconfig.adc"
rsource "Kconfig.battery"
rsource "Kconfig.console"
@@ -39,6 +40,7 @@ rsource "Kconfig.keyboard"
rsource "Kconfig.led"
rsource "Kconfig.powerseq"
rsource "Kconfig.motionsense"
+rsource "Kconfig.system"
rsource "Kconfig.tasks"
rsource "Kconfig.temperature"
rsource "Kconfig.usbc"
diff --git a/zephyr/Kconfig.system b/zephyr/Kconfig.system
new file mode 100644
index 0000000000..d8ae87b149
--- /dev/null
+++ b/zephyr/Kconfig.system
@@ -0,0 +1,18 @@
+# Copyright 2021 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.
+
+if PLATFORM_EC
+
+config PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY
+ int "System pre-initialization priority"
+ default 20
+ range 0 99
+ help
+ This defines the initialization priority for the CROS
+ system_pre_init() function. system_pre_init() reads chip level reset
+ cause and stores it into the system reset flags. All drivers, except
+ those critical to determining the reset type, should be initialized at
+ lower priority so that the system reset flags are valid.
+
+endif # PLATFORM_EC
diff --git a/zephyr/drivers/cros_bbram/Kconfig b/zephyr/drivers/cros_bbram/Kconfig
index ba7ce8b1ad..43850b032a 100644
--- a/zephyr/drivers/cros_bbram/Kconfig
+++ b/zephyr/drivers/cros_bbram/Kconfig
@@ -7,4 +7,18 @@ menuconfig CROS_BBRAM_NPCX
depends on SOC_FAMILY_NPCX
default y
help
- This options enables stuff. \ No newline at end of file
+ This options enables stuff.
+
+if CROS_BBRAM_NPCX
+
+config CROS_BBRAM_NPCX_INIT_PRIORITY
+ int "cros_bbram npcx initialization priority"
+ default 11
+ range 10 19
+ help
+ This sets the npcx cros_bbram driver initialization priority. NPCX
+ chip uses BBRAM to save some system information that persists across
+ chip resets. The priority should be higher than
+ SYSTEM_PRE_INIT_PRIORITY & lower than CROS_SYSTEM_NPCX_INIT_PRIORITY.
+
+endif # CROS_BBRAM_NPCX
diff --git a/zephyr/drivers/cros_bbram/cros_bbram_npcx.c b/zephyr/drivers/cros_bbram/cros_bbram_npcx.c
index f6fa64fdd2..20698df85b 100644
--- a/zephyr/drivers/cros_bbram/cros_bbram_npcx.c
+++ b/zephyr/drivers/cros_bbram/cros_bbram_npcx.c
@@ -126,6 +126,12 @@ static int bbram_npcx_init(const struct device *dev)
/*
* The priority of bbram_npcx_init() should lower than cros_system_npcx_init().
*/
+#if (CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY <= \
+ CONFIG_CROS_SYSTEM_NPCX_INIT_PRIORITY)
+#error CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY must greater than \
+ CONFIG_CROS_SYSTEM_NPCX_INIT_PRIORITY
+#endif
+
#define CROS_BBRAM_INIT(inst) \
static struct { \
} cros_bbram_data_##inst; \
@@ -137,7 +143,7 @@ static int bbram_npcx_init(const struct device *dev)
DEVICE_DEFINE(cros_bbram_npcx_##inst, DT_INST_LABEL(inst), \
bbram_npcx_init, NULL, &cros_bbram_data_##inst, \
&cros_bbram_cfg_##inst, PRE_KERNEL_1, \
- CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
+ CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY, \
&cros_bbram_npcx_driver_api);
DT_INST_FOREACH_STATUS_OKAY(CROS_BBRAM_INIT);
diff --git a/zephyr/drivers/cros_system/Kconfig b/zephyr/drivers/cros_system/Kconfig
index e1e7163f99..09d47ad7e7 100644
--- a/zephyr/drivers/cros_system/Kconfig
+++ b/zephyr/drivers/cros_system/Kconfig
@@ -11,3 +11,16 @@ menuconfig CROS_SYSTEM_NPCX
processors. Currently, Zephyr doesn't provide the system related API.
The cros system driver provides the low-level driver related to
chromium ec system functionality.
+
+if CROS_SYSTEM_NPCX
+
+config CROS_SYSTEM_NPCX_INIT_PRIORITY
+ int "cros_system npcx initialization priority"
+ default 10
+ range 10 19
+ help
+ This sets the npcx cros_system driver initialization priority. The
+ cros_system driver provides access to the NPCX reset cause and must be
+ higher priority than CONFIG_SYSTEM_PRE_INIT_PRIORITY.
+
+endif # CROS_SYSTEM_NPCX
diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c
index b21219355d..48e33188cf 100644
--- a/zephyr/drivers/cros_system/cros_system_npcx.c
+++ b/zephyr/drivers/cros_system/cros_system_npcx.c
@@ -128,12 +128,13 @@ static const struct cros_system_driver_api cros_system_driver_npcx_api = {
};
/*
- * The priority of cros_system_npcx_init() should be lower than watchdog init
+ * The priority of cros_system_npcx_init() should be higher than watchdog init
* for reset cause check.
*/
DEVICE_DEFINE(cros_system_npcx_0, "CROS_SYSTEM", cros_system_npcx_init, NULL,
&cros_system_npcx_dev_data, &cros_system_dev_cfg, PRE_KERNEL_1,
- 30, &cros_system_driver_npcx_api);
+ CONFIG_CROS_SYSTEM_NPCX_INIT_PRIORITY,
+ &cros_system_driver_npcx_api);
#define HAL_DBG_REG_BASE_ADDR \
((struct dbg_reg *)DT_REG_ADDR(DT_INST(0, nuvoton_npcx_cros_dbg)))
diff --git a/zephyr/shim/chip/npcx/Kconfig.npcx b/zephyr/shim/chip/npcx/Kconfig.npcx
new file mode 100644
index 0000000000..1107a846a8
--- /dev/null
+++ b/zephyr/shim/chip/npcx/Kconfig.npcx
@@ -0,0 +1,18 @@
+# Copyright 2021 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.
+
+if PLATFORM_EC
+
+config CROS_SYSTEM_NPCX_PRE_INIT_PRIORITY
+ int "System pre-initialization priority"
+ default 15
+ range 10 19
+ depends on SOC_FAMILY_NPCX
+ help
+ This sets the priority of the NPCX chip system initialization. The
+ chip system initialization verifies the integrity of the BBRAM and
+ must be a lower priority than CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY and
+ must be a higher priority than PLATFORM_EC_SYSTEM_PRE_INIT.
+
+endif # PLATFORM_EC
diff --git a/zephyr/shim/chip/npcx/system.c b/zephyr/shim/chip/npcx/system.c
index d776733827..96fccfebca 100644
--- a/zephyr/shim/chip/npcx/system.c
+++ b/zephyr/shim/chip/npcx/system.c
@@ -4,10 +4,8 @@
*/
#include <drivers/cros_bbram.h>
-#include <drivers/cros_system.h>
#include <logging/log.h>
-#include "watchdog.h"
#include "system.h"
#define GET_BBRAM_OFFSET(node) \
@@ -16,7 +14,7 @@
LOG_MODULE_REGISTER(shim_npcx_system, LOG_LEVEL_ERR);
-const struct device *bbram_dev;
+const static struct device *bbram_dev;
void chip_save_reset_flags(uint32_t flags)
{
@@ -44,51 +42,53 @@ uint32_t chip_read_reset_flags(void)
return flags;
}
-void system_reset(int flags)
+void chip_bbram_status_check(void)
{
- const struct device *sys_dev = device_get_binding("CROS_SYSTEM");
- int err;
- uint32_t save_flags;
-
- if (!sys_dev)
- LOG_ERR("sys_dev get binding failed");
-
- /* Disable interrupts to avoid task swaps during reboot */
- interrupt_disable_all();
-
- /* Get flags to be saved in BBRAM */
- system_encode_save_flags(flags, &save_flags);
-
- /* Store flags to battery backed RAM. */
- chip_save_reset_flags(save_flags);
-
- /* If WAIT_EXT is set, then allow 10 seconds for external reset */
- if (flags & SYSTEM_RESET_WAIT_EXT) {
- int i;
-
- /* Wait 10 seconds for external reset */
- for (i = 0; i < 1000; i++) {
- watchdog_reload();
- udelay(10000);
- }
+ if (!bbram_dev) {
+ LOG_DBG("bbram_dev doesn't binding");
+ return;
}
- err = cros_system_soc_reset(sys_dev);
-
- if (err < 0)
- LOG_ERR("soc reset failed");
-
- /* should never return */
- while (1)
- ;
+ if (cros_bbram_get_ibbr(bbram_dev)) {
+ LOG_ERR("VBAT power drop!");
+ cros_bbram_reset_ibbr(bbram_dev);
+ }
+ if (cros_bbram_get_vsby(bbram_dev)) {
+ LOG_ERR("VSBY power drop!");
+ cros_bbram_reset_vsby(bbram_dev);
+ }
+ if (cros_bbram_get_vcc1(bbram_dev)) {
+ LOG_ERR("VCC1 power drop!");
+ cros_bbram_reset_vcc1(bbram_dev);
+ }
}
static int chip_system_init(const struct device *unused)
{
ARG_UNUSED(unused);
+ /*
+ * NPCX chip uses BBRAM to save the reset flag. Binding & check BBRAM
+ * here.
+ */
bbram_dev = device_get_binding(DT_LABEL(DT_NODELABEL(bbram)));
+ if (!bbram_dev) {
+ LOG_ERR("bbram_dev gets binding failed");
+ return -1;
+ }
+
+ /* check the BBRAM status */
+ chip_bbram_status_check();
+
return 0;
}
-
-SYS_INIT(chip_system_init, PRE_KERNEL_1, 50);
+/*
+ * The priority should be lower than CROS_BBRAM_NPCX_INIT_PRIORITY.
+ */
+#if (CONFIG_CROS_SYSTEM_NPCX_PRE_INIT_PRIORITY <= \
+ CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY)
+#error CONFIG_CROS_SYSTEM_NPCX_PRE_INIT_PRIORITY must greater than \
+ CONFIG_CROS_BBRAM_NPCX_INIT_PRIORITY
+#endif
+SYS_INIT(chip_system_init, PRE_KERNEL_1,
+ CONFIG_CROS_SYSTEM_NPCX_PRE_INIT_PRIORITY);
diff --git a/zephyr/shim/src/system.c b/zephyr/shim/src/system.c
index bf421ad8ae..1e17dcea13 100644
--- a/zephyr/shim/src/system.c
+++ b/zephyr/shim/src/system.c
@@ -5,18 +5,24 @@
#include <device.h>
#include <drivers/cros_bbram.h>
+#include <drivers/cros_system.h>
+#include <logging/log.h>
#include "bbram.h"
#include "common.h"
#include "cros_version.h"
#include "system.h"
+#include "watchdog.h"
#define BBRAM_REGION_PD0 DT_PATH(named_bbram_regions, pd0)
#define BBRAM_REGION_PD1 DT_PATH(named_bbram_regions, pd1)
#define BBRAM_REGION_PD2 DT_PATH(named_bbram_regions, pd2)
#define BBRAM_REGION_TRY_SLOT DT_PATH(named_bbram_regions, try_slot)
+LOG_MODULE_REGISTER(shim_system, LOG_LEVEL_ERR);
+
STATIC_IF_NOT(CONFIG_ZTEST) const struct device *bbram_dev;
+STATIC_IF_NOT(CONFIG_ZTEST) const struct device *sys_dev;
#if DT_NODE_EXISTS(DT_NODELABEL(bbram))
static int system_init(const struct device *unused)
@@ -95,3 +101,170 @@ const char *system_get_chip_revision(void)
{
return "";
}
+
+void system_reset(int flags)
+{
+ int err;
+ uint32_t save_flags;
+
+ if (!sys_dev)
+ LOG_ERR("sys_dev get binding failed");
+
+ /* Disable interrupts to avoid task swaps during reboot */
+ interrupt_disable_all();
+
+ /* Get flags to be saved in BBRAM */
+ system_encode_save_flags(flags, &save_flags);
+
+ /* Store flags to battery backed RAM. */
+ chip_save_reset_flags(save_flags);
+
+ /* If WAIT_EXT is set, then allow 10 seconds for external reset */
+ if (flags & SYSTEM_RESET_WAIT_EXT) {
+ int i;
+
+ /* Wait 10 seconds for external reset */
+ for (i = 0; i < 1000; i++) {
+ watchdog_reload();
+ udelay(10000);
+ }
+ }
+
+ err = cros_system_soc_reset(sys_dev);
+
+ if (err < 0)
+ LOG_ERR("soc reset failed");
+
+ /* should never return */
+ while (1)
+ continue;
+}
+
+static int check_reset_cause(void)
+{
+ uint32_t chip_flags = 0; /* used to write back to the BBRAM */
+ uint32_t system_flags = chip_read_reset_flags(); /* system reset flag */
+ int chip_reset_cause = 0; /* chip-level reset cause */
+
+ chip_reset_cause = cros_system_get_reset_cause(sys_dev);
+ if (chip_reset_cause < 0)
+ return -1;
+
+ /*
+ * TODO(b/182876692): Implement CONFIG_POWER_BUTTON_INIT_IDLE &
+ * CONFIG_BOARD_FORCE_RESET_PIN. Also, check the hibernate flow if PSL
+ * merge into tot.
+ */
+
+ switch (chip_reset_cause) {
+ case POWERUP:
+ system_flags |= EC_RESET_FLAG_POWER_ON;
+ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON)) {
+ /*
+ * Power-on restart, so set a flag and save it for the
+ * next imminent reset. Later code will check for this
+ * flag and wait for the second reset.
+ */
+ system_flags |= EC_RESET_FLAG_INITIAL_PWR;
+ chip_flags |= EC_RESET_FLAG_INITIAL_PWR;
+ }
+ break;
+
+ case VCC1_RST_PIN:
+ /*
+ * If configured, check the saved flags to see whether the
+ * previous restart was a power-on, in which case treat this
+ * restart as a power-on as well. This is to workaround the fact
+ * that the H1 will reset the EC at power up.
+ */
+ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON)) {
+ if (system_flags & EC_RESET_FLAG_INITIAL_PWR) {
+ /*
+ * The previous restart was a power-on so treat
+ * this restart as that, and clear the flag so
+ * later code will not wait for the second
+ * reset.
+ */
+ system_flags = (system_flags &
+ ~EC_RESET_FLAG_INITIAL_PWR) |
+ EC_RESET_FLAG_POWER_ON;
+ } else {
+ /*
+ * No previous reset flag, so this is a
+ * subsequent restart i.e any restarts after the
+ * second restart caused by the H1.
+ */
+ system_flags |= EC_RESET_FLAG_RESET_PIN;
+ }
+ } else {
+ system_flags |= EC_RESET_FLAG_RESET_PIN;
+ }
+ break;
+
+ case DEBUG_RST:
+ system_flags |= EC_RESET_FLAG_SOFT;
+ break;
+
+ case WATCHDOG_RST:
+ /*
+ * Don't set EC_RESET_FLAG_WATCHDOG flag if watchdog is issued
+ * by system_reset in order to distinguish reset cause is panic
+ * reason or not.
+ */
+ if (!(system_flags & (EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HARD)))
+ system_flags |= EC_RESET_FLAG_WATCHDOG;
+ break;
+ }
+
+ /* Clear & set the reset flags for the following reset. */
+ chip_save_reset_flags(chip_flags);
+
+ /* Set the system reset flags. */
+ system_set_reset_flags(system_flags);
+
+ return 0;
+}
+
+static int system_preinitialize(const struct device *unused)
+{
+ ARG_UNUSED(unused);
+
+ sys_dev = device_get_binding("CROS_SYSTEM");
+ if (!sys_dev) {
+ /*
+ * TODO(b/183022804): This should not happen in normal
+ * operation. Check whether the error check can be change to
+ * build-time error, or at least a fatal run-time error.
+ */
+ LOG_ERR("sys_dev gets binding failed");
+ return -1;
+ }
+
+ /* check the reset cause */
+ if (check_reset_cause() != 0) {
+ LOG_ERR("check the reset cause failed");
+ return -1;
+ }
+
+ /*
+ * For some boards on power-on, the EC is reset by the H1 after
+ * power-on, so the EC sees 2 resets. This config enables the EC to save
+ * a flag on the first power-up restart, and then wait for the second
+ * reset before any other setup is done (such as GPIOs, timers, UART
+ * etc.) On the second reset, the saved flag is used to detect the
+ * previous power-on, and treat the second reset as a power-on instead
+ * of a reset.
+ */
+ if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) &&
+ system_get_reset_flags() & EC_RESET_FLAG_INITIAL_PWR) {
+ /* TODO(b/182875520): Change to use 2 second delay. */
+ while (1)
+ continue;
+ }
+
+ return 0;
+}
+#if (!defined(CONFIG_ZTEST))
+SYS_INIT(system_preinitialize, PRE_KERNEL_1,
+ CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY);
+#endif