Yidi Lin has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85654?usp=email )
Change subject: soc/mediatek/mt8196: Add GPUEB support ......................................................................
soc/mediatek/mt8196: Add GPUEB support
GPUEB is a micro-processor used for GPU power management. It is also responsible for controlling GPU DVFS and GPU thermal throttling. This gpueb load flow adds 47ms to the boot time.
coreboot log: CBFS: Found 'gpueb_fw.img' @0x84740 size 0x29736 in mcache @0xfffdd374 Loaded (and reset) gpueb_fw.img in 47 msecs.
TEST=Boot ok BUG=b:317009620
Signed-off-by: Andy.Hsu andy.hsu@mediatek.corp-partner.google.com Change-Id: I0f10dfc753f73df97ea08a4c23e97de416832be2 Reviewed-on: https://review.coreboot.org/c/coreboot/+/85654 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/common/include/soc/symbols.h M src/soc/mediatek/mt8196/Kconfig M src/soc/mediatek/mt8196/Makefile.mk A src/soc/mediatek/mt8196/gpueb.c M src/soc/mediatek/mt8196/include/soc/addressmap.h A src/soc/mediatek/mt8196/include/soc/gpueb.h A src/soc/mediatek/mt8196/include/soc/gpueb_priv.h M src/soc/mediatek/mt8196/include/soc/memlayout.ld M src/soc/mediatek/mt8196/soc.c 9 files changed, 608 insertions(+), 0 deletions(-)
Approvals: Yu-Ping Wu: Looks good to me, approved Yidi Lin: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/src/soc/mediatek/common/include/soc/symbols.h b/src/soc/mediatek/common/include/soc/symbols.h index 065c300..46a9d9a 100644 --- a/src/soc/mediatek/common/include/soc/symbols.h +++ b/src/soc/mediatek/common/include/soc/symbols.h @@ -7,5 +7,7 @@
DECLARE_REGION(dram_dma) DECLARE_REGION(resv_mem_optee) +DECLARE_REGION(resv_mem_gpu) +DECLARE_REGION(resv_mem_gpueb)
#endif /* _SOC_MEDIATEK_COMMON_SYMBOLS_H_ */ diff --git a/src/soc/mediatek/mt8196/Kconfig b/src/soc/mediatek/mt8196/Kconfig index c5c6bf4..014b596 100644 --- a/src/soc/mediatek/mt8196/Kconfig +++ b/src/soc/mediatek/mt8196/Kconfig @@ -50,4 +50,11 @@ default "spm_firmware.pm" help The file name of the MediaTek SPM firmware. + +config GPUEB_FIRMWARE + string + default "gpueb_fw.img" + help + The file name of the MediaTek GPUEB firmware. + endif diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index e967707..9bb31e1 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -48,6 +48,7 @@ ramstage-y += dramc_info.c 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/mmu_operations.c ../common/mmu_cmops.c @@ -75,6 +76,7 @@ mcu-firmware-files := \ $(CONFIG_DPM_DM_FIRMWARE) \ $(CONFIG_DPM_PM_FIRMWARE) \ + $(CONFIG_GPUEB_FIRMWARE) \ $(CONFIG_SSPM_FIRMWARE) \ $(CONFIG_SPM_FIRMWARE)
diff --git a/src/soc/mediatek/mt8196/gpueb.c b/src/soc/mediatek/mt8196/gpueb.c new file mode 100644 index 0000000..f13630b --- /dev/null +++ b/src/soc/mediatek/mt8196/gpueb.c @@ -0,0 +1,386 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +/* + * These values are used by MediaTek internally. + * We can find these registers in "CODA_GPU_RPC_202306081135". + * The setting values are provided by MediaTek designers. + */ + +#include <arch/barrier.h> +#include <cbfs.h> +#include <console/console.h> +#include <delay.h> +#include <device/mmio.h> +#include <soc/gpueb.h> +#include <soc/mcu_common.h> +#include <soc/symbols.h> +#include <timer.h> + +#define DUMP_REG(reg) printk(BIOS_DEBUG, #reg "(%#x) = %#x\n", (reg), read32p((reg))) + +static struct st_auto_dma_fw { + const void *fw; + size_t fw_size; + uint64_t fw_addr; +} auto_dma_fw[PT_FW_NUM]; + +static void gpu_reset(void) +{ + /* Reset MFG before normal boot */ + write32p(MFG_RPC_MFG36_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG35_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG34_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG33_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG32_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG31_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG30_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG29_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG28_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG27_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG26_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG25_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG20_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG19_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG18_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG17_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG16_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG15_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG14_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG13_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG12_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG11_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG10_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG9_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG23_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG8_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG7_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG5_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG4_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG3_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG2_PWR_CON, MFG_PWR_OFF_VALUE0); + write32p(MFG_RPC_MFG37_PWR_CON, MFG_PWR_OFF_VALUE1); + write32p(MFG_RPC_MFG1_PWR_CON, MFG_PWR_OFF_VALUE2); + write32p(MFG_RPC_MFG0_PWR_CON, MFG_PWR_OFF_VALUE3); + write32p(MFG_GHPM_CFG0_CON, 0x0); + write32p(MFG_RPC_GHPM_CFG13_CON, 0x0); + write32p(MFG_RPCTOP_DUMMY_REG_0, 0x0); +} + +static bool is_mfg0_power_on(void) +{ + return (read32p(MFG0_PWR_CON) & MFG0_PWR_ACK_BIT) == MFG0_PWR_ACK_BIT; +} + +static u32 get_mfg0_pwr_con(void) +{ + return read32p(MFG_RPC_MFG0_PWR_CON); +} + +static void gpueb_dump_register(void) +{ + DUMP_REG(MFG_RPC_MFG0_PWR_CON); + DUMP_REG(MFG_RPC_SLV_SLP_PROT_RDY_STA); +} + +static void gpueb_print_exp_status(void) +{ + printk(BIOS_ERR, "%s: Request mainpll polling ack: failed\n", __func__); + printk(BIOS_ERR, "%s: MFG0_PWR_CON = %#x\n", __func__, get_mfg0_pwr_con()); + DUMP_REG(MFG_RPC_AO_CLK_CFG); + DUMP_REG(MAINPLL_SEL); + DUMP_REG(MFG_SODI_VRF18); + DUMP_REG(GPUEB_BUSPLL_RES_STA_GPR); + DUMP_REG(MFG_RPC_GHPM_CFG13_CON); + DUMP_REG(MFG_GHPM_RO2_CON); +} + +static bool wait_status_ready(uintptr_t status_reg, uint32_t mask, + uint32_t expect, uint32_t count) +{ + uint32_t i = 0; + + do { + udelay(MTCMOS_DELAY_TIME_US); + if ((read32p(status_reg) & mask) == expect) + return true; + i++; + } while (i < count); + + gpueb_dump_register(); + return false; +} + +static void gpueb_request_resource(void) +{ + setbits32p(MFG_RPC_GHPM_CFG13_CON, RESOURCE_BITS); + if (!wait_status_ready(MFG_GHPM_RO2_CON, RESOURCE_ACK_BITS, RESOURCE_ACK_BITS, + ACK_SYNC_COUNT)) { + gpueb_print_exp_status(); + die("%s: Failed to wait for resource ready\n", __func__); + } +} + +static void mfg0_power_on(void) +{ + /* Check if the power of MFG0 is OFF; if it is ON, then return */ + if (read32p(MFG_RPC_MFG0_PWR_CON) == MFG0_PWR_ON_VALUE) + return; + + /* Check if the power condition of MFG0 SRAM is ACK; if not, then return */ + if (!(read32p(MFG_RPC_MFG0_PWR_CON) & MFG0_PWR_SRAM_PDN)) + return; + + setbits32p(MFG_RPC_MFG0_PWR_CON, BIT(28)); + setbits32p(MFG_RPC_MFG0_PWR_CON, BIT(2)); + if (!wait_status_ready(MFG_RPC_MFG0_PWR_CON, BIT(30), BIT(30), POWER_ACK_DELAY_COUNT)) + return; + + udelay(MFG0_PWR_ON_DELAY_US); + + setbits32p(MFG_RPC_MFG0_PWR_CON, BIT(3)); + if (!wait_status_ready(MFG_RPC_MFG0_PWR_CON, GENMASK(31, 30), GENMASK(31, 30), + POWER_2ND_ACK_DELAY_COUNT)) + return; + + clrbits32p(MFG_RPC_MFG0_PWR_CON, BIT(4)); + clrbits32p(MFG_RPC_MFG0_PWR_CON, BIT(1)); + setbits32p(MFG_RPC_MFG0_PWR_CON, BIT(0)); + clrbits32p(MFG_RPC_MFG0_PWR_CON, BIT(8)); + if (!wait_status_ready(MFG_RPC_MFG0_PWR_CON, BIT(12), 0, POWER_2ND_ACK_DELAY_COUNT)) + return; + + setbits32p(MFG_RPC_MFG0_PWR_CON, BIT(21)); + clrbits32p(MFG_RPC_MFG0_PWR_CON, BIT(22)); + write32p(MFGSYS_PROTECT_EN_CLR_0, GENMASK(31, 25) | GENMASK(19, 16) | GENMASK(3, 0)); + if (!wait_status_ready(MFGSYS_PROTECT_EN_STA_0, + GENMASK(31, 26) | BIT(7) | GENMASK(3, 0), 0, + POWER_2ND_ACK_DELAY_COUNT)) + return; + + write32p(MFG_RPC_SLV_SLP_PROT_EN_CLR, BIT(0)); + if (!wait_status_ready(MFG_RPC_SLV_SLP_PROT_RDY_STA, BIT(0), 0, + POWER_2ND_ACK_DELAY_COUNT)) + return; + + write32p(MFG_RPC_SLV_SLP_PROT_EN_CLR, BIT(1)); + if (!wait_status_ready(MFG_RPC_SLV_SLP_PROT_RDY_STA, BIT(1), 0, + POWER_2ND_ACK_DELAY_COUNT)) + return; + + write32p(MFG_RPC_SLV_WAY_EN_SET, BIT(0)); + wait_status_ready(MFG_RPC_SLV_CTRL_UPDATE, BIT(0), BIT(0), POWER_2ND_ACK_DELAY_COUNT); +} + +static void switch_mux_pll(void) +{ + gpueb_request_resource(); + setbits32p(MFG_RPC_AO_CLK_CFG, GPUEB_CKMUX_SEL_26M_BIT); + udelay(SWITCH_MUX_WAIT_US); +} + +static void gpueb_assert_init_success(void) +{ + u32 gpueb_mux; + + gpueb_mux = read32p(MFG_RPC_AO_CLK_CFG); + if (is_mfg0_power_on() && + ((gpueb_mux & GPUEB_CKMUX_SEL_26M_BIT) == GPUEB_CKMUX_SEL_26M_BIT)) { + printk(BIOS_INFO, "%s: Done\n", __func__); + return; + } + gpueb_print_exp_status(); + die("%s: Failed to assert init\n", __func__); +} + +static void parse_fw(const void *buf_addr, size_t buf_size, const void **img, size_t *img_size) +{ + int i; + void *addr; + struct gpueb_pt_hdr *hdr; + + hdr = (struct gpueb_pt_hdr *)buf_addr; + + if (buf_size <= sizeof(*hdr)) + die("%s: Buffer size too small\n", __func__); + + while ((uintptr_t)hdr + sizeof(*hdr) <= (uintptr_t)buf_addr + buf_size && + hdr->magic == GPUEB_PT_MAGIC) { + addr = (void *)hdr + hdr->hdr_size; + + if (hdr->id == 0 || hdr->id >= PT_FW_NUM) { + printk(BIOS_WARNING, "%s: unexpected hdr (%d)\n", __func__, hdr->id); + addr += ALIGN_UP(hdr->img_size, hdr->align); + hdr = (struct gpueb_pt_hdr *)addr; + continue; + } + + if ((uintptr_t)addr + hdr->img_size > (uintptr_t)buf_addr + buf_size) + break; + + if (hdr->id == PT_FW_IDX_GPUEB_FW) { + *img = addr; + *img_size = hdr->img_size; + } else { + auto_dma_fw[hdr->id].fw = addr; + auto_dma_fw[hdr->id].fw_size = hdr->img_size; + auto_dma_fw[hdr->id].fw_addr = hdr->addr; + } + + addr += ALIGN_UP(hdr->img_size, hdr->align); + hdr = (struct gpueb_pt_hdr *)addr; + } + + if (!*img || !*img_size) + die("%s: img:%p, img_size:%ld\n", __func__, *img, *img_size); + + for (i = PT_FW_IDX_AUTO_DMA_START; i <= PT_FW_IDX_AUTO_DMA_END; i++) { + if (!auto_dma_fw[i].fw || !auto_dma_fw[i].fw_size) { + die("%s: Partition missing (@%p)\n" + "fw_id[%d]:%p, size:%ld\n", __func__, buf_addr, i, + auto_dma_fw[i].fw, auto_dma_fw[i].fw_size); + } + } +} + +static void load_fw(enum pt_fw_idx pt_id) +{ + assert(auto_dma_fw[pt_id].fw_addr + auto_dma_fw[pt_id].fw_size <= GPUEB_SRAM_SIZE); + memcpy((void *)(MFG_GPUEB_BASE + auto_dma_fw[pt_id].fw_addr), + auto_dma_fw[pt_id].fw, auto_dma_fw[pt_id].fw_size); +} + +static void load_auto_dma_fw(void) +{ + load_fw(PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART1_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART2_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART3_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CS_HBVC_LOGGING_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CS_TOP_SESV8_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CS_STK_SESV8_FW); + load_fw(PT_FW_IDX_AUTO_DMA_SMMU_FW); + load_fw(PT_FW_IDX_AUTO_DMA_PREOC_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CCMD_CH1_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CCMD_CH2_FW); + load_fw(PT_FW_IDX_AUTO_DMA_CCMD_CH0_FW); + load_fw(PT_FW_IDX_AUTO_DMA_HBVC_CONFIG_GRP0_FW); + load_fw(PT_FW_IDX_AUTO_DMA_HBVC_CONFIG_GRP1_FW); + load_fw(PT_FW_IDX_AUTO_DMA_GPM_OUT_OF_RATIO_FW); + load_fw(PT_FW_IDX_AUTO_DMA_GPM_OUT_OF_SUM_MAX_FW); +} + +static bool gpueb_is_sram_access(void) +{ + u32 mfg0_pwr_con; + + mfg0_pwr_con = read32p(MFG0_PWR_CON); + + if (mfg0_pwr_con & MFG0_PWR_SRAM_PDN_ACK) { + printk(BIOS_ERR, "%s: SRAM is power-down(%#x)\n", __func__, mfg0_pwr_con); + return false; + } + + if ((mfg0_pwr_con & MFG0_PWR_SRAM_SLEEP_B_ACK) != MFG0_PWR_SRAM_SLEEP_B_ACK) { + printk(BIOS_ERR, "%s: SRAM is under sleep mode(%#x)\n", __func__, mfg0_pwr_con); + return false; + } + + return true; +} + +static void gpueb_power_init(void) +{ + mfg0_power_on(); + switch_mux_pll(); + gpueb_assert_init_success(); +} + +static void gpueb_reset(struct mtk_mcu *mcu) +{ + const void *gpueb_img = NULL; + size_t gpueb_img_size = 0; + u32 tcm_lock_info; + + parse_fw(mcu->load_buffer, mcu->buffer_size, &gpueb_img, &gpueb_img_size); + if (!gpueb_img || !gpueb_img_size) + die("%s: Failed to parse gpueb FW", __func__); + + tcm_lock_info = (TCM_LOCK_ADDR >> 12) & GPUEB_TCM_LOCK_MASK; + tcm_lock_info = tcm_lock_info << 24; + + write32p(GPUEB_CFGREG_SW_RSTN, 0); + memset((void *)MFG_GPUEB_BASE, 0, GPUEB_SRAM_SIZE); + assert(gpueb_img_size <= GPUEB_SRAM_SIZE); + memcpy((void *)MFG_GPUEB_BASE, gpueb_img, gpueb_img_size); + + load_auto_dma_fw(); + + write32p(GPUEB_ABNORMAL_BOOT, 0); + write32p(GPUEB_WARM_BOOT, 0); + write32p(GPUMPU_RSV_ADDR, (uintptr_t)_resv_mem_gpueb >> PAGE_SHIFT); + + /* Trigger GPUEB */ + write32p(GPUEB_CFGREG_SW_RSTN, 0); + write32p(GPUEB_CFGREG_SW_RSTN, + GPUEB_CFGREG_SW_RSTN_SW_RSTN | GPUEB_CFGREG_SW_RSTN_DMA_BUSY_MASK | + tcm_lock_info | GPUEB_CFGREG_PTCM_LOCK); +} + +static bool is_boot_up_complete(void) +{ + return read32p(GPUEB_INIT_FOOTPRINT) == GPUEB_BOOT_UP_COMPLETE; +} + +static bool gpueb_wait_boot_up_done(void) +{ + if (!wait_us(BOOT_TIMEOUT_US, is_boot_up_complete())) { + printk(BIOS_CRIT, "%s: GPUEB boot-up timed out!!!\n", __func__); + DUMP_REG(GPUEB_MUX); + DUMP_REG(MFG0_PWR_CON); + DUMP_REG(MFG_RPC_GPUEB_CFG); + DUMP_REG(GPUEB_CFGREG_SW_RSTN); + DUMP_REG(GPUEB_CFGREG_DBG_APB_PC); + DUMP_REG(GPUEB_CFGREG_DBG_APB_LR); + DUMP_REG(GPUEB_CFGREG_DBG_APB_SP); + DUMP_REG(GPUEB_INIT_FOOTPRINT); + DUMP_REG(GPUFREQ_FOOTPRINT_GPR); + DUMP_REG(GPUPTP3_BAD_SAMPLE); + DUMP_REG(GPUEB_DIAGNOSIS_GPR); + + write32p(GPUEB_INFO, 0x5A5A5A5A); + DUMP_REG(GPUEB_INFO); + return false; + } + + return true; +} + +static struct mtk_mcu gpueb = { + .firmware_name = CONFIG_GPUEB_FIRMWARE, + .load_buffer = _dram_dma, + .buffer_size = REGION_SIZE(dram_dma), + .reset = gpueb_reset, +}; + +static void gpueb_load(void) +{ + if (!is_mfg0_power_on() || !gpueb_is_sram_access()) + die("%s: GPUEB(MFG0) NOT power-on!!!", __func__); + + /* Load FW image and trigger GPUEB */ + if (mtk_init_mcu(&gpueb)) + die("%s: Failed to load FW image", __func__); + + if (!gpueb_wait_boot_up_done()) + die("%s: Failed to wait for boot up", __func__); + + printk(BIOS_INFO, "%s: GPUEB boot-up complete (magic: %#x)\n", __func__, + read32p(GPUEB_INIT_FOOTPRINT)); +} + +void gpueb_init(void) +{ + gpu_reset(); + gpueb_power_init(); + gpueb_load(); + printk(BIOS_INFO, "%s: Init done\n", __func__); +} diff --git a/src/soc/mediatek/mt8196/include/soc/addressmap.h b/src/soc/mediatek/mt8196/include/soc/addressmap.h index 8d0a4bb..3790c02 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -33,11 +33,13 @@ APMIXED_BASE = IO_PHYS + 0x00000800, INFRACFG_AO_BASE = IO_PHYS + 0x00001000, CKSYS_GP2_BASE = IO_PHYS + 0x0000C000, + DRM_DEBUG_BASE = IO_PHYS + 0x0000D000, APMIXEDSYS_GP2_BASE = IO_PHYS + 0x0000C800, BCRM_INFRA_AO_BASE = IO_PHYS + 0x00022000, PMIF_SPI_BASE = IO_PHYS + 0x00024000, PMICSPI_MST_BASE = IO_PHYS + 0x00025000, BCRM_INFRA1_AO_BASE = IO_PHYS + 0x0002A000, + IFRBUS_AO_REG_BUS_BASE = IO_PHYS + 0x0002C000, GPIO_BASE = IO_PHYS + 0x0002D000, DBGSYS_AO_DEBUG_BASE = IO_PHYS + 0x00031000, APINFRA_IO_AO_DEBUG_BASE = IO_PHYS + 0x00155000, @@ -191,9 +193,13 @@ OVLSYS1_CONFIG_BASE = IO_PHYS + 0x22C00000, DISP_VDISP_AO_CONFIG_BASE = IO_PHYS + 0x2E800000, EDP_BASE = IO_PHYS + 0x2EC40000, + MFG_TOP_CFG_BASE = MFGSYS_BASE + 0x08500000, + MFG_GPUEB_BASE = MFGSYS_BASE + 0x0B000000, + MFG_GPUEB_RPC_BASE = MFGSYS_BASE + 0x0B800000, MFG_PLL_PLL_CTRL_BASE = MFGSYS_BASE + 0x0B810000, MFG_PLL_SC0_PLL_CTRL_BASE = MFGSYS_BASE + 0x0B810400, MFG_PLL_SC1_PLL_CTRL_BASE = MFGSYS_BASE + 0x0B810800, + MFG_VCORE_AO_CFG_BASE = MFGSYS_BASE + 0x0B860000, };
#endif diff --git a/src/soc/mediatek/mt8196/include/soc/gpueb.h b/src/soc/mediatek/mt8196/include/soc/gpueb.h new file mode 100644 index 0000000..ce93139 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/gpueb.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_H__ +#define __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_H__ + +#include <soc/gpueb_priv.h> + +void gpueb_init(void); + +#endif /* __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_H__ */ diff --git a/src/soc/mediatek/mt8196/include/soc/gpueb_priv.h b/src/soc/mediatek/mt8196/include/soc/gpueb_priv.h new file mode 100644 index 0000000..fe50b41 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/gpueb_priv.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_PRIV_H__ +#define __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_PRIV_H__ + +#include <soc/addressmap.h> +#include <types.h> + +#define MAINPLL_SEL (IO_PHYS + 0x0060) /* 0x10000060 */ +#define MFG_RPC_SLV_WAY_EN_SET (MFG_GPUEB_RPC_BASE + 0x0060) /* 0x4B800060 */ +#define MFG_RPC_SLV_WAY_EN_CLR (MFG_GPUEB_RPC_BASE + 0x0064) /* 0x4B800064 */ +#define MFG_RPC_SLV_CTRL_UPDATE (MFG_GPUEB_RPC_BASE + 0x0068) /* 0x4B800068 */ +#define MFG_RPC_SLV_SLP_PROT_EN_SET (MFG_GPUEB_RPC_BASE + 0x0070) /* 0x4B800070 */ +#define MFG_RPC_SLV_SLP_PROT_EN_CLR (MFG_GPUEB_RPC_BASE + 0x0074) /* 0x4B800074 */ +#define MFG_RPC_SLV_SLP_PROT_RDY_STA (MFG_GPUEB_RPC_BASE + 0x0078) /* 0x4B800078 */ +#define MFG_RPC_MFG1_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0500) /* 0x4B800500 */ +#define MFG_RPC_MFG0_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0504) /* 0x4B800504 */ +#define MFG_RPC_MFG2_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0508) /* 0x4B800508 */ +#define MFG_RPC_MFG3_PWR_CON (MFG_GPUEB_RPC_BASE + 0x050C) /* 0x4B80050C */ +#define MFG_RPC_MFG4_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0510) /* 0x4B800510 */ +#define MFG_RPC_MFG5_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0514) /* 0x4B800514 */ +#define MFG_RPC_MFG7_PWR_CON (MFG_GPUEB_RPC_BASE + 0x051C) /* 0x4B80051C */ +#define MFG_RPC_MFG8_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0520) /* 0x4B800520 */ +#define MFG_RPC_MFG9_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0524) /* 0x4B800524 */ +#define MFG_RPC_MFG10_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0528) /* 0x4B800528 */ +#define MFG_RPC_MFG11_PWR_CON (MFG_GPUEB_RPC_BASE + 0x052C) /* 0x4B80052C */ +#define MFG_RPC_MFG12_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0530) /* 0x4B800530 */ +#define MFG_RPC_MFG13_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0534) /* 0x4B800534 */ +#define MFG_RPC_MFG14_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0538) /* 0x4B800538 */ +#define MFG_RPC_MFG15_PWR_CON (MFG_GPUEB_RPC_BASE + 0x053C) /* 0x4B80053C */ +#define MFG_RPC_MFG16_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0540) /* 0x4B800540 */ +#define MFG_RPC_MFG17_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0544) /* 0x4B800544 */ +#define MFG_RPC_MFG18_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0548) /* 0x4B800548 */ +#define MFG_RPC_MFG19_PWR_CON (MFG_GPUEB_RPC_BASE + 0x054C) /* 0x4B80054C */ +#define MFG_RPC_MFG20_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0550) /* 0x4B800550 */ +#define MFG_RPC_MFG23_PWR_CON (MFG_GPUEB_RPC_BASE + 0x055C) /* 0x4B80055C */ +#define MFG_RPC_MFG25_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0564) /* 0x4B800564 */ +#define MFG_RPC_MFG26_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0568) /* 0x4B800568 */ +#define MFG_RPC_MFG27_PWR_CON (MFG_GPUEB_RPC_BASE + 0x056C) /* 0x4B80056C */ +#define MFG_RPC_MFG28_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0570) /* 0x4B800570 */ +#define MFG_RPC_MFG29_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0574) /* 0x4B800574 */ +#define MFG_RPC_MFG30_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0578) /* 0x4B800578 */ +#define MFG_RPC_MFG31_PWR_CON (MFG_GPUEB_RPC_BASE + 0x057C) /* 0x4B80057C */ +#define MFG_RPC_MFG32_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0580) /* 0x4B800580 */ +#define MFG_RPC_MFG33_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0584) /* 0x4B800584 */ +#define MFG_RPC_MFG34_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0588) /* 0x4B800588 */ +#define MFG_RPC_MFG35_PWR_CON (MFG_GPUEB_RPC_BASE + 0x058C) /* 0x4B80058C */ +#define MFG_RPC_MFG36_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0590) /* 0x4B800590 */ +#define MFG_RPC_MFG37_PWR_CON (MFG_GPUEB_RPC_BASE + 0x0594) /* 0x4B800594 */ +#define MFG_RPCTOP_DUMMY_REG_0 (MFG_GPUEB_RPC_BASE + 0x0650) /* 0x4B800650 */ +#define MFG_GHPM_CFG0_CON (MFG_GPUEB_RPC_BASE + 0x0800) /* 0x4B800800 */ +#define MFG_RPC_GHPM_CFG13_CON (MFG_GPUEB_RPC_BASE + 0x0834) /* 0x4B800834 */ +#define MFG_GHPM_RO2_CON (MFG_GPUEB_RPC_BASE + 0x09AC) /* 0x4B8009AC */ +#define MFG_RPC_GPUEB_CFG (MFG_VCORE_AO_CFG_BASE + 0x0074) /* 0x4B860074 */ +#define MFG_RPC_AO_CLK_CFG (MFG_VCORE_AO_CFG_BASE + 0x0078) /* 0x4B860078 */ +#define MFGSYS_PROTECT_EN_SET_0 (MFG_VCORE_AO_CFG_BASE + 0x0080) /* 0x4B860080 */ +#define MFGSYS_PROTECT_EN_CLR_0 (MFG_VCORE_AO_CFG_BASE + 0x0084) /* 0x4B860084 */ +#define MFGSYS_PROTECT_EN_STA_0 (MFG_VCORE_AO_CFG_BASE + 0x0088) /* 0x4B860088 */ +#define MFG_SODI_VRF18 (MFG_VCORE_AO_CFG_BASE + 0x00D4) /* 0x4B8600D4 */ + +/* GPUEB */ +#define GPUEB_MUX MFG_RPC_AO_CLK_CFG +#define GPUEB_SRAM_SIZE (640 * KiB) +#define GPUEB_GPR_SIZE 128 +#define GPUEB_SRAM_GPR_SIZE 4 +#define GPR_BASE_START (MFG_GPUEB_BASE + 0x0009FD00) +#define GPR_BASE_ADDR(x) (GPR_BASE_START + (x * GPUEB_SRAM_GPR_SIZE)) +#define GPUEB_INFO GPR_BASE_ADDR(0) +#define GPUEB_ABNORMAL_BOOT GPR_BASE_ADDR(1) +#define GPUEB_INIT_FOOTPRINT GPR_BASE_ADDR(2) +#define GPUMPU_RSV_ADDR GPR_BASE_ADDR(6) +#define GPUFREQ_FOOTPRINT_GPR GPR_BASE_ADDR(17) +#define GPUEB_DIAGNOSIS_GPR GPR_BASE_ADDR(18) +#define GPUEB_WARM_BOOT GPR_BASE_ADDR(23) +#define GPUPTP3_BAD_SAMPLE GPR_BASE_ADDR(30) +#define GPUEB_CFGREG_BASE (MFG_GPUEB_BASE + 0x140100) +#define GPUEB_CFGREG_SW_RSTN (GPUEB_CFGREG_BASE + 0x0000) +#define GPUEB_CFGREG_SW_RSTN_SW_RSTN BIT(0) +#define GPUEB_CFGREG_SW_RSTN_DMA_BUSY_MASK BIT(1) +#define GPUEB_CFGREG_PTCM_LOCK BIT(3) +#define GPUEB_CKMUX_SEL_26M_BIT BIT(6) +#define GPUEB_TCM_LOCK_MASK 0xFF +#define GPUEB_CFGREG_DBG_APB_PC (GPUEB_CFGREG_BASE + 0x011C) +#define GPUEB_CFGREG_DBG_APB_LR (GPUEB_CFGREG_BASE + 0x0120) +#define GPUEB_CFGREG_DBG_APB_SP (GPUEB_CFGREG_BASE + 0x0124) + +#define GPU_PMU_COUNTER_SIZE 100 +#define GPU_PMU_COUNTER_END GPR_BASE_ADDR(0) +#define GPU_PMU_COUNTER_START (GPU_PMU_COUNTER_END - GPU_PMU_COUNTER_SIZE) +#define GPUEB_SMEM_START (GPU_PMU_COUNTER_START & TCM_LOCK_ALIGNMENT) + +#define TCM_LOCK_ADDR GPUEB_SMEM_START +#define TCM_LOCK_ALIGNMENT 0xFFFFF000 /* 4KB alignment */ + +#define SW_VCORE_REQ BIT(0) +#define SW_PMIC_REQ BIT(1) +#define SW_CK26M_REQ BIT(2) +#define SW_MAINPLL_REQ BIT(3) +#define RESOURCE_BITS (SW_MAINPLL_REQ | SW_CK26M_REQ | SW_PMIC_REQ |\ + SW_VCORE_REQ) + +#define VCORE_ACK_SYNC BIT(28) +#define PMIC_ACK_SYNC BIT(29) +#define CK26M_ACK_SYNC BIT(30) +#define MAINPLL_ACK_SYNC BIT(31) +#define RESOURCE_ACK_BITS (MAINPLL_ACK_SYNC | CK26M_ACK_SYNC |\ + PMIC_ACK_SYNC | VCORE_ACK_SYNC) + +#define MFG_RPC_MFG0_PWR_ACK_2ND_BIT BIT(31) +#define MFG_RPC_MFG0_PWR_ACK_1ST_BIT BIT(30) +#define MFG_RPC_MFG0_PWR_ACK_BIT (MFG_RPC_MFG0_PWR_ACK_1ST_BIT |\ + MFG_RPC_MFG0_PWR_ACK_2ND_BIT) +#define MFG_RPC_MFG0_PWR_SRAM_PDN_ACK BIT(12) +#define MFG_RPC_MFG0_PWR_SRAM_SLEEP_B_ACK BIT(23) +#define MFG0_PWR_CON MFG_RPC_MFG0_PWR_CON +#define MFG0_PWR_ACK_BIT MFG_RPC_MFG0_PWR_ACK_BIT +#define MFG0_PWR_SRAM_SLEEP_B_ACK MFG_RPC_MFG0_PWR_SRAM_SLEEP_B_ACK +#define MFG0_PWR_SRAM_PDN_ACK MFG_RPC_MFG0_PWR_SRAM_PDN_ACK +#define GPUEB_BOOT_UP_COMPLETE 0x55667788 +#define GPUEB_PT_MAGIC 0x58901690 +#define GPUEB_BUSPLL_RES_STA_GPR GPR_BASE_ADDR(25) +#define MFG0_PWR_SRAM_PDN BIT(8) +#define MFG_PWR_OFF_VALUE0 0x00001112 +#define MFG_PWR_OFF_VALUE2 0x00003312 +#define MFG_PWR_OFF_VALUE3 0x00700112 +#define SPM_MFG_PWR_OFF_VALUE 0x02000372 +#define MFG_PWR_OFF_VALUE1 0x60001112 +#define MFG0_PWR_ON_VALUE 0xD0B0000D + +#define BOOT_TIMEOUT_US 1000000 +#define MTCMOS_DELAY_TIME_US 3 +#define MFG0_PWR_ON_DELAY_US 50 +#define PAGE_SHIFT 12 +#define SWITCH_MUX_WAIT_US 10 +#define ACK_SYNC_COUNT 50 +#define POWER_ACK_DELAY_COUNT 50 +#define POWER_2ND_ACK_DELAY_COUNT 1000 + +enum pt_fw_idx { + PT_FW_IDX_GPUEB_FW = 1, + PT_FW_IDX_AUTO_DMA_BRCAST_PART1_FW = 2, + PT_FW_IDX_AUTO_DMA_BRCAST_PART2_FW = 3, + PT_FW_IDX_AUTO_DMA_BRCAST_PART3_FW = 4, + PT_FW_IDX_AUTO_DMA_SMMU_FW = 5, + PT_FW_IDX_AUTO_DMA_PREOC_FW = 6, + PT_FW_IDX_AUTO_DMA_HBVC_LOGGING_FW = 7, + PT_FW_IDX_AUTO_DMA_CCMD_CH1_FW = 8, + PT_FW_IDX_AUTO_DMA_CCMD_CH2_FW = 9, + PT_FW_IDX_AUTO_DMA_CCMD_CH0_FW = 10, + PT_FW_IDX_AUTO_DMA_HBVC_CONFIG_GRP0_FW = 11, + PT_FW_IDX_AUTO_DMA_HBVC_CONFIG_GRP1_FW = 12, + PT_FW_IDX_AUTO_DMA_GPM_OUT_OF_RATIO_FW = 13, + PT_FW_IDX_AUTO_DMA_GPM_OUT_OF_SUM_MAX_FW = 14, + PT_FW_IDX_AUTO_DMA_TOP_SESV8_FW = 15, + PT_FW_IDX_AUTO_DMA_STK_SESV8_FW = 16, + PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART1_FW = 17, + PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART2_FW = 18, + PT_FW_IDX_AUTO_DMA_CS_BRCAST_PART3_FW = 19, + PT_FW_IDX_AUTO_DMA_CS_HBVC_LOGGING_FW = 20, + PT_FW_IDX_AUTO_DMA_CS_TOP_SESV8_FW = 21, + PT_FW_IDX_AUTO_DMA_CS_STK_SESV8_FW = 22, + PT_FW_NUM = 23, + + PT_FW_IDX_AUTO_DMA_START = PT_FW_IDX_AUTO_DMA_BRCAST_PART1_FW, + PT_FW_IDX_AUTO_DMA_END = PT_FW_IDX_AUTO_DMA_STK_SESV8_FW, +}; + +struct gpueb_pt_hdr { + unsigned int magic; /* magic number*/ + unsigned int hdr_size; /* data size */ + unsigned int img_size; /* img size */ + unsigned int align; /* align */ + unsigned int id; /* image id */ + unsigned int addr; /* the FW address is in the 4GB range */ +}; + +#endif /* __SOC_MEDIATEK_MT8196_INCLUDE_SOC_GPUEB_PRIV_H__ */ diff --git a/src/soc/mediatek/mt8196/include/soc/memlayout.ld b/src/soc/mediatek/mt8196/include/soc/memlayout.ld index 83e80b6..f8ee114 100644 --- a/src/soc/mediatek/mt8196/include/soc/memlayout.ld +++ b/src/soc/mediatek/mt8196/include/soc/memlayout.ld @@ -5,6 +5,12 @@ #define OPTEE_BUF(addr, size) \ REGION(resv_mem_optee, addr, size, 4K)
+#define GPU_SEC_BUF(addr, size) \ + REGION(resv_mem_gpu, addr, size, 4K) + +#define RESV_MEMORY_GPUEB(addr, size)\ + REGION(resv_mem_gpueb, addr, size, 2M) + SECTIONS { /* MT8196 has 256KB SRAM. */ @@ -60,4 +66,9 @@ OPTEE_BUF(0x80500000, 70M)
BL31(0x94600000, 0x200000) + + /* Reserved memory for the shared buffer between AP and microprocessor */ + RESV_MEMORY_GPUEB(0xA0000000, 2M) + /* Reserved memory for the dedicated secured memory allocator of GPU Mali firmware */ + GPU_SEC_BUF(0xA2000000, 16M) } diff --git a/src/soc/mediatek/mt8196/soc.c b/src/soc/mediatek/mt8196/soc.c index 0fe6909..6a78d1c 100644 --- a/src/soc/mediatek/mt8196/soc.c +++ b/src/soc/mediatek/mt8196/soc.c @@ -1,9 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */
+#include <bootmem.h> #include <device/device.h> #include <device/pci.h> #include <soc/dramc_info.h> #include <soc/emi.h> +#include <soc/gpueb.h> #include <soc/mmu_operations.h> #include <soc/pcie.h> #include <soc/sspm.h> @@ -17,6 +19,10 @@ REGION_SIZE(resv_mem_optee), BM_MEM_RESERVED);
reserve_buffer_for_dramc(); + + bootmem_add_range((uint64_t)_resv_mem_gpu, REGION_SIZE(resv_mem_gpu), BM_MEM_RESERVED); + bootmem_add_range((uint64_t)_resv_mem_gpueb, + REGION_SIZE(resv_mem_gpueb), BM_MEM_RESERVED); }
static void soc_read_resources(struct device *dev) @@ -28,6 +34,7 @@ { mtk_mmu_disable_l2c_sram(); sspm_init(); + gpueb_init(); }
static struct device_operations soc_ops = {