From 5183e637a0496ad8dfbd8c892bc874ac6a1531bf Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Mon, 5 Jul 2021 20:42:09 +0800 Subject: [PATCH] feat(plat/mdeiatek/mt8192): add DFD control in SiP service DFD (Design for Debug) is a debugging tool, which scans flip-flops and dumps to internal RAM on the WDT reset. After system reboots, those values could be showed for debugging. Signed-off-by: Rex-BC Chen Change-Id: I9c7af9a4f75216ed2c6b44458d121a352bef4b95 --- plat/mediatek/mt8192/drivers/dfd/plat_dfd.c | 139 ++++++++++++++++++ plat/mediatek/mt8192/drivers/dfd/plat_dfd.h | 70 +++++++++ plat/mediatek/mt8192/include/plat_sip_calls.h | 6 +- plat/mediatek/mt8192/plat_pm.c | 3 + plat/mediatek/mt8192/plat_sip_calls.c | 6 + plat/mediatek/mt8192/platform.mk | 2 + 6 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 plat/mediatek/mt8192/drivers/dfd/plat_dfd.c create mode 100644 plat/mediatek/mt8192/drivers/dfd/plat_dfd.h diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c new file mode 100644 index 000000000..69c395e9c --- /dev/null +++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +static bool dfd_enabled; +static uint64_t dfd_base_addr; +static uint64_t dfd_chain_length; +static uint64_t dfd_cache_dump; + +static void dfd_setup(uint64_t base_addr, uint64_t chain_length, + uint64_t cache_dump) +{ + /* bit[0]: rg_rw_dfd_internal_dump_en -> 1 */ + /* bit[2]: rg_rw_dfd_clock_stop_en -> 1 */ + sync_writel(DFD_INTERNAL_CTL, 0x5); + + /* bit[13]: xreset_b_update_disable */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 13); + + /* + * bit[10:3]: DFD trigger selection mask + * bit[3]: rg_rw_dfd_trigger_sel[0] = 1(enable wdt trigger) + * bit[4]: rg_rw_dfd_trigger_sel[1] = 1(enable HW trigger) + * bit[5]: rg_rw_dfd_trigger_sel[2] = 1(enable SW trigger) + * bit[6]: rg_rw_dfd_trigger_sel[3] = 1(enable SW non-security trigger) + * bit[7]: rg_rw_dfd_trigger_sel[4] = 1(enable timer trigger) + */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 3); + + /* bit[20:19]: rg_dfd_armpll_div_mux_sel switch to PLL2 for DFD */ + mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19); + + /* + * bit[0]: rg_rw_dfd_auto_power_on = 1 + * bit[2:1]: rg_rw_dfd_auto_power_on_dely = 1(10us) + * bit[4:2]: rg_rw_dfd_power_on_wait_time = 1(20us) + */ + mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB); + + /* longest scan chain length */ + mmio_write_32(DFD_CHAIN_LENGTH0, chain_length); + + /* bit[1:0]: rg_rw_dfd_shift_clock_ratio */ + mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0); + + /* rg_dfd_test_so_over_64 */ + mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1); + + /* DFD3.0 */ + mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_DIS_VAL); + mmio_write_32(DFD_TEST_SI_1, DFD_TEST_SI_1_VAL); + mmio_write_32(DFD_TEST_SI_2, DFD_TEST_SI_2_VAL); + mmio_write_32(DFD_TEST_SI_3, DFD_TEST_SI_3_VAL); + + /* for iLDO feature */ + sync_writel(DFD_POWER_CTL, 0xF9); + + /* set base address */ + mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24); + + /* + * disable sleep protect of DFD + * 10001220[8]: protect_en_reg[8] + * 10001a3c[2]: infra_mcu_pwr_ctl_mask[2] + */ + mmio_clrbits_32(DFD_O_PROTECT_EN_REG, 1 << 8); + mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, 1 << 2); + + /* clean DFD trigger status */ + sync_writel(DFD_CLEAN_STATUS, 0x1); + sync_writel(DFD_CLEAN_STATUS, 0x0); + + /* DFD-3.0 */ + sync_writel(DFD_V30_CTL, 0x1); + + /* setup global variables for suspend and resume */ + dfd_enabled = true; + dfd_base_addr = base_addr; + dfd_chain_length = chain_length; + dfd_cache_dump = cache_dump; + + if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) { + /* DFD3.5 */ + mmio_write_32(DFD_TEST_SI_0, DFD_TEST_SI_0_CACHE_EN_VAL); + sync_writel(DFD_V35_ENALBE, 0x1); + sync_writel(DFD_V35_TAP_NUMBER, 0xB); + sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL); + sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL); + + if (cache_dump & DFD_PARITY_ERR_TRIGGER) { + sync_writel(DFD_HW_TRIGGER_MASK, 0xC); + mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4); + } + } + dsbsy(); +} + +void dfd_resume(void) +{ + if (dfd_enabled == true) { + dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump); + } +} + +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3) +{ + uint64_t ret = 0L; + + switch (arg0) { + case PLAT_MTK_DFD_SETUP_MAGIC: + dfd_setup(arg1, arg2, arg3); + break; + case PLAT_MTK_DFD_READ_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + ret = mmio_read_32(MISC1_CFG_BASE + arg1); + } + break; + case PLAT_MTK_DFD_WRITE_MAGIC: + /* only allow to access DFD register base + 0x200 */ + if (arg1 <= 0x200) { + sync_writel(MISC1_CFG_BASE + arg1, arg2); + } + break; + default: + ret = MTK_SIP_E_INVALID_PARAM; + break; + } + + return ret; +} diff --git a/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h new file mode 100644 index 000000000..7f0f4b51f --- /dev/null +++ b/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_DFD_H +#define PLAT_DFD_H + +#include +#include +#include + +#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); \ + dsbsy(); \ + } while (0) + +#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150) +#define PLAT_MTK_DFD_READ_MAGIC (0x99716151) +#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152) + +#define MCU_BIU_BASE (MCUCFG_BASE) +#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040) +#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00) +#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08) +#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C) +#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10) +#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C) +#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20) +#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24) +#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28) +#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30) +#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34) +#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48) +#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C) +#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50) +#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58) +#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C) +#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60) +#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8) +#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC) +#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC) + +#define DFD_V35_ENALBE (MCU_BIU_BASE + 0xE0A8) +#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC) +#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0) +#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4) +#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0) +#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4) + +#define DFD_O_PROTECT_EN_REG (0x10001220) +#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C) +#define DFD_O_SET_BASEADDR_REG (0x10043034) + +#define DFD_CACHE_DUMP_ENABLE 1U +#define DFD_PARITY_ERR_TRIGGER 2U + +#define DFD_TEST_SI_0_CACHE_DIS_VAL (0x1E000202) +#define DFD_TEST_SI_0_CACHE_EN_VAL (0x1E000002) +#define DFD_TEST_SI_1_VAL (0x20408100) +#define DFD_TEST_SI_2_VAL (0x10101000) +#define DFD_TEST_SI_3_VAL (0x00000010) +#define DFD_V35_TAP_EN_VAL (0x43FF) +#define DFD_V35_SEQ0_0_VAL (0x63668820) + +void dfd_resume(void); +uint64_t dfd_smc_dispatcher(uint64_t arg0, uint64_t arg1, + uint64_t arg2, uint64_t arg3); + +#endif /* PLAT_DFD_H */ diff --git a/plat/mediatek/mt8192/include/plat_sip_calls.h b/plat/mediatek/mt8192/include/plat_sip_calls.h index 0e423225c..f68a4eabf 100644 --- a/plat/mediatek/mt8192/include/plat_sip_calls.h +++ b/plat/mediatek/mt8192/include/plat_sip_calls.h @@ -10,6 +10,10 @@ /******************************************************************************* * Plat SiP function constants ******************************************************************************/ -#define MTK_PLAT_SIP_NUM_CALLS 0 +#define MTK_PLAT_SIP_NUM_CALLS 2 + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205 +#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205 #endif /* PLAT_SIP_CALLS_H */ diff --git a/plat/mediatek/mt8192/plat_pm.c b/plat/mediatek/mt8192/plat_pm.c index 6dfb6c905..018e41837 100644 --- a/plat/mediatek/mt8192/plat_pm.c +++ b/plat/mediatek/mt8192/plat_pm.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -168,6 +169,8 @@ static void plat_mcusys_pwron_common(unsigned int cpu, mt_gic_distif_restore(); gic_sgi_restore_all(); + dfd_resume(); + plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state); } diff --git a/plat/mediatek/mt8192/plat_sip_calls.c b/plat/mediatek/mt8192/plat_sip_calls.c index f567f02ef..353faf8a2 100644 --- a/plat/mediatek/mt8192/plat_sip_calls.c +++ b/plat/mediatek/mt8192/plat_sip_calls.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "plat_sip_calls.h" uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid, @@ -34,6 +35,11 @@ uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid, ret = apusys_kernel_ctrl(x1, x2, x3, x4, &rnd_val0); SMC_RET2(handle, ret, rnd_val0); break; + case MTK_SIP_KERNEL_DFD_AARCH32: + case MTK_SIP_KERNEL_DFD_AARCH64: + ret = dfd_smc_dispatcher(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; default: ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); break; diff --git a/plat/mediatek/mt8192/platform.mk b/plat/mediatek/mt8192/platform.mk index 7761a55bf..cbdaadd94 100644 --- a/plat/mediatek/mt8192/platform.mk +++ b/plat/mediatek/mt8192/platform.mk @@ -19,6 +19,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ -I${MTK_PLAT_SOC}/drivers/apusys/ \ -I${MTK_PLAT_SOC}/drivers/dcm \ -I${MTK_PLAT_SOC}/drivers/devapc \ + -I${MTK_PLAT_SOC}/drivers/dfd \ -I${MTK_PLAT_SOC}/drivers/emi_mpu/ \ -I${MTK_PLAT_SOC}/drivers/gpio/ \ -I${MTK_PLAT_SOC}/drivers/mcdi/ \ @@ -68,6 +69,7 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \ ${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \ ${MTK_PLAT_SOC}/drivers/devapc/devapc.c \ + ${MTK_PLAT_SOC}/drivers/dfd/plat_dfd.c \ ${MTK_PLAT_SOC}/drivers/emi_mpu/emi_mpu.c \ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ ${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \