GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+114
@@ -0,0 +1,114 @@
|
||||
#
|
||||
# Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
include lib/libfdt/libfdt.mk
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
AW_PLAT := plat/allwinner
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/plat/arm/common/aarch64 \
|
||||
-I${AW_PLAT}/common/include \
|
||||
-I${AW_PLAT}/${PLAT}/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/ti/uart/${ARCH}/16550_console.S \
|
||||
${XLAT_TABLES_LIB_SRCS} \
|
||||
${AW_PLAT}/common/plat_helpers.S \
|
||||
${AW_PLAT}/common/sunxi_common.c
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/common.c \
|
||||
${GICV2_SOURCES} \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
lib/cpus/${ARCH}/cortex_a53.S \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/common/plat_psci_common.c \
|
||||
${AW_PLAT}/common/sunxi_bl31_setup.c \
|
||||
${AW_PLAT}/${PLAT}/sunxi_idle_states.c \
|
||||
${AW_PLAT}/common/sunxi_pm.c \
|
||||
${AW_PLAT}/${PLAT}/sunxi_power.c \
|
||||
${AW_PLAT}/common/sunxi_security.c \
|
||||
${AW_PLAT}/common/sunxi_topology.c
|
||||
|
||||
# By default, attempt to use SCPI to the ARISC management processor. If SCPI
|
||||
# is not enabled or SCP firmware is not loaded, fall back to a simpler native
|
||||
# implementation that does not support CPU or system suspend.
|
||||
#
|
||||
# If SCP firmware will always be present (or absent), the unused implementation
|
||||
# can be compiled out.
|
||||
SUNXI_PSCI_USE_NATIVE ?= 1
|
||||
SUNXI_PSCI_USE_SCPI ?= 1
|
||||
|
||||
$(eval $(call assert_boolean,SUNXI_PSCI_USE_NATIVE))
|
||||
$(eval $(call assert_boolean,SUNXI_PSCI_USE_SCPI))
|
||||
$(eval $(call add_define,SUNXI_PSCI_USE_NATIVE))
|
||||
$(eval $(call add_define,SUNXI_PSCI_USE_SCPI))
|
||||
|
||||
ifeq (${SUNXI_PSCI_USE_NATIVE}${SUNXI_PSCI_USE_SCPI},00)
|
||||
$(error "At least one of SCPI or native PSCI ops must be enabled")
|
||||
endif
|
||||
|
||||
ifeq (${SUNXI_PSCI_USE_NATIVE},1)
|
||||
BL31_SOURCES += ${AW_PLAT}/common/sunxi_cpu_ops.c \
|
||||
${AW_PLAT}/common/sunxi_native_pm.c
|
||||
endif
|
||||
|
||||
ifeq (${SUNXI_PSCI_USE_SCPI},1)
|
||||
BL31_SOURCES += drivers/allwinner/sunxi_msgbox.c \
|
||||
drivers/arm/css/scpi/css_scpi.c \
|
||||
${AW_PLAT}/common/sunxi_scpi_pm.c
|
||||
endif
|
||||
|
||||
SUNXI_SETUP_REGULATORS ?= 1
|
||||
$(eval $(call assert_boolean,SUNXI_SETUP_REGULATORS))
|
||||
$(eval $(call add_define,SUNXI_SETUP_REGULATORS))
|
||||
|
||||
SUNXI_BL31_IN_DRAM ?= 0
|
||||
$(eval $(call assert_boolean,SUNXI_BL31_IN_DRAM))
|
||||
|
||||
ifeq (${SUNXI_BL31_IN_DRAM},1)
|
||||
SUNXI_AMEND_DTB := 1
|
||||
$(eval $(call add_define,SUNXI_BL31_IN_DRAM))
|
||||
endif
|
||||
|
||||
SUNXI_AMEND_DTB ?= 0
|
||||
$(eval $(call assert_boolean,SUNXI_AMEND_DTB))
|
||||
$(eval $(call add_define,SUNXI_AMEND_DTB))
|
||||
|
||||
ifeq (${SUNXI_AMEND_DTB},1)
|
||||
BL31_SOURCES += common/fdt_fixup.c \
|
||||
${AW_PLAT}/common/sunxi_prepare_dtb.c
|
||||
endif
|
||||
|
||||
# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
|
||||
COLD_BOOT_SINGLE_CPU := 1
|
||||
|
||||
# Do not enable SPE (not supported on ARM v8.0).
|
||||
ENABLE_SPE_FOR_LOWER_ELS := 0
|
||||
|
||||
# Do not enable SVE (not supported on ARM v8.0).
|
||||
ENABLE_SVE_FOR_NS := 0
|
||||
|
||||
# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
|
||||
ERRATA_A53_835769 := 1
|
||||
ERRATA_A53_843419 := 1
|
||||
ERRATA_A53_855873 := 1
|
||||
ERRATA_A53_1530924 := 1
|
||||
|
||||
# The traditional U-Boot load address is 160MB into DRAM.
|
||||
PRELOADED_BL33_BASE ?= 0x4a000000
|
||||
|
||||
# The reset vector can be changed for each CPU.
|
||||
PROGRAMMABLE_RESET_ADDRESS := 1
|
||||
|
||||
# Allow mapping read-only data as execute-never.
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
|
||||
RESET_TO_BL31 := 1
|
||||
|
||||
# This platform is single-cluster and does not require coherency setup.
|
||||
WARMBOOT_ENABLE_DCACHE_EARLY := 1
|
||||
@@ -0,0 +1,115 @@
|
||||
# turn_off_core.S
|
||||
#
|
||||
# Copyright (c) 2018, Andre Przywara <osp@andrep.de>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# OpenRISC assembly to turn off an ARM core on an Allwinner SoC from
|
||||
# the arisc management controller.
|
||||
# Generate a binary representation with:
|
||||
# $ or1k-elf-as -c -o turn_off_core.o turn_off_core.S
|
||||
# $ or1k-elf-objcopy -O binary --reverse-bytes=4 turn_off_core.o \
|
||||
# turn_off_core.bin
|
||||
# The encoded instructions go into an array defined in
|
||||
# plat/allwinner/sun50i_*/include/core_off_arisc.h, to be handed off to
|
||||
# the arisc processor.
|
||||
#
|
||||
# This routine is meant to be called directly from arisc reset (put the
|
||||
# start address in the reset vector), to be actually triggered by that
|
||||
# very ARM core to be turned off.
|
||||
# It expects the core number presented as a mask in the upper half of
|
||||
# r3, so to be patched in the lower 16 bits of the first instruction,
|
||||
# overwriting the 0 in this code here.
|
||||
# The code will do the following:
|
||||
# - Read the C_CPU_STATUS register, which contains the status of the WFI
|
||||
# lines of each of the four A53 cores.
|
||||
# - Loop until the core in question reaches WFI.
|
||||
# - Using that mask, activate the core output clamps by setting the
|
||||
# respective core bit in CPUX_PWROFF_GATING_REG (0x1f01500).
|
||||
# Note that the clamp for core 0 covers more than just the core, activating
|
||||
# it hangs the whole system. So we skip this step for core 0.
|
||||
# - Using the negated mask, assert the core's reset line by clearing the
|
||||
# respective bit in C_RST_CTRL (0x1f01c30).
|
||||
# - Finally turn off the core's power switch by writing 0xff to the
|
||||
# respective CPUx_PWR_SWITCH_REG (0x1f01540 ff.)
|
||||
# - Assert the arisc's own reset to end execution.
|
||||
# This also signals other arisc users that the chip is free again.
|
||||
# So in C this would look like:
|
||||
# while (!(readl(0x1700030) & (1U << core_nr)))
|
||||
# ;
|
||||
# if (core_nr != 0)
|
||||
# writel(readl(0x1f01500) | (1U << core_nr), 0x1f01500);
|
||||
# writel(readl(0x1f01c30) & ~(1U << core_nr), 0x1f01c30);
|
||||
# writel(0xff, 0x1f01540 + (core_nr * 4));
|
||||
# (using A64/H5 addresses)
|
||||
|
||||
.text
|
||||
_start:
|
||||
l.movhi r3, 0 # FIXUP! with core mask
|
||||
l.movhi r0, 0 # clear r0
|
||||
l.movhi r13, 0x170 # r13: CPU_CFG_BASE=0x01700000
|
||||
wait_wfi:
|
||||
l.lwz r5, 0x30(r13) # load C_CPU_STATUS
|
||||
l.and r5, r5, r3 # mask requested core
|
||||
l.sfeq r5, r0 # is it not yet in WFI?
|
||||
l.bf wait_wfi # try again
|
||||
|
||||
l.srli r6, r3, 16 # move mask to lower 16 bits
|
||||
l.sfeqi r6, 1 # core 0 is special
|
||||
l.bf 1f # don't touch the bit for core 0
|
||||
l.movhi r13, 0x1f0 # address of R_CPUCFG (delay)
|
||||
l.lwz r5, 0x1500(r13) # core output clamps
|
||||
l.or r5, r5, r6 # set bit to ...
|
||||
l.sw 0x1500(r13), r5 # ... activate for our core
|
||||
|
||||
1: l.lwz r5, 0x1c30(r13) # CPU power-on reset
|
||||
l.xori r6, r6, -1 # negate core mask
|
||||
l.and r5, r5, r6 # clear bit to ...
|
||||
l.sw 0x1c30(r13), r5 # ... assert for our core
|
||||
|
||||
l.ff1 r6, r3 # get core number from high mask
|
||||
l.addi r6, r6, -17 # convert to 0-3
|
||||
l.slli r6, r6, 2 # r5: core number*4 (0-12)
|
||||
l.add r6, r6, r13 # add to base address
|
||||
l.ori r5, r0, 0xff # 0xff means all switches off
|
||||
l.sw 0x1540(r6), r5 # core power switch registers
|
||||
|
||||
reset: l.sw 0x1c00(r13),r0 # pull down our own reset line
|
||||
|
||||
l.j reset # just in case ....
|
||||
l.nop 0x0 # (delay slot)
|
||||
|
||||
# same as above, but with the MMIO addresses matching the H6 SoC
|
||||
_start_h6:
|
||||
l.movhi r3, 0 # FIXUP! with core mask
|
||||
l.movhi r0, 0 # clear r0
|
||||
l.movhi r13, 0x901 # r13: CPU_CFG_BASE=0x09010000
|
||||
1:
|
||||
l.lwz r5, 0x80(r13) # load C_CPU_STATUS
|
||||
l.and r5, r5, r3 # mask requested core
|
||||
l.sfeq r5, r0 # is it not yet in WFI?
|
||||
l.bf 1b # try again
|
||||
|
||||
l.srli r6, r3, 16 # move mask to lower 16 bits(ds)
|
||||
l.sfeqi r6, 1 # core 0 is special
|
||||
l.bf 1f # don't touch the bit for core 0
|
||||
l.movhi r13, 0x700 # address of R_CPUCFG (ds)
|
||||
l.lwz r5, 0x0444(r13) # core output clamps
|
||||
l.or r5, r5, r6 # set bit to ...
|
||||
l.sw 0x0444(r13), r5 # ... activate for our core
|
||||
|
||||
1: l.lwz r5, 0x0440(r13) # CPU power-on reset
|
||||
l.xori r6, r6, -1 # negate core mask
|
||||
l.and r5, r5, r6 # clear bit to ...
|
||||
l.sw 0x0440(r13), r5 # ... assert for our core
|
||||
|
||||
l.ff1 r6, r3 # get core number from high mask
|
||||
l.addi r6, r6, -17 # convert to 0-3
|
||||
l.slli r6, r6, 2 # r5: core number*4 (0-12)
|
||||
l.add r6, r6, r13 # add to base address
|
||||
l.ori r5, r0, 0xff # 0xff means all switches off
|
||||
l.sw 0x0450(r6), r5 # core power switch registers
|
||||
|
||||
1: l.sw 0x0400(r13),r0 # pull down our own reset line
|
||||
|
||||
l.j 1b # just in case ...
|
||||
l.nop 0x0 # (delay slot)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* https://spdx.org/licenses
|
||||
*/
|
||||
/* This driver provides I2C support for Allwinner sunXi SoCs */
|
||||
|
||||
#ifndef MENTOR_I2C_PLAT_H
|
||||
#define MENTOR_I2C_PLAT_H
|
||||
|
||||
#define CONFIG_SYS_TCLK 24000000
|
||||
#define CONFIG_SYS_I2C_SPEED 100000
|
||||
#define CONFIG_SYS_I2C_SLAVE 0
|
||||
|
||||
#define I2C_INTERRUPT_CLEAR_INVERTED
|
||||
|
||||
struct mentor_i2c_regs {
|
||||
uint32_t slave_address;
|
||||
uint32_t xtnd_slave_addr;
|
||||
uint32_t data;
|
||||
uint32_t control;
|
||||
uint32_t status;
|
||||
uint32_t baudrate;
|
||||
uint32_t soft_reset;
|
||||
};
|
||||
|
||||
#endif /* MENTOR_I2C_PLAT_H */
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <arm_macros.S>
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant GIC and CCI registers
|
||||
* whenever an unhandled exception is taken in
|
||||
* BL31.
|
||||
* Clobbers: x0 - x10, x16, x17, sp
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
mov_imm x17, SUNXI_GICC_BASE
|
||||
mov_imm x16, SUNXI_GICD_BASE
|
||||
arm_print_gic_regs
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
#ifdef SUNXI_BL31_IN_DRAM
|
||||
|
||||
#define BL31_BASE SUNXI_DRAM_BASE
|
||||
#define BL31_LIMIT (SUNXI_DRAM_BASE + 0x40000)
|
||||
|
||||
#define MAX_XLAT_TABLES 4
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
#define SUNXI_BL33_VIRT_BASE PRELOADED_BL33_BASE
|
||||
|
||||
#else /* !SUNXI_BL31_IN_DRAM */
|
||||
|
||||
#define BL31_BASE (SUNXI_SRAM_A2_BASE + \
|
||||
SUNXI_SRAM_A2_BL31_OFFSET)
|
||||
#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + \
|
||||
SUNXI_SRAM_A2_SIZE - SUNXI_SCP_SIZE)
|
||||
|
||||
/* Overwrite U-Boot SPL, but reserve the first page for the SPL header. */
|
||||
#define BL31_NOBITS_BASE (SUNXI_SRAM_A1_BASE + 0x1000)
|
||||
#define BL31_NOBITS_LIMIT (SUNXI_SRAM_A1_BASE + SUNXI_SRAM_A1_SIZE)
|
||||
|
||||
#define MAX_XLAT_TABLES 1
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 28)
|
||||
|
||||
#define SUNXI_BL33_VIRT_BASE SUNXI_DRAM_VIRT_BASE
|
||||
|
||||
/* The SCP firmware is allocated the last 16KiB of SRAM A2. */
|
||||
#define SUNXI_SCP_BASE BL31_LIMIT
|
||||
#define SUNXI_SCP_SIZE 0x4000
|
||||
|
||||
#endif /* SUNXI_BL31_IN_DRAM */
|
||||
|
||||
/* How much DRAM to map (to map BL33, for fetching the DTB from U-Boot) */
|
||||
#define SUNXI_DRAM_MAP_SIZE (64U << 20)
|
||||
|
||||
#define CACHE_WRITEBACK_SHIFT 6
|
||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
#define MAX_STATIC_MMAP_REGIONS 3
|
||||
#define MAX_MMAP_REGIONS (5 + MAX_STATIC_MMAP_REGIONS)
|
||||
|
||||
#define PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
|
||||
(SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE - 0x200)
|
||||
|
||||
/* These states are used directly for SCPI communication. */
|
||||
#define PLAT_MAX_PWR_LVL_STATES U(3)
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(3)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL U(2)
|
||||
#define PLAT_NUM_PWR_DOMAINS (U(1) + \
|
||||
PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
|
||||
|
||||
#ifndef SPD_none
|
||||
#ifndef BL32_BASE
|
||||
#define BL32_BASE SUNXI_DRAM_BASE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_DEF_H
|
||||
#define SUNXI_DEF_H
|
||||
|
||||
/* Clock configuration */
|
||||
#define SUNXI_OSC24M_CLK_IN_HZ 24000000
|
||||
|
||||
/* UART configuration */
|
||||
#define SUNXI_UART0_BAUDRATE 115200
|
||||
#define SUNXI_UART0_CLK_IN_HZ SUNXI_OSC24M_CLK_IN_HZ
|
||||
|
||||
#define SUNXI_SOC_A64 0x1689
|
||||
#define SUNXI_SOC_H5 0x1718
|
||||
#define SUNXI_SOC_H6 0x1728
|
||||
#define SUNXI_SOC_H616 0x1823
|
||||
#define SUNXI_SOC_R329 0x1851
|
||||
|
||||
#define JEDEC_ALLWINNER_BKID 9U
|
||||
#define JEDEC_ALLWINNER_MFID 0x9eU
|
||||
|
||||
#endif /* SUNXI_DEF_H */
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_PRIVATE_H
|
||||
#define SUNXI_PRIVATE_H
|
||||
|
||||
#include <common/fdt_fixup.h>
|
||||
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
extern const struct psci_cpu_idle_state sunxi_idle_states[];
|
||||
|
||||
void sunxi_configure_mmu_el3(int flags);
|
||||
|
||||
void sunxi_cpu_on(u_register_t mpidr);
|
||||
void sunxi_cpu_power_off_others(void);
|
||||
void sunxi_cpu_power_off_self(void);
|
||||
void sunxi_power_down(void);
|
||||
|
||||
#if SUNXI_PSCI_USE_NATIVE
|
||||
void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops);
|
||||
#else
|
||||
static inline void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#if SUNXI_PSCI_USE_SCPI
|
||||
bool sunxi_psci_is_scpi(void);
|
||||
int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops);
|
||||
#else
|
||||
static inline bool sunxi_psci_is_scpi(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint);
|
||||
|
||||
int sunxi_pmic_setup(uint16_t socid, const void *fdt);
|
||||
void sunxi_security_setup(void);
|
||||
|
||||
uint16_t sunxi_read_soc_id(void);
|
||||
void sunxi_set_gpio_out(char port, int pin, bool level_high);
|
||||
int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb);
|
||||
void sunxi_execute_arisc_code(uint32_t *code, size_t size, uint16_t param);
|
||||
|
||||
#if SUNXI_AMEND_DTB
|
||||
void sunxi_prepare_dtb(void *fdt);
|
||||
#else
|
||||
static inline void sunxi_prepare_dtb(void *fdt)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SUNXI_PRIVATE_H */
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_my_core_pos
|
||||
.globl platform_mem_init
|
||||
.globl plat_report_exception
|
||||
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, SUNXI_UART0_BASE
|
||||
mov_imm x1, SUNXI_UART0_CLK_IN_HZ
|
||||
mov_imm x2, SUNXI_UART0_BAUDRATE
|
||||
b console_16550_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, SUNXI_UART0_BASE
|
||||
b console_16550_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
func plat_crash_console_flush
|
||||
ret
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
and x1, x0, #MPIDR_CLUSTER_MASK
|
||||
and x0, x0, #MPIDR_CPU_MASK
|
||||
add x0, x0, x1, LSR #6
|
||||
ret
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
func plat_report_exception
|
||||
ret
|
||||
endfunc plat_report_exception
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
static console_t console;
|
||||
|
||||
static void *fdt;
|
||||
|
||||
static const gicv2_driver_data_t sunxi_gic_data = {
|
||||
.gicd_base = SUNXI_GICD_BASE,
|
||||
.gicc_base = SUNXI_GICC_BASE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Try to find a DTB loaded in memory by previous stages.
|
||||
*
|
||||
* At the moment we implement a heuristic to find the DTB attached to U-Boot:
|
||||
* U-Boot appends its DTB to the end of the image. Assuming that BL33 is
|
||||
* U-Boot, try to find the size of the U-Boot image to learn the DTB address.
|
||||
* The generic ARMv8 U-Boot image contains the load address and its size
|
||||
* as u64 variables at the beginning of the image. There might be padding
|
||||
* or other headers before that data, so scan the first 2KB after the BL33
|
||||
* entry point to find the load address, which should be followed by the
|
||||
* size. Adding those together gives us the address of the DTB.
|
||||
*/
|
||||
static void sunxi_find_dtb(void)
|
||||
{
|
||||
uint64_t *u_boot_base;
|
||||
int i;
|
||||
|
||||
u_boot_base = (void *)SUNXI_BL33_VIRT_BASE;
|
||||
|
||||
for (i = 0; i < 2048 / sizeof(uint64_t); i++) {
|
||||
void *dtb_base;
|
||||
|
||||
if (u_boot_base[i] != PRELOADED_BL33_BASE)
|
||||
continue;
|
||||
|
||||
/* Does the suspected U-Boot size look anyhow reasonable? */
|
||||
if (u_boot_base[i + 1] >= 256 * 1024 * 1024)
|
||||
continue;
|
||||
|
||||
/* end of the image: base address + size */
|
||||
dtb_base = (char *)u_boot_base + u_boot_base[i + 1];
|
||||
|
||||
if (fdt_check_header(dtb_base) == 0) {
|
||||
fdt = dtb_base;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Initialize the debug console as soon as possible */
|
||||
console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
|
||||
SUNXI_UART0_BAUDRATE, &console);
|
||||
|
||||
#ifdef BL32_BASE
|
||||
/* Populate entry point information for BL32 */
|
||||
SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
|
||||
SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
|
||||
bl32_image_ep_info.pc = BL32_BASE;
|
||||
#endif
|
||||
|
||||
/* Populate entry point information for BL33 */
|
||||
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
|
||||
/*
|
||||
* Tell BL31 where the non-trusted software image
|
||||
* is located and the entry state information
|
||||
*/
|
||||
bl33_image_ep_info.pc = PRELOADED_BL33_BASE;
|
||||
bl33_image_ep_info.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX,
|
||||
DISABLE_ALL_EXCEPTIONS);
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
sunxi_configure_mmu_el3(0);
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
const char *soc_name;
|
||||
uint16_t soc_id = sunxi_read_soc_id();
|
||||
|
||||
switch (soc_id) {
|
||||
case SUNXI_SOC_A64:
|
||||
soc_name = "A64/H64/R18";
|
||||
break;
|
||||
case SUNXI_SOC_H5:
|
||||
soc_name = "H5";
|
||||
break;
|
||||
case SUNXI_SOC_H6:
|
||||
soc_name = "H6";
|
||||
break;
|
||||
case SUNXI_SOC_H616:
|
||||
soc_name = "H616";
|
||||
break;
|
||||
case SUNXI_SOC_R329:
|
||||
soc_name = "R329";
|
||||
break;
|
||||
default:
|
||||
soc_name = "unknown";
|
||||
break;
|
||||
}
|
||||
NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id);
|
||||
|
||||
generic_delay_timer_init();
|
||||
|
||||
sunxi_find_dtb();
|
||||
if (fdt) {
|
||||
const char *model;
|
||||
int length;
|
||||
|
||||
model = fdt_getprop(fdt, 0, "model", &length);
|
||||
NOTICE("BL31: Found U-Boot DTB at %p, model: %s\n", fdt,
|
||||
model ?: "unknown");
|
||||
} else {
|
||||
NOTICE("BL31: No DTB found.\n");
|
||||
}
|
||||
|
||||
/* Configure the interrupt controller */
|
||||
gicv2_driver_init(&sunxi_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
sunxi_security_setup();
|
||||
|
||||
/*
|
||||
* On the A64 U-Boot's SPL sets the bus clocks to some conservative
|
||||
* values, to work around FEL mode instabilities with SRAM C accesses.
|
||||
* FEL mode is gone when we reach ATF, so bring the AHB1 bus
|
||||
* (the "main" bus) clock frequency back to the recommended 200MHz,
|
||||
* for improved performance.
|
||||
*/
|
||||
if (soc_id == SUNXI_SOC_A64)
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x00003180);
|
||||
|
||||
/*
|
||||
* U-Boot or the kernel don't setup AHB2, which leaves it at the
|
||||
* AHB1 frequency (200 MHz, see above). However Allwinner recommends
|
||||
* 300 MHz, for improved Ethernet and USB performance. Switch the
|
||||
* clock to use "PLL_PERIPH0 / 2".
|
||||
*/
|
||||
if (soc_id == SUNXI_SOC_A64 || soc_id == SUNXI_SOC_H5)
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0x1);
|
||||
|
||||
sunxi_pmic_setup(soc_id, fdt);
|
||||
|
||||
INFO("BL31: Platform setup done\n");
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
/* Change the DTB if the configuration requires so. */
|
||||
sunxi_prepare_dtb(fdt);
|
||||
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
assert(sec_state_is_valid(type) != 0);
|
||||
|
||||
if (type == NON_SECURE)
|
||||
return &bl33_image_ep_info;
|
||||
|
||||
if ((type == SECURE) && bl32_image_ep_info.pc)
|
||||
return &bl32_image_ep_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/smccc.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <services/arm_arch_svc.h>
|
||||
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
static const mmap_region_t sunxi_mmap[MAX_STATIC_MMAP_REGIONS + 1] = {
|
||||
MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
|
||||
MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER),
|
||||
MAP_REGION(PRELOADED_BL33_BASE, SUNXI_BL33_VIRT_BASE,
|
||||
SUNXI_DRAM_MAP_SIZE, MT_RW_DATA | MT_NS),
|
||||
{},
|
||||
};
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return SUNXI_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
|
||||
void sunxi_configure_mmu_el3(int flags)
|
||||
{
|
||||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
||||
BL_CODE_END - BL_CODE_BASE,
|
||||
MT_CODE | MT_SECURE);
|
||||
mmap_add_region(BL_CODE_END, BL_CODE_END,
|
||||
BL_END - BL_CODE_END,
|
||||
MT_RW_DATA | MT_SECURE);
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE,
|
||||
MT_RO_DATA | MT_SECURE);
|
||||
#endif
|
||||
#if SEPARATE_NOBITS_REGION
|
||||
mmap_add_region(BL_NOBITS_BASE, BL_NOBITS_BASE,
|
||||
BL_NOBITS_END - BL_NOBITS_BASE,
|
||||
MT_RW_DATA | MT_SECURE);
|
||||
#endif
|
||||
#if USE_COHERENT_MEM
|
||||
mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE,
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER);
|
||||
#endif
|
||||
|
||||
mmap_add(sunxi_mmap);
|
||||
init_xlat_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
#define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
|
||||
uint16_t sunxi_read_soc_id(void)
|
||||
{
|
||||
uint32_t reg = mmio_read_32(SRAM_VER_REG);
|
||||
|
||||
/* Set bit 15 to prepare for the SOCID read. */
|
||||
mmio_write_32(SRAM_VER_REG, reg | BIT(15));
|
||||
|
||||
reg = mmio_read_32(SRAM_VER_REG);
|
||||
|
||||
/* deactivate the SOCID access again */
|
||||
mmio_write_32(SRAM_VER_REG, reg & ~BIT(15));
|
||||
|
||||
return reg >> 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure a given pin to the GPIO-OUT function and sets its level.
|
||||
* The port is given as a capital letter, the pin is the number within
|
||||
* this port group.
|
||||
* So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true);
|
||||
*/
|
||||
void sunxi_set_gpio_out(char port, int pin, bool level_high)
|
||||
{
|
||||
uintptr_t port_base;
|
||||
|
||||
if (port < 'A' || port > 'L')
|
||||
return;
|
||||
if (port == 'L')
|
||||
port_base = SUNXI_R_PIO_BASE;
|
||||
else
|
||||
port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24;
|
||||
|
||||
/* Set the new level first before configuring the pin. */
|
||||
if (level_high)
|
||||
mmio_setbits_32(port_base + 0x10, BIT(pin));
|
||||
else
|
||||
mmio_clrbits_32(port_base + 0x10, BIT(pin));
|
||||
|
||||
/* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */
|
||||
mmio_clrsetbits_32(port_base + (pin / 8) * 4,
|
||||
0x7 << ((pin % 8) * 4),
|
||||
0x1 << ((pin % 8) * 4));
|
||||
}
|
||||
|
||||
int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb)
|
||||
{
|
||||
uint32_t pin_func = 0x77;
|
||||
uint32_t device_bit;
|
||||
unsigned int reset_offset = 0xb0;
|
||||
|
||||
switch (socid) {
|
||||
case SUNXI_SOC_H5:
|
||||
if (use_rsb)
|
||||
return -ENODEV;
|
||||
pin_func = 0x22;
|
||||
device_bit = BIT(6);
|
||||
break;
|
||||
case SUNXI_SOC_H6:
|
||||
case SUNXI_SOC_H616:
|
||||
pin_func = use_rsb ? 0x22 : 0x33;
|
||||
device_bit = BIT(16);
|
||||
reset_offset = use_rsb ? 0x1bc : 0x19c;
|
||||
break;
|
||||
case SUNXI_SOC_A64:
|
||||
pin_func = use_rsb ? 0x22 : 0x33;
|
||||
device_bit = use_rsb ? BIT(3) : BIT(6);
|
||||
break;
|
||||
default:
|
||||
INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* un-gate R_PIO clock */
|
||||
if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616)
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0));
|
||||
|
||||
/* switch pins PL0 and PL1 to the desired function */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func);
|
||||
|
||||
/* level 2 drive strength */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU);
|
||||
|
||||
/* set both pins to pull-up */
|
||||
mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U);
|
||||
|
||||
/* un-gate clock */
|
||||
if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616)
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit);
|
||||
else
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0));
|
||||
|
||||
/* assert, then de-assert reset of I2C/RSB controller */
|
||||
mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
|
||||
mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t plat_is_smccc_feature_available(u_register_t fid)
|
||||
{
|
||||
switch (fid) {
|
||||
case SMCCC_ARCH_SOC_ID:
|
||||
return SMC_ARCH_CALL_SUCCESS;
|
||||
default:
|
||||
return SMC_ARCH_CALL_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t plat_get_soc_version(void)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
ret = SOC_ID_SET_JEP_106(JEDEC_ALLWINNER_BKID, JEDEC_ALLWINNER_MFID);
|
||||
|
||||
return ret | (sunxi_read_soc_id() & SOC_ID_IMPL_DEF_MASK);
|
||||
}
|
||||
|
||||
int32_t plat_get_soc_revision(void)
|
||||
{
|
||||
uint32_t reg = mmio_read_32(SRAM_VER_REG);
|
||||
|
||||
return reg & GENMASK_32(7, 0);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, 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/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core)
|
||||
{
|
||||
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
|
||||
return;
|
||||
|
||||
VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
|
||||
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
|
||||
}
|
||||
|
||||
static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core)
|
||||
{
|
||||
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
|
||||
return;
|
||||
|
||||
VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
|
||||
|
||||
/* Power enable sequence from original Allwinner sources */
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8);
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0);
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80);
|
||||
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* We can't turn ourself off like this, but it works for other cores. */
|
||||
static void sunxi_cpu_off(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
|
||||
VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
|
||||
|
||||
/* Deassert DBGPWRDUP */
|
||||
mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
||||
/* Activate the core output clamps, but not for core 0. */
|
||||
if (core != 0)
|
||||
mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
|
||||
/* Assert CPU power-on reset */
|
||||
mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
||||
/* Remove power from the CPU */
|
||||
sunxi_cpu_disable_power(cluster, core);
|
||||
}
|
||||
|
||||
void sunxi_cpu_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
|
||||
VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
|
||||
|
||||
/* Assert CPU core reset */
|
||||
mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
||||
/* Assert CPU power-on reset */
|
||||
mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
||||
/* Set CPU to start in AArch64 mode */
|
||||
mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster),
|
||||
BIT(SUNXI_AA64nAA32_OFFSET + core));
|
||||
/* Apply power to the CPU */
|
||||
sunxi_cpu_enable_power(cluster, core);
|
||||
/* Release the core output clamps */
|
||||
mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core));
|
||||
/* Deassert CPU power-on reset */
|
||||
mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core));
|
||||
/* Deassert CPU core reset */
|
||||
mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
|
||||
/* Assert DBGPWRDUP */
|
||||
mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
|
||||
}
|
||||
|
||||
void sunxi_cpu_power_off_others(void)
|
||||
{
|
||||
u_register_t self = read_mpidr();
|
||||
unsigned int cluster;
|
||||
unsigned int core;
|
||||
|
||||
for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) {
|
||||
for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) {
|
||||
u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) |
|
||||
(core << MPIDR_AFF0_SHIFT) |
|
||||
BIT(31);
|
||||
if (mpidr != self)
|
||||
sunxi_cpu_off(mpidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
#define SUNXI_WDOG0_CTRL_REG (SUNXI_R_WDOG_BASE + 0x0010)
|
||||
#define SUNXI_WDOG0_CFG_REG (SUNXI_R_WDOG_BASE + 0x0014)
|
||||
#define SUNXI_WDOG0_MODE_REG (SUNXI_R_WDOG_BASE + 0x0018)
|
||||
|
||||
static int sunxi_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
sunxi_cpu_on(mpidr);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
sunxi_cpu_power_off_self();
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
static void __dead2 sunxi_system_off(void)
|
||||
{
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* Attempt to power down the board (may not return) */
|
||||
sunxi_power_down();
|
||||
|
||||
/* Turn off all CPUs */
|
||||
sunxi_cpu_power_off_others();
|
||||
sunxi_cpu_power_off_self();
|
||||
psci_power_down_wfi();
|
||||
}
|
||||
|
||||
static void __dead2 sunxi_system_reset(void)
|
||||
{
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* Reset the whole system when the watchdog times out */
|
||||
mmio_write_32(SUNXI_WDOG0_CFG_REG, 1);
|
||||
/* Enable the watchdog with the shortest timeout (0.5 seconds) */
|
||||
mmio_write_32(SUNXI_WDOG0_MODE_REG, (0 << 4) | 1);
|
||||
/* Wait for twice the watchdog timeout before panicking */
|
||||
mdelay(1000);
|
||||
|
||||
ERROR("PSCI: System reset failed\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static const plat_psci_ops_t sunxi_native_psci_ops = {
|
||||
.pwr_domain_on = sunxi_pwr_domain_on,
|
||||
.pwr_domain_off = sunxi_pwr_domain_off,
|
||||
.pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
|
||||
.system_off = sunxi_system_off,
|
||||
.system_reset = sunxi_system_reset,
|
||||
.validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
|
||||
};
|
||||
|
||||
void sunxi_set_native_psci_ops(const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
*psci_ops = &sunxi_native_psci_ops;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
static bool psci_is_scpi;
|
||||
|
||||
#if SUNXI_PSCI_USE_SCPI
|
||||
bool sunxi_psci_is_scpi(void)
|
||||
{
|
||||
return psci_is_scpi;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
|
||||
{
|
||||
/* The non-secure entry point must be in DRAM */
|
||||
if (ns_entrypoint < SUNXI_DRAM_BASE) {
|
||||
return PSCI_E_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
assert(psci_ops);
|
||||
|
||||
/* Program all CPU entry points. */
|
||||
for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; ++cpu) {
|
||||
mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
|
||||
sec_entrypoint & 0xffffffff);
|
||||
mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
|
||||
sec_entrypoint >> 32);
|
||||
}
|
||||
|
||||
if (sunxi_set_scpi_psci_ops(psci_ops) == 0) {
|
||||
INFO("PSCI: Suspend is available via SCPI\n");
|
||||
psci_is_scpi = true;
|
||||
} else {
|
||||
INFO("PSCI: Suspend is unavailable\n");
|
||||
sunxi_set_native_psci_ops(psci_ops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
|
||||
#include <sunxi_private.h>
|
||||
|
||||
void sunxi_prepare_dtb(void *fdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fdt == NULL || fdt_check_header(fdt) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = fdt_open_into(fdt, fdt, 0x10000);
|
||||
if (ret < 0) {
|
||||
ERROR("Preparing devicetree at %p: error %d\n", fdt, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SUNXI_BL31_IN_DRAM
|
||||
/* Reserve memory used by Trusted Firmware. */
|
||||
if (fdt_add_reserved_memory(fdt, "tf-a@40000000", BL31_BASE,
|
||||
BL31_LIMIT - BL31_BASE)) {
|
||||
WARN("Failed to add reserved memory nodes to DT.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sunxi_psci_is_scpi()) {
|
||||
ret = fdt_add_cpu_idle_states(fdt, sunxi_idle_states);
|
||||
if (ret < 0) {
|
||||
WARN("Failed to add idle states to DT: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
ret = fdt_pack(fdt);
|
||||
if (ret < 0) {
|
||||
ERROR("Failed to pack devicetree at %p: error %d\n",
|
||||
fdt, ret);
|
||||
}
|
||||
|
||||
clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
|
||||
INFO("Changed devicetree.\n");
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, 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/debug.h>
|
||||
#include <drivers/arm/css/css_scpi.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
/*
|
||||
* The addresses for the SCP exception vectors are defined in the or1k
|
||||
* architecture specification.
|
||||
*/
|
||||
#define OR1K_VEC_FIRST 0x01
|
||||
#define OR1K_VEC_LAST 0x0e
|
||||
#define OR1K_VEC_ADDR(n) (0x100 * (n))
|
||||
|
||||
/*
|
||||
* This magic value is the little-endian representation of the or1k
|
||||
* instruction "l.mfspr r2, r0, 0x12", which is guaranteed to be the
|
||||
* first instruction in the SCP firmware.
|
||||
*/
|
||||
#define SCP_FIRMWARE_MAGIC 0xb4400012
|
||||
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
#define CPU_PWR_LVL MPIDR_AFFLVL0
|
||||
#define CLUSTER_PWR_LVL MPIDR_AFFLVL1
|
||||
#define SYSTEM_PWR_LVL MPIDR_AFFLVL2
|
||||
|
||||
#define CPU_PWR_STATE(state) \
|
||||
((state)->pwr_domain_state[CPU_PWR_LVL])
|
||||
#define CLUSTER_PWR_STATE(state) \
|
||||
((state)->pwr_domain_state[CLUSTER_PWR_LVL])
|
||||
#define SYSTEM_PWR_STATE(state) \
|
||||
((state)->pwr_domain_state[SYSTEM_PWR_LVL])
|
||||
|
||||
static void sunxi_cpu_standby(plat_local_state_t cpu_state)
|
||||
{
|
||||
u_register_t scr = read_scr_el3();
|
||||
|
||||
assert(is_local_state_retn(cpu_state));
|
||||
|
||||
write_scr_el3(scr | SCR_IRQ_BIT);
|
||||
wfi();
|
||||
write_scr_el3(scr);
|
||||
}
|
||||
|
||||
static int sunxi_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
scpi_set_css_power_state(mpidr,
|
||||
scpi_power_on,
|
||||
scpi_power_on,
|
||||
scpi_power_on);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
plat_local_state_t cpu_pwr_state = CPU_PWR_STATE(target_state);
|
||||
plat_local_state_t cluster_pwr_state = CLUSTER_PWR_STATE(target_state);
|
||||
plat_local_state_t system_pwr_state = SYSTEM_PWR_STATE(target_state);
|
||||
|
||||
if (is_local_state_off(cpu_pwr_state)) {
|
||||
gicv2_cpuif_disable();
|
||||
}
|
||||
|
||||
scpi_set_css_power_state(read_mpidr(),
|
||||
cpu_pwr_state,
|
||||
cluster_pwr_state,
|
||||
system_pwr_state);
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
|
||||
gicv2_distif_init();
|
||||
}
|
||||
if (is_local_state_off(CPU_PWR_STATE(target_state))) {
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void __dead2 sunxi_system_off(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* Send the power down request to the SCP. */
|
||||
ret = scpi_sys_power_state(scpi_system_shutdown);
|
||||
if (ret != SCP_OK) {
|
||||
ERROR("PSCI: SCPI %s failed: %d\n", "shutdown", ret);
|
||||
}
|
||||
|
||||
psci_power_down_wfi();
|
||||
}
|
||||
|
||||
static void __dead2 sunxi_system_reset(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* Send the system reset request to the SCP. */
|
||||
ret = scpi_sys_power_state(scpi_system_reboot);
|
||||
if (ret != SCP_OK) {
|
||||
ERROR("PSCI: SCPI %s failed: %d\n", "reboot", ret);
|
||||
}
|
||||
|
||||
psci_power_down_wfi();
|
||||
}
|
||||
|
||||
static int sunxi_validate_power_state(unsigned int power_state,
|
||||
psci_power_state_t *req_state)
|
||||
{
|
||||
unsigned int power_level = psci_get_pstate_pwrlvl(power_state);
|
||||
unsigned int state_id = psci_get_pstate_id(power_state);
|
||||
unsigned int type = psci_get_pstate_type(power_state);
|
||||
unsigned int i;
|
||||
|
||||
assert(req_state != NULL);
|
||||
|
||||
if (power_level > PLAT_MAX_PWR_LVL) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
if (type == PSTATE_TYPE_STANDBY) {
|
||||
return PSCI_E_INVALID_PARAMS;
|
||||
}
|
||||
|
||||
/* Pass through the requested PSCI state as-is. */
|
||||
for (i = 0; i <= power_level; ++i) {
|
||||
unsigned int local_pstate = state_id & PLAT_LOCAL_PSTATE_MASK;
|
||||
|
||||
req_state->pwr_domain_state[i] = local_pstate;
|
||||
state_id >>= PLAT_LOCAL_PSTATE_WIDTH;
|
||||
}
|
||||
|
||||
/* Higher power domain levels should all remain running */
|
||||
for (; i <= PLAT_MAX_PWR_LVL; ++i) {
|
||||
req_state->pwr_domain_state[i] = PSCI_LOCAL_STATE_RUN;
|
||||
}
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void sunxi_get_sys_suspend_power_state(psci_power_state_t *req_state)
|
||||
{
|
||||
assert(req_state != NULL);
|
||||
|
||||
for (unsigned int i = 0; i <= PLAT_MAX_PWR_LVL; ++i) {
|
||||
req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
static const plat_psci_ops_t sunxi_scpi_psci_ops = {
|
||||
.cpu_standby = sunxi_cpu_standby,
|
||||
.pwr_domain_on = sunxi_pwr_domain_on,
|
||||
.pwr_domain_off = sunxi_pwr_domain_off,
|
||||
.pwr_domain_suspend = sunxi_pwr_domain_off,
|
||||
.pwr_domain_on_finish = sunxi_pwr_domain_on_finish,
|
||||
.pwr_domain_suspend_finish = sunxi_pwr_domain_on_finish,
|
||||
.system_off = sunxi_system_off,
|
||||
.system_reset = sunxi_system_reset,
|
||||
.validate_power_state = sunxi_validate_power_state,
|
||||
.validate_ns_entrypoint = sunxi_validate_ns_entrypoint,
|
||||
.get_sys_suspend_power_state = sunxi_get_sys_suspend_power_state,
|
||||
};
|
||||
|
||||
int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
*psci_ops = &sunxi_scpi_psci_ops;
|
||||
|
||||
/* Check for a valid SCP firmware. */
|
||||
if (mmio_read_32(SUNXI_SCP_BASE) != SCP_FIRMWARE_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Program SCP exception vectors to the firmware entrypoint. */
|
||||
for (unsigned int i = OR1K_VEC_FIRST; i <= OR1K_VEC_LAST; ++i) {
|
||||
uint32_t vector = SUNXI_SRAM_A2_BASE + OR1K_VEC_ADDR(i);
|
||||
uint32_t offset = SUNXI_SCP_BASE - vector;
|
||||
|
||||
mmio_write_32(vector, offset >> 2);
|
||||
}
|
||||
|
||||
/* Take the SCP out of reset. */
|
||||
mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
|
||||
|
||||
/* Wait for the SCP firmware to boot. */
|
||||
return scpi_wait_ready();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sunxi_ccu.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
#include <sunxi_spc.h>
|
||||
|
||||
#define DMA_SEC_REG 0x20
|
||||
|
||||
/*
|
||||
* Setup the peripherals to be accessible by non-secure world.
|
||||
* This will not work for the Secure Peripherals Controller (SPC) unless
|
||||
* a fuse it burnt (seems to be an erratum), but we do it nevertheless,
|
||||
* to allow booting on boards using secure boot.
|
||||
*/
|
||||
void sunxi_security_setup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
INFO("Configuring SPC Controller\n");
|
||||
/* SPC setup: set all devices to non-secure */
|
||||
for (i = 0; i < SUNXI_SPC_NUM_PORTS; i++)
|
||||
mmio_write_32(SUNXI_SPC_DECPORT_SET_REG(i), 0xffffffff);
|
||||
|
||||
/* set MBUS clocks, bus clocks (AXI/AHB/APB) and PLLs to non-secure */
|
||||
mmio_write_32(SUNXI_CCU_SEC_SWITCH_REG, 0x7);
|
||||
|
||||
/* Set R_PRCM bus clocks to non-secure */
|
||||
mmio_write_32(SUNXI_R_PRCM_SEC_SWITCH_REG, 0x1);
|
||||
|
||||
/* Set all DMA channels (16 max.) to non-secure */
|
||||
mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <arch.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
static const unsigned char plat_power_domain_tree_desc[PLAT_MAX_PWR_LVL + 1] = {
|
||||
/* One root node for the SoC */
|
||||
1,
|
||||
/* One node for each cluster */
|
||||
PLATFORM_CLUSTER_COUNT,
|
||||
/* One set of CPUs per cluster */
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER,
|
||||
};
|
||||
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
|
||||
if (MPIDR_AFFLVL3_VAL(mpidr) > 0 ||
|
||||
MPIDR_AFFLVL2_VAL(mpidr) > 0 ||
|
||||
cluster >= PLATFORM_CLUSTER_COUNT ||
|
||||
core >= PLATFORM_MAX_CPUS_PER_CLUSTER) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return cluster * PLATFORM_MAX_CPUS_PER_CLUSTER + core;
|
||||
}
|
||||
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return plat_power_domain_tree_desc;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
static uint32_t arisc_core_off[] = {
|
||||
0x18600000, /* l.movhi r3, <corenr> */
|
||||
0x18000000, /* l.movhi r0, 0x0 */
|
||||
0x19a00170, /* l.movhi r13, 0x170 */
|
||||
0x84ad0030, /* l.lwz r5, 0x30(r13) */
|
||||
0xe0a51803, /* l.and r5, r5, r3 */
|
||||
0xe4050000, /* l.sfeq r5, r0 */
|
||||
0x13fffffd, /* l.bf -12 */
|
||||
|
||||
0xb8c30050, /* l.srli r6, r3, 16 */
|
||||
0xbc060001, /* l.sfeqi r6, 1 */
|
||||
0x10000005, /* l.bf +20 */
|
||||
0x19a001f0, /* l.movhi r13, 0x1f0 */
|
||||
0x84ad1500, /* l.lwz r5, 0x1500(r13) */
|
||||
0xe0a53004, /* l.or r5, r5, r6 */
|
||||
0xd44d2d00, /* l.sw 0x1500(r13), r5 */
|
||||
|
||||
0x84ad1c30, /* l.lwz r5, 0x1c30(r13) */
|
||||
0xacc6ffff, /* l.xori r6, r6, -1 */
|
||||
0xe0a53003, /* l.and r5, r5, r6 */
|
||||
0xd46d2c30, /* l.sw 0x1c30(r13), r5 */
|
||||
|
||||
0xe0c3000f, /* l.ff1 r6, r3 */
|
||||
0x9cc6ffef, /* l.addi r6, r6, -17 */
|
||||
0xb8c60002, /* l.slli r6, r6, 2 */
|
||||
0xe0c66800, /* l.add r6, r6, r13 */
|
||||
0xa8a000ff, /* l.ori r5, r0, 0xff */
|
||||
0xd4462d40, /* l.sw 0x1540(r6), r5 */
|
||||
|
||||
0xd46d0400, /* l.sw 0x1c00(r13), r0 */
|
||||
0x03ffffff, /* l.j -1 */
|
||||
0x15000000, /* l.nop */
|
||||
};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CCU_H
|
||||
#define SUNXI_CCU_H
|
||||
|
||||
#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x02f0)
|
||||
|
||||
#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x01d0)
|
||||
|
||||
#endif /* SUNXI_CCU_H */
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CPUCFG_H
|
||||
#define SUNXI_CPUCFG_H
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
/* c = cluster, n = core */
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 16)
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0004 + (c) * 16)
|
||||
#define SUNXI_CPUCFG_CACHE_CFG_REG0 (SUNXI_CPUCFG_BASE + 0x0008)
|
||||
#define SUNXI_CPUCFG_CACHE_CFG_REG1 (SUNXI_CPUCFG_BASE + 0x000c)
|
||||
#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x0020)
|
||||
#define SUNXI_CPUCFG_GLB_CTRL_REG (SUNXI_CPUCFG_BASE + 0x0028)
|
||||
#define SUNXI_CPUCFG_CPU_STS_REG(c) (SUNXI_CPUCFG_BASE + 0x0030 + (c) * 4)
|
||||
#define SUNXI_CPUCFG_L2_STS_REG (SUNXI_CPUCFG_BASE + 0x003c)
|
||||
#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0080 + (c) * 4)
|
||||
#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x00a0 + (n) * 8)
|
||||
#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x00a4 + (n) * 8)
|
||||
|
||||
#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_PRCM_BASE + 0x0140 + \
|
||||
(c) * 16 + (n) * 4)
|
||||
#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_PRCM_BASE + 0x0100 + (c) * 4)
|
||||
#define SUNXI_R_CPUCFG_CPUS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0000)
|
||||
#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0030 + (c) * 4)
|
||||
#define SUNXI_R_CPUCFG_SYS_RST_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
|
||||
#define SUNXI_R_CPUCFG_SS_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01a0)
|
||||
#define SUNXI_R_CPUCFG_CPU_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a4)
|
||||
#define SUNXI_R_CPUCFG_SS_ENTRY_REG (SUNXI_R_CPUCFG_BASE + 0x01a8)
|
||||
#define SUNXI_R_CPUCFG_HP_FLAG_REG (SUNXI_R_CPUCFG_BASE + 0x01ac)
|
||||
|
||||
#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
|
||||
#define SUNXI_AA64nAA32_OFFSET 24
|
||||
|
||||
#endif /* SUNXI_CPUCFG_H */
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_MMAP_H
|
||||
#define SUNXI_MMAP_H
|
||||
|
||||
/* Memory regions */
|
||||
#define SUNXI_ROM_BASE 0x00000000
|
||||
#define SUNXI_ROM_SIZE 0x00010000
|
||||
#define SUNXI_SRAM_BASE 0x00010000
|
||||
#define SUNXI_SRAM_SIZE 0x00044000
|
||||
#define SUNXI_SRAM_A1_BASE 0x00010000
|
||||
#define SUNXI_SRAM_A1_SIZE 0x00008000
|
||||
#define SUNXI_SRAM_A2_BASE 0x00040000
|
||||
#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
|
||||
#define SUNXI_SRAM_A2_SIZE 0x00014000
|
||||
#define SUNXI_SRAM_C_BASE 0x00018000
|
||||
#define SUNXI_SRAM_C_SIZE 0x0001c000
|
||||
#define SUNXI_DEV_BASE 0x01000000
|
||||
#define SUNXI_DEV_SIZE 0x01000000
|
||||
#define SUNXI_DRAM_BASE 0x40000000
|
||||
#define SUNXI_DRAM_VIRT_BASE 0x02000000
|
||||
|
||||
/* Memory-mapped devices */
|
||||
#define SUNXI_CPU_MBIST_BASE 0x01502000
|
||||
#define SUNXI_CPUCFG_BASE 0x01700000
|
||||
#define SUNXI_SYSCON_BASE 0x01c00000
|
||||
#define SUNXI_DMA_BASE 0x01c02000
|
||||
#define SUNXI_KEYMEM_BASE 0x01c0b000
|
||||
#define SUNXI_SMHC0_BASE 0x01c0f000
|
||||
#define SUNXI_SMHC1_BASE 0x01c10000
|
||||
#define SUNXI_SMHC2_BASE 0x01c11000
|
||||
#define SUNXI_SID_BASE 0x01c14000
|
||||
#define SUNXI_MSGBOX_BASE 0x01c17000
|
||||
#define SUNXI_SPINLOCK_BASE 0x01c18000
|
||||
#define SUNXI_CCU_BASE 0x01c20000
|
||||
#define SUNXI_PIO_BASE 0x01c20800
|
||||
#define SUNXI_TIMER_BASE 0x01c20c00
|
||||
#define SUNXI_WDOG_BASE 0x01c20ca0
|
||||
#define SUNXI_SPC_BASE 0x01c23400
|
||||
#define SUNXI_THS_BASE 0x01c25000
|
||||
#define SUNXI_UART0_BASE 0x01c28000
|
||||
#define SUNXI_UART1_BASE 0x01c28400
|
||||
#define SUNXI_UART2_BASE 0x01c28800
|
||||
#define SUNXI_UART3_BASE 0x01c28c00
|
||||
#define SUNXI_I2C0_BASE 0x01c2ac00
|
||||
#define SUNXI_I2C1_BASE 0x01c2b000
|
||||
#define SUNXI_I2C2_BASE 0x01c2b400
|
||||
#define SUNXI_DRAMCOM_BASE 0x01c62000
|
||||
#define SUNXI_DRAMCTL_BASE 0x01c63000
|
||||
#define SUNXI_DRAMPHY_BASE 0x01c65000
|
||||
#define SUNXI_SPI0_BASE 0x01c68000
|
||||
#define SUNXI_SPI1_BASE 0x01c69000
|
||||
#define SUNXI_SCU_BASE 0x01c80000
|
||||
#define SUNXI_GICD_BASE 0x01c81000
|
||||
#define SUNXI_GICC_BASE 0x01c82000
|
||||
#define SUNXI_RTC_BASE 0x01f00000
|
||||
#define SUNXI_R_TIMER_BASE 0x01f00800
|
||||
#define SUNXI_R_INTC_BASE 0x01f00c00
|
||||
#define SUNXI_R_WDOG_BASE 0x01f01000
|
||||
#define SUNXI_R_PRCM_BASE 0x01f01400
|
||||
#define SUNXI_R_TWD_BASE 0x01f01800
|
||||
#define SUNXI_R_CPUCFG_BASE 0x01f01c00
|
||||
#define SUNXI_R_CIR_BASE 0x01f02000
|
||||
#define SUNXI_R_I2C_BASE 0x01f02400
|
||||
#define SUNXI_R_UART_BASE 0x01f02800
|
||||
#define SUNXI_R_PIO_BASE 0x01f02c00
|
||||
#define SUNXI_R_RSB_BASE 0x01f03400
|
||||
#define SUNXI_R_PWM_BASE 0x01f03800
|
||||
|
||||
#endif /* SUNXI_MMAP_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_SPC_H
|
||||
#define SUNXI_SPC_H
|
||||
|
||||
#define SUNXI_SPC_NUM_PORTS 6
|
||||
|
||||
#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x0c * (p))
|
||||
#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x0c * (p))
|
||||
#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x000c + 0x0c * (p))
|
||||
|
||||
#endif /* SUNXI_SPC_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# The differences between the platform are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/axp803.c \
|
||||
drivers/allwinner/sunxi_rsb.c
|
||||
|
||||
FDT_ASSUME_MASK := "(ASSUME_LATEST | ASSUME_NO_ROLLBACK | ASSUME_LIBFDT_ORDER)"
|
||||
$(eval $(call add_define,FDT_ASSUME_MASK))
|
||||
|
||||
# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL.
|
||||
SEPARATE_NOBITS_REGION := 1
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sunxi_private.h>
|
||||
|
||||
const struct psci_cpu_idle_state sunxi_idle_states[] = {
|
||||
{
|
||||
.name = "cpu-sleep",
|
||||
.power_state = 0x00010003,
|
||||
.local_timer_stop = true,
|
||||
.entry_latency_us = 800,
|
||||
.exit_latency_us = 1500,
|
||||
.min_residency_us = 25000
|
||||
},
|
||||
{
|
||||
.name = "cluster-sleep",
|
||||
.power_state = 0x01010013,
|
||||
.local_timer_stop = true,
|
||||
.entry_latency_us = 850,
|
||||
.exit_latency_us = 1500,
|
||||
.min_residency_us = 50000
|
||||
},
|
||||
{}
|
||||
};
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/allwinner/axp.h>
|
||||
#include <drivers/allwinner/sunxi_rsb.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <core_off_arisc.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
static enum pmic_type {
|
||||
UNKNOWN,
|
||||
GENERIC_H5,
|
||||
GENERIC_A64,
|
||||
REF_DESIGN_H5, /* regulators controlled by GPIO pins on port L */
|
||||
AXP803_RSB, /* PMIC connected via RSB on most A64 boards */
|
||||
} pmic;
|
||||
|
||||
#define AXP803_HW_ADDR 0x3a3
|
||||
#define AXP803_RT_ADDR 0x2d
|
||||
|
||||
/*
|
||||
* On boards without a proper PMIC we struggle to turn off the system properly.
|
||||
* Try to turn off as much off the system as we can, to reduce power
|
||||
* consumption. This should be entered with only one core running and SMP
|
||||
* disabled.
|
||||
* This function only cares about peripherals.
|
||||
*/
|
||||
static void sunxi_turn_off_soc(uint16_t socid)
|
||||
{
|
||||
int i;
|
||||
|
||||
/** Turn off most peripherals, most importantly DRAM users. **/
|
||||
/* Keep DRAM controller running for now. */
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
|
||||
/* Contains msgbox (bit 21) and spinlock (bit 22) */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
|
||||
/* Keep PIO controller running for now. */
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
|
||||
/* Contains UART0 (bit 16) */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
|
||||
|
||||
/** Turn off DRAM controller. **/
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
|
||||
|
||||
/** Migrate CPU and bus clocks away from the PLLs. **/
|
||||
/* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
|
||||
/* APB2: use OSC24M */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
|
||||
/* AHB2: use AHB1 clock */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
|
||||
/* CPU: use OSC24M */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
|
||||
|
||||
/** Turn off PLLs. **/
|
||||
for (i = 0; i < 6; i++)
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
|
||||
switch (socid) {
|
||||
case SUNXI_SOC_H5:
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
|
||||
break;
|
||||
case SUNXI_SOC_A64:
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
|
||||
mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int rsb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rsb_init_controller();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch to the recommended 3 MHz bus clock. */
|
||||
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
|
||||
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Associate the 8-bit runtime address with the 12-bit bus address. */
|
||||
ret = rsb_assign_runtime_address(AXP803_HW_ADDR,
|
||||
AXP803_RT_ADDR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return axp_check_id();
|
||||
}
|
||||
|
||||
int axp_read(uint8_t reg)
|
||||
{
|
||||
return rsb_read(AXP803_RT_ADDR, reg);
|
||||
}
|
||||
|
||||
int axp_write(uint8_t reg, uint8_t val)
|
||||
{
|
||||
return rsb_write(AXP803_RT_ADDR, reg, val);
|
||||
}
|
||||
|
||||
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (socid) {
|
||||
case SUNXI_SOC_H5:
|
||||
NOTICE("PMIC: Assuming H5 reference regulator design\n");
|
||||
|
||||
pmic = REF_DESIGN_H5;
|
||||
|
||||
break;
|
||||
case SUNXI_SOC_A64:
|
||||
pmic = GENERIC_A64;
|
||||
|
||||
INFO("PMIC: Probing AXP803 on RSB\n");
|
||||
|
||||
ret = sunxi_init_platform_r_twi(socid, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rsb_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmic = AXP803_RSB;
|
||||
axp_setup_regulators(fdt);
|
||||
|
||||
/* Switch the PMIC back to I2C mode. */
|
||||
ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sunxi_power_down(void)
|
||||
{
|
||||
switch (pmic) {
|
||||
case GENERIC_H5:
|
||||
/* Turn off as many peripherals and clocks as we can. */
|
||||
sunxi_turn_off_soc(SUNXI_SOC_H5);
|
||||
/* Turn off the pin controller now. */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
|
||||
break;
|
||||
case GENERIC_A64:
|
||||
/* Turn off as many peripherals and clocks as we can. */
|
||||
sunxi_turn_off_soc(SUNXI_SOC_A64);
|
||||
/* Turn off the pin controller now. */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
|
||||
break;
|
||||
case REF_DESIGN_H5:
|
||||
sunxi_turn_off_soc(SUNXI_SOC_H5);
|
||||
|
||||
/*
|
||||
* Switch PL pins to power off the board:
|
||||
* - PL5 (VCC_IO) -> high
|
||||
* - PL8 (PWR-STB = CPU power supply) -> low
|
||||
* - PL9 (PWR-DRAM) ->low
|
||||
* - PL10 (power LED) -> low
|
||||
* Note: Clearing PL8 will reset the board, so keep it up.
|
||||
*/
|
||||
sunxi_set_gpio_out('L', 5, 1);
|
||||
sunxi_set_gpio_out('L', 9, 0);
|
||||
sunxi_set_gpio_out('L', 10, 0);
|
||||
|
||||
/* Turn off pin controller now. */
|
||||
mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
|
||||
|
||||
break;
|
||||
case AXP803_RSB:
|
||||
/* (Re-)init RSB in case the rich OS has disabled it. */
|
||||
sunxi_init_platform_r_twi(SUNXI_SOC_A64, true);
|
||||
rsb_init();
|
||||
axp_power_off();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* This lock synchronises access to the arisc management processor. */
|
||||
static DEFINE_BAKERY_LOCK(arisc_lock);
|
||||
|
||||
/*
|
||||
* If we are supposed to turn ourself off, tell the arisc SCP to do that
|
||||
* work for us. Without any SCPI provider running there, we place some
|
||||
* OpenRISC code into SRAM, put the address of that into the reset vector
|
||||
* and release the arisc reset line. The SCP will wait for the core to enter
|
||||
* WFI, then execute that code and pull the line up again.
|
||||
* The code expects the core mask to be patched into the first instruction.
|
||||
*/
|
||||
void sunxi_cpu_power_off_self(void)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr();
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100;
|
||||
uint32_t *code = arisc_core_off;
|
||||
|
||||
do {
|
||||
bakery_lock_get(&arisc_lock);
|
||||
/* Wait until the arisc is in reset state. */
|
||||
if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0)))
|
||||
break;
|
||||
|
||||
bakery_lock_release(&arisc_lock);
|
||||
} while (1);
|
||||
|
||||
/* Patch up the code to feed in an input parameter. */
|
||||
code[0] = (code[0] & ~0xffff) | BIT_32(core);
|
||||
clean_dcache_range((uintptr_t)code, sizeof(arisc_core_off));
|
||||
|
||||
/*
|
||||
* The OpenRISC unconditional branch has opcode 0, the branch offset
|
||||
* is in the lower 26 bits, containing the distance to the target,
|
||||
* in instruction granularity (32 bits).
|
||||
*/
|
||||
mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4);
|
||||
|
||||
/* De-assert the arisc reset line to let it run. */
|
||||
mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
|
||||
|
||||
/*
|
||||
* We release the lock here, although the arisc is still busy.
|
||||
* But as long as it runs, the reset line is high, so other users
|
||||
* won't leave the loop above.
|
||||
* Once it has finished, the code is supposed to clear the reset line,
|
||||
* to signal this to other users.
|
||||
*/
|
||||
bakery_lock_release(&arisc_lock);
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CCU_H
|
||||
#define SUNXI_CCU_H
|
||||
|
||||
#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
|
||||
|
||||
#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
|
||||
|
||||
#endif /* SUNXI_CCU_H */
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CPUCFG_H
|
||||
#define SUNXI_CPUCFG_H
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
/* c = cluster, n = core */
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
|
||||
#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
|
||||
#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
|
||||
|
||||
#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
|
||||
#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
|
||||
#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
|
||||
|
||||
#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
|
||||
#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
|
||||
#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
|
||||
(c) * 0x10 + (n) * 4)
|
||||
|
||||
#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100)
|
||||
#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104)
|
||||
#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
|
||||
#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
|
||||
|
||||
#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
|
||||
#define SUNXI_AA64nAA32_OFFSET 24
|
||||
|
||||
#endif /* SUNXI_CPUCFG_H */
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_MMAP_H
|
||||
#define SUNXI_MMAP_H
|
||||
|
||||
/* Memory regions */
|
||||
#define SUNXI_ROM_BASE 0x00000000
|
||||
#define SUNXI_ROM_SIZE 0x00010000
|
||||
#define SUNXI_SRAM_BASE 0x00020000
|
||||
#define SUNXI_SRAM_SIZE 0x000f8000
|
||||
#define SUNXI_SRAM_A1_BASE 0x00020000
|
||||
#define SUNXI_SRAM_A1_SIZE 0x00008000
|
||||
#define SUNXI_SRAM_A2_BASE 0x00100000
|
||||
#define SUNXI_SRAM_A2_BL31_OFFSET 0x00004000
|
||||
#define SUNXI_SRAM_A2_SIZE 0x00018000
|
||||
#define SUNXI_SRAM_C_BASE 0x00028000
|
||||
#define SUNXI_SRAM_C_SIZE 0x0001e000
|
||||
#define SUNXI_DEV_BASE 0x01000000
|
||||
#define SUNXI_DEV_SIZE 0x09000000
|
||||
#define SUNXI_DRAM_BASE 0x40000000
|
||||
#define SUNXI_DRAM_VIRT_BASE 0x0a000000
|
||||
|
||||
/* Memory-mapped devices */
|
||||
#define SUNXI_SYSCON_BASE 0x03000000
|
||||
#define SUNXI_CPUCFG_BASE 0x09010000
|
||||
#define SUNXI_SID_BASE 0x03006000
|
||||
#define SUNXI_DMA_BASE 0x03002000
|
||||
#define SUNXI_MSGBOX_BASE 0x03003000
|
||||
#define SUNXI_CCU_BASE 0x03001000
|
||||
#define SUNXI_PIO_BASE 0x0300b000
|
||||
#define SUNXI_SPC_BASE 0x03008000
|
||||
#define SUNXI_TIMER_BASE 0x03009000
|
||||
#define SUNXI_WDOG_BASE 0x030090a0
|
||||
#define SUNXI_THS_BASE 0x05070400
|
||||
#define SUNXI_UART0_BASE 0x05000000
|
||||
#define SUNXI_UART1_BASE 0x05000400
|
||||
#define SUNXI_UART2_BASE 0x05000800
|
||||
#define SUNXI_UART3_BASE 0x05000c00
|
||||
#define SUNXI_I2C0_BASE 0x05002000
|
||||
#define SUNXI_I2C1_BASE 0x05002400
|
||||
#define SUNXI_I2C2_BASE 0x05002800
|
||||
#define SUNXI_I2C3_BASE 0x05002c00
|
||||
#define SUNXI_SPI0_BASE 0x05010000
|
||||
#define SUNXI_SPI1_BASE 0x05011000
|
||||
#define SUNXI_SCU_BASE 0x03020000
|
||||
#define SUNXI_GICD_BASE 0x03021000
|
||||
#define SUNXI_GICC_BASE 0x03022000
|
||||
#define SUNXI_R_TIMER_BASE 0x07020000
|
||||
#define SUNXI_R_INTC_BASE 0x07021000
|
||||
#define SUNXI_R_WDOG_BASE 0x07020400
|
||||
#define SUNXI_R_PRCM_BASE 0x07010000
|
||||
#define SUNXI_R_TWD_BASE 0x07020800
|
||||
#define SUNXI_R_CPUCFG_BASE 0x07000400
|
||||
#define SUNXI_R_I2C_BASE 0x07081400
|
||||
#define SUNXI_R_RSB_BASE 0x07083000
|
||||
#define SUNXI_R_UART_BASE 0x07080000
|
||||
#define SUNXI_R_PIO_BASE 0x07022000
|
||||
|
||||
#endif /* SUNXI_MMAP_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_SPC_H
|
||||
#define SUNXI_SPC_H
|
||||
|
||||
#define SUNXI_SPC_NUM_PORTS 14
|
||||
|
||||
#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
|
||||
|
||||
#endif /* SUNXI_SPC_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# The differences between the platform are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/axp805.c \
|
||||
drivers/allwinner/sunxi_rsb.c
|
||||
|
||||
# Put NOBITS memory in SRAM A1, overwriting U-Boot's SPL.
|
||||
SEPARATE_NOBITS_REGION := 1
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sunxi_private.h>
|
||||
|
||||
const struct psci_cpu_idle_state sunxi_idle_states[] = {
|
||||
{}
|
||||
};
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/allwinner/axp.h>
|
||||
#include <drivers/allwinner/sunxi_rsb.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
#define AXP805_HW_ADDR 0x745
|
||||
#define AXP805_RT_ADDR 0x3a
|
||||
|
||||
static enum pmic_type {
|
||||
UNKNOWN,
|
||||
AXP805,
|
||||
} pmic;
|
||||
|
||||
int axp_read(uint8_t reg)
|
||||
{
|
||||
return rsb_read(AXP805_RT_ADDR, reg);
|
||||
}
|
||||
|
||||
int axp_write(uint8_t reg, uint8_t val)
|
||||
{
|
||||
return rsb_write(AXP805_RT_ADDR, reg, val);
|
||||
}
|
||||
|
||||
static int rsb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rsb_init_controller();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch to the recommended 3 MHz bus clock. */
|
||||
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
|
||||
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Associate the 8-bit runtime address with the 12-bit bus address. */
|
||||
ret = rsb_assign_runtime_address(AXP805_HW_ADDR, AXP805_RT_ADDR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return axp_check_id();
|
||||
}
|
||||
|
||||
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
INFO("PMIC: Probing AXP805 on RSB\n");
|
||||
|
||||
ret = sunxi_init_platform_r_twi(socid, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rsb_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch the AXP805 to master/single-PMIC mode. */
|
||||
ret = axp_write(0xff, 0x0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pmic = AXP805;
|
||||
axp_setup_regulators(fdt);
|
||||
|
||||
/* Switch the PMIC back to I2C mode. */
|
||||
ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sunxi_power_down(void)
|
||||
{
|
||||
switch (pmic) {
|
||||
case AXP805:
|
||||
/* (Re-)init RSB in case the rich OS has disabled it. */
|
||||
sunxi_init_platform_r_twi(SUNXI_SOC_H6, true);
|
||||
rsb_init();
|
||||
axp_power_off();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sunxi_cpu_power_off_self(void)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr();
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
|
||||
/* Enable the CPUIDLE hardware (only really needs to be done once). */
|
||||
mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
|
||||
mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
|
||||
|
||||
/* Trigger power off for this core. */
|
||||
mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CCU_H
|
||||
#define SUNXI_CCU_H
|
||||
|
||||
#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
|
||||
|
||||
#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
|
||||
|
||||
#endif /* SUNXI_CCU_H */
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CPUCFG_H
|
||||
#define SUNXI_CPUCFG_H
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
/* c = cluster, n = core */
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
|
||||
#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
|
||||
#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
|
||||
|
||||
#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
|
||||
#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
|
||||
#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
|
||||
|
||||
#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
|
||||
#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
|
||||
#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
|
||||
(c) * 0x10 + (n) * 4)
|
||||
|
||||
#define SUNXI_CPUIDLE_EN_REG (SUNXI_R_CPUCFG_BASE + 0x0100)
|
||||
#define SUNXI_CORE_CLOSE_REG (SUNXI_R_CPUCFG_BASE + 0x0104)
|
||||
#define SUNXI_PWR_SW_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0140)
|
||||
#define SUNXI_CONFIG_DELAY_REG (SUNXI_R_CPUCFG_BASE + 0x0144)
|
||||
|
||||
#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_CLS_CTRL_REG0
|
||||
#define SUNXI_AA64nAA32_OFFSET 24
|
||||
|
||||
#endif /* SUNXI_CPUCFG_H */
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_MMAP_H
|
||||
#define SUNXI_MMAP_H
|
||||
|
||||
/* Memory regions */
|
||||
#define SUNXI_ROM_BASE 0x00000000
|
||||
#define SUNXI_ROM_SIZE 0x00010000
|
||||
#define SUNXI_SRAM_BASE 0x00020000
|
||||
#define SUNXI_SRAM_SIZE 0x00038000
|
||||
#define SUNXI_SRAM_A1_BASE 0x00020000
|
||||
#define SUNXI_SRAM_A1_SIZE 0x00008000
|
||||
#define SUNXI_SRAM_C_BASE 0x00028000
|
||||
#define SUNXI_SRAM_C_SIZE 0x00030000
|
||||
#define SUNXI_DEV_BASE 0x01000000
|
||||
#define SUNXI_DEV_SIZE 0x09000000
|
||||
#define SUNXI_DRAM_BASE 0x40000000
|
||||
#define SUNXI_DRAM_VIRT_BASE SUNXI_DRAM_BASE
|
||||
|
||||
/* Memory-mapped devices */
|
||||
#define SUNXI_SYSCON_BASE 0x03000000
|
||||
#define SUNXI_CCU_BASE 0x03001000
|
||||
#define SUNXI_DMA_BASE 0x03002000
|
||||
#define SUNXI_SID_BASE 0x03006000
|
||||
#define SUNXI_SPC_BASE 0x03008000
|
||||
#define SUNXI_WDOG_BASE 0x030090a0
|
||||
#define SUNXI_PIO_BASE 0x0300b000
|
||||
#define SUNXI_GICD_BASE 0x03021000
|
||||
#define SUNXI_GICC_BASE 0x03022000
|
||||
#define SUNXI_UART0_BASE 0x05000000
|
||||
#define SUNXI_SPI0_BASE 0x05010000
|
||||
#define SUNXI_R_CPUCFG_BASE 0x07000400
|
||||
#define SUNXI_R_PRCM_BASE 0x07010000
|
||||
//#define SUNXI_R_WDOG_BASE 0x07020400
|
||||
#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE
|
||||
#define SUNXI_R_PIO_BASE 0x07022000
|
||||
#define SUNXI_R_UART_BASE 0x07080000
|
||||
#define SUNXI_R_I2C_BASE 0x07081400
|
||||
#define SUNXI_R_RSB_BASE 0x07083000
|
||||
#define SUNXI_CPUCFG_BASE 0x09010000
|
||||
|
||||
#endif /* SUNXI_MMAP_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_SPC_H
|
||||
#define SUNXI_SPC_H
|
||||
|
||||
#define SUNXI_SPC_NUM_PORTS 14
|
||||
|
||||
#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
|
||||
|
||||
#endif /* SUNXI_SPC_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2017-2020, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
SUNXI_BL31_IN_DRAM := 1
|
||||
|
||||
# Without a management processor there is no SCPI support.
|
||||
SUNXI_PSCI_USE_SCPI := 0
|
||||
SUNXI_PSCI_USE_NATIVE := 1
|
||||
|
||||
# The differences between the platforms are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
|
||||
# the above could be overwritten on the command line
|
||||
ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
|
||||
$(error "H616 does not support SCPI PSCI ops")
|
||||
endif
|
||||
|
||||
BL31_SOURCES += drivers/allwinner/axp/axp805.c \
|
||||
drivers/allwinner/sunxi_rsb.c \
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sunxi_private.h>
|
||||
|
||||
const struct psci_cpu_idle_state sunxi_idle_states[] = {
|
||||
{}
|
||||
};
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2020, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/allwinner/axp.h>
|
||||
#include <drivers/allwinner/sunxi_rsb.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
#define AXP305_I2C_ADDR 0x36
|
||||
#define AXP305_HW_ADDR 0x745
|
||||
#define AXP305_RT_ADDR 0x3a
|
||||
|
||||
static enum pmic_type {
|
||||
UNKNOWN,
|
||||
AXP305,
|
||||
} pmic;
|
||||
|
||||
int axp_read(uint8_t reg)
|
||||
{
|
||||
return rsb_read(AXP305_RT_ADDR, reg);
|
||||
}
|
||||
|
||||
int axp_write(uint8_t reg, uint8_t val)
|
||||
{
|
||||
return rsb_write(AXP305_RT_ADDR, reg, val);
|
||||
}
|
||||
|
||||
static int rsb_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rsb_init_controller();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Switch to the recommended 3 MHz bus clock. */
|
||||
ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
|
||||
ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Associate the 8-bit runtime address with the 12-bit bus address. */
|
||||
ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return axp_check_id();
|
||||
}
|
||||
|
||||
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
INFO("PMIC: Probing AXP305 on RSB\n");
|
||||
|
||||
ret = sunxi_init_platform_r_twi(socid, true);
|
||||
if (ret) {
|
||||
INFO("Could not init platform bus: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rsb_init();
|
||||
if (ret) {
|
||||
INFO("Could not init RSB: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pmic = AXP305;
|
||||
axp_setup_regulators(fdt);
|
||||
|
||||
/* Switch the PMIC back to I2C mode. */
|
||||
ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sunxi_power_down(void)
|
||||
{
|
||||
switch (pmic) {
|
||||
case AXP305:
|
||||
/* Re-initialise after rich OS might have used it. */
|
||||
sunxi_init_platform_r_twi(SUNXI_SOC_H616, true);
|
||||
rsb_init();
|
||||
axp_power_off();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void sunxi_cpu_power_off_self(void)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr();
|
||||
unsigned int core = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
|
||||
/* Enable the CPUIDLE hardware (only really needs to be done once). */
|
||||
mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000);
|
||||
mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001);
|
||||
|
||||
/* Trigger power off for this core. */
|
||||
mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core));
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Sipeed
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CCU_H
|
||||
#define SUNXI_CCU_H
|
||||
|
||||
#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x0f00)
|
||||
|
||||
#define SUNXI_R_PRCM_SEC_SWITCH_REG (SUNXI_R_PRCM_BASE + 0x0290)
|
||||
|
||||
#endif /* SUNXI_CCU_H */
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Sipeed
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_CPUCFG_H
|
||||
#define SUNXI_CPUCFG_H
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
/* c = cluster, n = core */
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_C0_CPUXCFG_BASE + 0x0010)
|
||||
#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_C0_CPUXCFG_BASE + 0x0014)
|
||||
#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_C0_CPUXCFG_BASE + 0x0024)
|
||||
#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_C0_CPUXCFG_BASE + 0x00c0)
|
||||
|
||||
#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_C0_CPUXCFG_BASE + 0x0000)
|
||||
#define SUNXI_CPUCFG_GEN_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0000)
|
||||
#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
|
||||
#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
|
||||
|
||||
#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
|
||||
#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
|
||||
#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
|
||||
(c) * 0x10 + (n) * 4)
|
||||
|
||||
#define SUNXI_AA64nAA32_REG SUNXI_CPUCFG_GEN_CTRL_REG0
|
||||
#define SUNXI_AA64nAA32_OFFSET 4
|
||||
|
||||
#endif /* SUNXI_CPUCFG_H */
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_MMAP_H
|
||||
#define SUNXI_MMAP_H
|
||||
|
||||
/* Memory regions */
|
||||
#define SUNXI_ROM_BASE 0x00000000
|
||||
#define SUNXI_ROM_SIZE 0x00010000
|
||||
/*
|
||||
* In fact all SRAM from 0x100000 is SRAM A2. However as it's too big for
|
||||
* firmware, and the user manual gives a tip on a 2*64K/27*64K partition,
|
||||
* only use the first 2*64K for firmwares now, with the SPL using the first
|
||||
* 64K and BL3-1 using the second one.
|
||||
*
|
||||
* Only the used 2*64K SRAM is defined here, to prevent a gaint translation
|
||||
* table to be generated.
|
||||
*/
|
||||
#define SUNXI_SRAM_BASE 0x00100000
|
||||
#define SUNXI_SRAM_SIZE 0x00020000
|
||||
#define SUNXI_SRAM_A1_BASE 0x00100000
|
||||
#define SUNXI_SRAM_A1_SIZE 0x00010000
|
||||
#define SUNXI_SRAM_A2_BASE 0x00110000
|
||||
#define SUNXI_SRAM_A2_BL31_OFFSET 0x00000000
|
||||
#define SUNXI_SRAM_A2_SIZE 0x00010000
|
||||
#define SUNXI_DEV_BASE 0x01000000
|
||||
#define SUNXI_DEV_SIZE 0x09000000
|
||||
#define SUNXI_DRAM_BASE 0x40000000
|
||||
#define SUNXI_DRAM_VIRT_BASE 0x0a000000
|
||||
|
||||
/* Memory-mapped devices */
|
||||
#define SUNXI_WDOG_BASE 0x020000a0
|
||||
#define SUNXI_R_WDOG_BASE SUNXI_WDOG_BASE
|
||||
#define SUNXI_PIO_BASE 0x02000400
|
||||
#define SUNXI_SPC_BASE 0x02000800
|
||||
#define SUNXI_CCU_BASE 0x02001000
|
||||
#define SUNXI_UART0_BASE 0x02500000
|
||||
#define SUNXI_SYSCON_BASE 0x03000000
|
||||
#define SUNXI_DMA_BASE 0x03002000
|
||||
#define SUNXI_SID_BASE 0x03006000
|
||||
#define SUNXI_GICD_BASE 0x03021000
|
||||
#define SUNXI_GICC_BASE 0x03022000
|
||||
#define SUNXI_SPI0_BASE 0x04025000
|
||||
#define SUNXI_R_CPUCFG_BASE 0x07000400
|
||||
#define SUNXI_R_PRCM_BASE 0x07010000
|
||||
#define SUNXI_R_PIO_BASE 0x07022000
|
||||
#define SUNXI_R_UART_BASE 0x07080000
|
||||
#define SUNXI_R_I2C_BASE 0x07081400
|
||||
#define SUNXI_CPUCFG_BASE 0x08100000
|
||||
#define SUNXI_C0_CPUXCFG_BASE 0x09010000
|
||||
|
||||
#endif /* SUNXI_MMAP_H */
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Sipeed
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef SUNXI_SPC_H
|
||||
#define SUNXI_SPC_H
|
||||
|
||||
/* Get by REing stock ATF and checking initialization loop boundary */
|
||||
#define SUNXI_SPC_NUM_PORTS 11
|
||||
|
||||
#define SUNXI_SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + 0x0000 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + 0x0004 + 0x10 * (p))
|
||||
#define SUNXI_SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + 0x0008 + 0x10 * (p))
|
||||
|
||||
#endif /* SUNXI_SPC_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2021 Sipeed
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Without a management processor there is no SCPI support.
|
||||
SUNXI_PSCI_USE_SCPI := 0
|
||||
SUNXI_PSCI_USE_NATIVE := 1
|
||||
|
||||
# The differences between the platforms are covered by the include files.
|
||||
include plat/allwinner/common/allwinner-common.mk
|
||||
|
||||
# the above could be overwritten on the command line
|
||||
ifeq (${SUNXI_PSCI_USE_SCPI}, 1)
|
||||
$(error "R329 does not support SCPI PSCI ops")
|
||||
endif
|
||||
|
||||
# Put NOBITS memory in the first 64K of SRAM A2, overwriting U-Boot's SPL.
|
||||
SEPARATE_NOBITS_REGION := 1
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sunxi_private.h>
|
||||
|
||||
const struct psci_cpu_idle_state sunxi_idle_states[] = {
|
||||
{}
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Sipeed
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <sunxi_private.h>
|
||||
|
||||
int sunxi_pmic_setup(uint16_t socid, const void *fdt)
|
||||
{
|
||||
/* Currently known hardware has no PMIC */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sunxi_power_down(void)
|
||||
{
|
||||
}
|
||||
|
||||
void sunxi_cpu_power_off_self(void)
|
||||
{
|
||||
/* TODO: It's still unknown whether CPUIDLE exists on R329 */
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
static image_info_t bl30_image_info;
|
||||
static image_info_t bl301_image_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_image_ep_info : &bl32_image_ep_info;
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint. */
|
||||
if (next_image_info->pc != 0U)
|
||||
return next_image_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-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.
|
||||
******************************************************************************/
|
||||
struct axg_bl31_param {
|
||||
param_header_t h;
|
||||
image_info_t *bl31_image_info;
|
||||
entry_point_info_t *bl32_ep_info;
|
||||
image_info_t *bl32_image_info;
|
||||
entry_point_info_t *bl33_ep_info;
|
||||
image_info_t *bl33_image_info;
|
||||
image_info_t *scp_image_info[];
|
||||
};
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
struct axg_bl31_param *from_bl2;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
aml_console_init();
|
||||
|
||||
from_bl2 = (struct axg_bl31_param *)arg0;
|
||||
|
||||
/* Check params passed from BL2 are not NULL. */
|
||||
assert(from_bl2 != NULL);
|
||||
assert(from_bl2->h.type == PARAM_BL31);
|
||||
assert(from_bl2->h.version >= VERSION_1);
|
||||
|
||||
/*
|
||||
* Copy BL32 and BL33 entry point information. It is stored in Secure
|
||||
* RAM, in BL2's address space.
|
||||
*/
|
||||
bl32_image_ep_info = *from_bl2->bl32_ep_info;
|
||||
bl33_image_ep_info = *from_bl2->bl33_ep_info;
|
||||
|
||||
#if AML_USE_ATOS
|
||||
/*
|
||||
* BL2 is unconditionally setting 0 (OPTEE_AARCH64) in arg0 even when
|
||||
* the BL32 image is 32bit (OPTEE_AARCH32). This is causing the boot to
|
||||
* hang when ATOS (32bit Amlogic BL32 binary-only TEE OS) is used.
|
||||
*
|
||||
* Hardcode to OPTEE_AARCH32 / MODE_RW_32.
|
||||
*/
|
||||
bl32_image_ep_info.args.arg0 = MODE_RW_32;
|
||||
#endif
|
||||
|
||||
if (bl33_image_ep_info.pc == 0U) {
|
||||
ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
bl30_image_info = *from_bl2->scp_image_info[0];
|
||||
bl301_image_info = *from_bl2->scp_image_info[1];
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
aml_setup_page_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
static inline bool axg_scp_ready(void)
|
||||
{
|
||||
return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT));
|
||||
}
|
||||
|
||||
static inline void axg_scp_boot(void)
|
||||
{
|
||||
aml_scpi_upload_scp_fw(bl30_image_info.image_base,
|
||||
bl30_image_info.image_size, 0);
|
||||
aml_scpi_upload_scp_fw(bl301_image_info.image_base,
|
||||
bl301_image_info.image_size, 1);
|
||||
while (!axg_scp_ready())
|
||||
;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GICv2 driver setup information
|
||||
******************************************************************************/
|
||||
static const interrupt_prop_t axg_interrupt_props[] = {
|
||||
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
|
||||
};
|
||||
|
||||
static const gicv2_driver_data_t axg_gic_data = {
|
||||
.gicd_base = AML_GICD_BASE,
|
||||
.gicc_base = AML_GICC_BASE,
|
||||
.interrupt_props = axg_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(axg_interrupt_props)
|
||||
};
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
aml_mhu_secure_init();
|
||||
|
||||
gicv2_driver_init(&axg_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
axg_scp_boot();
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/ep_info.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform memory map regions
|
||||
******************************************************************************/
|
||||
#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
|
||||
AML_NSDRAM0_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \
|
||||
AML_NS_SHARE_MEM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \
|
||||
AML_SEC_SHARE_MEM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
|
||||
AML_SEC_DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW)
|
||||
|
||||
#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \
|
||||
AML_GIC_DEVICE_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
|
||||
AML_SEC_DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
|
||||
AML_SEC_DEVICE2_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
|
||||
AML_TZRAM_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
static const mmap_region_t axg_mmap[] = {
|
||||
MAP_NSDRAM0,
|
||||
MAP_NS_SHARE_MEM,
|
||||
MAP_SEC_SHARE_MEM,
|
||||
MAP_SEC_DEVICE0,
|
||||
MAP_GIC_DEVICE,
|
||||
MAP_SEC_DEVICE1,
|
||||
MAP_SEC_DEVICE2,
|
||||
MAP_TZRAM,
|
||||
{0}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Per-image regions
|
||||
******************************************************************************/
|
||||
#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
|
||||
BL31_END - BL31_BASE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
|
||||
BL_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE)
|
||||
|
||||
#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the translation tables.
|
||||
******************************************************************************/
|
||||
void aml_setup_page_tables(void)
|
||||
{
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t axg_bl_mmap[] = {
|
||||
MAP_BL31,
|
||||
MAP_BL_CODE,
|
||||
MAP_BL_RO_DATA,
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_BL_COHERENT,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
mmap_add(axg_bl_mmap);
|
||||
|
||||
mmap_add(axg_mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that returns the system counter frequency
|
||||
******************************************************************************/
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
mmio_clrbits_32(AML_SYS_CPU_CFG7, PLAT_SYS_CPU_CFG7);
|
||||
mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, PLAT_AO_TIMESTAMP_CNTL);
|
||||
|
||||
return AML_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef AXG_DEF_H
|
||||
#define AXG_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* System oscillator
|
||||
******************************************************************************/
|
||||
#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory regions
|
||||
******************************************************************************/
|
||||
#define AML_NS_SHARE_MEM_BASE UL(0x05000000)
|
||||
#define AML_NS_SHARE_MEM_SIZE UL(0x00100000)
|
||||
|
||||
#define AML_SEC_SHARE_MEM_BASE UL(0x05200000)
|
||||
#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000)
|
||||
|
||||
#define AML_GIC_DEVICE_BASE UL(0xFFC00000)
|
||||
#define AML_GIC_DEVICE_SIZE UL(0x00008000)
|
||||
|
||||
#define AML_NSDRAM0_BASE UL(0x01000000)
|
||||
#define AML_NSDRAM0_SIZE UL(0x0F000000)
|
||||
|
||||
#define BL31_BASE UL(0x05100000)
|
||||
#define BL31_SIZE UL(0x00100000)
|
||||
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
|
||||
|
||||
/* Shared memory used for SMC services */
|
||||
#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
|
||||
#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
|
||||
|
||||
#define AML_SEC_DEVICE0_BASE UL(0xFFD00000)
|
||||
#define AML_SEC_DEVICE0_SIZE UL(0x00026000)
|
||||
|
||||
#define AML_SEC_DEVICE1_BASE UL(0xFF800000)
|
||||
#define AML_SEC_DEVICE1_SIZE UL(0x0000A000)
|
||||
|
||||
#define AML_SEC_DEVICE2_BASE UL(0xFF620000)
|
||||
#define AML_SEC_DEVICE2_SIZE UL(0x00028000)
|
||||
|
||||
#define AML_TZRAM_BASE UL(0xFFFC0000)
|
||||
#define AML_TZRAM_SIZE UL(0x00020000)
|
||||
|
||||
/* Mailboxes */
|
||||
#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFD3800)
|
||||
#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFD3A00)
|
||||
#define AML_PSCI_MAILBOX_BASE UL(0xFFFD3F00)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC-400 and interrupt handling related constants
|
||||
******************************************************************************/
|
||||
#define AML_GICD_BASE UL(0xFFC01000)
|
||||
#define AML_GICC_BASE UL(0xFFC02000)
|
||||
|
||||
#define IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define IRQ_SEC_SGI_0 8
|
||||
#define IRQ_SEC_SGI_1 9
|
||||
#define IRQ_SEC_SGI_2 10
|
||||
#define IRQ_SEC_SGI_3 11
|
||||
#define IRQ_SEC_SGI_4 12
|
||||
#define IRQ_SEC_SGI_5 13
|
||||
#define IRQ_SEC_SGI_6 14
|
||||
#define IRQ_SEC_SGI_7 15
|
||||
#define IRQ_SEC_SGI_8 16
|
||||
|
||||
/*******************************************************************************
|
||||
* UART definitions
|
||||
******************************************************************************/
|
||||
#define AML_UART0_AO_BASE UL(0xFF803000)
|
||||
#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
|
||||
#define AML_UART_BAUDRATE U(115200)
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory-mapped I/O Registers
|
||||
******************************************************************************/
|
||||
#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4)
|
||||
|
||||
#define AML_SYS_CPU_CFG7 UL(0xFF634664)
|
||||
|
||||
#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C)
|
||||
#define AML_AO_RTI_SCP_STAT UL(0xFF80023C)
|
||||
#define AML_AO_RTI_SCP_READY_OFF U(0x14)
|
||||
#define AML_A0_RTI_SCP_READY_MASK U(3)
|
||||
#define AML_AO_RTI_SCP_IS_READY(v) \
|
||||
((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
|
||||
AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
|
||||
|
||||
#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404)
|
||||
#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408)
|
||||
#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C)
|
||||
#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428)
|
||||
#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C)
|
||||
#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430)
|
||||
|
||||
#define AML_SHA_DMA_BASE UL(0xFF63E000)
|
||||
#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
|
||||
#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28)
|
||||
|
||||
/*******************************************************************************
|
||||
* System Monitor Call IDs and arguments
|
||||
******************************************************************************/
|
||||
#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
|
||||
#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
|
||||
|
||||
#define AML_SM_EFUSE_READ U(0x82000030)
|
||||
#define AML_SM_EFUSE_USER_MAX U(0x82000033)
|
||||
|
||||
#define AML_SM_JTAG_ON U(0x82000040)
|
||||
#define AML_SM_JTAG_OFF U(0x82000041)
|
||||
#define AML_SM_GET_CHIP_ID U(0x82000044)
|
||||
|
||||
#define AML_JTAG_STATE_ON U(0)
|
||||
#define AML_JTAG_STATE_OFF U(1)
|
||||
|
||||
#define AML_JTAG_M3_AO U(0)
|
||||
#define AML_JTAG_M3_EE U(1)
|
||||
#define AML_JTAG_A53_AO U(2)
|
||||
#define AML_JTAG_A53_EE U(3)
|
||||
|
||||
#endif /* AXG_DEF_H */
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <errno.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define SCPI_POWER_ON 0
|
||||
#define SCPI_POWER_RETENTION 1
|
||||
#define SCPI_POWER_OFF 3
|
||||
|
||||
#define SCPI_SYSTEM_SHUTDOWN 0
|
||||
#define SCPI_SYSTEM_REBOOT 1
|
||||
|
||||
static uintptr_t axg_sec_entrypoint;
|
||||
|
||||
static void axg_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
|
||||
|
||||
mmio_write_64(cpu_mailbox_addr, value);
|
||||
}
|
||||
|
||||
static void axg_pm_reset(u_register_t mpidr, uint32_t value)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
|
||||
|
||||
mmio_write_32(cpu_mailbox_addr, value);
|
||||
}
|
||||
|
||||
static void __dead2 axg_system_reset(void)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
int ret;
|
||||
|
||||
INFO("BL31: PSCI_SYSTEM_RESET\n");
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
axg_pm_reset(mpidr, 0);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 axg_system_off(void)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
int ret;
|
||||
|
||||
INFO("BL31: PSCI_SYSTEM_OFF\n");
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
axg_pm_set_reset_addr(mpidr, 0);
|
||||
axg_pm_reset(mpidr, 0);
|
||||
|
||||
dmbsy();
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static int32_t axg_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
axg_pm_set_reset_addr(mpidr, axg_sec_entrypoint);
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
dmbsy();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void axg_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
axg_pm_set_reset_addr(read_mpidr_el1(), 0);
|
||||
}
|
||||
|
||||
static void axg_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
uint32_t system_state = SCPI_POWER_ON;
|
||||
uint32_t cluster_state = SCPI_POWER_ON;
|
||||
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
axg_pm_reset(mpidr, -1);
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
if (target_state->pwr_domain_state[MPIDR_AFFLVL2] ==
|
||||
PLAT_LOCAL_STATE_OFF)
|
||||
system_state = SCPI_POWER_OFF;
|
||||
|
||||
if (target_state->pwr_domain_state[MPIDR_AFFLVL1] ==
|
||||
PLAT_LOCAL_STATE_OFF)
|
||||
cluster_state = SCPI_POWER_OFF;
|
||||
|
||||
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_OFF, cluster_state,
|
||||
system_state);
|
||||
}
|
||||
|
||||
static void __dead2 axg_pwr_domain_pwr_down_wfi(const psci_power_state_t
|
||||
*target_state)
|
||||
{
|
||||
dsbsy();
|
||||
axg_pm_reset(read_mpidr_el1(), 0);
|
||||
|
||||
for (;;)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers and setup function.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t axg_ops = {
|
||||
.pwr_domain_on = axg_pwr_domain_on,
|
||||
.pwr_domain_on_finish = axg_pwr_domain_on_finish,
|
||||
.pwr_domain_off = axg_pwr_domain_off,
|
||||
.pwr_domain_pwr_down_wfi = axg_pwr_domain_pwr_down_wfi,
|
||||
.system_off = axg_system_off,
|
||||
.system_reset = axg_system_reset
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
axg_sec_entrypoint = sec_entrypoint;
|
||||
*psci_ops = &axg_ops;
|
||||
return 0;
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include "../axg_def.h"
|
||||
|
||||
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||
#define PLATFORM_LINKER_ARCH aarch64
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x1000)
|
||||
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
|
||||
#define AML_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
#define PLAT_SYS_CPU_CFG7 (U(1) << 25)
|
||||
#define PLAT_AO_TIMESTAMP_CNTL U(0x1ff)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for power-down. Valid for CPU and cluster power domains. */
|
||||
#define PLAT_LOCAL_STATE_OFF U(2)
|
||||
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/* Memory-related defines */
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
|
||||
#define MAX_MMAP_REGIONS 16
|
||||
#define MAX_XLAT_TABLES 8
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,95 @@
|
||||
#
|
||||
# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
AML_PLAT := plat/amlogic
|
||||
AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
|
||||
AML_PLAT_COMMON := ${AML_PLAT}/common
|
||||
|
||||
DOIMAGEPATH ?= tools/amlogic
|
||||
DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
|
||||
-I${AML_PLAT_SOC}/include \
|
||||
-I${AML_PLAT_COMMON}/include
|
||||
|
||||
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
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
drivers/amlogic/console/aarch64/meson_console.S \
|
||||
${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_pm.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_common.c \
|
||||
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
|
||||
${AML_PLAT_COMMON}/aml_efuse.c \
|
||||
${AML_PLAT_COMMON}/aml_mhu.c \
|
||||
${AML_PLAT_COMMON}/aml_scpi.c \
|
||||
${AML_PLAT_COMMON}/aml_sip_svc.c \
|
||||
${AML_PLAT_COMMON}/aml_thermal.c \
|
||||
${AML_PLAT_COMMON}/aml_topology.c \
|
||||
${AML_PLAT_COMMON}/aml_console.c \
|
||||
drivers/amlogic/crypto/sha_dma.c \
|
||||
${XLAT_TABLES_LIB_SRCS} \
|
||||
${GIC_SOURCES}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else
|
||||
TF_CFLAGS_aarch64 += -mtune=cortex-a53
|
||||
endif
|
||||
|
||||
# Build config flags
|
||||
# ------------------
|
||||
|
||||
# Enable all errata workarounds for Cortex-A53
|
||||
ERRATA_A53_855873 := 1
|
||||
ERRATA_A53_819472 := 1
|
||||
ERRATA_A53_824069 := 1
|
||||
ERRATA_A53_827319 := 1
|
||||
|
||||
WORKAROUND_CVE_2017_5715 := 0
|
||||
|
||||
# Have different sections for code and rodata
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# Use Coherent memory
|
||||
USE_COHERENT_MEM := 1
|
||||
|
||||
AML_USE_ATOS := 0
|
||||
$(eval $(call assert_boolean,AML_USE_ATOS))
|
||||
$(eval $(call add_define,AML_USE_ATOS))
|
||||
|
||||
# Verify build config
|
||||
# -------------------
|
||||
|
||||
ifneq (${RESET_TO_BL31}, 0)
|
||||
$(error Error: ${PLAT} needs RESET_TO_BL31=0)
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error Error: AArch32 not supported on ${PLAT})
|
||||
endif
|
||||
|
||||
all: ${BUILD_PLAT}/bl31.img
|
||||
distclean realclean clean: cleanimage
|
||||
|
||||
cleanimage:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH} clean
|
||||
|
||||
${DOIMAGETOOL}:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH}
|
||||
|
||||
${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
|
||||
${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl platform_mem_init
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl plat_my_core_pos
|
||||
.globl plat_reset_handler
|
||||
.globl plat_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_my_core_pos(void);
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
b plat_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_calc_core_pos(u_register_t mpidr);
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_calc_core_pos
|
||||
and x0, x0, #MPIDR_CPU_MASK
|
||||
ret
|
||||
endfunc plat_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary(void);
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)
|
||||
cmp x0, #AML_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void platform_mem_init(void);
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_init(void)
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, AML_UART0_AO_BASE
|
||||
mov_imm x1, AML_UART0_AO_CLK_IN_HZ
|
||||
mov_imm x2, AML_UART_BAUDRATE
|
||||
b console_meson_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int plat_crash_console_putc(int c)
|
||||
* Clobber list : x1, x2
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, AML_UART0_AO_BASE
|
||||
b console_meson_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_crash_console_flush()
|
||||
* Out : void.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, AML_UART0_AO_BASE
|
||||
b console_meson_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void plat_reset_handler(void);
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func plat_reset_handler
|
||||
ret
|
||||
endfunc plat_reset_handler
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Carlo Caione <ccaione@baylibre.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <meson_console.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the console
|
||||
******************************************************************************/
|
||||
static console_t aml_console;
|
||||
|
||||
void aml_console_init(void)
|
||||
{
|
||||
int rc = console_meson_register(AML_UART0_AO_BASE,
|
||||
AML_UART0_AO_CLK_IN_HZ,
|
||||
AML_UART_BAUDRATE,
|
||||
&aml_console);
|
||||
if (rc == 0) {
|
||||
/*
|
||||
* The crash console doesn't use the multi console API, it uses
|
||||
* the core console functions directly. It is safe to call panic
|
||||
* and let it print debug information.
|
||||
*/
|
||||
panic();
|
||||
}
|
||||
|
||||
console_set_scope(&aml_console,
|
||||
CONSOLE_FLAG_BOOT | CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define EFUSE_BASE 0x140
|
||||
#define EFUSE_SIZE 0xC0
|
||||
|
||||
uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size)
|
||||
{
|
||||
if ((uint64_t)(offset + size) > (uint64_t)EFUSE_SIZE)
|
||||
return 0;
|
||||
|
||||
return aml_scpi_efuse_read(dst, offset + EFUSE_BASE, size);
|
||||
}
|
||||
|
||||
uint64_t aml_efuse_user_max(void)
|
||||
{
|
||||
return EFUSE_SIZE;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static DEFINE_BAKERY_LOCK(mhu_lock);
|
||||
|
||||
void aml_mhu_secure_message_start(void)
|
||||
{
|
||||
bakery_lock_get(&mhu_lock);
|
||||
|
||||
while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
void aml_mhu_secure_message_send(uint32_t msg)
|
||||
{
|
||||
mmio_write_32(AML_HIU_MAILBOX_SET_3, msg);
|
||||
|
||||
while (mmio_read_32(AML_HIU_MAILBOX_STAT_3) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
uint32_t aml_mhu_secure_message_wait(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
do {
|
||||
val = mmio_read_32(AML_HIU_MAILBOX_STAT_0);
|
||||
} while (val == 0);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void aml_mhu_secure_message_end(void)
|
||||
{
|
||||
mmio_write_32(AML_HIU_MAILBOX_CLR_0, 0xFFFFFFFF);
|
||||
|
||||
bakery_lock_release(&mhu_lock);
|
||||
}
|
||||
|
||||
void aml_mhu_secure_init(void)
|
||||
{
|
||||
bakery_lock_init(&mhu_lock);
|
||||
|
||||
mmio_write_32(AML_HIU_MAILBOX_CLR_3, 0xFFFFFFFF);
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <crypto/sha_dma.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define SIZE_SHIFT 20
|
||||
#define SIZE_MASK 0x1FF
|
||||
#define SIZE_FWBLK 0x200UL
|
||||
|
||||
/*
|
||||
* Note: The Amlogic SCP firmware uses the legacy SCPI protocol.
|
||||
*/
|
||||
#define SCPI_CMD_SET_CSS_POWER_STATE 0x04
|
||||
#define SCPI_CMD_SET_SYS_POWER_STATE 0x08
|
||||
|
||||
#define SCPI_CMD_JTAG_SET_STATE 0xC0
|
||||
#define SCPI_CMD_EFUSE_READ 0xC2
|
||||
#define SCPI_CMD_CHIP_ID 0xC6
|
||||
|
||||
#define SCPI_CMD_COPY_FW 0xd4
|
||||
#define SCPI_CMD_SET_FW_ADDR 0xd3
|
||||
#define SCPI_CMD_FW_SIZE 0xd2
|
||||
|
||||
static inline uint32_t aml_scpi_cmd(uint32_t command, uint32_t size)
|
||||
{
|
||||
return command | (size << SIZE_SHIFT);
|
||||
}
|
||||
|
||||
static void aml_scpi_secure_message_send(uint32_t command, uint32_t size)
|
||||
{
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(command, size));
|
||||
}
|
||||
|
||||
static uint32_t aml_scpi_secure_message_receive(void **message_out, size_t *size_out)
|
||||
{
|
||||
uint32_t response = aml_mhu_secure_message_wait();
|
||||
|
||||
size_t size = (response >> SIZE_SHIFT) & SIZE_MASK;
|
||||
|
||||
response &= ~(SIZE_MASK << SIZE_SHIFT);
|
||||
|
||||
if (size_out != NULL)
|
||||
*size_out = size;
|
||||
|
||||
if (message_out != NULL)
|
||||
*message_out = (void *)AML_MHU_SECURE_SCP_TO_AP_PAYLOAD;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
|
||||
uint32_t cluster_state, uint32_t css_state)
|
||||
{
|
||||
uint32_t state = (mpidr & 0x0F) | /* CPU ID */
|
||||
((mpidr & 0xF00) >> 4) | /* Cluster ID */
|
||||
(cpu_state << 8) |
|
||||
(cluster_state << 12) |
|
||||
(css_state << 16);
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, state);
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_CSS_POWER_STATE, 4));
|
||||
aml_mhu_secure_message_wait();
|
||||
aml_mhu_secure_message_end();
|
||||
}
|
||||
|
||||
uint32_t aml_scpi_sys_power_state(uint64_t system_state)
|
||||
{
|
||||
uint32_t *response;
|
||||
size_t size;
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
mmio_write_8(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, system_state);
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_SET_SYS_POWER_STATE, 1));
|
||||
aml_scpi_secure_message_receive((void *)&response, &size);
|
||||
aml_mhu_secure_message_end();
|
||||
|
||||
return *response;
|
||||
}
|
||||
|
||||
void aml_scpi_jtag_set_state(uint32_t state, uint8_t select)
|
||||
{
|
||||
assert(state <= AML_JTAG_STATE_OFF);
|
||||
|
||||
if (select > AML_JTAG_A53_EE) {
|
||||
WARN("BL31: Invalid JTAG select (0x%x).\n", select);
|
||||
return;
|
||||
}
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD,
|
||||
(state << 8) | (uint32_t)select);
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_JTAG_SET_STATE, 4));
|
||||
aml_mhu_secure_message_wait();
|
||||
aml_mhu_secure_message_end();
|
||||
}
|
||||
|
||||
uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size)
|
||||
{
|
||||
uint32_t *response;
|
||||
size_t resp_size;
|
||||
|
||||
if (size > 0x1FC)
|
||||
return 0;
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, base);
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 4, size);
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_EFUSE_READ, 8));
|
||||
aml_scpi_secure_message_receive((void *)&response, &resp_size);
|
||||
aml_mhu_secure_message_end();
|
||||
|
||||
/*
|
||||
* response[0] is the size of the response message.
|
||||
* response[1 ... N] are the contents.
|
||||
*/
|
||||
if (*response != 0)
|
||||
memcpy(dst, response + 1, *response);
|
||||
|
||||
return *response;
|
||||
}
|
||||
|
||||
void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3)
|
||||
{
|
||||
aml_mhu_secure_message_start();
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x0, arg0);
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x4, arg1);
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0x8, arg2);
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD + 0xC, arg3);
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(0xC3, 16));
|
||||
aml_mhu_secure_message_wait();
|
||||
aml_mhu_secure_message_end();
|
||||
}
|
||||
|
||||
uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize)
|
||||
{
|
||||
uint32_t *response;
|
||||
size_t resp_size;
|
||||
|
||||
if ((osize != 16) && (osize != 12))
|
||||
return 0;
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
aml_mhu_secure_message_send(aml_scpi_cmd(SCPI_CMD_CHIP_ID, osize));
|
||||
aml_scpi_secure_message_receive((void *)&response, &resp_size);
|
||||
aml_mhu_secure_message_end();
|
||||
|
||||
if (!((resp_size == 16) && (osize == 16)) &&
|
||||
!((resp_size == 0) && (osize == 12)))
|
||||
return 0;
|
||||
|
||||
memcpy((void *)obuff, (const void *)response, osize);
|
||||
|
||||
return osize;
|
||||
}
|
||||
|
||||
static inline void aml_scpi_copy_scp_data(uint8_t *data, size_t len)
|
||||
{
|
||||
void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
|
||||
size_t sz;
|
||||
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
|
||||
aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
|
||||
aml_mhu_secure_message_wait();
|
||||
|
||||
for (sz = 0; sz < len; sz += SIZE_FWBLK) {
|
||||
memcpy(dst, data + sz, MIN(SIZE_FWBLK, len - sz));
|
||||
aml_mhu_secure_message_send(SCPI_CMD_COPY_FW);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void aml_scpi_set_scp_addr(uint64_t addr, size_t len)
|
||||
{
|
||||
volatile uint64_t *dst = (uint64_t *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
|
||||
|
||||
/*
|
||||
* It is ok as AML_MHU_SECURE_AP_TO_SCP_PAYLOAD is mapped as
|
||||
* non cachable
|
||||
*/
|
||||
*dst = addr;
|
||||
aml_scpi_secure_message_send(SCPI_CMD_SET_FW_ADDR, sizeof(addr));
|
||||
aml_mhu_secure_message_wait();
|
||||
|
||||
mmio_write_32(AML_MHU_SECURE_AP_TO_SCP_PAYLOAD, len);
|
||||
aml_scpi_secure_message_send(SCPI_CMD_FW_SIZE, len);
|
||||
aml_mhu_secure_message_wait();
|
||||
}
|
||||
|
||||
static inline void aml_scpi_send_fw_hash(uint8_t hash[], size_t len)
|
||||
{
|
||||
void *dst = (void *)AML_MHU_SECURE_AP_TO_SCP_PAYLOAD;
|
||||
|
||||
memcpy(dst, hash, len);
|
||||
aml_mhu_secure_message_send(0xd0);
|
||||
aml_mhu_secure_message_send(0xd1);
|
||||
aml_mhu_secure_message_send(0xd5);
|
||||
aml_mhu_secure_message_end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a FW to SCP.
|
||||
*
|
||||
* @param addr: firmware data address
|
||||
* @param size: size of firmware
|
||||
* @param send: If set, actually copy the firmware in SCP memory otherwise only
|
||||
* send the firmware address.
|
||||
*/
|
||||
void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send)
|
||||
{
|
||||
struct asd_ctx ctx;
|
||||
|
||||
asd_sha_init(&ctx, ASM_SHA256);
|
||||
asd_sha_update(&ctx, (void *)addr, size);
|
||||
asd_sha_finalize(&ctx);
|
||||
|
||||
aml_mhu_secure_message_start();
|
||||
if (send == 0)
|
||||
aml_scpi_set_scp_addr(addr, size);
|
||||
else
|
||||
aml_scpi_copy_scp_data((void *)addr, size);
|
||||
|
||||
aml_scpi_send_fw_hash(ctx.digest, sizeof(ctx.digest));
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
struct aml_cpu_info {
|
||||
uint32_t version;
|
||||
uint8_t chip_id[16];
|
||||
};
|
||||
|
||||
static int aml_sip_get_chip_id(uint64_t version)
|
||||
{
|
||||
struct aml_cpu_info *info = (void *)AML_SHARE_MEM_OUTPUT_BASE;
|
||||
uint32_t size;
|
||||
|
||||
if (version > 2)
|
||||
return -1;
|
||||
|
||||
memset(info, 0, sizeof(struct aml_cpu_info));
|
||||
|
||||
if (version == 2) {
|
||||
info->version = 2;
|
||||
size = 16;
|
||||
} else {
|
||||
info->version = 1;
|
||||
size = 12;
|
||||
}
|
||||
|
||||
if (aml_scpi_get_chip_id(info->chip_id, size) == 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function is responsible for handling all SiP calls
|
||||
******************************************************************************/
|
||||
static uintptr_t aml_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)
|
||||
{
|
||||
switch (smc_fid) {
|
||||
|
||||
case AML_SM_GET_SHARE_MEM_INPUT_BASE:
|
||||
SMC_RET1(handle, AML_SHARE_MEM_INPUT_BASE);
|
||||
|
||||
case AML_SM_GET_SHARE_MEM_OUTPUT_BASE:
|
||||
SMC_RET1(handle, AML_SHARE_MEM_OUTPUT_BASE);
|
||||
|
||||
case AML_SM_EFUSE_READ:
|
||||
{
|
||||
void *dst = (void *)AML_SHARE_MEM_OUTPUT_BASE;
|
||||
uint64_t ret = aml_efuse_read(dst, (uint32_t)x1, x2);
|
||||
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
case AML_SM_EFUSE_USER_MAX:
|
||||
SMC_RET1(handle, aml_efuse_user_max());
|
||||
|
||||
case AML_SM_JTAG_ON:
|
||||
aml_scpi_jtag_set_state(AML_JTAG_STATE_ON, x1);
|
||||
SMC_RET1(handle, 0);
|
||||
|
||||
case AML_SM_JTAG_OFF:
|
||||
aml_scpi_jtag_set_state(AML_JTAG_STATE_OFF, x1);
|
||||
SMC_RET1(handle, 0);
|
||||
|
||||
case AML_SM_GET_CHIP_ID:
|
||||
SMC_RET1(handle, aml_sip_get_chip_id(x1));
|
||||
|
||||
default:
|
||||
ERROR("BL31: Unhandled SIP SMC: 0x%08x\n", smc_fid);
|
||||
break;
|
||||
}
|
||||
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
DECLARE_RT_SVC(
|
||||
aml_sip_handler,
|
||||
|
||||
OEN_SIP_START,
|
||||
OEN_SIP_END,
|
||||
SMC_TYPE_FAST,
|
||||
NULL,
|
||||
aml_sip_handler
|
||||
);
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
static int32_t modules_initialized = -1;
|
||||
|
||||
/*******************************************************************************
|
||||
* Unknown commands related to something thermal-related
|
||||
******************************************************************************/
|
||||
void aml_thermal_unknown(void)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
if (modules_initialized == -1) {
|
||||
aml_scpi_efuse_read(&ret, 0, 2);
|
||||
modules_initialized = ret;
|
||||
}
|
||||
|
||||
aml_scpi_unknown_thermal(10, 2, /* thermal */
|
||||
13, 1); /* thermalver */
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
/* The power domain tree descriptor */
|
||||
static unsigned char power_domain_tree_desc[] = {
|
||||
/* Number of root nodes */
|
||||
PLATFORM_CLUSTER_COUNT,
|
||||
/* Number of children for the first node */
|
||||
PLATFORM_CLUSTER0_CORE_COUNT
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the ARM default topology tree information.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function implements a part of the critical interface between the psci
|
||||
* generic layer and the platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index. An error code (-1) is returned
|
||||
* in case the MPIDR is invalid.
|
||||
******************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster_id, cpu_id;
|
||||
|
||||
mpidr &= MPIDR_AFFINITY_MASK;
|
||||
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
|
||||
return -1;
|
||||
|
||||
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
|
||||
if (cluster_id >= PLATFORM_CLUSTER_COUNT)
|
||||
return -1;
|
||||
|
||||
if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
return -1;
|
||||
|
||||
return plat_calc_core_pos(mpidr);
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef AML_PRIVATE_H
|
||||
#define AML_PRIVATE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Utility functions */
|
||||
unsigned int plat_calc_core_pos(u_register_t mpidr);
|
||||
void aml_console_init(void);
|
||||
void aml_setup_page_tables(void);
|
||||
|
||||
/* MHU functions */
|
||||
void aml_mhu_secure_message_start(void);
|
||||
void aml_mhu_secure_message_send(uint32_t msg);
|
||||
uint32_t aml_mhu_secure_message_wait(void);
|
||||
void aml_mhu_secure_message_end(void);
|
||||
void aml_mhu_secure_init(void);
|
||||
|
||||
/* SCPI functions */
|
||||
void aml_scpi_set_css_power_state(u_register_t mpidr, uint32_t cpu_state,
|
||||
uint32_t cluster_state, uint32_t css_state);
|
||||
uint32_t aml_scpi_sys_power_state(uint64_t system_state);
|
||||
void aml_scpi_jtag_set_state(uint32_t state, uint8_t select);
|
||||
uint32_t aml_scpi_efuse_read(void *dst, uint32_t base, uint32_t size);
|
||||
void aml_scpi_unknown_thermal(uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3);
|
||||
void aml_scpi_upload_scp_fw(uintptr_t addr, size_t size, int send);
|
||||
uint32_t aml_scpi_get_chip_id(uint8_t *obuff, uint32_t osize);
|
||||
|
||||
/* Peripherals */
|
||||
void aml_thermal_unknown(void);
|
||||
uint64_t aml_efuse_read(void *dst, uint32_t offset, uint32_t size);
|
||||
uint64_t aml_efuse_user_max(void);
|
||||
|
||||
#endif /* AML_PRIVATE_H */
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MACROS_S
|
||||
#define PLAT_MACROS_S
|
||||
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.section .rodata.gic_reg_name, "aS"
|
||||
|
||||
gicc_regs:
|
||||
.asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", ""
|
||||
gicd_pend_reg:
|
||||
.asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
|
||||
newline:
|
||||
.asciz "\n"
|
||||
spacer:
|
||||
.asciz ":\t\t0x"
|
||||
|
||||
/* ---------------------------------------------
|
||||
* The below required platform porting macro
|
||||
* prints out relevant GIC and CCI registers
|
||||
* whenever an unhandled exception is taken in
|
||||
* BL31.
|
||||
* Clobbers: x0 - x10, x16, x17, sp
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
.macro plat_crash_print_regs
|
||||
|
||||
/* GICC registers */
|
||||
|
||||
mov_imm x17, AML_GICC_BASE
|
||||
|
||||
adr x6, gicc_regs
|
||||
ldr w8, [x17, #GICC_HPPIR]
|
||||
ldr w9, [x17, #GICC_AHPPIR]
|
||||
ldr w10, [x17, #GICC_CTLR]
|
||||
bl str_in_crash_buf_print
|
||||
|
||||
/* GICD registers */
|
||||
|
||||
mov_imm x16, AML_GICD_BASE
|
||||
|
||||
add x7, x16, #GICD_ISPENDR
|
||||
adr x4, gicd_pend_reg
|
||||
bl asm_print_str
|
||||
|
||||
gicd_ispendr_loop:
|
||||
sub x4, x7, x16
|
||||
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:
|
||||
|
||||
.endm
|
||||
|
||||
#endif /* PLAT_MACROS_S */
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl32_image_ep_info;
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
static image_info_t bl30_image_info;
|
||||
static image_info_t bl301_image_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_image_ep_info : &bl32_image_ep_info;
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint. */
|
||||
if (next_image_info->pc != 0U)
|
||||
return next_image_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-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.
|
||||
******************************************************************************/
|
||||
struct g12a_bl31_param {
|
||||
param_header_t h;
|
||||
image_info_t *bl31_image_info;
|
||||
entry_point_info_t *bl32_ep_info;
|
||||
image_info_t *bl32_image_info;
|
||||
entry_point_info_t *bl33_ep_info;
|
||||
image_info_t *bl33_image_info;
|
||||
image_info_t *scp_image_info[];
|
||||
};
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
struct g12a_bl31_param *from_bl2;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
aml_console_init();
|
||||
|
||||
from_bl2 = (struct g12a_bl31_param *)arg0;
|
||||
|
||||
/* Check params passed from BL2 are not NULL. */
|
||||
assert(from_bl2 != NULL);
|
||||
assert(from_bl2->h.type == PARAM_BL31);
|
||||
assert(from_bl2->h.version >= VERSION_1);
|
||||
|
||||
/*
|
||||
* Copy BL32 and BL33 entry point information. It is stored in Secure
|
||||
* RAM, in BL2's address space.
|
||||
*/
|
||||
bl32_image_ep_info = *from_bl2->bl32_ep_info;
|
||||
bl33_image_ep_info = *from_bl2->bl33_ep_info;
|
||||
|
||||
if (bl33_image_ep_info.pc == 0U) {
|
||||
ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
bl30_image_info = *from_bl2->scp_image_info[0];
|
||||
bl301_image_info = *from_bl2->scp_image_info[1];
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
aml_setup_page_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GICv2 driver setup information
|
||||
******************************************************************************/
|
||||
static const interrupt_prop_t g12a_interrupt_props[] = {
|
||||
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL)
|
||||
};
|
||||
|
||||
static const gicv2_driver_data_t g12a_gic_data = {
|
||||
.gicd_base = AML_GICD_BASE,
|
||||
.gicc_base = AML_GICC_BASE,
|
||||
.interrupt_props = g12a_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(g12a_interrupt_props)
|
||||
};
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
aml_mhu_secure_init();
|
||||
|
||||
gicv2_driver_init(&g12a_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/ep_info.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform memory map regions
|
||||
******************************************************************************/
|
||||
#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
|
||||
AML_NSDRAM0_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_NS_SHARE_MEM MAP_REGION_FLAT(AML_NS_SHARE_MEM_BASE, \
|
||||
AML_NS_SHARE_MEM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_SEC_SHARE_MEM MAP_REGION_FLAT(AML_SEC_SHARE_MEM_BASE, \
|
||||
AML_SEC_SHARE_MEM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
|
||||
AML_SEC_DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW)
|
||||
|
||||
#define MAP_HDCP_RX MAP_REGION_FLAT(AML_HDCP_RX_BASE, \
|
||||
AML_HDCP_RX_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_HDCP_TX MAP_REGION_FLAT(AML_HDCP_TX_BASE, \
|
||||
AML_HDCP_TX_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_GIC_DEVICE MAP_REGION_FLAT(AML_GIC_DEVICE_BASE, \
|
||||
AML_GIC_DEVICE_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
|
||||
AML_SEC_DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
|
||||
AML_SEC_DEVICE2_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
|
||||
AML_TZRAM_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
static const mmap_region_t g12a_mmap[] = {
|
||||
MAP_NSDRAM0,
|
||||
MAP_NS_SHARE_MEM,
|
||||
MAP_SEC_SHARE_MEM,
|
||||
MAP_SEC_DEVICE0,
|
||||
MAP_HDCP_RX,
|
||||
MAP_HDCP_TX,
|
||||
MAP_GIC_DEVICE,
|
||||
MAP_SEC_DEVICE1,
|
||||
MAP_SEC_DEVICE2,
|
||||
MAP_TZRAM,
|
||||
{0}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Per-image regions
|
||||
******************************************************************************/
|
||||
#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
|
||||
BL31_END - BL31_BASE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
|
||||
BL_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE)
|
||||
|
||||
#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the translation tables.
|
||||
******************************************************************************/
|
||||
void aml_setup_page_tables(void)
|
||||
{
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t g12a_bl_mmap[] = {
|
||||
MAP_BL31,
|
||||
MAP_BL_CODE,
|
||||
MAP_BL_RO_DATA,
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_BL_COHERENT,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
mmap_add(g12a_bl_mmap);
|
||||
|
||||
mmap_add(g12a_mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that returns the system counter frequency
|
||||
******************************************************************************/
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
mmio_clrbits_32(AML_SYS_CPU_CFG7, ~0xFDFFFFFF);
|
||||
mmio_clrbits_32(AML_AO_TIMESTAMP_CNTL, ~0xFFFFFE00);
|
||||
|
||||
return AML_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef G12A_DEF_H
|
||||
#define G12A_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* System oscillator
|
||||
******************************************************************************/
|
||||
#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory regions
|
||||
******************************************************************************/
|
||||
#define AML_HDCP_RX_BASE UL(0xFFE0D000)
|
||||
#define AML_HDCP_RX_SIZE UL(0x00002000)
|
||||
|
||||
#define AML_HDCP_TX_BASE UL(0xFFE01000)
|
||||
#define AML_HDCP_TX_SIZE UL(0x00001000)
|
||||
|
||||
#define AML_NS_SHARE_MEM_BASE UL(0x05000000)
|
||||
#define AML_NS_SHARE_MEM_SIZE UL(0x00100000)
|
||||
|
||||
#define AML_SEC_SHARE_MEM_BASE UL(0x05200000)
|
||||
#define AML_SEC_SHARE_MEM_SIZE UL(0x00100000)
|
||||
|
||||
#define AML_GIC_DEVICE_BASE UL(0xFFC00000)
|
||||
#define AML_GIC_DEVICE_SIZE UL(0x00008000)
|
||||
|
||||
#define AML_NSDRAM0_BASE UL(0x01000000)
|
||||
#define AML_NSDRAM0_SIZE UL(0x0F000000)
|
||||
|
||||
#define BL31_BASE UL(0x05100000)
|
||||
#define BL31_SIZE UL(0x00100000)
|
||||
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
|
||||
|
||||
/* Shared memory used for SMC services */
|
||||
#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
|
||||
#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
|
||||
|
||||
#define AML_SEC_DEVICE0_BASE UL(0xFFD00000)
|
||||
#define AML_SEC_DEVICE0_SIZE UL(0x00026000)
|
||||
|
||||
#define AML_SEC_DEVICE1_BASE UL(0xFF800000)
|
||||
#define AML_SEC_DEVICE1_SIZE UL(0x0000A000)
|
||||
|
||||
#define AML_TZRAM_BASE UL(0xFFFA0000)
|
||||
#define AML_TZRAM_SIZE UL(0x00048000)
|
||||
|
||||
/* Mailboxes */
|
||||
#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xFFFE7800)
|
||||
#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xFFFE7A00)
|
||||
#define AML_PSCI_MAILBOX_BASE UL(0xFFFE7F00)
|
||||
|
||||
#define AML_SEC_DEVICE2_BASE UL(0xFF620000)
|
||||
#define AML_SEC_DEVICE2_SIZE UL(0x00028000)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC-400 and interrupt handling related constants
|
||||
******************************************************************************/
|
||||
#define AML_GICD_BASE UL(0xFFC01000)
|
||||
#define AML_GICC_BASE UL(0xFFC02000)
|
||||
|
||||
#define IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define IRQ_SEC_SGI_0 8
|
||||
#define IRQ_SEC_SGI_1 9
|
||||
#define IRQ_SEC_SGI_2 10
|
||||
#define IRQ_SEC_SGI_3 11
|
||||
#define IRQ_SEC_SGI_4 12
|
||||
#define IRQ_SEC_SGI_5 13
|
||||
#define IRQ_SEC_SGI_6 14
|
||||
#define IRQ_SEC_SGI_7 15
|
||||
#define IRQ_SEC_SGI_8 16
|
||||
|
||||
/*******************************************************************************
|
||||
* UART definitions
|
||||
******************************************************************************/
|
||||
#define AML_UART0_AO_BASE UL(0xFF803000)
|
||||
#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
|
||||
#define AML_UART_BAUDRATE U(115200)
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory-mapped I/O Registers
|
||||
******************************************************************************/
|
||||
#define AML_AO_TIMESTAMP_CNTL UL(0xFF8000B4)
|
||||
|
||||
#define AML_SYS_CPU_CFG7 UL(0xFF634664)
|
||||
|
||||
#define AML_AO_RTI_STATUS_REG3 UL(0xFF80001C)
|
||||
#define AML_AO_RTI_SCP_STAT UL(0xFF80023C)
|
||||
#define AML_AO_RTI_SCP_READY_OFF U(0x14)
|
||||
#define AML_A0_RTI_SCP_READY_MASK U(3)
|
||||
#define AML_AO_RTI_SCP_IS_READY(v) \
|
||||
((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
|
||||
AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
|
||||
|
||||
#define AML_HIU_MAILBOX_SET_0 UL(0xFF63C404)
|
||||
#define AML_HIU_MAILBOX_STAT_0 UL(0xFF63C408)
|
||||
#define AML_HIU_MAILBOX_CLR_0 UL(0xFF63C40C)
|
||||
#define AML_HIU_MAILBOX_SET_3 UL(0xFF63C428)
|
||||
#define AML_HIU_MAILBOX_STAT_3 UL(0xFF63C42C)
|
||||
#define AML_HIU_MAILBOX_CLR_3 UL(0xFF63C430)
|
||||
|
||||
#define AML_SHA_DMA_BASE UL(0xFF63E000)
|
||||
#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
|
||||
#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x28)
|
||||
|
||||
/*******************************************************************************
|
||||
* System Monitor Call IDs and arguments
|
||||
******************************************************************************/
|
||||
#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
|
||||
#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
|
||||
|
||||
#define AML_SM_EFUSE_READ U(0x82000030)
|
||||
#define AML_SM_EFUSE_USER_MAX U(0x82000033)
|
||||
|
||||
#define AML_SM_JTAG_ON U(0x82000040)
|
||||
#define AML_SM_JTAG_OFF U(0x82000041)
|
||||
#define AML_SM_GET_CHIP_ID U(0x82000044)
|
||||
|
||||
#define AML_JTAG_STATE_ON U(0)
|
||||
#define AML_JTAG_STATE_OFF U(1)
|
||||
|
||||
#define AML_JTAG_M3_AO U(0)
|
||||
#define AML_JTAG_M3_EE U(1)
|
||||
#define AML_JTAG_A53_AO U(2)
|
||||
#define AML_JTAG_A53_EE U(3)
|
||||
|
||||
#endif /* G12A_DEF_H */
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <errno.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define SCPI_POWER_ON 0
|
||||
#define SCPI_POWER_RETENTION 1
|
||||
#define SCPI_POWER_OFF 3
|
||||
|
||||
#define SCPI_SYSTEM_SHUTDOWN 0
|
||||
#define SCPI_SYSTEM_REBOOT 1
|
||||
|
||||
static uintptr_t g12a_sec_entrypoint;
|
||||
static volatile uint32_t g12a_cpu0_go;
|
||||
|
||||
static void g12a_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
|
||||
|
||||
mmio_write_64(cpu_mailbox_addr, value);
|
||||
}
|
||||
|
||||
static void g12a_pm_reset(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
|
||||
|
||||
mmio_write_32(cpu_mailbox_addr, 0);
|
||||
}
|
||||
|
||||
static void __dead2 g12a_system_reset(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_RESET\n");
|
||||
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
|
||||
int ret;
|
||||
|
||||
NOTICE("BL31: Reboot reason: 0x%x\n", status);
|
||||
|
||||
status &= 0xFFFF0FF0;
|
||||
|
||||
console_flush();
|
||||
|
||||
mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
g12a_pm_reset(mpidr);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 g12a_system_off(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_OFF\n");
|
||||
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
int ret;
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
g12a_pm_set_reset_addr(mpidr, 0);
|
||||
g12a_pm_reset(mpidr);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static int32_t g12a_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
/* CPU0 can't be turned OFF */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
|
||||
|
||||
g12a_cpu0_go = 1;
|
||||
flush_dcache_range((uintptr_t)&g12a_cpu0_go,
|
||||
sizeof(g12a_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
g12a_pm_set_reset_addr(mpidr, g12a_sec_entrypoint);
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
dmbsy();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void g12a_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(read_mpidr_el1());
|
||||
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
g12a_cpu0_go = 0;
|
||||
flush_dcache_range((uintptr_t)&g12a_cpu0_go,
|
||||
sizeof(g12a_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
}
|
||||
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
static void g12a_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* CPU0 can't be turned OFF */
|
||||
if (core == AML_PRIMARY_CPU)
|
||||
return;
|
||||
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_OFF, SCPI_POWER_ON,
|
||||
SCPI_POWER_ON);
|
||||
}
|
||||
|
||||
static void __dead2 g12a_pwr_domain_pwr_down_wfi(const psci_power_state_t
|
||||
*target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: CPU0 entering wait loop...\n");
|
||||
|
||||
while (g12a_cpu0_go == 0)
|
||||
wfe();
|
||||
|
||||
VERBOSE("BL31: CPU0 resumed.\n");
|
||||
|
||||
/*
|
||||
* Because setting CPU0's warm reset entrypoint through PSCI
|
||||
* mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
|
||||
* to work, jump to it manually.
|
||||
* In order to avoid an assert, MMU has to be disabled.
|
||||
*/
|
||||
disable_mmu_el3();
|
||||
((void(*)(void))g12a_sec_entrypoint)();
|
||||
}
|
||||
|
||||
dsbsy();
|
||||
g12a_pm_set_reset_addr(mpidr, 0);
|
||||
g12a_pm_reset(mpidr);
|
||||
|
||||
for (;;)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers and setup function.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t g12a_ops = {
|
||||
.pwr_domain_on = g12a_pwr_domain_on,
|
||||
.pwr_domain_on_finish = g12a_pwr_domain_on_finish,
|
||||
.pwr_domain_off = g12a_pwr_domain_off,
|
||||
.pwr_domain_pwr_down_wfi = g12a_pwr_domain_pwr_down_wfi,
|
||||
.system_off = g12a_system_off,
|
||||
.system_reset = g12a_system_reset
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
g12a_sec_entrypoint = sec_entrypoint;
|
||||
*psci_ops = &g12a_ops;
|
||||
g12a_cpu0_go = 0;
|
||||
return 0;
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include "../g12a_def.h"
|
||||
|
||||
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||
#define PLATFORM_LINKER_ARCH aarch64
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x1000)
|
||||
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
|
||||
#define AML_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for power-down. Valid for CPU and cluster power domains. */
|
||||
#define PLAT_LOCAL_STATE_OFF U(2)
|
||||
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/* Memory-related defines */
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
|
||||
#define MAX_MMAP_REGIONS 16
|
||||
#define MAX_XLAT_TABLES 8
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
AML_PLAT := plat/amlogic
|
||||
AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
|
||||
AML_PLAT_COMMON := ${AML_PLAT}/common
|
||||
|
||||
DOIMAGEPATH ?= tools/amlogic
|
||||
DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
|
||||
-I${AML_PLAT_SOC}/include \
|
||||
-I${AML_PLAT_COMMON}/include
|
||||
|
||||
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
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
drivers/amlogic/console/aarch64/meson_console.S \
|
||||
${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_pm.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_common.c \
|
||||
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
|
||||
${AML_PLAT_COMMON}/aml_efuse.c \
|
||||
${AML_PLAT_COMMON}/aml_mhu.c \
|
||||
${AML_PLAT_COMMON}/aml_scpi.c \
|
||||
${AML_PLAT_COMMON}/aml_sip_svc.c \
|
||||
${AML_PLAT_COMMON}/aml_thermal.c \
|
||||
${AML_PLAT_COMMON}/aml_topology.c \
|
||||
${AML_PLAT_COMMON}/aml_console.c \
|
||||
drivers/amlogic/crypto/sha_dma.c \
|
||||
${XLAT_TABLES_LIB_SRCS} \
|
||||
${GIC_SOURCES}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else
|
||||
TF_CFLAGS_aarch64 += -mtune=cortex-a53
|
||||
endif
|
||||
|
||||
# Build config flags
|
||||
# ------------------
|
||||
|
||||
# Enable all errata workarounds for Cortex-A53
|
||||
ERRATA_A53_855873 := 1
|
||||
ERRATA_A53_819472 := 1
|
||||
ERRATA_A53_824069 := 1
|
||||
ERRATA_A53_827319 := 1
|
||||
|
||||
WORKAROUND_CVE_2017_5715 := 0
|
||||
|
||||
# Have different sections for code and rodata
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# Use Coherent memory
|
||||
USE_COHERENT_MEM := 1
|
||||
|
||||
# Verify build config
|
||||
# -------------------
|
||||
|
||||
ifneq (${RESET_TO_BL31}, 0)
|
||||
$(error Error: ${PLAT} needs RESET_TO_BL31=0)
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error Error: AArch32 not supported on ${PLAT})
|
||||
endif
|
||||
|
||||
all: ${BUILD_PLAT}/bl31.img
|
||||
distclean realclean clean: cleanimage
|
||||
|
||||
cleanimage:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH} clean
|
||||
|
||||
${DOIMAGETOOL}:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH}
|
||||
|
||||
${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
|
||||
${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl33_image_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;
|
||||
|
||||
assert(type == NON_SECURE);
|
||||
|
||||
next_image_info = &bl33_image_ep_info;
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint. */
|
||||
if (next_image_info->pc != 0U) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-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.
|
||||
******************************************************************************/
|
||||
struct gxbb_bl31_param {
|
||||
param_header_t h;
|
||||
image_info_t *bl31_image_info;
|
||||
entry_point_info_t *bl32_ep_info;
|
||||
image_info_t *bl32_image_info;
|
||||
entry_point_info_t *bl33_ep_info;
|
||||
image_info_t *bl33_image_info;
|
||||
};
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
struct gxbb_bl31_param *from_bl2;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
aml_console_init();
|
||||
|
||||
/*
|
||||
* In debug builds, we pass a special value in 'arg1' to verify platform
|
||||
* parameters from BL2 to BL31. In release builds it's not used.
|
||||
*/
|
||||
assert(arg1 == AML_BL31_PLAT_PARAM_VAL);
|
||||
|
||||
/* Check that params passed from BL2 are not NULL. */
|
||||
from_bl2 = (struct gxbb_bl31_param *) arg0;
|
||||
|
||||
/* Check params passed from BL2 are not NULL. */
|
||||
assert(from_bl2 != NULL);
|
||||
assert(from_bl2->h.type == PARAM_BL31);
|
||||
assert(from_bl2->h.version >= VERSION_1);
|
||||
|
||||
/*
|
||||
* Copy BL33 entry point information. It is stored in Secure RAM, in
|
||||
* BL2's address space.
|
||||
*/
|
||||
bl33_image_ep_info = *from_bl2->bl33_ep_info;
|
||||
|
||||
if (bl33_image_ep_info.pc == 0U) {
|
||||
ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
aml_setup_page_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GICv2 driver setup information
|
||||
******************************************************************************/
|
||||
static const interrupt_prop_t gxbb_interrupt_props[] = {
|
||||
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
};
|
||||
|
||||
static const gicv2_driver_data_t gxbb_gic_data = {
|
||||
.gicd_base = AML_GICD_BASE,
|
||||
.gicc_base = AML_GICC_BASE,
|
||||
.interrupt_props = gxbb_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(gxbb_interrupt_props),
|
||||
};
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
aml_mhu_secure_init();
|
||||
|
||||
gicv2_driver_init(&gxbb_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
aml_thermal_unknown();
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/ep_info.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform memory map regions
|
||||
******************************************************************************/
|
||||
#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
|
||||
AML_NSDRAM0_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \
|
||||
AML_NSDRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
|
||||
AML_SEC_DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
|
||||
AML_SEC_DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
|
||||
AML_TZRAM_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
|
||||
AML_SEC_DEVICE2_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \
|
||||
AML_SEC_DEVICE3_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
static const mmap_region_t gxbb_mmap[] = {
|
||||
MAP_NSDRAM0,
|
||||
MAP_NSDRAM1,
|
||||
MAP_SEC_DEVICE0,
|
||||
MAP_SEC_DEVICE1,
|
||||
MAP_TZRAM,
|
||||
MAP_SEC_DEVICE2,
|
||||
MAP_SEC_DEVICE3,
|
||||
{0}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Per-image regions
|
||||
******************************************************************************/
|
||||
#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
|
||||
BL31_END - BL31_BASE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
|
||||
BL_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE)
|
||||
|
||||
#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the translation tables.
|
||||
******************************************************************************/
|
||||
void aml_setup_page_tables(void)
|
||||
{
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t gxbb_bl_mmap[] = {
|
||||
MAP_BL31,
|
||||
MAP_BL_CODE,
|
||||
MAP_BL_RO_DATA,
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_BL_COHERENT,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
mmap_add(gxbb_bl_mmap);
|
||||
|
||||
mmap_add(gxbb_mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that returns the system counter frequency
|
||||
******************************************************************************/
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = mmio_read_32(AML_SYS_CPU_CFG7);
|
||||
val &= 0xFDFFFFFF;
|
||||
mmio_write_32(AML_SYS_CPU_CFG7, val);
|
||||
|
||||
val = mmio_read_32(AML_AO_TIMESTAMP_CNTL);
|
||||
val &= 0xFFFFFE00;
|
||||
mmio_write_32(AML_AO_TIMESTAMP_CNTL, val);
|
||||
|
||||
return AML_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef GXBB_DEF_H
|
||||
#define GXBB_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* System oscillator
|
||||
******************************************************************************/
|
||||
#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory regions
|
||||
******************************************************************************/
|
||||
#define AML_NSDRAM0_BASE UL(0x01000000)
|
||||
#define AML_NSDRAM0_SIZE UL(0x0F000000)
|
||||
|
||||
#define AML_NSDRAM1_BASE UL(0x10000000)
|
||||
#define AML_NSDRAM1_SIZE UL(0x00100000)
|
||||
|
||||
#define BL31_BASE UL(0x10100000)
|
||||
#define BL31_SIZE UL(0x000C0000)
|
||||
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
|
||||
|
||||
/* Shared memory used for SMC services */
|
||||
#define AML_SHARE_MEM_INPUT_BASE UL(0x100FE000)
|
||||
#define AML_SHARE_MEM_OUTPUT_BASE UL(0x100FF000)
|
||||
|
||||
#define AML_SEC_DEVICE0_BASE UL(0xC0000000)
|
||||
#define AML_SEC_DEVICE0_SIZE UL(0x09000000)
|
||||
|
||||
#define AML_SEC_DEVICE1_BASE UL(0xD0040000)
|
||||
#define AML_SEC_DEVICE1_SIZE UL(0x00008000)
|
||||
|
||||
#define AML_TZRAM_BASE UL(0xD9000000)
|
||||
#define AML_TZRAM_SIZE UL(0x00014000)
|
||||
/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
|
||||
|
||||
/* Mailboxes */
|
||||
#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800)
|
||||
#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00)
|
||||
#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00)
|
||||
|
||||
#define AML_TZROM_BASE UL(0xD9040000)
|
||||
#define AML_TZROM_SIZE UL(0x00010000)
|
||||
|
||||
#define AML_SEC_DEVICE2_BASE UL(0xDA000000)
|
||||
#define AML_SEC_DEVICE2_SIZE UL(0x00200000)
|
||||
|
||||
#define AML_SEC_DEVICE3_BASE UL(0xDA800000)
|
||||
#define AML_SEC_DEVICE3_SIZE UL(0x00200000)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC-400 and interrupt handling related constants
|
||||
******************************************************************************/
|
||||
#define AML_GICD_BASE UL(0xC4301000)
|
||||
#define AML_GICC_BASE UL(0xC4302000)
|
||||
|
||||
#define IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define IRQ_SEC_SGI_0 8
|
||||
#define IRQ_SEC_SGI_1 9
|
||||
#define IRQ_SEC_SGI_2 10
|
||||
#define IRQ_SEC_SGI_3 11
|
||||
#define IRQ_SEC_SGI_4 12
|
||||
#define IRQ_SEC_SGI_5 13
|
||||
#define IRQ_SEC_SGI_6 14
|
||||
#define IRQ_SEC_SGI_7 15
|
||||
|
||||
/*******************************************************************************
|
||||
* UART definitions
|
||||
******************************************************************************/
|
||||
#define AML_UART0_AO_BASE UL(0xC81004C0)
|
||||
#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
|
||||
#define AML_UART_BAUDRATE U(115200)
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory-mapped I/O Registers
|
||||
******************************************************************************/
|
||||
#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4)
|
||||
|
||||
#define AML_SYS_CPU_CFG7 UL(0xC8834664)
|
||||
|
||||
#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C)
|
||||
|
||||
#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404)
|
||||
#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408)
|
||||
#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C)
|
||||
#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428)
|
||||
#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
|
||||
#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
|
||||
|
||||
#define AML_SHA_DMA_BASE UL(0xC883E000)
|
||||
#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
|
||||
#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
|
||||
|
||||
/*******************************************************************************
|
||||
* System Monitor Call IDs and arguments
|
||||
******************************************************************************/
|
||||
#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
|
||||
#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
|
||||
|
||||
#define AML_SM_EFUSE_READ U(0x82000030)
|
||||
#define AML_SM_EFUSE_USER_MAX U(0x82000033)
|
||||
|
||||
#define AML_SM_JTAG_ON U(0x82000040)
|
||||
#define AML_SM_JTAG_OFF U(0x82000041)
|
||||
#define AML_SM_GET_CHIP_ID U(0x82000044)
|
||||
|
||||
#define AML_JTAG_STATE_ON U(0)
|
||||
#define AML_JTAG_STATE_OFF U(1)
|
||||
|
||||
#define AML_JTAG_M3_AO U(0)
|
||||
#define AML_JTAG_M3_EE U(1)
|
||||
#define AML_JTAG_A53_AO U(2)
|
||||
#define AML_JTAG_A53_EE U(3)
|
||||
|
||||
#endif /* GXBB_DEF_H */
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <errno.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define SCPI_POWER_ON 0
|
||||
#define SCPI_POWER_RETENTION 1
|
||||
#define SCPI_POWER_OFF 3
|
||||
|
||||
#define SCPI_SYSTEM_SHUTDOWN 0
|
||||
#define SCPI_SYSTEM_REBOOT 1
|
||||
|
||||
static uintptr_t gxbb_sec_entrypoint;
|
||||
static volatile uint32_t gxbb_cpu0_go;
|
||||
|
||||
static void gxbb_program_mailbox(u_register_t mpidr, uint64_t value)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
|
||||
|
||||
mmio_write_64(cpu_mailbox_addr, value);
|
||||
flush_dcache_range(cpu_mailbox_addr, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
static void __dead2 gxbb_system_reset(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_RESET\n");
|
||||
|
||||
uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
|
||||
|
||||
NOTICE("BL31: Reboot reason: 0x%x\n", status);
|
||||
|
||||
status &= 0xFFFF0FF0;
|
||||
|
||||
console_flush();
|
||||
|
||||
mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
|
||||
|
||||
int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %u\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 gxbb_system_off(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_OFF\n");
|
||||
|
||||
unsigned int ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %u\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
gxbb_program_mailbox(read_mpidr_el1(), 0);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static int32_t gxbb_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
|
||||
|
||||
gxbb_cpu0_go = 1;
|
||||
flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
gxbb_program_mailbox(mpidr, gxbb_sec_entrypoint);
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
dmbsy();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void gxbb_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(read_mpidr_el1());
|
||||
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
gxbb_cpu0_go = 0;
|
||||
flush_dcache_range((uintptr_t)&gxbb_cpu0_go, sizeof(gxbb_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
}
|
||||
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
static void gxbb_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t addr = AML_PSCI_MAILBOX_BASE + 8 + (core << 4);
|
||||
|
||||
mmio_write_32(addr, 0xFFFFFFFF);
|
||||
flush_dcache_range(addr, sizeof(uint32_t));
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU)
|
||||
return;
|
||||
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
}
|
||||
|
||||
static void __dead2 gxbb_pwr_domain_pwr_down_wfi(const psci_power_state_t
|
||||
*target_state)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(read_mpidr_el1());
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: CPU0 entering wait loop...\n");
|
||||
|
||||
while (gxbb_cpu0_go == 0)
|
||||
wfe();
|
||||
|
||||
VERBOSE("BL31: CPU0 resumed.\n");
|
||||
|
||||
write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT);
|
||||
}
|
||||
|
||||
dsbsy();
|
||||
|
||||
for (;;)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers and setup function.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t gxbb_ops = {
|
||||
.pwr_domain_on = gxbb_pwr_domain_on,
|
||||
.pwr_domain_on_finish = gxbb_pwr_domain_on_finish,
|
||||
.pwr_domain_off = gxbb_pwr_domain_off,
|
||||
.pwr_domain_pwr_down_wfi = gxbb_pwr_domain_pwr_down_wfi,
|
||||
.system_off = gxbb_system_off,
|
||||
.system_reset = gxbb_system_reset,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
gxbb_sec_entrypoint = sec_entrypoint;
|
||||
*psci_ops = &gxbb_ops;
|
||||
gxbb_cpu0_go = 0;
|
||||
return 0;
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include "../gxbb_def.h"
|
||||
|
||||
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||
#define PLATFORM_LINKER_ARCH aarch64
|
||||
|
||||
/* Special value used to verify platform parameters from BL2 to BL31 */
|
||||
#define AML_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978)
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x1000)
|
||||
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
|
||||
#define AML_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for power-down. Valid for CPU and cluster power domains. */
|
||||
#define PLAT_LOCAL_STATE_OFF U(2)
|
||||
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/* Memory-related defines */
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
|
||||
#define MAX_MMAP_REGIONS 12
|
||||
#define MAX_XLAT_TABLES 5
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
#
|
||||
# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
AML_PLAT := plat/amlogic
|
||||
AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
|
||||
AML_PLAT_COMMON := ${AML_PLAT}/common
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
|
||||
-I${AML_PLAT_SOC}/include \
|
||||
-I${AML_PLAT_COMMON}/include
|
||||
|
||||
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
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
drivers/amlogic/console/aarch64/meson_console.S \
|
||||
${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_pm.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_common.c \
|
||||
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
|
||||
${AML_PLAT_COMMON}/aml_efuse.c \
|
||||
${AML_PLAT_COMMON}/aml_mhu.c \
|
||||
${AML_PLAT_COMMON}/aml_scpi.c \
|
||||
${AML_PLAT_COMMON}/aml_sip_svc.c \
|
||||
${AML_PLAT_COMMON}/aml_thermal.c \
|
||||
${AML_PLAT_COMMON}/aml_topology.c \
|
||||
${AML_PLAT_COMMON}/aml_console.c \
|
||||
${XLAT_TABLES_LIB_SRCS} \
|
||||
${GIC_SOURCES}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else
|
||||
TF_CFLAGS_aarch64 += -mtune=cortex-a53
|
||||
endif
|
||||
|
||||
# Build config flags
|
||||
# ------------------
|
||||
|
||||
# Enable all errata workarounds for Cortex-A53
|
||||
ERRATA_A53_826319 := 1
|
||||
ERRATA_A53_835769 := 1
|
||||
ERRATA_A53_836870 := 1
|
||||
ERRATA_A53_843419 := 1
|
||||
ERRATA_A53_855873 := 1
|
||||
|
||||
WORKAROUND_CVE_2017_5715 := 0
|
||||
|
||||
# Have different sections for code and rodata
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# Use Coherent memory
|
||||
USE_COHERENT_MEM := 1
|
||||
|
||||
# Verify build config
|
||||
# -------------------
|
||||
|
||||
ifneq (${RESET_TO_BL31}, 0)
|
||||
$(error Error: ${PLAT} needs RESET_TO_BL31=0)
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error Error: AArch32 not supported on ${PLAT})
|
||||
endif
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/interrupt_props.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_mmu_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
/*
|
||||
* Placeholder variables for copying the arguments that have been passed to
|
||||
* BL31 from BL2.
|
||||
*/
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
static image_info_t bl30_image_info;
|
||||
static image_info_t bl301_image_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;
|
||||
|
||||
assert(type == NON_SECURE);
|
||||
|
||||
next_image_info = &bl33_image_ep_info;
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint. */
|
||||
if (next_image_info->pc != 0U) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL31 early platform setup. Here is an opportunity to copy
|
||||
* parameters passed by the calling EL (S-EL1 in BL2 & S-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.
|
||||
******************************************************************************/
|
||||
struct gxl_bl31_param {
|
||||
param_header_t h;
|
||||
image_info_t *bl31_image_info;
|
||||
entry_point_info_t *bl32_ep_info;
|
||||
image_info_t *bl32_image_info;
|
||||
entry_point_info_t *bl33_ep_info;
|
||||
image_info_t *bl33_image_info;
|
||||
image_info_t *scp_image_info[];
|
||||
};
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
struct gxl_bl31_param *from_bl2;
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
aml_console_init();
|
||||
|
||||
/* Check that params passed from BL2 are not NULL. */
|
||||
from_bl2 = (struct gxl_bl31_param *) arg0;
|
||||
|
||||
/* Check params passed from BL2 are not NULL. */
|
||||
assert(from_bl2 != NULL);
|
||||
assert(from_bl2->h.type == PARAM_BL31);
|
||||
assert(from_bl2->h.version >= VERSION_1);
|
||||
|
||||
/*
|
||||
* Copy BL33 entry point information. It is stored in Secure RAM, in
|
||||
* BL2's address space.
|
||||
*/
|
||||
bl33_image_ep_info = *from_bl2->bl33_ep_info;
|
||||
|
||||
if (bl33_image_ep_info.pc == 0U) {
|
||||
ERROR("BL31: BL33 entrypoint not obtained from BL2\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
bl30_image_info = *from_bl2->scp_image_info[0];
|
||||
bl301_image_info = *from_bl2->scp_image_info[1];
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
aml_setup_page_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
static inline bool gxl_scp_ready(void)
|
||||
{
|
||||
return AML_AO_RTI_SCP_IS_READY(mmio_read_32(AML_AO_RTI_SCP_STAT));
|
||||
}
|
||||
|
||||
static inline void gxl_scp_boot(void)
|
||||
{
|
||||
aml_scpi_upload_scp_fw(bl30_image_info.image_base,
|
||||
bl30_image_info.image_size, 0);
|
||||
aml_scpi_upload_scp_fw(bl301_image_info.image_base,
|
||||
bl301_image_info.image_size, 1);
|
||||
while (!gxl_scp_ready())
|
||||
;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* GICv2 driver setup information
|
||||
******************************************************************************/
|
||||
static const interrupt_prop_t gxl_interrupt_props[] = {
|
||||
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
};
|
||||
|
||||
static const gicv2_driver_data_t gxl_gic_data = {
|
||||
.gicd_base = AML_GICD_BASE,
|
||||
.gicc_base = AML_GICC_BASE,
|
||||
.interrupt_props = gxl_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(gxl_interrupt_props),
|
||||
};
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
aml_mhu_secure_init();
|
||||
|
||||
gicv2_driver_init(&gxl_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
gxl_scp_boot();
|
||||
|
||||
aml_thermal_unknown();
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/ep_info.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform memory map regions
|
||||
******************************************************************************/
|
||||
#define MAP_NSDRAM0 MAP_REGION_FLAT(AML_NSDRAM0_BASE, \
|
||||
AML_NSDRAM0_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_NSDRAM1 MAP_REGION_FLAT(AML_NSDRAM1_BASE, \
|
||||
AML_NSDRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define MAP_SEC_DEVICE0 MAP_REGION_FLAT(AML_SEC_DEVICE0_BASE, \
|
||||
AML_SEC_DEVICE0_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE1 MAP_REGION_FLAT(AML_SEC_DEVICE1_BASE, \
|
||||
AML_SEC_DEVICE1_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_TZRAM MAP_REGION_FLAT(AML_TZRAM_BASE, \
|
||||
AML_TZRAM_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE2 MAP_REGION_FLAT(AML_SEC_DEVICE2_BASE, \
|
||||
AML_SEC_DEVICE2_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_SEC_DEVICE3 MAP_REGION_FLAT(AML_SEC_DEVICE3_BASE, \
|
||||
AML_SEC_DEVICE3_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
static const mmap_region_t gxl_mmap[] = {
|
||||
MAP_NSDRAM0,
|
||||
MAP_NSDRAM1,
|
||||
MAP_SEC_DEVICE0,
|
||||
MAP_SEC_DEVICE1,
|
||||
MAP_TZRAM,
|
||||
MAP_SEC_DEVICE2,
|
||||
MAP_SEC_DEVICE3,
|
||||
{0}
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* Per-image regions
|
||||
******************************************************************************/
|
||||
#define MAP_BL31 MAP_REGION_FLAT(BL31_BASE, \
|
||||
BL31_END - BL31_BASE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_BL_CODE MAP_REGION_FLAT(BL_CODE_BASE, \
|
||||
BL_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE)
|
||||
|
||||
#define MAP_BL_RO_DATA MAP_REGION_FLAT(BL_RO_DATA_BASE, \
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#define MAP_BL_COHERENT MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, \
|
||||
BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that sets up the translation tables.
|
||||
******************************************************************************/
|
||||
void aml_setup_page_tables(void)
|
||||
{
|
||||
#if IMAGE_BL31
|
||||
const mmap_region_t gxl_bl_mmap[] = {
|
||||
MAP_BL31,
|
||||
MAP_BL_CODE,
|
||||
MAP_BL_RO_DATA,
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_BL_COHERENT,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
mmap_add(gxl_bl_mmap);
|
||||
|
||||
mmap_add(gxl_mmap);
|
||||
|
||||
init_xlat_tables();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that returns the system counter frequency
|
||||
******************************************************************************/
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = mmio_read_32(AML_SYS_CPU_CFG7);
|
||||
val &= 0xFDFFFFFF;
|
||||
mmio_write_32(AML_SYS_CPU_CFG7, val);
|
||||
|
||||
val = mmio_read_32(AML_AO_TIMESTAMP_CNTL);
|
||||
val &= 0xFFFFFE00;
|
||||
mmio_write_32(AML_AO_TIMESTAMP_CNTL, val);
|
||||
|
||||
return AML_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef GXL_DEF_H
|
||||
#define GXL_DEF_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* System oscillator
|
||||
******************************************************************************/
|
||||
#define AML_OSC24M_CLK_IN_HZ ULL(24000000) /* 24 MHz */
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory regions
|
||||
******************************************************************************/
|
||||
#define AML_NSDRAM0_BASE UL(0x01000000)
|
||||
#define AML_NSDRAM0_SIZE UL(0x0F000000)
|
||||
|
||||
#define AML_NSDRAM1_BASE UL(0x10000000)
|
||||
#define AML_NSDRAM1_SIZE UL(0x00100000)
|
||||
|
||||
#define BL31_BASE UL(0x05100000)
|
||||
#define BL31_SIZE UL(0x000C0000)
|
||||
#define BL31_LIMIT (BL31_BASE + BL31_SIZE)
|
||||
|
||||
/* Shared memory used for SMC services */
|
||||
#define AML_SHARE_MEM_INPUT_BASE UL(0x050FE000)
|
||||
#define AML_SHARE_MEM_OUTPUT_BASE UL(0x050FF000)
|
||||
|
||||
#define AML_SEC_DEVICE0_BASE UL(0xC0000000)
|
||||
#define AML_SEC_DEVICE0_SIZE UL(0x09000000)
|
||||
|
||||
#define AML_SEC_DEVICE1_BASE UL(0xD0040000)
|
||||
#define AML_SEC_DEVICE1_SIZE UL(0x00008000)
|
||||
|
||||
#define AML_TZRAM_BASE UL(0xD9000000)
|
||||
#define AML_TZRAM_SIZE UL(0x00014000)
|
||||
/* Top 0xC000 bytes (up to 0xD9020000) used by BL2 */
|
||||
|
||||
/* Mailboxes */
|
||||
#define AML_MHU_SECURE_SCP_TO_AP_PAYLOAD UL(0xD9013800)
|
||||
#define AML_MHU_SECURE_AP_TO_SCP_PAYLOAD UL(0xD9013A00)
|
||||
#define AML_PSCI_MAILBOX_BASE UL(0xD9013F00)
|
||||
|
||||
// * [ 1K] 0xD901_3800 - 0xD901_3BFF Secure Mailbox (3)
|
||||
// * [ 1K] 0xD901_3400 - 0xD901_37FF High Mailbox (2) *
|
||||
// * [ 1K] 0xD901_3000 - 0xD901_33FF High Mailbox (1) *
|
||||
|
||||
#define AML_TZROM_BASE UL(0xD9040000)
|
||||
#define AML_TZROM_SIZE UL(0x00010000)
|
||||
|
||||
#define AML_SEC_DEVICE2_BASE UL(0xDA000000)
|
||||
#define AML_SEC_DEVICE2_SIZE UL(0x00200000)
|
||||
|
||||
#define AML_SEC_DEVICE3_BASE UL(0xDA800000)
|
||||
#define AML_SEC_DEVICE3_SIZE UL(0x00200000)
|
||||
|
||||
/*******************************************************************************
|
||||
* GIC-400 and interrupt handling related constants
|
||||
******************************************************************************/
|
||||
#define AML_GICD_BASE UL(0xC4301000)
|
||||
#define AML_GICC_BASE UL(0xC4302000)
|
||||
|
||||
#define IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define IRQ_SEC_SGI_0 8
|
||||
#define IRQ_SEC_SGI_1 9
|
||||
#define IRQ_SEC_SGI_2 10
|
||||
#define IRQ_SEC_SGI_3 11
|
||||
#define IRQ_SEC_SGI_4 12
|
||||
#define IRQ_SEC_SGI_5 13
|
||||
#define IRQ_SEC_SGI_6 14
|
||||
#define IRQ_SEC_SGI_7 15
|
||||
|
||||
/*******************************************************************************
|
||||
* UART definitions
|
||||
******************************************************************************/
|
||||
#define AML_UART0_AO_BASE UL(0xC81004C0)
|
||||
#define AML_UART0_AO_CLK_IN_HZ AML_OSC24M_CLK_IN_HZ
|
||||
#define AML_UART_BAUDRATE U(115200)
|
||||
|
||||
/*******************************************************************************
|
||||
* Memory-mapped I/O Registers
|
||||
******************************************************************************/
|
||||
#define AML_AO_TIMESTAMP_CNTL UL(0xC81000B4)
|
||||
|
||||
#define AML_SYS_CPU_CFG7 UL(0xC8834664)
|
||||
|
||||
#define AML_AO_RTI_STATUS_REG3 UL(0xDA10001C)
|
||||
#define AML_AO_RTI_SCP_STAT UL(0xDA10023C)
|
||||
#define AML_AO_RTI_SCP_READY_OFF U(0x14)
|
||||
#define AML_A0_RTI_SCP_READY_MASK U(3)
|
||||
#define AML_AO_RTI_SCP_IS_READY(v) \
|
||||
((((v) >> AML_AO_RTI_SCP_READY_OFF) & \
|
||||
AML_A0_RTI_SCP_READY_MASK) == AML_A0_RTI_SCP_READY_MASK)
|
||||
|
||||
#define AML_HIU_MAILBOX_SET_0 UL(0xDA83C404)
|
||||
#define AML_HIU_MAILBOX_STAT_0 UL(0xDA83C408)
|
||||
#define AML_HIU_MAILBOX_CLR_0 UL(0xDA83C40C)
|
||||
#define AML_HIU_MAILBOX_SET_3 UL(0xDA83C428)
|
||||
#define AML_HIU_MAILBOX_STAT_3 UL(0xDA83C42C)
|
||||
#define AML_HIU_MAILBOX_CLR_3 UL(0xDA83C430)
|
||||
|
||||
#define AML_SHA_DMA_BASE UL(0xC883E000)
|
||||
#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
|
||||
#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
|
||||
|
||||
/*******************************************************************************
|
||||
* System Monitor Call IDs and arguments
|
||||
******************************************************************************/
|
||||
#define AML_SM_GET_SHARE_MEM_INPUT_BASE U(0x82000020)
|
||||
#define AML_SM_GET_SHARE_MEM_OUTPUT_BASE U(0x82000021)
|
||||
|
||||
#define AML_SM_EFUSE_READ U(0x82000030)
|
||||
#define AML_SM_EFUSE_USER_MAX U(0x82000033)
|
||||
|
||||
#define AML_SM_JTAG_ON U(0x82000040)
|
||||
#define AML_SM_JTAG_OFF U(0x82000041)
|
||||
#define AML_SM_GET_CHIP_ID U(0x82000044)
|
||||
|
||||
#define AML_JTAG_STATE_ON U(0)
|
||||
#define AML_JTAG_STATE_OFF U(1)
|
||||
|
||||
#define AML_JTAG_M3_AO U(0)
|
||||
#define AML_JTAG_M3_EE U(1)
|
||||
#define AML_JTAG_A53_AO U(2)
|
||||
#define AML_JTAG_A53_EE U(3)
|
||||
|
||||
#endif /* GXL_DEF_H */
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <drivers/console.h>
|
||||
#include <errno.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#include "aml_private.h"
|
||||
|
||||
#define SCPI_POWER_ON 0
|
||||
#define SCPI_POWER_RETENTION 1
|
||||
#define SCPI_POWER_OFF 3
|
||||
|
||||
#define SCPI_SYSTEM_SHUTDOWN 0
|
||||
#define SCPI_SYSTEM_REBOOT 1
|
||||
|
||||
static uintptr_t gxl_sec_entrypoint;
|
||||
static volatile uint32_t gxl_cpu0_go;
|
||||
|
||||
static void gxl_pm_set_reset_addr(u_register_t mpidr, uint64_t value)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4);
|
||||
|
||||
mmio_write_64(cpu_mailbox_addr, value);
|
||||
}
|
||||
|
||||
static void gxl_pm_reset(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
uintptr_t cpu_mailbox_addr = AML_PSCI_MAILBOX_BASE + (core << 4) + 8;
|
||||
|
||||
mmio_write_32(cpu_mailbox_addr, 0);
|
||||
}
|
||||
|
||||
static void __dead2 gxl_system_reset(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_RESET\n");
|
||||
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
uint32_t status = mmio_read_32(AML_AO_RTI_STATUS_REG3);
|
||||
int ret;
|
||||
|
||||
NOTICE("BL31: Reboot reason: 0x%x\n", status);
|
||||
|
||||
status &= 0xFFFF0FF0;
|
||||
|
||||
console_flush();
|
||||
|
||||
mmio_write_32(AML_AO_RTI_STATUS_REG3, status);
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_REBOOT);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: SCP error: %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
gxl_pm_reset(mpidr);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_RESET: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 gxl_system_off(void)
|
||||
{
|
||||
INFO("BL31: PSCI_SYSTEM_OFF\n");
|
||||
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
int ret;
|
||||
|
||||
ret = aml_scpi_sys_power_state(SCPI_SYSTEM_SHUTDOWN);
|
||||
|
||||
if (ret != 0) {
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: SCP error %i\n", ret);
|
||||
panic();
|
||||
}
|
||||
|
||||
gxl_pm_set_reset_addr(mpidr, 0);
|
||||
gxl_pm_reset(mpidr);
|
||||
|
||||
wfi();
|
||||
|
||||
ERROR("BL31: PSCI_SYSTEM_OFF: Operation not handled\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static int32_t gxl_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: Releasing CPU0 from wait loop...\n");
|
||||
|
||||
gxl_cpu0_go = 1;
|
||||
flush_dcache_range((uintptr_t)&gxl_cpu0_go,
|
||||
sizeof(gxl_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
gxl_pm_set_reset_addr(mpidr, gxl_sec_entrypoint);
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_ON, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
dmbsy();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void gxl_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
unsigned int core = plat_calc_core_pos(read_mpidr_el1());
|
||||
|
||||
assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
|
||||
PLAT_LOCAL_STATE_OFF);
|
||||
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
gxl_cpu0_go = 0;
|
||||
flush_dcache_range((uintptr_t)&gxl_cpu0_go,
|
||||
sizeof(gxl_cpu0_go));
|
||||
dsb();
|
||||
isb();
|
||||
}
|
||||
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
static void gxl_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
gicv2_cpuif_disable();
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU)
|
||||
return;
|
||||
|
||||
aml_scpi_set_css_power_state(mpidr,
|
||||
SCPI_POWER_OFF, SCPI_POWER_ON, SCPI_POWER_ON);
|
||||
}
|
||||
|
||||
static void __dead2 gxl_pwr_domain_pwr_down_wfi(const psci_power_state_t
|
||||
*target_state)
|
||||
{
|
||||
u_register_t mpidr = read_mpidr_el1();
|
||||
unsigned int core = plat_calc_core_pos(mpidr);
|
||||
|
||||
/* CPU0 can't be turned OFF, emulate it with a WFE loop */
|
||||
if (core == AML_PRIMARY_CPU) {
|
||||
VERBOSE("BL31: CPU0 entering wait loop...\n");
|
||||
|
||||
while (gxl_cpu0_go == 0)
|
||||
wfe();
|
||||
|
||||
VERBOSE("BL31: CPU0 resumed.\n");
|
||||
|
||||
/*
|
||||
* Because setting CPU0's warm reset entrypoint through PSCI
|
||||
* mailbox and/or mmio mapped RVBAR (0xda834650) does not seem
|
||||
* to work, jump to it manually.
|
||||
* In order to avoid an assert, mmu has to be disabled.
|
||||
*/
|
||||
disable_mmu_el3();
|
||||
((void(*)(void))gxl_sec_entrypoint)();
|
||||
}
|
||||
|
||||
dsbsy();
|
||||
gxl_pm_set_reset_addr(mpidr, 0);
|
||||
gxl_pm_reset(mpidr);
|
||||
|
||||
for (;;)
|
||||
wfi();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handlers and setup function.
|
||||
******************************************************************************/
|
||||
static const plat_psci_ops_t gxl_ops = {
|
||||
.pwr_domain_on = gxl_pwr_domain_on,
|
||||
.pwr_domain_on_finish = gxl_pwr_domain_on_finish,
|
||||
.pwr_domain_off = gxl_pwr_domain_off,
|
||||
.pwr_domain_pwr_down_wfi = gxl_pwr_domain_pwr_down_wfi,
|
||||
.system_off = gxl_system_off,
|
||||
.system_reset = gxl_system_reset,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
gxl_sec_entrypoint = sec_entrypoint;
|
||||
*psci_ops = &gxl_ops;
|
||||
gxl_cpu0_go = 0;
|
||||
return 0;
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <arch.h>
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#include "../gxl_def.h"
|
||||
|
||||
#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
|
||||
#define PLATFORM_LINKER_ARCH aarch64
|
||||
|
||||
#define PLATFORM_STACK_SIZE UL(0x1000)
|
||||
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4)
|
||||
#define PLATFORM_CLUSTER_COUNT U(1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER
|
||||
#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT
|
||||
|
||||
#define AML_PRIMARY_CPU U(0)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
|
||||
#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_MAX_RET_STATE U(1)
|
||||
#define PLAT_MAX_OFF_STATE U(2)
|
||||
|
||||
/* Local power state for power domains in Run state. */
|
||||
#define PLAT_LOCAL_STATE_RUN U(0)
|
||||
/* Local power state for retention. Valid only for CPU power domains */
|
||||
#define PLAT_LOCAL_STATE_RET U(1)
|
||||
/* Local power state for power-down. Valid for CPU and cluster power domains. */
|
||||
#define PLAT_LOCAL_STATE_OFF U(2)
|
||||
|
||||
/*
|
||||
* Macros used to parse state information from State-ID if it is using the
|
||||
* recommended encoding for State-ID.
|
||||
*/
|
||||
#define PLAT_LOCAL_PSTATE_WIDTH U(4)
|
||||
#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1)
|
||||
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_SHIFT U(6)
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/* Memory-related defines */
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32)
|
||||
|
||||
#define MAX_MMAP_REGIONS 12
|
||||
#define MAX_XLAT_TABLES 6
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,91 @@
|
||||
#
|
||||
# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
AML_PLAT := plat/amlogic
|
||||
AML_PLAT_SOC := ${AML_PLAT}/${PLAT}
|
||||
AML_PLAT_COMMON := ${AML_PLAT}/common
|
||||
|
||||
DOIMAGEPATH ?= tools/amlogic
|
||||
DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/drivers/amlogic/ \
|
||||
-I${AML_PLAT_SOC}/include \
|
||||
-I${AML_PLAT_COMMON}/include
|
||||
|
||||
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
|
||||
|
||||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
drivers/amlogic/console/aarch64/meson_console.S \
|
||||
${AML_PLAT_SOC}/${PLAT}_bl31_setup.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_pm.c \
|
||||
${AML_PLAT_SOC}/${PLAT}_common.c \
|
||||
${AML_PLAT_COMMON}/aarch64/aml_helpers.S \
|
||||
${AML_PLAT_COMMON}/aml_efuse.c \
|
||||
${AML_PLAT_COMMON}/aml_mhu.c \
|
||||
${AML_PLAT_COMMON}/aml_scpi.c \
|
||||
${AML_PLAT_COMMON}/aml_sip_svc.c \
|
||||
${AML_PLAT_COMMON}/aml_thermal.c \
|
||||
${AML_PLAT_COMMON}/aml_topology.c \
|
||||
${AML_PLAT_COMMON}/aml_console.c \
|
||||
drivers/amlogic/crypto/sha_dma.c \
|
||||
${XLAT_TABLES_LIB_SRCS} \
|
||||
${GIC_SOURCES}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
ifeq ($(notdir $(CC)),armclang)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else ifneq ($(findstring clang,$(notdir $(CC))),)
|
||||
TF_CFLAGS_aarch64 += -mcpu=cortex-a53
|
||||
else
|
||||
TF_CFLAGS_aarch64 += -mtune=cortex-a53
|
||||
endif
|
||||
|
||||
# Build config flags
|
||||
# ------------------
|
||||
|
||||
# Enable all errata workarounds for Cortex-A53
|
||||
ERRATA_A53_855873 := 1
|
||||
ERRATA_A53_819472 := 1
|
||||
ERRATA_A53_824069 := 1
|
||||
ERRATA_A53_827319 := 1
|
||||
|
||||
WORKAROUND_CVE_2017_5715 := 0
|
||||
|
||||
# Have different sections for code and rodata
|
||||
SEPARATE_CODE_AND_RODATA := 1
|
||||
|
||||
# Use Coherent memory
|
||||
USE_COHERENT_MEM := 1
|
||||
|
||||
# Verify build config
|
||||
# -------------------
|
||||
|
||||
ifneq (${RESET_TO_BL31}, 0)
|
||||
$(error Error: ${PLAT} needs RESET_TO_BL31=0)
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error Error: AArch32 not supported on ${PLAT})
|
||||
endif
|
||||
|
||||
all: ${BUILD_PLAT}/bl31.img
|
||||
distclean realclean clean: cleanimage
|
||||
|
||||
cleanimage:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH} clean
|
||||
|
||||
${DOIMAGETOOL}:
|
||||
${Q}${MAKE} -C ${DOIMAGEPATH}
|
||||
|
||||
${BUILD_PLAT}/bl31.img: ${BUILD_PLAT}/bl31.bin ${DOIMAGETOOL}
|
||||
${DOIMAGETOOL} ${BUILD_PLAT}/bl31.bin ${BUILD_PLAT}/bl31.img
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
******************************************************************************/
|
||||
void bl1_early_platform_setup(void)
|
||||
{
|
||||
arm_bl1_early_platform_setup();
|
||||
}
|
||||
|
||||
void bl1_platform_setup(void)
|
||||
{
|
||||
arm_bl1_platform_setup();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
|
||||
}
|
||||
|
||||
void bl2_platform_setup(void)
|
||||
{
|
||||
arm_bl2_platform_setup();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <plat/arm/common/arm_config.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
#define MAP_PERIPHBASE MAP_REGION_FLAT(PERIPHBASE,\
|
||||
PERIPH_SIZE,\
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define MAP_A5_PERIPHERALS MAP_REGION_FLAT(A5_PERIPHERALS_BASE,\
|
||||
A5_PERIPHERALS_SIZE,\
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#ifdef IMAGE_BL1
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
MAP_BOOT_RW,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL2
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
MAP_BOOT_RW,
|
||||
ARM_MAP_NS_DRAM1,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
#ifdef IMAGE_BL32
|
||||
const mmap_region_t plat_arm_mmap[] = {
|
||||
ARM_MAP_SHARED_RAM,
|
||||
MAP_PERIPHBASE,
|
||||
MAP_A5_PERIPHERALS,
|
||||
{0}
|
||||
};
|
||||
#endif
|
||||
|
||||
ARM_CASSERT_MMAP
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return A5DS_TIMER_BASE_FREQUENCY;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* a5ds error handler
|
||||
*/
|
||||
void __dead2 plat_arm_error_handler(int err)
|
||||
{
|
||||
while (true) {
|
||||
wfi();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/psci/psci.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform handler called when a power domain is about to be turned on. The
|
||||
* mpidr determines the CPU to be turned on.
|
||||
******************************************************************************/
|
||||
static int a5ds_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
unsigned int pos = plat_core_pos_by_mpidr(mpidr);
|
||||
uint64_t *hold_base = (uint64_t *)A5DS_HOLD_BASE;
|
||||
|
||||
hold_base[pos] = A5DS_HOLD_STATE_GO;
|
||||
dsbish();
|
||||
sev();
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform 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 a5ds_pwr_domain_on_finish(const psci_power_state_t *target_state)
|
||||
{
|
||||
/* TODO: This setup is needed only after a cold boot*/
|
||||
gicv2_pcpu_distif_init();
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
gicv2_cpuif_enable();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Platform 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.
|
||||
* a5ds only has always-on power domain and there is no power control present.
|
||||
******************************************************************************/
|
||||
void a5ds_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
ERROR("CPU_OFF not supported on this platform\n");
|
||||
assert(false);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Export the platform handlers via a5ds_psci_pm_ops. The ARM Standard
|
||||
* platform layer will take care of registering the handlers with PSCI.
|
||||
******************************************************************************/
|
||||
plat_psci_ops_t a5ds_psci_pm_ops = {
|
||||
/* dummy struct */
|
||||
.validate_ns_entrypoint = NULL,
|
||||
.pwr_domain_on = a5ds_pwr_domain_on,
|
||||
.pwr_domain_on_finish = a5ds_pwr_domain_on_finish,
|
||||
.pwr_domain_off = a5ds_pwr_domain_off
|
||||
};
|
||||
|
||||
int __init plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
uintptr_t *mailbox = (void *)A5DS_TRUSTED_MAILBOX_BASE;
|
||||
*mailbox = sec_entrypoint;
|
||||
|
||||
*psci_ops = &a5ds_psci_pm_ops;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef A5DS_PRIVATE_H
|
||||
#define A5DS_PRIVATE_H
|
||||
|
||||
/*******************************************************************************
|
||||
* Function and variable prototypes
|
||||
******************************************************************************/
|
||||
void a5ds_config_setup(void);
|
||||
|
||||
#endif /* A5DS_PRIVATE_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
/*
|
||||
* We assume that all security programming is done by the primary core.
|
||||
*/
|
||||
void plat_arm_security_setup(void)
|
||||
{
|
||||
/*
|
||||
* The platform currently does not have any security setup.
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* The A5DS power domain tree descriptor */
|
||||
static const unsigned char a5ds_power_domain_tree_desc[] = {
|
||||
1,
|
||||
/* No of children for the root node */
|
||||
A5DS_CLUSTER_COUNT,
|
||||
/* No of children for the first cluster node */
|
||||
A5DS_CORE_COUNT,
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* This function returns the topology according to A5DS_CLUSTER_COUNT.
|
||||
******************************************************************************/
|
||||
const unsigned char *plat_get_power_domain_tree_desc(void)
|
||||
{
|
||||
return a5ds_power_domain_tree_desc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Get core position using mpidr
|
||||
******************************************************************************/
|
||||
int plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
{
|
||||
unsigned int cluster_id, cpu_id;
|
||||
|
||||
mpidr &= MPIDR_AFFINITY_MASK;
|
||||
|
||||
if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK))
|
||||
return -1;
|
||||
|
||||
cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK;
|
||||
|
||||
if (cluster_id >= A5DS_CLUSTER_COUNT)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Validate cpu_id by checking whether it represents a CPU in
|
||||
* one of the two clusters present on the platform.
|
||||
*/
|
||||
if (cpu_id >= A5DS_MAX_CPUS_PER_CLUSTER)
|
||||
return -1;
|
||||
|
||||
return (cpu_id + (cluster_id * 4));
|
||||
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_is_my_cpu_primary
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* 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
|
||||
/* Calculate address of our hold entry */
|
||||
bl plat_my_core_pos
|
||||
lsl r0, r0, #A5DS_HOLD_ENTRY_SHIFT
|
||||
mov_imm r2, A5DS_HOLD_BASE
|
||||
/* Clear the value stored in the hold address for the specific core */
|
||||
mov_imm r3, A5DS_HOLD_STATE_WAIT
|
||||
str r3, [r2, r0]
|
||||
dmb ish
|
||||
|
||||
/* Wait until we have a go */
|
||||
poll_mailbox:
|
||||
ldr r1, [r2, r0]
|
||||
cmp r1, #A5DS_HOLD_STATE_WAIT
|
||||
beq 1f
|
||||
mov_imm r0, A5DS_TRUSTED_MAILBOX_BASE
|
||||
ldr r1, [r0]
|
||||
bx r1
|
||||
1:
|
||||
wfe
|
||||
b poll_mailbox
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned long plat_get_my_entrypoint (void);
|
||||
*
|
||||
* Main job of this routine is to distinguish between a cold and warm
|
||||
* boot.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
/* TODO support warm boot */
|
||||
/* Cold reset */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary
|
||||
* cpu.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
ldcopr r0, MPIDR
|
||||
ldr r1, =MPIDR_AFFINITY_MASK
|
||||
and r0, r1
|
||||
cmp r0, #0
|
||||
moveq r0, #1
|
||||
movne r0, #0
|
||||
bx lr
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Loads MPIDR in r0 and calls plat_arm_calc_core_pos
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
ldcopr r0, MPIDR
|
||||
b plat_arm_calc_core_pos
|
||||
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* unsigned int plat_arm_calc_core_pos(u_register_t mpidr)
|
||||
*
|
||||
* Function to calculate the core position on A5DS.
|
||||
*
|
||||
* (ClusterId * A5DS_MAX_CPUS_PER_CLUSTER * A5DS_MAX_PE_PER_CPU) +
|
||||
* (CPUId * A5DS_MAX_PE_PER_CPU) +
|
||||
* ThreadId
|
||||
*
|
||||
* which can be simplified as:
|
||||
*
|
||||
* ((ClusterId * A5DS_MAX_CPUS_PER_CLUSTER + CPUId) * A5DS_MAX_PE_PER_CPU)
|
||||
* + ThreadId
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
func plat_arm_calc_core_pos
|
||||
mov r3, r0
|
||||
|
||||
/*
|
||||
* Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
|
||||
* look as if in a multi-threaded implementation
|
||||
*/
|
||||
tst r0, #MPIDR_MT_MASK
|
||||
lsleq r3, r0, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
/* Compute linear position */
|
||||
mov r3, #A5DS_MAX_CPUS_PER_CLUSTER
|
||||
mla r1, r2, r3, r1
|
||||
mov r3, #A5DS_MAX_PE_PER_CPU
|
||||
mla r0, r1, r3, r0
|
||||
|
||||
bx lr
|
||||
endfunc plat_arm_calc_core_pos
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
dtb-registry {
|
||||
compatible = "fconf,dyn_cfg-dtb_registry";
|
||||
|
||||
tb_fw-config {
|
||||
load-address = <0x0 0x2001300>;
|
||||
max-size = <0x200>;
|
||||
id = <TB_FW_CONFIG_ID>;
|
||||
};
|
||||
|
||||
hw-config {
|
||||
load-address = <0x0 0x83000000>;
|
||||
max-size = <0x01000000>;
|
||||
id = <HW_CONFIG_ID>;
|
||||
};
|
||||
};
|
||||
};
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
tb_fw-config {
|
||||
compatible = "arm,tb_fw";
|
||||
|
||||
/* Disable authentication for development */
|
||||
disable_auth = <0x0>;
|
||||
};
|
||||
};
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <plat/arm/board/common/v2m_def.h>
|
||||
#include <plat/arm/common/smccc_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* Memory location options for TSP */
|
||||
#define ARM_DRAM_ID 2
|
||||
|
||||
#define ARM_DRAM1_BASE UL(0x80000000)
|
||||
#define ARM_DRAM1_SIZE UL(0x80000000)
|
||||
#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
|
||||
ARM_DRAM1_SIZE - 1)
|
||||
|
||||
#define SRAM_BASE 0x2000000
|
||||
#define SRAM_SIZE 0x200000
|
||||
|
||||
/* The first 4KB of NS DRAM1 are used as shared memory */
|
||||
#define A5DS_SHARED_RAM_BASE SRAM_BASE
|
||||
#define A5DS_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
|
||||
|
||||
/* The next 252 kB of NS DRAM is used to load the BL images */
|
||||
#define ARM_BL_RAM_BASE (A5DS_SHARED_RAM_BASE + \
|
||||
A5DS_SHARED_RAM_SIZE)
|
||||
#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \
|
||||
A5DS_SHARED_RAM_SIZE)
|
||||
|
||||
#define PERIPHBASE 0x1a000000
|
||||
#define PERIPH_SIZE 0x00240000
|
||||
#define A5_PERIPHERALS_BASE 0x1c000000
|
||||
#define A5_PERIPHERALS_SIZE 0x10000
|
||||
|
||||
#define ARM_CACHE_WRITEBACK_SHIFT 5
|
||||
|
||||
#define ARM_IRQ_SEC_PHY_TIMER 29
|
||||
|
||||
#define ARM_IRQ_SEC_SGI_0 8
|
||||
#define ARM_IRQ_SEC_SGI_1 9
|
||||
#define ARM_IRQ_SEC_SGI_2 10
|
||||
#define ARM_IRQ_SEC_SGI_3 11
|
||||
#define ARM_IRQ_SEC_SGI_4 12
|
||||
#define ARM_IRQ_SEC_SGI_5 13
|
||||
#define ARM_IRQ_SEC_SGI_6 14
|
||||
#define ARM_IRQ_SEC_SGI_7 15
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define ARM_G1S_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE), \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define ARM_G0_IRQ_PROPS(grp) \
|
||||
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_EDGE)
|
||||
|
||||
#define A5DS_IRQ_TZ_WDOG 56
|
||||
#define A5DS_IRQ_SEC_SYS_TIMER 57
|
||||
|
||||
/* Default cluster count for A5DS */
|
||||
#define A5DS_CLUSTER_COUNT U(1)
|
||||
|
||||
/* Default number of CPUs per cluster on A5DS */
|
||||
#define A5DS_MAX_CPUS_PER_CLUSTER U(4)
|
||||
|
||||
/* Default number of threads per CPU on A5DS */
|
||||
#define A5DS_MAX_PE_PER_CPU U(1)
|
||||
|
||||
#define A5DS_CORE_COUNT U(4)
|
||||
|
||||
#define A5DS_PRIMARY_CPU 0x0
|
||||
|
||||
#define BOOT_BASE ARM_DRAM1_BASE
|
||||
#define BOOT_SIZE UL(0x2800000)
|
||||
|
||||
#define ARM_NS_DRAM1_BASE (ARM_DRAM1_BASE + BOOT_SIZE)
|
||||
/*
|
||||
* The last 2MB is meant to be NOLOAD and will not be zero
|
||||
* initialized.
|
||||
*/
|
||||
#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \
|
||||
BOOT_SIZE - \
|
||||
0x00200000)
|
||||
|
||||
#define MAP_BOOT_RW MAP_REGION_FLAT( \
|
||||
BOOT_BASE, \
|
||||
BOOT_SIZE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \
|
||||
A5DS_SHARED_RAM_BASE, \
|
||||
A5DS_SHARED_RAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \
|
||||
ARM_NS_DRAM1_BASE, \
|
||||
ARM_NS_DRAM1_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
#define ARM_MAP_SRAM MAP_REGION_FLAT( \
|
||||
SRAM_BASE, \
|
||||
SRAM_SIZE, \
|
||||
MT_MEMORY | MT_RW | MT_NS)
|
||||
|
||||
/*
|
||||
* Mapping for the BL1 RW region. This mapping is needed by BL2 in order to
|
||||
* share the Mbed TLS heap. Since the heap is allocated inside BL1, it resides
|
||||
* in the BL1 RW region. Hence, BL2 needs access to the BL1 RW region in order
|
||||
* to be able to access the heap.
|
||||
*/
|
||||
|
||||
#define ARM_MAP_BL_RO MAP_REGION_FLAT(\
|
||||
BL_CODE_BASE,\
|
||||
BL_CODE_END - BL_CODE_BASE,\
|
||||
MT_CODE | MT_SECURE),\
|
||||
MAP_REGION_FLAT(\
|
||||
BL_RO_DATA_BASE,\
|
||||
BL_RO_DATA_END\
|
||||
- BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
|
||||
#if USE_COHERENT_MEM
|
||||
#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT(\
|
||||
BL_COHERENT_RAM_BASE,\
|
||||
BL_COHERENT_RAM_END \
|
||||
- BL_COHERENT_RAM_BASE, \
|
||||
MT_DEVICE | MT_RW | MT_SECURE)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Map the region for device tree configuration with read and write permissions
|
||||
*/
|
||||
#define ARM_MAP_BL_CONFIG_REGION MAP_REGION_FLAT(ARM_BL_RAM_BASE, \
|
||||
(ARM_FW_CONFIGS_LIMIT \
|
||||
- ARM_BL_RAM_BASE), \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
|
||||
/*
|
||||
* The max number of regions like RO(code), coherent and data required by
|
||||
* different BL stages which need to be mapped in the MMU.
|
||||
*/
|
||||
#define ARM_BL_REGIONS 6
|
||||
|
||||
#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \
|
||||
ARM_BL_REGIONS)
|
||||
|
||||
/* Memory mapped Generic timer interfaces */
|
||||
#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
|
||||
|
||||
#define ARM_CONSOLE_BAUDRATE 115200
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
/*
|
||||
* This macro defines the deepest retention state possible. A higher state
|
||||
* id will represent an invalid or a power down state.
|
||||
*/
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
|
||||
/*
|
||||
* This macro defines the deepest power down states possible. Any state ID
|
||||
* higher than this is invalid.
|
||||
*/
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
/*
|
||||
* Some data must be 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.
|
||||
*/
|
||||
#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
/*
|
||||
* To enable FW_CONFIG to be loaded by BL1, define the corresponding base
|
||||
* and limit. Leave enough space of BL2 meminfo.
|
||||
*/
|
||||
#define ARM_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t))
|
||||
#define ARM_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE)
|
||||
|
||||
/*
|
||||
* Define limit of firmware configuration memory:
|
||||
* ARM_FW_CONFIG + ARM_BL2_MEM_DESC memory
|
||||
*/
|
||||
#define ARM_FW_CONFIGS_LIMIT (ARM_BL_RAM_BASE + (PAGE_SIZE * 2))
|
||||
|
||||
/*******************************************************************************
|
||||
* BL1 specific defines.
|
||||
* BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of
|
||||
* addresses.
|
||||
******************************************************************************/
|
||||
#define BL1_RO_BASE 0x00000000
|
||||
#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE
|
||||
/*
|
||||
* Put BL1 RW at the top of the memory allocated for BL images in NS DRAM.
|
||||
*/
|
||||
#define BL1_RW_BASE (ARM_BL_RAM_BASE + \
|
||||
ARM_BL_RAM_SIZE - \
|
||||
(PLAT_ARM_MAX_BL1_RW_SIZE))
|
||||
#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \
|
||||
(ARM_BL_RAM_SIZE))
|
||||
/*******************************************************************************
|
||||
* BL2 specific defines.
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* Put BL2 just below BL1.
|
||||
*/
|
||||
#define BL2_BASE (BL1_RW_BASE - A5DS_MAX_BL2_SIZE)
|
||||
#define BL2_LIMIT BL1_RW_BASE
|
||||
|
||||
/* Put BL32 below BL2 in NS DRAM.*/
|
||||
#define ARM_BL2_MEM_DESC_BASE ARM_FW_CONFIG_LIMIT
|
||||
#define ARM_BL2_MEM_DESC_LIMIT (ARM_BL2_MEM_DESC_BASE \
|
||||
+ (PAGE_SIZE / 2U))
|
||||
|
||||
#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
|
||||
- PLAT_ARM_MAX_BL32_SIZE)
|
||||
#define BL32_PROGBITS_LIMIT BL2_BASE
|
||||
#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
|
||||
|
||||
/* Required platform porting definitions */
|
||||
#define PLATFORM_CORE_COUNT A5DS_CORE_COUNT
|
||||
#define PLAT_NUM_PWR_DOMAINS (A5DS_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT) + U(1)
|
||||
|
||||
#define PLAT_MAX_PWR_LVL 2
|
||||
|
||||
/*
|
||||
* Other platform porting definitions are provided by included headers
|
||||
*/
|
||||
|
||||
/*
|
||||
* Required ARM standard platform porting definitions
|
||||
*/
|
||||
|
||||
#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */
|
||||
|
||||
#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000
|
||||
#define PLAT_ARM_TRUSTED_ROM_SIZE 0x10000 /* 64KB */
|
||||
|
||||
#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000)
|
||||
|
||||
/*
|
||||
* Load address of BL33 for this platform port
|
||||
*/
|
||||
#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000))
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the
|
||||
* plat_arm_mmap array defined for each BL stage.
|
||||
*/
|
||||
#if defined(IMAGE_BL32)
|
||||
# define PLAT_ARM_MMAP_ENTRIES 8
|
||||
# define MAX_XLAT_TABLES 6
|
||||
#else
|
||||
# define PLAT_ARM_MMAP_ENTRIES 12
|
||||
# define MAX_XLAT_TABLES 6
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size
|
||||
* plus a little space for growth.
|
||||
*/
|
||||
#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000
|
||||
|
||||
/*
|
||||
* A5DS_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a
|
||||
* little space for growth.
|
||||
*/
|
||||
#define A5DS_MAX_BL2_SIZE 0x11000
|
||||
|
||||
/*
|
||||
* Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
|
||||
* calculated using the current SP_MIN PROGBITS debug size plus the sizes of
|
||||
* BL2 and BL1-RW
|
||||
*/
|
||||
#define PLAT_ARM_MAX_BL32_SIZE 0x3B000
|
||||
/*
|
||||
* 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 0x440
|
||||
#endif
|
||||
|
||||
#define MAX_IO_DEVICES 3
|
||||
#define MAX_IO_HANDLES 4
|
||||
|
||||
/* Reserve the last block of flash for PSCI MEM PROTECT flag */
|
||||
#define PLAT_ARM_FLASH_IMAGE_BASE BOOT_BASE
|
||||
#define PLAT_ARM_FLASH_IMAGE_MAX_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
|
||||
|
||||
#define PLAT_ARM_NVM_BASE BOOT_BASE
|
||||
#define PLAT_ARM_NVM_SIZE (BOOT_SIZE - V2M_FLASH_BLOCK_SIZE)
|
||||
|
||||
/*
|
||||
* PL011 related constants
|
||||
*/
|
||||
#define PLAT_ARM_BOOT_UART_BASE 0x1A200000
|
||||
#define PLAT_ARM_BOOT_UART_CLK_IN_HZ UL(7500000)
|
||||
|
||||
#define PLAT_ARM_RUN_UART_BASE 0x1A210000
|
||||
#define PLAT_ARM_RUN_UART_CLK_IN_HZ UL(7500000)
|
||||
|
||||
#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE
|
||||
#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ
|
||||
|
||||
#define A5DS_TIMER_BASE_FREQUENCY UL(7500000)
|
||||
|
||||
/* System timer related constants */
|
||||
#define PLAT_ARM_NSTIMER_FRAME_ID 1
|
||||
|
||||
/* Mailbox base address */
|
||||
#define A5DS_TRUSTED_MAILBOX_BASE A5DS_SHARED_RAM_BASE
|
||||
#define A5DS_TRUSTED_MAILBOX_SIZE (8 + A5DS_HOLD_SIZE)
|
||||
#define A5DS_HOLD_BASE (A5DS_TRUSTED_MAILBOX_BASE + 8)
|
||||
#define A5DS_HOLD_SIZE (PLATFORM_CORE_COUNT * \
|
||||
A5DS_HOLD_ENTRY_SIZE)
|
||||
#define A5DS_HOLD_ENTRY_SHIFT 3
|
||||
#define A5DS_HOLD_ENTRY_SIZE (1 << A5DS_HOLD_ENTRY_SHIFT)
|
||||
#define A5DS_HOLD_STATE_WAIT 0
|
||||
#define A5DS_HOLD_STATE_GO 1
|
||||
|
||||
/* Snoop Control Unit base address */
|
||||
#define A5DS_SCU_BASE 0x1C000000
|
||||
|
||||
/*
|
||||
* GIC related constants to cater for GICv2
|
||||
*/
|
||||
#define PLAT_ARM_GICD_BASE 0x1C001000
|
||||
#define PLAT_ARM_GICC_BASE 0x1C000100
|
||||
|
||||
/*
|
||||
* Define a list of Group 1 Secure and Group 0 interrupts as per GICv3
|
||||
* terminology. On a GICv2 system or mode, the lists will be merged and treated
|
||||
* as Group 0 interrupts.
|
||||
*/
|
||||
#define PLAT_ARM_G1S_IRQ_PROPS(grp) \
|
||||
ARM_G1S_IRQ_PROPS(grp), \
|
||||
INTR_PROP_DESC(A5DS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL), \
|
||||
INTR_PROP_DESC(A5DS_IRQ_SEC_SYS_TIMER,\
|
||||
GIC_HIGHEST_SEC_PRIORITY, (grp), \
|
||||
GIC_INTR_CFG_LEVEL)
|
||||
|
||||
#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
@@ -0,0 +1,111 @@
|
||||
#
|
||||
# Copyright (c) 2019-2021, Arm Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Firmware Configuration Framework sources
|
||||
include common/fdt_wrappers.mk
|
||||
include lib/fconf/fconf.mk
|
||||
|
||||
BL1_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
|
||||
BL2_SOURCES += ${FCONF_SOURCES} ${FCONF_DYN_SOURCES}
|
||||
|
||||
# Add `libfdt` and Arm common helpers required for Dynamic Config
|
||||
include lib/libfdt/libfdt.mk
|
||||
|
||||
DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \
|
||||
plat/arm/common/arm_dyn_cfg_helpers.c
|
||||
|
||||
DYN_CFG_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
# Include GICv2 driver files
|
||||
include drivers/arm/gic/v2/gicv2.mk
|
||||
|
||||
A5DS_GIC_SOURCES := ${GICV2_SOURCES} \
|
||||
plat/common/plat_gicv2.c \
|
||||
plat/arm/common/arm_gicv2.c
|
||||
|
||||
A5DS_SECURITY_SOURCES := plat/arm/board/a5ds/a5ds_security.c
|
||||
|
||||
PLAT_INCLUDES := -Iplat/arm/board/a5ds/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/${ARCH}/pl011_console.S \
|
||||
plat/arm/board/a5ds/a5ds_common.c \
|
||||
plat/arm/common/${ARCH}/arm_helpers.S \
|
||||
plat/arm/common/arm_common.c \
|
||||
plat/arm/common/arm_console.c \
|
||||
plat/arm/board/common/${ARCH}/board_arm_helpers.S
|
||||
|
||||
A5DS_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S
|
||||
|
||||
BL1_SOURCES += drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
plat/arm/common/arm_bl1_setup.c \
|
||||
plat/arm/common/arm_err.c \
|
||||
plat/arm/board/a5ds/a5ds_err.c \
|
||||
plat/arm/common/arm_io_storage.c \
|
||||
plat/arm/common/fconf/arm_fconf_io.c \
|
||||
plat/arm/board/a5ds/${ARCH}/a5ds_helpers.S \
|
||||
plat/arm/board/a5ds/a5ds_bl1_setup.c \
|
||||
lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
${A5DS_CPU_LIBS} \
|
||||
${DYN_CFG_SOURCES}
|
||||
|
||||
BL2_SOURCES += lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
drivers/delay_timer/delay_timer.c \
|
||||
drivers/delay_timer/generic_delay_timer.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
drivers/io/io_fip.c \
|
||||
drivers/io/io_memmap.c \
|
||||
drivers/io/io_storage.c \
|
||||
plat/arm/board/a5ds/a5ds_bl2_setup.c \
|
||||
plat/arm/common/arm_bl2_setup.c \
|
||||
plat/arm/common/arm_err.c \
|
||||
plat/arm/board/a5ds/a5ds_err.c \
|
||||
plat/arm/common/arm_io_storage.c \
|
||||
plat/arm/common/fconf/arm_fconf_io.c \
|
||||
plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \
|
||||
plat/arm/common/arm_image_load.c \
|
||||
common/desc_image_load.c \
|
||||
${DYN_CFG_SOURCES} \
|
||||
${A5DS_SECURITY_SOURCES}
|
||||
|
||||
# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env)
|
||||
ifdef UNIX_MK
|
||||
|
||||
FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_fw_config.dtb
|
||||
TB_FW_CONFIG := ${BUILD_PLAT}/fdts/a5ds_tb_fw_config.dtb
|
||||
|
||||
# Add the TB_FW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${TB_FW_CONFIG},--tb-fw-config,${TB_FW_CONFIG}))
|
||||
# Add the FW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${FW_CONFIG},--fw-config,${FW_CONFIG}))
|
||||
|
||||
$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \
|
||||
fdts/$(notdir ${FVP_HW_CONFIG_DTS})))
|
||||
# Add the HW_CONFIG to FIP and specify the same to certtool
|
||||
$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config,${FVP_HW_CONFIG}))
|
||||
|
||||
FDT_SOURCES += plat/arm/board/a5ds/fdts/a5ds_fw_config.dts \
|
||||
plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts \
|
||||
${FVP_HW_CONFIG_DTS}
|
||||
endif
|
||||
|
||||
NEED_BL32 := yes
|
||||
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += lib/xlat_tables/aarch32/nonlpae_tables.c
|
||||
|
||||
# Use translation tables library v1 when using Cortex-A5
|
||||
ARM_XLAT_TABLES_LIB_V1 := 1
|
||||
$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1))
|
||||
$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
|
||||
|
||||
$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG))
|
||||
$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG))
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <drivers/arm/scu.h>
|
||||
#include <plat/arm/common/plat_arm.h>
|
||||
|
||||
|
||||
void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3);
|
||||
|
||||
/* enable snoop control unit */
|
||||
enable_snoop_ctrl_unit(A5DS_SCU_BASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* A5DS will only have one always-on power domain and there
|
||||
* is no power control present.
|
||||
*/
|
||||
void plat_arm_pwrc_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (c) 2019, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# SP_MIN source files specific to A5DS platform
|
||||
BL32_SOURCES += drivers/arm/scu/scu.c \
|
||||
drivers/cfi/v2m/v2m_flash.c \
|
||||
lib/utils/mem_region.c \
|
||||
lib/aarch32/arm32_aeabi_divmod.c \
|
||||
lib/aarch32/arm32_aeabi_divmod_a32.S \
|
||||
plat/arm/board/a5ds/aarch32/a5ds_helpers.S \
|
||||
plat/arm/board/a5ds/a5ds_pm.c \
|
||||
plat/arm/board/a5ds/a5ds_topology.c \
|
||||
plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c \
|
||||
plat/arm/common/sp_min/arm_sp_min_setup.c \
|
||||
plat/common/aarch32/platform_mp_stack.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
${A5DS_CPU_LIBS} \
|
||||
${A5DS_GIC_SOURCES} \
|
||||
${A5DS_SECURITY_SOURCES}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <common/bl_common.h>
|
||||
#include "../fpga_private.h"
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
.globl plat_get_my_entrypoint
|
||||
.globl plat_secondary_cold_boot_setup
|
||||
.globl plat_is_my_cpu_primary
|
||||
.globl platform_mem_init
|
||||
.globl plat_my_core_pos
|
||||
.globl plat_crash_console_init
|
||||
.globl plat_crash_console_putc
|
||||
.globl plat_crash_console_flush
|
||||
.globl plat_fpga_calc_core_pos
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* Indicate a cold boot for every CPU - warm boot is unsupported for the
|
||||
* holding pen PSCI implementation.
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_get_my_entrypoint
|
||||
mov x0, #0
|
||||
ret
|
||||
endfunc plat_get_my_entrypoint
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* void plat_secondary_cold_boot_setup (void);
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_secondary_cold_boot_setup
|
||||
|
||||
/*
|
||||
* Wait for the primary processor to initialise the .BSS segment
|
||||
* to avoid a race condition that would erase fpga_valid_mpids
|
||||
* if it is populated before the C runtime is ready.
|
||||
*
|
||||
* We cannot use the current spin-lock implementation until the
|
||||
* runtime is up and we should not rely on sevl/wfe instructions as
|
||||
* it is optional whether they are implemented or not, so we use
|
||||
* a global variable as lock and wait for the primary processor to
|
||||
* finish the C runtime bring-up.
|
||||
*/
|
||||
|
||||
ldr w0, =C_RUNTIME_READY_KEY
|
||||
adrp x1, secondary_core_spinlock
|
||||
add x1, x1, :lo12:secondary_core_spinlock
|
||||
1:
|
||||
wfe
|
||||
ldr w2, [x1]
|
||||
cmp w2, w0
|
||||
b.ne 1b
|
||||
/* Prevent reordering of the store into fpga_valid_mpids below */
|
||||
dmb ish
|
||||
|
||||
mov x10, x30
|
||||
bl plat_my_core_pos
|
||||
mov x30, x10
|
||||
|
||||
adrp x4, fpga_valid_mpids
|
||||
add x4, x4, :lo12:fpga_valid_mpids
|
||||
mov x5, #VALID_MPID
|
||||
strb w5, [x4, x0]
|
||||
|
||||
/*
|
||||
* Poll the CPU's hold entry until it indicates to jump
|
||||
* to the entrypoint address.
|
||||
*/
|
||||
|
||||
adrp x1, hold_base
|
||||
add x1, x1, :lo12:hold_base
|
||||
poll_hold_entry:
|
||||
ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT]
|
||||
cmp x3, #PLAT_FPGA_HOLD_STATE_GO
|
||||
b.ne 1f
|
||||
|
||||
adrp x2, fpga_sec_entrypoint
|
||||
add x2, x2, :lo12:fpga_sec_entrypoint
|
||||
ldr x3, [x2]
|
||||
br x3
|
||||
1:
|
||||
wfe
|
||||
b poll_hold_entry
|
||||
|
||||
endfunc plat_secondary_cold_boot_setup
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* unsigned int plat_is_my_cpu_primary (void);
|
||||
*
|
||||
* Find out whether the current cpu is the primary cpu
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_is_my_cpu_primary
|
||||
mrs x0, mpidr_el1
|
||||
mov_imm x1, MPIDR_AFFINITY_MASK
|
||||
and x0, x0, x1
|
||||
cmp x0, #FPGA_PRIMARY_CPU
|
||||
cset w0, eq
|
||||
ret
|
||||
endfunc plat_is_my_cpu_primary
|
||||
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
func plat_my_core_pos
|
||||
ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT))
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, x1
|
||||
b plat_fpga_calc_core_pos
|
||||
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* unsigned int plat_fpga_calc_core_pos (uint32_t mpid)
|
||||
* Clobber registers: x0 to x5
|
||||
* -----------------------------------------------------------------------
|
||||
*/
|
||||
func plat_fpga_calc_core_pos
|
||||
/*
|
||||
* Check for MT bit in MPIDR, which may be either value for images
|
||||
* running on the FPGA.
|
||||
*
|
||||
* If not set, shift MPIDR to left to make it look as if in a
|
||||
* multi-threaded implementation.
|
||||
*
|
||||
*/
|
||||
tst x0, #MPIDR_MT_MASK
|
||||
lsl x3, x0, #MPIDR_AFFINITY_BITS
|
||||
csel x3, x3, x0, eq
|
||||
|
||||
/* Extract individual affinity fields from MPIDR */
|
||||
ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
|
||||
|
||||
mov x4, #FPGA_MAX_CPUS_PER_CLUSTER
|
||||
mov x5, #FPGA_MAX_PE_PER_CPU
|
||||
|
||||
/* Compute linear position */
|
||||
madd x1, x2, x4, x1
|
||||
madd x0, x1, x5, x0
|
||||
|
||||
ret
|
||||
endfunc plat_fpga_calc_core_pos
|
||||
|
||||
func plat_crash_console_init
|
||||
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_init
|
||||
endfunc plat_crash_console_init
|
||||
|
||||
func plat_crash_console_putc
|
||||
mov_imm x1, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_putc
|
||||
endfunc plat_crash_console_putc
|
||||
|
||||
func plat_crash_console_flush
|
||||
mov_imm x0, PLAT_FPGA_CRASH_UART_BASE
|
||||
b console_pl011_core_flush
|
||||
endfunc plat_crash_console_flush
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Linker script for the Arm Ltd. FPGA boards to generate an ELF file that
|
||||
* contains the ROM trampoline, BL31 and the DTB.
|
||||
*
|
||||
* This allows to pass just one file to the uploader tool, and automatically
|
||||
* provides the correct load addresses.
|
||||
*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleaarch64")
|
||||
OUTPUT_ARCH(aarch64)
|
||||
|
||||
INPUT(./rom_trampoline.o)
|
||||
INPUT(./kernel_trampoline.o)
|
||||
|
||||
TARGET(binary)
|
||||
INPUT(./bl31.bin)
|
||||
INPUT(./fdts/arm_fpga.dtb)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.rom (0x0): {
|
||||
*rom_trampoline.o(.text*)
|
||||
KEEP(*(.rom))
|
||||
}
|
||||
|
||||
.bl31 (BL31_BASE): {
|
||||
ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE is not page aligned");
|
||||
*bl31.bin
|
||||
}
|
||||
|
||||
.dtb (FPGA_PRELOADED_DTB_BASE): {
|
||||
ASSERT(. == ALIGN(8), "DTB address is not 8-byte aligned");
|
||||
*arm_fpga.dtb
|
||||
}
|
||||
|
||||
.kern_tramp (PRELOADED_BL33_BASE): {
|
||||
*kernel_trampoline.o(.text*)
|
||||
KEEP(*(.kern_tramp))
|
||||
}
|
||||
|
||||
/DISCARD/ : { *(stacks) }
|
||||
/DISCARD/ : { *(.debug_*) }
|
||||
/DISCARD/ : { *(.note*) }
|
||||
/DISCARD/ : { *(.comment*) }
|
||||
}
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <common/fdt_fixup.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#include <lib/extensions/spe.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include "fpga_private.h"
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
static unsigned int system_freq;
|
||||
volatile uint32_t secondary_core_spinlock;
|
||||
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
return PRELOADED_BL33_BASE;
|
||||
#else
|
||||
return 0ULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t fpga_get_spsr_for_bl33_entry(void)
|
||||
{
|
||||
return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
}
|
||||
|
||||
void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3)
|
||||
{
|
||||
/* Add this core to the VALID mpids list */
|
||||
fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID;
|
||||
|
||||
/*
|
||||
* Notify the secondary CPUs that the C runtime is ready
|
||||
* so they can announce themselves.
|
||||
*/
|
||||
secondary_core_spinlock = C_RUNTIME_READY_KEY;
|
||||
dsbish();
|
||||
sev();
|
||||
|
||||
fpga_console_init();
|
||||
|
||||
bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
|
||||
bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry();
|
||||
SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
|
||||
|
||||
/* Set x0-x3 for the primary CPU as expected by the kernel */
|
||||
bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE;
|
||||
bl33_image_ep_info.args.arg1 = 0U;
|
||||
bl33_image_ep_info.args.arg2 = 0U;
|
||||
bl33_image_ep_info.args.arg3 = 0U;
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
/* Write frequency to CNTCRL and initialize timer */
|
||||
generic_delay_timer_init();
|
||||
|
||||
/*
|
||||
* Before doing anything else, wait for some time to ensure that
|
||||
* the secondary CPUs have populated the fpga_valid_mpids array.
|
||||
* As the number of secondary cores is unknown and can even be 0,
|
||||
* it is not possible to rely on any signal from them, so use a
|
||||
* delay instead.
|
||||
*/
|
||||
mdelay(5);
|
||||
|
||||
/*
|
||||
* On the event of a cold reset issued by, for instance, a reset pin
|
||||
* assertion, we cannot guarantee memory to be initialized to zero.
|
||||
* In such scenario, if the secondary cores reached
|
||||
* plat_secondary_cold_boot_setup before the primary one initialized
|
||||
* .BSS, we could end up having a race condition if the spinlock
|
||||
* was not cleared before.
|
||||
*
|
||||
* Similarly, if there were a reset before the spinlock had been
|
||||
* cleared, the secondary cores would find the lock opened before
|
||||
* .BSS is cleared, causing another race condition.
|
||||
*
|
||||
* So clean the spinlock as soon as we think it is safe to reduce the
|
||||
* chances of any race condition on a reset.
|
||||
*/
|
||||
secondary_core_spinlock = 0UL;
|
||||
|
||||
/* Initialize the GIC driver, cpu and distributor interfaces */
|
||||
plat_fpga_gic_init();
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
next_image_info = &bl33_image_ep_info;
|
||||
|
||||
/* Only expecting BL33: the kernel will run in EL2NS */
|
||||
assert(type == NON_SECURE);
|
||||
|
||||
/* None of the images can have 0x0 as the entrypoint */
|
||||
if (next_image_info->pc) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Even though we sell the FPGA UART as an SBSA variant, it is actually
|
||||
* a full fledged PL011. So the baudrate divider registers exist.
|
||||
*/
|
||||
#ifndef UARTIBRD
|
||||
#define UARTIBRD 0x024
|
||||
#define UARTFBRD 0x028
|
||||
#endif
|
||||
|
||||
/* Round an integer to the closest multiple of a value. */
|
||||
static unsigned int round_multiple(unsigned int x, unsigned int multiple)
|
||||
{
|
||||
if (multiple < 2) {
|
||||
return x;
|
||||
}
|
||||
|
||||
return ((x + (multiple / 2 - 1)) / multiple) * multiple;
|
||||
}
|
||||
|
||||
#define PL011_FRAC_SHIFT 6
|
||||
#define FPGA_DEFAULT_BAUDRATE 38400
|
||||
#define PL011_OVERSAMPLING 16
|
||||
static unsigned int pl011_freq_from_divider(unsigned int divider)
|
||||
{
|
||||
unsigned int freq;
|
||||
|
||||
freq = divider * FPGA_DEFAULT_BAUDRATE * PL011_OVERSAMPLING;
|
||||
|
||||
return freq >> PL011_FRAC_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* The FPGAs run most peripherals from one main clock, among them the CPUs,
|
||||
* the arch timer, and the UART baud base clock.
|
||||
* The SCP knows this frequency and programs the UART clock divider for a
|
||||
* 38400 bps baudrate. Recalculate the base input clock from there.
|
||||
*/
|
||||
static unsigned int fpga_get_system_frequency(void)
|
||||
{
|
||||
const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
int node, err;
|
||||
|
||||
/*
|
||||
* If the arch timer DT node has an explicit clock-frequency property
|
||||
* set, use that, to allow people overriding auto-detection.
|
||||
*/
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,armv8-timer");
|
||||
if (node >= 0) {
|
||||
uint32_t freq;
|
||||
|
||||
err = fdt_read_uint32(fdt, node, "clock-frequency", &freq);
|
||||
if (err >= 0) {
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
|
||||
if (node >= 0) {
|
||||
uintptr_t pl011_base;
|
||||
unsigned int divider;
|
||||
|
||||
err = fdt_get_reg_props_by_index(fdt, node, 0,
|
||||
&pl011_base, NULL);
|
||||
if (err >= 0) {
|
||||
divider = mmio_read_32(pl011_base + UARTIBRD);
|
||||
divider <<= PL011_FRAC_SHIFT;
|
||||
divider += mmio_read_32(pl011_base + UARTFBRD);
|
||||
|
||||
/*
|
||||
* The result won't be exact, due to rounding errors,
|
||||
* but the input frequency was a multiple of 250 KHz.
|
||||
*/
|
||||
return round_multiple(pl011_freq_from_divider(divider),
|
||||
250000);
|
||||
} else {
|
||||
WARN("Cannot read PL011 MMIO base\n");
|
||||
}
|
||||
} else {
|
||||
WARN("No PL011 DT node\n");
|
||||
}
|
||||
|
||||
/* No PL011 DT node or calculation failed. */
|
||||
return FPGA_DEFAULT_TIMER_FREQUENCY;
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
if (system_freq == 0U) {
|
||||
system_freq = fpga_get_system_frequency();
|
||||
}
|
||||
|
||||
return system_freq;
|
||||
}
|
||||
|
||||
static void fpga_dtb_update_clock(void *fdt, unsigned int freq)
|
||||
{
|
||||
uint32_t freq_dtb = fdt32_to_cpu(freq);
|
||||
uint32_t phandle;
|
||||
int node, err;
|
||||
|
||||
node = fdt_node_offset_by_compatible(fdt, 0, "arm,pl011");
|
||||
if (node < 0) {
|
||||
WARN("%s(): No PL011 DT node found\n", __func__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err = fdt_read_uint32(fdt, node, "clocks", &phandle);
|
||||
if (err != 0) {
|
||||
WARN("Cannot find clocks property\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(fdt, phandle);
|
||||
if (node < 0) {
|
||||
WARN("Cannot get phandle\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err = fdt_setprop_inplace(fdt, node,
|
||||
"clock-frequency",
|
||||
&freq_dtb,
|
||||
sizeof(freq_dtb));
|
||||
if (err < 0) {
|
||||
WARN("Could not update DT baud clock frequency\n");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#define CMDLINE_SIGNATURE "CMD:"
|
||||
|
||||
static int fpga_dtb_set_commandline(void *fdt, const char *cmdline)
|
||||
{
|
||||
int chosen;
|
||||
const char *eol;
|
||||
char nul = 0;
|
||||
int slen, err;
|
||||
|
||||
chosen = fdt_add_subnode(fdt, 0, "chosen");
|
||||
if (chosen == -FDT_ERR_EXISTS) {
|
||||
chosen = fdt_path_offset(fdt, "/chosen");
|
||||
}
|
||||
|
||||
if (chosen < 0) {
|
||||
return chosen;
|
||||
}
|
||||
|
||||
/*
|
||||
* There is most likely an EOL at the end of the
|
||||
* command line, make sure we terminate the line there.
|
||||
* We can't replace the EOL with a NUL byte in the
|
||||
* source, as this is in read-only memory. So we first
|
||||
* create the property without any termination, then
|
||||
* append a single NUL byte.
|
||||
*/
|
||||
eol = strchr(cmdline, '\n');
|
||||
if (eol == NULL) {
|
||||
eol = strchr(cmdline, 0);
|
||||
}
|
||||
/* Skip the signature and omit the EOL/NUL byte. */
|
||||
slen = eol - (cmdline + strlen(CMDLINE_SIGNATURE));
|
||||
/*
|
||||
* Let's limit the size of the property, just in case
|
||||
* we find the signature by accident. The Linux kernel
|
||||
* limits to 4096 characters at most (in fact 2048 for
|
||||
* arm64), so that sounds like a reasonable number.
|
||||
*/
|
||||
if (slen > 4095) {
|
||||
slen = 4095;
|
||||
}
|
||||
|
||||
err = fdt_setprop(fdt, chosen, "bootargs",
|
||||
cmdline + strlen(CMDLINE_SIGNATURE), slen);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return fdt_appendprop(fdt, chosen, "bootargs", &nul, 1);
|
||||
}
|
||||
|
||||
static void fpga_prepare_dtb(void)
|
||||
{
|
||||
void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
const char *cmdline = (void *)(uintptr_t)FPGA_PRELOADED_CMD_LINE;
|
||||
int err;
|
||||
|
||||
err = fdt_open_into(fdt, fdt, FPGA_MAX_DTB_SIZE);
|
||||
if (err < 0) {
|
||||
ERROR("cannot open devicetree at %p: %d\n", fdt, err);
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Reserve memory used by Trusted Firmware. */
|
||||
if (fdt_add_reserved_memory(fdt, "tf-a@80000000", BL31_BASE,
|
||||
BL31_LIMIT - BL31_BASE)) {
|
||||
WARN("Failed to add reserved memory node to DT\n");
|
||||
}
|
||||
|
||||
/* Check for the command line signature. */
|
||||
if (!strncmp(cmdline, CMDLINE_SIGNATURE, strlen(CMDLINE_SIGNATURE))) {
|
||||
err = fpga_dtb_set_commandline(fdt, cmdline);
|
||||
if (err == 0) {
|
||||
INFO("using command line at 0x%x\n",
|
||||
FPGA_PRELOADED_CMD_LINE);
|
||||
} else {
|
||||
ERROR("failed to put command line into DTB: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
ERROR("Error %d extending Device Tree\n", err);
|
||||
panic();
|
||||
}
|
||||
|
||||
err = fdt_add_cpus_node(fdt, FPGA_MAX_PE_PER_CPU,
|
||||
FPGA_MAX_CPUS_PER_CLUSTER,
|
||||
FPGA_MAX_CLUSTER_COUNT);
|
||||
|
||||
if (err == -EEXIST) {
|
||||
WARN("Not overwriting already existing /cpus node in DTB\n");
|
||||
} else {
|
||||
if (err < 0) {
|
||||
ERROR("Error %d creating the /cpus DT node\n", err);
|
||||
panic();
|
||||
} else {
|
||||
unsigned int nr_cores = fpga_get_nr_gic_cores();
|
||||
|
||||
INFO("Adjusting GICR DT region to cover %u cores\n",
|
||||
nr_cores);
|
||||
err = fdt_adjust_gic_redist(fdt, nr_cores,
|
||||
fpga_get_redist_base(),
|
||||
fpga_get_redist_size());
|
||||
if (err < 0) {
|
||||
ERROR("Error %d fixing up GIC DT node\n", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fpga_dtb_update_clock(fdt, system_freq);
|
||||
|
||||
/* Check whether we support the SPE PMU. Remove the DT node if not. */
|
||||
if (!spe_supported()) {
|
||||
int node = fdt_node_offset_by_compatible(fdt, 0,
|
||||
"arm,statistical-profiling-extension-v1");
|
||||
|
||||
if (node >= 0) {
|
||||
fdt_del_node(fdt, node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether we have an ITS. Remove the DT node if not. */
|
||||
if (!fpga_has_its()) {
|
||||
int node = fdt_node_offset_by_compatible(fdt, 0,
|
||||
"arm,gic-v3-its");
|
||||
|
||||
if (node >= 0) {
|
||||
fdt_del_node(fdt, node);
|
||||
}
|
||||
}
|
||||
|
||||
err = fdt_pack(fdt);
|
||||
if (err < 0) {
|
||||
ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, err);
|
||||
}
|
||||
|
||||
clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt));
|
||||
}
|
||||
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
fpga_prepare_dtb();
|
||||
}
|
||||
|
||||
void bl31_plat_enable_mmu(uint32_t flags)
|
||||
{
|
||||
/* TODO: determine if MMU needs to be enabled */
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/arm/pl011.h>
|
||||
#include <drivers/console.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
static console_t console;
|
||||
|
||||
void fpga_console_init(void)
|
||||
{
|
||||
const void *fdt = (void *)(uintptr_t)FPGA_PRELOADED_DTB_BASE;
|
||||
uintptr_t base_addr = PLAT_FPGA_CRASH_UART_BASE;
|
||||
int node;
|
||||
|
||||
/*
|
||||
* Try to read the UART base address from the DT, by chasing the
|
||||
* stdout-path property of the chosen node.
|
||||
* If this does not work, use the crash console address as a fallback.
|
||||
*/
|
||||
node = fdt_get_stdout_node_offset(fdt);
|
||||
if (node >= 0) {
|
||||
fdt_get_reg_props_by_index(fdt, node, 0, &base_addr, NULL);
|
||||
}
|
||||
|
||||
(void)console_pl011_register(base_addr, 0, 0, &console);
|
||||
|
||||
console_set_scope(&console, CONSOLE_FLAG_BOOT |
|
||||
CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
#ifndef FPGA_DEF_H
|
||||
#define FPGA_DEF_H
|
||||
|
||||
/*
|
||||
* These are set to large values to account for images describing systems with
|
||||
* larger cluster configurations.
|
||||
*
|
||||
* For cases where the number of clusters, cores or threads is smaller than a
|
||||
* maximum value below, this does not affect the PSCI functionality as any PEs
|
||||
* that are present will still be indexed appropriately regardless of any empty
|
||||
* entries in the array used to represent the topology.
|
||||
*/
|
||||
|
||||
#define FPGA_MAX_CLUSTER_COUNT 4
|
||||
#define FPGA_MAX_CPUS_PER_CLUSTER 8
|
||||
#define FPGA_MAX_PE_PER_CPU 4
|
||||
|
||||
#define FPGA_PRIMARY_CPU 0x0
|
||||
/*******************************************************************************
|
||||
* FPGA image memory map related constants
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* UART base address, just for the crash console, as a fallback.
|
||||
* The actual console UART address is taken from the DT.
|
||||
*/
|
||||
#define PLAT_FPGA_CRASH_UART_BASE 0x7ff80000
|
||||
|
||||
#define FPGA_DEFAULT_TIMER_FREQUENCY 10000000
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user