diff options
-rw-r--r-- | board/it83xx_evb/gpio.inc | 2 | ||||
-rw-r--r-- | board/reef_it8320/gpio.inc | 2 | ||||
-rw-r--r-- | chip/it83xx/build.mk | 1 | ||||
-rw-r--r-- | chip/it83xx/espi.c | 387 | ||||
-rw-r--r-- | chip/it83xx/intc.c | 9 | ||||
-rw-r--r-- | chip/it83xx/intc.h | 3 | ||||
-rw-r--r-- | chip/it83xx/lpc.c | 25 | ||||
-rw-r--r-- | chip/it83xx/registers.h | 70 | ||||
-rw-r--r-- | chip/it83xx/uart.c | 6 | ||||
-rw-r--r-- | core/nds32/init.S | 8 | ||||
-rw-r--r-- | include/espi.h | 3 |
11 files changed, 514 insertions, 2 deletions
diff --git a/board/it83xx_evb/gpio.inc b/board/it83xx_evb/gpio.inc index b14cfc8287..96d362e4bd 100644 --- a/board/it83xx_evb/gpio.inc +++ b/board/it83xx_evb/gpio.inc @@ -9,7 +9,9 @@ * Note: Those with interrupt handlers must be declared first. */ GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH | GPIO_PULL_UP, power_button_interrupt) +#ifndef CONFIG_ESPI_VW_SIGNALS GPIO_INT(PCH_PLTRST_L, PIN(E, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lpcrst_interrupt) +#endif GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH | GPIO_PULL_DOWN, lid_interrupt) GPIO_INT(WP_L, PIN(E, 1), GPIO_INT_BOTH, switch_interrupt) /* Write protect input */ #ifdef CONFIG_LOW_POWER_IDLE diff --git a/board/reef_it8320/gpio.inc b/board/reef_it8320/gpio.inc index 5a09785e0d..24b1b7a6ca 100644 --- a/board/reef_it8320/gpio.inc +++ b/board/reef_it8320/gpio.inc @@ -20,7 +20,9 @@ GPIO_INT(PCH_SLP_S0_L, PIN(B, 7), GPIO_INT_BOTH, power_signal_interrupt) /* #endif GPIO_INT(SUSPWRNACK, PIN(E, 1), GPIO_INT_BOTH, power_signal_interrupt) /* SUSPWRNACK */ GPIO_INT(LID_OPEN, PIN(E, 2), GPIO_INT_BOTH, lid_interrupt) /* LID_OPEN */ +#ifndef CONFIG_ESPI_VW_SIGNALS GPIO_INT(PCH_PLTRST_L, PIN(E, 3), GPIO_INT_BOTH | GPIO_PULL_UP, lpcrst_interrupt) /* PLT_RST_L */ +#endif GPIO_INT(POWER_BUTTON_L, PIN(E, 4), GPIO_INT_BOTH, power_button_interrupt) /* MECH_PWR_BTN_ODL */ GPIO_INT(ALL_SYS_PGOOD, PIN(F, 0), GPIO_INT_BOTH, power_signal_interrupt) /* PMIC_EC_PWROK_OD */ GPIO_INT(RSMRST_L_PGOOD, PIN(F, 1), GPIO_INT_BOTH, power_signal_interrupt) /* PMIC_EC_RSMRST_ODL */ diff --git a/chip/it83xx/build.mk b/chip/it83xx/build.mk index 2179b8c17e..cff3cea031 100644 --- a/chip/it83xx/build.mk +++ b/chip/it83xx/build.mk @@ -21,6 +21,7 @@ chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_ADC)+=adc.o chip-$(CONFIG_EC2I)+=ec2i.o chip-$(CONFIG_LPC)+=lpc.o +chip-$(CONFIG_ESPI)+=espi.o chip-$(CONFIG_SPI)+=spi.o chip-$(CONFIG_PECI)+=peci.o chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o diff --git a/chip/it83xx/espi.c b/chip/it83xx/espi.c new file mode 100644 index 0000000000..9d105d4af8 --- /dev/null +++ b/chip/it83xx/espi.c @@ -0,0 +1,387 @@ +/* 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. + */ + +/* ESPI module for Chrome EC */ + +#include "console.h" +#include "espi.h" +#include "hooks.h" +#include "port80.h" +#include "power.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "uart.h" +#include "util.h" + +#define CHIP_ESPI_VW_INTERRUPT_NUM 8 + +/* Console output macros */ +#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) + +struct vw_channel_t { + uint8_t index; /* VW index of signal */ + uint8_t level_mask; /* level bit of signal */ + uint8_t valid_mask; /* valid bit of signal */ +}; + +/* VW settings at initialization */ +static const struct vw_channel_t vw_init_setting[] = { + {ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(0), + VW_VALID_FIELD(VW_IDX_4_OOB_RST_ACK)}, + {ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_LEVEL_FIELD(VW_IDX_5_BTLD_STATUS_DONE), + VW_VALID_FIELD(VW_IDX_5_BTLD_STATUS_DONE)}, + {ESPI_SYSTEM_EVENT_VW_IDX_40, + VW_LEVEL_FIELD(0), + VW_VALID_FIELD(VW_IDX_40_SUS_ACK)}, +}; + +/* VW settings at host startup */ +static const struct vw_channel_t vw_host_startup_setting[] = { + {ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | + VW_IDX_6_RCIN | VW_IDX_6_HOST_RST_ACK), + VW_VALID_FIELD(VW_IDX_6_SCI | VW_IDX_6_SMI | + VW_IDX_6_RCIN | VW_IDX_6_HOST_RST_ACK)}, +}; + +#define VW_CHAN(name, idx, level, valid) \ + [(name - VW_SIGNAL_BASE)] = {idx, level, valid} + +/* VW signals used in eSPI (NOTE: must match order of enum espi_vw_signal). */ +static const struct vw_channel_t vw_channel_list[] = { + /* index 02h: master to slave. */ + VW_CHAN(VW_SLP_S3_L, + ESPI_SYSTEM_EVENT_VW_IDX_2, + VW_LEVEL_FIELD(VW_IDX_2_SLP_S3), + VW_VALID_FIELD(VW_IDX_2_SLP_S3)), + VW_CHAN(VW_SLP_S4_L, + ESPI_SYSTEM_EVENT_VW_IDX_2, + VW_LEVEL_FIELD(VW_IDX_2_SLP_S4), + VW_VALID_FIELD(VW_IDX_2_SLP_S4)), + VW_CHAN(VW_SLP_S5_L, + ESPI_SYSTEM_EVENT_VW_IDX_2, + VW_LEVEL_FIELD(VW_IDX_2_SLP_S5), + VW_VALID_FIELD(VW_IDX_2_SLP_S5)), + /* index 03h: master to slave. */ + VW_CHAN(VW_SUS_STAT_L, + ESPI_SYSTEM_EVENT_VW_IDX_3, + VW_LEVEL_FIELD(VW_IDX_3_SUS_STAT), + VW_VALID_FIELD(VW_IDX_3_SUS_STAT)), + VW_CHAN(VW_PLTRST_L, + ESPI_SYSTEM_EVENT_VW_IDX_3, + VW_LEVEL_FIELD(VW_IDX_3_PLTRST), + VW_VALID_FIELD(VW_IDX_3_PLTRST)), + VW_CHAN(VW_OOB_RST_WARN, + ESPI_SYSTEM_EVENT_VW_IDX_3, + VW_LEVEL_FIELD(VW_IDX_3_OOB_RST_WARN), + VW_VALID_FIELD(VW_IDX_3_OOB_RST_WARN)), + /* index 04h: slave to master. */ + VW_CHAN(VW_OOB_RST_ACK, + ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(VW_IDX_4_OOB_RST_ACK), + VW_VALID_FIELD(VW_IDX_4_OOB_RST_ACK)), + VW_CHAN(VW_WAKE_L, + ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(VW_IDX_4_WAKE), + VW_VALID_FIELD(VW_IDX_4_WAKE)), + VW_CHAN(VW_PME_L, + ESPI_SYSTEM_EVENT_VW_IDX_4, + VW_LEVEL_FIELD(VW_IDX_4_PME), + VW_VALID_FIELD(VW_IDX_4_PME)), + /* index 05h: slave to master. */ + VW_CHAN(VW_ERROR_FATAL, + ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_LEVEL_FIELD(VW_IDX_5_FATAL), + VW_VALID_FIELD(VW_IDX_5_FATAL)), + VW_CHAN(VW_ERROR_NON_FATAL, + ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_LEVEL_FIELD(VW_IDX_5_NON_FATAL), + VW_VALID_FIELD(VW_IDX_5_NON_FATAL)), + VW_CHAN(VW_SLAVE_BTLD_STATUS_DONE, + ESPI_SYSTEM_EVENT_VW_IDX_5, + VW_LEVEL_FIELD(VW_IDX_5_BTLD_STATUS_DONE), + VW_VALID_FIELD(VW_IDX_5_BTLD_STATUS_DONE)), + /* index 06h: slave to master. */ + VW_CHAN(VW_SCI_L, + ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SCI), + VW_VALID_FIELD(VW_IDX_6_SCI)), + VW_CHAN(VW_SMI_L, + ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_SMI), + VW_VALID_FIELD(VW_IDX_6_SMI)), + VW_CHAN(VW_RCIN_L, + ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_RCIN), + VW_VALID_FIELD(VW_IDX_6_RCIN)), + VW_CHAN(VW_HOST_RST_ACK, + ESPI_SYSTEM_EVENT_VW_IDX_6, + VW_LEVEL_FIELD(VW_IDX_6_HOST_RST_ACK), + VW_VALID_FIELD(VW_IDX_6_HOST_RST_ACK)), + /* index 07h: master to slave. */ + VW_CHAN(VW_HOST_RST_WARN, + ESPI_SYSTEM_EVENT_VW_IDX_7, + VW_LEVEL_FIELD(VW_IDX_7_HOST_RST_WARN), + VW_VALID_FIELD(VW_IDX_7_HOST_RST_WARN)), + /* index 40h: slave to master. */ + VW_CHAN(VW_SUS_ACK, + ESPI_SYSTEM_EVENT_VW_IDX_40, + VW_LEVEL_FIELD(VW_IDX_40_SUS_ACK), + VW_VALID_FIELD(VW_IDX_40_SUS_ACK)), + /* index 41h: master to slave. */ + VW_CHAN(VW_SUS_WARN_L, + ESPI_SYSTEM_EVENT_VW_IDX_41, + VW_LEVEL_FIELD(VW_IDX_41_SUS_WARN), + VW_VALID_FIELD(VW_IDX_41_SUS_WARN)), + VW_CHAN(VW_SUS_PWRDN_ACK_L, + ESPI_SYSTEM_EVENT_VW_IDX_41, + VW_LEVEL_FIELD(VW_IDX_41_SUS_PWRDN_ACK), + VW_VALID_FIELD(VW_IDX_41_SUS_PWRDN_ACK)), + VW_CHAN(VW_SLP_A_L, + ESPI_SYSTEM_EVENT_VW_IDX_41, + VW_LEVEL_FIELD(VW_IDX_41_SLP_A), + VW_VALID_FIELD(VW_IDX_41_SLP_A)), + /* index 42h: master to slave. */ + VW_CHAN(VW_SLP_LAN, + ESPI_SYSTEM_EVENT_VW_IDX_42, + VW_LEVEL_FIELD(VW_IDX_42_SLP_LAN), + VW_VALID_FIELD(VW_IDX_42_SLP_LAN)), + VW_CHAN(VW_SLP_WLAN, + ESPI_SYSTEM_EVENT_VW_IDX_42, + VW_LEVEL_FIELD(VW_IDX_42_SLP_WLAN), + VW_VALID_FIELD(VW_IDX_42_SLP_WLAN)), +}; +BUILD_ASSERT(ARRAY_SIZE(vw_channel_list) == + (VW_SIGNAL_BASE_END - VW_SIGNAL_BASE)); + +/* Get vw index & value information by signal */ +static int espi_vw_get_signal_index(enum espi_vw_signal event) +{ + uint32_t i = event - VW_SIGNAL_BASE; + + return (i < ARRAY_SIZE(vw_channel_list)) ? i : -1; +} + +/** + * Set eSPI Virtual-Wire signal to Host + * + * @param signal vw signal needs to set + * @param level level of vw signal + * @return EC_SUCCESS, or non-zero if error. + */ +int espi_vw_set_wire(enum espi_vw_signal signal, uint8_t level) +{ + /* Get index of vw signal list by signale name */ + int i = espi_vw_get_signal_index(signal); + + if (i < 0) + return EC_ERROR_PARAM1; + + /* critical section with interrupts off */ + interrupt_disable(); + if (level) + IT83XX_ESPI_VWIDX(vw_channel_list[i].index) |= + vw_channel_list[i].level_mask; + else + IT83XX_ESPI_VWIDX(vw_channel_list[i].index) &= + ~vw_channel_list[i].level_mask; + /* restore interrupts */ + interrupt_enable(); + + return EC_SUCCESS; +} + +/** + * Get eSPI Virtual-Wire signal from host + * + * @param signal vw signal needs to get + * @return 1: set by host, otherwise: no signal + */ +int espi_vw_get_wire(enum espi_vw_signal signal) +{ + /* Get index of vw signal list by signale name */ + int i = espi_vw_get_signal_index(signal); + + if (i < 0) + return 0; + + /* Not valid */ + if (!(IT83XX_ESPI_VWIDX(vw_channel_list[i].index) & + vw_channel_list[i].valid_mask)) + return 0; + + return !!(IT83XX_ESPI_VWIDX(vw_channel_list[i].index) & + vw_channel_list[i].level_mask); +} + +/** + * Enable VW interrupt of power sequence signal + * + * @param signal vw signal needs to enable interrupt + * @return EC_SUCCESS, or non-zero if error. + */ +int espi_vw_enable_wire_int(enum espi_vw_signal signal) +{ + /* + * Common code calls this function to enable VW interrupt of power + * sequence signal. + * IT83xx only use a bit (bit7@IT83XX_ESPI_VWCTRL0) to enable VW + * interrupt. + * VW interrupt will be triggerd with any updated VW index flag + * if this control bit is set. + * So we will always return success here. + */ + return EC_SUCCESS; +} + +/** + * Disable VW interrupt of power sequence signal + * + * @param signal vw signal needs to disable interrupt + * @return EC_SUCCESS, or non-zero if error. + */ +int espi_vw_disable_wire_int(enum espi_vw_signal signal) +{ + /* + * We can't disable VW interrupt of power sequence signal + * individually. + */ + return EC_ERROR_UNIMPLEMENTED; +} + +static void espi_vw_host_startup(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(vw_host_startup_setting); i++) + IT83XX_ESPI_VWIDX(vw_host_startup_setting[i].index) = + (vw_host_startup_setting[i].level_mask | + vw_host_startup_setting[i].valid_mask); +} + +static void espi_vw_no_isr(uint8_t flag_changed) +{ +} + +static void espi_vw_idx41_isr(uint8_t flag_changed) +{ + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_41_SUS_WARN)) + espi_vw_set_wire(VW_SUS_ACK, espi_vw_get_wire(VW_SUS_WARN_L)); +} + +static void espi_vw_idx7_isr(uint8_t flag_changed) +{ + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_7_HOST_RST_WARN)) + espi_vw_set_wire(VW_HOST_RST_ACK, + espi_vw_get_wire(VW_HOST_RST_WARN)); +} + +static void espi_vw_idx3_isr(uint8_t flag_changed) +{ + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_3_PLTRST)) { + int pltrst = espi_vw_get_wire(VW_PLTRST_L); + + if (pltrst) + espi_vw_host_startup(); + else + /* Store port 80 reset event */ + port_80_write(PORT_80_EVENT_RESET); + + CPRINTS("PLTRST_L %sasserted", pltrst ? "de" : ""); + } + + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_3_OOB_RST_WARN)) + espi_vw_set_wire(VW_OOB_RST_ACK, + espi_vw_get_wire(VW_OOB_RST_WARN)); +} + +static void espi_vw_idx2_isr(uint8_t flag_changed) +{ + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_2_SLP_S3)) + power_signal_interrupt(VW_SLP_S3_L); + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_2_SLP_S4)) + power_signal_interrupt(VW_SLP_S4_L); + if (flag_changed & VW_LEVEL_FIELD(VW_IDX_2_SLP_S5)) + power_signal_interrupt(VW_SLP_S5_L); +} + +struct vw_interrupt_t { + void (*vw_isr)(uint8_t flag_changed); + uint8_t vw_index; +}; + +static const struct vw_interrupt_t vw_isr_list[CHIP_ESPI_VW_INTERRUPT_NUM] = { + {espi_vw_idx2_isr, ESPI_SYSTEM_EVENT_VW_IDX_2}, + {espi_vw_idx3_isr, ESPI_SYSTEM_EVENT_VW_IDX_3}, + {espi_vw_idx7_isr, ESPI_SYSTEM_EVENT_VW_IDX_7}, + {espi_vw_idx41_isr, ESPI_SYSTEM_EVENT_VW_IDX_41}, + {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_42}, + {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_43}, + {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_44}, + {espi_vw_no_isr, ESPI_SYSTEM_EVENT_VW_IDX_47}, +}; + +/* + * This is used to record the previous VW valid / level field state to discover + * changes. Then do following sequence only when state is changed. + */ +static uint8_t vw_index_flag[CHIP_ESPI_VW_INTERRUPT_NUM]; + +void espi_vw_interrupt(void) +{ + int i; + uint8_t vwidx_updated = IT83XX_ESPI_VWCTRL1; + + /* + * TODO(b:68918637): write-1 clear bug. + * for now, we have to write 0xff to clear pending bit. + */ +#if 0 + IT83XX_ESPI_VWCTRL1 = vwidx_updated; +#else + IT83XX_ESPI_VWCTRL1 = 0xff; +#endif + task_clear_pending_irq(IT83XX_IRQ_ESPI_VW); + + for (i = 0; i < CHIP_ESPI_VW_INTERRUPT_NUM; i++) { + if (vwidx_updated & (1 << i)) { + uint8_t idx_flag; + + idx_flag = IT83XX_ESPI_VWIDX(vw_isr_list[i].vw_index); + vw_isr_list[i].vw_isr(vw_index_flag[i] ^ idx_flag); + vw_index_flag[i] = idx_flag; + } + } +} + +void espi_interrupt(void) +{ +} + +void espi_init(void) +{ + int i; + + /* TODO: PLL change won't success if eSPI chip select is low. */ +#if (PLL_CLOCK != 48000000) +#error "Not support PLL change if eSPI module is enabled. " +#endif + + for (i = 0; i < ARRAY_SIZE(vw_init_setting); i++) + IT83XX_ESPI_VWIDX(vw_init_setting[i].index) = + (vw_init_setting[i].level_mask | + vw_init_setting[i].valid_mask); + + for (i = 0; i < CHIP_ESPI_VW_INTERRUPT_NUM; i++) + vw_index_flag[i] = IT83XX_ESPI_VWIDX(vw_isr_list[i].vw_index); + + task_clear_pending_irq(IT83XX_IRQ_ESPI_VW); + /* bit7: VW interrupt enable */ + IT83XX_ESPI_VWCTRL0 |= (1 << 7); + task_enable_irq(IT83XX_IRQ_ESPI_VW); +} diff --git a/chip/it83xx/intc.c b/chip/it83xx/intc.c index cd4e147d01..a2fd06dea4 100644 --- a/chip/it83xx/intc.c +++ b/chip/it83xx/intc.c @@ -106,6 +106,15 @@ void intc_cpu_int_group_12(void) peci_interrupt(); break; #endif +#ifdef CONFIG_ESPI + case IT83XX_IRQ_ESPI: + espi_interrupt(); + break; + + case IT83XX_IRQ_ESPI_VW: + espi_vw_interrupt(); + break; +#endif #ifdef CONFIG_USB_PD_TCPM_ITE83XX case IT83XX_IRQ_USBPD0: chip_pd_irq(USBPD_PORT_A); diff --git a/chip/it83xx/intc.h b/chip/it83xx/intc.h index 8c6d35aa02..508b7e0f3b 100644 --- a/chip/it83xx/intc.h +++ b/chip/it83xx/intc.h @@ -23,5 +23,8 @@ void i2c_interrupt(int port); void clock_sleep_mode_wakeup_isr(void); int clock_ec_wake_from_sleep(void); void __enter_hibernate(uint32_t seconds, uint32_t microseconds); +void espi_interrupt(void); +void espi_vw_interrupt(void); +void espi_init(void); #endif /* __CROS_EC_INTC_H */ diff --git a/chip/it83xx/lpc.c b/chip/it83xx/lpc.c index e1ce1be832..ed83a85c01 100644 --- a/chip/it83xx/lpc.c +++ b/chip/it83xx/lpc.c @@ -11,9 +11,11 @@ #include "common.h" #include "console.h" #include "ec2i_chip.h" +#include "espi.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" +#include "intc.h" #include "irq_chip.h" #include "keyboard_protocol.h" #include "lpc.h" @@ -363,10 +365,12 @@ void lpc_clear_acpi_status_mask(uint8_t mask) pm_set_status(LPC_ACPI_CMD, mask, 0); } +#ifndef CONFIG_ESPI_VW_SIGNALS int lpc_get_pltrst_asserted(void) { return !gpio_get_level(GPIO_PCH_PLTRST_L); } +#endif /* KBC and PMC control modules */ void lpc_kbc_ibf_interrupt(void) @@ -663,7 +667,9 @@ static void lpc_init(void) */ IT83XX_GCTRL_SPCTRL1 |= 0xC2; +#ifndef CONFIG_ESPI_VW_SIGNALS gpio_enable_interrupt(GPIO_PCH_PLTRST_L); +#endif task_clear_pending_irq(IT83XX_IRQ_KBC_OUT); task_disable_irq(IT83XX_IRQ_KBC_OUT); @@ -682,6 +688,9 @@ static void lpc_init(void) task_clear_pending_irq(IT83XX_IRQ_PMC3_IN); task_enable_irq(IT83XX_IRQ_PMC3_IN); +#ifdef CONFIG_ESPI + espi_init(); +#endif /* Sufficiently initialized */ init_done = 1; @@ -694,6 +703,21 @@ static void lpc_init(void) */ DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_INIT_LPC); +void lpc_host_reset(void) +{ + /* Host Reset Control will assert RCIN# */ +#ifdef CONFIG_ESPI_VW_SIGNALS + espi_vw_set_wire(VW_RCIN_L, 0); + udelay(10); + espi_vw_set_wire(VW_RCIN_L, 1); +#else + gpio_set_level(GPIO_PCH_RCIN_L, 0); + udelay(10); + gpio_set_level(GPIO_PCH_RCIN_L, 1); +#endif +} + +#ifndef CONFIG_ESPI_VW_SIGNALS void lpcrst_interrupt(enum gpio_signal signal) { if (lpc_get_pltrst_asserted()) @@ -703,6 +727,7 @@ void lpcrst_interrupt(enum gpio_signal signal) CPRINTS("LPC RESET# %sasserted", lpc_get_pltrst_asserted() ? "" : "de"); } +#endif /* Enable LPC ACPI-EC interrupts */ void lpc_enable_acpi_interrupts(void) diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h index 21d8e7fc1a..93417e08b9 100644 --- a/chip/it83xx/registers.h +++ b/chip/it83xx/registers.h @@ -761,6 +761,7 @@ enum clock_gate_offsets { #define IT83XX_GCTRL_RSTS REG8(IT83XX_GCTRL_BASE+0x06) #define IT83XX_GCTRL_BADRSEL REG8(IT83XX_GCTRL_BASE+0x0A) #define IT83XX_GCTRL_SPCTRL1 REG8(IT83XX_GCTRL_BASE+0x0D) +#define IT83XX_GCTRL_RSTDMMC REG8(IT83XX_GCTRL_BASE+0x10) #define IT83XX_GCTRL_RSTC4 REG8(IT83XX_GCTRL_BASE+0x11) #define IT83XX_GCTRL_SPCTRL4 REG8(IT83XX_GCTRL_BASE+0x1C) #define IT83XX_GCTRL_MCCR REG8(IT83XX_GCTRL_BASE+0x30) @@ -1203,6 +1204,75 @@ enum usbpd_port { #define USB_VID_ITE 0x048d +#define IT83XX_ESPI_BASE 0x00F03100 + +/* eSPI VW */ +#define IT83XX_ESPI_VW_BASE 0x00F03200 +#define IT83XX_ESPI_VWIDX(i) REG8(IT83XX_ESPI_VW_BASE+(i)) + +#define VW_LEVEL_FIELD(f) ((f) << 0) +#define VW_VALID_FIELD(f) ((f) << 4) + +#define ESPI_SYSTEM_EVENT_VW_IDX_2 0x2 +#define VW_IDX_2_SLP_S3 (1 << 0) +#define VW_IDX_2_SLP_S4 (1 << 1) +#define VW_IDX_2_SLP_S5 (1 << 2) + +#define ESPI_SYSTEM_EVENT_VW_IDX_3 0x3 +#define VW_IDX_3_SUS_STAT (1 << 0) +#define VW_IDX_3_PLTRST (1 << 1) +#define VW_IDX_3_OOB_RST_WARN (1 << 2) + +#define ESPI_SYSTEM_EVENT_VW_IDX_4 0x4 +#define VW_IDX_4_OOB_RST_ACK (1 << 0) +#define VW_IDX_4_WAKE (1 << 2) +#define VW_IDX_4_PME (1 << 3) + +#define ESPI_SYSTEM_EVENT_VW_IDX_5 0x5 +#define VW_IDX_5_SLAVE_BTLD_DONE (1 << 0) +#define VW_IDX_5_FATAL (1 << 1) +#define VW_IDX_5_NON_FATAL (1 << 2) +#define VW_IDX_5_SLAVE_BTLD_STATUS (1 << 3) +#define VW_IDX_5_BTLD_STATUS_DONE (VW_IDX_5_SLAVE_BTLD_DONE | \ + VW_IDX_5_SLAVE_BTLD_STATUS) + +#define ESPI_SYSTEM_EVENT_VW_IDX_6 0x6 +#define VW_IDX_6_SCI (1 << 0) +#define VW_IDX_6_SMI (1 << 1) +#define VW_IDX_6_RCIN (1 << 2) +#define VW_IDX_6_HOST_RST_ACK (1 << 3) + +#define ESPI_SYSTEM_EVENT_VW_IDX_7 0x7 +#define VW_IDX_7_HOST_RST_WARN (1 << 0) + +#define ESPI_SYSTEM_EVENT_VW_IDX_40 0x40 +#define VW_IDX_40_SUS_ACK (1 << 0) + +#define ESPI_SYSTEM_EVENT_VW_IDX_41 0x41 +#define VW_IDX_41_SUS_WARN (1 << 0) +#define VW_IDX_41_SUS_PWRDN_ACK (1 << 1) +#define VW_IDX_41_SLP_A (1 << 3) + +#define ESPI_SYSTEM_EVENT_VW_IDX_42 0x42 +#define VW_IDX_42_SLP_LAN (1 << 0) +#define VW_IDX_42_SLP_WLAN (1 << 1) + +#define ESPI_SYSTEM_EVENT_VW_IDX_43 0x43 +#define ESPI_SYSTEM_EVENT_VW_IDX_44 0x44 +#define ESPI_SYSTEM_EVENT_VW_IDX_47 0x47 + +#define IT83XX_ESPI_VWCTRL0 REG8(IT83XX_ESPI_VW_BASE+0x90) +#define IT83XX_ESPI_VWCTRL1 REG8(IT83XX_ESPI_VW_BASE+0x91) +#define IT83XX_ESPI_VWCTRL2 REG8(IT83XX_ESPI_VW_BASE+0x92) +#define IT83XX_ESPI_VWCTRL3 REG8(IT83XX_ESPI_VW_BASE+0x93) + +/* eSPI Queue 0 */ +#define IT83XX_ESPI_QUEUE_BASE 0x00F03300 +/* PUT_PC data byte 0 - 63 */ +#define IT83XX_ESPI_QUEUE_PUT_PC(i) REG8(IT83XX_ESPI_QUEUE_BASE+(i)) +/* PUT_OOB data byte 0 - 79 */ +#define IT83XX_ESPI_QUEUE_PUT_OOB(i) REG8(IT83XX_ESPI_QUEUE_BASE+0x80+(i)) + /* Wake pin definitions, defined at board-level */ extern const enum gpio_signal hibernate_wake_pins[]; extern const int hibernate_wake_pins_used; diff --git a/chip/it83xx/uart.c b/chip/it83xx/uart.c index 91624d4930..24dc2ec4c6 100644 --- a/chip/it83xx/uart.c +++ b/chip/it83xx/uart.c @@ -205,6 +205,12 @@ void uart_deepsleep_interrupt(enum gpio_signal signal) void uart_init(void) { + /* + * bit3: uart1 belongs to the EC side. + * This is necessary for enabling eSPI module. + */ + IT83XX_GCTRL_RSTDMMC |= (1 << 3); + /* reset uart before config it */ IT83XX_GCTRL_RSTC4 |= (1 << 1); diff --git a/core/nds32/init.S b/core/nds32/init.S index d278d4a899..2ee7815908 100644 --- a/core/nds32/init.S +++ b/core/nds32/init.S @@ -84,7 +84,13 @@ vector irq_15, 15 /* HW 15 */ .balign 16 .global eflash_sig eflash_sig: -.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xB4 +.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 +#ifdef CONFIG_ESPI +.byte 0xA4 /* eSPI */ +#else +.byte 0xA5 /* LPC */ +#endif +.byte 0xB4 /* flag of signature */ .byte 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0xAA, 0x55, 0x55 /* flags: internal oscillator + implicit location */ diff --git a/include/espi.h b/include/espi.h index 72def9b536..d96f79c9c8 100644 --- a/include/espi.h +++ b/include/espi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 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. */ @@ -37,6 +37,7 @@ enum espi_vw_signal { VW_SLP_A_L, VW_SLP_LAN, /* index 42h (In) */ VW_SLP_WLAN, + VW_SIGNAL_BASE_END, }; /** |