diff options
Diffstat (limited to 'zephyr/drivers/cros_system')
-rw-r--r-- | zephyr/drivers/cros_system/CMakeLists.txt | 6 | ||||
-rw-r--r-- | zephyr/drivers/cros_system/Kconfig | 47 | ||||
-rw-r--r-- | zephyr/drivers/cros_system/cros_system_it8xxx2.c | 246 | ||||
-rw-r--r-- | zephyr/drivers/cros_system/cros_system_npcx.c | 556 |
4 files changed, 0 insertions, 855 deletions
diff --git a/zephyr/drivers/cros_system/CMakeLists.txt b/zephyr/drivers/cros_system/CMakeLists.txt deleted file mode 100644 index 733b8be450..0000000000 --- a/zephyr/drivers/cros_system/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# 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. - -zephyr_library_sources_ifdef(CONFIG_CROS_SYSTEM_IT8XXX2 cros_system_it8xxx2.c) -zephyr_library_sources_ifdef(CONFIG_CROS_SYSTEM_NPCX cros_system_npcx.c) diff --git a/zephyr/drivers/cros_system/Kconfig b/zephyr/drivers/cros_system/Kconfig deleted file mode 100644 index c5d98b6081..0000000000 --- a/zephyr/drivers/cros_system/Kconfig +++ /dev/null @@ -1,47 +0,0 @@ -# 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. - -menuconfig CROS_SYSTEM_NPCX - bool "Nuvoton NPCX cros system driver" - depends on SOC_FAMILY_NPCX - default y - help - This option enables the cros system driver for the NPCX family of - 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 - -config CROS_SYSTEM_IT8XXX2 - bool "ITE IT8XXX2 cros system driver" - depends on SOC_FAMILY_RISCV_ITE - default y - help - This option enables the cros system driver for the it8xxx2 family of - processors. - -if CROS_SYSTEM_IT8XXX2 - -config CROS_SYSTEM_IT8XXX2_INIT_PRIORITY - int "cros_system it8xxx2 initialization priority" - default 10 - help - This sets the it8xxx2 cros_system driver initialization priority. - The cros_system driver provides access to the it8xxx2 reset cause - and must be higher priority than - CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY. - -endif # CROS_SYSTEM_IT8XXX2 diff --git a/zephyr/drivers/cros_system/cros_system_it8xxx2.c b/zephyr/drivers/cros_system/cros_system_it8xxx2.c deleted file mode 100644 index 5731dcf984..0000000000 --- a/zephyr/drivers/cros_system/cros_system_it8xxx2.c +++ /dev/null @@ -1,246 +0,0 @@ -/* 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. - */ - -#define DT_DRV_COMPAT ite_it8xxx2_gctrl - -#include <device.h> -#include <drivers/cros_system.h> -#include <logging/log.h> -#include <soc.h> -#include <soc/ite_it8xxx2/reg_def_cros.h> - -#include "gpio.h" -#include "system.h" -#include "util.h" - -LOG_MODULE_REGISTER(cros_system, LOG_LEVEL_ERR); - -#define GCTRL_IT8XXX2_REG_BASE \ - ((struct gctrl_it8xxx2_regs *)DT_INST_REG_ADDR(0)) - -#define WDT_IT8XXX2_REG_BASE \ - ((struct wdt_it8xxx2_regs *)DT_REG_ADDR(DT_NODELABEL(twd0))) - -static const char *cros_system_it8xxx2_get_chip_vendor(const struct device *dev) -{ - ARG_UNUSED(dev); - - return "ite"; -} - -static uint32_t system_get_chip_id(void) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - return (gctrl_base->GCTRL_ECHIPID1 << 16) | - (gctrl_base->GCTRL_ECHIPID2 << 8) | - gctrl_base->GCTRL_ECHIPID3; -} - -static uint8_t system_get_chip_version(void) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - /* bit[3-0], chip version */ - return gctrl_base->GCTRL_ECHIPVER & 0x0F; -} - -static const char *cros_system_it8xxx2_get_chip_name(const struct device *dev) -{ - ARG_UNUSED(dev); - - static char buf[8] = {'i', 't'}; - uint32_t chip_id = system_get_chip_id(); - int num = 4; - - for (int n = 2; num >= 0; n++, num--) - snprintf(buf+n, (sizeof(buf)-n), "%x", - chip_id >> (num * 4) & 0xF); - - return buf; -} - -static const char *cros_system_it8xxx2_get_chip_revision(const struct device - *dev) -{ - ARG_UNUSED(dev); - - static char buf[3]; - uint8_t rev = system_get_chip_version(); - - snprintf(buf, sizeof(buf), "%1xx", rev+0xa); - - return buf; -} - -static int cros_system_it8xxx2_get_reset_cause(const struct device *dev) -{ - ARG_UNUSED(dev); - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - /* system reset flag */ - uint32_t system_flags = chip_read_reset_flags(); - int chip_reset_cause = 0; - uint8_t raw_reset_cause = gctrl_base->GCTRL_RSTS & IT8XXX2_GCTRL_LRS; - uint8_t raw_reset_cause2 = gctrl_base->GCTRL_SPCTRL4 & - (IT8XXX2_GCTRL_LRSIWR | IT8XXX2_GCTRL_LRSIPWRSWTR | - IT8XXX2_GCTRL_LRSIPGWR); - - /* Clear reset cause. */ - gctrl_base->GCTRL_RSTS |= IT8XXX2_GCTRL_LRS; - gctrl_base->GCTRL_SPCTRL4 |= (IT8XXX2_GCTRL_LRSIWR | - IT8XXX2_GCTRL_LRSIPWRSWTR | IT8XXX2_GCTRL_LRSIPGWR); - - /* Determine if watchdog reset or power on reset. */ - if (raw_reset_cause & IT8XXX2_GCTRL_IWDTR) { - system_flags |= EC_RESET_FLAG_WATCHDOG; - chip_reset_cause = WATCHDOG_RST; - } else if (raw_reset_cause < 2) { - system_flags |= EC_RESET_FLAG_POWER_ON; - chip_reset_cause = POWERUP; - } - /* Determine reset-pin reset. */ - if (raw_reset_cause2 & IT8XXX2_GCTRL_LRSIWR) { - system_flags |= EC_RESET_FLAG_RESET_PIN; - chip_reset_cause = VCC1_RST_PIN; - } - - /* watchdog module triggers these reset */ - if (system_flags & (EC_RESET_FLAG_HARD | EC_RESET_FLAG_SOFT)) - system_flags &= ~EC_RESET_FLAG_WATCHDOG; - - /* Set the system reset flags. */ - system_set_reset_flags(system_flags); - - return chip_reset_cause; -} - -static int cros_system_it8xxx2_init(const struct device *dev) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - - /* System triggers a soft reset by default (command: reboot). */ - gctrl_base->GCTRL_ETWDUARTCR &= ~IT8XXX2_GCTRL_ETWD_HW_RST_EN; - - return 0; -} - -static int cros_system_it8xxx2_soc_reset(const struct device *dev) -{ - struct gctrl_it8xxx2_regs *const gctrl_base = GCTRL_IT8XXX2_REG_BASE; - struct wdt_it8xxx2_regs *const wdt_base = WDT_IT8XXX2_REG_BASE; - uint32_t chip_reset_flags = chip_read_reset_flags(); - - /* Disable interrupts to avoid task swaps during reboot. */ - interrupt_disable_all(); - - if (chip_reset_flags & (EC_RESET_FLAG_HARD | EC_RESET_FLAG_HIBERNATE)) - gctrl_base->GCTRL_ETWDUARTCR |= IT8XXX2_GCTRL_ETWD_HW_RST_EN; - - /* - * Writing invalid key to watchdog module triggers a soft or hardware - * reset. It depends on the setting of bit0 at ETWDUARTCR register. - */ - wdt_base->ETWCFG |= IT8XXX2_WDT_EWDKEYEN; - wdt_base->EWDKEYR = 0x00; - - /* Spin and wait for reboot */ - while (1) - ; - - /* Should never return */ - return 0; -} - -static int cros_system_it8xxx2_hibernate(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - struct wdt_it8xxx2_regs *const wdt_base = WDT_IT8XXX2_REG_BASE; - - /* Disable all interrupts. */ - interrupt_disable_all(); - - /* Save and disable interrupts */ - if (IS_ENABLED(CONFIG_ITE_IT8XXX2_INTC)) - ite_intc_save_and_disable_interrupts(); - - /* bit5: watchdog is disabled. */ - wdt_base->ETWCTRL |= IT8XXX2_WDT_EWDSCEN; - - /* - * Setup GPIOs for hibernate. On some boards, it's possible that this - * may not return at all. On those boards, power to the EC is likely - * being turn off entirely. - */ - if (board_hibernate_late) { - /* - * Set reset flag in case board_hibernate_late() doesn't - * return. - */ - chip_save_reset_flags(EC_RESET_FLAG_HIBERNATE); - board_hibernate_late(); - } - - if (seconds || microseconds) { - /* - * Convert milliseconds(or at least 1 ms) to 32 Hz - * free run timer count for hibernate. - */ - uint32_t c = (seconds * 1000 + microseconds / 1000 + 1) * - 32 / 1000; - - /* Enable a 32-bit timer and clock source is 32 Hz */ - /* Disable external timer x */ - IT8XXX2_EXT_CTRLX(FREE_RUN_TIMER) &= ~IT8XXX2_EXT_ETXEN; - irq_disable(FREE_RUN_TIMER_IRQ); - IT8XXX2_EXT_PSRX(FREE_RUN_TIMER) = EXT_PSR_32; - IT8XXX2_EXT_CNTX(FREE_RUN_TIMER) = c & FREE_RUN_TIMER_MAX_CNT; - /* Enable and re-start external timer x */ - IT8XXX2_EXT_CTRLX(FREE_RUN_TIMER) |= - (IT8XXX2_EXT_ETXEN | IT8XXX2_EXT_ETXRST); - irq_enable(FREE_RUN_TIMER_IRQ); - } - - static const int wakeup_pin_list[] = { -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_HIBERNATE_CONFIG) - UTIL_LISTIFY(SYSTEM_DT_NODE_WAKEUP_PIN_LEN, - SYSTEM_DT_WAKEUP_GPIO_ENUM_BY_IDX, _) -#endif - }; - - /* Reconfigure wake-up GPIOs */ - for (int i = 0; i < ARRAY_SIZE(wakeup_pin_list); i++) - /* Re-enable interrupt for wake-up inputs */ - gpio_enable_interrupt(wakeup_pin_list[i]); - - /* EC sleep mode */ - chip_pll_ctrl(CHIP_PLL_SLEEP); - - /* Chip sleep and wait timer wake it up */ - __asm__ volatile ("wfi"); - - /* Reset EC when wake up from sleep mode (system hibernate) */ - system_reset(SYSTEM_RESET_HIBERNATE); - - return 0; -} - -static const struct cros_system_driver_api cros_system_driver_it8xxx2_api = { - .get_reset_cause = cros_system_it8xxx2_get_reset_cause, - .soc_reset = cros_system_it8xxx2_soc_reset, - .hibernate = cros_system_it8xxx2_hibernate, - .chip_vendor = cros_system_it8xxx2_get_chip_vendor, - .chip_name = cros_system_it8xxx2_get_chip_name, - .chip_revision = cros_system_it8xxx2_get_chip_revision, -}; - -#if CONFIG_CROS_SYSTEM_IT8XXX2_INIT_PRIORITY >= \ - CONFIG_PLATFORM_EC_SYSTEM_PRE_INIT_PRIORITY -#error "CROS_SYSTEM must initialize before the SYSTEM_PRE initialization" -#endif -DEVICE_DEFINE(cros_system_it8xxx2_0, "CROS_SYSTEM", cros_system_it8xxx2_init, - NULL, NULL, NULL, PRE_KERNEL_1, - CONFIG_CROS_SYSTEM_IT8XXX2_INIT_PRIORITY, - &cros_system_driver_it8xxx2_api); diff --git a/zephyr/drivers/cros_system/cros_system_npcx.c b/zephyr/drivers/cros_system/cros_system_npcx.c deleted file mode 100644 index e3d3bc29b2..0000000000 --- a/zephyr/drivers/cros_system/cros_system_npcx.c +++ /dev/null @@ -1,556 +0,0 @@ -/* 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. - */ - -#include <arch/arm/aarch32/cortex_m/cmsis.h> -#include <drivers/cros_system.h> -#include <drivers/gpio.h> -#include <drivers/watchdog.h> -#include <logging/log.h> -#include <soc.h> -#include <soc/nuvoton_npcx/reg_def_cros.h> -#include <sys/util.h> - -#include "gpio.h" -#include "rom_chip.h" -#include "soc_gpio.h" -#include "soc_miwu.h" -#include "system.h" - -LOG_MODULE_REGISTER(cros_system, LOG_LEVEL_ERR); - -/* Driver config */ -struct cros_system_npcx_config { - /* hardware module base address */ - uintptr_t base_scfg; - uintptr_t base_twd; - uintptr_t base_mswc; -}; - -/* Driver data */ -struct cros_system_npcx_data { - int reset; /* reset cause */ -}; - -/* Driver convenience defines */ -#define DRV_CONFIG(dev) ((const struct cros_system_npcx_config *)(dev)->config) - -#define HAL_SCFG_INST(dev) (struct scfg_reg *)(DRV_CONFIG(dev)->base_scfg) -#define HAL_TWD_INST(dev) (struct twd_reg *)(DRV_CONFIG(dev)->base_twd) -#define HAL_MSWC_INST(dev) (struct mswc_reg *)(DRV_CONFIG(dev)->base_mswc) - -#define DRV_DATA(dev) ((struct cros_system_npcx_data *)(dev)->data) - -#define SYSTEM_DT_NODE_SOC_ID_CONFIG DT_INST(0, nuvoton_npcx_soc_id) - -/* Chip info devicetree data */ -#define NPCX_FAMILY_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, family_id) - -#define NPCX_CHIP_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, chip_id) - -#define NPCX_DEVICE_ID DT_PROP(SYSTEM_DT_NODE_SOC_ID_CONFIG, device_id) - -#define NPCX_REVISION_ADDR \ - DT_PROP_BY_IDX(SYSTEM_DT_NODE_SOC_ID_CONFIG, revision_reg, 0) -#define NPCX_REVISION_LEN \ - DT_PROP_BY_IDX(SYSTEM_DT_NODE_SOC_ID_CONFIG, revision_reg, 1) - -/* RAM block size in npcx family (Unit: bytes) */ -#define NPCX_RAM_BLOCK_SIZE (32 * 1024) -/* RAM block number in npcx7 series */ - -/* Calculate the number of RAM blocks: - * total RAM size = code ram + data ram + extra 2K for ROM functions - * divided by the block size 32k. - */ -#define DATA_RAM_SIZE DT_REG_SIZE(DT_NODELABEL(sram0)) -#define CODE_RAM_SIZE DT_REG_SIZE(DT_NODELABEL(flash0)) -#define NPCX_RAM_BLOCK_COUNT \ - ((DATA_RAM_SIZE + CODE_RAM_SIZE + KB(2)) / NPCX_RAM_BLOCK_SIZE) - -/* Valid bit-depth of RAM block Power-Down control (RAM_PD) registers. Use its - * mask to power down all unnecessary RAM blocks before hibernating. - */ -#define NPCX_RAM_PD_DEPTH DT_PROP(DT_NODELABEL(pcc), ram_pd_depth) -#define NPCX_RAM_BLOCK_PD_MASK (BIT(NPCX_RAM_PD_DEPTH) - 1) - -/* Get saved reset flag address in battery-backed ram */ -#define BBRAM_SAVED_RESET_FLAG_ADDR \ - (DT_REG_ADDR(DT_INST(0, nuvoton_npcx_bbram)) + \ - DT_PROP(DT_PATH(named_bbram_regions, saved_reset_flags), offset)) - -/* Soc specific system local functions */ -static int system_npcx_watchdog_stop(void) -{ - if (IS_ENABLED(CONFIG_WATCHDOG)) { - const struct device *wdt_dev = DEVICE_DT_GET( - DT_NODELABEL(twd0)); - if (!device_is_ready(wdt_dev)) { - LOG_ERR("Error: device %s is not ready", wdt_dev->name); - return -ENODEV; - } - - wdt_disable(wdt_dev); - } - - return 0; -} - -static void system_npcx_set_flash_pins_tri_state(const struct device *dev) -{ - struct scfg_reg *const inst_scfg = HAL_SCFG_INST(dev); - - inst_scfg->DEVCNT |= BIT(NPCX_DEVCNT_F_SPI_TRIS); -} - -static void system_npcx_init_watchdog_reset(const struct device *dev) -{ - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - - /* Enable early touch */ - inst_twd->T0CSR &= ~BIT(NPCX_T0CSR_TESDIS); - /* watchdog touched by writing 5Ch to WDSDM */ - inst_twd->TWCFG |= BIT(NPCX_TWCFG_WDSDME); -} - -static void system_npcx_turn_off_adc(void) -{ - struct adc_reg *const inst_adc = - (struct adc_reg *)(DT_REG_ADDR(DT_INST(0, nuvoton_npcx_adc))); - - inst_adc->ADCCNF = 0; - /* Wait for 1000 us to make sure conversion is completed. */ - k_busy_wait(1000); -} - -static void system_npcx_turn_off_kernel_timer(void) -{ - static struct itim32_reg *const evt_tmr = - (struct itim32_reg *)DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_itim_timer), evt_itim); - - evt_tmr->ITCTS32 &= ~BIT(NPCX_ITCTSXX_ITEN); -} - -static void system_npcx_disable_instant_wakeup(void) -{ - struct pmc_reg *const inst_pmc = (struct pmc_reg *)(DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_pcc), pmc)); - - inst_pmc->ENIDL_CTL &= ~BIT(NPCX_ENIDL_CTL_LP_WK_CTL); -} - -static void system_npcx_set_wakeup_gpios_before_hibernate(void) -{ - const uintptr_t miwu_base[] = { - DT_REG_ADDR(DT_INST(0, nuvoton_npcx_miwu)), - DT_REG_ADDR(DT_INST(1, nuvoton_npcx_miwu)), - DT_REG_ADDR(DT_INST(2, nuvoton_npcx_miwu)), - }; - - /* Disable all MIWU inputs before entering hibernate */ - for (int table = 0; table < ARRAY_SIZE(miwu_base); table++) { - for (int group = 0; group < NPCX_MIWU_GROUP_COUNT; group++) { - /* Disable all wake-ups */ - NPCX_WKEN(miwu_base[table], group) = 0x00; - /* Clear all pending bits of wake-ups */ - NPCX_WKPCL(miwu_base[table], group) = 0xFF; - /* - * Disable all inputs of wake-ups to prevent leakage - * caused by input floating. - */ - NPCX_WKINEN(miwu_base[table], group) = 0x00; - } - } - - static const int wakeup_pin_list[] = { -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_HIBERNATE_CONFIG) - UTIL_LISTIFY(SYSTEM_DT_NODE_WAKEUP_PIN_LEN, - SYSTEM_DT_WAKEUP_GPIO_ENUM_BY_IDX, _) -#endif - }; - - /* Reconfigure wake-up GPIOs */ - for (int i = 0; i < ARRAY_SIZE(wakeup_pin_list); i++) { - gpio_reset(wakeup_pin_list[i]); - /* Re-enable interrupt for wake-up inputs */ - gpio_enable_interrupt(wakeup_pin_list[i]); - } -} - -/* - * Hibernate function locates in the last 32K ram block in npcx7 series. - * Do not use global variables or call functions since we have turned off - * the other ram blocks. - */ -noreturn void __keep __attribute__((section(".lfw.hiber"))) -system_npcx_hibernate_by_lfw_in_last_ram(const struct device *dev, - uint32_t pd_ram_mask) -{ - /* Modules used for hibernating */ - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - struct mtc_reg *const inst_mtc = (struct mtc_reg *)(DT_REG_ADDR( - DT_INST(0, nuvoton_npcx_cros_mtc))); - struct pmc_reg *const inst_pmc = (struct pmc_reg *)(DT_REG_ADDR_BY_NAME( - DT_INST(0, nuvoton_npcx_pcc), pmc)); - uint32_t reset_flags; - volatile uint8_t *saved_reset_flags = - (volatile uint8_t *)BBRAM_SAVED_RESET_FLAG_ADDR; - - /* Turn off all blocks except last one for better power consumption */ - inst_pmc->RAM_PD[0] = (uint8_t)pd_ram_mask; - inst_pmc->RAM_PD[1] = (uint8_t)(pd_ram_mask >> 8); - - /* Set deep idle mode */ - inst_pmc->PMCSR = BIT(NPCX_PMCSR_IDLE) | BIT(NPCX_PMCSR_DHF); - - /* Enter system sleep mode */ - __asm__ volatile("wfi"); - - /* - * Mark wake-up reason for hibernate. Do not call bbram utilities - * directly since the other ram blocks are power down. - */ - if (IS_BIT_SET(inst_mtc->WTC, NPCX_WTC_PTO)) { - /* Save wake-up reason as RTC alarm. */ - reset_flags = EC_RESET_FLAG_RTC_ALARM; - } else { - /* Otherwise, we treat it as GPIOs wake-up */ - reset_flags = EC_RESET_FLAG_WAKE_PIN; - } - - saved_reset_flags[0] |= reset_flags; - saved_reset_flags[1] |= reset_flags >> 8; - saved_reset_flags[2] |= reset_flags >> 16; - saved_reset_flags[3] |= reset_flags >> 24; - - /* - * 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; - - /* Spin and wait for reboot; should never return */ - while (1) - continue; -} - -static inline int system_npcx_get_ram_blk_by_lfw_addr(char *address) -{ - return NPCX_RAM_BLOCK_COUNT - - ceiling_fraction((uint32_t)address - - CONFIG_CROS_EC_PROGRAM_MEMORY_BASE, - NPCX_RAM_BLOCK_SIZE); -} - -static void system_npcx_hibernate_by_disable_ram(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - /* Get 32kb ram block order of lfw function */ - extern char __lfw_text_start[], __lfw_text_end[]; - int lfw_block = system_npcx_get_ram_blk_by_lfw_addr(__lfw_text_start); - uint32_t pd_ram_mask = ~BIT(lfw_block) & NPCX_RAM_BLOCK_PD_MASK; - - if (lfw_block != system_npcx_get_ram_blk_by_lfw_addr(__lfw_text_end)) { - LOG_ERR("LFW cannot cross ram blocks!"); - return; - } - - /* - * Set status of pins which connect to flash to tri-state in case - * the leakage current. - */ - system_npcx_set_flash_pins_tri_state(dev); - - /* Initialize watchdog for reset after wake-up from hibernating */ - system_npcx_init_watchdog_reset(dev); - - /* Disable ADC and wait for 1000 us to make sure conversion is done */ - if (IS_ENABLED(CONFIG_ADC)) - system_npcx_turn_off_adc(); - - /* Disable kernel timer */ - system_npcx_turn_off_kernel_timer(); - - /* Disable instant wake up mode for better power consumption */ - system_npcx_disable_instant_wakeup(); - - /* - * Set wake-up input GPIOs and turn off the other sources for better - * power consumption before entering hibernate mode. - */ - system_npcx_set_wakeup_gpios_before_hibernate(); - - /* - * Give the board a chance to do any late stage hibernation work. This - * is likely going to configure GPIOs for hibernation. On some boards, - * it's possible that this may not return at all. On those boards, - * power to the EC is likely being turn off entirely. - */ - if (board_hibernate_late) { - board_hibernate_late(); - } - - /* Setup a RTC alarm if needed */ - if (IS_ENABLED(CONFIG_RTC) && (seconds || microseconds)) { - system_set_rtc_alarm(seconds, microseconds); - } - - /* Clear all pending IRQs in case wake-up immediately after sleeping */ - for (int i = 0; i < CONFIG_NUM_IRQS; i++) { - NVIC_ClearPendingIRQ(i); - } - - /* Execute hibernate by lfw which locates in last 32K block ram */ - system_npcx_hibernate_by_lfw_in_last_ram(dev, pd_ram_mask); -} - -static const char *cros_system_npcx_get_chip_vendor(const struct device *dev) -{ - struct mswc_reg *const inst_mswc = HAL_MSWC_INST(dev); - static char str[11] = "Unknown-XX"; - char *p = str + 8; - uint8_t fam_id = inst_mswc->SID_CR; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - if (fam_id == NPCX_FAMILY_ID) { - return "Nuvoton"; - } -#endif - - hex2char(fam_id >> 4, p++); - hex2char(fam_id & 0xf, p); - return str; -} - -static const char *cros_system_npcx_get_chip_name(const struct device *dev) -{ - struct mswc_reg *const inst_mswc = HAL_MSWC_INST(dev); - static char str[13] = "Unknown-XXXX"; - char *p = str + 8; - uint8_t chip_id = inst_mswc->SRID_CR; - uint8_t device_id = inst_mswc->DEVICE_ID_CR; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - if (chip_id == NPCX_CHIP_ID && device_id == NPCX_DEVICE_ID) { - return CONFIG_SOC; - } -#endif - - hex2char(chip_id >> 4, p++); - hex2char(chip_id & 0xf, p++); - hex2char(device_id >> 4, p++); - hex2char(device_id & 0xf, p); - return str; -} - -static const char *cros_system_npcx_get_chip_revision(const struct device *dev) -{ - ARG_UNUSED(dev); -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - static char rev[NPCX_REVISION_LEN * 2 + 1]; -#else - static char rev[1]; -#endif - char *p = rev; - -#if DT_NODE_EXISTS(SYSTEM_DT_NODE_SOC_ID_CONFIG) - /* - * For NPCX7, the revision number is 1 byte. - * For NPCX9 and later chips, the revision number is 4 bytes. - */ - for (int s = NPCX_REVISION_ADDR + NPCX_REVISION_LEN - 1; - s >= NPCX_REVISION_ADDR; s--) { - uint8_t r = *((volatile uint8_t *)s); - hex2char(r >> 4, p++); - hex2char(r & 0xf, p++); - } -#endif - *p = '\0'; - - return rev; -} - -static void system_npcx_hibernate_by_psl(const struct device *dev, - uint32_t seconds, - uint32_t microseconds) -{ - ARG_UNUSED(dev); - /* - * TODO(b/178230662): RTC wake-up in PSL mode only support in npcx9 - * series. Nuvoton will introduce CLs for it later. - */ - ARG_UNUSED(seconds); - ARG_UNUSED(microseconds); - - /* - * Configure PSL input pads from "psl-in-pads" property in device tree - * file. - */ - npcx_pinctrl_psl_input_configure(); - - /* - * Give the board a chance to do any late stage hibernation work. This - * is likely going to configure GPIOs for hibernation. On some boards, - * it's possible that this may not return at all. On those boards, - * power to the EC is likely being turn off entirely. - */ - if (board_hibernate_late) - board_hibernate_late(); - - /* Turn off VCC1 to enter ultra-low-power mode for hibernating */ - npcx_pinctrl_psl_output_set_inactive(); -} - -static int cros_system_npcx_get_reset_cause(const struct device *dev) -{ - struct cros_system_npcx_data *data = DRV_DATA(dev); - - return data->reset; -} - -static int cros_system_npcx_init(const struct device *dev) -{ - struct scfg_reg *const inst_scfg = HAL_SCFG_INST(dev); - struct twd_reg *const inst_twd = HAL_TWD_INST(dev); - struct cros_system_npcx_data *data = DRV_DATA(dev); - - /* check reset cause */ - if (IS_BIT_SET(inst_twd->T0CSR, NPCX_T0CSR_WDRST_STS)) { - data->reset = WATCHDOG_RST; - inst_twd->T0CSR |= BIT(NPCX_T0CSR_WDRST_STS); - } else if (IS_BIT_SET(inst_scfg->RSTCTL, NPCX_RSTCTL_DBGRST_STS)) { - data->reset = DEBUG_RST; - inst_scfg->RSTCTL |= BIT(NPCX_RSTCTL_DBGRST_STS); - } else if (IS_BIT_SET(inst_scfg->RSTCTL, NPCX_RSTCTL_VCC1_RST_STS)) { - data->reset = VCC1_RST_PIN; - } else { - data->reset = POWERUP; - } - - 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 */ - system_npcx_watchdog_stop(); - - /* Initialize watchdog for reset */ - system_npcx_init_watchdog_reset(dev); - - /* - * 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 int cros_system_npcx_hibernate(const struct device *dev, - uint32_t seconds, uint32_t microseconds) -{ - /* Disable interrupt first */ - interrupt_disable_all(); - - /* Stop the watchdog */ - system_npcx_watchdog_stop(); - - /* Enter hibernate mode */ - if (IS_ENABLED(CONFIG_PLATFORM_EC_HIBERNATE_PSL)) { - system_npcx_hibernate_by_psl(dev, seconds, microseconds); - } else { - system_npcx_hibernate_by_disable_ram(dev, seconds, - microseconds); - } - - return 0; -} - -__maybe_unused static uint64_t -cros_system_npcx_deep_sleep_ticks(const struct device *dev) -{ - return npcx_clock_get_sleep_ticks(); -} - -static struct cros_system_npcx_data cros_system_npcx_dev_data; - -static const struct cros_system_npcx_config cros_system_dev_cfg = { - .base_scfg = DT_REG_ADDR(DT_INST(0, nuvoton_npcx_scfg)), - .base_twd = DT_REG_ADDR(DT_INST(0, nuvoton_npcx_watchdog)), - .base_mswc = - DT_REG_ADDR_BY_NAME(DT_INST(0, nuvoton_npcx_host_sub), mswc), -}; - -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, - .hibernate = cros_system_npcx_hibernate, - .chip_vendor = cros_system_npcx_get_chip_vendor, - .chip_name = cros_system_npcx_get_chip_name, - .chip_revision = cros_system_npcx_get_chip_revision, -#ifdef CONFIG_SOC_POWER_MANAGEMENT_TRACE - .deep_sleep_ticks = cros_system_npcx_deep_sleep_ticks, -#endif -}; - -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, - CONFIG_CROS_SYSTEM_NPCX_INIT_PRIORITY, - &cros_system_driver_npcx_api); - -#if DT_NODE_EXISTS(DT_NODELABEL(dbg)) -#define HAL_DBG_REG_BASE_ADDR \ - ((struct dbg_reg *)DT_REG_ADDR(DT_INST(0, nuvoton_npcx_cros_dbg))) - -#define DBG_NODE DT_NODELABEL(dbg) -#define DBG_PINCTRL_PH DT_PHANDLE_BY_IDX(DBG_NODE, pinctrl_0, 0) -#define DBG_ALT_FILED(f) DT_PHA_BY_IDX(DBG_PINCTRL_PH, alts, 0, f) - -static int jtag_init(const struct device *dev) -{ - ARG_UNUSED(dev); - struct dbg_reg *const dbg_reg_base = HAL_DBG_REG_BASE_ADDR; - const struct npcx_alt jtag_alts[] = { - { - .group = DBG_ALT_FILED(group), - .bit = DBG_ALT_FILED(bit), - .inverted = DBG_ALT_FILED(inv) - } - }; - - dbg_reg_base->DBGCTRL = 0x04; - dbg_reg_base->DBGFRZEN3 &= ~BIT(NPCX_DBGFRZEN3_GLBL_FRZ_DIS); - if (DT_NODE_HAS_STATUS(DT_NODELABEL(dbg), okay)) - npcx_pinctrl_mux_configure(jtag_alts, 1, 1); - - return 0; -} -#if CONFIG_KERNEL_INIT_PRIORITY_DEFAULT >= 41 -#error "jtag_init must be called after default kernel init" -#endif -SYS_INIT(jtag_init, PRE_KERNEL_1, 41); -#endif /* DT_NODE_EXISTS(DT_NODELABEL(dbg)) */ |