Merge pull request #1400 from Andre-ARM/allwinner/v1
Allwinner platform support
This commit is contained in:
commit
ac0197d9d5
|
@ -0,0 +1,29 @@
|
|||
Trusted Firmware-A for Allwinner ARMv8 SoCs
|
||||
===========================================
|
||||
|
||||
Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner
|
||||
SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and
|
||||
PSCI runtime services.
|
||||
U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot).
|
||||
Loading is done from SD card, eMMC or SPI flash, also via an USB debug
|
||||
interface (FEL).
|
||||
BL31 lives in SRAM A2, which is documented to be accessible from secure
|
||||
world only.
|
||||
|
||||
Current limitations:
|
||||
|
||||
- Missing PMIC support
|
||||
|
||||
After building bl31.bin, the binary must be fed to the U-Boot build system
|
||||
to include it in the FIT image that the SPL loader will process.
|
||||
bl31.bin can be either copied (or sym-linked) into U-Boot's root directory,
|
||||
or the environment variable BL31 must contain the binary's path.
|
||||
See the respective `U-Boot documentation`_ for more details.
|
||||
|
||||
To build:
|
||||
|
||||
::
|
||||
|
||||
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
|
||||
|
||||
.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
|
|
@ -64,6 +64,16 @@ Files:
|
|||
- plat/hisilicon/hikey/\*
|
||||
- plat/hisilicon/hikey960/\*
|
||||
|
||||
Allwinner ARMv8 platform sub-maintainer
|
||||
---------------------------------------
|
||||
|
||||
Andre Przywara (andre.przywara@arm.com, `Andre-ARM`_)
|
||||
|
||||
Files:
|
||||
|
||||
- docs/plat/allwinner.rst
|
||||
- plat/allwinner/\*
|
||||
|
||||
HiSilicon Poplar platform sub-maintainer
|
||||
----------------------------------------
|
||||
|
||||
|
@ -151,3 +161,4 @@ Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_)
|
|||
.. _rockchip-linux: https://github.com/rockchip-linux
|
||||
.. _etienne-lms: https://github.com/etienne-lms
|
||||
.. _qoriq-open-source: https://github.com/qoriq-open-source
|
||||
.. _Andre-ARM: https://github.com/Andre-ARM
|
||||
|
|
|
@ -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__ */
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_DEF_H__
|
||||
#define __PLATFORM_DEF_H__
|
||||
|
||||
#include <common_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <tbbr/tbbr_img_def.h>
|
||||
|
||||
#define BL31_BASE SUNXI_SRAM_A2_BASE
|
||||
#define BL31_LIMIT (SUNXI_SRAM_A2_BASE + SUNXI_SRAM_A2_SIZE)
|
||||
|
||||
/* The traditional U-Boot load address is 160MB into DRAM, so at 0x4a000000 */
|
||||
#define PLAT_SUNXI_NS_IMAGE_OFFSET (SUNXI_DRAM_BASE + (160U << 20))
|
||||
|
||||
#define CACHE_WRITEBACK_SHIFT 6
|
||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
#define MAX_MMAP_REGIONS (4 + PLATFORM_MMAP_REGIONS)
|
||||
#define MAX_XLAT_TABLES 2
|
||||
|
||||
#define PLAT_MAX_PWR_LVL_STATES 2
|
||||
#define PLAT_MAX_RET_STATE 1
|
||||
#define PLAT_MAX_OFF_STATE 2
|
||||
|
||||
#define PLAT_MAX_PWR_LVL 2
|
||||
#define PLAT_NUM_PWR_DOMAINS (1 + \
|
||||
PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
|
||||
#define PLATFORM_CLUSTER_COUNT 1
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
|
||||
PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
|
||||
#define PLATFORM_MMAP_REGIONS 4
|
||||
#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
|
||||
|
||||
#endif /* __PLATFORM_DEF_H__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
#endif /* __SUNXI_DEF_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
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <assert.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <generic_delay_timer.h>
|
||||
#include <gicv2.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <uart_16550.h>
|
||||
|
||||
#include "sunxi_private.h"
|
||||
|
||||
static entry_point_info_t bl33_image_ep_info;
|
||||
|
||||
static console_16550_t console;
|
||||
|
||||
static const gicv2_driver_data_t sunxi_gic_data = {
|
||||
.gicd_base = SUNXI_GICD_BASE,
|
||||
.gicc_base = SUNXI_GICC_BASE,
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* 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 = plat_get_ns_image_entrypoint();
|
||||
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);
|
||||
|
||||
/* Turn off all secondary CPUs */
|
||||
sunxi_disable_secondary_cpus(plat_my_core_pos());
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
sunxi_configure_mmu_el3(0);
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
generic_delay_timer_init();
|
||||
|
||||
/* Configure the interrupt controller */
|
||||
gicv2_driver_init(&sunxi_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
|
||||
sunxi_security_setup();
|
||||
|
||||
INFO("BL31: Platform setup done\n");
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
assert(sec_state_is_valid(type) != 0);
|
||||
assert(type == NON_SECURE);
|
||||
|
||||
return &bl33_image_ep_info;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <sunxi_def.h>
|
||||
#include <xlat_tables_v2.h>
|
||||
|
||||
static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
|
||||
MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
|
||||
MT_MEMORY | MT_RO | MT_SECURE),
|
||||
MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
|
||||
MT_MEMORY | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
|
||||
MT_DEVICE | MT_RW | MT_SECURE),
|
||||
MAP_REGION_FLAT(SUNXI_DRAM_BASE, SUNXI_DRAM_SIZE,
|
||||
MT_MEMORY | MT_RW | MT_NS),
|
||||
{},
|
||||
};
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return SUNXI_OSC24M_CLK_IN_HZ;
|
||||
}
|
||||
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
#ifdef PRELOADED_BL33_BASE
|
||||
return PRELOADED_BL33_BASE;
|
||||
#else
|
||||
return PLAT_SUNXI_NS_IMAGE_OFFSET;
|
||||
#endif
|
||||
}
|
||||
|
||||
void sunxi_configure_mmu_el3(int flags)
|
||||
{
|
||||
mmap_add_region(BL31_BASE, BL31_BASE,
|
||||
BL31_LIMIT - BL31_BASE,
|
||||
MT_MEMORY | MT_RW | MT_SECURE);
|
||||
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
|
||||
BL_CODE_END - BL_CODE_BASE,
|
||||
MT_CODE | MT_SECURE);
|
||||
mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE,
|
||||
BL_RO_DATA_END - BL_RO_DATA_BASE,
|
||||
MT_RO_DATA | MT_SECURE);
|
||||
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);
|
||||
mmap_add(sunxi_mmap);
|
||||
init_xlat_tables();
|
||||
|
||||
enable_mmu_el3(0);
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_cpucfg.h>
|
||||
#include <utils_def.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;
|
||||
|
||||
INFO("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;
|
||||
|
||||
INFO("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);
|
||||
}
|
||||
|
||||
void sunxi_cpu_off(unsigned int cluster, unsigned int core)
|
||||
{
|
||||
INFO("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 */
|
||||
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(unsigned int cluster, unsigned int core)
|
||||
{
|
||||
INFO("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_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + 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_disable_secondary_cpus(unsigned int primary_cpu)
|
||||
{
|
||||
for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
|
||||
if (cpu == primary_cpu)
|
||||
continue;
|
||||
sunxi_cpu_off(cpu / PLATFORM_MAX_CPUS_PER_CLUSTER,
|
||||
cpu % PLATFORM_MAX_CPUS_PER_CLUSTER);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <delay_timer.h>
|
||||
#include <gicv2.h>
|
||||
#include <mmio.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <psci.h>
|
||||
#include <sunxi_mmap.h>
|
||||
#include <sunxi_cpucfg.h>
|
||||
|
||||
#define SUNXI_WDOG0_CTRL_REG (SUNXI_WDOG_BASE + 0x0010)
|
||||
#define SUNXI_WDOG0_CFG_REG (SUNXI_WDOG_BASE + 0x0014)
|
||||
#define SUNXI_WDOG0_MODE_REG (SUNXI_WDOG_BASE + 0x0018)
|
||||
|
||||
#include "sunxi_private.h"
|
||||
|
||||
#define mpidr_is_valid(mpidr) ( \
|
||||
MPIDR_AFFLVL3_VAL(mpidr) == 0 && \
|
||||
MPIDR_AFFLVL2_VAL(mpidr) == 0 && \
|
||||
MPIDR_AFFLVL1_VAL(mpidr) < PLATFORM_CLUSTER_COUNT && \
|
||||
MPIDR_AFFLVL0_VAL(mpidr) < PLATFORM_MAX_CPUS_PER_CLUSTER)
|
||||
|
||||
static int sunxi_pwr_domain_on(u_register_t mpidr)
|
||||
{
|
||||
if (mpidr_is_valid(mpidr) == 0)
|
||||
return PSCI_E_INTERN_FAIL;
|
||||
|
||||
sunxi_cpu_on(MPIDR_AFFLVL1_VAL(mpidr), MPIDR_AFFLVL0_VAL(mpidr));
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void sunxi_pwr_domain_off(const psci_power_state_t *target_state)
|
||||
{
|
||||
gicv2_cpuif_disable();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* Turn off all secondary CPUs */
|
||||
sunxi_disable_secondary_cpus(plat_my_core_pos());
|
||||
|
||||
ERROR("PSCI: Full shutdown not implemented, halting\n");
|
||||
wfi();
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 sunxi_system_reset(void)
|
||||
{
|
||||
/* 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");
|
||||
wfi();
|
||||
panic();
|
||||
}
|
||||
|
||||
static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
|
||||
{
|
||||
/* The non-secure entry point must be in DRAM */
|
||||
if (ns_entrypoint >= SUNXI_DRAM_BASE &&
|
||||
ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE)
|
||||
return PSCI_E_SUCCESS;
|
||||
|
||||
return PSCI_E_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
static plat_psci_ops_t sunxi_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,
|
||||
};
|
||||
|
||||
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
|
||||
const plat_psci_ops_t **psci_ops)
|
||||
{
|
||||
assert(psci_ops);
|
||||
|
||||
for (int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) {
|
||||
mmio_write_32(SUNXI_CPUCFG_RVBAR_LO_REG(cpu),
|
||||
sec_entrypoint & 0xffffffff);
|
||||
mmio_write_32(SUNXI_CPUCFG_RVBAR_HI_REG(cpu),
|
||||
sec_entrypoint >> 32);
|
||||
}
|
||||
|
||||
*psci_ops = &sunxi_psci_ops;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __SUNXI_PRIVATE_H__
|
||||
#define __SUNXI_PRIVATE_H__
|
||||
|
||||
void sunxi_configure_mmu_el3(int flags);
|
||||
void sunxi_cpu_off(unsigned int cluster, unsigned int core);
|
||||
void sunxi_cpu_on(unsigned int cluster, unsigned int core);
|
||||
void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
|
||||
|
||||
void sunxi_security_setup(void);
|
||||
|
||||
#endif /* __SUNXI_PRIVATE_H__ */
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <debug.h>
|
||||
#include <mmio.h>
|
||||
#include <sunxi_mmap.h>
|
||||
|
||||
#ifdef SUNXI_SPC_BASE
|
||||
#define SPC_DECPORT_STA_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x4)
|
||||
#define SPC_DECPORT_SET_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0x8)
|
||||
#define SPC_DECPORT_CLR_REG(p) (SUNXI_SPC_BASE + ((p) * 0x0c) + 0xc)
|
||||
#endif
|
||||
|
||||
#define R_PRCM_SEC_SWITCH_REG 0x1d0
|
||||
#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;
|
||||
|
||||
#ifdef SUNXI_SPC_BASE
|
||||
INFO("Configuring SPC Controller\n");
|
||||
/* SPC setup: set all devices to non-secure */
|
||||
for (i = 0; i < 6; i++)
|
||||
mmio_write_32(SPC_DECPORT_SET_REG(i), 0xff);
|
||||
#endif
|
||||
|
||||
/* 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 clocks to non-secure */
|
||||
mmio_write_32(SUNXI_R_PRCM_BASE + R_PRCM_SEC_SWITCH_REG, 0x7);
|
||||
|
||||
/* Set all DMA channels (16 max.) to non-secure */
|
||||
mmio_write_32(SUNXI_DMA_BASE + DMA_SEC_REG, 0xffff);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static 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;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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)
|
||||
|
||||
#endif /* __SUNXI_CPUCFG_H__ */
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2018, 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 0x00044000
|
||||
#define SUNXI_SRAM_A2_SIZE 0x00010000
|
||||
#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_SIZE 0x80000000
|
||||
|
||||
/* Memory-mapped devices */
|
||||
#define SUNXI_CPU_MBIST_BASE 0x01502000
|
||||
#define SUNXI_CPUCFG_BASE 0x01700000
|
||||
#define SUNXI_SYSCON_BASE 0x01c00000
|
||||
#define SUNXI_SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
|
||||
#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_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0x2f0)
|
||||
#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__ */
|
|
@ -0,0 +1,59 @@
|
|||
#
|
||||
# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
AW_PLAT := plat/allwinner
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
|
||||
-Iinclude/plat/arm/common/aarch64 \
|
||||
-I${AW_PLAT}/common/include \
|
||||
-I${AW_PLAT}/${PLAT}/include
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \
|
||||
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/arm/gic/common/gic_common.c \
|
||||
drivers/arm/gic/v2/gicv2_helpers.c \
|
||||
drivers/arm/gic/v2/gicv2_main.c \
|
||||
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}/common/sunxi_cpu_ops.c \
|
||||
${AW_PLAT}/common/sunxi_pm.c \
|
||||
${AW_PLAT}/common/sunxi_security.c \
|
||||
${AW_PLAT}/common/sunxi_topology.c
|
||||
|
||||
# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
|
||||
COLD_BOOT_SINGLE_CPU := 1
|
||||
|
||||
# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
|
||||
ERRATA_A53_835769 := 1
|
||||
ERRATA_A53_843419 := 1
|
||||
ERRATA_A53_855873 := 1
|
||||
|
||||
# Disable the PSCI platform compatibility layer.
|
||||
ENABLE_PLAT_COMPAT := 0
|
||||
|
||||
MULTI_CONSOLE_API := 1
|
||||
|
||||
# Prohibit using deprecated interfaces. We rely on this for this platform.
|
||||
ERROR_DEPRECATED := 1
|
||||
|
||||
# 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
|
Loading…
Reference in New Issue