drivers/espi: ite: Add it51xxx compatibility with it8xxx2 support retained

The driver originally supported only it8xxx2 series. This updates
introduces compatibility allow it to also support it51xxx series
with minimal changes.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
Tim Lin 2025-02-07 14:16:50 +08:00 committed by Benjamin Cabé
commit a62f157118
6 changed files with 95 additions and 13 deletions

View file

@ -5,7 +5,7 @@ config ESPI_IT8XXX2
bool "ITE IT8XXX2 embedded controller ESPI driver"
default y
depends on DT_HAS_ITE_IT8XXX2_ESPI_ENABLED
depends on SOC_IT8XXX2
depends on SOC_IT8XXX2 || SOC_IT51XXX
help
Enable ITE IT8XXX2 ESPI driver.

View file

@ -9,6 +9,7 @@
#include <assert.h>
#include <zephyr/drivers/espi.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/interrupt_controller/wuc_ite_it51xxx.h>
#include <zephyr/drivers/interrupt_controller/wuc_ite_it8xxx2.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/util.h>
@ -21,8 +22,7 @@
#include <zephyr/irq.h>
LOG_MODULE_REGISTER(espi, CONFIG_ESPI_LOG_LEVEL);
#define ESPI_IT8XXX2_GET_GCTRL_BASE \
((struct gctrl_it8xxx2_regs *)DT_REG_ADDR(DT_NODELABEL(gctrl)))
#define ESPI_ITE_GET_GCTRL_BASE ((struct gctrl_ite_ec_regs *)DT_REG_ADDR(DT_NODELABEL(gctrl)))
#define IT8XXX2_ESPI_IRQ DT_INST_IRQ_BY_IDX(0, 0, irq)
#define IT8XXX2_ESPI_VW_IRQ DT_INST_IRQ_BY_IDX(0, 1, irq)
@ -827,9 +827,10 @@ static const struct ec2i_t smfi_settings[] = {
static void smfi_it8xxx2_init(const struct device *dev)
{
const struct espi_it8xxx2_config *const config = dev->config;
struct smfi_it8xxx2_regs *const smfi_reg =
(struct smfi_it8xxx2_regs *)config->base_smfi;
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
struct smfi_ite_ec_regs *const smfi_reg = (struct smfi_ite_ec_regs *)config->base_smfi;
#ifdef CONFIG_SOC_SERIES_IT8XXX2
struct gctrl_ite_ec_regs *const gctrl = ESPI_ITE_GET_GCTRL_BASE;
uint8_t h2ram_offset;
/* Set the host to RAM cycle address offset */
@ -838,6 +839,7 @@ static void smfi_it8xxx2_init(const struct device *dev)
gctrl->GCTRL_H2ROFSR =
(gctrl->GCTRL_H2ROFSR & ~IT8XXX2_ESPI_H2RAM_OFFSET_MASK) |
h2ram_offset;
#endif
#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD
memset(&h2ram_pool[CONFIG_ESPI_PERIPHERAL_HOST_CMD_PARAM_PORT_NUM], 0,
@ -929,12 +931,13 @@ static void pnpcfg_it8xxx2_configure(const struct device *dev,
#define PNPCFG(_s) \
pnpcfg_it8xxx2_configure(dev, _s##_settings, ARRAY_SIZE(_s##_settings))
extern uint8_t _h2ram_pool_start[];
static void pnpcfg_it8xxx2_init(const struct device *dev)
{
const struct espi_it8xxx2_config *const config = dev->config;
struct ec2i_regs *const ec2i = (struct ec2i_regs *)config->base_ec2i;
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
struct gctrl_ite_ec_regs *const gctrl = ESPI_ITE_GET_GCTRL_BASE;
/* The register pair to access PNPCFG is 004Eh and 004Fh */
gctrl->GCTRL_BADRSEL = 0x1;
@ -953,6 +956,15 @@ static void pnpcfg_it8xxx2_init(const struct device *dev)
#if defined(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || \
defined(CONFIG_ESPI_PERIPHERAL_ACPI_SHM_REGION)
PNPCFG(smfi);
#ifdef CONFIG_SOC_SERIES_IT51XXX
uint8_t h2ram_pool_idx;
h2ram_pool_idx = ((uint32_t)_h2ram_pool_start & IT8XXX2_ESPI_H2RAM_BASEADDR_MASK) /
IT8XXX2_ESPI_H2RAM_POOL_SIZE_MAX;
/* H2RAM 4K page select */
ec2i_it8xxx2_write(dev, HOST_INDEX_DSLDC13, h2ram_pool_idx);
#endif
#endif
}
@ -1086,7 +1098,7 @@ static void pmc1_it8xxx2_init(const struct device *dev)
static void port80_it8xxx2_isr(const struct device *dev)
{
struct espi_it8xxx2_data *const data = dev->data;
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
struct gctrl_ite_ec_regs *const gctrl = ESPI_ITE_GET_GCTRL_BASE;
struct espi_event evt = {
ESPI_BUS_PERIPHERAL_NOTIFICATION,
(ESPI_PERIPHERAL_INDEX_0 << 16) | ESPI_PERIPHERAL_DEBUG_PORT80,
@ -1107,7 +1119,7 @@ static void port80_it8xxx2_isr(const struct device *dev)
static void port80_it8xxx2_init(const struct device *dev)
{
ARG_UNUSED(dev);
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
struct gctrl_ite_ec_regs *const gctrl = ESPI_ITE_GET_GCTRL_BASE;
/* Accept Port 80h (and 81h) Cycle */
if (IS_ENABLED(CONFIG_ESPI_IT8XXX2_PORT_81_CYCLE)) {
@ -2395,7 +2407,11 @@ void espi_it8xxx2_enable_trans_irq(const struct device *dev, bool enable)
} else {
irq_disable(IT8XXX2_TRANS_IRQ);
/* Clear pending interrupt */
#ifdef CONFIG_SOC_SERIES_IT51XXX
it51xxx_wuc_clear_status(config->wuc.wucs, config->wuc.mask);
#else
it8xxx2_wuc_clear_status(config->wuc.wucs, config->wuc.mask);
#endif
}
}
@ -2431,7 +2447,7 @@ void espi_it8xxx2_espi_reset_isr(const struct device *port,
#define ESPI_IT8XXX2_ESPI_RESET_PIN 2
static void espi_it8xxx2_enable_reset(void)
{
struct gpio_it8xxx2_regs *const gpio_regs = GPIO_IT8XXX2_REG_BASE;
struct gpio_ite_ec_regs *const gpio_regs = GPIO_ITE_EC_REGS_BASE;
static struct gpio_callback espi_reset_cb;
/* eSPI reset is enabled on GPD2 */
@ -2472,7 +2488,7 @@ static int espi_it8xxx2_init(const struct device *dev)
(struct espi_vw_regs *)config->base_espi_vw;
struct espi_slave_regs *const slave_reg =
(struct espi_slave_regs *)config->base_espi_slave;
struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE;
struct gctrl_ite_ec_regs *const gctrl = ESPI_ITE_GET_GCTRL_BASE;
/* configure VCC detector */
gctrl->GCTRL_RSTS = (gctrl->GCTRL_RSTS &
@ -2539,8 +2555,13 @@ static int espi_it8xxx2_init(const struct device *dev)
slave_reg->ESGCTRL2 |= IT8XXX2_ESPI_TO_WUC_ENABLE;
/* Enable WU42 of WUI */
#ifdef CONFIG_SOC_SERIES_IT51XXX
it51xxx_wuc_clear_status(config->wuc.wucs, config->wuc.mask);
it51xxx_wuc_enable(config->wuc.wucs, config->wuc.mask);
#else
it8xxx2_wuc_clear_status(config->wuc.wucs, config->wuc.mask);
it8xxx2_wuc_enable(config->wuc.wucs, config->wuc.mask);
#endif
/*
* Only register isr here, the interrupt only need to be enabled
* before CPU and RAM clocks gated in the idle function.

View file

@ -1189,6 +1189,31 @@
kso17-gpios = <&gpioc 5 (GPIO_OPEN_DRAIN | GPIO_PULL_UP)>;
};
espi0: espi@f03100 {
compatible = "ite,it8xxx2-espi";
reg = <0x00f03100 0xd8 /* eSPI slave */
0x00f03200 0x9a /* eSPI VW */
0x00f03300 0xd0 /* eSPI Queue 0 */
0x00f03400 0xc0 /* eSPI Queue 1 */
0x00f01200 6 /* EC2I bridge */
0x00f01300 11 /* Host KBC */
0x00f01500 0x100 /* Host PMC */
0x00f01000 0xd1>; /* SMFI */
interrupts = <IT51XXX_IRQ_ESPI IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_ESPI_VW IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_KBC_IBF IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_KBC_OBE IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_PMC1_IBF IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_PCH_P80 IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_PMC2_IBF IRQ_TYPE_LEVEL_HIGH
IT51XXX_IRQ_WKINTD IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&intc>;
wucctrl = <&wuc_wu42>;
#address-cells = <1>;
#size-cells = <1>;
status = "disabled";
};
twd0: watchdog@f04780 {
compatible = "ite,it51xxx-watchdog";
reg = <0x00f04780 0x20>;

View file

@ -267,8 +267,16 @@ struct gctrl_it51xxx_regs {
volatile uint8_t reserved_1d_1f[3];
/* 0x20: Reset Control 5 */
volatile uint8_t GCTRL_RSTC5;
/* 0x21-0x37: reserved_21_37 */
volatile uint8_t reserved_21_37[23];
/* 0x21-0x2f: reserved_21_2f */
volatile uint8_t reserved_21_2f[15];
/* 0x30: Port 80h/81h Status Register */
volatile uint8_t GCTRL_P80H81HSR;
/* 0x31: Port 80h Data Register */
volatile uint8_t GCTRL_P80HDR;
/* 0x32: Port 81h Data Register */
volatile uint8_t GCTRL_P81HDR;
/* 0x33-0x37: reserved_33_37 */
volatile uint8_t reserved_33_37[5];
/* 0x38: Special Control 9 */
volatile uint8_t GCTRL_SPCTRL9;
/* 0x39-0x46: reserved_39_46 */

View file

@ -377,6 +377,19 @@ SECTIONS
__data_region_end = .;
SECTION_DATA_PROLOGUE(.h2ram_pool,(NOLOAD),)
{
/*
* Append h2ram_pool section at the end of used memory, so gap
* due to alignment is still available for newly added variables
*/
. = ALIGN(0x1000);
_h2ram_pool_start = .;
KEEP(*(.h2ram_pool))
_h2ram_pool_end = .;
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
_h2ram_pool_size = ABSOLUTE(_h2ram_pool_end - _h2ram_pool_start);
__kernel_ram_end = .;
__kernel_ram_size = __kernel_ram_end - __kernel_ram_start;

View file

@ -7,6 +7,8 @@
#include <soc_common.h>
#include <zephyr/kernel.h>
#include "soc_espi.h"
static mm_reg_t ecpm_base = DT_REG_ADDR(DT_NODELABEL(ecpm));
/* it51xxx ECPM registers definition */
/* 0x03: PLL Control */
@ -57,12 +59,25 @@ void riscv_idle(enum chip_pll_mode mode, unsigned int key)
csr_clear(mie, MIP_MEIP);
sys_trace_idle();
#ifdef CONFIG_ESPI
/*
* H2RAM feature requires RAM clock to be active. Since the below doze
* mode will disable CPU and RAM clocks, enable eSPI transaction
* interrupt to restore clocks. With this interrupt, EC will not defer
* eSPI bus while transaction is accepted.
*/
espi_ite_ec_enable_trans_irq(ESPI_ITE_SOC_DEV, true);
#endif
/* Chip doze after wfi instruction */
chip_pll_ctrl(mode);
/* Wait for interrupt */
__asm__ volatile("wfi");
#ifdef CONFIG_ESPI
/* CPU has been woken up, the interrupt is no longer needed */
espi_ite_ec_enable_trans_irq(ESPI_ITE_SOC_DEV, false);
#endif
/*
* Enable M-mode external interrupt
* An interrupt can not be fired yet until we enable global interrupt