Browse Source

feat(rockchip): add RK3566/RK3568 Socs support

RK3566/RK3568 is a Quad-core soc and Cortex-a55 inside.
This patch supports the following functions:
1. basic platform setup
2. power up/off cpus
3. suspend/resume cpus
4. suspend/resume system
5. reset system

Signed-off-by: shengfei Xu <xsf@rock-chips.com>
Change-Id: I8b98a4d07664de26bd6078f63664cbc3d9c1c68c
pull/2000/merge
shengfei Xu 2 years ago
committed by xsf
parent
commit
9fd9f1d024
  1. 1
      docs/plat/rockchip.rst
  2. 4
      include/lib/cpus/aarch64/dsu_def.h
  3. 13
      lib/cpus/aarch64/dsu_helpers.S
  4. 7
      plat/rockchip/common/aarch64/plat_helpers.S
  5. 11
      plat/rockchip/common/aarch64/platform_common.c
  6. 11
      plat/rockchip/common/bl31_plat_setup.c
  7. 7
      plat/rockchip/common/include/plat_private.h
  8. 18
      plat/rockchip/rk3568/drivers/pmu/plat_pmu_macros.S
  9. 543
      plat/rockchip/rk3568/drivers/pmu/pmu.c
  10. 304
      plat/rockchip/rk3568/drivers/pmu/pmu.h
  11. 103
      plat/rockchip/rk3568/drivers/soc/soc.c
  12. 63
      plat/rockchip/rk3568/drivers/soc/soc.h
  13. 36
      plat/rockchip/rk3568/include/plat.ld.S
  14. 12
      plat/rockchip/rk3568/include/plat_sip_calls.h
  15. 136
      plat/rockchip/rk3568/include/platform_def.h
  16. 29
      plat/rockchip/rk3568/plat_sip_calls.c
  17. 96
      plat/rockchip/rk3568/platform.mk
  18. 104
      plat/rockchip/rk3568/rk3568_def.h

1
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

4
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 */

13
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

7
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

11
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 <common/debug.h>
#include <drivers/arm/cci.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <plat_private.h>
#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(); \

11
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
}

7
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 <stdint.h>
#include <lib/psci/psci.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <lib/mmio.h>
#include <lib/psci/psci.h>
#include <lib/xlat_tables/xlat_tables_compat.h>
#include <plat_params.h>
#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);

18
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 <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
.macro func_rockchip_clst_warmboot
/* Nothing to do for rk3568 */
.endm
.macro rockchip_clst_warmboot_data
/* Nothing to do for rk3568 */
.endm

543
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 <assert.h>
#include <errno.h>
#include <bakery_lock.h>
#include <cortex_a55.h>
#include <dsu_def.h>
#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <pmu.h>
#include <cpus_on_fixed_addr.h>
#include <plat_private.h>
#include <soc.h>
/*
* 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);
}

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

103
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 <common/debug.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <mmio.h>
#include <platform_def.h>
#include <soc.h>
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);
}

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

36
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 */

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

136
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 <arch.h>
#include <common_def.h>
#include <rk3568_def.h>
#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__ */

29
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 <assert.h>
#include <errno.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <plat_sip_calls.h>
#include <rockchip_sip_svc.h>
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);
}

96
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

104
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__ */
Loading…
Cancel
Save