summaryrefslogtreecommitdiff
path: root/zephyr/drivers/cros_system/cros_system_xec.c
diff options
context:
space:
mode:
authorTom Hughes <tomhughes@chromium.org>2022-09-21 14:10:01 -0700
committerTom Hughes <tomhughes@chromium.org>2022-09-22 12:49:33 -0700
commit2bcf863b492fe7ed8105c853814dba6ed32ba719 (patch)
treefcf6ce5810f9ff9e3c8cce434812dd75492269ed /zephyr/drivers/cros_system/cros_system_xec.c
parente5fb0b9ba488614b5684e640530f00821ab7b943 (diff)
parent28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff)
downloadchrome-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.c289
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;