diff --git a/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..2003749 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2016, 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 rk3288 */ +.endm + +.macro rockchip_clst_warmboot_data + /* Nothing to do for rk3288 */ +.endm diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.c b/plat/rockchip/rk3288/drivers/pmu/pmu.c new file mode 100644 index 0000000..d6d7098 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/pmu/pmu.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +DEFINE_BAKERY_LOCK(rockchip_pd_lock); + +static uint32_t cpu_warm_boot_addr; + +static uint32_t store_pmu_pwrmode_con; +static uint32_t store_sgrf_soc_con0; +static uint32_t store_sgrf_cpu_con0; + +/* These enum are variants of low power mode */ +enum { + ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, + ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, +}; + +static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle) +{ + uint32_t mask = BIT(req); + uint32_t idle_mask = 0; + uint32_t idle_target = 0; + uint32_t val; + uint32_t wait_cnt = 0; + + switch (req) { + case bus_ide_req_gpu: + idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu); + idle_target = (idle << pmu_idle_ack_gpu) | + (idle << pmu_idle_gpu); + break; + case bus_ide_req_core: + idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core); + idle_target = (idle << pmu_idle_ack_core) | + (idle << pmu_idle_core); + break; + case bus_ide_req_cpup: + idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup); + idle_target = (idle << pmu_idle_ack_cpup) | + (idle << pmu_idle_cpup); + break; + case bus_ide_req_bus: + idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus); + idle_target = (idle << pmu_idle_ack_bus) | + (idle << pmu_idle_bus); + break; + case bus_ide_req_dma: + idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma); + idle_target = (idle << pmu_idle_ack_dma) | + (idle << pmu_idle_dma); + break; + case bus_ide_req_peri: + idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri); + idle_target = (idle << pmu_idle_ack_peri) | + (idle << pmu_idle_peri); + break; + case bus_ide_req_video: + idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video); + idle_target = (idle << pmu_idle_ack_video) | + (idle << pmu_idle_video); + break; + case bus_ide_req_hevc: + idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc); + idle_target = (idle << pmu_idle_ack_hevc) | + (idle << pmu_idle_hevc); + break; + case bus_ide_req_vio: + idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio); + idle_target = (pmu_idle_ack_vio) | + (idle << pmu_idle_vio); + break; + case bus_ide_req_alive: + idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive); + idle_target = (idle << pmu_idle_ack_alive) | + (idle << pmu_idle_alive); + break; + default: + ERROR("%s: Unsupported the idle request\n", __func__); + break; + } + + val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ); + if (idle) + val |= mask; + else + val &= ~mask; + + mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val); + + while ((mmio_read_32(PMU_BASE + + PMU_BUS_IDE_ST) & idle_mask) != idle_target) { + wait_cnt++; + if (!(wait_cnt % MAX_WAIT_CONUT)) + WARN("%s:st=%x(%x)\n", __func__, + mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST), + idle_mask); + } + + return 0; +} + +static bool rk3288_sleep_disable_osc(void) +{ + static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0, + GRF_UOC2_CON0 }; + uint32_t reg, i; + + /* + * if any usb phy is still on(GRF_SIDDQ==0), that means we need the + * function of usb wakeup, so do not switch to 32khz, since the usb phy + * clk does not connect to 32khz osc + */ + for (i = 0; i < ARRAY_SIZE(reg_offset); i++) { + reg = mmio_read_32(GRF_BASE + reg_offset[i]); + if (!(reg & GRF_SIDDQ)) + return false; + } + + return true; +} + +static void pmu_set_sleep_mode(int level) +{ + uint32_t mode_set, mode_set1; + bool osc_disable = rk3288_sleep_disable_osc(); + + mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) | + BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) | + BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) | + BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) | + BIT(pmu_mode_scu_pd); + + mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup); + + if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { + /* arm off, logic deep sleep */ + mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) | + BIT(pmu_mode_ddrio1_ret) | + BIT(pmu_mode_ddrio0_ret) | + BIT(pmu_mode_pmu_alive_use_lf) | + BIT(pmu_mode_pll_pd); + + if (osc_disable) + mode_set |= BIT(pmu_mode_osc_dis); + + mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) | + BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, + pmu_armint_wakeup_en); + + /* + * In deep suspend we use PMU_PMU_USE_LF to let the rk3288 + * switch its main clock supply to the alternative 32kHz + * source. Therefore set 30ms on a 32kHz clock for pmic + * stabilization. Similar 30ms on 24MHz for the other + * mode below. + */ + mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30); + + /* only wait for stabilization, if we turned the osc off */ + mmio_write_32(PMU_BASE + PMU_OSC_CNT, + osc_disable ? 32 * 30 : 0); + } else { + /* + * arm off, logic normal + * if pmu_clk_core_src_gate_en is not set, + * wakeup will be error + */ + mode_set |= BIT(pmu_mode_core_src_gt); + + mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, + BIT(pmu_armint_wakeup_en) | + BIT(pmu_gpioint_wakeup_en)); + + /* 30ms on a 24MHz clock for pmic stabilization */ + mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30); + + /* oscillator is still running, so no need to wait */ + mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0); + } + + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set); + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1); +} + +static int cpus_power_domain_on(uint32_t cpu_id) +{ + uint32_t cpu_pd; + + cpu_pd = PD_CPU0 + cpu_id; + + /* if the core has been on, power it off first */ + if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { + /* put core in reset - some sort of A12/A17 bug */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), + BIT(cpu_id) | (BIT(cpu_id) << 16)); + + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + } + + pmu_power_domain_ctr(cpu_pd, pmu_pd_on); + + /* pull core out of reset */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16); + + return 0; +} + +static int cpus_power_domain_off(uint32_t cpu_id) +{ + uint32_t cpu_pd = PD_CPU0 + cpu_id; + + if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) + return 0; + + if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) + return -EINVAL; + + /* put core in reset - some sort of A12/A17 bug */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), + BIT(cpu_id) | (BIT(cpu_id) << 16)); + + pmu_power_domain_ctr(cpu_pd, pmu_pd_off); + + return 0; +} + +static void nonboot_cpus_off(void) +{ + uint32_t boot_cpu, cpu; + + boot_cpu = plat_my_core_pos(); + boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr()); + + /* turn off noboot cpus */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { + if (cpu == boot_cpu) + continue; + + cpus_power_domain_off(cpu); + } +} + +void sram_save(void) +{ + /* TODO: support the sdram save for rk3288 SoCs*/ +} + +void sram_restore(void) +{ + /* TODO: support the sdram restore for rk3288 SoCs */ +} + +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); + assert(cpuson_flags[cpu_id] == 0); + cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; + cpuson_entry_point[cpu_id] = entrypoint; + dsb(); + + cpus_power_domain_on(cpu_id); + + /* + * We communicate with the bootrom to active the cpus other + * than cpu0, after a blob of initialize code, they will + * stay at wfe state, once they are actived, they will check + * the mailbox: + * sram_base_addr + 4: 0xdeadbeaf + * sram_base_addr + 8: start address for pc + * The cpu0 need to wait the other cpus other than cpu0 entering + * the wfe state.The wait time is affected by many aspects. + * (e.g: cpu frequency, bootrom frequency, sram frequency, ...) + */ + mdelay(1); /* ensure the cpus other than cpu0 to startup */ + + /* tell the bootrom mailbox where to start from */ + mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr); + mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF); + dsb(); + sev(); + + return 0; +} + +int rockchip_soc_cores_pwr_dm_on_finish(void) +{ + return 0; +} + +int rockchip_soc_sys_pwr_dm_resume(void) +{ + mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con); + mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), + store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK); + + /* disable fastboot mode */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), + store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS); + + secure_watchdog_ungate(); + clk_gate_con_restore(); + clk_sel_con_restore(); + clk_plls_resume(); + + secure_gic_init(); + plat_rockchip_gic_init(); + + return 0; +} + +int rockchip_soc_sys_pwr_dm_suspend(void) +{ + nonboot_cpus_off(); + + store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0)); + store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0)); + store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON); + + /* save clk-gates and ungate all for suspend */ + clk_gate_con_save(); + clk_gate_con_disable(); + clk_sel_con_save(); + + pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); + + clk_plls_suspend(); + secure_watchdog_gate(); + + /* + * The dapswjdp can not auto reset before resume, that cause it may + * access some illegal address during resume. Let's disable it before + * suspend, and the MASKROM will enable it back. + */ + mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK); + + /* + * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR + */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA); + + /* boot-address of resuming system is from this register value */ + mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR, + (uint32_t)&pmu_cpuson_entrypoint); + + /* flush all caches - otherwise we might loose the resume address */ + dcsw_op_all(DC_OP_CISW); + + return 0; +} + +void rockchip_plat_mmu_svc_mon(void) +{ +} + +void plat_rockchip_pmu_init(void) +{ + uint32_t cpu; + + cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot; + + /* on boot all power-domains are on */ + for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) + cpuson_flags[cpu] = pmu_pd_on; + + nonboot_cpus_off(); +} diff --git a/plat/rockchip/rk3288/drivers/pmu/pmu.h b/plat/rockchip/rk3288/drivers/pmu/pmu.h new file mode 100644 index 0000000..06d5528 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/pmu/pmu.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMU_H +#define PMU_H + +/* Allocate sp reginon in pmusram */ +#define PSRAM_SP_SIZE 0x80 +#define PSRAM_SP_BOTTOM (PSRAM_SP_TOP - PSRAM_SP_SIZE) + +/***************************************************************************** + * pmu con,reg + *****************************************************************************/ +#define PMU_WAKEUP_CFG0 0x0 +#define PMU_WAKEUP_CFG1 0x4 +#define PMU_PWRDN_CON 0x8 +#define PMU_PWRDN_ST 0xc + +#define PMU_PWRMODE_CON 0x18 +#define PMU_BUS_IDE_REQ 0x10 +#define PMU_BUS_IDE_ST 0x14 + +#define PMU_OSC_CNT 0x20 +#define PMU_PLL_CNT 0x24 +#define PMU_STABL_CNT 0x28 +#define PMU_DDRIO0_PWR_CNT 0x2c +#define PMU_DDRIO1_PWR_CNT 0x30 +#define PMU_WKUPRST_CNT 0x44 +#define PMU_SFT_CON 0x48 +#define PMU_PWRMODE_CON1 0x90 + +enum pmu_pdid { + PD_CPU0 = 0, + PD_CPU1, + PD_CPU2, + PD_CPU3, + PD_BUS = 5, + PD_PERI, + PD_VIO, + PD_VIDEO, + PD_GPU, + PD_SCU = 11, + PD_HEVC = 14, + PD_END +}; + +enum pmu_bus_ide { + bus_ide_req_bus = 0, + bus_ide_req_peri, + bus_ide_req_gpu, + bus_ide_req_video, + bus_ide_req_vio, + bus_ide_req_core, + bus_ide_req_alive, + bus_ide_req_dma, + bus_ide_req_cpup, + bus_ide_req_hevc, + bus_ide_req_end +}; + +enum pmu_pwrmode { + pmu_mode_en = 0, + pmu_mode_core_src_gt, + pmu_mode_glb_int_dis, + pmu_mode_l2_flush_en, + pmu_mode_bus_pd, + pmu_mode_cpu0_pd, + pmu_mode_scu_pd, + pmu_mode_pll_pd = 7, + pmu_mode_chip_pd, + pmu_mode_pwr_off_comb, + pmu_mode_pmu_alive_use_lf, + pmu_mode_pmu_use_lf, + pmu_mode_osc_dis = 12, + pmu_mode_input_clamp, + pmu_mode_wkup_rst, + pmu_mode_sref0_enter, + pmu_mode_sref1_enter, + pmu_mode_ddrio0_ret, + pmu_mode_ddrio1_ret, + pmu_mode_ddrc0_gt, + pmu_mode_ddrc1_gt, + pmu_mode_ddrio0_ret_deq, + pmu_mode_ddrio1_ret_deq, +}; + +enum pmu_pwrmode1 { + pmu_mode_clr_bus = 0, + pmu_mode_clr_core, + pmu_mode_clr_cpup, + pmu_mode_clr_alive, + pmu_mode_clr_dma, + pmu_mode_clr_peri, + pmu_mode_clr_gpu, + pmu_mode_clr_video, + pmu_mode_clr_hevc, + pmu_mode_clr_vio +}; + +enum pmu_sft_con { + pmu_sft_ddrio0_ret_cfg = 6, + pmu_sft_ddrio1_ret_cfg = 9, + pmu_sft_l2flsh = 15, +}; + +enum pmu_wakeup_cfg1 { + pmu_armint_wakeup_en = 0, + pmu_gpio_wakeup_negedge, + pmu_sdmmc0_wakeup_en, + pmu_gpioint_wakeup_en, +}; + +enum pmu_bus_idle_st { + pmu_idle_bus = 0, + pmu_idle_peri, + pmu_idle_gpu, + pmu_idle_video, + pmu_idle_vio, + pmu_idle_core, + pmu_idle_alive, + pmu_idle_dma, + pmu_idle_cpup, + pmu_idle_hevc, + pmu_idle_ack_bus = 16, + pmu_idle_ack_peri, + pmu_idle_ack_gpu, + pmu_idle_ack_video, + pmu_idle_ack_vio, + pmu_idle_ack_core, + pmu_idle_ack_alive, + pmu_idle_ack_dma, + pmu_idle_ack_cpup, + pmu_idle_ack_hevc, +}; + +#define CHECK_CPU_WFIE_BASE (0) + +#define clstl_cpu_wfe -1 +#define clstb_cpu_wfe -1 +#define CKECK_WFEI_MSK 0 + + +#define PD_CTR_LOOP 500 +#define CHK_CPU_LOOP 500 + +#define MAX_WAIT_CONUT 1000 + +#endif /* PMU_H */ diff --git a/plat/rockchip/rk3288/drivers/secure/secure.c b/plat/rockchip/rk3288/drivers/secure/secure.c new file mode 100644 index 0000000..68994e4 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/secure/secure.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +static void sgrf_ddr_rgn_global_bypass(uint32_t bypass) +{ + if (bypass) + /* set bypass (non-secure regions) for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21), + SGRF_DDR_RGN_BYPS); + else + /* cancel bypass for whole ddr regions */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(21), + SGRF_DDR_RGN_NO_BYPS); +} + +/** + * There are 8 + 1 regions for DDR secure control: + * DDR_RGN_0 ~ DDR_RGN_7: Per DDR_RGNs grain size is 1MB + * DDR_RGN_X - the memories of exclude DDR_RGN_0 ~ DDR_RGN_7 + * + * SGRF_SOC_CON6 - start address of RGN_0 + control + * SGRF_SOC_CON7 - end address of RGN_0 + * ... + * SGRF_SOC_CON20 - start address of the RGN_7 + control + * SGRF_SOC_CON21 - end address of the RGN_7 + RGN_X control + * + * @rgn - the DDR regions 0 ~ 7 which are can be configured. + * The @st and @ed indicate the start and end addresses for which to set + * the security, and the unit is byte. When the st_mb == 0, ed_mb == 0, the + * address range 0x0 ~ 0xfffff is secure. + * + * For example, if we would like to set the range [0, 32MB) is security via + * DDR_RGN0, then rgn == 0, st_mb == 0, ed_mb == 31. + */ +static void sgrf_ddr_rgn_config(uint32_t rgn, uintptr_t st, uintptr_t ed) +{ + uintptr_t st_mb, ed_mb; + + assert(rgn <= 7); + assert(st < ed); + + /* check aligned 1MB */ + assert(st % SIZE_M(1) == 0); + assert(ed % SIZE_M(1) == 0); + + st_mb = st / SIZE_M(1); + ed_mb = ed / SIZE_M(1); + + /* set ddr region addr start */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_ADDR_WMSK, 0)); + + /* set ddr region addr end */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2) + 1), + BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_ADDR_WMSK, 0)); + + /* select region security */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + SGRF_DDR_RGN_SECURE_SEL); + + /* enable region security */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6 + (rgn * 2)), + SGRF_DDR_RGN_SECURE_EN); +} + +void secure_watchdog_gate(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_GATE); +} + +void secure_watchdog_ungate(void) +{ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_PCLK_WDT_UNGATE); +} + +__pmusramfunc void sram_secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0); + + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void secure_gic_init(void) +{ + /* (re-)enable non-secure access to the gic*/ + mmio_write_32(CORE_AXI_BUS_BASE + CORE_AXI_SECURITY0, + AXI_SECURITY0_GIC); +} + +void secure_timer_init(void) +{ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, 0); + + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT0, 0xffffffff); + mmio_write_32(STIMER1_BASE + TIMER_LOAD_COUNT1, 0xffffffff); + + /* auto reload & enable the timer */ + mmio_write_32(STIMER1_BASE + TIMER_CONTROL_REG, TIMER_EN); +} + +void secure_sgrf_init(void) +{ + /* + * We use the first sram part to talk to the bootrom, + * so make it secure. + */ + mmio_write_32(TZPC_BASE + TZPC_R0SIZE, TZPC_SRAM_SECURE_4K(1)); + + secure_gic_init(); + + /* set all master ip to non-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(2), SGRF_SOC_CON2_MST_NS); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(3), SGRF_SOC_CON3_MST_NS); + + /* setting all configurable ip into non-secure */ + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(4), + SGRF_SOC_CON4_SECURE_WMSK /*TODO:|SGRF_STIMER_SECURE*/); + mmio_write_32(SGRF_BASE + SGRF_SOC_CON(5), SGRF_SOC_CON5_SECURE_WMSK); + + /* secure dma to non-secure */ + mmio_write_32(TZPC_BASE + TZPC_DECPROT1SET, 0xff); + mmio_write_32(TZPC_BASE + TZPC_DECPROT2SET, 0xff); + mmio_write_32(SGRF_BASE + SGRF_BUSDMAC_CON(1), 0x3800); + dsb(); + + /* rst dma1 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), + RST_DMA1_MSK | (RST_DMA1_MSK << 16)); + /* rst dma2 */ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), + RST_DMA2_MSK | (RST_DMA2_MSK << 16)); + + dsb(); + + /* release dma1 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(1), (RST_DMA1_MSK << 16)); + /* release dma2 rst*/ + mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(4), (RST_DMA2_MSK << 16)); +} + +void secure_sgrf_ddr_rgn_init(void) +{ + sgrf_ddr_rgn_config(0, TZRAM_BASE, TZRAM_SIZE); + sgrf_ddr_rgn_global_bypass(0); +} diff --git a/plat/rockchip/rk3288/drivers/secure/secure.h b/plat/rockchip/rk3288/drivers/secure/secure.h new file mode 100644 index 0000000..6c0b2b7 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/secure/secure.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SECURE_H +#define SECURE_H + +/****************************************************************************** + * TZPC TrustZone controller + ******************************************************************************/ + +#define TZPC_R0SIZE 0x0 +#define TZPC_SRAM_SECURE_4K(n) ((n) > 0x200 ? 0x200 : (n)) +#define TZPC_DECPROT1STAT 0x80c +#define TZPC_DECPROT1SET 0x810 +#define TZPC_DECPROT1CLR 0x814 +#define TZPC_DECPROT2STAT 0x818 +#define TZPC_DECPROT2SET 0x818 +#define TZPC_DECPROT2CLR 0x820 + +/************************************************** + * sgrf reg, offset + **************************************************/ +/* + * soc_con0-5 start at 0x0, soc_con6-... start art 0x50 + * adjusted for the 5 lower registers + */ +#define SGRF_SOC_CON(n) ((((n) < 6) ? 0x0 : 0x38) + (n) * 4) +#define SGRF_BUSDMAC_CON(n) (0x20 + (n) * 4) +#define SGRF_CPU_CON(n) (0x40 + (n) * 4) +#define SGRF_SOC_STATUS(n) (0x100 + (n) * 4) +#define SGRF_FAST_BOOT_ADDR 0x120 + +/* SGRF_SOC_CON0 */ +#define SGRF_FAST_BOOT_ENA BIT_WITH_WMSK(8) +#define SGRF_FAST_BOOT_DIS WMSK_BIT(8) +#define SGRF_PCLK_WDT_GATE BIT_WITH_WMSK(6) +#define SGRF_PCLK_WDT_UNGATE WMSK_BIT(6) +#define SGRF_PCLK_STIMER_GATE BIT_WITH_WMSK(4) + +#define SGRF_SOC_CON2_MST_NS 0xffe0ffe0 +#define SGRF_SOC_CON3_MST_NS 0x003f003f + +/* SGRF_SOC_CON4 */ +#define SGRF_SOC_CON4_SECURE_WMSK 0xffff0000 +#define SGRF_DDRC1_SECURE BIT_WITH_WMSK(12) +#define SGRF_DDRC0_SECURE BIT_WITH_WMSK(11) +#define SGRF_PMUSRAM_SECURE BIT_WITH_WMSK(8) +#define SGRF_WDT_SECURE BIT_WITH_WMSK(7) +#define SGRF_STIMER_SECURE BIT_WITH_WMSK(6) + +/* SGRF_SOC_CON5 */ +#define SGRF_SLV_SEC_BYPS BIT_WITH_WMSK(15) +#define SGRF_SLV_SEC_NO_BYPS WMSK_BIT(15) +#define SGRF_SOC_CON5_SECURE_WMSK 0x00ff0000 + +/* ddr regions in SGRF_SOC_CON6 and following */ +#define SGRF_DDR_RGN_SECURE_SEL BIT_WITH_WMSK(15) +#define SGRF_DDR_RGN_SECURE_EN BIT_WITH_WMSK(14) +#define SGRF_DDR_RGN_ADDR_WMSK 0x0fff + +/* SGRF_SOC_CON21 */ +/* All security of the DDR RGNs are bypassed */ +#define SGRF_DDR_RGN_BYPS BIT_WITH_WMSK(15) +#define SGRF_DDR_RGN_NO_BYPS WMSK_BIT(15) + +/* SGRF_CPU_CON0 */ +#define SGRF_DAPDEVICE_ENA BIT_WITH_WMSK(0) +#define SGRF_DAPDEVICE_MSK WMSK_BIT(0) + +/***************************************************************************** + * core-axi + *****************************************************************************/ +#define CORE_AXI_SECURITY0 0x08 +#define AXI_SECURITY0_GIC BIT(0) + +/***************************************************************************** + * secure timer + *****************************************************************************/ +#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_EN 0x1 + +#define STIMER1_BASE (STIME_BASE + 0x20) + +/* export secure operating APIs */ +void secure_watchdog_gate(void); +void secure_watchdog_ungate(void); +void secure_gic_init(void); +void secure_timer_init(void); +void secure_sgrf_init(void); +void secure_sgrf_ddr_rgn_init(void); +__pmusramfunc void sram_secure_timer_init(void); + +#endif /* SECURE_H */ diff --git a/plat/rockchip/rk3288/drivers/soc/soc.c b/plat/rockchip/rk3288/drivers/soc/soc.c new file mode 100644 index 0000000..db90ae4 --- /dev/null +++ b/plat/rockchip/rk3288/drivers/soc/soc.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* sleep data for pll suspend */ +static struct deepsleep_data_s slp_data; + +/* Table of regions to map using the MMU. */ +const mmap_region_t plat_rk_mmap[] = { + MAP_REGION_FLAT(GIC400_BASE, GIC400_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(STIME_BASE, STIME_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SGRF_BASE, SGRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TZPC_BASE, TZPC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMUSRAM_BASE, PMUSRAM_SIZE, + MT_MEMORY | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SRAM_BASE, SRAM_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(PMU_BASE, PMU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(UART_DBG_BASE, UART_DBG_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRU_BASE, CRU_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(GRF_BASE, GRF_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL0_BASE, DDR_PCTL0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY0_BASE, DDR_PHY0_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PCTL1_BASE, DDR_PCTL1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DDR_PHY1_BASE, DDR_PHY1_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(SERVICE_BUS_BASE, SERVICE_BUS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CORE_AXI_BUS_BASE, CORE_AXI_BUS_SIZE, + MT_DEVICE | 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, +}; + +void plat_rockchip_soc_init(void) +{ + secure_timer_init(); + secure_sgrf_init(); + /* + * We cannot enable ddr security at this point, as the kernel + * seems to have an issue with it even living in the same 128MB + * memory block. Only when moving the kernel to the second + * 128MB block does it not conflict, but then we'd loose this + * memory area for use. Late maybe enable + * secure_sgrf_ddr_rgn_init(); + */ +} + +void regs_update_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift) +{ + uint32_t tmp, orig; + + orig = mmio_read_32(addr); + + tmp = orig & ~(mask << shift); + tmp |= (val & mask) << shift; + + if (tmp != orig) + mmio_write_32(addr, tmp); + dsb(); +} + +static void pll_save(uint32_t pll_id) +{ + uint32_t *pll = slp_data.pll_con[pll_id]; + + pll[0] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 0)); + pll[1] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 1)); + pll[2] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 2)); + pll[3] = mmio_read_32(CRU_BASE + PLL_CONS((pll_id), 3)); +} + +void clk_plls_suspend(void) +{ + pll_save(NPLL_ID); + pll_save(CPLL_ID); + pll_save(GPLL_ID); + pll_save(APLL_ID); + slp_data.pll_mode = mmio_read_32(CRU_BASE + PLL_MODE_CON); + + /* + * Switch PLLs other than DPLL (for SDRAM) to slow mode to + * avoid crashes on resume. The Mask ROM on the system will + * put APLL, CPLL, and GPLL into slow mode at resume time + * anyway (which is why we restore them), but we might not + * even make it to the Mask ROM if this isn't done at suspend + * time. + * + * NOTE: only APLL truly matters here, but we'll do them all. + */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); +} + +void clk_plls_resume(void) +{ + /* restore pll-modes */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, + slp_data.pll_mode | REG_SOC_WMSK); +} + +void clk_gate_con_save(void) +{ + uint32_t i = 0; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + slp_data.cru_gate_con[i] = + mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); +} + +void clk_gate_con_disable(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), REG_SOC_WMSK); +} + +void clk_gate_con_restore(void) +{ + uint32_t i; + + for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) + mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), + REG_SOC_WMSK | slp_data.cru_gate_con[i]); +} + +void clk_sel_con_save(void) +{ + uint32_t i = 0; + + for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) + slp_data.cru_sel_con[i] = + mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(i)); +} + +void clk_sel_con_restore(void) +{ + uint32_t i, val; + + for (i = 0; i < CRU_CLKSELS_CON_CNT; i++) { + /* fractional dividers don't have write-masks */ + if ((i >= 7 && i <= 9) || + (i >= 17 && i <= 20) || + (i == 23) || (i == 41)) + val = slp_data.cru_sel_con[i]; + else + val = slp_data.cru_sel_con[i] | REG_SOC_WMSK; + + mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(i), val); + } +} + +void __dead2 rockchip_soc_soft_reset(void) +{ + uint32_t temp_val; + + /* + * Switch PLLs other than DPLL (for SDRAM) to slow mode to + * avoid crashes on resume. The Mask ROM on the system will + * put APLL, CPLL, and GPLL into slow mode at resume time + * anyway (which is why we restore them), but we might not + * even make it to the Mask ROM if this isn't done at suspend + * time. + * + * NOTE: only APLL truly matters here, but we'll do them all. + */ + mmio_write_32(CRU_BASE + PLL_MODE_CON, 0xf3030000); + + temp_val = mmio_read_32(CRU_BASE + CRU_GLB_RST_CON); + temp_val &= ~PMU_RST_MASK; + temp_val |= PMU_RST_BY_SECOND_SFT; + mmio_write_32(CRU_BASE + CRU_GLB_RST_CON, temp_val); + mmio_write_32(CRU_BASE + CRU_GLB_SRST_SND, 0xeca8); + + /* + * Maybe the HW needs some times to reset the system, + * so we do not hope the core to excute valid codes. + */ + while (1) + ; +} diff --git a/plat/rockchip/rk3288/drivers/soc/soc.h b/plat/rockchip/rk3288/drivers/soc/soc.h new file mode 100644 index 0000000..b96c4dc --- /dev/null +++ b/plat/rockchip/rk3288/drivers/soc/soc.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_H +#define SOC_H + +enum plls_id { + APLL_ID = 0, + DPLL_ID, + CPLL_ID, + GPLL_ID, + NPLL_ID, + END_PLL_ID, +}; + + +#define CYCL_24M_CNT_US(us) (24 * (us)) +#define CYCL_24M_CNT_MS(ms) ((ms) * CYCL_24M_CNT_US(1000)) + +/***************************************************************************** + * grf regs + *****************************************************************************/ +#define GRF_UOC0_CON0 0x320 +#define GRF_UOC1_CON0 0x334 +#define GRF_UOC2_CON0 0x348 +#define GRF_SIDDQ BIT(13) + +/***************************************************************************** + * cru reg, offset + *****************************************************************************/ +#define CRU_SOFTRST_CON 0x1b8 +#define CRU_SOFTRSTS_CON(n) (CRU_SOFTRST_CON + ((n) * 4)) +#define CRU_SOFTRSTS_CON_CNT 11 + +#define RST_DMA1_MSK 0x4 +#define RST_DMA2_MSK 0x1 + +#define CRU_CLKSEL_CON 0x60 +#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON + ((i) * 4)) +#define CRU_CLKSELS_CON_CNT 42 + +#define CRU_CLKGATE_CON 0x160 +#define CRU_CLKGATES_CON(i) (CRU_CLKGATE_CON + ((i) * 4)) +#define CRU_CLKGATES_CON_CNT 18 + +#define CRU_GLB_SRST_FST 0x1b0 +#define CRU_GLB_SRST_SND 0x1b4 +#define CRU_GLB_RST_CON 0x1f0 + +#define CRU_CONS_GATEID(i) (16 * (i)) +#define GATE_ID(reg, bit) (((reg) * 16) + (bit)) + +#define PMU_RST_MASK 0x3 +#define PMU_RST_BY_FIRST_SFT (0 << 2) +#define PMU_RST_BY_SECOND_SFT (1 << 2) +#define PMU_RST_NOT_BY_SFT (2 << 2) + +/*************************************************************************** + * pll + ***************************************************************************/ +#define PLL_CON_COUNT 4 +#define PLL_CONS(id, i) ((id) * 0x10 + ((i) * 4)) +#define PLL_PWR_DN_MSK BIT(1) +#define PLL_PWR_DN REG_WMSK_BITS(1, 1, 0x1) +#define PLL_PWR_ON REG_WMSK_BITS(0, 1, 0x1) +#define PLL_RESET REG_WMSK_BITS(1, 5, 0x1) +#define PLL_RESET_RESUME REG_WMSK_BITS(0, 5, 0x1) +#define PLL_BYPASS_MSK BIT(0) +#define PLL_BYPASS_W_MSK (PLL_BYPASS_MSK << 16) +#define PLL_BYPASS REG_WMSK_BITS(1, 0, 0x1) +#define PLL_NO_BYPASS REG_WMSK_BITS(0, 0, 0x1) + +#define PLL_MODE_CON 0x50 + +struct deepsleep_data_s { + uint32_t pll_con[END_PLL_ID][PLL_CON_COUNT]; + uint32_t pll_mode; + uint32_t cru_sel_con[CRU_CLKSELS_CON_CNT]; + uint32_t cru_gate_con[CRU_CLKGATES_CON_CNT]; +}; + +#define REG_W_MSK(bits_shift, msk) \ + ((msk) << ((bits_shift) + 16)) +#define REG_VAL_CLRBITS(val, bits_shift, msk) \ + ((val) & (~((msk) << bits_shift))) +#define REG_SET_BITS(bits, bits_shift, msk) \ + (((bits) & (msk)) << (bits_shift)) +#define REG_WMSK_BITS(bits, bits_shift, msk) \ + (REG_W_MSK(bits_shift, msk) | \ + REG_SET_BITS(bits, bits_shift, msk)) +#define REG_SOC_WMSK 0xffff0000 + +#define regs_update_bit_set(addr, shift) \ + regs_update_bits((addr), 0x1, 0x1, (shift)) +#define regs_update_bit_clr(addr, shift) \ + regs_update_bits((addr), 0x0, 0x1, (shift)) + +void regs_update_bits(uintptr_t addr, uint32_t val, + uint32_t mask, uint32_t shift); +void clk_plls_suspend(void); +void clk_plls_resume(void); +void clk_gate_con_save(void); +void clk_gate_con_disable(void); +void clk_gate_con_restore(void); +void clk_sel_con_save(void); +void clk_sel_con_restore(void); +#endif /* SOC_H */ diff --git a/plat/rockchip/rk3288/include/plat_sip_calls.h b/plat/rockchip/rk3288/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/plat/rockchip/rk3288/include/plat_sip_calls.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, 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/rk3288/include/plat_sp_min.ld.S b/plat/rockchip/rk3288/include/plat_sp_min.ld.S new file mode 100644 index 0000000..2878437 --- /dev/null +++ b/plat/rockchip/rk3288/include/plat_sp_min.ld.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ROCKCHIP_PLAT_LD_S +#define ROCKCHIP_PLAT_LD_S + +#include + +MEMORY { + SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE + PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE +} + +SECTIONS +{ + . = SRAM_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "SRAM_BASE address is not aligned on a page boundary.") + + .text_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_text_start = .; + *(.sram.text) + *(.sram.rodata) + __bl32_sram_text_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl32_sram_text_end = .; + } >SRAM + ASSERT((__bl32_sram_text_real_end - __bl32_sram_text_start) <= + SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") + + .data_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_data_start = .; + *(.sram.data) + __bl32_sram_data_real_end = .; + . = ALIGN(PAGE_SIZE); + __bl32_sram_data_end = .; + } >SRAM + ASSERT((__bl32_sram_data_real_end - __bl32_sram_data_start) <= + SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") + + .stack_sram : ALIGN(PAGE_SIZE) { + __bl32_sram_stack_start = .; + . += PAGE_SIZE; + __bl32_sram_stack_end = .; + } >SRAM + + . = 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."); + *(.pmusram.entry) + + __bl32_pmusram_text_start = .; + *(.pmusram.text) + *(.pmusram.rodata) + __bl32_pmusram_text_end = .; + + __bl32_pmusram_data_start = .; + *(.pmusram.data) + __bl32_pmusram_data_end = .; + } >PMUSRAM +} + +#endif /* ROCKCHIP_PLAT_LD_S */ diff --git a/plat/rockchip/rk3288/include/platform_def.h b/plat/rockchip/rk3288/include/platform_def.h new file mode 100644 index 0000000..d9e0bc6 --- /dev/null +++ b/plat/rockchip/rk3288/include/platform_def.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf32-littlearm" +#define PLATFORM_LINKER_ARCH arm + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#if defined(IMAGE_BL1) +#define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +#define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +#define PLATFORM_STACK_SIZE 0x800 +#endif + +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2 +#define PLATFORM_SYSTEM_COUNT 1 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT 4 +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 +#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_RK_CLST_TO_CPUID_SHIFT 6 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +/* + * 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 U(1) + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE U(2) + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define MAX_XLAT_TABLES 8 +#define MAX_MMAP_REGIONS 18 + +/******************************************************************************* + * 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 RK3288_GICD_BASE +#define PLAT_RK_GICC_BASE RK3288_GICC_BASE + +#define PLAT_RK_UART_BASE RK3288_UART2_BASE +#define PLAT_RK_UART_CLOCK RK3288_UART_CLOCK +#define PLAT_RK_UART_BAUDRATE RK3288_BAUDRATE + +/* ClusterId is always 0x5 on rk3288, filter it */ +#define PLAT_RK_MPIDR_CLUSTER_MASK 0 +#define PLAT_RK_PRIMARY_CPU 0x0 + +#define PSRAM_DO_DDR_RESUME 0 +#define PSRAM_CHECK_WAKEUP_CPU 0 + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/rockchip/rk3288/include/shared/bl32_param.h b/plat/rockchip/rk3288/include/shared/bl32_param.h new file mode 100644 index 0000000..743dad4 --- /dev/null +++ b/plat/rockchip/rk3288/include/shared/bl32_param.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL32_PARAM_H +#define BL32_PARAM_H + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* TF txet, ro, rw, Size: 2MB */ +#define TZRAM_BASE (0x0) +#define TZRAM_SIZE (0x200000) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +/* + * Put BL32 at the top of the Trusted RAM + */ +#define BL32_BASE (TZRAM_BASE + 0x100000) +#define BL32_LIMIT (TZRAM_BASE + TZRAM_SIZE) + +#endif /* BL32_PARAM_H */ diff --git a/plat/rockchip/rk3288/plat_sip_calls.c b/plat/rockchip/rk3288/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/plat/rockchip/rk3288/plat_sip_calls.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#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/rk3288/platform.mk b/plat/rockchip/rk3288/platform.mk new file mode 100644 index 0000000..1a0a617 --- /dev/null +++ b/plat/rockchip/rk3288/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ARM_CORTEX_A12 := yes +ARM_ARCH_MAJOR := 7 + +RK_PLAT := plat/rockchip +RK_PLAT_SOC := ${RK_PLAT}/${PLAT} +RK_PLAT_COMMON := ${RK_PLAT}/common + +include lib/libfdt/libfdt.mk + +PLAT_INCLUDES := -I${RK_PLAT_COMMON}/ \ + -I${RK_PLAT_COMMON}/include/ \ + -I${RK_PLAT_COMMON}/aarch32/ \ + -I${RK_PLAT_COMMON}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/ \ + -I${RK_PLAT_SOC}/drivers/pmu/ \ + -I${RK_PLAT_SOC}/drivers/secure/ \ + -I${RK_PLAT_SOC}/drivers/soc/ \ + -I${RK_PLAT_SOC}/include/ \ + -I${RK_PLAT_SOC}/include/shared/ \ + +RK_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c \ + ${RK_PLAT}/common/rockchip_gicv2.c + +PLAT_BL_COMMON_SOURCES := plat/common/aarch32/crash_console_helpers.S \ + plat/common/plat_psci_common.c + +PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch32/xlat_tables.c + +BL32_SOURCES += ${RK_GIC_SOURCES} \ + drivers/arm/cci/cci.c \ + drivers/ti/uart/aarch32/16550_console.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + lib/cpus/aarch32/cortex_a12.S \ + $(LIBFDT_SRCS) \ + ${RK_PLAT_COMMON}/aarch32/plat_helpers.S \ + ${RK_PLAT_COMMON}/params_setup.c \ + ${RK_PLAT_COMMON}/aarch32/pmu_sram_cpus_on.S \ + ${RK_PLAT_COMMON}/plat_pm.c \ + ${RK_PLAT_COMMON}/plat_topology.c \ + ${RK_PLAT_COMMON}/aarch32/platform_common.c \ + ${RK_PLAT_COMMON}/rockchip_sip_svc.c \ + ${RK_PLAT_SOC}/plat_sip_calls.c \ + ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ + ${RK_PLAT_SOC}/drivers/secure/secure.c \ + ${RK_PLAT_SOC}/drivers/soc/soc.c \ + +MULTI_CONSOLE_API := 1 + +include lib/coreboot/coreboot.mk + +$(eval $(call add_define,PLAT_SP_MIN_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 diff --git a/plat/rockchip/rk3288/rk3288_def.h b/plat/rockchip/rk3288/rk3288_def.h new file mode 100644 index 0000000..7b5018c --- /dev/null +++ b/plat/rockchip/rk3288/rk3288_def.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RK3288_DEF_H +#define RK3288_DEF_H + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RK_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define SIZE_K(n) ((n) * 1024) +#define SIZE_M(n) ((n) * 1024 * 1024) + +#define SRAM_TEXT_LIMIT (4 * 1024) +#define SRAM_DATA_LIMIT (4 * 1024) + +#define DDR_PCTL0_BASE 0xff610000 +#define DDR_PCTL0_SIZE SIZE_K(64) + +#define DDR_PHY0_BASE 0xff620000 +#define DDR_PHY0_SIZE SIZE_K(64) + +#define DDR_PCTL1_BASE 0xff630000 +#define DDR_PCTL1_SIZE SIZE_K(64) + +#define DDR_PHY1_BASE 0xff640000 +#define DDR_PHY1_SIZE SIZE_K(64) + +#define UART_DBG_BASE 0xff690000 +#define UART_DBG_SIZE SIZE_K(64) + +/* 96k instead of 64k? */ +#define SRAM_BASE 0xff700000 +#define SRAM_SIZE SIZE_K(64) + +#define PMUSRAM_BASE 0xff720000 +#define PMUSRAM_SIZE SIZE_K(4) +#define PMUSRAM_RSIZE SIZE_K(4) + +#define PMU_BASE 0xff730000 +#define PMU_SIZE SIZE_K(64) + +#define SGRF_BASE 0xff740000 +#define SGRF_SIZE SIZE_K(64) + +#define CRU_BASE 0xff760000 +#define CRU_SIZE SIZE_K(64) + +#define GRF_BASE 0xff770000 +#define GRF_SIZE SIZE_K(64) + +/* timer 6+7 can be set as secure in SGRF */ +#define STIME_BASE 0xff810000 +#define STIME_SIZE SIZE_K(64) + +#define SERVICE_BUS_BASE 0xffac0000 +#define SERVICE_BUS_SIZE SIZE_K(64) + +#define TZPC_BASE 0xffb00000 +#define TZPC_SIZE SIZE_K(64) + +#define GIC400_BASE 0xffc00000 +#define GIC400_SIZE SIZE_K(64) + +#define CORE_AXI_BUS_BASE 0xffd00000 +#define CORE_AXI_BUS_SIZE SIZE_M(1) + +#define COLD_BOOT_BASE 0xffff0000 +/************************************************************************** + * UART related constants + **************************************************************************/ +#define RK3288_UART2_BASE UART_DBG_BASE +#define RK3288_BAUDRATE 115200 +#define RK3288_UART_CLOCK 24000000 + +/****************************************************************************** + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 24000000 + +/****************************************************************************** + * GIC-400 & interrupt handling related constants + ******************************************************************************/ + +/* Base rk_platform compatible GIC memory map */ +#define RK3288_GICD_BASE (GIC400_BASE + 0x1000) +#define RK3288_GICC_BASE (GIC400_BASE + 0x2000) +#define RK3288_GICR_BASE 0 /* no GICR in GIC-400 */ + +/****************************************************************************** + * sgi, ppi + ******************************************************************************/ +#define RK_IRQ_SEC_PHY_TIMER 29 + +/* what are these, and are they present on rk3288? */ +#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 a list of Group 0 interrupts. + */ +#define PLAT_RK_GICV2_G0_IRQS \ + INTR_PROP_DESC(RK_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(RK_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL) + +#endif /* RK3288_DEF_H */ diff --git a/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk new file mode 100644 index 0000000..befdca3 --- /dev/null +++ b/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \ + plat/rockchip/common/sp_min_plat_setup.c