diff --git a/drivers/espi/Kconfig.rts5912 b/drivers/espi/Kconfig.rts5912 index 2c6d30d682c..1459d19db02 100644 --- a/drivers/espi/Kconfig.rts5912 +++ b/drivers/espi/Kconfig.rts5912 @@ -10,6 +10,9 @@ config ESPI_RTS5912 if ESPI_RTS5912 +config ESPI_PERIPHERAL_EC_HOST_CMD + default y + config ESPI_PERIPHERAL_DEBUG_PORT_80 default y diff --git a/drivers/espi/espi_realtek_rts5912.c b/drivers/espi/espi_realtek_rts5912.c index 50cbbcfebc0..44487e40c73 100644 --- a/drivers/espi/espi_realtek_rts5912.c +++ b/drivers/espi/espi_realtek_rts5912.c @@ -17,6 +17,8 @@ LOG_MODULE_REGISTER(espi, CONFIG_ESPI_LOG_LEVEL); #include "espi_utils.h" +#include "reg/reg_acpi.h" +#include "reg/reg_emi.h" #include "reg/reg_espi.h" #include "reg/reg_port80.h" @@ -26,6 +28,14 @@ struct espi_rts5912_config { volatile struct espi_reg *const espi_reg; uint32_t espislv_clk_grp; uint32_t espislv_clk_idx; +#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD + volatile struct acpi_reg *const promt0_reg; + uint32_t promt0_clk_grp; + uint32_t promt0_clk_idx; + volatile struct emi_reg *const emi0_reg; + uint32_t emi0_clk_grp; + uint32_t emi0_clk_idx; +#endif #ifdef CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80 volatile struct port80_reg *const port80_reg; uint32_t port80_clk_grp; @@ -51,6 +61,88 @@ struct espi_rts5912_data { #endif }; +/* + * ========================================================================= + * ESPI Peripheral EC Host Command (Promt0) + * ========================================================================= + */ + +#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD + +#define ESPI_RTK_PERIPHERAL_HOST_CMD_PARAM_SIZE 256 + +static uint8_t ec_host_cmd_sram[ESPI_RTK_PERIPHERAL_HOST_CMD_PARAM_SIZE] __aligned(256); + +static void espi_setup_host_cmd_shm(const struct espi_rts5912_config *const espi_config) +{ + volatile struct emi_reg *const emi0_reg = espi_config->emi0_reg; + + emi0_reg->SAR = (uint32_t)&ec_host_cmd_sram[0]; +} + +static void promt0_ibf_isr(const struct device *dev) +{ + const struct espi_rts5912_config *const espi_config = dev->config; + volatile struct acpi_reg *const promt0_reg = espi_config->promt0_reg; + struct espi_rts5912_data *data = dev->data; + struct espi_event evt = {.evt_type = ESPI_BUS_PERIPHERAL_NOTIFICATION, + .evt_details = ESPI_PERIPHERAL_EC_HOST_CMD, + .evt_data = ESPI_PERIPHERAL_NODATA}; + + promt0_reg->STS |= ACPI_STS_STS0; + evt.evt_data = (uint8_t)promt0_reg->IB; + espi_send_callbacks(&data->callbacks, dev, evt); +} + +static int espi_promt0_setup(const struct device *dev) +{ + const struct espi_rts5912_config *const espi_config = dev->config; + struct rts5912_sccon_subsys sccon; + volatile struct acpi_reg *const promt0_reg = espi_config->promt0_reg; + int rc; + + if (!device_is_ready(espi_config->clk_dev)) { + LOG_ERR("Promt0 clock not ready"); + return -ENODEV; + } + + sccon.clk_grp = espi_config->promt0_clk_grp; + sccon.clk_idx = espi_config->promt0_clk_idx; + + rc = clock_control_on(espi_config->clk_dev, (clock_control_subsys_t)&sccon); + if (rc != 0) { + LOG_ERR("Promt0 clock control on failed"); + return rc; + } + + promt0_reg->STS = 0; + + if (promt0_reg->STS & ACPI_STS_IBF) { + rc = promt0_reg->IB; + } + + if (promt0_reg->STS & ACPI_STS_IBF) { + promt0_reg->IB |= ACPI_IB_IBCLR; + } + + promt0_reg->PTADDR = + CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM | (0x04 << ACPI_PTADDR_OFFSET_Pos); + promt0_reg->VWCTRL1 = ACPI_VWCTRL1_ACTEN; + promt0_reg->INTEN = ACPI_INTEN_IBFINTEN; + + NVIC_ClearPendingIRQ(DT_IRQ_BY_NAME(DT_DRV_INST(0), promt0_ibf, irq)); + + /* IBF */ + IRQ_CONNECT(DT_IRQ_BY_NAME(DT_DRV_INST(0), promt0_ibf, irq), + DT_IRQ_BY_NAME(DT_DRV_INST(0), promt0_ibf, priority), promt0_ibf_isr, + DEVICE_DT_GET(DT_DRV_INST(0)), 0); + irq_enable(DT_IRQ_BY_NAME(DT_DRV_INST(0), promt0_ibf, irq)); + + return 0; +} + +#endif /* CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD */ + /* * ========================================================================= * ESPI Peripheral Debug Port 80 @@ -1635,6 +1727,16 @@ static int espi_rts5912_init(const struct device *dev) /* Setup eSPI bus reset */ espi_bus_reset_setup(dev); +#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD + rc = espi_promt0_setup(dev); + if (rc != 0) { + LOG_ERR("eSPI Promt0 setup failed"); + goto exit; + } + + espi_setup_host_cmd_shm(espi_config); +#endif + #ifdef CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80 /* Setup Port80 */ rc = espi_peri_ch_port80_setup(dev); @@ -1679,6 +1781,15 @@ static const struct espi_rts5912_config espi_rts5912_config = { .espi_reg = (volatile struct espi_reg *const)DT_INST_REG_ADDR_BY_NAME(0, espi_target), .espislv_clk_grp = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), espi_target, clk_grp), .espislv_clk_idx = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), espi_target, clk_idx), +#ifdef CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD + .promt0_reg = (volatile struct acpi_reg *const)DT_INST_REG_ADDR_BY_NAME(0, promt0), + .promt0_clk_grp = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), promt0, clk_grp), + .promt0_clk_idx = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), promt0, clk_idx), + + .emi0_reg = (volatile struct emi_reg *const)DT_INST_REG_ADDR_BY_NAME(0, emi0), + .emi0_clk_grp = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), emi0, clk_grp), + .emi0_clk_idx = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), emi0, clk_idx), +#endif #ifdef CONFIG_ESPI_PERIPHERAL_DEBUG_PORT_80 .port80_reg = (volatile struct port80_reg *const)DT_INST_REG_ADDR_BY_NAME(0, port80), .port80_clk_grp = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(0), port80, clk_grp), diff --git a/soc/realtek/ec/rts5912/reg/reg_acpi.h b/soc/realtek/ec/rts5912/reg/reg_acpi.h new file mode 100644 index 00000000000..bb1747c2fff --- /dev/null +++ b/soc/realtek/ec/rts5912/reg/reg_acpi.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025 Realtek, SIBG-SD7 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_ACPI_H +#define ZEPHYR_SOC_REALTEK_RTS5912_REG_ACPI_H + +struct acpi_reg { + uint32_t STS; + uint32_t IB; + uint32_t OB; + uint32_t PTADDR; + uint32_t INTEN; + uint32_t VWCTRL0; + uint32_t VWCTRL1; +}; + +/* STS */ +#define ACPI_STS_OBF BIT(0) +#define ACPI_STS_IBF BIT(1) +#define ACPI_STS_STS0 BIT(2) +#define ACPI_STS_CMDSEL BIT(3) +#define ACPI_STS_BURST BIT(4) +#define ACPI_STS_STS2 BIT(5) +#define ACPI_STS_STS3 BIT(6) +#define ACPI_STS_STS4 BIT(7) + +/* IB */ +#define ACPI_IB_IBDAT_Pos (0UL) +#define ACPI_IB_IBDAT_Msk GENMASK(7, 0) +#define ACPI_IB_IBCLR BIT(8) + +/* OB */ +#define ACPI_OB_OBDAT_Pos (0UL) +#define ACPI_OB_OBDAT_Msk GENMASK(7, 0) +#define ACPI_OB_OBCLR BIT(8) + +/* PTADDR */ +#define ACPI_PTADDR_ADDR_Pos (0UL) +#define ACPI_PTADDR_ADDR_Msk GENMASK(11, 0) +#define ACPI_PTADDR_OFFSET_Pos (12UL) +#define ACPI_PTADDR_OFFSET_Msk GENMASK(14, 12) + +/* INTEN */ +#define ACPI_INTEN_OBFINTEN BIT(0) +#define ACPI_INTEN_IBFINTEN BIT(1) + +/* VWCTRL0 */ +#define ACPI_VWCTRL0_IRQEN BIT(0) +#define ACPI_VWCTRL0_TGLV BIT(1) + +/* VWCTRL1 */ +#define ACPI_VWCTRL1_IRQNUM_Pos (0UL) +#define ACPI_VWCTRL1_IRQNUM_Msk GENMASK(7, 0) +#define ACPI_VWCTRL1_ACTEN BIT(8) + +#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_ACPI_H */ diff --git a/soc/realtek/ec/rts5912/reg/reg_emi.h b/soc/realtek/ec/rts5912/reg/reg_emi.h new file mode 100644 index 00000000000..41c18e3c1bf --- /dev/null +++ b/soc/realtek/ec/rts5912/reg/reg_emi.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2025 Realtek, SIBG-SD7 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_EMI_H +#define ZEPHYR_SOC_REALTEK_RTS5912_REG_EMI_H + +struct emi_reg { + uint32_t CFG; + uint32_t INTCTRL; + uint32_t IRQNUM; + uint32_t SAR; + uint32_t INTSTS; + uint32_t STS; +}; + +#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_EMI_H */