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>
This commit is contained in:
Agogo Huang 2024-05-21 20:27:34 +08:00 committed by Yu-Ping Wu
commit c5f6daba81
6 changed files with 235 additions and 1 deletions

View file

@ -57,4 +57,10 @@ config GPUEB_FIRMWARE
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

View file

@ -53,7 +53,7 @@ ramstage-y += ../common/early_init.c
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 @@ mcu-firmware-files := \
$(CONFIG_DPM_DM_FIRMWARE) \
$(CONFIG_DPM_PM_FIRMWARE) \
$(CONFIG_GPUEB_FIRMWARE) \
$(CONFIG_MCUPM_FIRMWARE) \
$(CONFIG_SSPM_FIRMWARE) \
$(CONFIG_SPM_FIRMWARE)

View file

@ -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 @@ enum {
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,

View file

@ -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__ */

View file

@ -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__);
}

View file

@ -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 @@ static void soc_init(struct device *dev)
mtk_mmu_disable_l2c_sram();
sspm_init();
gpueb_init();
mcupm_init();
}
static struct device_operations soc_ops = {