espi: it8xxx2: enable configuration of Chromebook

This enables the below configuration so the AP and EC are able to
communicate over eSPI:

CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE

Signed-off-by: Dino Li <Dino.Li@ite.com.tw>
This commit is contained in:
Dino Li 2021-12-16 14:14:00 +08:00 committed by Anas Nashif
commit 36164c29c1
8 changed files with 434 additions and 7 deletions

View file

@ -21,6 +21,101 @@ config ESPI_PERIPHERAL_HOST_IO
config ESPI_PERIPHERAL_DEBUG_PORT_80
default y
config ESPI_PERIPHERAL_EC_HOST_CMD
default y
choice IT8XXX2_H2RAM_HC_SIZE_CHOICE
prompt "H2RAM space for ec host command"
default IT8XXX2_H2RAM_HC_SIZE_256
depends on ESPI_PERIPHERAL_EC_HOST_CMD
config IT8XXX2_H2RAM_HC_SIZE_16
bool "16"
config IT8XXX2_H2RAM_HC_SIZE_32
bool "32"
config IT8XXX2_H2RAM_HC_SIZE_64
bool "64"
config IT8XXX2_H2RAM_HC_SIZE_128
bool "128"
config IT8XXX2_H2RAM_HC_SIZE_256
bool "256"
config IT8XXX2_H2RAM_HC_SIZE_512
bool "512"
config IT8XXX2_H2RAM_HC_SIZE_1024
bool "1024"
config IT8XXX2_H2RAM_HC_SIZE_2048
bool "2048"
endchoice
config ESPI_IT8XXX2_HC_H2RAM_SIZE
int
depends on ESPI_PERIPHERAL_EC_HOST_CMD
default 16 if IT8XXX2_H2RAM_HC_SIZE_16
default 32 if IT8XXX2_H2RAM_HC_SIZE_32
default 64 if IT8XXX2_H2RAM_HC_SIZE_64
default 128 if IT8XXX2_H2RAM_HC_SIZE_128
default 256 if IT8XXX2_H2RAM_HC_SIZE_256
default 512 if IT8XXX2_H2RAM_HC_SIZE_512
default 1024 if IT8XXX2_H2RAM_HC_SIZE_1024
default 2048 if IT8XXX2_H2RAM_HC_SIZE_2048
config ESPI_PERIPHERAL_ACPI_SHM_REGION
default y
choice IT8XXX2_H2RAM_ACPI_SHM_SIZE_CHOICE
prompt "H2RAM space for ACPI shared memory region"
default IT8XXX2_H2RAM_ACPI_SHM_SIZE_256
depends on ESPI_PERIPHERAL_ACPI_SHM_REGION
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_16
bool "16"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_32
bool "32"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_64
bool "64"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_128
bool "128"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_256
bool "256"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_512
bool "512"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_1024
bool "1024"
config IT8XXX2_H2RAM_ACPI_SHM_SIZE_2048
bool "2048"
endchoice
config ESPI_IT8XXX2_ACPI_SHM_H2RAM_SIZE
int
depends on ESPI_PERIPHERAL_ACPI_SHM_REGION
default 16 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_16
default 32 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_32
default 64 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_64
default 128 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_128
default 256 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_256
default 512 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_512
default 1024 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_1024
default 2048 if IT8XXX2_H2RAM_ACPI_SHM_SIZE_2048
config ESPI_PERIPHERAL_CUSTOM_OPCODE
default y
config ESPI_FLASH_CHANNEL
default y

View file

@ -26,6 +26,7 @@ LOG_MODULE_REGISTER(espi, CONFIG_ESPI_LOG_LEVEL);
#define IT8XXX2_KBC_OBE_IRQ DT_INST_IRQ_BY_IDX(0, 3, irq)
#define IT8XXX2_PMC1_IBF_IRQ DT_INST_IRQ_BY_IDX(0, 4, irq)
#define IT8XXX2_PORT_80_IRQ DT_INST_IRQ_BY_IDX(0, 5, irq)
#define IT8XXX2_PMC2_IBF_IRQ DT_INST_IRQ_BY_IDX(0, 6, irq)
/* General Capabilities and Configuration 1 */
#define IT8XXX2_ESPI_MAX_FREQ_MASK GENMASK(2, 0)
@ -72,6 +73,7 @@ struct espi_it8xxx2_config {
uintptr_t base_ec2i;
uintptr_t base_kbc;
uintptr_t base_pmc;
uintptr_t base_smfi;
};
struct espi_it8xxx2_data {
@ -153,6 +155,125 @@ static const struct ec2i_t pmc1_settings[] = {
{HOST_INDEX_LDA, 0x01},
};
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
#define IT8XXX2_ESPI_HC_DATA_PORT_MSB \
((CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM >> 8) & 0xff)
#define IT8XXX2_ESPI_HC_DATA_PORT_LSB \
(CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM & 0xff)
#define IT8XXX2_ESPI_HC_CMD_PORT_MSB \
(((CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) >> 8) & 0xff)
#define IT8XXX2_ESPI_HC_CMD_PORT_LSB \
((CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) & 0xff)
static const struct ec2i_t pmc2_settings[] = {
/* Select logical device 12h(PM2 host command) */
{HOST_INDEX_LDN, LDN_PMC2},
/* I/O Port Base Address (data/command ports) */
{HOST_INDEX_IOBAD0_MSB, IT8XXX2_ESPI_HC_DATA_PORT_MSB},
{HOST_INDEX_IOBAD0_LSB, IT8XXX2_ESPI_HC_DATA_PORT_LSB},
{HOST_INDEX_IOBAD1_MSB, IT8XXX2_ESPI_HC_CMD_PORT_MSB},
{HOST_INDEX_IOBAD1_LSB, IT8XXX2_ESPI_HC_CMD_PORT_LSB},
/* Set IRQ=00h for logical device */
{HOST_INDEX_IRQNUMX, 0x00},
/* Enable logical device */
{HOST_INDEX_LDA, 0x01},
};
#endif
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || \
defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
/*
* Host to RAM (H2RAM) memory mapping.
* This feature allows host access EC's memory directly by eSPI I/O cycles.
* Mapping range is 4K bytes and base address is adjustable.
* Eg. the I/O cycle 800h~8ffh from host can be mapped to x800h~x8ffh.
* Linker script of h2ram.ld will make the pool 4K aligned.
*/
#define IT8XXX2_ESPI_H2RAM_POOL_SIZE 0x1000
static uint8_t h2ram_pool[IT8XXX2_ESPI_H2RAM_POOL_SIZE]
__attribute__((section(".h2ram_pool")));
#if defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
#define H2RAM_ACPI_SHM_MAX ((CONFIG_ESPI_IT8XXX2_ACPI_SHM_H2RAM_SIZE) + \
(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM))
#if (H2RAM_ACPI_SHM_MAX > IT8XXX2_ESPI_H2RAM_POOL_SIZE)
#error "ACPI shared memory region out of h2ram"
#endif
#endif /* CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION */
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD)
#define H2RAM_EC_HOST_CMD_MAX ((CONFIG_ESPI_IT8XXX2_HC_H2RAM_SIZE) + \
(CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM))
#if (H2RAM_EC_HOST_CMD_MAX > IT8XXX2_ESPI_H2RAM_POOL_SIZE)
#error "EC host command parameters out of h2ram"
#endif
#endif /* CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD */
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) && \
defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
#if (MIN(H2RAM_ACPI_SHM_MAX, H2RAM_EC_HOST_CMD_MAX) > \
MAX(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM, \
CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM))
#error "ACPI and HC sections of h2ram overlap"
#endif
#endif
#define H2RAM_WINDOW_SIZE(ram_size) ((find_msb_set((ram_size) / 16) - 1) & 0x7)
static const struct ec2i_t smfi_settings[] = {
/* Select logical device 0Fh(SMFI) */
{HOST_INDEX_LDN, LDN_SMFI},
/* Internal RAM base address on eSPI I/O space */
{HOST_INDEX_DSLDC6, 0x00},
/* Enable H2RAM eSPI I/O cycle */
{HOST_INDEX_DSLDC7, 0x01},
/* Enable logical device */
{HOST_INDEX_LDA, 0x01},
};
static void smfi_it8xxx2_init(const struct device *dev)
{
const struct espi_it8xxx2_config *const config = dev->config;
struct flash_it8xxx2_regs *const smfi_reg =
(struct flash_it8xxx2_regs *)config->base_smfi;
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
uint8_t h2ram_offset;
/* Set the host to RAM cycle address offset */
h2ram_offset = ((uint32_t)h2ram_pool & 0xffff) /
IT8XXX2_ESPI_H2RAM_POOL_SIZE;
gctrl->GCTRL_H2ROFSR |= h2ram_offset;
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
memset(&h2ram_pool[CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM], 0,
CONFIG_ESPI_IT8XXX2_HC_H2RAM_SIZE);
/* Set host RAM window 0 base address */
smfi_reg->SMFI_HRAMW0BA =
(CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM >> 4) & 0xff;
/* Set host RAM window 0 size. (allow R/W) */
smfi_reg->SMFI_HRAMW0AAS =
H2RAM_WINDOW_SIZE(CONFIG_ESPI_IT8XXX2_HC_H2RAM_SIZE);
/* Enable window 0, H2RAM through IO cycle */
smfi_reg->SMFI_HRAMWC |= (SMFI_H2RAMPS | SMFI_H2RAMW0E);
#endif
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
memset(&h2ram_pool[CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM], 0,
CONFIG_ESPI_IT8XXX2_ACPI_SHM_H2RAM_SIZE);
/* Set host RAM window 1 base address */
smfi_reg->SMFI_HRAMW1BA =
(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM >> 4) & 0xff;
/* Set host RAM window 1 size. (read-only) */
smfi_reg->SMFI_HRAMW1AAS =
H2RAM_WINDOW_SIZE(CONFIG_ESPI_IT8XXX2_ACPI_SHM_H2RAM_SIZE) |
SMFI_HRAMWXWPE_ALL;
/* Enable window 1, H2RAM through IO cycle */
smfi_reg->SMFI_HRAMWC |= (SMFI_H2RAMPS | SMFI_H2RAMW1E);
#endif
}
#endif /* CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD ||
* CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
*/
static void ec2i_it8xxx2_wait_status_cleared(const struct device *dev,
uint8_t mask)
{
@ -230,6 +351,13 @@ static void pnpcfg_it8xxx2_init(const struct device *dev)
if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO)) {
PNPCFG(pmc1);
}
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
PNPCFG(pmc2);
#endif
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || \
defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
PNPCFG(smfi);
#endif
}
/* KBC (port 60h/64h) */
@ -387,6 +515,41 @@ static void port80_it8xxx2_init(const struct device *dev)
}
#endif
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
/* PMC 2 (Host command port CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM) */
static void pmc2_it8xxx2_ibf_isr(const struct device *dev)
{
const struct espi_it8xxx2_config *const config = dev->config;
struct espi_it8xxx2_data *const data = dev->data;
struct pmc_regs *const pmc_reg = (struct pmc_regs *)config->base_pmc;
struct espi_event evt = {
ESPI_BUS_PERIPHERAL_NOTIFICATION,
ESPI_PERIPHERAL_EC_HOST_CMD,
ESPI_PERIPHERAL_NODATA
};
/* Set processing flag before reading command byte */
pmc_reg->PM2STS |= PMC_PM2STS_GPF;
evt.evt_data = pmc_reg->PM2DI;
espi_send_callbacks(&data->callbacks, dev, evt);
}
static void pmc2_it8xxx2_init(const struct device *dev)
{
const struct espi_it8xxx2_config *const config = dev->config;
struct pmc_regs *const pmc_reg = (struct pmc_regs *)config->base_pmc;
/* Dedicated interrupt for PMC2 */
pmc_reg->MBXCTRL |= PMC_MBXCTRL_DINT;
/* Enable pmc2 input buffer full interrupt */
pmc_reg->PM2CTL |= PMC_PM2CTL_IBFIE;
IRQ_CONNECT(IT8XXX2_PMC2_IBF_IRQ, 0, pmc2_it8xxx2_ibf_isr,
DEVICE_DT_INST_GET(0), 0);
irq_enable(IT8XXX2_PMC2_IBF_IRQ);
}
#endif
/* eSPI api functions */
#define VW_CHAN(signal, index, level, valid) \
[signal] = {.vw_index = index, .level_mask = level, .valid_mask = valid}
@ -616,10 +779,30 @@ static int espi_it8xxx2_read_lpc_request(const struct device *dev,
case EACPI_READ_STS:
*data = pmc_reg->PM1STS;
break;
#ifdef CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION
case EACPI_GET_SHARED_MEMORY:
*data = (uint32_t)&h2ram_pool[
CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION_PORT_NUM];
break;
#endif /* CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION */
default:
return -EINVAL;
}
} else {
}
#ifdef CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE
else if (op >= ECUSTOM_START_OPCODE && op <= ECUSTOM_MAX_OPCODE) {
switch (op) {
case ECUSTOM_HOST_CMD_GET_PARAM_MEMORY:
*data = (uint32_t)&h2ram_pool[
CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM];
break;
default:
return -EINVAL;
}
}
#endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
else {
return -ENOTSUP;
}
@ -695,7 +878,33 @@ static int espi_it8xxx2_write_lpc_request(const struct device *dev,
default:
return -EINVAL;
}
} else {
}
#ifdef CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE
else if (op >= ECUSTOM_START_OPCODE && op <= ECUSTOM_MAX_OPCODE) {
struct pmc_regs *const pmc_reg =
(struct pmc_regs *)config->base_pmc;
switch (op) {
/* Enable/Disable PMC1 (port 62h/66h) interrupt */
case ECUSTOM_HOST_SUBS_INTERRUPT_EN:
if (*data) {
pmc_reg->PM1CTL |= PMC_PM1CTL_IBFIE;
} else {
pmc_reg->PM1CTL &= ~PMC_PM1CTL_IBFIE;
}
break;
case ECUSTOM_HOST_CMD_SEND_RESULT:
/* Write result to data output port (set OBF status) */
pmc_reg->PM2DO = (*data & 0xff);
/* Clear processing flag */
pmc_reg->PM2STS &= ~PMC_PM2STS_GPF;
break;
default:
return -EINVAL;
}
}
#endif /* CONFIG_ESPI_PERIPHERAL_CUSTOM_OPCODE */
else {
return -ENOTSUP;
}
@ -1606,6 +1815,7 @@ static const struct espi_it8xxx2_config espi_it8xxx2_config_0 = {
.base_ec2i = DT_INST_REG_ADDR_BY_IDX(0, 4),
.base_kbc = DT_INST_REG_ADDR_BY_IDX(0, 5),
.base_pmc = DT_INST_REG_ADDR_BY_IDX(0, 6),
.base_smfi = DT_INST_REG_ADDR_BY_IDX(0, 7),
};
DEVICE_DT_INST_DEFINE(0, &espi_it8xxx2_init, NULL,
@ -1642,6 +1852,14 @@ static int espi_it8xxx2_init(const struct device *dev)
/* Accept Port 80h Cycle */
port80_it8xxx2_init(dev);
#endif
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || \
defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
smfi_it8xxx2_init(dev);
#endif
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
/* enable pmc2 for host command port */
pmc2_it8xxx2_init(dev);
#endif
/* Reset vwidx_cached_flag[] at initialization */
espi_it8xxx2_reset_vwidx_cache(dev);