diff options
Diffstat (limited to 'zephyr/shim/src/system.c')
-rw-r--r-- | zephyr/shim/src/system.c | 378 |
1 files changed, 0 insertions, 378 deletions
diff --git a/zephyr/shim/src/system.c b/zephyr/shim/src/system.c deleted file mode 100644 index 8db8ba437a..0000000000 --- a/zephyr/shim/src/system.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Copyright 2020 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. - */ - -#include <device.h> -#include <drivers/bbram.h> -#include <drivers/cros_system.h> -#include <logging/log.h> - -#include "bbram.h" -#include "common.h" -#include "console.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) - -#define GET_BBRAM_OFFSET(node) \ - DT_PROP(DT_PATH(named_bbram_regions, node), offset) -#define GET_BBRAM_SIZE(node) DT_PROP(DT_PATH(named_bbram_regions, node), size) - -/* 2 second delay for waiting the H1 reset */ -#define WAIT_RESET_TIME \ - (CONFIG_PLATFORM_EC_PREINIT_HW_CYCLES_PER_SEC * 2 / \ - CONFIG_PLATFORM_EC_WAIT_RESET_CYCLES_PER_ITERATION) - -LOG_MODULE_REGISTER(shim_system, LOG_LEVEL_ERR); - -STATIC_IF_NOT(CONFIG_ZTEST) const struct device *bbram_dev; -static const struct device *sys_dev; - -/* Map idx to a bbram offset/size, or return -1 on invalid idx */ -static int bbram_lookup(enum system_bbram_idx idx, int *offset_out, - int *size_out) -{ - switch (idx) { - case SYSTEM_BBRAM_IDX_PD0: - *offset_out = DT_PROP(BBRAM_REGION_PD0, offset); - *size_out = DT_PROP(BBRAM_REGION_PD0, size); - break; - case SYSTEM_BBRAM_IDX_PD1: - *offset_out = DT_PROP(BBRAM_REGION_PD1, offset); - *size_out = DT_PROP(BBRAM_REGION_PD1, size); - break; - case SYSTEM_BBRAM_IDX_PD2: - *offset_out = DT_PROP(BBRAM_REGION_PD2, offset); - *size_out = DT_PROP(BBRAM_REGION_PD2, size); - break; - case SYSTEM_BBRAM_IDX_TRY_SLOT: - *offset_out = DT_PROP(BBRAM_REGION_TRY_SLOT, offset); - *size_out = DT_PROP(BBRAM_REGION_TRY_SLOT, size); - break; - default: - return EC_ERROR_INVAL; - } - return EC_SUCCESS; -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - int offset, size, rc; - - if (bbram_dev == NULL) - return EC_ERROR_INVAL; - - rc = bbram_lookup(idx, &offset, &size); - if (rc) - return rc; - - rc = bbram_read(bbram_dev, offset, size, value); - - return rc ? EC_ERROR_INVAL : EC_SUCCESS; -} - -void chip_save_reset_flags(uint32_t flags) -{ - if (bbram_dev == NULL) { - LOG_ERR("bbram_dev doesn't binding"); - return; - } - - bbram_write(bbram_dev, GET_BBRAM_OFFSET(saved_reset_flags), - GET_BBRAM_SIZE(saved_reset_flags), (uint8_t *)&flags); -} - -uint32_t chip_read_reset_flags(void) -{ - uint32_t flags; - - if (bbram_dev == NULL) { - LOG_ERR("bbram_dev doesn't binding"); - return 0; - } - - bbram_read(bbram_dev, GET_BBRAM_OFFSET(saved_reset_flags), - GET_BBRAM_SIZE(saved_reset_flags), (uint8_t *)&flags); - - return flags; -} - -int system_set_scratchpad(uint32_t value) -{ - if (bbram_dev == NULL) { - LOG_ERR("bbram_dev doesn't binding"); - return -EC_ERROR_INVAL; - } - - return bbram_write(bbram_dev, GET_BBRAM_OFFSET(scratchpad), - GET_BBRAM_SIZE(scratchpad), (uint8_t *)&value); -} - -int system_get_scratchpad(uint32_t *value) -{ - if (bbram_dev == NULL) { - LOG_ERR("bbram_dev doesn't binding"); - return -EC_ERROR_INVAL; - } - - if (bbram_read(bbram_dev, GET_BBRAM_OFFSET(scratchpad), - GET_BBRAM_SIZE(scratchpad), (uint8_t *)value)) { - return -EC_ERROR_INVAL; - } - - return 0; -} - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); - int err; - - /* Flush console before hibernating */ - cflush(); - - if (board_hibernate) - board_hibernate(); - - /* Save 'wake-up from hibernate' reset flag */ - chip_save_reset_flags(chip_read_reset_flags() | - EC_RESET_FLAG_HIBERNATE); - - err = cros_system_hibernate(sys_dev, seconds, microseconds); - if (err < 0) { - LOG_ERR("hibernate failed %d", err); - return; - } - - /* should never reach this point */ - while (1) - continue; -} - -#ifdef CONFIG_PM -/** - * Print low power idle statistics - */ -static int command_idle_stats(int argc, char **argv) -{ - const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); - - timestamp_t ts = get_time(); - uint64_t deep_sleep_ticks = cros_system_deep_sleep_ticks(sys_dev); - - ccprintf("Time spent in deep-sleep: %.6llds\n", - k_ticks_to_us_near64(deep_sleep_ticks)); - ccprintf("Total time on: %.6llds\n", ts.val); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(idlestats, command_idle_stats, - "", - "Print last idle stats"); -#endif - -const char *system_get_chip_vendor(void) -{ - const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); - - return cros_system_chip_vendor(sys_dev); -} - -const char *system_get_chip_name(void) -{ - const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); - - return cros_system_chip_name(sys_dev); -} - -const char *system_get_chip_revision(void) -{ - const struct device *sys_dev = device_get_binding("CROS_SYSTEM"); - - return cros_system_chip_revision(sys_dev); -} - -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. - */ - - switch (chip_reset_cause) { - case POWERUP: - system_flags |= EC_RESET_FLAG_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. Waking from PSL hibernate is power-on - * for EC but not for H1, so do not wait for the second reset. - */ - if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) && - ((system_flags & EC_RESET_FLAG_HIBERNATE) == 0)) { - 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 or hibernate in order to distinguish reset - * cause is panic reason or not. - */ - if (!(system_flags & (EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) - 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); - -#if DT_NODE_EXISTS(DT_NODELABEL(bbram)) - bbram_dev = DEVICE_DT_GET(DT_NODELABEL(bbram)); - if (!device_is_ready(bbram_dev)) { - LOG_ERR("Error: device %s is not ready", bbram_dev->name); - return -1; - } -#endif - - 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. - */ -#ifdef CONFIG_BOARD_RESET_AFTER_POWER_ON - if (system_get_reset_flags() & EC_RESET_FLAG_INITIAL_PWR) { - /* - * The current initial stage couldn't use the kernel delay - * function. Use CPU nop instruction to wait for the external - * reset from H1. - */ - for (uint32_t i = WAIT_RESET_TIME; i; i--) - arch_nop(); - } -#endif - return 0; -} - -SYS_INIT(system_preinitialize, PRE_KERNEL_1, - CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY); |