diff --git a/docs/plat/rockchip.rst b/docs/plat/rockchip.rst index 01cf176d6..53f63b59f 100644 --- a/docs/plat/rockchip.rst +++ b/docs/plat/rockchip.rst @@ -10,6 +10,7 @@ This includes right now: - rk3328: Quad-Core Cortex-A53 - rk3368: Octa-Core Cortex-A53 - rk3399: Hexa-Core Cortex-A53/A72 +- rk3566/rk3568: Quad-Core Cortex-A55 Boot Sequence diff --git a/include/lib/cpus/aarch64/dsu_def.h b/include/lib/cpus/aarch64/dsu_def.h index 577de6199..51fbfd1db 100644 --- a/include/lib/cpus/aarch64/dsu_def.h +++ b/include/lib/cpus/aarch64/dsu_def.h @@ -30,6 +30,7 @@ * DSU Cluster Auxiliary Control registers definitions ********************************************************************/ #define CLUSTERACTLR_EL1 S3_0_C15_C3_3 +#define CLUSTERPWRCTLR_EL1 S3_0_C15_C3_5 #define CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING (ULL(1) << 15) #define CLUSTERACTLR_EL1_DISABLE_SCLK_GATING (ULL(3) << 15) @@ -39,4 +40,7 @@ ********************************************************************/ #define DSU_ERRATA_936184_MASK (U(0x3) << 15) +#ifndef __ASSEMBLER__ +void dsu_pwr_dwn(void); +#endif #endif /* DSU_DEF_H */ diff --git a/lib/cpus/aarch64/dsu_helpers.S b/lib/cpus/aarch64/dsu_helpers.S index 8e5b4598c..3c5bf2ea1 100644 --- a/lib/cpus/aarch64/dsu_helpers.S +++ b/lib/cpus/aarch64/dsu_helpers.S @@ -24,6 +24,7 @@ */ .globl check_errata_dsu_798953 .globl errata_dsu_798953_wa + .globl dsu_pwr_dwn func check_errata_dsu_798953 mov x2, #ERRATA_APPLIES @@ -202,3 +203,15 @@ func errata_dsu_2313941_wa 1: ret x8 endfunc errata_dsu_2313941_wa + + /* --------------------------------------------- + * controls power features of the cluster + * 1. Cache portion power not request + * 2. Disable the retention circuit + * --------------------------------------------- + */ +func dsu_pwr_dwn + msr CLUSTERPWRCTLR_EL1, xzr + isb + ret +endfunc dsu_pwr_dwn diff --git a/plat/rockchip/common/aarch64/plat_helpers.S b/plat/rockchip/common/aarch64/plat_helpers.S index c4c0dec3c..dde66aa7d 100644 --- a/plat/rockchip/common/aarch64/plat_helpers.S +++ b/plat/rockchip/common/aarch64/plat_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -150,7 +150,12 @@ endfunc platform_cpu_warmboot * Per-CPU Secure entry point - resume or power up * -------------------------------------------------------------------- */ + +#if USE_COHERENT_MEM .section .tzfw_coherent_mem, "a" +#else + .data +#endif .align 3 cpuson_entry_point: .rept PLATFORM_CORE_COUNT diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c index 81e852062..d563dfd8f 100644 --- a/plat/rockchip/common/aarch64/platform_common.c +++ b/plat/rockchip/common/aarch64/platform_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,8 +13,6 @@ #include #include #include -#include - #include #ifdef PLAT_RK_CCI_BASE @@ -42,9 +40,10 @@ static const int cci_map[] = { mmap_add_region(ro_start, ro_start, \ ro_limit - ro_start, \ MT_MEMORY | MT_RO | MT_SECURE); \ - mmap_add_region(coh_start, coh_start, \ - coh_limit - coh_start, \ - MT_DEVICE | MT_RW | MT_SECURE); \ + if ((coh_limit - coh_start) != 0) \ + mmap_add_region(coh_start, coh_start, \ + coh_limit - coh_start, \ + MT_DEVICE | MT_RW | MT_SECURE); \ mmap_add(plat_rk_mmap); \ rockchip_plat_mmu_el##_el(); \ init_xlat_tables(); \ diff --git a/plat/rockchip/common/bl31_plat_setup.c b/plat/rockchip/common/bl31_plat_setup.c index 59db3d85c..62147226a 100644 --- a/plat/rockchip/common/bl31_plat_setup.c +++ b/plat/rockchip/common/bl31_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -93,10 +93,19 @@ void bl31_plat_arch_setup(void) { plat_cci_init(); plat_cci_enable(); +#if USE_COHERENT_MEM plat_configure_mmu_el3(BL_CODE_BASE, BL_COHERENT_RAM_END - BL_CODE_BASE, BL_CODE_BASE, BL_CODE_END, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); +#else + plat_configure_mmu_el3(BL31_START, + BL31_END - BL31_START, + BL_CODE_BASE, + BL_CODE_END, + 0, + 0); +#endif } diff --git a/plat/rockchip/common/include/plat_private.h b/plat/rockchip/common/include/plat_private.h index 990d1065f..465f372e5 100644 --- a/plat/rockchip/common/include/plat_private.h +++ b/plat/rockchip/common/include/plat_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2023, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,9 +11,9 @@ #include -#include -#include #include +#include +#include #include #define __sramdata __attribute__((section(".sram.data"))) @@ -135,7 +135,6 @@ extern const unsigned char rockchip_power_domain_tree_desc[]; extern void *pmu_cpuson_entrypoint; extern u_register_t cpuson_entry_point[PLATFORM_CORE_COUNT]; extern uint32_t cpuson_flags[PLATFORM_CORE_COUNT]; - extern const mmap_region_t plat_rk_mmap[]; uint32_t rockchip_get_uart_base(void); diff --git a/plat/rockchip/rk3568/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3568/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 000000000..8ddea0ee2 --- /dev/null +++ b/plat/rockchip/rk3568/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +.macro func_rockchip_clst_warmboot + /* Nothing to do for rk3568 */ +.endm + +.macro rockchip_clst_warmboot_data + /* Nothing to do for rk3568 */ +.endm diff --git a/plat/rockchip/rk3568/drivers/pmu/pmu.c b/plat/rockchip/rk3568/drivers/pmu/pmu.c new file mode 100644 index 000000000..970caec52 --- /dev/null +++ b/plat/rockchip/rk3568/drivers/pmu/pmu.c @@ -0,0 +1,543 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * The power management unit (PMU) is designed for controlling power resources. + * The PMU is dedicated for managing the power of the whole chip. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Use this macro to instantiate lock before it is used in below + * rockchip_pd_lock_xxx() macros + */ +DECLARE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t grf_ddr_con3; +static struct psram_data_t *psram_sleep_cfg = + (struct psram_data_t *)&sys_sleep_flag_sram; + +/* + * These are wrapper macros to the powe domain Bakery Lock API. + */ +#define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) +#define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) +#define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) + +void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) +{ + uint64_t ctrl; + + __asm__ volatile ("mrs %0, " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) : "=r" (ctrl)); + ctrl |= 0x01; + __asm__ volatile ("msr " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) ", %0" : : "r" (ctrl)); + isb(); + + while (1) + wfi(); +} + +static void pmu_pmic_sleep_mode_config(void) +{ + /* pmic sleep function selection + * 1'b0: From reset pulse generator, can reset external PMIC + * 1'b1: From pmu block, only support sleep function for external PMIC + */ + mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), WRITE_MASK_SET(BIT(7))); + mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_IOMUX_L, PMIC_SLEEP_FUN); +} + +static void pmu_wakeup_source_config(void) +{ + /* config wakeup source */ + mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, WRITE_MASK_SET(BIT(WAKEUP_GPIO0_INT_EN))); + + INFO("WAKEUP: PMU_WAKEUP_INT_CON:0x%x, reg: 0x%x\n", + mmio_read_32(PMU_BASE + PMU_WAKEUP_INT_CON), PMU_WAKEUP_INT_CON); +} + +static void pmu_pll_powerdown_config(void) +{ + uint32_t pll_id; + + /* PLL power down by PMU */ + pll_id = BIT(APLL_PD_ENA) | + BIT(CPLL_PD_ENA) | + BIT(GPLL_PD_ENA) | + BIT(MPLL_PD_ENA) | + BIT(NPLL_PD_ENA) | + BIT(HPLL_PD_ENA) | + BIT(PPLL_PD_ENA) | + BIT(VPLL_PD_ENA); + mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(pll_id)); + INFO("PLL: PMU_PLLPD_CON(0x%x):0x%x\n", + PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON)); +} + +static void pmu_stable_count_config(void) +{ + mmio_write_32(PMU_BASE + PMU_DSU_STABLE_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_PMIC_STABLE_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_OSC_STABLE_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_WAKEUP_RSTCLR_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_PLL_LOCK_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_DSU_PWRUP_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_DSU_PWRDN_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_GPU_VOLUP_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_GPU_VOLDN_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_PWM_SWITCH_CNT, 0x180); + mmio_write_32(PMU_BASE + PMU_DBG_RST_CNT, 0x180); +} + +static void pmu_pd_powerdown_config(void) +{ + uint32_t pwr_gate_con, pwr_dwn_st, pmu_bus_idle_con0 = 0; + uint32_t pmu_bus_idle_con1; + + /* Pd power down by PMU */ + pwr_dwn_st = mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST); + pwr_gate_con = ~pwr_dwn_st & 0x3ff; + + if (pwr_gate_con & BIT(PD_GPU_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_GPU); + } + + if (pwr_gate_con & BIT(PD_NPU_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_NPU); + } + + if (pwr_gate_con & BIT(PD_RKVENC_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVENC); + } + + if (pwr_gate_con & BIT(PD_RKVDEC_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVDEC); + } + + if (pwr_gate_con & BIT(PD_RGA_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_RGA); + } + + if (pwr_gate_con & BIT(PD_VI_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_VI); + } + + if (pwr_gate_con & BIT(PD_VO_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_VO); + } + + if (pwr_gate_con & BIT(PD_PIPE_DWN_ENA)) { + pmu_bus_idle_con0 |= BIT(IDLE_REQ_PIPE); + } + + pmu_bus_idle_con0 |= BIT(IDLE_REQ_GIC_AUDIO) | + BIT(IDLE_REQ_MSCH) | + BIT(IDLE_REQ_PHP) | + BIT(IDLE_REQ_SECURE_FLASH) | + BIT(IDLE_REQ_PERIMID) | + BIT(IDLE_REQ_USB) | + BIT(IDLE_REQ_BUS); + + /* Enable power down PD by PMU automatically */ + pwr_gate_con |= (BIT(PD_GPU_DWN_ENA) | + BIT(PD_NPU_DWN_ENA) | + BIT(PD_VPU_DWN_ENA) | + BIT(PD_RKVENC_DWN_ENA) | + BIT(PD_RKVDEC_DWN_ENA) | + BIT(PD_RGA_DWN_ENA) | + BIT(PD_VI_DWN_ENA) | + BIT(PD_VO_DWN_ENA) | + BIT(PD_PIPE_DWN_ENA)) << 16; + + pmu_bus_idle_con1 = 0; + + mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, pwr_gate_con); + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, WRITE_MASK_SET(pmu_bus_idle_con0)); + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, WRITE_MASK_SET(pmu_bus_idle_con1)); + + /* When perform idle operation, + * corresponding clock can be opened or gated automatically + */ + mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff); + mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007); + + mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, WRITE_MASK_SET(BIT(VD_NPU_ENA))); + + mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(PWRDN_BYPASS))); + mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(BUS_BYPASS))); + + INFO("PD & BUS:PMU_PWR_DWN_ST(0x%x):0x%x\n", + PMU_PWR_DWN_ST, mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST)); + INFO("PD & BUS:PMU_PWR_GATE_CON(0x%x):0x%x\n", + PMU_PWR_GATE_CON, mmio_read_32(PMU_BASE + PMU_PWR_GATE_CON)); + INFO("PD & BUS:PMU_BUS_IDLE_CON0(0x%x):0x%x\n", + PMU_BUS_IDLE_CON0, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON0)); + INFO("PD & BUS:PMU_BUS_IDLE_CON1(0x%x):0x%x\n", + PMU_BUS_IDLE_CON1, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON1)); + INFO("PD & BUS:PMU_PWR_CON(0x%x):0x%x\n", + PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON)); +} + +static void pmu_ddr_suspend_config(void) +{ + uint32_t pmu_ddr_pwr_con; + + pmu_ddr_pwr_con = BIT(DDR_SREF_ENA) | + BIT(DDRIO_RET_ENTER_ENA) | + BIT(DDRIO_RET_EXIT_ENA) | + BIT(DDRPHY_AUTO_GATING_ENA); + + mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, WRITE_MASK_SET(pmu_ddr_pwr_con)); + /* DPLL power down by PMU */ + mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(BIT(DPLL_PD_ENA))); + mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DDR_BYPASS))); + + grf_ddr_con3 = mmio_read_32(DDRGRF_BASE + GRF_DDR_CON3); + + mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, 0x00600020); + + pmu_ddr_pwr_con = mmio_read_32(PMU_BASE + PMU_DDR_PWR_CON); + + INFO("DDR: PMU_PLLPD_CON(0x%x):0x%x\n", + PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON)); + INFO("DDR: PMU_DDR_PWR_CON(0x%x):\t0x%x\n", + PMU_DDR_PWR_CON, pmu_ddr_pwr_con); + + if (pmu_ddr_pwr_con & BIT(DDR_SREF_ENA)) { + INFO("\t DDR_SREF_ENA\n"); + } + + if (pmu_ddr_pwr_con & BIT(DDRIO_RET_ENTER_ENA)) { + INFO("\t DDRIO_RET_ENTER_ENA\n"); + } + + if (pmu_ddr_pwr_con & BIT(DDRIO_RET_EXIT_ENA)) { + INFO("\t DDRIO_RET_EXIT_ENA\n"); + } + + if (pmu_ddr_pwr_con & BIT(DDRPHY_AUTO_GATING_ENA)) { + INFO("\t DDRPHY_AUTO_GATING_ENA\n"); + } +} + +static void pmu_dsu_suspend_config(void) +{ + uint32_t pmu_dsu_pwr_con; + + pmu_dsu_pwr_con = BIT(DSU_PWRDN_ENA); + + mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0x000f000f); + mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, WRITE_MASK_SET(pmu_dsu_pwr_con)); + mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DSU_BYPASS))); + dsu_pwr_dwn(); + + INFO("DSU: PMU_DSU_PWR_CON(0x%x): 0x%x\n", + PMU_DSU_PWR_CON, mmio_read_32(PMU_BASE + PMU_DSU_PWR_CON)); + INFO("DSU: PMU_CLUSTER_IDLE_CON(0x%x),: 0x%x\n", + PMU_CLUSTER_IDLE_CON, mmio_read_32(PMU_BASE + PMU_CLUSTER_IDLE_CON)); + INFO("DSU: PMU_PWR_CON(0x%x),: 0x%x\n", + PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON)); +} + +static void pmu_cpu_powerdown_config(void) +{ + uint32_t pmu_cluster_pwr_st, cpus_state, cpus_bypass; + + pmu_cluster_pwr_st = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST); + cpus_state = pmu_cluster_pwr_st & 0x0f; + + cpus_bypass = cpus_state << CPU0_BYPASS; + + INFO("CPU: PMU_CLUSTER_PWR_ST(0x%x):0x%x\n", + PMU_CLUSTER_PWR_ST, mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST)); + mmio_write_32(PMU_BASE + PMU_PWR_CON, (0xf << (16 + CPU0_BYPASS)) | cpus_bypass); + + INFO("CPU: PMU_PWR_CON(0x%x), 0x%x\n", + PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON)); +} + +static void pvtm_32k_config(void) +{ + uint32_t pmu_cru_pwr_con; + uint32_t pvtm_freq_khz, pvtm_div; + + mmio_write_32(PMUCRU_BASE + PMUCRU_PMUGATE_CON01, 0x38000000); + mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00020002); + dsb(); + + mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x001c0000); + + mmio_write_32(PMUPVTM_BASE + PVTM_CON1, PVTM_CALC_CNT); + dsb(); + + mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00010001); + dsb(); + + while (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) < 30) { + ; + } + + dsb(); + while (!(mmio_read_32(PMUPVTM_BASE + PVTM_STATUS0) & 0x1)) { + ; + } + + pvtm_freq_khz = (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) * 24000 + + PVTM_CALC_CNT / 2) / PVTM_CALC_CNT; + pvtm_div = (pvtm_freq_khz + 16) / 32; + + mmio_write_32(PMUGRF_BASE + PMU_GRF_DLL_CON0, pvtm_div); + + mmio_write_32(PMUCRU_BASE + PMUCRU_PMUCLKSEL_CON00, 0x00c00000); + + pmu_cru_pwr_con = BIT(ALIVE_32K_ENA) | BIT(OSC_DIS_ENA); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 32000 * 10); + + mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con)); + INFO("PVTM: PMU_CRU_PWR_CON(0x0%x): 0x%x\n", + PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON)); +} + +static void pmu_cru_suspendmode_config(void) +{ + uint32_t pmu_cru_pwr_con; + + pmu_cru_pwr_con = BIT(ALIVE_OSC_ENA); + + mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con)); + INFO("CRU: PMU_CRU_PWR_CON(0x0%x): 0x%x\n", + PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON)); +} + +static void pmu_suspend_cru_fsm(void) +{ + pmu_pmic_sleep_mode_config(); + + /* Global interrupt disable */ + mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, CLB_INT_DISABLE); + mmio_write_32(PMU_BASE + PMU_PWR_CON, CPUS_BYPASS); + + pmu_stable_count_config(); + pmu_wakeup_source_config(); + mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x5dc0 * 20000); + /* default cru config */ + mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(BIT(ALIVE_OSC_ENA))); + + pmu_cru_suspendmode_config(); + pmu_cpu_powerdown_config(); + pmu_pll_powerdown_config(); + pmu_pd_powerdown_config(); + pmu_ddr_suspend_config(); + pmu_dsu_suspend_config(); + pvtm_32k_config(); + mmio_write_32(PMU_BASE + PMU_PWR_CON, 0x00010001); +} + +static void pmu_reinit(void) +{ + mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, grf_ddr_con3 | 0xffff0000); + mmio_write_32(PMU_BASE + PMU_PWR_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, 0xffff0000); + + mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, 0xffff0000); + + mmio_write_32(PMU_BASE + PMU_PLLPD_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_INFO_TX_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, 0xffff0000); + mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0xffff0000); +} + +void rockchip_plat_mmu_el3(void) +{ +} + +int rockchip_soc_cores_pwr_dm_suspend(void) +{ + return 0; +} + +int rockchip_soc_cores_pwr_dm_resume(void) +{ + return 0; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + psram_sleep_cfg->pm_flag = 0; + flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag), + sizeof(uint32_t)); + pmu_suspend_cru_fsm(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + pmu_reinit(); + plat_rockchip_gic_cpuif_enable(); + psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT; + flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag), + sizeof(uint32_t)); + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) +{ + uint32_t apm_value, offset, idx; + + apm_value = BIT(core_pm_en) | BIT(core_pm_int_wakeup_glb_msk); + + if (pd_cfg == core_pwr_wfi_int) { + apm_value |= BIT(core_pm_int_wakeup_en); + } + + idx = cpu_id / 2; + offset = (cpu_id % 2) << 3; + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx), + BITS_WITH_WMASK(apm_value, 0xf, offset)); + dsb(); + + return 0; +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t offset, idx; + + idx = cpu_id / 2; + offset = (cpu_id % 2) << 3; + + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx), + WMSK_BIT(core_pm_en + offset)); + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx), + BIT_WITH_WMSK(core_pm_sft_wakeup_en + offset)); + dsb(); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) +{ + uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); + + assert(cpu_id < PLATFORM_CORE_COUNT); + + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags)); + flush_dcache_range((uintptr_t)cpuson_entry_point, + sizeof(cpuson_entry_point)); + + cpus_power_domain_on(cpu_id); + return 0; +} + +int rockchip_soc_cores_pwr_dm_off(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + + cpus_power_domain_off(cpu_id, + core_pwr_wfi); + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + uint32_t cpu_id = plat_my_core_pos(); + uint32_t offset, idx; + + /* Disable core_pm */ + idx = cpu_id / 2; + offset = (cpu_id % 2) << 3; + mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx), + BITS_WITH_WMASK(0, 0xf, offset)); + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t tmp; + + cpus_power_domain_off(1, 0); + cpus_power_domain_off(2, 0); + cpus_power_domain_off(3, 0); + + mmio_write_32(SYSSRAM_BASE + 0x04, 0xdeadbeaf); + mmio_write_32(SYSSRAM_BASE + 0x08, (uintptr_t)&rockchip_soc_sys_pd_pwr_dn_wfi); + sev(); + + do { + tmp = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST); + } while ((tmp & 0xe) != 0xe); +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + rockchip_pd_lock_init(); + nonboot_cpus_off(); + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = PMU_CPU_HOTPLUG; + + psram_sleep_cfg->ddr_data = (uint64_t)0; + psram_sleep_cfg->sp = PSRAM_SP_TOP; + psram_sleep_cfg->ddr_flag = 0x00; + psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; + psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT; + + /* + * When perform idle operation, corresponding clock can be + * opened or gated automatically. + */ + mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff); + mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007); + + /* grf_con_pmic_sleep_sel + * pmic sleep function selection + * 1'b0: From reset pulse generator, can reset external PMIC + * 1'b1: From pmu block, only support sleep function for external PMIC + */ + mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), 0x00800080); + + /* + * force jtag control + * 1'b0: CPU debug port IO mux is controlled by sdmmc_detect_en status + * 1'b0: CPU debug port IO mux IS controlled by GRF + */ + mmio_write_32(SGRF_BASE + 0x008, 0x00100000); + + /* + * remap + * 2'b00: Boot from boot-rom. + * 2'b01: Boot from pmu mem. + * 2'b10: Boot from sys mem. + */ + mmio_write_32(PMUSGRF_BASE + PMU_SGRF_SOC_CON1, 0x18000800); +} diff --git a/plat/rockchip/rk3568/drivers/pmu/pmu.h b/plat/rockchip/rk3568/drivers/pmu/pmu.h new file mode 100644 index 000000000..5821514ba --- /dev/null +++ b/plat/rockchip/rk3568/drivers/pmu/pmu.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PMU_H__ +#define __PMU_H__ + +#define PMU_VERSION 0x0000 +#define PMU_PWR_CON 0x0004 +#define PMU_MAIN_PWR_STATE 0x0008 +#define PMU_INT_MASK_CON 0x000C +#define PMU_WAKEUP_INT_CON 0x0010 +#define PMU_WAKEUP_INT_ST 0x0014 +#define PMU_WAKEUP_EDGE_CON 0x0018 +#define PMU_WAKEUP_EDGE_ST 0x001C +#define PMU_BUS_IDLE_CON0 0x0040 +#define PMU_BUS_IDLE_CON1 0x0044 +#define PMU_BUS_IDLE_SFTCON0 0x0050 +#define PMU_BUS_IDLE_SFTCON1 0x0054 +#define PMU_BUS_IDLE_ACK 0x0060 +#define PMU_BUS_IDLE_ST 0x0068 +#define PMU_NOC_AUTO_CON0 0x0070 +#define PMU_NOC_AUTO_CON1 0x0074 +#define PMU_DDR_PWR_CON 0x0080 +#define PMU_DDR_PWR_SFTCON 0x0084 +#define PMU_DDR_PWR_STATE 0x0088 +#define PMU_DDR_PWR_ST 0x008C +#define PMU_PWR_GATE_CON 0x0090 +#define PMU_PWR_GATE_STATE 0x0094 +#define PMU_PWR_DWN_ST 0x0098 +#define PMU_PWR_GATE_SFTCON 0x00A0 +#define PMU_VOL_GATE_SFTCON 0x00A8 +#define PMU_CRU_PWR_CON 0x00B0 +#define PMU_CRU_PWR_SFTCON 0x00B4 +#define PMU_CRU_PWR_STATE 0x00B8 +#define PMU_PLLPD_CON 0x00C0 +#define PMU_PLLPD_SFTCON 0x00C4 +#define PMU_INFO_TX_CON 0x00D0 +#define PMU_DSU_STABLE_CNT 0x0100 +#define PMU_PMIC_STABLE_CNT 0x0104 +#define PMU_OSC_STABLE_CNT 0x0108 +#define PMU_WAKEUP_RSTCLR_CNT 0x010C +#define PMU_PLL_LOCK_CNT 0x0110 +#define PMU_DSU_PWRUP_CNT 0x0118 +#define PMU_DSU_PWRDN_CNT 0x011C +#define PMU_GPU_VOLUP_CNT 0x0120 +#define PMU_GPU_VOLDN_CNT 0x0124 +#define PMU_WAKEUP_TIMEOUT_CNT 0x0128 +#define PMU_PWM_SWITCH_CNT 0x012C +#define PMU_DBG_RST_CNT 0x0130 +#define PMU_SYS_REG0 0x0180 +#define PMU_SYS_REG1 0x0184 +#define PMU_SYS_REG2 0x0188 +#define PMU_SYS_REG3 0x018C +#define PMU_SYS_REG4 0x0190 +#define PMU_SYS_REG5 0x0194 +#define PMU_SYS_REG6 0x0198 +#define PMU_SYS_REG7 0x019C +#define PMU_DSU_PWR_CON 0x0300 +#define PMU_DSU_PWR_SFTCON 0x0304 +#define PMU_DSU_AUTO_CON 0x0308 +#define PMU_DSU_PWR_STATE 0x030C +#define PMU_CPU_AUTO_PWR_CON0 0x0310 +#define PMU_CPU_AUTO_PWR_CON1 0x0314 +#define PMU_CPU_PWR_SFTCON 0x0318 +#define PMU_CLUSTER_PWR_ST 0x031C +#define PMU_CLUSTER_IDLE_CON 0x0320 +#define PMU_CLUSTER_IDLE_SFTCON 0x0324 +#define PMU_CLUSTER_IDLE_ACK 0x0328 +#define PMU_CLUSTER_IDLE_ST 0x032C +#define PMU_DBG_PWR_CON 0x0330 + +/* PMU_SGRF */ +#define PMU_SGRF_SOC_CON1 0x0004 +#define PMU_SGRF_FAST_BOOT_ADDR 0x0180 + +/* sys grf */ +#define GRF_CPU_STATUS0 0x0420 + +#define CRU_SOFTRST_CON00 0x0400 + +#define CORES_PM_DISABLE 0x0 +#define PD_CHECK_LOOP 500 +#define WFEI_CHECK_LOOP 500 + +#define PMUSGRF_SOC_CON(i) ((i) * 0x4) +/* Needed aligned 16 bytes for sp stack top */ +#define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf) +#define PMU_CPUAPM_CON(cpu) (0x0310 + (cpu) * 0x4) + +#define PMIC_SLEEP_FUN 0x07000100 +#define PMIC_SLEEP_GPIO 0x07000000 +#define GPIO_SWPORT_DR_L 0x0000 +#define GPIO_SWPORT_DR_H 0x0004 +#define GPIO_SWPORT_DDR_L 0x0008 +#define GPIO_SWPORT_DDR_H 0x000C +#define PMIC_SLEEP_HIGH_LEVEL 0x00040004 +#define PMIC_SLEEP_LOW_LEVEL 0x00040000 +#define PMIC_SLEEP_OUT 0x00040004 +#define CPUS_BYPASS 0x007e4f7e +#define CLB_INT_DISABLE 0x00010001 +#define WRITE_MASK_SET(value) ((value << 16) | value) +#define WRITE_MASK_CLR(value) ((value << 16)) + +enum pmu_cores_pm_by_wfi { + core_pm_en = 0, + core_pm_int_wakeup_en, + core_pm_int_wakeup_glb_msk, + core_pm_sft_wakeup_en, +}; + +/* The ways of cores power domain contorlling */ +enum cores_pm_ctr_mode { + core_pwr_pd = 0, + core_pwr_wfi = 1, + core_pwr_wfi_int = 2 +}; + +/* PMU_PWR_DWN_ST */ +enum pmu_pdid { + PD_GPU, + PD_NPU, + PD_VPU, + PD_RKVENC, + PD_RKVDEC, + PD_RGA, + PD_VI, + PD_VO, + PD_PIPE, + PD_CENTER, + PD_END +}; + +/* PMU_PWR_CON */ +enum pmu_pwr_con { + POWRMODE_EN, + DSU_BYPASS, + BUS_BYPASS = 4, + DDR_BYPASS, + PWRDN_BYPASS, + CRU_BYPASS, + CPU0_BYPASS, + CPU1_BYPASS, + CPU2_BYPASS, + CPU3_BYPASS, + PMU_SLEEP_LOW = 15, +}; + +/* PMU_CRU_PWR_CON */ +enum pmu_cru_pwr_con { + ALIVE_32K_ENA, + OSC_DIS_ENA, + WAKEUP_RST_ENA, + INPUT_CLAMP_ENA, + + ALIVE_OSC_ENA, + POWER_OFF_ENA, + PWM_SWITCH_ENA, + PWM_GPIO_IOE_ENA, + + PWM_SWITCH_IOUT, + PD_BUS_CLK_SRC_GATE_ENA, + PD_PERI_CLK_SRC_GATE_ENA, + PD_PMU_CLK_SRC_GATE_ENA, + + PMUMEM_CLK_SRC_GATE_ENA, + PWR_CON_END +}; + +/* PMU_PLLPD_CON */ +enum pmu_pllpd_con { + APLL_PD_ENA, + DPLL_PD_ENA, + CPLL_PD_ENA, + GPLL_PD_ENA, + MPLL_PD_ENA, + NPLL_PD_ENA, + HPLL_PD_ENA, + PPLL_PD_ENA, + VPLL_PD_ENA, + PLL_PD_END +}; + +/* PMU_DSU_PWR_CON */ +enum pmu_dsu_pwr_con { + DSU_PWRDN_ENA = 2, + DSU_PWROFF_ENA, + DSU_RET_ENA = 6, + CLUSTER_CLK_SRC_GATE_ENA, + DSU_PWR_CON_END +}; + +enum cpu_power_state { + CPU_POWER_ON, + CPU_POWER_OFF, + CPU_EMULATION_OFF, + CPU_RETENTION, + CPU_DEBUG +}; + +enum dsu_power_state { + DSU_POWER_ON, + CLUSTER_TRANSFER_IDLE, + DSU_POWER_DOWN, + DSU_OFF, + DSU_WAKEUP, + DSU_POWER_UP, + CLUSTER_TRANSFER_RESUME, + DSU_FUNCTION_RETENTION +}; + +enum pmu_wakeup_int_con { + WAKEUP_CPU0_INT_EN, + WAKEUP_CPU1_INT_EN, + WAKEUP_CPU2_INT_EN, + WAKEUP_CPU3_INT_EN, + WAKEUP_GPIO0_INT_EN, + WAKEUP_UART0_EN, + WAKEUP_SDMMC0_EN, + WAKEUP_SDMMC1_EN, + WAKEUP_SDMMC2_EN, + WAKEUP_USB_EN, + WAKEUP_PCIE_EN, + WAKEUP_VAD_EN, + WAKEUP_TIMER_EN, + WAKEUP_PWM0_EN, + WAKEUP_TIMEROUT_EN, + WAKEUP_MCU_SFT_EN, +}; + +enum pmu_wakeup_int_st { + WAKEUP_CPU0_INT_ST, + WAKEUP_CPU1_INT_ST, + WAKEUP_CPU2_INT_ST, + WAKEUP_CPU3_INT_ST, + WAKEUP_GPIO0_INT_ST, + WAKEUP_UART0_ST, + WAKEUP_SDMMC0_ST, + WAKEUP_SDMMC1_ST, + WAKEUP_SDMMC2_ST, + WAKEUP_USB_ST, + WAKEUP_PCIE_ST, + WAKEUP_VAD_ST, + WAKEUP_TIMER_ST, + WAKEUP_PWM0_ST, + WAKEUP_TIMEOUT_ST, + WAKEUP_SYS_INT_ST, +}; + +enum pmu_bus_idle_con0 { + IDLE_REQ_MSCH, + IDLE_REQ_GPU, + IDLE_REQ_NPU, + IDLE_REQ_VI, + IDLE_REQ_VO, + IDLE_REQ_RGA, + IDLE_REQ_VPU, + IDLE_REQ_RKVENC, + IDLE_REQ_RKVDEC, + IDLE_REQ_GIC_AUDIO, + IDLE_REQ_PHP, + IDLE_REQ_PIPE, + IDLE_REQ_SECURE_FLASH, + IDLE_REQ_PERIMID, + IDLE_REQ_USB, + IDLE_REQ_BUS, +}; + +enum pmu_bus_idle_con1 { + IDLE_REQ_TOP1, + IDLE_REQ_TOP2, + IDLE_REQ_PMU, +}; + +enum pmu_pwr_gate_con { + PD_GPU_DWN_ENA, + PD_NPU_DWN_ENA, + PD_VPU_DWN_ENA, + PD_RKVENC_DWN_ENA, + + PD_RKVDEC_DWN_ENA, + PD_RGA_DWN_ENA, + PD_VI_DWN_ENA, + PD_VO_DWN_ENA, + + PD_PIPE_DWN_ENA, + PD_CENTER_DWN_ENA, +}; + +enum pmu_ddr_pwr_con { + DDR_SREF_ENA, + DDRIO_RET_ENTER_ENA, + DDRIO_RET_EXIT_ENA = 2, + DDRPHY_AUTO_GATING_ENA = 4, +}; + +enum pmu_vol_gate_soft_con { + VD_GPU_ENA, + VD_NPU_ENA, +}; + +#endif /* __PMU_H__ */ diff --git a/plat/rockchip/rk3568/drivers/soc/soc.c b/plat/rockchip/rk3568/drivers/soc/soc.c new file mode 100644 index 000000000..2af388735 --- /dev/null +++ b/plat/rockchip/rk3568/drivers/soc/soc.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(RKFPGA_DEV_RNG0_BASE, RKFPGA_DEV_RNG0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + + { 0 } +}; + +/* The RockChip power domain tree descriptor */ +const unsigned char rockchip_power_domain_tree_desc[] = { + /* No of root nodes */ + PLATFORM_SYSTEM_COUNT, + /* No of children for the root node */ + PLATFORM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +static void secure_timer_init(void) +{ + mmio_write_32(STIMER0_CHN_BASE(1) + TIMER_CONTROL_REG, TIMER_DIS); + mmio_write_32(STIMER0_CHN_BASE(1) + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER0_CHN_BASE(1) + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER0_CHN_BASE(1) + TIMER_CONTROL_REG, TIMER_EN); +} + +static void sgrf_init(void) +{ + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(0), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(1), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(2), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(3), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(4), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(5), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(6), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(7), 0xffff0000); + mmio_write_32(SGRF_BASE + SGRF_FIREWALL_SLV_CON(8), 0xffff0000); + + mmio_write_32(DDRSGRF_BASE + FIREWALL_DDR_FW_DDR_CON_REG, 0xffff0000); +} + +static void set_pll_slow_mode(uint32_t clk_pll) +{ + mmio_write_32(CRU_BASE + CRU_MODE_CON00, 0x03 << (16 + clk_pll * 2)); +} + +static void __dead2 soc_global_soft_reset(void) +{ + set_pll_slow_mode(CLK_CPLL); + set_pll_slow_mode(CLK_GPLL); + set_pll_slow_mode(CLK_NPLL); + set_pll_slow_mode(CLK_VPLL); + set_pll_slow_mode(CLK_USBPLL); + set_pll_slow_mode(CLK_APLL); + mmio_write_32(PMUCRU_BASE + PMUCRU_MODE_CON00, 0x000f0000); + + dsb(); + mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL); + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) { + ; + } +} + +static void rockchip_system_reset_init(void) +{ + mmio_write_32(GRF_BASE + 0x0508, 0x00100010); + mmio_write_32(CRU_BASE + 0x00dc, 0x01030103); +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + soc_global_soft_reset(); +} + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + sgrf_init(); + rockchip_system_reset_init(); + NOTICE("BL31: Rockchip release version: v%d.%d\n", + MAJOR_VERSION, MINOR_VERSION); +} + diff --git a/plat/rockchip/rk3568/drivers/soc/soc.h b/plat/rockchip/rk3568/drivers/soc/soc.h new file mode 100644 index 000000000..41a2586a3 --- /dev/null +++ b/plat/rockchip/rk3568/drivers/soc/soc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SOC_H__ +#define __SOC_H__ + +#define RKFPGA_DEV_RNG0_BASE 0xf8000000 +#define RKFPGA_DEV_RNG0_SIZE 0x07fff000 + +#define CRU_MODE_CON00 0x00c0 +#define PMUCRU_MODE_CON00 0x0080 + +#define CRU_GLB_SRST_FST 0x00d4 +#define GLB_SRST_FST_CFG_VAL 0xfdb9 + +#define PMU_GRF_GPIO0A_IOMUX_L 0x00 +#define PMU_GRF_SOC_CON(i) (0x0100 + i * 4) + +#define CRU_SOFTRST_CON 0x300 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 26 +#define GRF_DDR_CON3 0x000c +#define SGRF_FIREWALL_SLV_CON(i) (0x240 + i * 4) + +#define FIREWALL_DDR_FW_DDR_CON_REG 0x80 + + /* low 32 bits */ +#define TIMER_LOAD_COUNT0 0x00 +#define TIMER_LOAD_COUNT1 0x04 +#define TIMER_CURRENT_VALUE0 0x08 +#define TIMER_CURRENT_VALUE1 0x0c +#define TIMER_CONTROL_REG 0x10 +#define TIMER_INTSTATUS 0x18 +#define TIMER_DIS 0x0 +#define TIMER_EN 0x1 +#define STIMER0_CHN_BASE(n) (STIME_BASE + 0x20 * (n)) + +#define PMU_GRF_GPIO0B_IOMUX_L 0x0008 +#define PMUCRU_PMUCLKSEL_CON00 0x0100 +#define PMUPVTM_BASE 0xfdd80000 +#define PVTM_CON0 0x0004 +#define PVTM_CON1 0x0008 +#define PVTM_STATUS0 0x0080 +#define PVTM_STATUS1 0x0084 +#define PMUCRU_PMUGATE_CON01 0x0184 +#define PVTM_CALC_CNT 0x200 +#define PMU_GRF_DLL_CON0 0x0180 + +enum cru_mode_con00 { + CLK_APLL, + CLK_DPLL, + CLK_CPLL, + CLK_GPLL, + CLK_REVSERVED, + CLK_NPLL, + CLK_VPLL, + CLK_USBPLL, +}; + +#endif /* __SOC_H__ */ diff --git a/plat/rockchip/rk3568/include/plat.ld.S b/plat/rockchip/rk3568/include/plat.ld.S new file mode 100644 index 000000000..ddd584d4a --- /dev/null +++ b/plat/rockchip/rk3568/include/plat.ld.S @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +MEMORY { + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = PMUSRAM_BASE; + + /* + * pmu_cpuson_entrypoint request address + * align 64K when resume, so put it in the + * start of pmusram + */ + .pmusram : { + ASSERT(. == ALIGN(64 * 1024), + ".pmusram.entry request 64K aligned."); + KEEP(*(.pmusram.entry)) + + __bl31_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl31_pmusram_text_end = .; + __bl31_pmusram_data_start = .; + *(.pmusram.data) + __bl31_pmusram_data_end = .; + } >PMUSRAM +} +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/plat/rockchip/rk3568/include/plat_sip_calls.h b/plat/rockchip/rk3568/include/plat_sip_calls.h new file mode 100644 index 000000000..6acb87628 --- /dev/null +++ b/plat/rockchip/rk3568/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_SIP_CALLS_H__ +#define __PLAT_SIP_CALLS_H__ + +#define RK_PLAT_SIP_NUM_CALLS 0 + +#endif /* __PLAT_SIP_CALLS_H__ */ diff --git a/plat/rockchip/rk3568/include/platform_def.h b/plat/rockchip/rk3568/include/platform_def.h new file mode 100644 index 000000000..19363a42b --- /dev/null +++ b/plat/rockchip/rk3568/include/platform_def.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLATFORM_DEF_H__ +#define __PLATFORM_DEF_H__ + +#include +#include +#include + +#define DEBUG_XLAT_TABLE 0 + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if DEBUG_XLAT_TABLE +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL1 +#define PLATFORM_STACK_SIZE 0x440 +#elif IMAGE_BL2 +#define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL31 +#define PLATFORM_STACK_SIZE 0x800 +#elif IMAGE_BL32 +#define PLATFORM_STACK_SIZE 0x440 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 + +#define PLATFORM_CLUSTER1_CORE_COUNT 0 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) + +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 8 + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF txet, ro, rw, Size: 512KB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x100000) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL3-1 at the top of the Trusted RAM + */ +#define BL31_BASE (TZRAM_BASE + 0x40000) +#define BL31_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +#define ADDR_SPACE_SIZE (1ull << 32) +#define MAX_XLAT_TABLES 18 +#define MAX_MMAP_REGIONS 27 + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned on the biggest cache line size in the platform. This is known only + * to the platform as it might have a combination of integrated and external + * caches. Such alignment ensures that two maiboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/* + * Define GICD and GICC and GICR base + */ +#define PLAT_RK_GICD_BASE PLAT_GICD_BASE +#define PLAT_RK_GICC_BASE PLAT_GICC_BASE +#define PLAT_RK_GICR_BASE PLAT_GICR_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ + +#define PLAT_RK_GICV3_G1S_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + INTR_GROUP1S, GIC_INTR_CFG_LEVEL) + +#define PLAT_RK_GICV3_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#define PLAT_RK_UART_BASE FPGA_UART_BASE +#define PLAT_RK_UART_CLOCK FPGA_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE FPGA_BAUDRATE + +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define ATAGS_PHYS_SIZE 0x2000 +#define ATAGS_PHYS_BASE (0x200000 - ATAGS_PHYS_SIZE)/* [2M-8K, 2M] */ + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rockchip/rk3568/plat_sip_calls.c b/plat/rockchip/rk3568/plat_sip_calls.c new file mode 100644 index 000000000..b0f3a03da --- /dev/null +++ b/plat/rockchip/rk3568/plat_sip_calls.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +uintptr_t rockchip_plat_sip_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/plat/rockchip/rk3568/platform.mk b/plat/rockchip/rk3568/platform.mk new file mode 100644 index 000000000..1155ff841 --- /dev/null +++ b/plat/rockchip/rk3568/platform.mk @@ -0,0 +1,96 @@ +# +# Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +DISABLE_BIN_GENERATION := 1 +GICV3_SUPPORT_GIC600 := 1 +include lib/coreboot/coreboot.mk +include lib/libfdt/libfdt.mk +include lib/xlat_tables_v2/xlat_tables.mk +# GIC-600 configuration +GICV3_IMPL := GIC600 +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +PLAT_INCLUDES := -Iinclude/bl31 \ + -Iinclude/common \ + -Iinclude/drivers \ + -Iinclude/drivers/arm \ + -Iinclude/drivers/auth \ + -Iinclude/drivers/io \ + -Iinclude/drivers/ti/uart \ + -Iinclude/lib \ + -Iinclude/lib/cpus/${ARCH} \ + -Iinclude/lib/el3_runtime \ + -Iinclude/lib/pmf \ + -Iinclude/lib/psci \ + -Iinclude/plat/common \ + -Iinclude/services \ + -Iinclude/plat/common/ \ + -Idrivers/arm/gic/v3/ \ + -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/pmusram/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_COMMON}/drivers/parameter/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ + +RK_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + ${RK_PLAT}/common/rockchip_gicv3.c + +PLAT_BL_COMMON_SOURCES := ${XLAT_TABLES_LIB_SRCS} \ + common/desc_image_load.c \ + plat/common/aarch64/crash_console_helpers.S \ + lib/bl_aux_params/bl_aux_params.c \ + plat/common/plat_psci_common.c + +ifneq (${ENABLE_STACK_PROTECTOR},0) +PLAT_BL_COMMON_SOURCES += ${RK_PLAT_COMMON}/rockchip_stack_protector.c +endif + +BL31_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + lib/cpus/aarch64/cortex_a55.S \ + drivers/ti/uart/aarch64/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + $(LIBFDT_SRCS) \ + ${RK_PLAT_COMMON}/aarch64/plat_helpers.S \ + ${RK_PLAT_COMMON}/bl31_plat_setup.c \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_COMMON}/pmusram/cpus_on_fixed_addr.S \ + ${RK_PLAT_COMMON}/drivers/parameter/ddr_parameter.c \ + ${RK_PLAT_COMMON}/aarch64/platform_common.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c + +ENABLE_PLAT_COMPAT := 0 +MULTI_CONSOLE_API := 1 +# System coherency is managed in hardware +HW_ASSISTED_COHERENCY := 1 +#Enable errata for cortex_a55 +ERRATA_A55_1530923 := 1 + +# When building for systems with hardware-assisted coherency, there's no need to +# use USE_COHERENT_MEM. Require that USE_COHERENT_MEM must be set to 0 too. +USE_COHERENT_MEM := 0 + +$(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER)) +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/rockchip/rk3568/rk3568_def.h b/plat/rockchip/rk3568/rk3568_def.h new file mode 100644 index 000000000..0d1e5d1a1 --- /dev/null +++ b/plat/rockchip/rk3568/rk3568_def.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __PLAT_DEF_H__ +#define __PLAT_DEF_H__ + +#define MAJOR_VERSION (1) +#define MINOR_VERSION (0) + +#define SIZE_K(n) ((n) * 1024) + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define GIC600_BASE 0xfd400000 +#define GIC600_SIZE SIZE_K(64) + +#define PMUSGRF_BASE 0xfdc00000 +#define SYSSGRF_BASE 0xfdc10000 +#define PMUGRF_BASE 0xfdc20000 +#define CPUGRF_BASE 0xfdc30000 +#define DDRGRF_BASE 0xfdc40000 +#define PIPEGRF_BASE 0xfdc50000 +#define GRF_BASE 0xfdc60000 +#define PIPEPHY_GRF0 0xfdc70000 +#define PIPEPHY_GRF1 0xfdc80000 +#define PIPEPHY_GRF2 0xfdc90000 +#define USBPHY_U3_GRF 0xfdca0000 +#define USB2PHY_U2_GRF 0xfdca8000 +#define EDPPHY_GRF 0xfdcb0000 +#define SYSSRAM_BASE 0xfdcc0000 +#define PCIE30PHY_GRF 0xfdcb8000 +#define USBGRF_BASE 0xfdcf0000 + +#define PMUCRU_BASE 0xfdd00000 +#define SCRU_BASE 0xfdd10000 +#define SGRF_BASE 0xfdd18000 +#define STIME_BASE 0xfdd1c000 +#define CRU_BASE 0xfdd20000 +#define PMUSCRU_BASE 0xfdd30000 +#define I2C0_BASE 0xfdd40000 + +#define UART0_BASE 0xfdd50000 +#define GPIO0_BASE 0xfdd60000 +#define PMUPVTM_BASE 0xfdd80000 +#define PMU_BASE 0xfdd90000 +#define PMUSRAM_BASE 0xfdcd0000 +#define PMUSRAM_SIZE SIZE_K(128) +#define PMUSRAM_RSIZE SIZE_K(8) + +#define DDRSGRF_BASE 0xfe200000 +#define UART1_BASE 0xfe650000 +#define UART2_BASE 0xfe660000 +#define GPIO1_BASE 0xfe740000 +#define GPIO2_BASE 0xfe750000 +#define GPIO3_BASE 0xfe760000 +#define GPIO4_BASE 0xfe770000 + +#define REMAP_BASE 0xffff0000 +#define REMAP_SIZE SIZE_K(64) +/************************************************************************** + * UART related constants + **************************************************************************/ +#define FPGA_UART_BASE UART2_BASE +#define FPGA_BAUDRATE 1500000 +#define FPGA_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 +#define SYS_COUNTER_FREQ_IN_MHZ 24 + +/****************************************************************************** + * GIC-600 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define PLAT_GICD_BASE GIC600_BASE +#define PLAT_GICC_BASE 0 +#define PLAT_GICR_BASE (GIC600_BASE + 0x60000) + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +#define RK_IRQ_SEC_SGI_0 8 +#define RK_IRQ_SEC_SGI_1 9 +#define RK_IRQ_SEC_SGI_2 10 +#define RK_IRQ_SEC_SGI_3 11 +#define RK_IRQ_SEC_SGI_4 12 +#define RK_IRQ_SEC_SGI_5 13 +#define RK_IRQ_SEC_SGI_6 14 +#define RK_IRQ_SEC_SGI_7 15 + +#define SHARE_MEM_BASE 0x100000/* [1MB, 1MB+60K]*/ +#define SHARE_MEM_PAGE_NUM 15 +#define SHARE_MEM_SIZE SIZE_K(SHARE_MEM_PAGE_NUM * 4) + +#endif /* __PLAT_DEF_H__ */