diff options
Diffstat (limited to 'chip/npcx/system.c')
-rw-r--r-- | chip/npcx/system.c | 1170 |
1 files changed, 0 insertions, 1170 deletions
diff --git a/chip/npcx/system.c b/chip/npcx/system.c deleted file mode 100644 index bac303afa0..0000000000 --- a/chip/npcx/system.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* Copyright 2014 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. - */ - -/* System module for Chrome EC : NPCX hardware specific implementation */ - -#include "clock.h" -#include "clock_chip.h" -#include "common.h" -#include "console.h" -#include "cpu.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "hwtimer_chip.h" -#include "registers.h" -#include "rom_chip.h" -#include "sib_chip.h" -#include "system.h" -#include "system_chip.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -/* Delay after writing TTC for value to latch */ -#define MTC_TTC_LOAD_DELAY_US 250 -#define MTC_ALARM_MASK (BIT(25) - 1) -#define MTC_WUI_GROUP MIWU_GROUP_4 -#define MTC_WUI_MASK MASK_PIN7 - -/* ROM address of chip revision */ -#define CHIP_REV_ADDR 0x00007FFC - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) - -/*****************************************************************************/ -/* Internal functions */ - -void system_watchdog_reset(void) -{ - /* Unlock & stop watchdog registers */ - watchdog_stop_and_unlock(); - - /* Reset TWCFG */ - NPCX_TWCFG = 0; - /* Select T0IN clock as watchdog prescaler clock */ - SET_BIT(NPCX_TWCFG, NPCX_TWCFG_WDCT0I); - - /* Clear watchdog reset status initially*/ - SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS); - - /* Keep prescaler ratio timer0 clock to 1:1 */ - NPCX_TWCP = 0x00; - - /* Set internal counter and prescaler */ - NPCX_TWDT0 = 0x00; - NPCX_WDCNT = 0x01; - - /* Disable interrupt */ - interrupt_disable(); - /* Reload and restart Timer 0*/ - SET_BIT(NPCX_T0CSR, NPCX_T0CSR_RST); - /* Wait for timer is loaded and restart */ - while (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_RST)) - ; - /* Enable interrupt */ - interrupt_enable(); -} - -/* Return true if index is stored as a single byte in bbram */ -static int bbram_is_byte_access(enum bbram_data_index index) -{ - return (index >= BBRM_DATA_INDEX_VBNVCNTXT && - index < BBRM_DATA_INDEX_RAMLOG) - || index == BBRM_DATA_INDEX_PD0 - || index == BBRM_DATA_INDEX_PD1 - || index == BBRM_DATA_INDEX_PD2 - || index == BBRM_DATA_INDEX_PANIC_FLAGS - ; -} - -/* Check and clear BBRAM status on any reset */ -void system_check_bbram_on_reset(void) -{ - if (IS_BIT_SET(NPCX_BKUP_STS, NPCX_BKUP_STS_IBBR)) { - /* - * If the reset cause is not power-on reset and VBAT has ever - * dropped, print a warning message. - */ - if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH) || - IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) - CPRINTF("VBAT drop!\n"); - - /* - * npcx5/npcx7m6g/npcx7m6f: - * Clear IBBR bit - * npcx7m6fb/npcx7m6fc/npcx7m7wb/npcx7m7wc: - * Clear IBBR/VSBY_STS/VCC1_STS bit - */ - NPCX_BKUP_STS = NPCX_BKUP_STS_ALL_MASK; - } -} - -/* Check index is within valid BBRAM range and IBBR is not set */ -static int bbram_valid(enum bbram_data_index index, int bytes) -{ - /* Check index */ - if (index < 0 || index + bytes > NPCX_BBRAM_SIZE) - return 0; - - /* Check BBRAM is valid */ - if (IS_BIT_SET(NPCX_BKUP_STS, NPCX_BKUP_STS_IBBR)) { - NPCX_BKUP_STS = BIT(NPCX_BKUP_STS_IBBR); - panic_printf("IBBR set: BBRAM corrupted!\n"); - return 0; - } - return 1; -} - -/** - * Read battery-backed ram (BBRAM) at specified index. - * - * @return The value of the register or 0 if invalid index. - */ -static uint32_t bbram_data_read(enum bbram_data_index index) -{ - uint32_t value = 0; - int bytes = bbram_is_byte_access(index) ? 1 : 4; - - if (!bbram_valid(index, bytes)) - return 0; - - /* Read BBRAM */ - if (bytes == 4) { - value += NPCX_BBRAM(index + 3); - value = value << 8; - value += NPCX_BBRAM(index + 2); - value = value << 8; - value += NPCX_BBRAM(index + 1); - value = value << 8; - } - value += NPCX_BBRAM(index); - - return value; -} - -/** - * Write battery-backed ram (BBRAM) at specified index. - * - * @return nonzero if error. - */ -static int bbram_data_write(enum bbram_data_index index, uint32_t value) -{ - int bytes = bbram_is_byte_access(index) ? 1 : 4; - - if (!bbram_valid(index, bytes)) - return EC_ERROR_INVAL; - - /* Write BBRAM */ - NPCX_BBRAM(index) = value & 0xFF; - if (bytes == 4) { - NPCX_BBRAM(index + 1) = (value >> 8) & 0xFF; - NPCX_BBRAM(index + 2) = (value >> 16) & 0xFF; - NPCX_BBRAM(index + 3) = (value >> 24) & 0xFF; - } - - /* Wait for write-complete */ - return EC_SUCCESS; -} - -/* Map idx to a returned BBRM_DATA_INDEX_*, or return -1 on invalid idx */ -static int bbram_idx_lookup(enum system_bbram_idx idx) -{ - if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 && - idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15) - return BBRM_DATA_INDEX_VBNVCNTXT + - idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0; - if (idx == SYSTEM_BBRAM_IDX_PD0) - return BBRM_DATA_INDEX_PD0; - if (idx == SYSTEM_BBRAM_IDX_PD1) - return BBRM_DATA_INDEX_PD1; - if (idx == SYSTEM_BBRAM_IDX_PD2) - return BBRM_DATA_INDEX_PD2; - if (idx == SYSTEM_BBRAM_IDX_TRY_SLOT) - return BBRM_DATA_INDEX_TRY_SLOT; - return -1; -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - int bbram_idx = bbram_idx_lookup(idx); - - if (bbram_idx < 0) - return EC_ERROR_INVAL; - - *value = bbram_data_read(bbram_idx); - return EC_SUCCESS; -} - -int system_set_bbram(enum system_bbram_idx idx, uint8_t value) -{ - int bbram_idx = bbram_idx_lookup(idx); - - if (bbram_idx < 0) - return EC_ERROR_INVAL; - - return bbram_data_write(bbram_idx, value); -} - -/* MTC functions */ -uint32_t system_get_rtc_sec(void) -{ - /* Get MTC counter unit:seconds */ - uint32_t sec = NPCX_TTC; - return sec; -} - -void system_set_rtc(uint32_t seconds) -{ - /* - * Set MTC counter unit:seconds, write twice to ensure values - * latch to NVMem. - */ - NPCX_TTC = seconds; - udelay(MTC_TTC_LOAD_DELAY_US); - NPCX_TTC = seconds; - udelay(MTC_TTC_LOAD_DELAY_US); -} - -#ifdef CONFIG_CHIP_PANIC_BACKUP -/* - * Following information from panic data is stored in BBRAM: - * - * index | data - * ==========|============= - * 36 | MMFS - * 40 | HFSR - * 44 | BFAR - * 48 | LREG1 - * 52 | LREG3 - * 56 | LREG4 - * 60 | reserved - * - * Above registers are chosen to be saved in case of panic because: - * 1. MMFS, HFSR and BFAR seem to provide more information about the fault. - * 2. LREG1, LREG3 and LREG4 store exception, reason and info in case of - * software panic. - */ -#define BKUP_MMFS (BBRM_DATA_INDEX_PANIC_BKUP + 0) -#define BKUP_HFSR (BBRM_DATA_INDEX_PANIC_BKUP + 4) -#define BKUP_BFAR (BBRM_DATA_INDEX_PANIC_BKUP + 8) -#define BKUP_LREG1 (BBRM_DATA_INDEX_PANIC_BKUP + 12) -#define BKUP_LREG3 (BBRM_DATA_INDEX_PANIC_BKUP + 16) -#define BKUP_LREG4 (BBRM_DATA_INDEX_PANIC_BKUP + 20) - -#define BKUP_PANIC_DATA_VALID BIT(0) - -void chip_panic_data_backup(void) -{ - struct panic_data *d = panic_get_data(); - - if (!d) - return; - - bbram_data_write(BKUP_MMFS, d->cm.mmfs); - bbram_data_write(BKUP_HFSR, d->cm.hfsr); - bbram_data_write(BKUP_BFAR, d->cm.dfsr); - bbram_data_write(BKUP_LREG1, d->cm.regs[1]); - bbram_data_write(BKUP_LREG3, d->cm.regs[3]); - bbram_data_write(BKUP_LREG4, d->cm.regs[4]); - bbram_data_write(BBRM_DATA_INDEX_PANIC_FLAGS, BKUP_PANIC_DATA_VALID); -} - -static void chip_panic_data_restore(void) -{ - struct panic_data *d = PANIC_DATA_PTR; - - /* Ensure BBRAM is valid. */ - if (!bbram_valid(BKUP_MMFS, 4)) - return; - - /* Ensure Panic data in BBRAM is valid. */ - if (!(bbram_data_read(BBRM_DATA_INDEX_PANIC_FLAGS) & - BKUP_PANIC_DATA_VALID)) - return; - - memset(d, 0, sizeof(*d)); - d->magic = PANIC_DATA_MAGIC; - d->struct_size = sizeof(*d); - d->struct_version = 2; - d->arch = PANIC_ARCH_CORTEX_M; - - d->cm.mmfs = bbram_data_read(BKUP_MMFS); - d->cm.hfsr = bbram_data_read(BKUP_HFSR); - d->cm.dfsr = bbram_data_read(BKUP_BFAR); - - d->cm.regs[1] = bbram_data_read(BKUP_LREG1); - d->cm.regs[3] = bbram_data_read(BKUP_LREG3); - d->cm.regs[4] = bbram_data_read(BKUP_LREG4); - - /* Reset panic data in BBRAM. */ - bbram_data_write(BBRM_DATA_INDEX_PANIC_FLAGS, 0); -} -#endif /* CONFIG_CHIP_PANIC_BACKUP */ - -void chip_save_reset_flags(uint32_t flags) -{ - bbram_data_write(BBRM_DATA_INDEX_SAVED_RESET_FLAGS, flags); -} - -uint32_t chip_read_reset_flags(void) -{ - return bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS); -} - -#ifdef CONFIG_POWER_BUTTON_INIT_IDLE -/* - * Set/clear AP_OFF flag. It's set when the system gracefully shuts down and - * it's cleared when the system boots up. The result is the system tries to - * go back to the previous state upon AC plug-in. If the system uncleanly - * shuts down, it boots immediately. If the system shuts down gracefully, - * it'll stay at S5 and wait for power button press. - */ -static void board_chipset_startup(void) -{ - uint32_t flags = bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS); - flags &= ~EC_RESET_FLAG_AP_OFF; - chip_save_reset_flags(flags); - system_clear_reset_flags(EC_RESET_FLAG_AP_OFF); - CPRINTS("Cleared AP_OFF flag"); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, board_chipset_startup, HOOK_PRIO_DEFAULT); - -static void board_chipset_shutdown(void) -{ - uint32_t flags = bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS); - flags |= EC_RESET_FLAG_AP_OFF; - chip_save_reset_flags(flags); - system_set_reset_flags(EC_RESET_FLAG_AP_OFF); - CPRINTS("Set AP_OFF flag"); -} -DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, board_chipset_shutdown, - /* Slightly higher than handle_pending_reboot because - * it may clear AP_OFF flag. */ - HOOK_PRIO_DEFAULT - 1); -#endif - -static void check_reset_cause(void) -{ - uint32_t hib_wake_flags = bbram_data_read(BBRM_DATA_INDEX_WAKE); - uint32_t flags = bbram_data_read(BBRM_DATA_INDEX_SAVED_RESET_FLAGS); - - /* Clear saved reset flags in bbram */ -#ifdef CONFIG_POWER_BUTTON_INIT_IDLE - /* We'll clear AP_OFF on S5->S3 transition */ - chip_save_reset_flags(flags & EC_RESET_FLAG_AP_OFF); -#else - chip_save_reset_flags(0); -#endif - /* Clear saved hibernate wake flag in bbram , too */ - bbram_data_write(BBRM_DATA_INDEX_WAKE, 0); - - /* Use scratch bit to check power on reset or VCC1_RST reset */ - if (!IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH)) { -#ifdef CONFIG_BOARD_FORCE_RESET_PIN - /* Treat all resets as RESET_PIN */ - flags |= EC_RESET_FLAG_RESET_PIN; -#else - /* Check for VCC1 reset */ - if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) - flags |= EC_RESET_FLAG_RESET_PIN; - else - flags |= EC_RESET_FLAG_POWER_ON; -#endif - } - - /* - * Set scratch bit to distinguish VCC1RST# is asserted again - * or not. This bit will be clear automatically when VCC1RST# - * is asserted or power-on reset occurs - */ - SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_VCC1_RST_SCRATCH); - - /* Software debugger reset */ - if (IS_BIT_SET(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS)) { - flags |= EC_RESET_FLAG_SOFT; - /* Clear debugger reset status initially*/ - SET_BIT(NPCX_RSTCTL, NPCX_RSTCTL_DBGRST_STS); - } - - /* Reset by hibernate */ - if (hib_wake_flags & HIBERNATE_WAKE_PIN) - flags |= EC_RESET_FLAG_WAKE_PIN | EC_RESET_FLAG_HIBERNATE; - else if (hib_wake_flags & HIBERNATE_WAKE_MTC) - flags |= EC_RESET_FLAG_RTC_ALARM | EC_RESET_FLAG_HIBERNATE; - - /* Watchdog Reset */ - if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) { - /* - * 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 (!(flags & (EC_RESET_FLAG_SOFT | EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) - flags |= EC_RESET_FLAG_WATCHDOG; - - /* Clear watchdog reset status initially*/ - SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS); - } - - system_set_reset_flags(flags); -} - -/** - * Chip-level function to set GPIOs and wake-up inputs for hibernate. - */ -#ifdef CONFIG_SUPPORT_CHIP_HIBERNATION -static void system_set_gpios_and_wakeup_inputs_hibernate(void) -{ - int table, i; - - /* Disable all MIWU inputs before entering hibernate */ - for (table = MIWU_TABLE_0 ; table < MIWU_TABLE_2 ; table++) { - for (i = 0 ; i < 8 ; i++) { - /* Disable all wake-ups */ - NPCX_WKEN(table, i) = 0x00; - /* Clear all pending bits of wake-ups */ - NPCX_WKPCL(table, i) = 0xFF; - /* - * Disable all inputs of wake-ups to prevent leakage - * caused by input floating. - */ - NPCX_WKINEN(table, i) = 0x00; - } - } - -#if defined(CHIP_FAMILY_NPCX7) - /* Disable MIWU 2 group 6 inputs which used for the additional GPIOs */ - NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_6) = 0x00; - NPCX_WKPCL(MIWU_TABLE_2, MIWU_GROUP_6) = 0xFF; - NPCX_WKINEN(MIWU_TABLE_2, MIWU_GROUP_6) = 0x00; -#endif - - /* Enable wake-up inputs of hibernate_wake_pins array */ - for (i = 0; i < hibernate_wake_pins_used; i++) { - gpio_reset(hibernate_wake_pins[i]); - /* Re-enable interrupt for wake-up inputs */ - gpio_enable_interrupt(hibernate_wake_pins[i]); -#if defined(CONFIG_HIBERNATE_PSL) - /* Config PSL pins setting for wake-up inputs */ - if (!system_config_psl_mode(hibernate_wake_pins[i])) - ccprintf("Invalid PSL setting in wake-up pin %d\n", i); -#endif - } -} - -/** - * hibernate function for npcx ec. - * - * @param seconds Number of seconds to sleep before LCT alarm - * @param microseconds Number of microseconds to sleep before LCT alarm - */ -void __enter_hibernate(uint32_t seconds, uint32_t microseconds) -{ - int i; - - /* Disable ADC */ - NPCX_ADCCNF = 0; - usleep(1000); - - /* Set SPI pins to be in Tri-State */ - SET_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS); - - /* Disable instant wake up mode for better power consumption */ - CLEAR_BIT(NPCX_ENIDL_CTL, NPCX_ENIDL_CTL_LP_WK_CTL); - - /* Disable interrupt */ - interrupt_disable(); - - /* ITIM event module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); - /* ITIM time module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN); - /* ITIM watchdog warn module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN); - - /* Unlock & stop watchdog */ - watchdog_stop_and_unlock(); - - /* Initialize watchdog */ - NPCX_TWCFG = 0; /* Select T0IN clock as watchdog prescaler clock */ - SET_BIT(NPCX_TWCFG, NPCX_TWCFG_WDCT0I); - NPCX_TWCP = 0x00; /* Keep prescaler ratio timer0 clock to 1:1 */ - NPCX_TWDT0 = 0x00; /* Set internal counter and prescaler */ - - /* Disable interrupt */ - interrupt_disable(); - - /* - * Set gpios and wake-up input for better power consumption before - * entering hibernate. - */ - system_set_gpios_and_wakeup_inputs_hibernate(); - - /* - * Give the board a chance to do any late stage hibernation work. - * This is likely going to configure GPIOs for hibernation. - */ - if (board_hibernate_late) - board_hibernate_late(); - - /* Clear all pending IRQ otherwise wfi will have no affect */ - for (i = NPCX_IRQ_0 ; i < NPCX_IRQ_COUNT ; i++) - task_clear_pending_irq(i); - - /* - * Set RTC interrupt in time to wake up before - * next event. - */ - if (seconds || microseconds) - system_set_rtc_alarm(seconds, microseconds); - - - /* execute hibernate func depend on chip series */ - __hibernate_npcx_series(); - -} -#endif /* CONFIG_SUPPORT_CHIP_HIBERNATION */ - -static char system_to_hex(uint8_t x) -{ - if (x <= 9) - return '0' + x; - return 'a' + x - 10; -} - -/*****************************************************************************/ -/* IC specific low-level driver */ - -/* - * Microseconds will be ignored. The WTC register only - * stores wakeup time in seconds. - * Set seconds = 0 to disable the alarm - */ -void system_set_rtc_alarm(uint32_t seconds, uint32_t microseconds) -{ - uint32_t cur_secs, alarm_secs; - - if (seconds == EC_RTC_ALARM_CLEAR && !microseconds) { - CLEAR_BIT(NPCX_WTC, NPCX_WTC_WIE); - SET_BIT(NPCX_WTC, NPCX_WTC_PTO); - - return; - } - - /* Get current clock */ - cur_secs = NPCX_TTC; - - /* If alarm clock is not sequential or not in range */ - alarm_secs = cur_secs + seconds; - alarm_secs = alarm_secs & MTC_ALARM_MASK; - - /* - * We should set new alarm (first 25 bits of clock value) first before - * clearing PTO in case issue rtc interrupt immediately. - */ - NPCX_WTC = alarm_secs; - - /* Reset alarm first */ - system_reset_rtc_alarm(); - - /* Enable interrupt mode alarm */ - SET_BIT(NPCX_WTC, NPCX_WTC_WIE); - - /* Enable MTC interrupt */ - task_enable_irq(NPCX_IRQ_MTC_WKINTAD_0); - - /* Enable wake-up input sources & clear pending bit */ - NPCX_WKPCL(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; - NPCX_WKINEN(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; - NPCX_WKEN(MIWU_TABLE_0, MTC_WUI_GROUP) |= MTC_WUI_MASK; -} - -void system_reset_rtc_alarm(void) -{ - /* - * Clear interrupt & Disable alarm interrupt - * Update alarm value to zero - */ - CLEAR_BIT(NPCX_WTC, NPCX_WTC_WIE); - SET_BIT(NPCX_WTC, NPCX_WTC_PTO); - - /* Disable MTC interrupt */ - task_disable_irq(NPCX_IRQ_MTC_WKINTAD_0); -} - -/* - * Return the seconds remaining before the RTC alarm goes off. - * Returns 0 if alarm is not set. - */ -uint32_t system_get_rtc_alarm(void) -{ - /* - * Return 0: - * 1. If alarm is not set to go off, OR - * 2. If alarm is set and has already gone off - */ - if (!IS_BIT_SET(NPCX_WTC, NPCX_WTC_WIE) || - IS_BIT_SET(NPCX_WTC, NPCX_WTC_PTO)) { - return 0; - } - /* Get seconds before alarm goes off */ - return (NPCX_WTC - NPCX_TTC) & MTC_ALARM_MASK; -} - -/** - * Enable hibernate interrupt - */ -void system_enable_hib_interrupt(void) -{ - task_enable_irq(NPCX_IRQ_MTC_WKINTAD_0); -} - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - /* Flush console before hibernating */ - cflush(); - - if (board_hibernate) - board_hibernate(); - -#ifdef CONFIG_SUPPORT_CHIP_HIBERNATION - /* Add additional hibernate operations here */ - __enter_hibernate(seconds, microseconds); -#endif -} - -void chip_pre_init(void) -{ - /* Setting for fixing JTAG issue */ - NPCX_DBGCTRL = 0x04; - /* Enable automatic freeze mode */ - CLEAR_BIT(NPCX_DBGFRZEN3, NPCX_DBGFRZEN3_GLBL_FRZ_DIS); - - /* - * Enable JTAG functionality by SW without pulling down strap-pin - * nJEN0 or nJEN1 during ec POWERON or VCCRST reset occurs. - * Please notice it will change pinmux to JTAG directly. - */ -#ifdef NPCX_ENABLE_JTAG -#if NPCX_JTAG_MODULE2 - CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_5), NPCX_DEVALT5_NJEN1_EN); -#else - CLEAR_BIT(NPCX_DEVALT(ALT_GROUP_5), NPCX_DEVALT5_NJEN0_EN); -#endif -#endif - -#ifndef CONFIG_ENABLE_JTAG_SELECTION - /* - * (b/129908668) - * This is the workaround to disable the JTAG0 which is enabled - * accidentally by a special key combination. - */ - if (!IS_BIT_SET(NPCX_DEVALT(5), NPCX_DEVALT5_NJEN0_EN)) { - int data; - /* Set DEVALT5.nJEN0_EN to disable JTAG0 */ - SET_BIT(NPCX_DEVALT(5), NPCX_DEVALT5_NJEN0_EN); - /* Enable Core-to-Host Modules Access */ - SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); - /* Clear SIOCFD.JEN0_HSL to disable JTAG0 */ - data = sib_read_reg(SIO_OFFSET, 0x2D); - data &= ~0x80; - sib_write_reg(SIO_OFFSET, 0x2D, data); - /* Disable Core-to-Host Modules Access */ - CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE); - } -#endif - -} - -void system_pre_init(void) -{ - uint8_t pwdwn6; - - /* - * Add additional initialization here - * EC should be initialized in Booter - */ - - /* Power-down the modules we don't need */ - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_1) = 0xF9; /* Skip SDP_PD FIU_PD */ - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_2) = 0xFF; -#if defined(CHIP_FAMILY_NPCX5) - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x0F; /* Skip GDMA */ -#elif defined(CHIP_FAMILY_NPCX7) - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x1F; /* Skip GDMA */ -#endif - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_4) = 0xF4; /* Skip ITIM2/1_PD */ - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5) = 0xF8; - - pwdwn6 = 0x70 | - BIT(NPCX_PWDWN_CTL6_ITIM6_PD) | - BIT(NPCX_PWDWN_CTL6_ITIM4_PD); /* Skip ITIM5_PD */ -#if !defined(CONFIG_HOSTCMD_ESPI) - pwdwn6 |= 1 << NPCX_PWDWN_CTL6_ESPI_PD; -#endif - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6) = pwdwn6; - -#if defined(CHIP_FAMILY_NPCX7) -#if defined(CHIP_VARIANT_NPCX7M6FB) || defined(CHIP_VARIANT_NPCX7M6FC) || \ - defined(CHIP_VARIANT_NPCX7M7WB) || defined(CHIP_VARIANT_NPCX7M7WC) - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_7) = 0xE7; -#else - NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_7) = 0x07; -#endif -#endif - - /* Following modules can be powered down automatically in npcx7 */ -#if defined(CHIP_FAMILY_NPCX5) - /* Power down the modules of npcx5 used internally */ - NPCX_INTERNAL_CTRL1 = 0x03; - NPCX_INTERNAL_CTRL2 = 0x03; - NPCX_INTERNAL_CTRL3 = 0x03; - - /* Enable low-power regulator */ - CLEAR_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN); - SET_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN); -#endif - - /* - * Configure LPRAM in the MPU as a regular memory - * and DATA RAM to prevent code execution - */ - system_mpu_config(); - - /* - * Change FMUL_WIN_DLY from 0x8A to 0x81 for better WoV - * audio quality. - */ -#ifdef CHIP_FAMILY_NPCX7 - NPCX_FMUL_WIN_DLY = 0x81; -#endif - -#ifdef CONFIG_CHIP_PANIC_BACKUP - chip_panic_data_restore(); -#endif -} - -void system_reset(int flags) -{ - uint32_t save_flags; - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - /* 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); - } - } - - /* Ask the watchdog to trigger a hard reboot */ - system_watchdog_reset(); - - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -/** - * Return the chip vendor/name/revision string. - */ -const char *system_get_chip_vendor(void) -{ - static char str[15] = "Unknown-"; - char *p = str + 8; - - /* Read Vendor ID in core register */ - uint8_t fam_id = NPCX_SID_CR; - switch (fam_id) { - case 0x20: - return "Nuvoton"; - default: - *p = system_to_hex((fam_id & 0xF0) >> 4); - *(p + 1) = system_to_hex(fam_id & 0x0F); - *(p + 2) = '\0'; - return str; - } -} - -const char *system_get_chip_name(void) -{ - static char str[15] = "Unknown-"; - char *p = str + 8; - - /* Read Chip ID in core register */ - uint8_t chip_id = NPCX_DEVICE_ID_CR; - switch (chip_id) { -#if defined(CHIP_FAMILY_NPCX5) - case 0x12: - return "NPCX585G"; - case 0x13: - return "NPCX575G"; - case 0x16: - return "NPCX586G"; - case 0x17: - return "NPCX576G"; -#elif defined(CHIP_FAMILY_NPCX7) - case 0x1F: - return "NPCX787G"; - case 0x21: - case 0x29: - return "NPCX796F"; - case 0x24: - case 0x2C: - return "NPCX797W"; -#endif - default: - *p = system_to_hex((chip_id & 0xF0) >> 4); - *(p + 1) = system_to_hex(chip_id & 0x0F); - *(p + 2) = '\0'; - return str; - } -} - -const char *system_get_chip_revision(void) -{ - static char rev[6]; - char *p = rev; - /* Read chip generation from SRID_CR */ - uint8_t chip_gen = NPCX_SRID_CR; - /* Read ROM data for chip revision directly */ - uint8_t rev_num = *((uint8_t *)CHIP_REV_ADDR); -#ifdef CHIP_FAMILY_NPCX7 - uint8_t chip_id = NPCX_DEVICE_ID_CR; -#endif - - switch (chip_gen) { -#if defined(CHIP_FAMILY_NPCX5) - case 0x05: - *p++ = 'A'; - break; -#elif defined(CHIP_FAMILY_NPCX7) - case 0x06: - *p++ = 'A'; - break; - case 0x07: - if (chip_id == 0x21 || chip_id == 0x24) - *p++ = 'B'; - else - *p++ = 'C'; - break; -#endif - default: - *p++ = system_to_hex((chip_gen & 0xF0) >> 4); - *p++ = system_to_hex(chip_gen & 0x0F); - break; - } - - *p++ = '.'; - *p++ = system_to_hex((rev_num & 0xF0) >> 4); - *p++ = system_to_hex(rev_num & 0x0F); - *p++ = '\0'; - - return rev; -} - -BUILD_ASSERT(BBRM_DATA_INDEX_VBNVCNTXT + EC_VBNV_BLOCK_SIZE <= NPCX_BBRAM_SIZE); - -/** - * Set a scratchpad register to the specified value. - * - * The scratchpad register must maintain its contents across a - * software-requested warm reset. - * - * @param value Value to store. - * @return EC_SUCCESS, or non-zero if error. - */ -int system_set_scratchpad(uint32_t value) -{ - return bbram_data_write(BBRM_DATA_INDEX_SCRATCHPAD, value); -} - -uint32_t system_get_scratchpad(void) -{ - return bbram_data_read(BBRM_DATA_INDEX_SCRATCHPAD); -} - -int system_is_reboot_warm(void) -{ - uint32_t reset_flags; - - /* - * Check reset cause here, - * gpio_pre_init is executed faster than system_pre_init - */ - check_reset_cause(); - reset_flags = system_get_reset_flags(); - - if ((reset_flags & EC_RESET_FLAG_RESET_PIN) || - (reset_flags & EC_RESET_FLAG_POWER_ON) || - (reset_flags & EC_RESET_FLAG_WATCHDOG) || - (reset_flags & EC_RESET_FLAG_HARD) || - (reset_flags & EC_RESET_FLAG_SOFT) || - (reset_flags & EC_RESET_FLAG_HIBERNATE)) - return 0; - else - return 1; -} - -/*****************************************************************************/ -/* Console commands */ -void print_system_rtc(enum console_channel ch) -{ - uint32_t sec = system_get_rtc_sec(); - - cprintf(ch, "RTC: 0x%08x (%d.00 s)\n", sec, sec); -} - -#ifdef CONFIG_CMD_RTC -static int command_system_rtc(int argc, char **argv) -{ - if (argc == 3 && !strcasecmp(argv[1], "set")) { - char *e; - uint32_t t = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - system_set_rtc(t); - } else if (argc > 1) { - return EC_ERROR_INVAL; - } - - print_system_rtc(CC_COMMAND); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rtc, command_system_rtc, - "[set <seconds>]", - "Get/set real-time clock"); - -#ifdef CONFIG_CMD_RTC_ALARM -/** - * Test the RTC alarm by setting an interrupt on RTC match. - */ -static int command_rtc_alarm_test(int argc, char **argv) -{ - int s = 1, us = 0; - char *e; - - ccprintf("Setting RTC alarm\n"); - system_enable_hib_interrupt(); - - if (argc > 1) { - s = strtoi(argv[1], &e, 10); - if (*e) - return EC_ERROR_PARAM1; - - } - if (argc > 2) { - us = strtoi(argv[2], &e, 10); - if (*e) - return EC_ERROR_PARAM2; - - } - - system_set_rtc_alarm(s, us); - - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(rtc_alarm, command_rtc_alarm_test, - "[seconds [microseconds]]", - "Test alarm"); -#endif /* CONFIG_CMD_RTC_ALARM */ -#endif /* CONFIG_CMD_RTC */ - -/*****************************************************************************/ -/* Host commands */ - -#ifdef CONFIG_HOSTCMD_RTC -static enum ec_status system_rtc_get_value(struct host_cmd_handler_args *args) -{ - struct ec_response_rtc *r = args->response; - - r->time = system_get_rtc_sec(); - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_VALUE, - system_rtc_get_value, - EC_VER_MASK(0)); - -static enum ec_status system_rtc_set_value(struct host_cmd_handler_args *args) -{ - const struct ec_params_rtc *p = args->params; - - system_set_rtc(p->time); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE, - system_rtc_set_value, - EC_VER_MASK(0)); - -static enum ec_status system_rtc_set_alarm(struct host_cmd_handler_args *args) -{ - const struct ec_params_rtc *p = args->params; - - system_set_rtc_alarm(p->time, 0); - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_ALARM, - system_rtc_set_alarm, - EC_VER_MASK(0)); - -static enum ec_status system_rtc_get_alarm(struct host_cmd_handler_args *args) -{ - struct ec_response_rtc *r = args->response; - - r->time = system_get_rtc_alarm(); - args->response_size = sizeof(*r); - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_RTC_GET_ALARM, - system_rtc_get_alarm, - EC_VER_MASK(0)); - -#endif /* CONFIG_HOSTCMD_RTC */ -#ifdef CONFIG_EXTERNAL_STORAGE -void system_jump_to_booter(void) -{ - enum API_RETURN_STATUS_T status __attribute__((unused)); - static uint32_t flash_offset; - static uint32_t flash_used; - static uint32_t addr_entry; - - /* - * Get memory offset and size for RO/RW regions. - * Both of them need 16-bytes alignment since GDMA burst mode. - */ - switch (system_get_shrspi_image_copy()) { - case SYSTEM_IMAGE_RW: - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_STORAGE_OFF; - flash_used = CONFIG_RW_SIZE; - break; -#ifdef CONFIG_RW_B - case SYSTEM_IMAGE_RW_B: - flash_offset = CONFIG_EC_WRITABLE_STORAGE_OFF + - CONFIG_RW_B_STORAGE_OFF; - flash_used = CONFIG_RW_SIZE; - break; -#endif - case SYSTEM_IMAGE_RO: - default: /* Jump to RO by default */ - flash_offset = CONFIG_EC_PROTECTED_STORAGE_OFF + - CONFIG_RO_STORAGE_OFF; - flash_used = CONFIG_RO_SIZE; - break; - } - - /* Make sure the reset vector is inside the destination image */ - addr_entry = *(uintptr_t *)(flash_offset + - CONFIG_MAPPED_STORAGE_BASE + 4); - - /* - * Speed up FW download time by increasing clock freq of EC. It will - * restore to default in clock_init() later. - */ - clock_turbo(); - - /* Bypass for GMDA issue of ROM api utilities */ -#if defined(CHIP_FAMILY_NPCX5) - system_download_from_flash( - flash_offset, /* The offset of the data in spi flash */ - CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of downloaded data */ - flash_used, /* Number of bytes to download */ - addr_entry /* jump to this address after download */ - ); -#else - download_from_flash( - flash_offset, /* The offset of the data in spi flash */ - CONFIG_PROGRAM_MEMORY_BASE, /* RAM Addr of downloaded data */ - flash_used, /* Number of bytes to download */ - SIGN_NO_CHECK, /* Need CRC check or not */ - addr_entry, /* jump to this address after download */ - &status /* Status fo download */ - ); -#endif -} - -uint32_t system_get_lfw_address() -{ - /* - * In A3 version, we don't use little FW anymore - * We provide the alternative function in ROM - */ - uint32_t jump_addr = (uint32_t)system_jump_to_booter; - return jump_addr; -} - -/* - * Set and clear image copy flags in MDC register. - * - * NPCX_FWCTRL_RO_REGION: 1 - RO, 0 - RW - * NPCX_FWCTRL_FW_SLOT: 1 - SLOT_A, 0 - SLOT_B - */ -void system_set_image_copy(enum system_image_copy_t copy) -{ - switch (copy) { - case SYSTEM_IMAGE_RW: - CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); - SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); - break; -#ifdef CONFIG_RW_B - case SYSTEM_IMAGE_RW_B: - CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); - CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); - break; -#endif - default: - CPRINTS("Invalid copy (%d) is requested as a jump destination. " - "Change it to %d.", copy, SYSTEM_IMAGE_RO); - /* Fall through to SYSTEM_IMAGE_RO */ - case SYSTEM_IMAGE_RO: - SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION); - SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT); - break; - } -} - -enum system_image_copy_t system_get_shrspi_image_copy(void) -{ - if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) { - /* RO image */ -#ifdef CHIP_HAS_RO_B - if (!IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT)) - return SYSTEM_IMAGE_RO_B; -#endif - return SYSTEM_IMAGE_RO; - } else { -#ifdef CONFIG_RW_B - /* RW image */ - if (!IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_FW_SLOT)) - /* Slot A */ - return SYSTEM_IMAGE_RW_B; -#endif - return SYSTEM_IMAGE_RW; - } -} - -#endif |