mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
npcx: Add espi driver of npcx5mng for x86-based platform.
Add espi driver for x86-based platform which support espi interface such
as skylake and so on.
Added source:
1. espi.c: Add drivers which supports the utilities of peripheral and
virtual-wire channels so far.
2. espi.h: Add espi virtual-wire declaration for power sequence FW.
Modified sources:
1. lpc.c: Add interrupts and initialization steps for espi.
2. gpio.c: Add interrupt handler of espi reset.
BRANCH=none
BUG=chrome-os-partner:34346
TEST=make buildall -j; test nuvoton IC specific drivers
Change-Id: Ie80afe79d85aba47fc0b72898a8374c2898ec114
Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
Reviewed-on: https://chromium-review.googlesource.com/366181
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
@@ -20,6 +20,7 @@ chip-$(CONFIG_FANS)+=fan.o
|
||||
chip-$(CONFIG_FLASH)+=flash.o
|
||||
chip-$(CONFIG_I2C)+=i2c.o
|
||||
chip-$(CONFIG_LPC)+=lpc.o
|
||||
chip-$(CONFIG_ESPI)+=espi.o
|
||||
chip-$(CONFIG_PECI)+=peci.o
|
||||
chip-$(CONFIG_HOSTCMD_SPS)+=shi.o
|
||||
# pwm functions are implemented with the fan functions
|
||||
|
||||
656
chip/npcx/espi.c
Normal file
656
chip/npcx/espi.c
Normal file
@@ -0,0 +1,656 @@
|
||||
/* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/* ESPI module for Chrome EC */
|
||||
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "console.h"
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
#include "power.h"
|
||||
#include "espi.h"
|
||||
#include "lpc_chip.h"
|
||||
|
||||
/* Console output macros */
|
||||
#if !(DEBUG_ESPI)
|
||||
#define CPUTS(...)
|
||||
#define CPRINTS(...)
|
||||
#else
|
||||
#define CPUTS(outstr) cputs(CC_LPC, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args)
|
||||
#endif
|
||||
|
||||
/* Default eSPI configuration for VW events */
|
||||
struct vwevms_config_t {
|
||||
uint8_t idx; /* VW index */
|
||||
uint8_t idx_en; /* Index enable */
|
||||
uint8_t pltrst_en; /* Enable reset by PLTRST assert */
|
||||
uint8_t espirst_en; /* Enable reset by eSPI_RST assert */
|
||||
uint8_t int_en; /* Interrupt/Wake-up enable */
|
||||
};
|
||||
|
||||
struct vwevsm_config_t {
|
||||
uint8_t idx; /* VW index */
|
||||
uint8_t idx_en; /* Index enable */
|
||||
uint8_t pltrst_en; /* Enable reset by PLTRST assert */
|
||||
uint8_t cdrst_en; /* Enable cold reset */
|
||||
uint8_t valid; /* Valid VW mask */
|
||||
};
|
||||
|
||||
/* Default MIWU configurations for VW events */
|
||||
struct host_wui_item {
|
||||
uint16_t table : 2; /* MIWU table 0-2 */
|
||||
uint16_t group : 3; /* MIWU group 0-7 */
|
||||
uint16_t num : 3; /* MIWU bit 0-7 */
|
||||
uint16_t edge : 4; /* MIWU edge trigger type rising/falling/any */
|
||||
};
|
||||
|
||||
/* Mapping item between VW signal, index and value */
|
||||
struct vw_event_t {
|
||||
uint16_t name; /* Name of signal */
|
||||
uint8_t evt_idx; /* VW index of signal */
|
||||
uint8_t evt_val; /* VW value of signal */
|
||||
};
|
||||
|
||||
/* Default settings of VWEVMS registers (Please refer Table.43/44) */
|
||||
static const struct vwevms_config_t espi_in_list[] = {
|
||||
/*IDX EN ENPL ENESP IE VW Event Bit 3 -0 (M->S) */
|
||||
{0x02, 1, 0, 0, 0}, /* SLP_S3#, SLP_S4#, SLP_S5, Reserve */
|
||||
{0x03, 1, 0, 1, 0}, /* SUS_STAT#, PLTRST#, ORST_WARN, Reserve */
|
||||
{0x07, 1, 1, 1, 0}, /* HRST_WARN, SMIOUT#, NMIOUT#, Reserve */
|
||||
{0x41, 1, 0, 1, 0}, /* SUS_WARN#, SPWRDN_ACK, Reserve, SLP_A# */
|
||||
{0x42, 1, 0, 0, 0}, /* SLP_LAN#, SLP_WAN#, Reserve, Reserve */
|
||||
{0x47, 1, 1, 1, 0}, /* HOST_C10, Reserve, Reserve, Reserve */
|
||||
};
|
||||
|
||||
/* Default settings of VWEVSM registers (Please refer Table.43/44) */
|
||||
static const struct vwevsm_config_t espi_out_list[] = {
|
||||
/*IDX EN ENPL ENCDR VDMASK VW Event Bit 3 -0 (S->M) */
|
||||
{0x04, 1, 0, 0, 0x0D}, /* PME#, WAKE#, Reserve, ORST_ACK */
|
||||
{0x05, 1, 0, 0, 0x0F}, /* SLV_BL_STS, ERR_NF, ERR_F, SLV_BL_DONE*/
|
||||
{0x06, 1, 1, 0, 0x0C}, /* HRST_ACK, RCIN#, SMI#, SCI# */
|
||||
{0x40, 1, 0, 0, 0x01}, /* Reserve, Reserve, Reserve, SUS_ACK# */
|
||||
};
|
||||
|
||||
/* eSPI interrupts used in MIWU */
|
||||
static const struct host_wui_item espi_vw_int_list[] = {
|
||||
/* ESPI_RESET */
|
||||
{MIWU_TABLE_0, MIWU_GROUP_5, 5, MIWU_EDGE_RISING},
|
||||
/* SLP_S3 */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_1, 0, MIWU_EDGE_ANYING},
|
||||
/* SLP_S4 */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_1, 1, MIWU_EDGE_ANYING},
|
||||
/* SLP_S5 */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_1, 2, MIWU_EDGE_ANYING},
|
||||
/* VW_WIRE_PLTRST */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_1, 5, MIWU_EDGE_RISING},
|
||||
/* VW_WIRE_OOB_RST_WARN */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_1, 6, MIWU_EDGE_ANYING},
|
||||
/* VW_WIRE_HOST_RST_WARN */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_2, 0, MIWU_EDGE_ANYING},
|
||||
/* VW_WIRE_SUS_WARN */
|
||||
{MIWU_TABLE_2, MIWU_GROUP_2, 4, MIWU_EDGE_RISING},
|
||||
};
|
||||
|
||||
/* VW signals used in eSPI */
|
||||
static const struct vw_event_t vw_events_list[] = {
|
||||
{VW_SLP_S3_L, 0x02, 0x01}, /* index 02h (In) */
|
||||
{VW_SLP_S4_L, 0x02, 0x02},
|
||||
{VW_SLP_S5_L, 0x02, 0x04},
|
||||
{VW_SUS_STAT_L, 0x03, 0x01}, /* index 03h (In) */
|
||||
{VW_PLTRST_L, 0x03, 0x02},
|
||||
{VW_OOB_RST_WARN, 0x03, 0x04},
|
||||
{VW_OOB_RST_ACK, 0x04, 0x01}, /* index 04h (Out) */
|
||||
{VW_WAKE_L, 0x04, 0x04},
|
||||
{VW_PME_L, 0x04, 0x08},
|
||||
{VW_ERROR_FATAL, 0x05, 0x02}, /* index 05h (Out) */
|
||||
{VW_ERROR_NON_FATAL, 0x05, 0x04},
|
||||
{VW_SLAVE_BTLD_STATUS_DONE, 0x05, 0x09},
|
||||
{VW_SCI_L, 0x06, 0x01}, /* index 06h (Out) */
|
||||
{VW_SMI_L, 0x06, 0x02},
|
||||
{VW_RCIN_L, 0x06, 0x04},
|
||||
{VW_HOST_RST_ACK, 0x06, 0x08},
|
||||
{VW_HOST_RST_WARN, 0x07, 0x01}, /* index 07h (In) */
|
||||
{VW_SUS_ACK, 0x40, 0x01}, /* index 40h (Out) */
|
||||
{VW_SUS_WARN_L, 0x41, 0x01}, /* index 41h (In) */
|
||||
{VW_SUS_PWRDN_ACK_L, 0x41, 0x02},
|
||||
{VW_SLP_A_L, 0x41, 0x08},
|
||||
{VW_SLP_LAN, 0x42, 0x01}, /* index 42h (In) */
|
||||
{VW_SLP_WLAN, 0x42, 0x02},
|
||||
};
|
||||
|
||||
/* Flag for SLAVE_BOOT_LOAD siganls */
|
||||
static uint8_t boot_load_done;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* eSPI internal utilities */
|
||||
|
||||
/* Recovery utility for eSPI reset */
|
||||
static void espi_reset_recovery(void)
|
||||
{
|
||||
/* TODO: Put recovery stuff related to eSPI reset here */
|
||||
|
||||
/* Clear boot load flag */
|
||||
boot_load_done = 0;
|
||||
}
|
||||
|
||||
/* Configure Master-to-Slave virtual wire inputs */
|
||||
static void espi_vw_config_in(const struct vwevms_config_t *config)
|
||||
{
|
||||
uint32_t val;
|
||||
uint8_t i, index;
|
||||
|
||||
switch (VM_TYPE(config->idx)) {
|
||||
case ESPI_VW_TYPE_SYS_EV:
|
||||
case ESPI_VW_TYPE_PLT:
|
||||
for (i = 0; i < ESPI_VWEVMS_NUM; i++) {
|
||||
index = VWEVMS_IDX_GET(NPCX_VWEVMS(i));
|
||||
/* Set VW input register */
|
||||
if (index == config->idx) {
|
||||
/* Get Wire field */
|
||||
val = NPCX_VWEVMS(i) & 0x0F;
|
||||
val |= VWEVMS_FIELD(config->idx,
|
||||
config->idx_en,
|
||||
config->pltrst_en,
|
||||
config->int_en,
|
||||
config->espirst_en);
|
||||
NPCX_VWEVMS(i) = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
CPRINTS("No match index of all VWEVMSs");
|
||||
break;
|
||||
default:
|
||||
CPRINTS("No support type of VWEVMS");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure Slave-to-Master virtual wire outputs */
|
||||
static void espi_vw_config_out(const struct vwevsm_config_t *config)
|
||||
{
|
||||
uint32_t val;
|
||||
uint8_t i, index;
|
||||
|
||||
switch (VM_TYPE(config->idx)) {
|
||||
case ESPI_VW_TYPE_SYS_EV:
|
||||
case ESPI_VW_TYPE_PLT:
|
||||
for (i = 0; i < ESPI_VWEVSM_NUM; i++) {
|
||||
index = VWEVSM_IDX_GET(NPCX_VWEVSM(i));
|
||||
/* Set VW output register */
|
||||
if (index == config->idx) {
|
||||
/* Get Wire field */
|
||||
val = NPCX_VWEVSM(i) & 0x0F;
|
||||
val |= VWEVSM_FIELD(config->idx,
|
||||
config->idx_en,
|
||||
config->valid,
|
||||
config->pltrst_en,
|
||||
config->cdrst_en);
|
||||
NPCX_VWEVSM(i) = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
CPRINTS("No match index of all VWEVSMs");
|
||||
break;
|
||||
default:
|
||||
CPRINTS("No support type of VWEVSM");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Config Master-to-Slave VWire interrupt edge type and enable it */
|
||||
static void espi_enable_vw_int(const struct host_wui_item *vwire_int)
|
||||
{
|
||||
uint8_t table = vwire_int->table;
|
||||
uint8_t group = vwire_int->group;
|
||||
uint8_t num = vwire_int->num;
|
||||
uint8_t edge = vwire_int->edge;
|
||||
|
||||
/* Set detection mode to edge */
|
||||
CLEAR_BIT(NPCX_WKMOD(table, group), num);
|
||||
|
||||
if (edge != MIWU_EDGE_ANYING) {
|
||||
/* Disable Any Edge */
|
||||
CLEAR_BIT(NPCX_WKAEDG(table, group), num);
|
||||
/* Enable Rising Edge */
|
||||
if (edge == MIWU_EDGE_RISING)
|
||||
CLEAR_BIT(NPCX_WKEDG(table, group), num);
|
||||
/* Enable Falling Edge */
|
||||
else
|
||||
SET_BIT(NPCX_WKEDG(table, group), num);
|
||||
} else
|
||||
/* enable Any Edge */
|
||||
SET_BIT(NPCX_WKAEDG(table, group), num);
|
||||
|
||||
/* Enable wake-up input sources */
|
||||
SET_BIT(NPCX_WKEN(table, group), num);
|
||||
}
|
||||
|
||||
/* Get vw index & value information by signal */
|
||||
static int espi_vw_get_signal_index(enum espi_vw_signal event)
|
||||
{
|
||||
int index;
|
||||
|
||||
/* Find the vw index by signal name first */
|
||||
for (index = 0; index < ARRAY_SIZE(vw_events_list); index++) {
|
||||
if (vw_events_list[index].name == event)
|
||||
break;
|
||||
}
|
||||
/* Cannot find the index */
|
||||
if (index == ARRAY_SIZE(vw_events_list))
|
||||
return -1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/* The ISRs of VW signals which used for power sequences */
|
||||
void espi_vw_power_signal_interrupt(enum espi_vw_signal signal)
|
||||
{
|
||||
/* TODO: Add VW handler in power/common.c */
|
||||
power_signal_interrupt((enum gpio_signal) signal);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* IC specific low-level driver */
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
uint8_t offset, sig_idx, value;
|
||||
|
||||
/* Get index of vw signal list by signale name */
|
||||
sig_idx = espi_vw_get_signal_index(signal);
|
||||
|
||||
/* Cannot find index by signal name */
|
||||
if (sig_idx < 0)
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
/* Find the output register offset by vw index */
|
||||
for (offset = 0; offset < ESPI_VWEVSM_NUM; offset++) {
|
||||
uint8_t vw_idx = VWEVSM_IDX_GET(NPCX_VWEVSM(offset));
|
||||
/* If index matches. break */
|
||||
if (vw_idx == vw_events_list[sig_idx].evt_idx)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cannot match index */
|
||||
if (offset == ESPI_VWEVSM_NUM)
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
value = GET_FIELD(NPCX_VWEVSM(offset), NPCX_VWEVSM_WIRE);
|
||||
/* Set wire */
|
||||
if (level)
|
||||
value |= vw_events_list[sig_idx].evt_val;
|
||||
else /* Clear wire */
|
||||
value &= (~vw_events_list[sig_idx].evt_val);
|
||||
|
||||
SET_FIELD(NPCX_VWEVSM(offset), NPCX_VWEVSM_WIRE, value);
|
||||
|
||||
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)
|
||||
{
|
||||
uint8_t offset, sig_idx, value;
|
||||
|
||||
/* Get index of vw signal list by signale name */
|
||||
sig_idx = espi_vw_get_signal_index(signal);
|
||||
|
||||
/* Cannot find index by signal name */
|
||||
if (sig_idx < 0)
|
||||
return -1;
|
||||
|
||||
/* Find the input register offset by vw index */
|
||||
for (offset = 0; offset < ESPI_VWEVMS_NUM; offset++) {
|
||||
uint8_t vw_idx = VWEVMS_IDX_GET(NPCX_VWEVMS(offset));
|
||||
/* If index matches. break */
|
||||
if (vw_idx == vw_events_list[sig_idx].evt_idx)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cannot match index */
|
||||
if (offset == ESPI_VWEVMS_NUM)
|
||||
return -1;
|
||||
|
||||
/* Get wire & check with valid bits */
|
||||
value = GET_FIELD(NPCX_VWEVMS(offset), NPCX_VWEVMS_WIRE);
|
||||
value &= GET_FIELD(NPCX_VWEVMS(offset), NPCX_VWEVMS_VALID);
|
||||
|
||||
return !!(value & vw_events_list[sig_idx].evt_val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (signal == VW_SLP_S3_L)
|
||||
SET_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 0);
|
||||
else if (signal == VW_SLP_S4_L)
|
||||
SET_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 1);
|
||||
else if (signal == VW_SLP_S5_L)
|
||||
SET_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 2);
|
||||
else
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
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)
|
||||
{
|
||||
if (signal == VW_SLP_S3_L)
|
||||
CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 0);
|
||||
else if (signal == VW_SLP_S4_L)
|
||||
CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 1);
|
||||
else if (signal == VW_SLP_S5_L)
|
||||
CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_2, MIWU_GROUP_1), 2);
|
||||
else
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* VW event handlers */
|
||||
|
||||
/* PLTRST# event handler */
|
||||
void espi_vw_evt_pltrst(void)
|
||||
{
|
||||
CPRINTS("VW PLTRST: %d", espi_vw_get_wire(VW_PLTRST_L));
|
||||
|
||||
/* Disable eSPI peripheral channel support first */
|
||||
CLEAR_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCCHN_SUPP);
|
||||
|
||||
/* Enable eSPI peripheral channel */
|
||||
SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCHANEN);
|
||||
/* Initialize host settings */
|
||||
host_register_init();
|
||||
|
||||
/* Re-enable eSPI peripheral channel support */
|
||||
SET_BIT(NPCX_ESPICFG, NPCX_ESPICFG_PCCHN_SUPP);
|
||||
|
||||
#ifdef CONFIG_CHIPSET_RESET_HOOK
|
||||
if (lpc_get_pltrst_asserted()) {
|
||||
/* Notify HOOK_CHIPSET_RESET */
|
||||
hook_call_deferred(lpc_chipset_reset, MSEC);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* SLP_Sx event handler */
|
||||
void espi_vw_evt_slp_s3(void)
|
||||
{
|
||||
CPRINTS("VW SLP_S3: %d", espi_vw_get_wire(VW_SLP_S3_L));
|
||||
espi_vw_power_signal_interrupt(VW_SLP_S3_L);
|
||||
}
|
||||
|
||||
void espi_vw_evt_slp_s4(void)
|
||||
{
|
||||
CPRINTS("VW SLP_S4: %d", espi_vw_get_wire(VW_SLP_S4_L));
|
||||
espi_vw_power_signal_interrupt(VW_SLP_S4_L);
|
||||
}
|
||||
|
||||
void espi_vw_evt_slp_s5(void)
|
||||
{
|
||||
CPRINTS("VW SLP_S5: %d", espi_vw_get_wire(VW_SLP_S5_L));
|
||||
espi_vw_power_signal_interrupt(VW_SLP_S5_L);
|
||||
}
|
||||
|
||||
/* OOB Reset event handler */
|
||||
void espi_vw_evt_oobrst(void)
|
||||
{
|
||||
CPRINTS("VW OOB_RST: %d", espi_vw_get_wire(VW_OOB_RST_WARN));
|
||||
|
||||
/* Send ACK to host by WARN#'s wire */
|
||||
espi_vw_set_wire(VW_OOB_RST_ACK, espi_vw_get_wire(VW_OOB_RST_WARN));
|
||||
}
|
||||
|
||||
/* SUS_WARN# event handler */
|
||||
void espi_vw_evt_sus_warn(void)
|
||||
{
|
||||
CPRINTS("VW SUS_WARN#: %d", espi_vw_get_wire(VW_SUS_WARN_L));
|
||||
|
||||
udelay(100);
|
||||
|
||||
/* Send ACK to host by WARN#'s wire */
|
||||
espi_vw_set_wire(VW_SUS_ACK, espi_vw_get_wire(VW_SUS_WARN_L));
|
||||
}
|
||||
|
||||
/* HOSTRST WARN event handler */
|
||||
void espi_vw_evt_hostrst_warn(void)
|
||||
{
|
||||
CPRINTS("VW HOST_RST_WARN#: %d", espi_vw_get_wire(VW_HOST_RST_WARN));
|
||||
|
||||
/* Send ACK to host by WARN#'s wire */
|
||||
espi_vw_set_wire(VW_HOST_RST_ACK, espi_vw_get_wire(VW_HOST_RST_WARN));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Interrupt handlers */
|
||||
|
||||
/* eSPI reset assert/de-assert interrupt */
|
||||
void espi_espirst_handler(void)
|
||||
{
|
||||
/* Clear pending bit of WUI */
|
||||
SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 5);
|
||||
|
||||
CPRINTS("eSPI RST issued!");
|
||||
}
|
||||
|
||||
/* Handle eSPI virtual wire interrupt 1 */
|
||||
void __espi_wk2a_interrupt(void)
|
||||
{
|
||||
uint8_t pending_bits = NPCX_WKPND(MIWU_TABLE_2, MIWU_GROUP_1);
|
||||
|
||||
/* Clear pending bits of MIWU */
|
||||
NPCX_WKPCL(MIWU_TABLE_2, MIWU_GROUP_1) = pending_bits;
|
||||
|
||||
/* Handle events of virtual-wire */
|
||||
if (IS_BIT_SET(pending_bits, 0))
|
||||
espi_vw_evt_slp_s3();
|
||||
if (IS_BIT_SET(pending_bits, 1))
|
||||
espi_vw_evt_slp_s4();
|
||||
if (IS_BIT_SET(pending_bits, 2))
|
||||
espi_vw_evt_slp_s5();
|
||||
if (IS_BIT_SET(pending_bits, 5))
|
||||
espi_vw_evt_pltrst();
|
||||
if (IS_BIT_SET(pending_bits, 6))
|
||||
espi_vw_evt_oobrst();
|
||||
}
|
||||
DECLARE_IRQ(NPCX_IRQ_WKINTA_2, __espi_wk2a_interrupt, 2);
|
||||
|
||||
/* Handle eSPI virtual wire interrupt 2 */
|
||||
void __espi_wk2b_interrupt(void)
|
||||
{
|
||||
uint8_t pending_bits = NPCX_WKPND(MIWU_TABLE_2, MIWU_GROUP_2);
|
||||
|
||||
/* Clear pending bits of MIWU */
|
||||
NPCX_WKPCL(MIWU_TABLE_2, MIWU_GROUP_2) = pending_bits;
|
||||
|
||||
/* Handle events of virtual-wire */
|
||||
if (IS_BIT_SET(pending_bits, 4))
|
||||
espi_vw_evt_sus_warn();
|
||||
if (IS_BIT_SET(pending_bits, 0))
|
||||
espi_vw_evt_hostrst_warn();
|
||||
}
|
||||
DECLARE_IRQ(NPCX_IRQ_WKINTB_2, __espi_wk2b_interrupt, 2);
|
||||
|
||||
/* Interrupt handler for eSPI status changed */
|
||||
void espi_interrupt(void)
|
||||
{
|
||||
int chan;
|
||||
uint32_t mask, status;
|
||||
|
||||
mask = NPCX_ESPIIE;
|
||||
status = NPCX_ESPISTS & mask;
|
||||
|
||||
while (status) {
|
||||
/* Clear pending bits first */
|
||||
NPCX_ESPISTS = status;
|
||||
|
||||
if (IS_BIT_SET(status, NPCX_ESPISTS_BERR))
|
||||
CPRINTS("eSPI Bus Error");
|
||||
|
||||
/* eSPI inband reset(from VW) */
|
||||
if (IS_BIT_SET(status, NPCX_ESPISTS_IBRST)) {
|
||||
CPRINTS("eSPI RST inband RST");
|
||||
espi_reset_recovery();
|
||||
|
||||
} /* eSPI reset (from eSPI_rst pin) */
|
||||
else if (IS_BIT_SET(status, NPCX_ESPISTS_ESPIRST)) {
|
||||
CPRINTS("eSPI RST");
|
||||
espi_reset_recovery();
|
||||
}
|
||||
|
||||
/* eSPI configuration is updated */
|
||||
if (IS_BIT_SET(status, NPCX_ESPISTS_CFGUPD)) {
|
||||
/*
|
||||
* If host enable/disable channel for VW/OOB/FLASH, EC
|
||||
* should follow except Peripheral channel. It is
|
||||
* handled by PLTRST separately.
|
||||
*/
|
||||
for (chan = NPCX_ESPI_CH_VW; chan < NPCX_ESPI_CH_COUNT;
|
||||
chan++) {
|
||||
if (!IS_SLAVE_CHAN_ENABLE(chan) &&
|
||||
IS_HOST_CHAN_EN(chan))
|
||||
ENABLE_ESPI_CHAN(chan);
|
||||
else if (IS_SLAVE_CHAN_ENABLE(chan) &&
|
||||
!IS_HOST_CHAN_EN(chan))
|
||||
DISABLE_ESPI_CHAN(chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send SLAVE_BOOTLOAD_DONE and SLAVE_BOOTLOAD_STATUS
|
||||
* events to host simultaneously. To indicate the
|
||||
* completion of EC firmware code loading.
|
||||
*/
|
||||
if (boot_load_done == 0 &&
|
||||
IS_SLAVE_CHAN_ENABLE(NPCX_ESPI_CH_VW)) {
|
||||
|
||||
espi_vw_set_wire(VW_SLAVE_BTLD_STATUS_DONE, 1);
|
||||
boot_load_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any VW signal sent by Host - leave it, handle in MIWU ISR */
|
||||
if (IS_BIT_SET(status, NPCX_ESPISTS_VWUPD))
|
||||
CPRINTS("VW Updated INT");
|
||||
|
||||
/* Get status again */
|
||||
status = NPCX_ESPISTS & mask;
|
||||
}
|
||||
}
|
||||
DECLARE_IRQ(NPCX_IRQ_ESPI, espi_interrupt, 3);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* eSPI Initialization functions */
|
||||
void espi_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Support all channels */
|
||||
NPCX_ESPICFG |= ESPI_SUPP_CH_ALL;
|
||||
|
||||
/* Support all I/O modes */
|
||||
SET_FIELD(NPCX_ESPICFG, NPCX_ESPICFG_IOMODE_FILED,
|
||||
NPCX_ESPI_IO_MODE_ALL);
|
||||
|
||||
/* Max freq 66 MHz of eSPI */
|
||||
SET_FIELD(NPCX_ESPICFG, NPCX_ESPICFG_MAXFREQ_FILED,
|
||||
NPCX_ESPI_MAXFREQ_66);
|
||||
|
||||
/* Configure Master-to-Slave Virtual Wire indexes (Inputs) */
|
||||
for (i = 0; i < ARRAY_SIZE(espi_in_list); i++)
|
||||
espi_vw_config_in(&espi_in_list[i]);
|
||||
|
||||
/* Configure Slave-to-Master Virtual Wire indexes (Outputs) */
|
||||
for (i = 0; i < ARRAY_SIZE(espi_out_list); i++)
|
||||
espi_vw_config_out(&espi_out_list[i]);
|
||||
|
||||
/* Configure MIWU for eSPI VW */
|
||||
for (i = 0; i < ARRAY_SIZE(espi_vw_int_list); i++)
|
||||
espi_enable_vw_int(&espi_vw_int_list[i]);
|
||||
}
|
||||
|
||||
static int command_espi(int argc, char **argv)
|
||||
{
|
||||
uint32_t chan;
|
||||
char *e;
|
||||
|
||||
if (argc == 1) {
|
||||
return EC_ERROR_INVAL;
|
||||
/* Get value of eSPI registers */
|
||||
} else if (argc == 2) {
|
||||
int i;
|
||||
|
||||
if (strcasecmp(argv[1], "cfg") == 0) {
|
||||
ccprintf("ESPICFG [0x%08x]\n", NPCX_ESPICFG);
|
||||
} else if (strcasecmp(argv[1], "vsm") == 0) {
|
||||
for (i = 0; i < ESPI_VWEVSM_NUM; i++) {
|
||||
uint32_t val = NPCX_VWEVSM(i);
|
||||
uint8_t idx = VWEVSM_IDX_GET(val);
|
||||
|
||||
ccprintf("VWEVSM%d: %02x [0x%08x]\n", i, idx,
|
||||
val);
|
||||
}
|
||||
} else if (strcasecmp(argv[1], "vms") == 0) {
|
||||
for (i = 0; i < ESPI_VWEVMS_NUM; i++) {
|
||||
uint32_t val = NPCX_VWEVMS(i);
|
||||
uint8_t idx = VWEVMS_IDX_GET(val);
|
||||
|
||||
ccprintf("VWEVMS%d: %02x [0x%08x]\n", i, idx,
|
||||
val);
|
||||
}
|
||||
}
|
||||
/* Enable/Disable the channels of eSPI */
|
||||
} else if (argc == 3) {
|
||||
uint32_t m = (uint32_t) strtoi(argv[2], &e, 0);
|
||||
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM2;
|
||||
if (m < 0 || m > 4)
|
||||
return EC_ERROR_PARAM2;
|
||||
else if (m == 4)
|
||||
chan = 0x0F;
|
||||
else
|
||||
chan = 0x01 << m;
|
||||
if (strcasecmp(argv[1], "en") == 0)
|
||||
NPCX_ESPICFG = NPCX_ESPICFG | chan;
|
||||
else if (strcasecmp(argv[1], "dis") == 0)
|
||||
NPCX_ESPICFG = NPCX_ESPICFG & ~chan;
|
||||
else
|
||||
return EC_ERROR_PARAM1;
|
||||
ccprintf("ESPICFG [0x%08x]\n", NPCX_ESPICFG);
|
||||
}
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(espi, command_espi,
|
||||
"cfg/vms/vsm/en/dis [channel]",
|
||||
"eSPI configurations",
|
||||
NULL);
|
||||
|
||||
@@ -786,18 +786,25 @@ void _irq_func(void) \
|
||||
/* If we need to handle the other type interrupts except GPIO, add code here */
|
||||
void __gpio_wk0efgh_interrupt(void)
|
||||
{
|
||||
#ifdef CONFIG_LPC
|
||||
/* Pending bit 7 or 6 ? */
|
||||
#if defined(CONFIG_LPC) || defined(CONFIG_ESPI)
|
||||
/* Pending bit 7 or 6 or 5? */
|
||||
if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0 , MIWU_GROUP_5), 6) &&
|
||||
IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0 , MIWU_GROUP_5), 6)) {
|
||||
/* Disable host wake-up */
|
||||
CLEAR_BIT(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 6);
|
||||
/* Clear pending bit of WUI */
|
||||
SET_BIT(NPCX_WKPCL(MIWU_TABLE_0 , MIWU_GROUP_5), 6);
|
||||
} else if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0 , MIWU_GROUP_5), 7) &&
|
||||
IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0 , MIWU_GROUP_5), 7))
|
||||
SET_BIT(NPCX_WKPCL(MIWU_TABLE_0, MIWU_GROUP_5), 6);
|
||||
}
|
||||
#ifdef CONFIG_ESPI
|
||||
else if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 5) &&
|
||||
IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 5))
|
||||
espi_espirst_handler();
|
||||
#else
|
||||
else if (IS_BIT_SET(NPCX_WKEN(MIWU_TABLE_0, MIWU_GROUP_5), 7) &&
|
||||
IS_BIT_SET(NPCX_WKPND(MIWU_TABLE_0, MIWU_GROUP_5), 7))
|
||||
lpc_lreset_pltrst_handler();
|
||||
else /* FW will jump into ISR again if other GPIOs' INT still issued */
|
||||
#endif
|
||||
else
|
||||
#endif
|
||||
gpio_interrupt(NPCX_IRQ_WKINTEFGH_0);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "uart.h"
|
||||
#include "util.h"
|
||||
#include "system_chip.h"
|
||||
#include "lpc_chip.h"
|
||||
|
||||
/* Console output macros */
|
||||
#if !(DEBUG_LPC)
|
||||
@@ -92,6 +93,15 @@ static void lpc_task_enable_irq(void)
|
||||
task_enable_irq(NPCX_IRQ_KBC_IBF);
|
||||
task_enable_irq(NPCX_IRQ_PM_CHAN_IBF);
|
||||
task_enable_irq(NPCX_IRQ_PORT80);
|
||||
#ifdef CONFIG_ESPI
|
||||
task_enable_irq(NPCX_IRQ_ESPI);
|
||||
/* Virtual Wire: SLP_S3/4/5, SUS_STAT, PLTRST, OOB_RST_WARN */
|
||||
task_enable_irq(NPCX_IRQ_WKINTA_2);
|
||||
/* Virtual Wire: HOST_RST_WARN, SUS_WARN, SUS_PWRDN_ACK, SLP_A */
|
||||
task_enable_irq(NPCX_IRQ_WKINTB_2);
|
||||
/* Enable eSPI module interrupts */
|
||||
NPCX_ESPIIE |= (ESPIIE_GENERIC | ESPIIE_VW);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lpc_task_disable_irq(void)
|
||||
@@ -99,6 +109,15 @@ static void lpc_task_disable_irq(void)
|
||||
task_disable_irq(NPCX_IRQ_KBC_IBF);
|
||||
task_disable_irq(NPCX_IRQ_PM_CHAN_IBF);
|
||||
task_disable_irq(NPCX_IRQ_PORT80);
|
||||
#ifdef CONFIG_ESPI
|
||||
task_disable_irq(NPCX_IRQ_ESPI);
|
||||
/* Virtual Wire: SLP_S3/4/5, SUS_STAT, PLTRST, OOB_RST_WARN */
|
||||
task_disable_irq(NPCX_IRQ_WKINTA_2);
|
||||
/* Virtual Wire: HOST_RST_WARN,SUS_WARN, SUS_PWRDN_ACK, SLP_A */
|
||||
task_disable_irq(NPCX_IRQ_WKINTB_2);
|
||||
/* Disable eSPI module interrupts */
|
||||
NPCX_ESPIIE &= ~(ESPIIE_GENERIC | ESPIIE_VW);
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* Generate SMI pulse to the host chipset via GPIO.
|
||||
@@ -688,7 +707,7 @@ uint8_t lpc_sib_read_reg(uint8_t io_offset, uint8_t index_value)
|
||||
}
|
||||
|
||||
/* For LPC host register initial via SIB module */
|
||||
void lpc_host_register_init(void)
|
||||
void host_register_init(void)
|
||||
{
|
||||
/* enable ACPI*/
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x11);
|
||||
@@ -751,6 +770,7 @@ int lpc_get_pltrst_asserted(void)
|
||||
return (NPCX_MSWCTL1 & 0x04) ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ESPI
|
||||
/* Initialize host settings by interrupt */
|
||||
void lpc_lreset_pltrst_handler(void)
|
||||
{
|
||||
@@ -774,7 +794,7 @@ void lpc_lreset_pltrst_handler(void)
|
||||
* won't be reset by Host domain reset but Core domain does.
|
||||
*/
|
||||
if (!pltrst_asserted)
|
||||
lpc_host_register_init();
|
||||
host_register_init();
|
||||
else {
|
||||
#ifdef CONFIG_CHIPSET_RESET_HOOK
|
||||
/* Notify HOOK_CHIPSET_RESET */
|
||||
@@ -782,14 +802,26 @@ void lpc_lreset_pltrst_handler(void)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* LPC/eSPI Initialization functions */
|
||||
|
||||
static void lpc_init(void)
|
||||
{
|
||||
/* Enable clock for LPC peripheral */
|
||||
clock_enable_peripheral(CGC_OFFSET_LPC, CGC_LPC_MASK,
|
||||
CGC_MODE_RUN | CGC_MODE_SLEEP);
|
||||
#ifdef CONFIG_ESPI
|
||||
/* Enable clock for eSPI peripheral */
|
||||
clock_enable_peripheral(CGC_OFFSET_ESPI, CGC_ESPI_MASK,
|
||||
CGC_MODE_RUN | CGC_MODE_SLEEP);
|
||||
/* Initialize eSPI IP */
|
||||
espi_init();
|
||||
#else
|
||||
/* Switching to LPC interface */
|
||||
NPCX_DEVCNT |= 0x04;
|
||||
#endif
|
||||
/* Enable 4E/4F */
|
||||
if (!IS_BIT_SET(NPCX_MSWCTL1, 3)) {
|
||||
NPCX_HCBAL = 0x4E;
|
||||
@@ -798,11 +830,13 @@ static void lpc_init(void)
|
||||
/* Clear Host Access Hold state */
|
||||
NPCX_SMC_CTL = 0xC0;
|
||||
|
||||
#ifndef CONFIG_ESPI
|
||||
/*
|
||||
* Set alternative pin from GPIO to CLKRUN no matter SERIRQ is under
|
||||
* continuous or quiet mode.
|
||||
*/
|
||||
SET_BIT(NPCX_DEVALT(1), NPCX_DEVALT1_CLKRN_SL);
|
||||
#endif
|
||||
|
||||
/* Initialize Hardware for UART Host */
|
||||
#if CONFIG_UART_HOST
|
||||
@@ -897,7 +931,7 @@ static void lpc_init(void)
|
||||
*/
|
||||
#ifdef BOARD_NPCX_EVB
|
||||
/* initial IO port address via SIB-write modules */
|
||||
lpc_host_register_init();
|
||||
host_register_init();
|
||||
#else
|
||||
/* Initialize LRESET# interrupt */
|
||||
/* Set detection mode to edge */
|
||||
|
||||
@@ -8,7 +8,16 @@
|
||||
#ifndef __CROS_EC_LPC_CHIP_H
|
||||
#define __CROS_EC_LPC_CHIP_H
|
||||
|
||||
/* Initialize host settings by interrupt */
|
||||
void lpc_lreset_pltrst_handler(void);
|
||||
/* For host registers initialization via SIB module */
|
||||
void host_register_init(void);
|
||||
|
||||
#ifdef CONFIG_ESPI
|
||||
/* eSPI Initialization functions */
|
||||
void espi_init(void);
|
||||
/* eSPI reset assert/de-assert interrupt */
|
||||
void espi_espirst_handler(void);
|
||||
#else
|
||||
/* LPC PLTRST assert/de-assert interrupt */
|
||||
void lpc_lreset_pltrst_handler(void);
|
||||
#endif
|
||||
#endif /* __CROS_EC_LPC_CHIP_H */
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#define DEBUG_SHI 0
|
||||
#define DEBUG_CLK 0
|
||||
#define DEBUG_LPC 0
|
||||
#define DEBUG_ESPI 0
|
||||
|
||||
/* Modules Map */
|
||||
#define NPCX_MDC_BASE_ADDR 0x4000C000
|
||||
@@ -84,6 +85,7 @@
|
||||
#define NPCX_SPI_BASE_ADDR 0x400D2000
|
||||
#define NPCX_PECI_BASE_ADDR 0x400D4000
|
||||
#define NPCX_TWD_BASE_ADDR 0x400D8000
|
||||
#define NPCX_ESPI_BASE_ADDR 0x4000A000
|
||||
|
||||
/* Multi-Modules Map */
|
||||
#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl) * 0x2000L))
|
||||
@@ -184,6 +186,7 @@
|
||||
#define NPCX_IRQ16_NOUSED NPCX_IRQ_16
|
||||
#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17
|
||||
#define NPCX_IRQ_SHI NPCX_IRQ_18
|
||||
#define NPCX_IRQ_ESPI NPCX_IRQ_18
|
||||
#define NPCX_IRQ19_NOUSED NPCX_IRQ_19
|
||||
#define NPCX_IRQ20_NOUSED NPCX_IRQ_20
|
||||
#define NPCX_IRQ_PS2 NPCX_IRQ_21
|
||||
@@ -347,6 +350,7 @@ enum {
|
||||
enum {
|
||||
MIWU_EDGE_RISING,
|
||||
MIWU_EDGE_FALLING,
|
||||
MIWU_EDGE_ANYING,
|
||||
};
|
||||
|
||||
/* MIWU utilities */
|
||||
@@ -464,6 +468,7 @@ enum {
|
||||
|
||||
/* SCFG register fields */
|
||||
#define NPCX_DEVCNT_F_SPI_TRIS 6
|
||||
#define NPCX_DEVCNT_HIF_TYP_SEL_FIELD FIELD(2, 2)
|
||||
#define NPCX_DEVCNT_JEN1_HEN 5
|
||||
#define NPCX_DEVCNT_JEN0_HEN 4
|
||||
#define NPCX_STRPST_TRIST 1
|
||||
@@ -1227,6 +1232,202 @@ enum ITIM16_MODULE_T {
|
||||
/* Low Power RAM definitions */
|
||||
#define NPCX_LPRAM_CTRL REG32(0x40001044)
|
||||
|
||||
/******************************************************************************/
|
||||
/* eSPI Registers */
|
||||
#define NPCX_ESPIID REG32(NPCX_ESPI_BASE_ADDR + 0X00)
|
||||
#define NPCX_ESPICFG REG32(NPCX_ESPI_BASE_ADDR + 0X04)
|
||||
#define NPCX_ESPISTS REG32(NPCX_ESPI_BASE_ADDR + 0X08)
|
||||
#define NPCX_ESPIIE REG32(NPCX_ESPI_BASE_ADDR + 0X0C)
|
||||
#define NPCX_ESPIIWE REG32(NPCX_ESPI_BASE_ADDR + 0X10)
|
||||
#define NPCX_VWREGIDX REG32(NPCX_ESPI_BASE_ADDR + 0X14)
|
||||
#define NPCX_VWREGDATA REG32(NPCX_ESPI_BASE_ADDR + 0X18)
|
||||
#define NPCX_OOBCTL REG32(NPCX_ESPI_BASE_ADDR + 0X24)
|
||||
#define NPCX_FLASHRXRDHEAD REG32(NPCX_ESPI_BASE_ADDR + 0X28)
|
||||
#define NPCX_FLASHTXWRHEAD REG32(NPCX_ESPI_BASE_ADDR + 0X2C)
|
||||
#define NPCX_FLASHCFG REG32(NPCX_ESPI_BASE_ADDR + 0X34)
|
||||
#define NPCX_FLASHCTL REG32(NPCX_ESPI_BASE_ADDR + 0X38)
|
||||
#define NPCX_ESPIIERR REG32(NPCX_ESPI_BASE_ADDR + 0X3C)
|
||||
|
||||
/* eSPI Virtual Wire channel registers */
|
||||
#define NPCX_VWEVSM(n) REG32(NPCX_ESPI_BASE_ADDR + 0x100 + (4*(n)))
|
||||
#define NPCX_VWEVMS(n) REG32(NPCX_ESPI_BASE_ADDR + 0x140 + (4*(n)))
|
||||
#define NPCX_VWGPSM(n) REG32(NPCX_ESPI_BASE_ADDR + 0x180 + (4*(n)))
|
||||
#define NPCX_VWGPMS(n) REG32(NPCX_ESPI_BASE_ADDR + 0x1C0 + (4*(n)))
|
||||
#define NPCX_VWPING REG32(NPCX_ESPI_BASE_ADDR + 0x2F8)
|
||||
#define NPCX_VWCTL REG32(NPCX_ESPI_BASE_ADDR + 0x2FC)
|
||||
|
||||
/* eSPI register fields */
|
||||
#define NPCX_ESPICFG_PCHANEN 0
|
||||
#define NPCX_ESPICFG_VWCHANEN 1
|
||||
#define NPCX_ESPICFG_OOBCHANEN 2
|
||||
#define NPCX_ESPICFG_FLASHCHANEN 3
|
||||
#define NPCX_ESPICFG_IOMODE_FILED FIELD(8, 9)
|
||||
#define NPCX_ESPICFG_MAXFREQ_FILED FIELD(10, 12)
|
||||
#define NPCX_ESPICFG_PCCHN_SUPP 24
|
||||
#define NPCX_ESPICFG_VWCHN_SUPP 25
|
||||
#define NPCX_ESPICFG_OOBCHN_SUPP 26
|
||||
#define NPCX_ESPICFG_FLASHCHN_SUPP 27
|
||||
#define NPCX_ESPIIE_IBRSTIE 0
|
||||
#define NPCX_ESPIIE_CFGUPDIE 1
|
||||
#define NPCX_ESPIIE_BERRIE 2
|
||||
#define NPCX_ESPIIE_OOBRXIE 3
|
||||
#define NPCX_ESPIIE_FLASHRXIE 4
|
||||
#define NPCX_ESPIIE_SFLASHRDIE 5
|
||||
#define NPCX_ESPIIE_PERACCIE 6
|
||||
#define NPCX_ESPIIE_DFRDIE 7
|
||||
#define NPCX_ESPIIE_VWUPDIE 8
|
||||
#define NPCX_ESPIIE_ESPIRSTIE 9
|
||||
#define NPCX_ESPIIE_PLTRSTIE 10
|
||||
#define NPCX_ESPIIE_VW1IE 11
|
||||
#define NPCX_ESPIIE_VW2IE 12
|
||||
#define NPCX_ESPIIE_VW3IE 13
|
||||
#define NPCX_ESPIIE_VW4IE 14
|
||||
#define NPCX_ESPIIE_AMERRIE 15
|
||||
#define NPCX_ESPIIE_AMDONEIE 16
|
||||
#define NPCX_ESPISTS_IBRST 0
|
||||
#define NPCX_ESPISTS_CFGUPD 1
|
||||
#define NPCX_ESPISTS_BERR 2
|
||||
#define NPCX_ESPISTS_OOBRX 3
|
||||
#define NPCX_ESPISTS_FLASHRX 4
|
||||
#define NPCX_ESPISTS_SFLASHRD 5
|
||||
#define NPCX_ESPISTS_PERACC 6
|
||||
#define NPCX_ESPISTS_DFRD 7
|
||||
#define NPCX_ESPISTS_VWUPD 8
|
||||
#define NPCX_ESPISTS_ESPIRST 9
|
||||
#define NPCX_ESPISTS_PLTRST 10
|
||||
#define NPCX_ESPISTS_VW1 11
|
||||
#define NPCX_ESPISTS_VW2 12
|
||||
#define NPCX_ESPISTS_VW3 13
|
||||
#define NPCX_ESPISTS_VW4 14
|
||||
#define NPCX_ESPISTS_AMERR 15
|
||||
#define NPCX_ESPISTS_AMDONE 16
|
||||
/* eSPI Virtual Wire channel register fields */
|
||||
#define NPCX_VWEVSM_WIRE FIELD(0, 4)
|
||||
#define NPCX_VWEVMS_WIRE FIELD(0, 4)
|
||||
#define NPCX_VWEVSM_VALID FIELD(4, 4)
|
||||
#define NPCX_VWEVMS_VALID FIELD(4, 4)
|
||||
|
||||
/* Marco functions for eSPI CFG & IE */
|
||||
#define IS_SLAVE_CHAN_ENABLE(ch) IS_BIT_SET(NPCX_ESPICFG, ch)
|
||||
#define IS_HOST_CHAN_EN(ch) IS_BIT_SET(NPCX_ESPICFG, (ch+4))
|
||||
#define ENABLE_ESPI_CHAN(ch) SET_BIT(NPCX_ESPICFG, ch)
|
||||
#define DISABLE_ESPI_CHAN(ch) CLEAR_BIT(NPCX_ESPICFG, ch)
|
||||
/* ESPI Slave Channel Support Definitions */
|
||||
#define ESPI_SUPP_CH_PC (1 << NPCX_ESPICFG_PCCHN_SUPP)
|
||||
#define ESPI_SUPP_CH_VM (1 << NPCX_ESPICFG_VWCHN_SUPP)
|
||||
#define ESPI_SUPP_CH_OOB (1 << NPCX_ESPICFG_OOBCHN_SUPP)
|
||||
#define ESPI_SUPP_CH_FLASH (1 << NPCX_ESPICFG_FLASHCHN_SUPP)
|
||||
#define ESPI_SUPP_CH_ALL (ESPI_SUPP_CH_PC | ESPI_SUPP_CH_VM | \
|
||||
ESPI_SUPP_CH_OOB | ESPI_SUPP_CH_FLASH)
|
||||
/* ESPI Interrupts Enable Definitions */
|
||||
#define ESPIIE_IBRST (1 << NPCX_ESPIIE_IBRSTIE)
|
||||
#define ESPIIE_CFGUPD (1 << NPCX_ESPIIE_CFGUPDIE)
|
||||
#define ESPIIE_BERR (1 << NPCX_ESPIIE_BERRIE)
|
||||
#define ESPIIE_OOBRX (1 << NPCX_ESPIIE_OOBRXIE)
|
||||
#define ESPIIE_FLASHRX (1 << NPCX_ESPIIE_FLASHRXIE)
|
||||
#define ESPIIE_SFLASHRD (1 << NPCX_ESPIIE_SFLASHRDIE)
|
||||
#define ESPIIE_PERACC (1 << NPCX_ESPIIE_PERACCIE)
|
||||
#define ESPIIE_DFRD (1 << NPCX_ESPIIE_DFRDIE)
|
||||
#define ESPIIE_VWUPD (1 << NPCX_ESPIIE_VWUPDIE)
|
||||
#define ESPIIE_ESPIRST (1 << NPCX_ESPIIE_ESPIRSTIE)
|
||||
#define ESPIIE_PLTRST (1 << NPCX_ESPIIE_PLTRSTIE)
|
||||
#define ESPIIE_VW1 (1 << NPCX_ESPIIE_VW1IE)
|
||||
#define ESPIIE_VW2 (1 << NPCX_ESPIIE_VW2IE)
|
||||
#define ESPIIE_VW3 (1 << NPCX_ESPIIE_VW3IE)
|
||||
#define ESPIIE_VW4 (1 << NPCX_ESPIIE_VW4IE)
|
||||
#define ESPIIE_AMERR (1 << NPCX_ESPIIE_AMERRIE)
|
||||
#define ESPIIE_AMDONE (1 << NPCX_ESPIIE_AMDONEIE)
|
||||
/* eSPI Interrupts for VW */
|
||||
#define ESPIIE_VW (ESPIIE_VWUPD | ESPIIE_VW1 | ESPIIE_VW2 | \
|
||||
ESPIIE_VW3 | ESPIIE_VW4 | ESPIIE_PLTRST)
|
||||
/* eSPI Interrupts for Generic */
|
||||
#define ESPIIE_GENERIC (ESPIIE_IBRST | ESPIIE_CFGUPD | \
|
||||
ESPIIE_BERR | ESPIIE_ESPIRST)
|
||||
|
||||
/* Marco functions for eSPI VW */
|
||||
#define ESPI_VWEVMS_NUM 12
|
||||
#define ESPI_VWEVSM_NUM 10
|
||||
#define ESPI_VWGPMS_NUM 16
|
||||
#define ESPI_VW_IDX_WIRE_NUM 4
|
||||
/* Determine Virtual Wire type */
|
||||
#define VM_TYPE(i) ((i >= 0 && i <= 1) ? ESPI_VW_TYPE_INT_EV : \
|
||||
(i >= 2 && i <= 7) ? ESPI_VW_TYPE_SYS_EV : \
|
||||
(i >= 64 && i <= 127) ? ESPI_VW_TYPE_PLT : \
|
||||
(i >= 128 && i <= 255) ? ESPI_VW_TYPE_GPIO : \
|
||||
ESPI_VW_TYPE_NONE)
|
||||
|
||||
/* Bit filed manipulation for VWEVMS Value */
|
||||
#define VWEVMS_INX(i) ((i<<8) & 0x00007F00)
|
||||
#define VWEVMS_INX_EN(n) ((n<<15) & 0x00008000)
|
||||
#define VWEVMS_PLTRST_EN(p) ((p<<17) & 0x00020000)
|
||||
#define VWEVMS_INT_EN(e) ((e<<18) & 0x00040000)
|
||||
#define VWEVMS_ESPIRST_EN(r) ((r<<19) & 0x00080000)
|
||||
#define VWEVMS_FIELD(i, n, p, e, r) (VWEVMS_INX(i) | VWEVMS_INX_EN(n) | \
|
||||
VWEVMS_PLTRST_EN(p) | VWEVMS_INT_EN(e) | \
|
||||
VWEVMS_ESPIRST_EN(r))
|
||||
#define VWEVMS_IDX_GET(reg) (((reg & 0x00007F00)>>8))
|
||||
|
||||
/* Bit filed manipulation for VWEVSM Value */
|
||||
#define VWEVSM_VALID_N(v) ((v<<4) & 0x000000F0)
|
||||
#define VWEVSM_INX(i) ((i<<8) & 0x00007F00)
|
||||
#define VWEVSM_INX_EN(n) ((n<<15) & 0x00008000)
|
||||
#define VWEVSM_DIRTY(d) ((d<<16) & 0x00010000)
|
||||
#define VWEVSM_PLTRST_EN(p) ((p<<17) & 0x00020000)
|
||||
#define VWEVSM_CDRST_EN(c) ((c<<19) & 0x00080000)
|
||||
#define VWEVSM_FIELD(i, n, v, p, c) (VWEVSM_INX(i) | VWEVSM_INX_EN(n) | \
|
||||
VWEVSM_VALID_N(v) | VWEVSM_PLTRST_EN(p) |\
|
||||
VWEVSM_CDRST_EN(c))
|
||||
#define VWEVSM_IDX_GET(reg) (((reg & 0x00007F00)>>8))
|
||||
|
||||
/* Bit filed manpulation for VWGPMS Value */
|
||||
#define VWGPMS_INX_EN(n) (((n<<15) & 0x00008000))
|
||||
#define VWGPMS_MODIFIED(m) (((m<<16) & 0x00010000))
|
||||
#define VWGPMS_PLTRST_EN(p) (((p<<17) & 0x00020000))
|
||||
#define VWGPMS_INT_EN(e) (((e<<18) & 0x00040000))
|
||||
#define VWGPMS_FIELD(n, m, p, e) (VMGPMS_INX_EN(n) | VWGPMS_MODIFIED(m) | \
|
||||
VWGPMS_PLTRST_EN(p) | VWGPMS_INT_EN(e))
|
||||
|
||||
/* eSPI enumeration */
|
||||
/* eSPI channels */
|
||||
enum {
|
||||
NPCX_ESPI_CH_PC = 0,
|
||||
NPCX_ESPI_CH_VW,
|
||||
NPCX_ESPI_CH_OOB,
|
||||
NPCX_ESPI_CH_FLASH,
|
||||
NPCX_ESPI_CH_COUNT,
|
||||
NPCX_ESPI_CH_GENERIC,
|
||||
NPCX_ESPI_CH_NONE = 0xFF
|
||||
};
|
||||
|
||||
/* eSPI IO modes */
|
||||
enum {
|
||||
NPCX_ESPI_IO_MODE_SINGLE = 0,
|
||||
NPCX_ESPI_IO_MODE_DUAL = 1,
|
||||
NPCX_ESPI_IO_MODE_Quad = 2,
|
||||
NPCX_ESPI_IO_MODE_ALL = 3,
|
||||
NPCX_ESPI_IO_MODE_NONE = 0xFF
|
||||
};
|
||||
|
||||
/* eSPI max supported frequency */
|
||||
enum {
|
||||
NPCX_ESPI_MAXFREQ_20 = 0,
|
||||
NPCX_ESPI_MAXFREQ_25 = 1,
|
||||
NPCX_ESPI_MAXFREQ_33 = 2,
|
||||
NPCX_ESPI_MAXFREQ_50 = 3,
|
||||
NPCX_ESPI_MAXFREQ_66 = 4,
|
||||
NPCX_ESPI_MAXFREQ_NOOE = 0xFF
|
||||
};
|
||||
|
||||
/* VW types */
|
||||
enum {
|
||||
ESPI_VW_TYPE_INT_EV, /* Interrupt event */
|
||||
ESPI_VW_TYPE_SYS_EV, /* System Event */
|
||||
ESPI_VW_TYPE_PLT, /* Platform specific */
|
||||
ESPI_VW_TYPE_GPIO, /* General Purpose I/O Expander */
|
||||
ESPI_VW_TYPE_NUM,
|
||||
ESPI_VW_TYPE_NONE = 0xFF
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* Nuvoton internal used only registers */
|
||||
#define NPCX_INTERNAL_CTRL1 REG8(0x400DB000)
|
||||
|
||||
75
include/espi.h
Normal file
75
include/espi.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/* eSPI module for Chrome EC */
|
||||
|
||||
#ifndef __CROS_EC_ESPI_H
|
||||
#define __CROS_EC_ESPI_H
|
||||
|
||||
#include "gpio_signal.h"
|
||||
|
||||
/* Signal through VW */
|
||||
enum espi_vw_signal {
|
||||
VW_SIGNAL_BASE = GPIO_COUNT,
|
||||
VW_SLP_S3_L, /* index 02h (In) */
|
||||
VW_SLP_S4_L,
|
||||
VW_SLP_S5_L,
|
||||
VW_SUS_STAT_L, /* index 03h (In) */
|
||||
VW_PLTRST_L,
|
||||
VW_OOB_RST_WARN,
|
||||
VW_OOB_RST_ACK, /* index 04h (Out) */
|
||||
VW_WAKE_L,
|
||||
VW_PME_L,
|
||||
VW_ERROR_FATAL, /* index 05h (Out) */
|
||||
VW_ERROR_NON_FATAL,
|
||||
/* Merge bit 3/0 into one signal. Need to set them simultaneously */
|
||||
VW_SLAVE_BTLD_STATUS_DONE,
|
||||
VW_SCI_L, /* index 06h (Out) */
|
||||
VW_SMI_L,
|
||||
VW_RCIN_L,
|
||||
VW_HOST_RST_ACK,
|
||||
VW_HOST_RST_WARN, /* index 07h (In) */
|
||||
VW_SUS_ACK, /* index 40h (Out) */
|
||||
VW_SUS_WARN_L, /* index 41h (In) */
|
||||
VW_SUS_PWRDN_ACK_L,
|
||||
VW_SLP_A_L,
|
||||
VW_SLP_LAN, /* index 42h (In) */
|
||||
VW_SLP_WLAN,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif /* __CROS_EC_ESPI_H */
|
||||
Reference in New Issue
Block a user