Yu-Ping Wu has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85888?usp=email )
Change subject: soc/mediatek/mt8196: Initialize MCUPM ......................................................................
soc/mediatek/mt8196: Initialize MCUPM
Load MCUPM firmware and boot up MCUPM in ramstage.
It takes 54 ms to load mcupm.bin.
coreboot logs: CBFS: Found 'mcupm.bin' @0x37a80 size 0xdbda in mcache @0xfffdd308 mtk_init_mcu: Loaded (and reset) mcupm.bin in 54 msecs (486931 bytes)
TEST=Build pass and we can see the mcupm logs after reset releases. BUG=b:317009620
Change-Id: I223f245d384f32d54f6170a28b29573638f77296 Signed-off-by: Agogo Huang agogo.huang@mediatek.corp-partner.google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85888 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Yidi Lin yidilin@google.com Reviewed-by: Yu-Ping Wu yupingso@google.com --- M src/soc/mediatek/mt8196/Kconfig M src/soc/mediatek/mt8196/Makefile.mk M src/soc/mediatek/mt8196/include/soc/addressmap.h A src/soc/mediatek/mt8196/include/soc/mcupm_plat.h A src/soc/mediatek/mt8196/mcupm.c M src/soc/mediatek/mt8196/soc.c 6 files changed, 235 insertions(+), 1 deletion(-)
Approvals: build bot (Jenkins): Verified Yu-Ping Wu: Looks good to me, approved Yidi Lin: Looks good to me, approved
diff --git a/src/soc/mediatek/mt8196/Kconfig b/src/soc/mediatek/mt8196/Kconfig index 014b596..6d7ea68 100644 --- a/src/soc/mediatek/mt8196/Kconfig +++ b/src/soc/mediatek/mt8196/Kconfig @@ -57,4 +57,10 @@ help The file name of the MediaTek GPUEB firmware.
+config MCUPM_FIRMWARE + string + default "mcupm.bin" + help + The file name of the MediaTek MCUPM firmware. + endif diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index a287949..073f67e 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -53,7 +53,7 @@ ramstage-y += ../common/emi.c ramstage-y += gpueb.c ramstage-y += l2c_ops.c -ramstage-y += ../common/mcu.c +ramstage-y += ../common/mcu.c mcupm.c ramstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c ramstage-$(CONFIG_PCI) += ../common/pcie.c pcie.c ramstage-$(CONFIG_COMMONLIB_STORAGE_MMC) += msdc.c @@ -80,6 +80,7 @@ $(CONFIG_DPM_DM_FIRMWARE) \ $(CONFIG_DPM_PM_FIRMWARE) \ $(CONFIG_GPUEB_FIRMWARE) \ + $(CONFIG_MCUPM_FIRMWARE) \ $(CONFIG_SSPM_FIRMWARE) \ $(CONFIG_SPM_FIRMWARE)
diff --git a/src/soc/mediatek/mt8196/include/soc/addressmap.h b/src/soc/mediatek/mt8196/include/soc/addressmap.h index 1ec3c86..6189a8a 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -6,6 +6,7 @@ enum { MCUSYS_BASE = 0x0C000000, MCUPM_CFG_BASE = 0x0C240000, + MCUPM_SRAM_BASE = 0x0C250000, BUS_TRACE_MONITOR_BASE = 0x0D040000, IO_PHYS = 0x10000000, MFGSYS_BASE = 0x40000000, @@ -45,6 +46,7 @@ APINFRA_IO_AO_DEBUG_BASE = IO_PHYS + 0x00155000, APINFRA_IO_CTRL_AO_BCRM_BASE = IO_PHYS + 0x00156000, APINFRA_IO_CTRL_AO_DEBUG_BASE = IO_PHYS + 0x00157000, + DEVAPC_INFRA_SECU_AO_BASE = IO_PHYS + 0x001C8000, DRAMC_CHA_AO_BASE = IO_PHYS + 0x00230000, APINFRA_DRAMC_AO_DEBUG_BASE = IO_PHYS + 0x002F1000, EMI0_BASE = IO_PHYS + 0x00469000, diff --git a/src/soc/mediatek/mt8196/include/soc/mcupm_plat.h b/src/soc/mediatek/mt8196/include/soc/mcupm_plat.h new file mode 100644 index 0000000..53ec241 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/mcupm_plat.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_INCLUDE_SOC_MCUPM_PLAT_H__ +#define __SOC_MEDIATEK_MT8196_INCLUDE_SOC_MCUPM_PLAT_H__ + +#include <soc/addressmap.h> +#include <soc/mcupm_plat.h> +#include <types.h> + +#define MCUPM_SW_RSTN (MCUCFG_BASE + 0x00240000) +#define CLK_CFG_14 (CKSYS_BASE + 0x000000F0) + +/* + * mcusys_par_wrap config + */ +/* CPU_EB_CLK_SRC_CONFIG */ +#define CPUEB_CLK_SRC (MCUCFG_BASE + 0x000002E8) + +#define CPUEB_SPMC_STATUS (MCUCFG_BASE + 0x00000B48) +#define CPUEB_FSM_STATE_ON 0xF +#define CPUEB_FSM_STATE_OFF 0x0 +#define CPUEB_FSM_STATE_RET 0x1D +#define CPUEB_FSM_STATE_FUNC_RET 0x13 + +#define CPUEB_SPMC_SEL (MCUCFG_BASE + 0x00000B4C) + +#define MCU_PORT_SET_W1C_0 (IFRBUS_AO_REG_BUS_BASE + 0x00000708) +#define CPUEB_PROTECT_EN_0 BIT(8) +#define CPUEB_PROTECT_EN_1 BIT(9) +#define MCU_PORT_SET_R0_0 (IFRBUS_AO_REG_BUS_BASE + 0x0000070C) +#define CPUEB_PROTECT_RDY_0 BIT(8) +#define CPUEB_PROTECT_RDY_1 BIT(9) + +/* + * SPM config: + * Enable register access key, POWERON_CONFIG_EN = 0x0B160001 + */ +#define POWERON_CONFIG_EN_MCU (SPM_BASE + 0x000) +#define SPM_PROJECT_CODE 0xB16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) +/* POWERON_CONFIG_EN */ +#define BCLK_CG_EN_LSB BIT(0) +/* CPUEB SPMC Control */ +/* SPM and MCUPM SPMC sideband control */ +#define SPM_MCUPM_SPMC_CON (SPM_BASE + 0x288) +/* 1'b0, SPM power state, 0: invalid, 1: valid */ +#define CPUEB_STATE_VALID BIT(0) +/* 1'b0, power state request for CPUEB */ +#define REQ_PWR_ON BIT(1) +/* 1'b0, memory retention state request for CPUEB */ +#define REQ_MEM_RET BIT(2) +/* 1'b0, spmc finish operation, 0:unfinish, 1:finish */ +#define CPUEB_STATE_FINISH_ACK BIT(31) + +/* 512K Bytes */ +#define MCUPM_SRAM_SIZE (512 * KiB) + +/* GPR */ +#define MCUPM_GPR_SIZE 0x00000070 /* 112 Bytes */ +/* IPI */ +#define IPI_NUMBER 16 +#define IPI_MBOX_TOTAL IPI_NUMBER + +/* MCUPM REG */ +#define MCUPM_CFGREG_SW_RSTN_SW_RSTN BIT(0) +#define MCUPM_CFGREG_SW_RSTN_DMA_BUSY_MASK (BIT(1)|BIT(2)|BIT(3)|BIT(4)) + +#define DEVAPC_INFRA_SECU_AO_SEC_REPLACE_0 (DEVAPC_INFRA_SECU_AO_BASE + 0x0300) +#define POLLING_MCU_RETRY_COUNTS 10 +#define POLLING_ACK_RETRY_COUNTS 10 +#define ABNORMALBOOT_REG_STATUS 0x0 +#define WARMBOOT_REG_STATUS 0x0 +#define MCUPM_RSTN_RESET 0x1F +#define MCUPM_RSTN_RSTN_INIT 0x0 + +#define CPUEB_SPMC_STATUS_OFFSET 3 +#define CPUEB_SPMC_STATUS_MASK 0x3F + +#define SRAM_GPR_SIZE 0x4 /* 4 Bytes */ + +#define MBOX_SLOT_SIZE 0x4 +/* 0x14 = 20 slots = 20*4Bytes = 80 Bytes */ +#define SRAM_SLOT_NUM 0x14 +#define PIN_S_NUM SRAM_SLOT_NUM +#define PIN_R_NUM SRAM_SLOT_NUM +#define MBOX_TABLE_NUM (PIN_S_NUM + PIN_R_NUM) + +#define GPR_BASE_ADDR_MCU(x) (MCUPM_SRAM_BASE + \ + MCUPM_SRAM_SIZE - \ + (IPI_MBOX_TOTAL * MBOX_TABLE_NUM * MBOX_SLOT_SIZE) - \ + MCUPM_GPR_SIZE + \ + ((x) * SRAM_GPR_SIZE)) + +#define ABNORMALBOOT_REG GPR_BASE_ADDR_MCU(1) +#define WARMBOOT_REG GPR_BASE_ADDR_MCU(23) + +#endif /* __SOC_MEDIATEK_MT8196_INCLUDE_SOC_MCUPM_PLAT_H__ */ diff --git a/src/soc/mediatek/mt8196/mcupm.c b/src/soc/mediatek/mt8196/mcupm.c new file mode 100644 index 0000000..193ecb5 --- /dev/null +++ b/src/soc/mediatek/mt8196/mcupm.c @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <console/console.h> +#include <delay.h> +#include <device/mmio.h> +#include <soc/mcu_common.h> +#include <soc/mcupm.h> +#include <soc/mcupm_plat.h> +#include <soc/symbols.h> + +static int eb_sleep_protect(void) +{ + /* Set MCU_PORT_SET_W1C_0[9:8] = 2'b11 */ + setbits32p(MCU_PORT_SET_W1C_0, CPUEB_PROTECT_EN_0 | CPUEB_PROTECT_EN_1); + + /* Poll MCU_PORT_SET_R0_0[9:8] = 2'b00 */ + if (!retry(POLLING_MCU_RETRY_COUNTS, + (read32p(MCU_PORT_SET_R0_0) & + (CPUEB_PROTECT_RDY_0 | CPUEB_PROTECT_RDY_1)) == 0, udelay(1))) { + printk(BIOS_ERR, + "[EB_SPMC] CPUEB_PROTECT_RDY not set after %d us, value %#x\n", + POLLING_MCU_RETRY_COUNTS, read32p(MCU_PORT_SET_R0_0)); + return -1; + } + + return 0; +} + +static int set_cpueb_state(bool state_valid) +{ + if (state_valid) + setbits32p(SPM_MCUPM_SPMC_CON, CPUEB_STATE_VALID); + else + clrbits32p(SPM_MCUPM_SPMC_CON, CPUEB_STATE_VALID); + + if (!retry(POLLING_ACK_RETRY_COUNTS, + ((read32p(SPM_MCUPM_SPMC_CON) & CPUEB_STATE_FINISH_ACK) != 0) == state_valid, + udelay(1))) { + printk(BIOS_ERR, "[EB_SPMC] Polling ACK timeout, %#x\n", + read32p(SPM_MCUPM_SPMC_CON)); + return -1; + } + + return 0; +} + +static int eb_spmc_spm(void) +{ + /* Unlock SPM POWERON_CONFIG_EN */ + setbits32p(POWERON_CONFIG_EN_MCU, SPM_REGWR_CFG_KEY | BCLK_CG_EN_LSB); + + /* Set REQ_PWR_ON = 1 and REQ_MEM_RET = 0 */ + setbits32p(SPM_MCUPM_SPMC_CON, REQ_PWR_ON); + + clrbits32p(SPM_MCUPM_SPMC_CON, REQ_MEM_RET); + + /* Set CPUEB_STATE_VALID = 1 */ + if (set_cpueb_state(true)) + return -1; + + /* Set CPUEB_STATE_VALID = 0 */ + if (set_cpueb_state(false)) + return -1; + + return eb_sleep_protect(); +} + +static int eb_spmc(void) +{ + uint32_t spmc_status = (read32p(CPUEB_SPMC_STATUS) >> CPUEB_SPMC_STATUS_OFFSET) & + CPUEB_SPMC_STATUS_MASK; + int ret; + + switch (spmc_status) { + case CPUEB_FSM_STATE_OFF: + case CPUEB_FSM_STATE_ON: + case CPUEB_FSM_STATE_RET: + case CPUEB_FSM_STATE_FUNC_RET: + printk(BIOS_INFO, "[EB_SPMC] spmc_status = %#x\n", spmc_status); + ret = eb_spmc_spm(); + break; + default: + printk(BIOS_ERR, "[EB_SPMC] EB SPMC in wrong state, spmc_status = %#x\n", + spmc_status); + ret = -1; + break; + } + + return ret; +} + +static void reset_mcupm(struct mtk_mcu *mcu) +{ + /* Clear abnormal boot register */ + write32p(ABNORMALBOOT_REG, ABNORMALBOOT_REG_STATUS); + write32p(WARMBOOT_REG, WARMBOOT_REG_STATUS); + write32(&mcupm_reg->sw_rstn, MCUPM_RSTN_RESET); + + write32p(MCUPM_SW_RSTN, + MCUPM_CFGREG_SW_RSTN_SW_RSTN | MCUPM_CFGREG_SW_RSTN_DMA_BUSY_MASK); +} + +static struct mtk_mcu mcupm = { + .firmware_name = CONFIG_MCUPM_FIRMWARE, + .run_address = (void *)MCUPM_SRAM_BASE, + .reset = reset_mcupm, +}; + +void mcupm_init(void) +{ + mcupm.load_buffer = _dram_dma; + mcupm.buffer_size = REGION_SIZE(dram_dma); + + /* Set CPUEB as secure master */ + printk(BIOS_INFO, "Before: DEVAPC_MCUPM = %#x\n", + read32p(DEVAPC_INFRA_SECU_AO_SEC_REPLACE_0)); + setbits32p(DEVAPC_INFRA_SECU_AO_SEC_REPLACE_0, BIT(15)); + printk(BIOS_INFO, "After: DEVAPC_MCUPM = %#x\n", + read32p(DEVAPC_INFRA_SECU_AO_SEC_REPLACE_0)); + + if (eb_spmc() != 0) + die("%s: eb sram power on failed\n", __func__); + write32(&mcupm_reg->sw_rstn, MCUPM_RSTN_RSTN_INIT); + if (mtk_init_mcu(&mcupm)) + die("%s: failed\n", __func__); +} diff --git a/src/soc/mediatek/mt8196/soc.c b/src/soc/mediatek/mt8196/soc.c index 6a78d1c..1f1da7c 100644 --- a/src/soc/mediatek/mt8196/soc.c +++ b/src/soc/mediatek/mt8196/soc.c @@ -6,6 +6,7 @@ #include <soc/dramc_info.h> #include <soc/emi.h> #include <soc/gpueb.h> +#include <soc/mcupm.h> #include <soc/mmu_operations.h> #include <soc/pcie.h> #include <soc/sspm.h> @@ -35,6 +36,7 @@ mtk_mmu_disable_l2c_sram(); sspm_init(); gpueb_init(); + mcupm_init(); }
static struct device_operations soc_ops = {