mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
it83xx: add espi module
Add espi control module for it83xx. Signed-off-by: Dino Li <dino.li@ite.com.tw> BRANCH=none BUG=none TEST=1. it8390+Intel SKL-Y RVP3 and boot to shell. 2. console command "kbpress 1 4" to test keyboard data. (board code for espi module test on CL:392587) Change-Id: I1b32bd16f7e01abf07b9c9a68ebef2399cc9828d Reviewed-on: https://chromium-review.googlesource.com/394471 Commit-Ready: Dino Li <Dino.Li@ite.com.tw> Tested-by: Dino Li <Dino.Li@ite.com.tw> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
387
chip/it83xx/espi.c
Normal file
387
chip/it83xx/espi.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user