diff --git a/docs/plat/xilinx-versal.md b/docs/plat/xilinx-versal.md new file mode 100644 index 0000000..c84014c --- /dev/null +++ b/docs/plat/xilinx-versal.md @@ -0,0 +1,33 @@ +Trusted Firmware-A for Xilinx Versal +================================ + +Trusted Firmware-A implements the EL3 firmware layer for Xilinx Versal. +The platform only uses the runtime part of TF-A as Xilinx Versal already has a +BootROM (BL1) and PMC FW (BL2). + +BL31 is TF-A. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 +``` + +To build ATF for different platform (for now its just versal virtual "versal_virt") +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31 +``` + +# Xilinx Versal platform specific build options +* `VERSAL_ATF_MEM_BASE`: Specifies the base address of the bl31 binary. +* `VERSAL_ATF_MEM_SIZE`: Specifies the size of the memory region of the bl31 binary. +* `VERSAL_BL32_MEM_BASE`: Specifies the base address of the bl32 binary. +* `VERSAL_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary. + +* `VERSAL_CONSOLE`: Select the console driver. Options: + - `pl011`, `pl011_0`: ARM pl011 UART 0 + - `pl011_1` : ARM pl011 UART 1 + +* `VERSAL_PLATFORM`: Select the platform. Options: + - `versal_virt` : Versal Virtual platform diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c new file mode 100644 index 0000000..c13b1b5 --- /dev/null +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "../versal_def.h" +#include "../versal_private.h" + +/* + * Table of regions to map using the MMU. + * This doesn't include TZRAM as the 'mem_layout' argument passed to + * configure_mmu_elx() will give the available subset of that, + */ +const mmap_region_t plat_versal_mmap[] = { + MAP_REGION_FLAT(DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(CRF_BASE, CRF_SIZE, MT_DEVICE | MT_RW | MT_SECURE), + { 0 } +}; + +const mmap_region_t *plat_versal_get_mmap(void) +{ + return plat_versal_mmap; +} + +static void versal_print_platform_name(void) +{ + NOTICE("ATF running on Xilinx %s\n", PLATFORM_NAME); +} + +void versal_config_setup(void) +{ + uint32_t val; + + versal_print_platform_name(); + + mmio_write_32(VERSAL_CRL_IOU_SWITCH_CTRL, + VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT | + (0x20 << VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT)); + + /* Global timer init - Program time stamp reference clk */ + val = mmio_read_32(VERSAL_CRL_TIMESTAMP_REF_CTRL); + val |= VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT; + mmio_write_32(VERSAL_CRL_TIMESTAMP_REF_CTRL, val); + + /* Clear reset of timestamp reg */ + mmio_write_32(VERSAL_CRL_RST_TIMESTAMP_OFFSET, 0x0); + + /* Program freq register in System counter and enable system counter. */ + mmio_write_32(VERSAL_IOU_SCNTRS_BASE_FREQ, VERSAL_CPU_CLOCK); + mmio_write_32(VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG, + VERSAL_IOU_SCNTRS_CONTROL_EN); + + generic_delay_timer_init(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return VERSAL_CPU_CLOCK; +} + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_VERSAL_NS_IMAGE_OFFSET; +#endif +} diff --git a/plat/xilinx/versal/aarch64/versal_helpers.S b/plat/xilinx/versal/aarch64/versal_helpers.S new file mode 100644 index 0000000..1b7f955 --- /dev/null +++ b/plat/xilinx/versal/aarch64/versal_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_is_my_cpu_primary + .globl versal_calc_core_pos + .globl platform_mem_init + .globl plat_my_core_pos + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * TODO: Should we read the PSYS register to make sure + * that the request has gone through. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + mrs x0, mpidr_el1 + + /* + * There is no sane reason to come out of this wfi. This + * cpu will be powered on and reset by the cpu_on pm api + */ + dsb sy + bl plat_panic_handler +endfunc plat_secondary_cold_boot_setup + +func plat_is_my_cpu_primary + mov x9, x30 + bl plat_my_core_pos + cmp x0, #VERSAL_PRIMARY_CPU + cset x0, eq + ret x9 +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * This function uses the versal_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b versal_calc_core_pos +endfunc plat_my_core_pos + +func versal_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc versal_calc_core_pos + + /* --------------------------------------------------------------------- + * We don't need to carry out any memory initialization on VERSAL + * platform. The Secure RAM is accessible straight away. + * --------------------------------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init diff --git a/plat/xilinx/versal/bl31_versal_setup.c b/plat/xilinx/versal/bl31_versal_setup.c new file mode 100644 index 0000000..9f71a1c --- /dev/null +++ b/plat/xilinx/versal/bl31_versal_setup.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "versal_private.h" + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; +static console_pl011_t versal_runtime_console; + +/* + * 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) +{ + assert(sec_state_is_valid(type)); + + if (type == NON_SECURE) + return &bl33_image_ep_info; + + return &bl32_image_ep_info; +} + +/* + * Perform any BL31 specific platform actions. 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. + */ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + + /* Initialize the console to provide early debug support */ + int rc = console_pl011_register(VERSAL_UART_BASE, + VERSAL_UART_CLOCK, + VERSAL_UART_BAUDRATE, + &versal_runtime_console); + if (rc == 0) + panic(); + + console_set_scope(&versal_runtime_console.console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); + + /* Initialize the platform config for future decision making */ + versal_config_setup(); + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(arg0 == 0U); + assert(arg1 == 0U); + + /* + * Do initial security configuration to allow DRAM/device access. On + * Base VERSAL only DRAM security is programmable (via TrustZone), but + * other platforms might have more programmable security devices + * present. + */ + + /* Populate common information for BL32 and BL33 */ + SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* use build time defaults in JTAG boot mode */ + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = 0; + 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); + + NOTICE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc); +} + +void bl31_platform_setup(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + plat_versal_gic_driver_init(); + plat_versal_gic_init(); +} + +void bl31_plat_runtime_setup(void) +{ +} + +/* + * Perform the very early platform specific architectural setup here. + */ +void bl31_plat_arch_setup(void) +{ + const mmap_region_t bl_regions[] = { + MAP_REGION_FLAT(BL31_BASE, BL31_END - BL31_BASE, + MT_MEMORY | MT_RW | MT_SECURE), + 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), + MAP_REGION_FLAT(BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE), + {0} + }; + + setup_page_tables(bl_regions, plat_versal_get_mmap()); + enable_mmu_el3(0); +} diff --git a/plat/xilinx/versal/include/plat_macros.S b/plat/xilinx/versal/include/plat_macros.S new file mode 100644 index 0000000..4fc1315 --- /dev/null +++ b/plat/xilinx/versal/include/plat_macros.S @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include "../include/platform_def.h" +#include +#include +#include + +.section .rodata.gic_reg_name, "aS" +/* Applicable only to GICv2 and GICv3 with SRE disabled (legacy mode) */ +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" + +/* Applicable only to GICv3 with SRE enabled */ +icc_regs: + .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", "" + +/* Registers common to both GICv2 and GICv3 */ +gicd_pend_reg: + .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t0x" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31 on Versal platform. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro versal_print_gic_regs + /* Check for GICv3 system register access */ + mrs x7, id_aa64pfr0_el1 + ubfx x7, x7, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_WIDTH + cmp x7, #1 + b.ne print_gicv2 + + /* Check for SRE enable */ + mrs x8, ICC_SRE_EL3 + tst x8, #ICC_SRE_SRE_BIT + b.eq print_gicv2 + + /* Load the icc reg list to x6 */ + adr x6, icc_regs + /* Load the icc regs to gp regs used by str_in_crash_buf_print */ + mrs x8, ICC_HPPIR0_EL1 + mrs x9, ICC_HPPIR1_EL1 + mrs x10, ICC_CTLR_EL3 + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + b print_gic_common + +print_gicv2: + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + +print_gic_common: + /* Print the GICD_ISPENDR regs */ + add x7, 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 + + /* --------------------------------------------- + * 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, PLAT_VERSAL_GICD_BASE + mov_imm x16, PLAT_VERSAL_GICR_BASE + versal_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/xilinx/versal/include/platform_def.h b/plat/xilinx/versal/include/platform_def.h new file mode 100644 index 0000000..45aaa84 --- /dev/null +++ b/plat/xilinx/versal/include/platform_def.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include "../versal_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 0x440 + +#define PLATFORM_CORE_COUNT 2 +#define PLAT_MAX_PWR_LVL 1 +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM (just below the shared memory, if + * present). BL31_BASE is calculated using the current BL31 debug size plus a + * little space for growth. + */ +#ifndef VERSAL_ATF_MEM_BASE +# define BL31_BASE 0xfffea000 +# define BL31_LIMIT 0xffffffff +#else +# define BL31_BASE (VERSAL_ATF_MEM_BASE) +# define BL31_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_SIZE - 1) +# ifdef VERSAL_ATF_MEM_PROGBITS_SIZE +# define BL31_PROGBITS_LIMIT (VERSAL_ATF_MEM_BASE + VERSAL_ATF_MEM_PROGBITS_SIZE - 1) +# endif +#endif + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#ifndef VERSAL_BL32_MEM_BASE +# define BL32_BASE 0x60000000 +# define BL32_LIMIT 0x7fffffff +#else +# define BL32_BASE (VERSAL_BL32_MEM_BASE) +# define BL32_LIMIT (VERSAL_BL32_MEM_BASE + VERSAL_BL32_MEM_SIZE - 1) +#endif + +/******************************************************************************* + * BL33 specific defines. + ******************************************************************************/ +#ifndef PRELOADED_BL33_BASE +# define PLAT_VERSAL_NS_IMAGE_OFFSET 0x8000000 +#else +# define PLAT_VERSAL_NS_IMAGE_OFFSET PRELOADED_BL33_BASE +#endif + +/******************************************************************************* + * TSP specific defines. + ******************************************************************************/ +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE + 1) + +/* ID of the secure physical generic timer interrupt used by the TSP */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ull << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ull << 32) +#define MAX_MMAP_REGIONS 7 +#define MAX_XLAT_TABLES 5 + +#define CACHE_WRITEBACK_SHIFT 6 +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +#define PLAT_VERSAL_GICD_BASE 0xF9000000 +#define PLAT_VERSAL_GICR_BASE 0xF9080000 + +/* + * 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_VERSAL_G1S_IRQS VERSAL_IRQ_SEC_PHY_TIMER +#define PLAT_VERSAL_G0_IRQS VERSAL_IRQ_SEC_PHY_TIMER + +#define PLAT_VERSAL_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(VERSAL_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_VERSAL_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/xilinx/versal/plat_psci.c b/plat/xilinx/versal/plat_psci.c new file mode 100644 index 0000000..37d00f6 --- /dev/null +++ b/plat/xilinx/versal/plat_psci.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "versal_private.h" + +static uintptr_t versal_sec_entry; + +static int versal_nopmc_pwr_domain_on(u_register_t mpidr) +{ + uint32_t r; + unsigned int cpu_id = plat_core_pos_by_mpidr(mpidr); + + VERBOSE("%s: mpidr: 0x%lx\n", __func__, mpidr); + + if (cpu_id == -1) + return PSCI_E_INTERN_FAIL; + + /* + * program RVBAR + */ + mmio_write_32(FPD_APU_RVBAR_L_0 + (cpu_id << 3), versal_sec_entry); + mmio_write_32(FPD_APU_RVBAR_H_0 + (cpu_id << 3), versal_sec_entry >> 32); + + /* + * clear VINITHI + */ + r = mmio_read_32(FPD_APU_CONFIG_0); + r &= ~(1 << FPD_APU_CONFIG_0_VINITHI_SHIFT << cpu_id); + mmio_write_32(FPD_APU_CONFIG_0, r); + + /* + * FIXME: Add power up sequence, By default it works + * now without the need of it as it was powered up by + * default. + */ + + /* + * clear power down request + */ + r = mmio_read_32(FPD_APU_PWRCTL); + r &= ~(1 << cpu_id); + mmio_write_32(FPD_APU_PWRCTL, r); + + /* + * release core reset + */ + r = mmio_read_32(CRF_RST_APU); + r &= ~((CRF_RST_APU_ACPU_PWRON_RESET | + CRF_RST_APU_ACPU_RESET) << cpu_id); + mmio_write_32(CRF_RST_APU, r); + + return PSCI_E_SUCCESS; +} + +void versal_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Enable the gic cpu interface */ + plat_versal_gic_pcpu_init(); + + /* Program the gic per-cpu distributor or re-distributor interface */ + plat_versal_gic_cpuif_enable(); +} + +static const struct plat_psci_ops versal_nopmc_psci_ops = { + .pwr_domain_on = versal_nopmc_pwr_domain_on, + .pwr_domain_on_finish = versal_pwr_domain_on_finish, +}; + +/******************************************************************************* + * Export the platform specific power ops. + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops) +{ + versal_sec_entry = sec_entrypoint; + + *psci_ops = &versal_nopmc_psci_ops; + + return 0; +} diff --git a/plat/xilinx/versal/plat_topology.c b/plat/xilinx/versal/plat_topology.c new file mode 100644 index 0000000..66d4fae --- /dev/null +++ b/plat/xilinx/versal/plat_topology.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static const unsigned char plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/plat/xilinx/versal/plat_versal.c b/plat/xilinx/versal/plat_versal.c new file mode 100644 index 0000000..152cb36 --- /dev/null +++ b/plat/xilinx/versal/plat_versal.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include "versal_private.h" + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + return -1; + + if ((mpidr & MPIDR_CPU_MASK) >= PLATFORM_CORE_COUNT) + return -1; + + return versal_calc_core_pos(mpidr); +} diff --git a/plat/xilinx/versal/platform.mk b/plat/xilinx/versal/platform.mk new file mode 100644 index 0000000..78e9b33 --- /dev/null +++ b/plat/xilinx/versal/platform.mk @@ -0,0 +1,63 @@ +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +override PROGRAMMABLE_RESET_ADDRESS := 1 +PSCI_EXTENDED_STATE_ID := 1 +A53_DISABLE_NON_TEMPORAL_HINT := 0 +SEPARATE_CODE_AND_RODATA := 1 +override RESET_TO_BL31 := 1 +PL011_GENERIC_UART := 1 +MULTI_CONSOLE_API := 1 + +ifdef VERSAL_ATF_MEM_BASE + $(eval $(call add_define,VERSAL_ATF_MEM_BASE)) + + ifndef VERSAL_ATF_MEM_SIZE + $(error "VERSAL_ATF_BASE defined without VERSAL_ATF_SIZE") + endif + $(eval $(call add_define,VERSAL_ATF_MEM_SIZE)) + + ifdef VERSAL_ATF_MEM_PROGBITS_SIZE + $(eval $(call add_define,VERSAL_ATF_MEM_PROGBITS_SIZE)) + endif +endif + +ifdef VERSAL_BL32_MEM_BASE + $(eval $(call add_define,VERSAL_BL32_MEM_BASE)) + + ifndef VERSAL_BL32_MEM_SIZE + $(error "VERSAL_BL32_BASE defined without VERSAL_BL32_SIZE") + endif + $(eval $(call add_define,VERSAL_BL32_MEM_SIZE)) +endif + +VERSAL_PLATFORM ?= versal_virt +$(eval $(call add_define_val,VERSAL_PLATFORM,VERSAL_PLATFORM_ID_${VERSAL_PLATFORM})) + +VERSAL_CONSOLE ?= pl011 +$(eval $(call add_define_val,VERSAL_CONSOLE,VERSAL_CONSOLE_ID_${VERSAL_CONSOLE})) + +PLAT_INCLUDES := -Iplat/xilinx/versal/include/ + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/pl011/aarch64/pl011_console.S \ + plat/common/plat_gicv3.c \ + plat/xilinx/versal/aarch64/versal_helpers.S \ + plat/xilinx/versal/aarch64/versal_common.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + plat/common/plat_psci_common.c \ + plat/xilinx/versal/bl31_versal_setup.c \ + plat/xilinx/versal/plat_psci.c \ + plat/xilinx/versal/plat_versal.c \ + plat/xilinx/versal/plat_topology.c \ + plat/xilinx/versal/sip_svc_setup.c \ + plat/xilinx/versal/versal_gicv3.c diff --git a/plat/xilinx/versal/sip_svc_setup.c b/plat/xilinx/versal/sip_svc_setup.c new file mode 100644 index 0000000..4007d5c --- /dev/null +++ b/plat/xilinx/versal/sip_svc_setup.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Top level SMC handler for SiP calls. Dispatch PM calls to PM SMC handler. */ + +#include +#include +#include + +/* SMC function IDs for SiP Service queries */ +#define VERSAL_SIP_SVC_CALL_COUNT 0x8200ff00 +#define VERSAL_SIP_SVC_UID 0x8200ff01 +#define VERSAL_SIP_SVC_VERSION 0x8200ff03 + +/* SiP Service Calls version numbers */ +#define SIP_SVC_VERSION_MAJOR 0 +#define SIP_SVC_VERSION_MINOR 1 + +/* These macros are used to identify PM calls from the SMC function ID */ +#define PM_FID_MASK 0xf000u +#define PM_FID_VALUE 0u +#define is_pm_fid(_fid) (((_fid) & PM_FID_MASK) == PM_FID_VALUE) + +/* SiP Service UUID */ +DEFINE_SVC_UUID2(versal_sip_uuid, + 0x2ab9e4ec, 0x93b9, 0x11e7, 0xa0, 0x19, + 0xdf, 0xe0, 0xdb, 0xad, 0x0a, 0xe0); + +/** + * sip_svc_setup() - Setup SiP Service + * + * Invokes PM setup + */ +static int32_t sip_svc_setup(void) +{ + return 0; +} + +/** + * sip_svc_smc_handler() - Top-level SiP Service SMC handler + * + * Handler for all SiP SMC calls. Handles standard SIP requests + * and calls PM SMC handler if the call is for a PM-API function. + */ +uintptr_t sip_svc_smc_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + /* Let PM SMC handler deal with PM-related requests */ + switch (smc_fid) { + case VERSAL_SIP_SVC_CALL_COUNT: + /* PM functions + default functions */ + SMC_RET1(handle, 2); + + case VERSAL_SIP_SVC_UID: + SMC_UUID_RET(handle, versal_sip_uuid); + + case VERSAL_SIP_SVC_VERSION: + SMC_RET2(handle, SIP_SVC_VERSION_MAJOR, SIP_SVC_VERSION_MINOR); + + default: + WARN("Unimplemented SiP Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register PM Service Calls as runtime service */ +DECLARE_RT_SVC( + sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + sip_svc_setup, + sip_svc_smc_handler); diff --git a/plat/xilinx/versal/versal_def.h b/plat/xilinx/versal/versal_def.h new file mode 100644 index 0000000..5e42bd7 --- /dev/null +++ b/plat/xilinx/versal/versal_def.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VERSAL_DEF_H +#define VERSAL_DEF_H + +#include + +/* List all consoles */ +#define VERSAL_CONSOLE_ID_pl011 1 +#define VERSAL_CONSOLE_ID_pl011_0 1 +#define VERSAL_CONSOLE_ID_pl011_1 2 +#define VERSAL_CONSOLE_ID_dcc 3 + +#define VERSAL_CONSOLE_IS(con) (VERSAL_CONSOLE_ID_ ## con == VERSAL_CONSOLE) + +/* List all supported platforms */ +#define VERSAL_PLATFORM_ID_versal_virt 1 + +#define VERSAL_PLATFORM_IS(con) (VERSAL_PLATFORM_ID_ ## con == VERSAL_PLATFORM) + +/* Firmware Image Package */ +#define VERSAL_PRIMARY_CPU 0 + +/******************************************************************************* + * memory map related constants + ******************************************************************************/ +#define DEVICE0_BASE 0xFF000000 +#define DEVICE0_SIZE 0x00E00000 +#define DEVICE1_BASE 0xF9000000 +#define DEVICE1_SIZE 0x00800000 + +/* CRL */ +#define VERSAL_CRL 0xFF5E0000 +#define VERSAL_CRL_IOU_SWITCH_CTRL (VERSAL_CRL + 0x114) +#define VERSAL_CRL_TIMESTAMP_REF_CTRL (VERSAL_CRL + 0x14C) +#define VERSAL_CRL_RST_TIMESTAMP_OFFSET (VERSAL_CRL + 0x348) + +#define VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 25) +#define VERSAL_IOU_SWITCH_CTRL_CLKACT_BIT (1 << 25) +#define VERSAL_IOU_SWITCH_CTRL_DIVISOR0_SHIFT 8 + +/* IOU SCNTRS */ +#define VERSAL_IOU_SCNTRS 0xFF140000 +#define VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG (VERSAL_IOU_SCNTRS + 0x0) +#define VERSAL_IOU_SCNTRS_BASE_FREQ (VERSAL_IOU_SCNTRS + 0x20) + +#define VERSAL_IOU_SCNTRS_CONTROL_EN 1 + +/******************************************************************************* + * IRQ constants + ******************************************************************************/ +#define VERSAL_IRQ_SEC_PHY_TIMER 29 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define VERSAL_UART0_BASE 0xFF000000 +#define VERSAL_UART1_BASE 0xFF010000 + +#if VERSAL_CONSOLE_IS(pl011) +# define VERSAL_UART_BASE VERSAL_UART0_BASE +#elif VERSAL_CONSOLE_IS(pl011_1) +# define VERSAL_UART_BASE VERSAL_UART1_BASE +#else +# error "invalid VERSAL_CONSOLE" +#endif + +#define PLAT_VERSAL_CRASH_UART_BASE VERSAL_UART_BASE +#define PLAT_VERSAL_CRASH_UART_CLK_IN_HZ VERSAL_UART_CLOCK +#define VERSAL_CONSOLE_BAUDRATE VERSAL_UART_BAUDRATE + +/******************************************************************************* + * Platform related constants + ******************************************************************************/ +#if VERSAL_PLATFORM_IS(versal_virt) +# define PLATFORM_NAME "Versal Virt" +# define VERSAL_UART_CLOCK 25000000 +# define VERSAL_UART_BAUDRATE 115200 +# define VERSAL_CPU_CLOCK 62500000 +#endif + +/* Access control register defines */ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) + +/* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ +#define CRF_BASE 0xFD1A0000 +#define CRF_SIZE 0x00600000 + +/* CRF registers and bitfields */ +#define CRF_RST_APU (CRF_BASE + 0X00000300) + +#define CRF_RST_APU_ACPU_RESET (1 << 0) +#define CRF_RST_APU_ACPU_PWRON_RESET (1 << 10) + +/* APU registers and bitfields */ +#define FPD_APU_BASE 0xFD5C0000 +#define FPD_APU_CONFIG_0 (FPD_APU_BASE + 0x20) +#define FPD_APU_RVBAR_L_0 (FPD_APU_BASE + 0x40) +#define FPD_APU_RVBAR_H_0 (FPD_APU_BASE + 0x44) +#define FPD_APU_PWRCTL (FPD_APU_BASE + 0x90) + +#define FPD_APU_CONFIG_0_VINITHI_SHIFT 8 + +#endif /* VERSAL_DEF_H */ diff --git a/plat/xilinx/versal/versal_gicv3.c b/plat/xilinx/versal/versal_gicv3.c new file mode 100644 index 0000000..72374b5 --- /dev/null +++ b/plat/xilinx/versal/versal_gicv3.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "versal_private.h" + +/****************************************************************************** + * The following functions are defined as weak to allow a platform to override + * the way the GICv3 driver is initialised and used. + *****************************************************************************/ +#pragma weak plat_versal_gic_driver_init +#pragma weak plat_versal_gic_init +#pragma weak plat_versal_gic_cpuif_enable +#pragma weak plat_versal_gic_cpuif_disable +#pragma weak plat_versal_gic_pcpu_init +#pragma weak plat_versal_gic_redistif_on +#pragma weak plat_versal_gic_redistif_off + +/* The GICv3 driver only needs to be initialized in EL3 */ +static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static const interrupt_prop_t versal_interrupt_props[] = { + PLAT_VERSAL_G1S_IRQ_PROPS(INTR_GROUP1S), + PLAT_VERSAL_G0_IRQ_PROPS(INTR_GROUP0) +}; + +/* + * We save and restore the GICv3 context on system suspend. Allocate the + * data in the designated EL3 Secure carve-out memory. + */ +static gicv3_redist_ctx_t rdist_ctx __section("versal_el3_tzc_dram"); +static gicv3_dist_ctx_t dist_ctx __section("versal_el3_tzc_dram"); + +/* + * MPIDR hashing function for translating MPIDRs read from GICR_TYPER register + * to core position. + * + * Calculating core position is dependent on MPIDR_EL1.MT bit. However, affinity + * values read from GICR_TYPER don't have an MT field. To reuse the same + * translation used for CPUs, we insert MT bit read from the PE's MPIDR into + * that read from GICR_TYPER. + * + * Assumptions: + * + * - All CPUs implemented in the system have MPIDR_EL1.MT bit set; + * - No CPUs implemented in the system use affinity level 3. + */ +static unsigned int versal_gicv3_mpidr_hash(u_register_t mpidr) +{ + mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); + return versal_calc_core_pos(mpidr); +} + +static const gicv3_driver_data_t versal_gic_data __unused = { + .gicd_base = PLAT_VERSAL_GICD_BASE, + .gicr_base = PLAT_VERSAL_GICR_BASE, + .interrupt_props = versal_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(versal_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = versal_gicv3_mpidr_hash +}; + +void __init plat_versal_gic_driver_init(void) +{ + /* + * The GICv3 driver is initialized in EL3 and does not need + * to be initialized again in SEL1. This is because the S-EL1 + * can use GIC system registers to manage interrupts and does + * not need GIC interface base addresses to be configured. + */ +#if IMAGE_BL31 + gicv3_driver_init(&versal_gic_data); +#endif +} + +/****************************************************************************** + * Versal common helper to initialize the GIC. Only invoked by BL31 + *****************************************************************************/ +void __init plat_versal_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to enable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to disable the GIC CPU interface + *****************************************************************************/ +void plat_versal_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to initialize the per-cpu redistributor interface in + * GICv3 + *****************************************************************************/ +void plat_versal_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helpers to power GIC redistributor interface + *****************************************************************************/ +void plat_versal_gic_redistif_on(void) +{ + gicv3_rdistif_on(plat_my_core_pos()); +} + +void plat_versal_gic_redistif_off(void) +{ + gicv3_rdistif_off(plat_my_core_pos()); +} + +/****************************************************************************** + * Versal common helper to save & restore the GICv3 on resume from system + * suspend + *****************************************************************************/ +void plat_versal_gic_save(void) +{ + /* + * If an ITS is available, save its context before + * the Redistributor using: + * gicv3_its_save_disable(gits_base, &its_ctx[i]) + * Additionnaly, an implementation-defined sequence may + * be required to save the whole ITS state. + */ + + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to save the context of the CPU that is issuing + * the SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); + + /* Save the GIC Distributor context */ + gicv3_distif_save(&dist_ctx); + + /* + * From here, all the components of the GIC can be safely powered down + * as long as there is an alternate way to handle wakeup interrupt + * sources. + */ +} + +void plat_versal_gic_resume(void) +{ + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(&dist_ctx); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. As we only handle SYSTEM SUSPEND API, + * we only need to restore the context of the CPU that issued + * the SYSTEM SUSPEND call. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); + + /* + * If an ITS is available, restore its context after + * the Redistributor using: + * gicv3_its_restore(gits_base, &its_ctx[i]) + * An implementation-defined sequence may be required to + * restore the whole ITS state. The ITS must also be + * re-enabled after this sequence has been executed. + */ +} diff --git a/plat/xilinx/versal/versal_private.h b/plat/xilinx/versal/versal_private.h new file mode 100644 index 0000000..1e30ebc --- /dev/null +++ b/plat/xilinx/versal/versal_private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VERSAL_PRIVATE_H +#define VERSAL_PRIVATE_H + +#include + +void versal_config_setup(void); + +const mmap_region_t *plat_versal_get_mmap(void); + +void plat_versal_gic_driver_init(void); +void plat_versal_gic_init(void); +void plat_versal_gic_cpuif_enable(void); +void plat_versal_gic_cpuif_disable(void); +void plat_versal_gic_pcpu_init(void); + +unsigned int versal_calc_core_pos(u_register_t mpidr); + +#endif /* VERSAL_PRIVATE_H */