Commit 58032586 authored by Samuel Holland's avatar Samuel Holland Committed by Andre Przywara
Browse files

allwinner: Introduce basic platform support



This platform supports Allwinner's SoCs with ARMv8 cores. So far they
all sport a single cluster of Cortex-A53 cores.

"sunxi" is the original code name used for this platform, and since it
appears in the Linux kernel and in U-Boot as well, we use it here as a
short file name prefix and for identifiers.

This port includes BL31 support only. U-Boot's SPL takes the role of the
primary loader, also doing the DRAM initialization. It then loads the
rest of the firmware, namely ATF and U-Boot (BL33), then hands execution
over to ATF.

This commit includes the basic platform code shared across all SoCs.
There is no platform.mk yet.

[Andre: moved files into proper directories, supported RESET_TO_BL31,
	various clean ups and simplifications ]
Signed-off-by: default avatarSamuel Holland <samuel@sholland.org>
Signed-off-by: default avatarAndre Przywara <andre.przywara@arm.com>
parent 498161a5
/*
* 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__ */
/*
* 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__ */
/*
* 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__ */
/*
* 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
/*
* 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);
}
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();
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;
}
/*
* 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);
}
/*
* 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 <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <psci.h>
#include <sunxi_mmap.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)
static void __dead2 sunxi_system_off(void)
{
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 plat_psci_ops_t sunxi_psci_ops = {
.system_off = sunxi_system_off,
.system_reset = sunxi_system_reset,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
assert(psci_ops);
*psci_ops = &sunxi_psci_ops;
return 0;
}
/*
* 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);
#endif /* __SUNXI_PRIVATE_H__ */
/*
* 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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment