summaryrefslogtreecommitdiff
path: root/chip/mchp/system.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/mchp/system.c')
-rw-r--r--chip/mchp/system.c591
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;
-}
-