diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst new file mode 100644 index 0000000000000000000000000000000000000000..a7e84a30429a20d5de91d0639f1d33212c14f42a --- /dev/null +++ b/docs/plat/allwinner.rst @@ -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 diff --git a/maintainers.rst b/maintainers.rst index 2217cbe010f8f152dec67f1ebc49979144b75f6f..9b0599e2d229ac2217a086c5701db8a35b7e896f 100644 --- a/maintainers.rst +++ b/maintainers.rst @@ -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 diff --git a/plat/allwinner/common/include/plat_macros.S b/plat/allwinner/common/include/plat_macros.S new file mode 100644 index 0000000000000000000000000000000000000000..6ee4597f2fa06f62a47daff2b655f5fc679093d1 --- /dev/null +++ b/plat/allwinner/common/include/plat_macros.S @@ -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__ */ diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h new file mode 100644 index 0000000000000000000000000000000000000000..ca7db2f241ed116a21a69eb0555f73ecdabf760f --- /dev/null +++ b/plat/allwinner/common/include/platform_def.h @@ -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__ */ diff --git a/plat/allwinner/common/include/sunxi_def.h b/plat/allwinner/common/include/sunxi_def.h new file mode 100644 index 0000000000000000000000000000000000000000..e68fbe4630631911f54e61a34b9a5f6d325fcc0f --- /dev/null +++ b/plat/allwinner/common/include/sunxi_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__ */ diff --git a/plat/allwinner/common/plat_helpers.S b/plat/allwinner/common/plat_helpers.S new file mode 100644 index 0000000000000000000000000000000000000000..b00c7aefd27277079137295dfdc7d68fa300011e --- /dev/null +++ b/plat/allwinner/common/plat_helpers.S @@ -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 diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..d1f1aa1530cf2d09ccf5e9a11f26398fc083e405 --- /dev/null +++ b/plat/allwinner/common/sunxi_bl31_setup.c @@ -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; +} diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c new file mode 100644 index 0000000000000000000000000000000000000000..e36c8b0718e15bbc411907a6d50cf7427290c2e4 --- /dev/null +++ b/plat/allwinner/common/sunxi_common.c @@ -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); +} diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c new file mode 100644 index 0000000000000000000000000000000000000000..be72dee45e6c4b40461fd7b10f97e92256128d4e --- /dev/null +++ b/plat/allwinner/common/sunxi_cpu_ops.c @@ -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); + } +} diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c new file mode 100644 index 0000000000000000000000000000000000000000..fcab130cd04e029f2e99083939bc152599648e82 --- /dev/null +++ b/plat/allwinner/common/sunxi_pm.c @@ -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; +} diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h new file mode 100644 index 0000000000000000000000000000000000000000..b9f0fb41c24bae4210c2ef5cd783a26ef78f495b --- /dev/null +++ b/plat/allwinner/common/sunxi_private.h @@ -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__ */ diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c new file mode 100644 index 0000000000000000000000000000000000000000..e76007285e684de28906c46d443ce49bc2b7d1a4 --- /dev/null +++ b/plat/allwinner/common/sunxi_security.c @@ -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); +} diff --git a/plat/allwinner/common/sunxi_topology.c b/plat/allwinner/common/sunxi_topology.c new file mode 100644 index 0000000000000000000000000000000000000000..98cf63c8cd391e69da160ca2f5c5ab98707da7f9 --- /dev/null +++ b/plat/allwinner/common/sunxi_topology.c @@ -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; +} diff --git a/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h new file mode 100644 index 0000000000000000000000000000000000000000..049c2ad23f47f9b222a488e3bdab6ddbc8f25838 --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h @@ -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__ */ diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h new file mode 100644 index 0000000000000000000000000000000000000000..cb202a8390a0bf29c5b2c5b3422f591619ece08c --- /dev/null +++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.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__ */ diff --git a/plat/allwinner/sun50i_a64/platform.mk b/plat/allwinner/sun50i_a64/platform.mk new file mode 100644 index 0000000000000000000000000000000000000000..236464fe8cf9615ff8abf36f878129dacde6b528 --- /dev/null +++ b/plat/allwinner/sun50i_a64/platform.mk @@ -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