GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <cortex_a12.h>
#include <plat_private.h>
#include <plat_pmu_macros.S>
.globl cpuson_entry_point
.globl cpuson_flags
.globl platform_cpu_warmboot
.globl plat_secondary_cold_boot_setup
.globl plat_report_exception
.globl plat_is_my_cpu_primary
.globl plat_my_core_pos
.globl plat_reset_handler
.globl plat_panic_handler
/*
* void plat_reset_handler(void);
*
* Determine the SOC type and call the appropriate reset
* handler.
*
*/
func plat_reset_handler
bx lr
endfunc plat_reset_handler
func plat_my_core_pos
ldcopr r0, MPIDR
and r1, r0, #MPIDR_CPU_MASK
#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
#else
and r0, r0, #MPIDR_CLUSTER_MASK
#endif
add r0, r1, r0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
bx lr
endfunc plat_my_core_pos
/* --------------------------------------------------------------------
* void plat_secondary_cold_boot_setup (void);
*
* This function performs any platform specific actions
* needed for a secondary cpu after a cold reset e.g
* mark the cpu's presence, mechanism to place it in a
* holding pen etc.
* --------------------------------------------------------------------
*/
func plat_secondary_cold_boot_setup
/* rk3288 does not do cold boot for secondary CPU */
cb_panic:
b cb_panic
endfunc plat_secondary_cold_boot_setup
func plat_is_my_cpu_primary
ldcopr r0, MPIDR
#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
ldr r1, =(PLAT_RK_MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
#else
ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
#endif
and r0, r1
cmp r0, #PLAT_RK_PRIMARY_CPU
moveq r0, #1
movne r0, #0
bx lr
endfunc plat_is_my_cpu_primary
/* --------------------------------------------------------------------
* void plat_panic_handler(void)
* Call system reset function on panic. Set up an emergency stack so we
* can run C functions (it only needs to last for a few calls until we
* reboot anyway).
* --------------------------------------------------------------------
*/
func plat_panic_handler
bl plat_set_my_stack
b rockchip_soc_soft_reset
endfunc plat_panic_handler
/* --------------------------------------------------------------------
* void platform_cpu_warmboot (void);
* cpus online or resume entrypoint
* --------------------------------------------------------------------
*/
func platform_cpu_warmboot _align=16
push { r4 - r7, lr }
ldcopr r0, MPIDR
and r5, r0, #MPIDR_CPU_MASK
#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
and r6, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
#else
and r6, r0, #MPIDR_CLUSTER_MASK
#endif
mov r0, r6
func_rockchip_clst_warmboot
/* --------------------------------------------------------------------
* big cluster id is 1
* big cores id is from 0-3, little cores id 4-7
* --------------------------------------------------------------------
*/
add r7, r5, r6, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
/* --------------------------------------------------------------------
* get per cpuup flag
* --------------------------------------------------------------------
*/
ldr r4, =cpuson_flags
add r4, r4, r7, lsl #2
ldr r1, [r4]
/* --------------------------------------------------------------------
* check cpuon reason
* --------------------------------------------------------------------
*/
cmp r1, #PMU_CPU_AUTO_PWRDN
beq boot_entry
cmp r1, #PMU_CPU_HOTPLUG
beq boot_entry
/* --------------------------------------------------------------------
* If the boot core cpuson_flags or cpuson_entry_point is not
* expection. force the core into wfe.
* --------------------------------------------------------------------
*/
wfe_loop:
wfe
b wfe_loop
boot_entry:
mov r1, #0
str r1, [r4]
/* --------------------------------------------------------------------
* get per cpuup boot addr
* --------------------------------------------------------------------
*/
ldr r5, =cpuson_entry_point
ldr r2, [r5, r7, lsl #2] /* ehem. #3 */
pop { r4 - r7, lr }
bx r2
endfunc platform_cpu_warmboot
/* --------------------------------------------------------------------
* Per-CPU Secure entry point - resume or power up
* --------------------------------------------------------------------
*/
.section tzfw_coherent_mem, "a"
.align 3
cpuson_entry_point:
.rept PLATFORM_CORE_COUNT
.quad 0
.endr
cpuson_flags:
.rept PLATFORM_CORE_COUNT
.word 0
.endr
rockchip_clst_warmboot_data
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <lib/utils.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <plat_private.h>
void plat_configure_mmu_svc_mon(unsigned long total_base,
unsigned long total_size,
unsigned long ro_start,
unsigned long ro_limit,
unsigned long coh_start,
unsigned long coh_limit)
{
mmap_add_region(total_base, total_base, total_size,
MT_MEMORY | MT_RW | MT_SECURE);
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);
mmap_add(plat_rk_mmap);
rockchip_plat_mmu_svc_mon();
init_xlat_tables();
enable_mmu_svc_mon(0);
}
unsigned int plat_get_syscnt_freq2(void)
{
return SYS_COUNTER_FREQ_IN_TICKS;
}
/*
* generic pm code does cci handling, but rockchip arm32 platforms
* have ever only 1 cluster, so nothing to do.
*/
void plat_cci_init(void)
{
}
void plat_cci_enable(void)
{
}
void plat_cci_disable(void)
{
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
.globl pmu_cpuson_entrypoint
.macro pmusram_entry_func _name
.section .pmusram.entry, "ax"
.type \_name, %function
.cfi_startproc
\_name:
.endm
pmusram_entry_func pmu_cpuson_entrypoint
#if PSRAM_CHECK_WAKEUP_CPU
check_wake_cpus:
ldcopr r0, MPIDR
and r1, r0, #MPIDR_CPU_MASK
#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
and r0, r0, #PLAT_RK_MPIDR_CLUSTER_MASK
#else
and r0, r0, #MPIDR_CLUSTER_MASK
#endif
orr r0, r0, r1
/* primary_cpu */
ldr r1, boot_mpidr
cmp r0, r1
beq sys_wakeup
/*
* If the core is not the primary cpu,
* force the core into wfe.
*/
wfe_loop:
wfe
b wfe_loop
sys_wakeup:
#endif
#if PSRAM_DO_DDR_RESUME
ddr_resume:
ldr r2, =__bl32_sram_stack_end
mov sp, r2
bl dmc_resume
#endif
bl sram_restore
sys_resume:
bl sp_min_warm_entrypoint
endfunc pmu_cpuson_entrypoint
@@ -0,0 +1,163 @@
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <cortex_a53.h>
#include <cortex_a72.h>
#include <plat_private.h>
#include <plat_pmu_macros.S>
.globl cpuson_entry_point
.globl cpuson_flags
.globl platform_cpu_warmboot
.globl plat_secondary_cold_boot_setup
.globl plat_report_exception
.globl plat_is_my_cpu_primary
.globl plat_my_core_pos
.globl plat_reset_handler
.globl plat_panic_handler
/*
* void plat_reset_handler(void);
*
* Determine the SOC type and call the appropriate reset
* handler.
*
*/
func plat_reset_handler
mrs x0, midr_el1
ubfx x0, x0, MIDR_PN_SHIFT, #12
cmp w0, #((CORTEX_A72_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
b.eq handler_a72
b handler_end
handler_a72:
/*
* This handler does the following:
* Set the L2 Data RAM latency for Cortex-A72.
* Set the L2 Tag RAM latency to for Cortex-A72.
*/
mov x0, #((5 << CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT) | \
(0x1 << 5))
msr CORTEX_A72_L2CTLR_EL1, x0
isb
handler_end:
ret
endfunc plat_reset_handler
func plat_my_core_pos
mrs x0, mpidr_el1
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
add x0, x1, x0, LSR #PLAT_RK_CLST_TO_CPUID_SHIFT
ret
endfunc plat_my_core_pos
/* --------------------------------------------------------------------
* void plat_secondary_cold_boot_setup (void);
*
* This function performs any platform specific actions
* needed for a secondary cpu after a cold reset e.g
* mark the cpu's presence, mechanism to place it in a
* holding pen etc.
* --------------------------------------------------------------------
*/
func plat_secondary_cold_boot_setup
/* rk3368 does not do cold boot for secondary CPU */
cb_panic:
b cb_panic
endfunc plat_secondary_cold_boot_setup
func plat_is_my_cpu_primary
mrs x0, mpidr_el1
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
cmp x0, #PLAT_RK_PRIMARY_CPU
cset x0, eq
ret
endfunc plat_is_my_cpu_primary
/* --------------------------------------------------------------------
* void plat_panic_handler(void)
* Call system reset function on panic. Set up an emergency stack so we
* can run C functions (it only needs to last for a few calls until we
* reboot anyway).
* --------------------------------------------------------------------
*/
func plat_panic_handler
msr spsel, #0
bl plat_set_my_stack
b rockchip_soc_soft_reset
endfunc plat_panic_handler
/* --------------------------------------------------------------------
* void platform_cpu_warmboot (void);
* cpus online or resume enterpoint
* --------------------------------------------------------------------
*/
func platform_cpu_warmboot _align=16
mrs x0, MPIDR_EL1
and x19, x0, #MPIDR_CPU_MASK
and x20, x0, #MPIDR_CLUSTER_MASK
mov x0, x20
func_rockchip_clst_warmboot
/* --------------------------------------------------------------------
* big cluster id is 1
* big cores id is from 0-3, little cores id 4-7
* --------------------------------------------------------------------
*/
add x21, x19, x20, lsr #PLAT_RK_CLST_TO_CPUID_SHIFT
/* --------------------------------------------------------------------
* get per cpuup flag
* --------------------------------------------------------------------
*/
adr x4, cpuson_flags
add x4, x4, x21, lsl #2
ldr w1, [x4]
/* --------------------------------------------------------------------
* check cpuon reason
* --------------------------------------------------------------------
*/
cmp w1, PMU_CPU_AUTO_PWRDN
b.eq boot_entry
cmp w1, PMU_CPU_HOTPLUG
b.eq boot_entry
/* --------------------------------------------------------------------
* If the boot core cpuson_flags or cpuson_entry_point is not
* expection. force the core into wfe.
* --------------------------------------------------------------------
*/
wfe_loop:
wfe
b wfe_loop
boot_entry:
str wzr, [x4]
/* --------------------------------------------------------------------
* get per cpuup boot addr
* --------------------------------------------------------------------
*/
adr x5, cpuson_entry_point
ldr x2, [x5, x21, lsl #3]
br x2
endfunc platform_cpu_warmboot
/* --------------------------------------------------------------------
* Per-CPU Secure entry point - resume or power up
* --------------------------------------------------------------------
*/
.section tzfw_coherent_mem, "a"
.align 3
cpuson_entry_point:
.rept PLATFORM_CORE_COUNT
.quad 0
.endr
cpuson_flags:
.rept PLATFORM_CORE_COUNT
.word 0
.endr
rockchip_clst_warmboot_data
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#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
static const int cci_map[] = {
PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX,
PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX
};
#endif
/******************************************************************************
* Macro generating the code for the function setting up the pagetables as per
* the platform memory map & initialize the mmu, for the given exception level
******************************************************************************/
#define DEFINE_CONFIGURE_MMU_EL(_el) \
void plat_configure_mmu_el ## _el(unsigned long total_base, \
unsigned long total_size, \
unsigned long ro_start, \
unsigned long ro_limit, \
unsigned long coh_start, \
unsigned long coh_limit) \
{ \
mmap_add_region(total_base, total_base, \
total_size, \
MT_MEMORY | MT_RW | MT_SECURE); \
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); \
mmap_add(plat_rk_mmap); \
rockchip_plat_mmu_el##_el(); \
init_xlat_tables(); \
\
enable_mmu_el ## _el(0); \
}
/* Define EL3 variants of the function initialising the MMU */
DEFINE_CONFIGURE_MMU_EL(3)
unsigned int plat_get_syscnt_freq2(void)
{
return SYS_COUNTER_FREQ_IN_TICKS;
}
void plat_cci_init(void)
{
#ifdef PLAT_RK_CCI_BASE
/* Initialize CCI driver */
cci_init(PLAT_RK_CCI_BASE, cci_map, ARRAY_SIZE(cci_map));
#endif
}
void plat_cci_enable(void)
{
/*
* Enable CCI coherency for this cluster.
* No need for locks as no other cpu is active at the moment.
*/
#ifdef PLAT_RK_CCI_BASE
cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
#endif
}
void plat_cci_disable(void)
{
#ifdef PLAT_RK_CCI_BASE
cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr()));
#endif
}
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
.globl pmu_cpuson_entrypoint
.macro pmusram_entry_func _name
.section .pmusram.entry, "ax"
.type \_name, %function
.cfi_startproc
\_name:
.endm
pmusram_entry_func pmu_cpuson_entrypoint
#if PSRAM_CHECK_WAKEUP_CPU
check_wake_cpus:
mrs x0, MPIDR_EL1
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
orr x0, x0, x1
/* primary_cpu */
ldr w1, boot_mpidr
cmp w0, w1
b.eq sys_wakeup
/*
* If the core is not the primary cpu,
* force the core into wfe.
*/
wfe_loop:
wfe
b wfe_loop
sys_wakeup:
#endif
#if PSRAM_DO_DDR_RESUME
ddr_resume:
ldr x2, =__bl31_sram_stack_end
mov sp, x2
bl dmc_resume
#endif
bl sram_restore
sys_resume:
bl bl31_warm_entrypoint
endfunc pmu_cpuson_entrypoint
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/console.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/ti/uart/uart_16550.h>
#include <lib/mmio.h>
#include <plat_private.h>
#include <plat/common/platform.h>
static entry_point_info_t bl32_ep_info;
static entry_point_info_t bl33_ep_info;
/*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type
* while BL32 corresponds to the secure image type. A NULL pointer is returned
* if the image does not exist.
******************************************************************************/
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
entry_point_info_t *next_image_info;
next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
assert(next_image_info->h.type == PARAM_EP);
/* None of the images on this platform can have 0x0 as the entrypoint */
if (next_image_info->pc)
return next_image_info;
else
return NULL;
}
#pragma weak params_early_setup
void params_early_setup(u_register_t plat_param_from_bl2)
{
}
/*******************************************************************************
* Perform any BL3-1 early platform setup. Here is an opportunity to copy
* parameters passed by the calling EL (S-EL1 in BL2 & EL3 in BL1) before they
* are lost (potentially). This needs to be done before the MMU is initialized
* so that the memory layout can be used while creating page tables.
* BL2 has flushed this information to memory, so we are guaranteed to pick up
* good data.
******************************************************************************/
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
static console_t console;
params_early_setup(arg1);
if (rockchip_get_uart_base() != 0)
console_16550_register(rockchip_get_uart_base(),
rockchip_get_uart_clock(),
rockchip_get_uart_baudrate(), &console);
VERBOSE("bl31_setup\n");
bl31_params_parse_helper(arg0, &bl32_ep_info, &bl33_ep_info);
}
/*******************************************************************************
* Perform any BL3-1 platform setup code
******************************************************************************/
void bl31_platform_setup(void)
{
generic_delay_timer_init();
plat_rockchip_soc_init();
/* Initialize the gic cpu and distributor interfaces */
plat_rockchip_gic_driver_init();
plat_rockchip_gic_init();
plat_rockchip_pmu_init();
}
/*******************************************************************************
* Perform the very early platform specific architectural setup here. At the
* moment this is only intializes the mmu in a quick and dirty way.
******************************************************************************/
void bl31_plat_arch_setup(void)
{
plat_cci_init();
plat_cci_enable();
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);
}
@@ -0,0 +1,135 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <plat_private.h>
#include <soc.h>
#include "ddr_parameter.h"
/*
* The miniloader delivers the parameters about ddr usage info from address
* 0x02000000 and the data format is defined as below figure. It tells ATF the
* areas of ddr that are used by platform, we treat them as non-secure regions
* by default. Then we should parse the other part regions and configurate them
* as secure regions to avoid illegal access.
*
* [ddr usage info data format]
* 0x02000000
* -----------------------------------------------------------------------------
* | <name> | <size> | <description> |
* -----------------------------------------------------------------------------
* | count | 4byte | the array numbers of the |
* | | | 'addr_array' and 'size_array' |
* -----------------------------------------------------------------------------
* | reserved | 4byte | just for 'addr_array' 8byte aligned |
* -----------------------------------------------------------------------------
* | addr_array[count] | per 8byte | memory region base address |
* -----------------------------------------------------------------------------
* | size_array[count] | per 8byte | memory region size (byte) |
* -----------------------------------------------------------------------------
*/
/*
* function: read parameters info(ns-regions) and try to parse s-regions info
*
* @addr: head address to the ddr usage struct from miniloader
* @max_mb: the max ddr capacity(MB) that the platform support
*/
struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb)
{
uint64_t base, top;
uint32_t i, addr_offset, size_offset;
struct param_ddr_usage p;
memset(&p, 0, sizeof(p));
/* read how many blocks of ns-regions, read from offset: 0x0 */
p.ns_nr = mmio_read_32(addr + REGION_NR_OFFSET);
if ((p.ns_nr > DDR_REGION_NR_MAX) || (p.ns_nr == 0)) {
ERROR("over or zero region, nr=%d, max=%d\n",
p.ns_nr, DDR_REGION_NR_MAX);
return p;
}
/* whole ddr regions boundary, it will be used when parse s-regions */
p.boundary = max_mb;
/* calculate ns-region base addr and size offset */
addr_offset = REGION_ADDR_OFFSET;
size_offset = REGION_ADDR_OFFSET + p.ns_nr * REGION_DATA_PER_BYTES;
/* read all ns-regions base and top address */
for (i = 0; i < p.ns_nr; i++) {
base = mmio_read_64(addr + addr_offset);
top = base + mmio_read_64(addr + size_offset);
/*
* translate byte to MB and store info,
* Miniloader will promise every ns-region is MB aligned.
*/
p.ns_base[i] = RG_SIZE_MB(base);
p.ns_top[i] = RG_SIZE_MB(top);
addr_offset += REGION_DATA_PER_BYTES;
size_offset += REGION_DATA_PER_BYTES;
}
/*
* a s-region's base starts from previous ns-region's top, and a
* s-region's top ends with next ns-region's base. maybe like this:
*
* case1: ns-regison start from 0MB
* -----------------------------------------------
* | ns0 | S0 | ns1 | S1 | ns2 |
* 0----------------------------------------------- max_mb
*
*
* case2: ns-regison not start from 0MB
* -----------------------------------------------
* | S0 | ns0 | ns1 | ns2 | S1 |
* 0----------------------------------------------- max_mb
*/
/* like above case2 figure, ns-region is not start from 0MB */
if (p.ns_base[0] != 0) {
p.s_base[p.s_nr] = 0;
p.s_top[p.s_nr] = p.ns_base[0];
p.s_nr++;
}
/*
* notice: if ns-regions not start from 0MB, p.s_nr = 1 now, otherwise 0
*/
for (i = 0; i < p.ns_nr; i++) {
/*
* if current ns-regions top covers boundary,
* that means s-regions are all parsed yet, so finsh.
*/
if (p.ns_top[i] == p.boundary)
goto out;
/* s-region's base starts from previous ns-region's top */
p.s_base[p.s_nr] = p.ns_top[i];
/* s-region's top ends with next ns-region's base */
if (i + 1 < p.ns_nr)
p.s_top[p.s_nr] = p.ns_base[i + 1];
else
p.s_top[p.s_nr] = p.boundary;
p.s_nr++;
}
out:
return p;
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef DDR_PARAMETER_H
#define DDR_PARAMETER_H
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <plat_private.h>
#include <soc.h>
#define DDR_REGION_NR_MAX 10
#define REGION_NR_OFFSET 0
#define REGION_ADDR_OFFSET 8
#define REGION_DATA_PER_BYTES 8
#define RG_SIZE_MB(byte) ((byte) >> 20)
/* unit: MB */
struct param_ddr_usage {
uint64_t boundary;
uint32_t ns_nr;
uint64_t ns_base[DDR_REGION_NR_MAX];
uint64_t ns_top[DDR_REGION_NR_MAX];
uint32_t s_nr;
uint64_t s_base[DDR_REGION_NR_MAX + 1];
uint64_t s_top[DDR_REGION_NR_MAX + 1];
};
struct param_ddr_usage ddr_region_usage_parse(uint64_t addr, uint64_t max_mb);
#endif /* DDR_PARAMETER_H */
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PMU_COM_H
#define PMU_COM_H
#ifndef CHECK_CPU_WFIE_BASE
#define CHECK_CPU_WFIE_BASE (PMU_BASE + PMU_CORE_PWR_ST)
#endif
/*
* Use this macro to instantiate lock before it is used in below
* rockchip_pd_lock_xxx() macros
*/
DECLARE_BAKERY_LOCK(rockchip_pd_lock);
/*
* 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)
/*****************************************************************************
* power domain on or off
*****************************************************************************/
enum pmu_pd_state {
pmu_pd_on = 0,
pmu_pd_off = 1
};
#pragma weak plat_ic_get_pending_interrupt_id
#pragma weak pmu_power_domain_ctr
#pragma weak check_cpu_wfie
static inline uint32_t pmu_power_domain_st(uint32_t pd)
{
uint32_t pwrdn_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd);
if (pwrdn_st)
return pmu_pd_off;
else
return pmu_pd_on;
}
static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
{
uint32_t val;
uint32_t loop = 0;
int ret = 0;
rockchip_pd_lock_get();
val = mmio_read_32(PMU_BASE + PMU_PWRDN_CON);
if (pd_state == pmu_pd_off)
val |= BIT(pd);
else
val &= ~BIT(pd);
mmio_write_32(PMU_BASE + PMU_PWRDN_CON, val);
dsb();
while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
udelay(1);
loop++;
}
if (pmu_power_domain_st(pd) != pd_state) {
WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
ret = -EINVAL;
}
rockchip_pd_lock_rls();
return ret;
}
static int check_cpu_wfie(uint32_t cpu_id, uint32_t wfie_msk)
{
uint32_t cluster_id, loop = 0;
if (cpu_id >= PLATFORM_CLUSTER0_CORE_COUNT) {
cluster_id = 1;
cpu_id -= PLATFORM_CLUSTER0_CORE_COUNT;
} else {
cluster_id = 0;
}
/*
* wfe/wfi tracking not possible, hopefully the host
* was sucessful in enabling wfe/wfi.
* We'll give a bit of additional time, like the kernel does.
*/
if ((cluster_id && clstb_cpu_wfe < 0) ||
(!cluster_id && clstl_cpu_wfe < 0)) {
mdelay(1);
return 0;
}
if (cluster_id)
wfie_msk <<= (clstb_cpu_wfe + cpu_id);
else
wfie_msk <<= (clstl_cpu_wfe + cpu_id);
while (!(mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) &&
(loop < CHK_CPU_LOOP)) {
udelay(1);
loop++;
}
if ((mmio_read_32(CHECK_CPU_WFIE_BASE) & wfie_msk) == 0) {
WARN("%s: %d, %d, %d, error!\n", __func__,
cluster_id, cpu_id, wfie_msk);
return -EINVAL;
}
return 0;
}
#endif /* PMU_COM_H */
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ROCKCHIP_PLAT_MACROS_S
#define ROCKCHIP_PLAT_MACROS_S
#include <drivers/arm/cci.h>
#include <drivers/arm/gic_common.h>
#include <drivers/arm/gicv2.h>
#include <drivers/arm/gicv3.h>
#include <platform_def.h>
.section .rodata.gic_reg_name, "aS"
/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */
gicc_regs:
.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
/* Applicable only to GICv3 with SRE enabled */
icc_regs:
.asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", ""
/* Registers common to both GICv2 and GICv3 */
gicd_pend_reg:
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
" Offset:\t\t\tvalue\n"
newline:
.asciz "\n"
spacer:
.asciz ":\t\t0x"
.section .rodata.cci_reg_name, "aS"
cci_iface_regs:
.asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , ""
/* ---------------------------------------------
* The below utility macro prints out relevant GIC
* and CCI registers whenever an unhandled
* exception is taken in BL31.
* Expects: GICD base in x26, GICC base in x27
* Clobbers: x0 - x10, sp
* ---------------------------------------------
*/
.macro plat_crash_print_regs
mov_imm x26, PLAT_RK_GICD_BASE
mov_imm x27, PLAT_RK_GICC_BASE
/* Check for GICv3 system register access */
mrs x7, id_aa64pfr0_el1
ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH
cmp x7, #1
b.ne print_gicv2
/* Check for SRE enable */
mrs x8, ICC_SRE_EL3
tst x8, #ICC_SRE_SRE_BIT
b.eq print_gicv2
/* Load the icc reg list to x6 */
adr x6, icc_regs
/* Load the icc regs to gp regs used by str_in_crash_buf_print */
mrs x8, ICC_HPPIR0_EL1
mrs x9, ICC_HPPIR1_EL1
mrs x10, ICC_CTLR_EL3
/* Store to the crash buf and print to console */
bl str_in_crash_buf_print
b print_gic_common
print_gicv2:
/* Load the gicc reg list to x6 */
adr x6, gicc_regs
/* Load the gicc regs to gp regs used by str_in_crash_buf_print */
ldr w8, [x27, #GICC_HPPIR]
ldr w9, [x27, #GICC_AHPPIR]
ldr w10, [x27, #GICC_CTLR]
/* Store to the crash buf and print to console */
bl str_in_crash_buf_print
print_gic_common:
/* Print the GICD_ISPENDR regs */
add x7, x26, #GICD_ISPENDR
adr x4, gicd_pend_reg
bl asm_print_str
gicd_ispendr_loop:
sub x4, x7, x26
cmp x4, #0x280
b.eq exit_print_gic_regs
bl asm_print_hex
adr x4, spacer
bl asm_print_str
ldr x4, [x7], #8
bl asm_print_hex
adr x4, newline
bl asm_print_str
b gicd_ispendr_loop
exit_print_gic_regs:
#if PLATFORM_CLUSTER_COUNT > 1
adr x6, cci_iface_regs
/* Store in x7 the base address of the first interface */
mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
PLAT_RK_CCI_CLUSTER0_SL_IFACE_IX))
ldr w8, [x7, #SNOOP_CTRL_REG]
/* Store in x7 the base address of the second interface */
mov_imm x7, (PLAT_RK_CCI_BASE + SLAVE_IFACE_OFFSET( \
PLAT_RK_CCI_CLUSTER1_SL_IFACE_IX))
ldr w9, [x7, #SNOOP_CTRL_REG]
/* Store to the crash buf and print to console */
bl str_in_crash_buf_print
#endif
.endm
#endif /* ROCKCHIP_PLAT_MACROS_S */
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_PARAMS_H
#define PLAT_PARAMS_H
#include <stdint.h>
#include <export/plat/rockchip/common/plat_params_exp.h>
#endif /* PLAT_PARAMS_H */
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_PRIVATE_H
#define PLAT_PRIVATE_H
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <lib/psci/psci.h>
#include <lib/xlat_tables/xlat_tables.h>
#include <lib/mmio.h>
#include <plat_params.h>
#define __sramdata __attribute__((section(".sram.data")))
#define __sramconst __attribute__((section(".sram.rodata")))
#define __sramfunc __attribute__((section(".sram.text")))
#define __pmusramdata __attribute__((section(".pmusram.data")))
#define __pmusramconst __attribute__((section(".pmusram.rodata")))
#define __pmusramfunc __attribute__((section(".pmusram.text")))
extern uint32_t __bl31_sram_text_start, __bl31_sram_text_end;
extern uint32_t __bl31_sram_data_start, __bl31_sram_data_end;
extern uint32_t __bl31_sram_stack_start, __bl31_sram_stack_end;
extern uint32_t __bl31_sram_text_real_end, __bl31_sram_data_real_end;
extern uint32_t __sram_incbin_start, __sram_incbin_end;
extern uint32_t __sram_incbin_real_end;
/******************************************************************************
* The register have write-mask bits, it is mean, if you want to set the bits,
* you needs set the write-mask bits at the same time,
* The write-mask bits is in high 16-bits.
* The fllowing macro definition helps access write-mask bits reg efficient!
******************************************************************************/
#define REG_MSK_SHIFT 16
#ifndef WMSK_BIT
#define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT)
#endif
/* set one bit with write mask */
#ifndef BIT_WITH_WMSK
#define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr))
#endif
#ifndef BITS_SHIFT
#define BITS_SHIFT(bits, shift) (bits << (shift))
#endif
#ifndef BITS_WITH_WMASK
#define BITS_WITH_WMASK(bits, msk, shift)\
(BITS_SHIFT(bits, shift) | BITS_SHIFT(msk, (shift + REG_MSK_SHIFT)))
#endif
/******************************************************************************
* Function and variable prototypes
*****************************************************************************/
#ifdef __aarch64__
void plat_configure_mmu_el3(unsigned long total_base,
unsigned long total_size,
unsigned long,
unsigned long,
unsigned long,
unsigned long);
void rockchip_plat_mmu_el3(void);
#else
void plat_configure_mmu_svc_mon(unsigned long total_base,
unsigned long total_size,
unsigned long,
unsigned long,
unsigned long,
unsigned long);
void rockchip_plat_mmu_svc_mon(void);
#endif
void plat_cci_init(void);
void plat_cci_enable(void);
void plat_cci_disable(void);
void plat_delay_timer_init(void);
void params_early_setup(u_register_t plat_params_from_bl2);
void plat_rockchip_gic_driver_init(void);
void plat_rockchip_gic_init(void);
void plat_rockchip_gic_cpuif_enable(void);
void plat_rockchip_gic_cpuif_disable(void);
void plat_rockchip_gic_pcpu_init(void);
void plat_rockchip_pmu_init(void);
void plat_rockchip_soc_init(void);
uintptr_t plat_get_sec_entrypoint(void);
void platform_cpu_warmboot(void);
struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void);
struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void);
struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count);
struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void);
void plat_rockchip_gpio_init(void);
void plat_rockchip_save_gpio(void);
void plat_rockchip_restore_gpio(void);
int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint);
int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
plat_local_state_t lvl_state);
int rockchip_soc_cores_pwr_dm_off(void);
int rockchip_soc_sys_pwr_dm_suspend(void);
int rockchip_soc_cores_pwr_dm_suspend(void);
int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl,
plat_local_state_t lvl_state);
int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
plat_local_state_t lvl_state);
int rockchip_soc_cores_pwr_dm_on_finish(void);
int rockchip_soc_sys_pwr_dm_resume(void);
int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl,
plat_local_state_t lvl_state);
int rockchip_soc_cores_pwr_dm_resume(void);
void __dead2 rockchip_soc_soft_reset(void);
void __dead2 rockchip_soc_system_off(void);
void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(
const psci_power_state_t *target_state);
void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void);
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);
uint32_t rockchip_get_uart_baudrate(void);
uint32_t rockchip_get_uart_clock(void);
#endif /* __ASSEMBLER__ */
/******************************************************************************
* cpu up status
* The bits of macro value is not more than 12 bits for cmp instruction!
******************************************************************************/
#define PMU_CPU_HOTPLUG 0xf00
#define PMU_CPU_AUTO_PWRDN 0xf0
#define PMU_CLST_RET 0xa5
#endif /* PLAT_PRIVATE_H */
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef ROCKCHIP_SIP_SVC_H
#define ROCKCHIP_SIP_SVC_H
/* SMC function IDs for SiP Service queries */
#define SIP_SVC_CALL_COUNT 0x8200ff00
#define SIP_SVC_UID 0x8200ff01
#define SIP_SVC_VERSION 0x8200ff03
/* rockchip SiP Service Calls version numbers */
#define RK_SIP_SVC_VERSION_MAJOR 0x0
#define RK_SIP_SVC_VERSION_MINOR 0x1
/* Number of ROCKCHIP SiP Calls implemented */
#define RK_COMMON_SIP_NUM_CALLS 0x3
enum {
RK_SIP_E_SUCCESS = 0,
RK_SIP_E_INVALID_PARAM = -1
};
#endif /* ROCKCHIP_SIP_SVC_H */
@@ -0,0 +1,256 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <lib/bl_aux_params/bl_aux_params.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <drivers/gpio.h>
#include <libfdt.h>
#include <lib/coreboot.h>
#include <lib/mmio.h>
#include <plat/common/platform.h>
#include <plat_params.h>
#include <plat_private.h>
static struct bl_aux_gpio_info rst_gpio = { .index = UINT_MAX } ;
static struct bl_aux_gpio_info poweroff_gpio = { .index = UINT_MAX };
static struct bl_aux_gpio_info suspend_gpio[10];
uint32_t suspend_gpio_cnt;
static struct bl_aux_rk_apio_info suspend_apio;
#if COREBOOT
static int dt_process_fdt(u_register_t param_from_bl2)
{
return -ENODEV;
}
#else
static uint32_t rk_uart_base = PLAT_RK_UART_BASE;
static uint32_t rk_uart_baudrate = PLAT_RK_UART_BAUDRATE;
static uint32_t rk_uart_clock = PLAT_RK_UART_CLOCK;
#define FDT_BUFFER_SIZE 0x20000
static uint64_t fdt_buffer[FDT_BUFFER_SIZE / 8];
void *plat_get_fdt(void)
{
return &fdt_buffer[0];
}
static void plat_rockchip_dt_process_fdt_uart(void *fdt)
{
const char *path_name = "/chosen";
const char *prop_name = "stdout-path";
int node_offset;
int stdout_path_len;
const char *stdout_path;
const char *separator;
const char *baud_start;
char serial_char;
int serial_no;
uint32_t uart_base;
uint32_t baud;
node_offset = fdt_path_offset(fdt, path_name);
if (node_offset < 0)
return;
stdout_path = fdt_getprop(fdt, node_offset, prop_name,
&stdout_path_len);
if (stdout_path == NULL)
return;
/*
* We expect something like:
* "serial0:baudrate"
*/
if (strncmp("serial", stdout_path, 6) != 0)
return;
serial_char = stdout_path[6];
serial_no = serial_char - '0';
switch (serial_no) {
case 0:
uart_base = UART0_BASE;
break;
case 1:
uart_base = UART1_BASE;
break;
case 2:
uart_base = UART2_BASE;
break;
#ifdef UART3_BASE
case 3:
uart_base = UART3_BASE;
break;
#endif
#ifdef UART4_BASE
case 4:
uart_base = UART4_BASE;
break;
#endif
#ifdef UART5_BASE
case 5:
uart_base = UART5_BASE;
break;
#endif
default:
return;
}
rk_uart_base = uart_base;
separator = strchr(stdout_path, ':');
if (!separator)
return;
baud = 0;
baud_start = separator + 1;
while (*baud_start != '\0') {
/*
* uart binding is <baud>{<parity>{<bits>{...}}}
* So the baudrate either is the whole string, or
* we end in the parity characters.
*/
if (*baud_start == 'n' || *baud_start == 'o' ||
*baud_start == 'e')
break;
baud = baud * 10 + (*baud_start - '0');
baud_start++;
}
rk_uart_baudrate = baud;
}
static int dt_process_fdt(u_register_t param_from_bl2)
{
void *fdt = plat_get_fdt();
int ret;
ret = fdt_open_into((void *)param_from_bl2, fdt, FDT_BUFFER_SIZE);
if (ret < 0)
return ret;
plat_rockchip_dt_process_fdt_uart(fdt);
return 0;
}
#endif
uint32_t rockchip_get_uart_base(void)
{
#if COREBOOT
return coreboot_serial.baseaddr;
#else
return rk_uart_base;
#endif
}
uint32_t rockchip_get_uart_baudrate(void)
{
#if COREBOOT
return coreboot_serial.baud;
#else
return rk_uart_baudrate;
#endif
}
uint32_t rockchip_get_uart_clock(void)
{
#if COREBOOT
return coreboot_serial.input_hertz;
#else
return rk_uart_clock;
#endif
}
struct bl_aux_gpio_info *plat_get_rockchip_gpio_reset(void)
{
if (rst_gpio.index == UINT_MAX)
return NULL;
return &rst_gpio;
}
struct bl_aux_gpio_info *plat_get_rockchip_gpio_poweroff(void)
{
if (poweroff_gpio.index == UINT_MAX)
return NULL;
return &poweroff_gpio;
}
struct bl_aux_gpio_info *plat_get_rockchip_suspend_gpio(uint32_t *count)
{
*count = suspend_gpio_cnt;
return &suspend_gpio[0];
}
struct bl_aux_rk_apio_info *plat_get_rockchip_suspend_apio(void)
{
return &suspend_apio;
}
static bool rk_aux_param_handler(struct bl_aux_param_header *param)
{
/* Store platform parameters for later processing if needed. */
switch (param->type) {
case BL_AUX_PARAM_RK_RESET_GPIO:
rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
return true;
case BL_AUX_PARAM_RK_POWEROFF_GPIO:
poweroff_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
return true;
case BL_AUX_PARAM_RK_SUSPEND_GPIO:
if (suspend_gpio_cnt >= ARRAY_SIZE(suspend_gpio)) {
ERROR("Exceeded the supported suspend GPIO number.\n");
return true;
}
suspend_gpio[suspend_gpio_cnt++] =
((struct bl_aux_param_gpio *)param)->gpio;
return true;
case BL_AUX_PARAM_RK_SUSPEND_APIO:
suspend_apio = ((struct bl_aux_param_rk_apio *)param)->apio;
return true;
}
return false;
}
void params_early_setup(u_register_t plat_param_from_bl2)
{
int ret;
/*
* Test if this is a FDT passed as a platform-specific parameter
* block.
*/
ret = dt_process_fdt(plat_param_from_bl2);
if (!ret) {
return;
} else if (ret != -FDT_ERR_BADMAGIC) {
/*
* If we found an FDT but couldn't parse it (e.g. corrupt, not
* enough space), return and don't attempt to parse the param
* as something else, since we know that will also fail. All
* we're doing is setting up UART, this doesn't need to be
* fatal.
*/
WARN("%s: found FDT but could not parse: error %d\n",
__func__, ret);
return;
}
bl_aux_params_parse(plat_param_from_bl2, rk_aux_param_handler);
}
@@ -0,0 +1,413 @@
/*
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/console.h>
#include <drivers/delay_timer.h>
#include <lib/psci/psci.h>
#include <plat_private.h>
/* Macros to read the rk power domain state */
#define RK_CORE_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL0])
#define RK_CLUSTER_PWR_STATE(state) \
((state)->pwr_domain_state[MPIDR_AFFLVL1])
#define RK_SYSTEM_PWR_STATE(state) \
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
static uintptr_t rockchip_sec_entrypoint;
#pragma weak rockchip_soc_cores_pwr_dm_on
#pragma weak rockchip_soc_hlvl_pwr_dm_off
#pragma weak rockchip_soc_cores_pwr_dm_off
#pragma weak rockchip_soc_sys_pwr_dm_suspend
#pragma weak rockchip_soc_cores_pwr_dm_suspend
#pragma weak rockchip_soc_hlvl_pwr_dm_suspend
#pragma weak rockchip_soc_hlvl_pwr_dm_on_finish
#pragma weak rockchip_soc_cores_pwr_dm_on_finish
#pragma weak rockchip_soc_sys_pwr_dm_resume
#pragma weak rockchip_soc_hlvl_pwr_dm_resume
#pragma weak rockchip_soc_cores_pwr_dm_resume
#pragma weak rockchip_soc_soft_reset
#pragma weak rockchip_soc_system_off
#pragma weak rockchip_soc_sys_pd_pwr_dn_wfi
#pragma weak rockchip_soc_cores_pd_pwr_dn_wfi
int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl,
plat_local_state_t lvl_state)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_cores_pwr_dm_off(void)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_sys_pwr_dm_suspend(void)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_cores_pwr_dm_suspend(void)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl,
plat_local_state_t lvl_state)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl,
plat_local_state_t lvl_state)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_cores_pwr_dm_on_finish(void)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_sys_pwr_dm_resume(void)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl,
plat_local_state_t lvl_state)
{
return PSCI_E_NOT_SUPPORTED;
}
int rockchip_soc_cores_pwr_dm_resume(void)
{
return PSCI_E_NOT_SUPPORTED;
}
void __dead2 rockchip_soc_soft_reset(void)
{
while (1)
;
}
void __dead2 rockchip_soc_system_off(void)
{
while (1)
;
}
void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(
const psci_power_state_t *target_state)
{
psci_power_down_wfi();
}
void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
{
psci_power_down_wfi();
}
/*******************************************************************************
* Rockchip standard platform handler called to check the validity of the power
* state parameter.
******************************************************************************/
int rockchip_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
int pstate = psci_get_pstate_type(power_state);
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
int i;
assert(req_state);
if (pwr_lvl > PLAT_MAX_PWR_LVL)
return PSCI_E_INVALID_PARAMS;
/* Sanity check the requested state */
if (pstate == PSTATE_TYPE_STANDBY) {
/*
* It's probably to enter standby only on power level 0
* ignore any other power level.
*/
if (pwr_lvl != MPIDR_AFFLVL0)
return PSCI_E_INVALID_PARAMS;
req_state->pwr_domain_state[MPIDR_AFFLVL0] =
PLAT_MAX_RET_STATE;
} else {
for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
req_state->pwr_domain_state[i] =
PLAT_MAX_OFF_STATE;
for (i = (pwr_lvl + 1); i <= PLAT_MAX_PWR_LVL; i++)
req_state->pwr_domain_state[i] =
PLAT_MAX_RET_STATE;
}
/* We expect the 'state id' to be zero */
if (psci_get_pstate_id(power_state))
return PSCI_E_INVALID_PARAMS;
return PSCI_E_SUCCESS;
}
void rockchip_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
int i;
for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
}
/*******************************************************************************
* RockChip handler called when a CPU is about to enter standby.
******************************************************************************/
void rockchip_cpu_standby(plat_local_state_t cpu_state)
{
u_register_t scr;
assert(cpu_state == PLAT_MAX_RET_STATE);
scr = read_scr_el3();
/* Enable PhysicalIRQ bit for NS world to wake the CPU */
write_scr_el3(scr | SCR_IRQ_BIT);
isb();
dsb();
wfi();
/*
* Restore SCR to the original value, synchronisation of scr_el3 is
* done by eret while el3_exit to save some execution cycles.
*/
write_scr_el3(scr);
}
/*******************************************************************************
* RockChip handler called when a power domain is about to be turned on. The
* mpidr determines the CPU to be turned on.
******************************************************************************/
int rockchip_pwr_domain_on(u_register_t mpidr)
{
return rockchip_soc_cores_pwr_dm_on(mpidr, rockchip_sec_entrypoint);
}
/*******************************************************************************
* RockChip handler called when a power domain is about to be turned off. The
* target_state encodes the power state that each level should transition to.
******************************************************************************/
void rockchip_pwr_domain_off(const psci_power_state_t *target_state)
{
uint32_t lvl;
plat_local_state_t lvl_state;
int ret;
assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
plat_rockchip_gic_cpuif_disable();
if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
plat_cci_disable();
rockchip_soc_cores_pwr_dm_off();
for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
lvl_state = target_state->pwr_domain_state[lvl];
ret = rockchip_soc_hlvl_pwr_dm_off(lvl, lvl_state);
if (ret == PSCI_E_NOT_SUPPORTED)
break;
}
}
/*******************************************************************************
* RockChip handler called when a power domain is about to be suspended. The
* target_state encodes the power state that each level should transition to.
******************************************************************************/
void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state)
{
uint32_t lvl;
plat_local_state_t lvl_state;
int ret;
if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
return;
/* Prevent interrupts from spuriously waking up this cpu */
plat_rockchip_gic_cpuif_disable();
if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
rockchip_soc_sys_pwr_dm_suspend();
else
rockchip_soc_cores_pwr_dm_suspend();
/* Perform the common cluster specific operations */
if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
plat_cci_disable();
if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
return;
for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
lvl_state = target_state->pwr_domain_state[lvl];
ret = rockchip_soc_hlvl_pwr_dm_suspend(lvl, lvl_state);
if (ret == PSCI_E_NOT_SUPPORTED)
break;
}
}
/*******************************************************************************
* RockChip handler called when a power domain has just been powered on after
* being turned off earlier. The target_state encodes the low power state that
* each level has woken up from.
******************************************************************************/
void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
uint32_t lvl;
plat_local_state_t lvl_state;
int ret;
assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE);
for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
lvl_state = target_state->pwr_domain_state[lvl];
ret = rockchip_soc_hlvl_pwr_dm_on_finish(lvl, lvl_state);
if (ret == PSCI_E_NOT_SUPPORTED)
break;
}
rockchip_soc_cores_pwr_dm_on_finish();
/* Perform the common cluster specific operations */
if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
/* Enable coherency if this cluster was off */
plat_cci_enable();
}
/* Enable the gic cpu interface */
plat_rockchip_gic_pcpu_init();
/* Program the gic per-cpu distributor or re-distributor interface */
plat_rockchip_gic_cpuif_enable();
}
/*******************************************************************************
* RockChip handler called when a power domain has just been powered on after
* having been suspended earlier. The target_state encodes the low power state
* that each level has woken up from.
* TODO: At the moment we reuse the on finisher and reinitialize the secure
* context. Need to implement a separate suspend finisher.
******************************************************************************/
void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
{
uint32_t lvl;
plat_local_state_t lvl_state;
int ret;
/* Nothing to be done on waking up from retention from CPU level */
if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
return;
if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
rockchip_soc_sys_pwr_dm_resume();
goto comm_finish;
}
for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) {
lvl_state = target_state->pwr_domain_state[lvl];
ret = rockchip_soc_hlvl_pwr_dm_resume(lvl, lvl_state);
if (ret == PSCI_E_NOT_SUPPORTED)
break;
}
rockchip_soc_cores_pwr_dm_resume();
/*
* Program the gic per-cpu distributor or re-distributor interface.
* For sys power domain operation, resuming of the gic needs to operate
* in rockchip_soc_sys_pwr_dm_resume(), according to the sys power mode
* implements.
*/
plat_rockchip_gic_cpuif_enable();
comm_finish:
/* Perform the common cluster specific operations */
if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
/* Enable coherency if this cluster was off */
plat_cci_enable();
}
}
/*******************************************************************************
* RockChip handlers to reboot the system
******************************************************************************/
static void __dead2 rockchip_system_reset(void)
{
rockchip_soc_soft_reset();
}
/*******************************************************************************
* RockChip handlers to power off the system
******************************************************************************/
static void __dead2 rockchip_system_poweroff(void)
{
rockchip_soc_system_off();
}
static void __dead2 rockchip_pd_pwr_down_wfi(
const psci_power_state_t *target_state)
{
if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
rockchip_soc_sys_pd_pwr_dn_wfi();
else
rockchip_soc_cores_pd_pwr_dn_wfi(target_state);
}
/*******************************************************************************
* Export the platform handlers via plat_rockchip_psci_pm_ops. The rockchip
* standard
* platform layer will take care of registering the handlers with PSCI.
******************************************************************************/
const plat_psci_ops_t plat_rockchip_psci_pm_ops = {
.cpu_standby = rockchip_cpu_standby,
.pwr_domain_on = rockchip_pwr_domain_on,
.pwr_domain_off = rockchip_pwr_domain_off,
.pwr_domain_suspend = rockchip_pwr_domain_suspend,
.pwr_domain_on_finish = rockchip_pwr_domain_on_finish,
.pwr_domain_suspend_finish = rockchip_pwr_domain_suspend_finish,
.pwr_domain_pwr_down_wfi = rockchip_pd_pwr_down_wfi,
.system_reset = rockchip_system_reset,
.system_off = rockchip_system_poweroff,
.validate_power_state = rockchip_validate_power_state,
.get_sys_suspend_power_state = rockchip_get_sys_suspend_power_state
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
*psci_ops = &plat_rockchip_psci_pm_ops;
rockchip_sec_entrypoint = sec_entrypoint;
return 0;
}
uintptr_t plat_get_sec_entrypoint(void)
{
assert(rockchip_sec_entrypoint);
return rockchip_sec_entrypoint;
}
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <arch.h>
#include <lib/psci/psci.h>
#include <plat_private.h>
/*******************************************************************************
* This function returns the RockChip default topology tree information.
******************************************************************************/
const unsigned char *plat_get_power_domain_tree_desc(void)
{
return rockchip_power_domain_tree_desc;
}
int plat_core_pos_by_mpidr(u_register_t mpidr)
{
unsigned int cluster_id, cpu_id;
cpu_id = mpidr & MPIDR_AFFLVL_MASK;
#ifdef PLAT_RK_MPIDR_CLUSTER_MASK
cluster_id = mpidr & PLAT_RK_MPIDR_CLUSTER_MASK;
#else
cluster_id = mpidr & MPIDR_CLUSTER_MASK;
#endif
cpu_id += (cluster_id >> PLAT_RK_CLST_TO_CPUID_SHIFT);
if (cpu_id >= PLATFORM_CORE_COUNT)
return -1;
return cpu_id;
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <platform_def.h>
#include <cpus_on_fixed_addr.h>
.globl sys_sleep_flag_sram
.globl pmu_cpuson_entrypoint
.macro pmusram_entry_func _name
.section .pmusram.entry, "ax"
.type \_name, %function
.cfi_startproc
\_name:
.endm
pmusram_entry_func pmu_cpuson_entrypoint
adr x5, sys_sleep_flag_sram
ldr w2, [x5, #PSRAM_DT_PM_FLAG]
tbz w2, #PM_WARM_BOOT_SHT, sys_resume_sp
ldr x1, =platform_cpu_warmboot
br x1
sys_resume_sp:
adr x5, sys_sleep_flag_sram
ldr x1, [x5, #PSRAM_DT_SP]
mov sp, x1
ddr_resume:
ldr x1, [x5, #PSRAM_DT_DDR_FUNC]
cmp x1, #0
b.eq sys_resume
blr x1
sys_resume:
ldr x1, =bl31_warm_entrypoint
br x1
endfunc pmu_cpuson_entrypoint
.section .pmusram.data, "a"
.align 3
sys_sleep_flag_sram:
.rept PSRAM_DT_SIZE_WORDS
.word 0
.endr
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __CPU_ON_FIXED_ADDR_H__
#define __CPU_ON_FIXED_ADDR_H__
/*****************************************************************************
* define data offset in struct psram_data
*****************************************************************************/
#define PSRAM_DT_SP 0x0
#define PSRAM_DT_DDR_FUNC 0x8
#define PSRAM_DT_DDR_DATA 0x10
#define PSRAM_DT_DDRFLAG 0x18
#define PSRAM_DT_MPIDR 0x1c
#define PSRAM_DT_PM_FLAG 0x20
#define PSRAM_DT_END 0x24
/* reserve 4 byte */
#define PSRAM_DT_END_RES4 (PSRAM_DT_END + 4)
#define PSRAM_DT_SIZE_WORDS (PSRAM_DT_END_RES4 / 4)
#define PM_WARM_BOOT_SHT 0
#define PM_WARM_BOOT_BIT (1 << PM_WARM_BOOT_SHT)
#ifndef __ASSEMBLER__
struct psram_data_t {
uint64_t sp;
uint64_t ddr_func;
uint64_t ddr_data;
uint32_t ddr_flag;
uint32_t boot_mpidr;
uint32_t pm_flag;
};
CASSERT(__builtin_offsetof(struct psram_data_t, sp) == PSRAM_DT_SP,
assert_psram_dt_sp_offset_mistmatch);
CASSERT(__builtin_offsetof(struct psram_data_t, ddr_func) == PSRAM_DT_DDR_FUNC,
assert_psram_dt_ddr_func_offset_mistmatch);
CASSERT(__builtin_offsetof(struct psram_data_t, ddr_data) == PSRAM_DT_DDR_DATA,
assert_psram_dt_ddr_data_offset_mistmatch);
CASSERT(__builtin_offsetof(struct psram_data_t, ddr_flag) == PSRAM_DT_DDRFLAG,
assert_psram_dt_ddr_flag_offset_mistmatch);
CASSERT(__builtin_offsetof(struct psram_data_t, boot_mpidr) == PSRAM_DT_MPIDR,
assert_psram_dt_mpidr_offset_mistmatch);
extern struct psram_data_t sys_sleep_flag_sram;
#endif /* __ASSEMBLER__ */
#endif
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/interrupt_props.h>
#include <drivers/arm/gicv2.h>
#include <lib/utils.h>
/******************************************************************************
* The following functions are defined as weak to allow a platform to override
* the way the GICv2 driver is initialised and used.
*****************************************************************************/
#pragma weak plat_rockchip_gic_driver_init
#pragma weak plat_rockchip_gic_init
#pragma weak plat_rockchip_gic_cpuif_enable
#pragma weak plat_rockchip_gic_cpuif_disable
#pragma weak plat_rockchip_gic_pcpu_init
/******************************************************************************
* List of interrupts.
*****************************************************************************/
static const interrupt_prop_t g0_interrupt_props[] = {
PLAT_RK_GICV2_G0_IRQS
};
/*
* Ideally `rockchip_gic_data` structure definition should be a `const` but it
* is kept as modifiable for overwriting with different GICD and GICC base when
* running on FVP with VE memory map.
*/
gicv2_driver_data_t rockchip_gic_data = {
.gicd_base = PLAT_RK_GICD_BASE,
.gicc_base = PLAT_RK_GICC_BASE,
.interrupt_props = g0_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(g0_interrupt_props),
};
/******************************************************************************
* RockChip common helper to initialize the GICv2 only driver.
*****************************************************************************/
void plat_rockchip_gic_driver_init(void)
{
gicv2_driver_init(&rockchip_gic_data);
}
void plat_rockchip_gic_init(void)
{
gicv2_distif_init();
gicv2_pcpu_distif_init();
gicv2_cpuif_enable();
}
/******************************************************************************
* RockChip common helper to enable the GICv2 CPU interface
*****************************************************************************/
void plat_rockchip_gic_cpuif_enable(void)
{
gicv2_cpuif_enable();
}
/******************************************************************************
* RockChip common helper to disable the GICv2 CPU interface
*****************************************************************************/
void plat_rockchip_gic_cpuif_disable(void)
{
gicv2_cpuif_disable();
}
/******************************************************************************
* RockChip common helper to initialize the per cpu distributor interface
* in GICv2
*****************************************************************************/
void plat_rockchip_gic_pcpu_init(void)
{
gicv2_pcpu_distif_init();
}
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/interrupt_props.h>
#include <drivers/arm/gicv3.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
/******************************************************************************
* The following functions are defined as weak to allow a platform to override
* the way the GICv3 driver is initialised and used.
*****************************************************************************/
#pragma weak plat_rockchip_gic_driver_init
#pragma weak plat_rockchip_gic_init
#pragma weak plat_rockchip_gic_cpuif_enable
#pragma weak plat_rockchip_gic_cpuif_disable
#pragma weak plat_rockchip_gic_pcpu_init
/* The GICv3 driver only needs to be initialized in EL3 */
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
static const interrupt_prop_t g01s_interrupt_props[] = {
PLAT_RK_GICV3_G0_IRQS,
PLAT_RK_GICV3_G1S_IRQS
};
static unsigned int plat_rockchip_mpidr_to_core_pos(unsigned long mpidr)
{
return (unsigned int)plat_core_pos_by_mpidr(mpidr);
}
const gicv3_driver_data_t rockchip_gic_data = {
.gicd_base = PLAT_RK_GICD_BASE,
.gicr_base = PLAT_RK_GICR_BASE,
.interrupt_props = g01s_interrupt_props,
.interrupt_props_num = ARRAY_SIZE(g01s_interrupt_props),
.rdistif_num = PLATFORM_CORE_COUNT,
.rdistif_base_addrs = rdistif_base_addrs,
.mpidr_to_core_pos = plat_rockchip_mpidr_to_core_pos,
};
void plat_rockchip_gic_driver_init(void)
{
/*
* The GICv3 driver is initialized in EL3 and does not need
* to be initialized again in SEL1. This is because the S-EL1
* can use GIC system registers to manage interrupts and does
* not need GIC interface base addresses to be configured.
*/
#ifdef IMAGE_BL31
gicv3_driver_init(&rockchip_gic_data);
#endif
}
/******************************************************************************
* RockChip common helper to initialize the GIC. Only invoked
* by BL31
*****************************************************************************/
void plat_rockchip_gic_init(void)
{
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
}
/******************************************************************************
* RockChip common helper to enable the GIC CPU interface
*****************************************************************************/
void plat_rockchip_gic_cpuif_enable(void)
{
gicv3_cpuif_enable(plat_my_core_pos());
}
/******************************************************************************
* RockChip common helper to disable the GIC CPU interface
*****************************************************************************/
void plat_rockchip_gic_cpuif_disable(void)
{
gicv3_cpuif_disable(plat_my_core_pos());
}
/******************************************************************************
* RockChip common helper to initialize the per-cpu redistributor interface
* in GICv3
*****************************************************************************/
void plat_rockchip_gic_pcpu_init(void)
{
gicv3_rdistif_init(plat_my_core_pos());
}
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/mmio.h>
#include <tools_share/uuid.h>
#include <plat_sip_calls.h>
#include <rockchip_sip_svc.h>
/* Rockchip SiP Service UUID */
DEFINE_SVC_UUID2(rk_sip_svc_uid,
0xe2c76fe8, 0x3e31, 0xe611, 0xb7, 0x0d,
0x8f, 0x88, 0xee, 0x74, 0x7b, 0x72);
#pragma weak rockchip_plat_sip_handler
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);
}
/*
* This function is responsible for handling all SiP calls from the NS world
*/
uintptr_t sip_smc_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)
{
uint32_t ns;
/* Determine which security state this SMC originated from */
ns = is_caller_non_secure(flags);
if (!ns)
SMC_RET1(handle, SMC_UNK);
switch (smc_fid) {
case SIP_SVC_CALL_COUNT:
/* Return the number of Rockchip SiP Service Calls. */
SMC_RET1(handle,
RK_COMMON_SIP_NUM_CALLS + RK_PLAT_SIP_NUM_CALLS);
case SIP_SVC_UID:
/* Return UID to the caller */
SMC_UUID_RET(handle, rk_sip_svc_uid);
case SIP_SVC_VERSION:
/* Return the version of current implementation */
SMC_RET2(handle, RK_SIP_SVC_VERSION_MAJOR,
RK_SIP_SVC_VERSION_MINOR);
default:
return rockchip_plat_sip_handler(smc_fid, x1, x2, x3, x4,
cookie, handle, flags);
}
}
/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
rockchip_sip_svc,
OEN_SIP_START,
OEN_SIP_END,
SMC_TYPE_FAST,
NULL,
sip_smc_handler
);
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <arch_helpers.h>
#include <plat/common/platform.h>
#define RANDOM_CANARY_VALUE ((u_register_t) 3288484550995823360ULL)
u_register_t plat_get_stack_protector_canary(void)
{
/*
* Ideally, a random number should be returned instead of the
* combination of a timer's value and a compile-time constant.
* As the virt platform does not have any random number generator,
* this is better than nothing but not necessarily really secure.
*/
return RANDOM_CANARY_VALUE ^ read_cntpct_el0();
}
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/console.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/ti/uart/uart_16550.h>
#include <lib/mmio.h>
#include <plat_private.h>
#include <plat/common/platform.h>
static entry_point_info_t bl33_ep_info;
/*******************************************************************************
* Return a pointer to the 'entry_point_info' structure of the next image for
* the security state specified. BL33 corresponds to the non-secure image type.
* A NULL pointer is returned if the image does not exist.
******************************************************************************/
entry_point_info_t *sp_min_plat_get_bl33_ep_info(void)
{
entry_point_info_t *next_image_info;
next_image_info = &bl33_ep_info;
if (next_image_info->pc == 0U) {
return NULL;
}
return next_image_info;
}
#pragma weak params_early_setup
void params_early_setup(u_register_t plat_param_from_bl2)
{
}
unsigned int plat_is_my_cpu_primary(void);
/*******************************************************************************
* Perform any BL32 specific platform actions.
******************************************************************************/
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
static console_t console;
params_early_setup(arg1);
if (rockchip_get_uart_base() != 0)
console_16550_register(rockchip_get_uart_base(),
rockchip_get_uart_clock(),
rockchip_get_uart_baudrate(), &console);
VERBOSE("sp_min_setup\n");
bl31_params_parse_helper(arg0, NULL, &bl33_ep_info);
}
/*******************************************************************************
* Perform any sp_min platform setup code
******************************************************************************/
void sp_min_platform_setup(void)
{
generic_delay_timer_init();
plat_rockchip_soc_init();
/* Initialize the gic cpu and distributor interfaces */
plat_rockchip_gic_driver_init();
plat_rockchip_gic_init();
plat_rockchip_pmu_init();
}
/*******************************************************************************
* Perform the very early platform specific architectural setup here. At the
* moment this is only intializes the mmu in a quick and dirty way.
******************************************************************************/
void sp_min_plat_arch_setup(void)
{
plat_cci_init();
plat_cci_enable();
plat_configure_mmu_svc_mon(BL_CODE_BASE,
BL_COHERENT_RAM_END - BL_CODE_BASE,
BL_CODE_BASE,
BL_CODE_END,
BL_COHERENT_RAM_BASE,
BL_COHERENT_RAM_END);
}
void sp_min_plat_fiq_handler(uint32_t id)
{
VERBOSE("[sp_min] interrupt #%d\n", id);
}