diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:10:01 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:49:33 -0700 |
commit | 2bcf863b492fe7ed8105c853814dba6ed32ba719 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /zephyr/drivers/cros_system/cros_system_xec.c | |
parent | e5fb0b9ba488614b5684e640530f00821ab7b943 (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-2bcf863b492fe7ed8105c853814dba6ed32ba719.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-bloonchipper-releasefirmware-fpmcu-bloonchipper-release
Generated by: ./util/update_release_branch.py --board bloonchipper
--relevant_paths_file ./util/fingerprint-relevant-paths.txt firmware-
fpmcu-bloonchipper-release
Relevant changes:
git log --oneline e5fb0b9ba4..28712dae9d -- board/hatch_fp
board/bloonchipper common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dc3e9008b8 board/hatch_fp/board.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:246424843 b:234181908 b:244781166 b:234181908 b:244387210
BUG=b:242720240 chromium:1098010 b:180945056 b:236025198 b:234181908
BUG=b:234181908 b:237344361 b:131913998 b:236386294 b:234143158
BUG=b:234781655 b:215613183 b:242720910
TEST=`make -j buildall`
TEST=./test/run_device_tests.py --board bloonchipper
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "stm32f_rtc": PASSED
Test "panic_data_bloonchipper_v2.0.4277": PASSED
Test "panic_data_bloonchipper_v2.0.5938": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I264ad0ffe7afcd507a1e483c6e934a9c4fea47c3
Diffstat (limited to 'zephyr/drivers/cros_system/cros_system_xec.c')
-rw-r--r-- | zephyr/drivers/cros_system/cros_system_xec.c | 289 |
1 files changed, 279 insertions, 10 deletions
diff --git a/zephyr/drivers/cros_system/cros_system_xec.c b/zephyr/drivers/cros_system/cros_system_xec.c index 8d0c8f864c..a3cf9aea22 100644 --- a/zephyr/drivers/cros_system/cros_system_xec.c +++ b/zephyr/drivers/cros_system/cros_system_xec.c @@ -1,4 +1,4 @@ -/* Copyright 2022 The Chromium OS Authors. All rights reserved. +/* Copyright 2022 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -13,9 +13,42 @@ #include "system.h" #include "system_chip.h" +#include <zephyr/drivers/interrupt_controller/intc_mchp_xec_ecia.h> +#include "gpio/gpio_int.h" LOG_MODULE_REGISTER(cros_system, LOG_LEVEL_ERR); +/* Modules Map */ +#define STRUCT_ADC_REG_BASE_ADDR \ + ((struct adc_regs *)(DT_REG_ADDR(DT_NODELABEL(adc0)))) + +#define STRUCT_UART_REG_BASE_ADDR \ + ((struct uart_regs *)(DT_REG_ADDR(DT_NODELABEL(uart0)))) + +#define STRUCT_ECS_REG_BASE_ADDR \ + ((struct ecs_regs *)(DT_REG_ADDR(DT_NODELABEL(ecs)))) + +#define STRUCT_TIMER4_REG_BASE_ADDR \ + ((struct btmr_regs *)(DT_REG_ADDR(DT_NODELABEL(timer4)))) + +#define STRUCT_ESPI_REG_BASE_ADDR \ + ((struct espi_iom_regs *)(DT_REG_ADDR(DT_NODELABEL(espi0)))) + +#define STRUCT_KBD_REG_BASE_ADDR \ + ((struct kscan_regs *)(DT_REG_ADDR(DT_NODELABEL(cros_kb_raw)))) + +#define STRUCT_QMSPI_REG_BASE_ADDR \ + ((struct qmspi_regs *)(DT_REG_ADDR(DT_NODELABEL(spi0)))) + +#define STRUCT_PWM_REG_BASE_ADDR \ + ((struct pwm_regs *)(DT_REG_ADDR(DT_NODELABEL(pwm0)))) + +#define STRUCT_TACH_REG_BASE_ADDR \ + ((struct tach_regs *)(DT_REG_ADDR(DT_NODELABEL(tach0)))) + +#define STRUCT_HTMR0_REG_BASE_ADDR \ + ((struct htmr_regs *)(DT_REG_ADDR(DT_NODELABEL(hibtimer0)))) + /* Driver config */ struct cros_system_xec_config { /* hardware module base address */ @@ -38,7 +71,7 @@ struct cros_system_xec_data { #define HAL_WDOG_INST(dev) (struct wdt_regs *)(DRV_CONFIG(dev)->base_wdog) /* Get saved reset flag address in battery-backed ram */ -#define BBRAM_SAVED_RESET_FLAG_ADDR \ +#define BBRAM_SAVED_RESET_FLAG_ADDR \ (DT_REG_ADDR(DT_INST(0, microchip_xec_bbram)) + \ DT_PROP(DT_PATH(named_bbram_regions, saved_reset_flags), offset)) @@ -46,8 +79,8 @@ struct cros_system_xec_data { static int system_xec_watchdog_stop(void) { if (IS_ENABLED(CONFIG_WATCHDOG)) { - const struct device *wdt_dev = DEVICE_DT_GET( - DT_NODELABEL(wdog)); + const struct device *wdt_dev = + DEVICE_DT_GET(DT_NODELABEL(wdog)); if (!device_is_ready(wdt_dev)) { LOG_ERR("Error: device %s is not ready", wdt_dev->name); return -ENODEV; @@ -120,6 +153,8 @@ noreturn static int cros_system_xec_soc_reset(const struct device *dev) /* Disable interrupts to avoid task swaps during reboot */ interrupt_disable_all(); + /* Stop the watchdog */ + system_xec_watchdog_stop(); /* Trigger chip reset */ pcr->SYS_RST |= MCHP_PCR_SYS_RESET_NOW; @@ -130,20 +165,254 @@ noreturn static int cros_system_xec_soc_reset(const struct device *dev) /* return 0; */ } -static int cros_system_xec_hibernate(const struct device *dev, - uint32_t seconds, uint32_t microseconds) +/* Configure wakeup GPIOs in hibernate (from hibernate-wake-pins). */ +static void system_xec_set_wakeup_gpios_before_hibernate(void) +{ +#if DT_NODE_EXISTS(SYSTEM_DT_NODE_HIBERNATE_CONFIG) + +/* + * Get the interrupt DTS node for this wakeup pin + */ +#define WAKEUP_INT(id, prop, idx) DT_PHANDLE_BY_IDX(id, prop, idx) + +/* + * Get the named-gpio node for this wakeup pin by reading the + * irq-gpio property from the interrupt node. + */ +#define WAKEUP_NGPIO(id, prop, idx) \ + DT_PHANDLE(WAKEUP_INT(id, prop, idx), irq_pin) + +/* + * Reset and re-enable interrupts on this wake pin. + */ +#define WAKEUP_SETUP(id, prop, idx) \ + do { \ + gpio_pin_configure_dt( \ + GPIO_DT_FROM_NODE(WAKEUP_NGPIO(id, prop, idx)), \ + GPIO_INPUT); \ + gpio_enable_dt_interrupt( \ + GPIO_INT_FROM_NODE(WAKEUP_INT(id, prop, idx))); \ + } while (0); + + /* + * For all the wake-pins, re-init the GPIO and re-enable the interrupt. + */ + DT_FOREACH_PROP_ELEM(SYSTEM_DT_NODE_HIBERNATE_CONFIG, wakeup_irqs, + WAKEUP_SETUP); + +#undef WAKEUP_INT +#undef WAKEUP_NGPIO +#undef WAKEUP_SETUP + +#endif +} + +/** + * initialization of Hibernation timer 0 + * GIRQ=23, aggregator bit = 16, Direct NVIC = 112 + * NVIC direct connect interrupts are used for all peripherals + * (exception GPIO's) + */ +static void htimer_init(void) +{ + struct htmr_regs *htmr0 = STRUCT_HTMR0_REG_BASE_ADDR; + + /* disable HT0 at beginning */ + htmr0->PRLD = 0U; + mchp_soc_ecia_girq_src_clr(MCHP_GIRQ23_ID, MCHP_HTMR_0_GIRQ_POS); + mchp_soc_ecia_girq_src_en(MCHP_GIRQ23_ID, MCHP_HTMR_0_GIRQ_POS); + + /* enable NVIC interrupt for HT0 */ + irq_enable(MCHP_HTMR_0_GIRQ_NVIC_DIRECT); +} + +/** + * Use hibernate module to set up an htimer interrupt at a given + * time from now + * + * @param seconds Number of seconds before htimer interrupt + * @param microseconds Number of microseconds before htimer interrupt + * @note hibernation timer input clock is 32.768KHz. + */ +static void system_set_htimer_alarm(uint32_t seconds, uint32_t microseconds) +{ + uint32_t hcnt, ns; + uint8_t hctrl; + struct htmr_regs *htmr0 = STRUCT_HTMR0_REG_BASE_ADDR; + + /* disable HT0 */ + htmr0->PRLD = 0U; + + if (microseconds > 1000000ul) { + ns = (microseconds / 1000000ul); + microseconds %= 1000000ul; + if ((0xfffffffful - seconds) > ns) + seconds += ns; + else + seconds = 0xfffffffful; + } + + /* + * Hibernation timer input clock is 32.768KHz. + * Control register bit[0] selects the divider. + * If bit[0] is 0, divide by 1 for 30.5 us per LSB for a maximum of + * 65535 * 30.5 us = 1998817.5 us or 32.786 counts per second + * If bit[0] is 1, divide by 4096 for 0.125 s per LSB for a maximum + * of ~2 hours, 65535 * 0.125 s ~ 8192 s = 2.27 hours + */ + if (seconds > 1) { + hcnt = (seconds << 3); /* divide by 0.125 */ + if (hcnt > 0xfffful) + hcnt = 0xfffful; + hctrl = 1; + } else { + /* + * approximate(~2% error) as seconds is 0 or 1 + * seconds / 30.5e-6 + microseconds / 30.5 + */ + hcnt = (seconds << 15) + (microseconds >> 5) + + (microseconds >> 10); + hctrl = 0; + } + + htmr0->CTRL = hctrl; + htmr0->PRLD = hcnt; +} + +/* Put the EC in hibernate (lowest EC power state). */ +noreturn static int cros_system_xec_hibernate(const struct device *dev, + uint32_t seconds, + uint32_t microseconds) { + struct pcr_regs *const pcr = HAL_PCR_INST(dev); +#ifdef CONFIG_ADC_XEC_V2 + struct adc_regs *adc0 = STRUCT_ADC_REG_BASE_ADDR; +#endif +#ifdef CONFIG_UART_XEC + struct uart_regs *uart0 = STRUCT_UART_REG_BASE_ADDR; +#endif + struct ecs_regs *ecs = STRUCT_ECS_REG_BASE_ADDR; + struct btmr_regs *btmr4 = STRUCT_TIMER4_REG_BASE_ADDR; + struct espi_iom_regs *espi0 = STRUCT_ESPI_REG_BASE_ADDR; +#ifdef CONFIG_CROS_KB_RAW_XEC + struct kscan_regs *kbd = STRUCT_KBD_REG_BASE_ADDR; +#endif + struct qmspi_regs *qmspi0 = STRUCT_QMSPI_REG_BASE_ADDR; +#if defined(CONFIG_PWM_XEC) + struct pwm_regs *pwm0 = STRUCT_PWM_REG_BASE_ADDR; +#endif +#if defined(CONFIG_TACH_XEC) + struct tach_regs *tach0 = STRUCT_TACH_REG_BASE_ADDR; +#endif + struct ecia_regs *ecia = (struct ecia_regs *)(ECIA_BASE_ADDR); + int i; + /* Disable interrupt first */ interrupt_disable_all(); - /* Stop the watchdog */ system_xec_watchdog_stop(); - /* Enter hibernate mode */ + /* Disable all individaul block interrupt and source */ + for (i = 0; i < MCHP_GIRQ_IDX_MAX; ++i) { + ecia->GIRQ[i].EN_CLR = 0xffffffff; + ecia->GIRQ[i].SRC = 0xffffffff; + } - /* MCHP TODO */ + /* Disable and clear all NVIC interrupt pending */ + for (i = 0; i < MCHP_MAX_NVIC_EXT_INPUTS; ++i) { + mchp_xec_ecia_nvic_clr_pend(i); + } - return 0; + /* Disable blocks */ +#ifdef CONFIG_ADC_XEC_V2 + /* Disable ADC */ + adc0->CONTROL &= ~(MCHP_ADC_CTRL_ACTV); +#endif + /* Disable eSPI */ + espi0->ACTV &= ~0x01; +#ifdef CONFIG_CROS_KB_RAW_XEC + /* Disable Keyboard Scanner */ + kbd->KSO_SEL &= ~(MCHP_KSCAN_KSO_EN); +#endif +#ifdef CONFIG_I2C + /* Disable SMB / I2C */ + for (i = 0; i < MCHP_I2C_SMB_INSTANCES; i++) { + uint32_t addr = + MCHP_I2C_SMB_BASE_ADDR(i) + MCHP_I2C_SMB_CFG_OFS; + uint32_t regval = sys_read32(addr); + + sys_write32(regval & ~(MCHP_I2C_SMB_CFG_ENAB), addr); + } +#endif + /* Disable QMSPI */ + qmspi0->MODE &= ~MCHP_QMSPI_M_ACTIVATE; +#if defined(CONFIG_PWM_XEC) + /* Disable PWM0 */ + pwm0->CONFIG &= ~MCHP_PWM_CFG_ENABLE; +#endif +#if defined(CONFIG_TACH_XEC) + /* Disable TACH0 */ + tach0->CONTROL &= ~MCHP_TACH_CTRL_EN; +#endif +#if defined(CONFIG_TACH_XEC) || defined(CONFIG_PWM_XEC) + /* This low-speed clock derived from the 48MHz clock domain is used as + * a time base for PWMs and TACHs + * Set SLOW_CLOCK_DIVIDE = CLKOFF to save additional power + */ + pcr->SLOW_CLK_CTRL &= + (~MCHP_PCR_SLOW_CLK_CTRL_100KHZ & MCHP_PCR_SLOW_CLK_CTRL_MASK); +#endif + /* Disable timers - 32bit timer 0 */ + btmr4->CTRL &= ~MCHP_BTMR_CTRL_ENABLE; + /* + * 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 wakeup GPIOs for hibernate */ + system_xec_set_wakeup_gpios_before_hibernate(); + /* Init htimer and enable interrupt if times are not 0 */ + if (seconds || microseconds) { + htimer_init(); + system_set_htimer_alarm(seconds, microseconds); + } + +#ifdef CONFIG_UART_XEC + /* Disable UART0 */ + /* Flush console before hibernating */ + cflush(); + uart0->ACTV &= ~(MCHP_UART_LD_ACTIVATE); +#endif + + /* Disable JATG and RTM */ + ecs->DEBUG_CTRL = 0; + ecs->ETM_CTRL = 0; + + /* + * Set sleep state + * arm sleep state to trigger on next WFI + */ + pcr->SYS_SLP_CTRL |= MCHP_PCR_SYS_SLP_HEAVY; + /* + * Set PRIMASK = 1 so on wake the CPU will not vector to any ISR. + * Set BASEPRI = 0 to allow any priority to wake. + */ + __set_BASEPRI(0); + /* triggers sleep hardware */ + __WFI(); + __NOP(); + __NOP(); + + /* Reset EC chip */ + cros_system_xec_soc_reset(dev); + + /* Should not reach here... */ + /* return 0; */ } static struct cros_system_xec_data cros_system_xec_dev_data; |