Jarried Lin has uploaded this change for review. ( 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 --- 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, 238 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/88/85888/1
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 9bb31e1..42a4d2a 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -50,7 +50,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 @@ -77,6 +77,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 3790c02..9f14b57 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, @@ -40,11 +41,13 @@ PMICSPI_MST_BASE = IO_PHYS + 0x00025000, BCRM_INFRA1_AO_BASE = IO_PHYS + 0x0002A000, IFRBUS_AO_REG_BUS_BASE = IO_PHYS + 0x0002C000, + APIFRBUS_AO_BASE = IO_PHYS + 0x0002C000, GPIO_BASE = IO_PHYS + 0x0002D000, DBGSYS_AO_DEBUG_BASE = IO_PHYS + 0x00031000, 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..8127fbe --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/mcupm_plat.h @@ -0,0 +1,98 @@ +/* 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 (APIFRBUS_AO_BASE + 0x00000708) +#define CPUEB_PROTECT_EN_0 BIT(8) +#define CPUEB_PROTECT_EN_1 BIT(9) +#define MCU_PORT_SET_R0_0 (APIFRBUS_AO_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 + */ + /* 0x1C004000 */ +#define POWERON_CONFIG_EN_MCU (SPM_BASE + 0x000) +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) +/* 1b */ +#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 REPLACE_15 BIT(15) +#define POLLING_MCU_TIME 10 +#define POLLING_ACK_TIME 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 0x00000004 +#define SRAM_SLOT_SIZE 0x00000014 /* 0x14 = 20 slots = 20*4Bytes = 80 Bytes */ +#define PIN_S_SIZE SRAM_SLOT_SIZE +#define PIN_R_SIZE SRAM_SLOT_SIZE +#define MBOX_TABLE_SIZE (PIN_S_SIZE + PIN_R_SIZE) + +#define GPR_BASE_ADDR_MCU(x) (MCUPM_SRAM_BASE + \ + MCUPM_SRAM_SIZE - \ + (IPI_MBOX_TOTAL * MBOX_TABLE_SIZE * MBOX_SLOT_SIZE) - \ + MCUPM_GPR_SIZE + \ + ((x) * SRAM_GPR_SIZE)) /* 0x1000BC7C */ + +#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..1cad4c9 --- /dev/null +++ b/src/soc/mediatek/mt8196/mcupm.c @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#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> +#include <stdlib.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); + + /* Polling MCU_PORT_SET_R0_0[9:8] = 2'b00 */ + if (!retry(POLLING_MCU_TIME, + (read32p(MCU_PORT_SET_R0_0) & + (CPUEB_PROTECT_RDY_0 | CPUEB_PROTECT_RDY_1)) == 0, udelay(1))) { + printk(BIOS_WARNING, + "[EB_SPMC] Polling MCU_PORT_SET_R0_0 timeout, %#x\n", + read32p(MCU_PORT_SET_R0_0)); + 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 */ + setbits32p(SPM_MCUPM_SPMC_CON, CPUEB_STATE_VALID); + + /* polling CPUEB_STATE_FINISH_ACK = 1 */ + if (!retry(POLLING_ACK_TIME, + (read32p(SPM_MCUPM_SPMC_CON) & CPUEB_STATE_FINISH_ACK) == + CPUEB_STATE_FINISH_ACK, udelay(1))) { + printk(BIOS_WARNING, + "[EB_SPMC] Polling ACK timeout, %#x\n", + read32p(SPM_MCUPM_SPMC_CON)); + return -1; + } + + /* set CPUEB_STATE_VALID = 0 */ + clrbits32p(SPM_MCUPM_SPMC_CON, CPUEB_STATE_VALID); + + /* polling CPUEB_STATE_FINISH_ACK = 0 */ + if (!retry(POLLING_ACK_TIME, + (read32p(SPM_MCUPM_SPMC_CON) & CPUEB_STATE_FINISH_ACK) != + CPUEB_STATE_FINISH_ACK, udelay(1))) { + printk(BIOS_WARNING, + "[EB_SPMC] Polling ACK timeout, %#x\n", + read32p(SPM_MCUPM_SPMC_CON)); + return -1; + } + + eb_sleep_protect(); + + return 0; +} + +static int eb_spmc(void) +{ + uint32_t spmc_status = (read32p(CPUEB_SPMC_STATUS) >> CPUEB_SPMC_STATUS_OFFSET) & + CPUEB_SPMC_STATUS_MASK; + int ret = 0; + + 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, "%s: spmc_status = %#x\n", __func__, spmc_status); + ret = eb_spmc_spm(); + break; + default: + printk(BIOS_ERR, "%s [EB_SPMC] EB SPMC in wrong state, spmc_status = %#x\n", + __func__, 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, REPLACE_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 = {