diff options
Diffstat (limited to 'chip/mchp/system.c')
-rw-r--r-- | chip/mchp/system.c | 591 |
1 files changed, 0 insertions, 591 deletions
diff --git a/chip/mchp/system.c b/chip/mchp/system.c deleted file mode 100644 index d67314d716..0000000000 --- a/chip/mchp/system.c +++ /dev/null @@ -1,591 +0,0 @@ -/* Copyright 2017 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 : MCHP hardware specific implementation */ - -#include <stdnoreturn.h> - -#include "common.h" /* includes config.h and board.h */ -#include "clock.h" -#include "clock_chip.h" -#include "console.h" -#include "cpu.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "lpc_chip.h" -#include "registers.h" -#include "shared_mem.h" -#include "spi.h" -#include "system.h" -#include "task.h" -#include "tfdp_chip.h" -#include "timer.h" -#include "util.h" - -#define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - -/* Index values for hibernate data registers (RAM backed by VBAT) */ -enum hibdata_index { - HIBDATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratch pad */ - HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */ - HIBDATA_INDEX_PD0, /* USB-PD0 saved port state */ - HIBDATA_INDEX_PD1, /* USB-PD1 saved port state */ - HIBDATA_INDEX_PD2, /* USB-PD2 saved port state */ -}; - -/* - * Voltage rail configuration - * MEC172x VTR1 is 3.3V only, VTR2 is auto-detected 3.3 or 1.8V, and - * VTR3 is always 1.8V. - * MEC170x and MEC152x require manual selection of VTR3 for 1.8 or 3.3V. - * The eSPI pins are on VTR3 and require 1.8V - */ -#ifdef CHIP_FAMILY_MEC172X -static void vtr3_voltage_select(int use18v) -{ - (void) use18v; -} -#else -static void vtr3_voltage_select(int use18v) -{ - if (use18v) - MCHP_EC_GPIO_BANK_PWR |= MCHP_EC_GPIO_BANK_PWR_VTR3_18; - else - MCHP_EC_GPIO_BANK_PWR &= ~(MCHP_EC_GPIO_BANK_PWR_VTR3_18); -} -#endif - - -/* - * The current logic will set EC_RESET_FLAG_RESET_PIN flag - * even if the reset was caused by WDT. MEC170x/MEC152x HW RESET_SYS - * status goes active for any of the following: - * RESET_VTR: power rail change - * WDT Event: WDT timed out - * FW triggered chip reset: SYSRESETREQ or PCR sys reset bit - * The code does check WDT status in the VBAT PFR register. - * Is it correct to report both EC_RESET_FLAG_RESET_PIN and - * EC_RESET_FLAG_WATCHDOG on a WDT only reset? - */ -static void check_reset_cause(void) -{ - uint32_t status = MCHP_VBAT_STS; - uint32_t flags = 0; - uint32_t rst_sts = MCHP_PCR_PWR_RST_STS & - (MCHP_PWR_RST_STS_SYS | - MCHP_PWR_RST_STS_VBAT); - - /* Clear the reset causes now that we've read them */ - MCHP_VBAT_STS |= status; - MCHP_PCR_PWR_RST_STS |= rst_sts; - - /* - * BIT[6] indicates RESET_SYS asserted. - * RESET_SYS will assert on VTR reset, WDT reset, or - * firmware triggering a reset using Cortex-M4 SYSRESETREQ - * or MCHP PCR system reset register. - */ - if (rst_sts & MCHP_PWR_RST_STS_SYS) - flags |= EC_RESET_FLAG_RESET_PIN; - - - flags |= chip_read_reset_flags(); - chip_save_reset_flags(0); - - if ((status & MCHP_VBAT_STS_WDT) && !(flags & (EC_RESET_FLAG_SOFT | - EC_RESET_FLAG_HARD | - EC_RESET_FLAG_HIBERNATE))) - flags |= EC_RESET_FLAG_WATCHDOG; - - system_set_reset_flags(flags); -} - -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)) - return 0; - else - return 1; -} - -/* - * Sleep unused blocks to reduce power. - * Drivers/modules will clear PCR sleep enables for their blocks. - * Keep sleep enables cleared for required blocks: - * ECIA, PMC, CPU, ECS and optionally JTAG. - * SLEEP_ALL feature will set these upon sleep entry. - * Based on CONFIG_CHIPSET_DEBUG enable or disable ARM SWD - * 2-pin JTAG mode. - */ -static void chip_periph_sleep_control(void) -{ - uint32_t d; - - d = MCHP_PCR_SLP_EN0_SLEEP; - - if (IS_ENABLED(CONFIG_CHIPSET_DEBUG)) { - d &= ~(MCHP_PCR_SLP_EN0_JTAG); - MCHP_EC_JTAG_EN = MCHP_JTAG_MODE_SWD | MCHP_JTAG_ENABLE; - } else - MCHP_EC_JTAG_EN &= ~(MCHP_JTAG_ENABLE); - - MCHP_PCR_SLP_EN0 = d; - MCHP_PCR_SLP_EN1 = MCHP_PCR_SLP_EN1_UNUSED_BLOCKS; - MCHP_PCR_SLP_EN2 = MCHP_PCR_SLP_EN2_SLEEP; - MCHP_PCR_SLP_EN3 = MCHP_PCR_SLP_EN3_SLEEP; - MCHP_PCR_SLP_EN4 = MCHP_PCR_SLP_EN4_SLEEP; -} - -#ifdef CONFIG_CHIP_PRE_INIT -void chip_pre_init(void) -{ - chip_periph_sleep_control(); - - if (IS_ENABLED(CONFIG_MCHP_TFDP)) { - /* MCHP Enable TFDP for fast debug messages */ - tfdp_power(1); - tfdp_enable(1, 1); - CPRINTS("chip_pre_init: Image type = 0x%02x", - MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX)); - } -} -#endif - -void system_pre_init(void) -{ - /* - * Make sure AHB Error capture is enabled. - * Signals bus fault to Cortex-M4 core if an address presented - * to AHB is not claimed by any HW block. - */ - MCHP_EC_AHB_ERR = 0; /* write any value to clear */ - MCHP_EC_AHB_ERR_EN = 0; /* enable capture of address on error */ - - /* Manual voltage selection only required for MEC170x and MEC152x */ - if (IS_ENABLED(CONFIG_HOSTCMD_ESPI)) - vtr3_voltage_select(1); - else - vtr3_voltage_select(0); - - if (!IS_ENABLED(CONFIG_CHIP_PRE_INIT)) - chip_periph_sleep_control(); - - /* Enable direct NVIC */ - MCHP_EC_INT_CTRL |= 1; - - /* Disable ARM TRACE debug port */ - MCHP_EC_TRACE_EN &= ~1; - - /* - * Enable aggregated only interrupt GIRQ's - * Make sure direct mode interrupt sources aggregated outputs - * are not enabled. - * Aggregated only GIRQ's 8,9,10,11,12,22,24,25,26 - * Direct GIRQ's = 13,14,15,16,17,18,19,21,23 - * These bits only need to be touched again on RESET_SYS. - * NOTE: GIRQ22 wake for AHB peripherals not processor. - */ - MCHP_INT_BLK_DIS = 0xfffffffful; - MCHP_INT_BLK_EN = MCHP_INT_AGGR_ONLY_BITMAP; - - spi_enable(SPI_FLASH_DEVICE, 1); -} - -uint32_t chip_read_reset_flags(void) -{ - return MCHP_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS); -} - -void chip_save_reset_flags(uint32_t flags) -{ - MCHP_VBAT_RAM(HIBDATA_INDEX_SAVED_RESET_FLAGS) = flags; -} - -noreturn void _system_reset(int flags, int wake_from_hibernate) -{ - uint32_t save_flags = 0; - - /* DEBUG */ - CPRINTS("MEC system reset: flag = 0x%08x wake = %d", flags, - wake_from_hibernate); - - /* Disable interrupts to avoid task swaps during reboot */ - interrupt_disable(); - - /* Save current reset reasons if necessary */ - if (flags & SYSTEM_RESET_PRESERVE_FLAGS) - save_flags = system_get_reset_flags() | EC_RESET_FLAG_PRESERVED; - - if (flags & SYSTEM_RESET_LEAVE_AP_OFF) - save_flags |= EC_RESET_FLAG_AP_OFF; - - if (wake_from_hibernate) - save_flags |= EC_RESET_FLAG_HIBERNATE; - else if (flags & SYSTEM_RESET_HARD) - save_flags |= EC_RESET_FLAG_HARD; - else - save_flags |= EC_RESET_FLAG_SOFT; - - chip_save_reset_flags(save_flags); - - /* - * Trigger chip reset - */ - if (!IS_ENABLED(CONFIG_DEBUG_BRINGUP)) - MCHP_PCR_SYS_RST |= MCHP_PCR_SYS_SOFT_RESET; - - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -void system_reset(int flags) -{ - _system_reset(flags, 0); -} - -const char *system_get_chip_vendor(void) -{ - return "mchp"; -} - -#ifdef CHIP_VARIANT_MEC1701 -/* - * MEC1701H Chip ID = 0x2D - * Rev = 0x82 - */ -const char *system_get_chip_name(void) -{ - switch (MCHP_CHIP_DEV_ID) { - case 0x2D: - return "mec1701"; - default: - return "unknown"; - } -} -#endif - -#ifdef CHIP_FAMILY_MEC152X -/* - * MEC152x family implements chip ID as a 32-bit - * register where: - * b[31:16] = 16-bit Device ID - * b[15:8] = 8-bit Sub ID - * b[7:0] = Revision - * - * MEC1521-128 WFBGA 0023_33_xxh - * MEC1521-144 WFBGA 0023_34_xxh - * MEC1523-144 WFBGA 0023_B4_xxh - * MEC1527-144 WFBGA 0023_74_xxh - * MEC1527-128 WFBGA 0023_73_xxh - */ -const char *system_get_chip_name(void) -{ - switch (MCHP_CHIP_DEVRID32 & ~(MCHP_CHIP_REV_MASK)) { - case 0x00201400: /* 144 pin rev A? */ - return "mec1503_revA"; - case 0x00203400: /* 144 pin */ - return "mec1501"; - case 0x00207400: /* 144 pin */ - return "mec1507"; - case 0x00208400: /* 144 pin */ - return "mec1503"; - case 0x00233300: /* 128 pin */ - case 0x00233400: /* 144 pin */ - return "mec1521"; - case 0x0023B400: /* 144 pin */ - return "mec1523"; - case 0x00237300: /* 128 pin */ - case 0x00237400: /* 144 pin */ - return "mec1527"; - default: - return "unknown"; - } -} -#endif - -#ifdef CHIP_FAMILY_MEC172X -/* - * MEC172x family implements chip ID as a 32-bit - * register where: - * b[31:16] = 16-bit Device ID - * b[15:8] = 8-bit Sub ID - * b[7:0] = Revision - * - * MEC1723N-B0-I/SZ 144 pin: 0x0022_34_xx - * MEC1727N-B0-I/SZ 144 pin: 0x0022_74_xx - * MEC1721N-B0-I/LJ 176 pin: 0x0022_27_xx - * MEC1723N-B0-I/LJ 176 pin: 0x0022_37_xx - * MEC1727N-B0-I/LJ 176 pin: 0x0022_77_xx - */ -const char *system_get_chip_name(void) -{ - switch (MCHP_CHIP_DEVRID32 & ~(MCHP_CHIP_REV_MASK)) { - case 0x00223400: - return "MEC1723NSZ"; - case 0x00227400: - return "MEC1727NSZ"; - case 0x00222700: - return "MEC1721NLJ"; - case 0x00223700: - return "MEC1723NLJ"; - case 0x00227700: - return "MEC1727NLJ"; - default: - return "unknown"; - } -} -#endif - -static char to_hex(int x) -{ - if (x >= 0 && x <= 9) - return '0' + x; - return 'a' + x - 10; -} - -const char *system_get_chip_revision(void) -{ - static char buf[3]; - uint8_t rev = MCHP_CHIP_DEV_REV; - - buf[0] = to_hex(rev / 16); - buf[1] = to_hex(rev & 0xf); - buf[2] = '\0'; - return buf; -} - -static int bbram_idx_lookup(enum system_bbram_idx idx) -{ - switch (idx) { - case SYSTEM_BBRAM_IDX_PD0: - return HIBDATA_INDEX_PD0; - case SYSTEM_BBRAM_IDX_PD1: - return HIBDATA_INDEX_PD1; - case SYSTEM_BBRAM_IDX_PD2: - return HIBDATA_INDEX_PD2; - default: - return 1; - } -} - -int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) -{ - int hibdata = bbram_idx_lookup(idx); - - if (hibdata < 0) - return EC_ERROR_UNIMPLEMENTED; - - *value = MCHP_VBAT_RAM(hibdata); - return EC_SUCCESS; -} - -int system_set_bbram(enum system_bbram_idx idx, uint8_t value) -{ - int hibdata = bbram_idx_lookup(idx); - - if (hibdata < 0) - return EC_ERROR_UNIMPLEMENTED; - - MCHP_VBAT_RAM(hibdata) = value; - return EC_SUCCESS; -} - -int system_set_scratchpad(uint32_t value) -{ - MCHP_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD) = value; - return EC_SUCCESS; -} - -int system_get_scratchpad(uint32_t *value) -{ - *value = MCHP_VBAT_RAM(HIBDATA_INDEX_SCRATCHPAD); - return EC_SUCCESS; -} - -/* - * Local function to disable clocks in the chip's host interface - * so the chip can enter deep sleep. Only MEC170X has LPC. - * MEC152x and MEC172x only include eSPI and SPI host interfaces. - * NOTE: we do it this way because the LPC registers are only - * defined for MEC170x and the IS_ENABLED() macro causes the - * compiler to evaluate both true and false code paths. - */ -#if defined(CONFIG_HOSTCMD_ESPI) -static void disable_host_ifc_clocks(void) -{ - MCHP_ESPI_ACTIVATE &= ~0x01; -} -#else -static void disable_host_ifc_clocks(void) -{ - #ifdef CHIP_FAMILY_MEC170X - MCHP_LPC_ACT &= ~0x1; - #endif -} -#endif - - -/* - * Called when hibernation timer is not used in deep sleep. - * Switch 32 KHz clock logic from external 32KHz input to - * internal silicon OSC. - * NOTE: MEC172x auto-switches from external source to silicon - * oscillator. - */ -#ifdef CHIP_FAMILY_MEC172X -static void switch_32k_pin2sil(void) {} -#else -static void switch_32k_pin2sil(void) -{ - MCHP_VBAT_CE &= ~(MCHP_VBAT_CE_32K_DOMAIN_32KHZ_IN_PIN); -} -#endif - -void system_hibernate(uint32_t seconds, uint32_t microseconds) -{ - int i; - - if (IS_ENABLED(CONFIG_HOSTCMD_PD)) { - /* Inform the PD MCU that we are going to hibernate. */ - host_command_pd_request_hibernate(); - /* Wait to ensure exchange with PD before hibernating. */ - msleep(100); - } - - cflush(); - - if (board_hibernate) - board_hibernate(); - - /* Disable interrupts */ - interrupt_disable(); - for (i = 0; i < MCHP_IRQ_MAX; ++i) { - task_disable_irq(i); - task_clear_pending_irq(i); - } - - for (i = MCHP_INT_GIRQ_FIRST; i <= MCHP_INT_GIRQ_LAST; ++i) { - MCHP_INT_DISABLE(i) = 0xffffffff; - MCHP_INT_SOURCE(i) = 0xffffffff; - } - - /* Disable UART */ - MCHP_UART_ACT(0) &= ~0x1; - - disable_host_ifc_clocks(); - - /* Disable JTAG */ - MCHP_EC_JTAG_EN &= ~1; - - /* Stop watchdog */ - MCHP_WDG_CTL &= ~(MCHP_WDT_CTL_ENABLE); - - /* Stop timers */ - MCHP_TMR32_CTL(0) &= ~1; - MCHP_TMR32_CTL(1) &= ~1; - for (i = 0; i < MCHP_TMR16_INSTANCES; i++) - MCHP_TMR16_CTL(i) &= ~1; - - /* Power down ADC */ - /* - * If ADC is in middle of acquisition it will continue until finished - */ - MCHP_ADC_CTRL &= ~1; - - /* Disable blocks */ - MCHP_PCR_SLOW_CLK_CTL &= ~(MCHP_PCR_SLOW_CLK_CTL_MASK); - - /* Setup GPIOs for hibernate */ - if (board_hibernate_late) - board_hibernate_late(); - - if (hibernate_wake_pins_used > 0) { - for (i = 0; i < hibernate_wake_pins_used; ++i) { - const enum gpio_signal pin = hibernate_wake_pins[i]; - - gpio_reset(pin); - gpio_enable_interrupt(pin); - } - - interrupt_enable(); - task_enable_irq(MCHP_IRQ_GIRQ8); - task_enable_irq(MCHP_IRQ_GIRQ9); - task_enable_irq(MCHP_IRQ_GIRQ10); - task_enable_irq(MCHP_IRQ_GIRQ11); - task_enable_irq(MCHP_IRQ_GIRQ12); - task_enable_irq(MCHP_IRQ_GIRQ26); - } - - if (seconds || microseconds) { - htimer_init(); - system_set_htimer_alarm(seconds, microseconds); - interrupt_enable(); - } else - switch_32k_pin2sil(); - - /* - * Set sleep state - * arm sleep state to trigger on next WFI - */ - CPU_SCB_SYSCTRL |= 0x4; - MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_HEAVY; - MCHP_PCR_SYS_SLP_CTL = MCHP_PCR_SYS_SLP_ALL; - - asm("dsb"); - asm("wfi"); - asm("isb"); - asm("nop"); - - /* Use fastest clock to speed through wake-up */ - MCHP_PCR_PROC_CLK_CTL = MCHP_PCR_CLK_CTL_FASTEST; - - /* Reboot */ - _system_reset(0, 1); - - /* We should never get here. */ - while (1) - ; -} - -void htimer_interrupt(void) -{ - /* Time to wake up */ -} -DECLARE_IRQ(MCHP_IRQ_HTIMER0, htimer_interrupt, 1); - -enum ec_image system_get_shrspi_image_copy(void) -{ - return MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX); -} - -uint32_t system_get_lfw_address(void) -{ - uint32_t * const lfw_vector = - (uint32_t * const)CONFIG_PROGRAM_MEMORY_BASE; - - return *(lfw_vector + 1); -} - -void system_set_image_copy(enum ec_image copy) -{ - MCHP_VBAT_RAM(MCHP_IMAGETYPE_IDX) = (copy == EC_IMAGE_RW) ? - EC_IMAGE_RW : EC_IMAGE_RO; -} - |