diff options
30 files changed, 1802 insertions, 24 deletions
diff --git a/docs/plat/fvp_ve.rst b/docs/plat/fvp_ve.rst new file mode 100644 index 000000000..c6d67c090 --- /dev/null +++ b/docs/plat/fvp_ve.rst @@ -0,0 +1,81 @@ +Description +=========== + +Versatile Express (VE) family development platform provides an +ultra fast environment for prototyping arm-v7 System-on-Chip designs. +VE Fixed Virtual Platforms (FVP) are simulations of Versatile Express boards. +The platform in arm-trusted-firmware has been verified with Arm Cortex-A5 +and Cortex-A7 VE FVP's. This platform is tested on and only expected to work +with single core models. + +Boot Sequence +============= + +BL1 --> BL2 --> BL32(sp_min) --> BL33(u-boot) --> Linux kernel + +How to build +============ + +Code Locations +--------------- +- `U-boot <https://git.linaro.org/landing-teams/working/arm/u-boot.git>`__ + +- `arm-trusted-firmware <https://github.com/ARM-software/arm-trusted-firmware>`__ + +Build Procedure +--------------- + +- Obtain arm toolchain. The software stack has been verified with linaro 6.2 + `arm-linux-gnueabihf <https://releases.linaro.org/components/toolchain/binaries/6.2-2016.11/arm-linux-gnueabihf/>`__. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Fetch and build u-boot. + Make the .config file using the command: + + .. code:: shell + + make ARCH=arm vexpress_aemv8a_aarch32_config + + Make the u-boot binary for Cortex-A5 using the command: + + .. code:: shell + + make ARCH=arm SUPPORT_ARCH_TIMER=no + + Make the u-boot binary for Cortex-A7 using the command: + + .. code:: shell + + make ARCH=arm + + +- Build TF-A: + + The make command for Cortex-A5 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A5=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A5x1.dts \ + ARM_XLAT_TABLES_LIB_V1=1 BL33=<path_to_u-boot.bin> all fip + + The make command for Cortex-A7 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A7=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A7x1.dts \ + BL33=<path_to_u-boot.bin> all fip + +Run Procedure +------------- + +The following model parameters should be used to boot Linux using the build of +arm-trusted-firmware-a made using the above make commands: + + .. code:: shell + + ./<path_to_model> <path_to_bl1.elf> \ + -C motherboard.flashloader1.fname=<path_to_fip.bin> \ + --data cluster.cpu0=<path_to_zImage>@0x80080000 \ + --data cluster.cpu0=<path_to_ramdisk>@0x84000000 diff --git a/drivers/arm/pl011/aarch32/pl011_console.S b/drivers/arm/pl011/aarch32/pl011_console.S index ae613b134..e9f95f289 100644 --- a/drivers/arm/pl011/aarch32/pl011_console.S +++ b/drivers/arm/pl011/aarch32/pl011_console.S @@ -63,7 +63,14 @@ func console_pl011_core_init /* Program the baudrate */ /* Divisor = (Uart clock * 4) / baudrate */ lsl r1, r1, #2 +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + push {r0,r3} + softudiv r0,r1,r2,r3 + mov r1, r0 + pop {r0,r3} +#else udiv r2, r1, r2 +#endif /* IBRD = Divisor >> 6 */ lsr r1, r2, #6 /* Write the IBRD */ diff --git a/fdts/fvp-ve-Cortex-A5x1.dts b/fdts/fvp-ve-Cortex-A5x1.dts new file mode 100644 index 000000000..0f766016d --- /dev/null +++ b/fdts/fvp-ve-Cortex-A5x1.dts @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2P-CA5s"; + compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + }; + + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x1000000>; + }; + + hdlcd@2a110000 { + compatible = "arm,hdlcd"; + reg = <0x2a110000 0x1000>; + interrupts = <0 85 4>; + clocks = <&oscclk3>; + clock-names = "pxlclk"; + }; + + scu@2c000000 { + compatible = "arm,cortex-a5-scu"; + reg = <0x2c000000 0x58>; + }; + + watchdog@2c000620 { + compatible = "arm,cortex-a5-twd-wdt"; + reg = <0x2c000620 0x20>; + interrupts = <1 14 0x304>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x2c001000 0x1000>, + <0x2c000100 0x100>; + }; + + dcc { + compatible = "arm,vexpress,config-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + oscclk0: osc@0 { + /* CPU and internal AXI reference clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 0>; + freq-range = <50000000 100000000>; + #clock-cells = <0>; + clock-output-names = "oscclk0"; + }; + + oscclk1: osc@1 { + /* Multiplexed AXI master clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <5000000 50000000>; + #clock-cells = <0>; + clock-output-names = "oscclk1"; + }; + + osc@2 { + /* DDR2 */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 2>; + freq-range = <80000000 120000000>; + #clock-cells = <0>; + clock-output-names = "oscclk2"; + }; + + oscclk3: osc@3 { + /* HDLCD */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 3>; + freq-range = <23750000 165000000>; + #clock-cells = <0>; + clock-output-names = "oscclk3"; + }; + + osc@4 { + /* Test chip gate configuration */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 4>; + freq-range = <80000000 80000000>; + #clock-cells = <0>; + clock-output-names = "oscclk4"; + }; + + smbclk: osc@5 { + /* SMB clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 5>; + freq-range = <25000000 60000000>; + #clock-cells = <0>; + clock-output-names = "oscclk5"; + }; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x08000000 0x04000000>, + <1 0 0x14000000 0x04000000>, + <2 0 0x18000000 0x04000000>, + <3 0 0x1c000000 0x04000000>, + <4 0 0x0c000000 0x04000000>, + <5 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + /include/ "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/fdts/fvp-ve-Cortex-A7x1.dts b/fdts/fvp-ve-Cortex-A7x1.dts new file mode 100644 index 000000000..fca3d90ab --- /dev/null +++ b/fdts/fvp-ve-Cortex-A7x1.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2F-1XV7 Cortex-A7x1 SMM"; + compatible = "arm,vexpress,v2f-1xv7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0 0>; + }; + }; + + memory@0,80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x80000000>; /* 2GB @ 2GB */ + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x1000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + /include/ "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/include/arch/aarch32/asm_macros.S b/include/arch/aarch32/asm_macros.S index 8408804fb..8cfa21231 100644 --- a/include/arch/aarch32/asm_macros.S +++ b/include/arch/aarch32/asm_macros.S @@ -78,7 +78,7 @@ * Clobber: r14, r1, r2 */ .macro get_my_mp_stack _name, _size - bl plat_my_core_pos + bl plat_my_core_pos ldr r2, =(\_name + \_size) mov r1, #\_size mla r0, r0, r1, r2 @@ -189,4 +189,31 @@ .endif .endm + /* + * Helper macro for carrying out division in software when + * hardware division is not suported. \top holds the dividend + * in the function call and the remainder after + * the function is executed. \bot holds the divisor. \div holds + * the quotient and \temp is a temporary registed used in calcualtion. + * The division algorithm has been obtained from: + * http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm + */ + .macro softudiv div:req,top:req,bot:req,temp:req + + mov \temp, \bot + cmp \temp, \top, lsr #1 +div1: + movls \temp, \temp, lsl #1 + cmp \temp, \top, lsr #1 + bls div1 + mov \div, #0 + +div2: + cmp \top, \temp + subcs \top, \top,\temp + ADC \div, \div, \div + mov \temp, \temp, lsr #1 + cmp \temp, \bot + bhs div2 + .endm #endif /* ASM_MACROS_S */ diff --git a/include/arch/aarch32/el3_common_macros.S b/include/arch/aarch32/el3_common_macros.S index 048f16103..4af76249f 100644 --- a/include/arch/aarch32/el3_common_macros.S +++ b/include/arch/aarch32/el3_common_macros.S @@ -94,9 +94,11 @@ * from all exception levels. * --------------------------------------------------------------------- */ +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_VFP) ldr r0, =(FPEXC_RESET_VAL | FPEXC_EN_BIT) vmsr FPEXC, r0 isb +#endif #if (ARM_ARCH_MAJOR > 7) /* --------------------------------------------------------------------- diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h index 6d0fb7896..f9bbe0f60 100644 --- a/include/lib/xlat_tables/xlat_tables_defs.h +++ b/include/lib/xlat_tables/xlat_tables_defs.h @@ -73,7 +73,11 @@ #define PAGE_SIZE_MASK (PAGE_SIZE - U(1)) #define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == U(0)) -#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes (1 << 3) */ +#if (ARM_ARCH_MAJOR == 7) && !ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#define XLAT_ENTRY_SIZE_SHIFT U(2) /* Each MMU table entry is 4 bytes */ +#else +#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes */ +#endif #define XLAT_ENTRY_SIZE (U(1) << XLAT_ENTRY_SIZE_SHIFT) #define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT /* Size of one complete table */ diff --git a/include/plat/arm/board/common/board_css_def.h b/include/plat/arm/board/common/board_css_def.h index a77ea96ef..452afbcc8 100644 --- a/include/plat/arm/board/common/board_css_def.h +++ b/include/plat/arm/board/common/board_css_def.h @@ -61,14 +61,14 @@ #define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE #define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ -#define PLAT_ARM_BL31_RUN_UART_BASE SOC_CSS_UART1_BASE -#define PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ #define PLAT_ARM_SP_MIN_RUN_UART_BASE SOC_CSS_UART1_BASE #define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ -#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE -#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ #define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART0_BASE #define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ diff --git a/lib/xlat_tables/aarch32/nonlpae_tables.c b/lib/xlat_tables/aarch32/nonlpae_tables.c new file mode 100644 index 000000000..eca3be3fc --- /dev/null +++ b/lib/xlat_tables/aarch32/nonlpae_tables.c @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2016-2017, Linaro Limited. All rights reserved. + * Copyright (c) 2014-2017, Arm Limited. All rights reserved. + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include <platform_def.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <common/debug.h> +#include <lib/cassert.h> +#include <lib/utils.h> +#include <lib/xlat_tables/xlat_tables.h> + +#include "../xlat_tables_private.h" + +#ifdef ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#error "ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING flag is set. \ +This module is to be used when LPAE is not supported" +#endif + +CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size); +CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size); + +#define MMU32B_UNSET_DESC ~0ul +#define MMU32B_INVALID_DESC 0ul + +#define MT_UNKNOWN ~0U + +/* + * MMU related values + */ + +/* Sharable */ +#define MMU32B_TTB_S (1 << 1) + +/* Not Outer Sharable */ +#define MMU32B_TTB_NOS (1 << 5) + +/* Normal memory, Inner Non-cacheable */ +#define MMU32B_TTB_IRGN_NC 0 + +/* Normal memory, Inner Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WBWA (1 << 6) + +/* Normal memory, Inner Write-Through Cacheable */ +#define MMU32B_TTB_IRGN_WT 1 + +/* Normal memory, Inner Write-Back no Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WB (1 | (1 << 6)) + +/* Normal memory, Outer Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_RNG_WBWA (1 << 3) + +#define MMU32B_DEFAULT_ATTRS \ + (MMU32B_TTB_S | MMU32B_TTB_NOS | \ + MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA) + +/* armv7 memory mapping attributes: section mapping */ +#define SECTION_SECURE (0 << 19) +#define SECTION_NOTSECURE (1 << 19) +#define SECTION_SHARED (1 << 16) +#define SECTION_NOTGLOBAL (1 << 17) +#define SECTION_ACCESS_FLAG (1 << 10) +#define SECTION_UNPRIV (1 << 11) +#define SECTION_RO (1 << 15) +#define SECTION_TEX(tex) ((((tex) >> 2) << 12) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SECTION_DEVICE SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL_CACHED \ + SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) + +#define SECTION_XN (1 << 4) +#define SECTION_PXN (1 << 0) +#define SECTION_SECTION (2 << 0) + +#define SECTION_PT_NOTSECURE (1 << 3) +#define SECTION_PT_PT (1 << 0) + +#define SMALL_PAGE_SMALL_PAGE (1 << 1) +#define SMALL_PAGE_SHARED (1 << 10) +#define SMALL_PAGE_NOTGLOBAL (1 << 11) +#define SMALL_PAGE_TEX(tex) ((((tex) >> 2) << 6) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SMALL_PAGE_DEVICE \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL_CACHED \ + SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) +#define SMALL_PAGE_ACCESS_FLAG (1 << 4) +#define SMALL_PAGE_UNPRIV (1 << 5) +#define SMALL_PAGE_RO (1 << 9) +#define SMALL_PAGE_XN (1 << 0) + +/* The TEX, C and B bits concatenated */ +#define MMU32B_ATTR_DEVICE_INDEX 0x0 +#define MMU32B_ATTR_IWBWA_OWBWA_INDEX 0x1 + +#define MMU32B_PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \ + ((uint32_t)(nos) << ((idx) + 24))) +#define MMU32B_NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \ + ((uint32_t)(or) << (2 * (idx) + 16))) +#define MMU32B_PRRR_DS0 (1 << 16) +#define MMU32B_PRRR_DS1 (1 << 17) +#define MMU32B_PRRR_NS0 (1 << 18) +#define MMU32B_PRRR_NS1 (1 << 19) + +#define DACR_DOMAIN(num, perm) ((perm) << ((num) * 2)) +#define DACR_DOMAIN_PERM_NO_ACCESS 0x0 +#define DACR_DOMAIN_PERM_CLIENT 0x1 +#define DACR_DOMAIN_PERM_MANAGER 0x3 + +#define NUM_1MB_IN_4GB (1 << 12) +#define NUM_4K_IN_1MB (1 << 8) + +#define ONE_MB_SHIFT 20 + +/* mmu 32b integration */ +#define MMU32B_L1_TABLE_SIZE (NUM_1MB_IN_4GB * 4) +#define MMU32B_L2_TABLE_SIZE (NUM_4K_IN_1MB * 4) +#define MMU32B_L1_TABLE_ALIGN (1 << 14) +#define MMU32B_L2_TABLE_ALIGN (1 << 10) + +static unsigned int next_xlat; +static unsigned long long xlat_max_pa; +static uintptr_t xlat_max_va; + +static uint32_t mmu_l1_base[NUM_1MB_IN_4GB] + __aligned(MMU32B_L1_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +static uint32_t mmu_l2_base[MAX_XLAT_TABLES][NUM_4K_IN_1MB] + __aligned(MMU32B_L2_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +/* + * Array of all memory regions stored in order of ascending base address. + * The list is terminated by the first entry with size == 0. + */ +static mmap_region_t mmap[MAX_MMAP_REGIONS + 1]; + +void print_mmap(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + mmap_region_t *mm = mmap; + + printf("init xlat - l1:%p l2:%p (%d)\n", + (void *)mmu_l1_base, (void *)mmu_l2_base, MAX_XLAT_TABLES); + printf("mmap:\n"); + while (mm->size) { + printf(" VA:%p PA:0x%llx size:0x%zx attr:0x%x\n", + (void *)mm->base_va, mm->base_pa, + mm->size, mm->attr); + ++mm; + }; + printf("\n"); +#endif +} + +void mmap_add(const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while ((mm_cursor->size != 0U) || (mm_cursor->attr != 0U)) { + mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, + mm_cursor->size, mm_cursor->attr); + mm_cursor++; + } +} + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t *mm = mmap; + const mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1U; + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + assert(IS_PAGE_ALIGNED(base_pa)); + assert(IS_PAGE_ALIGNED(base_va)); + assert(IS_PAGE_ALIGNED(size)); + + if (size == 0U) + return; + + assert(base_pa < end_pa); /* Check for overflows */ + assert(base_va < end_va); + + assert((base_va + (uintptr_t)size - (uintptr_t)1) <= + (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert((base_pa + (unsigned long long)size - 1ULL) <= + (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + +#if ENABLE_ASSERTIONS + + /* Check for PAs and VAs overlaps with all other regions */ + for (mm = mmap; mm->size; ++mm) { + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm->base_va) && (end_va <= mm_end_va)) || + ((mm->base_va >= base_va) && (mm_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + */ + if (fully_overlapped_va) { + assert((mm->base_va - mm->base_pa) == + (base_va - base_pa)); + assert((base_va != mm->base_va) || (size != mm->size)); + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_end_pa = + mm->base_pa + mm->size - 1; + + bool separated_pa = (end_pa < mm->base_pa) || + (base_pa > mm_end_pa); + bool separated_va = (end_va < mm->base_va) || + (base_va > mm_end_va); + + assert(separated_va && separated_pa); + } + } + + mm = mmap; /* Restore pointer to the start of the array */ + +#endif /* ENABLE_ASSERTIONS */ + + /* Find correct place in mmap to insert new region */ + while ((mm->base_va < base_va) && (mm->size != 0U)) + ++mm; + + /* + * If a section is contained inside another one with the same base + * address, it must be placed after the one it is contained in: + * + * 1st |-----------------------| + * 2nd |------------| + * 3rd |------| + * + * This is required for mmap_region_attr() to get the attributes of the + * small region correctly. + */ + while ((mm->base_va == base_va) && (mm->size > size)) + ++mm; + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check we haven't lost the empty sentinal from the end of the array */ + assert(mm_last->size == 0U); + + mm->base_pa = base_pa; + mm->base_va = base_va; + mm->size = size; + mm->attr = attr; + + if (end_pa > xlat_max_pa) + xlat_max_pa = end_pa; + if (end_va > xlat_max_va) + xlat_max_va = end_va; +} + +/* map all memory as shared/global/domain0/no-usr access */ +static unsigned long mmap_desc(unsigned attr, unsigned long addr_pa, + unsigned int level) +{ + unsigned long desc; + + switch (level) { + case 1: + assert(!(addr_pa & (MMU32B_L1_TABLE_ALIGN - 1))); + + desc = SECTION_SECTION | SECTION_SHARED; + + desc |= attr & MT_NS ? SECTION_NOTSECURE : 0; + + desc |= SECTION_ACCESS_FLAG; + desc |= attr & MT_RW ? 0 : SECTION_RO; + + desc |= attr & MT_MEMORY ? + SECTION_NORMAL_CACHED : SECTION_DEVICE; + + if ((attr & MT_RW) || !(attr & MT_MEMORY)) + desc |= SECTION_XN; + break; + case 2: + assert(!(addr_pa & (MMU32B_L2_TABLE_ALIGN - 1))); + + desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED; + + desc |= SMALL_PAGE_ACCESS_FLAG; + desc |= attr & MT_RW ? 0 : SMALL_PAGE_RO; + + desc |= attr & MT_MEMORY ? + SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE; + + if ((attr & MT_RW) || !(attr & MT_MEMORY)) + desc |= SMALL_PAGE_XN; + break; + default: + panic(); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only the non-lpae level 2 tables */ + if (level == 2) { + printf(attr & MT_MEMORY ? "MEM" : "dev"); + printf(attr & MT_RW ? "-rw" : "-RO"); + printf(attr & MT_NS ? "-NS" : "-S"); + } +#endif + return desc | addr_pa; +} + +static unsigned int mmap_region_attr(const mmap_region_t *mm, uintptr_t base_va, + size_t size, unsigned int *attr) +{ + /* Don't assume that the area is contained in the first region */ + unsigned int ret = MT_UNKNOWN; + + /* + * Get attributes from last (innermost) region that contains the + * requested area. Don't stop as soon as one region doesn't contain it + * because there may be other internal regions that contain this area: + * + * |-----------------------------1-----------------------------| + * |----2----| |-------3-------| |----5----| + * |--4--| + * + * |---| <- Area we want the attributes of. + * + * In this example, the area is contained in regions 1, 3 and 4 but not + * in region 2. The loop shouldn't stop at region 2 as inner regions + * have priority over outer regions, it should stop at region 5. + */ + for ( ; ; ++mm) { + + if (mm->size == 0U) + return ret; /* Reached end of list */ + + if (mm->base_va > (base_va + size - 1U)) + return ret; /* Next region is after area so end */ + + if ((mm->base_va + mm->size - 1U) < base_va) + continue; /* Next region has already been overtaken */ + + if ((ret == 0U) && (mm->attr == *attr)) + continue; /* Region doesn't override attribs so skip */ + + if ((mm->base_va > base_va) || + ((mm->base_va + mm->size - 1U) < (base_va + size - 1U))) + return MT_UNKNOWN; /* Region doesn't fully cover area */ + + *attr = mm->attr; + ret = 0U; + } + return ret; +} + +static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, + unsigned long base_va, + unsigned long *table, + unsigned int level) +{ + unsigned int level_size_shift = (level == 1) ? + ONE_MB_SHIFT : FOUR_KB_SHIFT; + unsigned int level_size = 1 << level_size_shift; + unsigned long level_index_mask = (level == 1) ? + (NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT : + (NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT; + + assert(level == 1 || level == 2); + + VERBOSE("init xlat table at %p (level%1d)\n", (void *)table, level); + + do { + unsigned long desc = MMU32B_UNSET_DESC; + + if (mm->base_va + mm->size <= base_va) { + /* Area now after the region so skip it */ + ++mm; + continue; + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2) + printf(" 0x%lx %x " + 6 - 2 * level, + base_va, level_size); +#endif + if (mm->base_va >= base_va + level_size) { + /* Next region is after area so nothing to map yet */ + desc = MMU32B_INVALID_DESC; + } else if (mm->base_va <= base_va && mm->base_va + mm->size >= + base_va + level_size) { + /* Next region covers all of area */ + unsigned int attr = mm->attr; + unsigned int r = mmap_region_attr(mm, base_va, + level_size, &attr); + + if (r == 0U) { + desc = mmap_desc(attr, + base_va - mm->base_va + mm->base_pa, + level); + } + } + + if (desc == MMU32B_UNSET_DESC) { + unsigned long xlat_table; + + /* + * Area not covered by a region so need finer table + * Reuse next level table if any (assert attrib matching). + * Otherwise allocate a xlat table. + */ + if (*table) { + assert((*table & 3) == SECTION_PT_PT); + assert(!(*table & SECTION_PT_NOTSECURE) == + !(mm->attr & MT_NS)); + + xlat_table = (*table) & + ~(MMU32B_L1_TABLE_ALIGN - 1); + desc = *table; + } else { + xlat_table = (unsigned long)mmu_l2_base + + next_xlat * MMU32B_L2_TABLE_SIZE; + assert(++next_xlat <= MAX_XLAT_TABLES); + memset((char *)xlat_table, 0, + MMU32B_L2_TABLE_SIZE); + + desc = xlat_table | SECTION_PT_PT; + desc |= mm->attr & MT_NS ? + SECTION_PT_NOTSECURE : 0; + } + /* Recurse to fill in new table */ + mm = init_xlation_table_inner(mm, base_va, + (unsigned long *)xlat_table, + level + 1); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2) + printf("\n"); +#endif + *table++ = desc; + base_va += level_size; + } while (mm->size && (base_va & level_index_mask)); + + return mm; +} + +void init_xlat_tables(void) +{ + print_mmap(); + + assert(!((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1))); + assert(!((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1))); + + memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE); + + init_xlation_table_inner(mmap, 0, (unsigned long *)mmu_l1_base, 1); + + VERBOSE("init xlat - max_va=%p, max_pa=%llx\n", + (void *)xlat_max_va, xlat_max_pa); + assert(xlat_max_va <= PLAT_VIRT_ADDR_SPACE_SIZE - 1); + assert(xlat_max_pa <= PLAT_VIRT_ADDR_SPACE_SIZE - 1); +} + +/******************************************************************************* + * Function for enabling the MMU in Secure PL1, assuming that the + * page-tables have already been created. + ******************************************************************************/ +void enable_mmu_svc_mon(unsigned int flags) +{ + unsigned int prrr; + unsigned int nmrr; + unsigned int sctlr; + + assert(IS_IN_SECURE()); + assert((read_sctlr() & SCTLR_M_BIT) == 0); + + /* Enable Access flag (simplified access permissions) and TEX remap */ + write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT); + + prrr = MMU32B_PRRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 1, 0) \ + | MMU32B_PRRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 2, 1); + nmrr = MMU32B_NMRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 0, 0) \ + | MMU32B_NMRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 1, 1); + + prrr |= MMU32B_PRRR_NS1 | MMU32B_PRRR_DS1; + + write_prrr(prrr); + write_nmrr(nmrr); + + /* Program Domain access control register: domain 0 only */ + write_dacr(DACR_DOMAIN(0, DACR_DOMAIN_PERM_CLIENT)); + + /* Invalidate TLBs at the current exception level */ + tlbiall(); + + /* set MMU base xlat table entry (use only TTBR0) */ + write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS); + write_ttbr1(0); + + /* + * Ensure all translation table writes have drained + * into memory, the TLB invalidation is complete, + * and translation register writes are committed + * before enabling the MMU + */ + dsb(); + isb(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_M_BIT; +#if ARMV7_SUPPORTS_VIRTUALIZATION + sctlr |= SCTLR_WXN_BIT; +#endif + + if (flags & DISABLE_DCACHE) + sctlr &= ~SCTLR_C_BIT; + else + sctlr |= SCTLR_C_BIT; + + write_sctlr(sctlr); + + /* Ensure the MMU enable takes effect immediately */ + isb(); +} diff --git a/make_helpers/armv7-a-cpus.mk b/make_helpers/armv7-a-cpus.mk index 20e7ec533..5571ab0f7 100644 --- a/make_helpers/armv7-a-cpus.mk +++ b/make_helpers/armv7-a-cpus.mk @@ -47,4 +47,9 @@ ifeq ($(filter yes,$(ARM_CORTEX_A7) $(ARM_CORTEX_A12) $(ARM_CORTEX_A15) $(ARM_CO $(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) $(eval $(call add_define,ARMV7_SUPPORTS_VIRTUALIZATION)) $(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER)) +$(eval $(call add_define,ARMV7_SUPPORTS_VFP)) +endif + +ifeq ($(ARM_CORTEX_A5),yes) +$(eval $(call add_define,ARM_CORTEX_A5)) endif diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 115310175..780e6fcbf 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -173,14 +173,11 @@ #define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE #define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ -#define PLAT_ARM_BL31_RUN_UART_BASE V2M_IOFPGA_UART1_BASE -#define PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ -#define PLAT_ARM_SP_MIN_RUN_UART_BASE V2M_IOFPGA_UART1_BASE -#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ - -#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE -#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ #define PLAT_ARM_TSP_UART_BASE V2M_IOFPGA_UART2_BASE #define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART2_CLK_IN_HZ diff --git a/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S new file mode 100644 index 000000000..78f6c68bd --- /dev/null +++ b/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + /* -------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * For AArch32, cold-booting secondary CPUs is not yet + * implemented and they panic. + * -------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup +cb_panic: + b cb_panic +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * unsigned long plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and warm + * boot. On FVP, this information can be queried from the power + * controller. The Power Control SYS Status Register (PSYSR) indicates + * the wake-up reason for the CPU. + * + * For a cold boot, return 0. + * For a warm boot, read the mailbox and return the address it contains. + * + * TODO: PSYSR is a common register and should be + * accessed using locks. Since it is not possible + * to use locks immediately after a cold reset + * we are relying on the fact that after a cold + * reset all cpus will read the same WK field + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO support warm boot */ + /* Cold reset */ + mov r0, #0 + bx lr + +endfunc plat_get_my_entrypoint + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Currently configured for a sigle CPU + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mov r0, #1 + bx lr +endfunc plat_is_my_cpu_primary diff --git a/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts new file mode 100644 index 000000000..9ab2d9656 --- /dev/null +++ b/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + /* Platform Config */ + plat_arm_bl2 { + compatible = "arm,tb_fw"; + hw_config_addr = <0x0 0x82000000>; + hw_config_max_size = <0x01000000>; + /* Disable authentication for development */ + disable_auth = <0x0>; + }; +}; diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c new file mode 100644 index 000000000..47cd87627 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + arm_bl1_early_platform_setup(); +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c new file mode 100644 index 000000000..25e096417 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/sp804_delay_timer.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> +#include <platform_def.h> + +#include "fvp_ve_private.h" + +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) +{ + arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1); + + /* Initialize the platform config for future decision making */ + fvp_ve_config_setup(); +} + +void bl2_platform_setup(void) +{ + arm_bl2_platform_setup(); + +#ifdef FVP_VE_USE_SP804_TIMER + /* + * Enable the clock override for SP804 timer 0, which means that no + * clock dividers are applied and the raw (35 MHz) clock will be used + */ + mmio_write_32(V2M_SP810_BASE, FVP_SP810_CTRL_TIM0_OV); + + /* Initialize delay timer driver using SP804 dual timer 0 */ + sp804_timer_init(V2M_SP804_TIMER0_BASE, + SP804_TIMER_CLKMULT, SP804_TIMER_CLKDIV); +#else + generic_delay_timer_init(); +#endif /* FVP_VE_USE_SP804_TIMER */ +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_common.c b/plat/arm/board/fvp_ve/fvp_ve_common.c new file mode 100644 index 000000000..768dad533 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_common.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <common/debug.h> +#include <lib/mmio.h> +#include <platform_def.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#ifdef IMAGE_BL1 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + {0} +}; +#endif +#ifdef IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH1_RW, + V2M_MAP_IOFPGA, + ARM_MAP_NS_DRAM1, + {0} +}; +#endif +#ifdef IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + MAP_DEVICE0, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +void __init fvp_ve_config_setup(void) +{ + unsigned int sys_id, arch; + + sys_id = mmio_read_32(V2M_SYSREGS_BASE + V2M_SYS_ID); + arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK; + + if (arch != ARCH_MODEL_VE) { + ERROR("This firmware is for FVP VE models\n"); + panic(); + } +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return FVP_VE_TIMER_BASE_FREQUENCY; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_def.h b/plat/arm/board/fvp_ve/fvp_ve_def.h new file mode 100644 index 000000000..565753ae7 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_def.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_DEF_H +#define FVP_VE_DEF_H + +#include <lib/utils_def.h> + +/* Default cluster count for FVP VE */ +#define FVP_VE_CLUSTER_COUNT 1 + +/* Default number of CPUs per cluster on FVP VE */ +#define FVP_VE_MAX_CPUS_PER_CLUSTER 1 + +/* Default number of threads per CPU on FVP VE */ +#define FVP_VE_MAX_PE_PER_CPU 1 + +#define FVP_VE_CORE_COUNT 1 + +#define FVP_VE_PRIMARY_CPU 0x0 + +/******************************************************************************* + * FVP memory map related constants + ******************************************************************************/ + +#define FLASH1_BASE 0x0c000000 +#define FLASH1_SIZE 0x04000000 + +/* Aggregate of all devices in the first GB */ +#define DEVICE0_BASE 0x20000000 +#define DEVICE0_SIZE 0x0c200000 + +#define NSRAM_BASE 0x2e000000 +#define NSRAM_SIZE 0x10000 + +#define PCIE_EXP_BASE 0x40000000 +#define TZRNG_BASE 0x7fe60000 + +#define ARCH_MODEL_VE 0x5 + +/* FVP Power controller base address*/ +#define PWRC_BASE UL(0x1c100000) + +/* FVP SP804 timer frequency is 35 MHz*/ +#define SP804_TIMER_CLKMULT 1 +#define SP804_TIMER_CLKDIV 35 + +/* SP810 controller. FVP specific flags */ +#define FVP_SP810_CTRL_TIM0_OV (1 << 16) +#define FVP_SP810_CTRL_TIM1_OV (1 << 18) +#define FVP_SP810_CTRL_TIM2_OV (1 << 20) +#define FVP_SP810_CTRL_TIM3_OV (1 << 22) + +/******************************************************************************* + * GIC-400 & interrupt handling related constants + ******************************************************************************/ +/* VE compatible GIC memory map */ +#define VE_GICD_BASE 0x2c001000 +#ifdef ARM_CORTEX_A5 +#define VE_GICC_BASE 0x2c000100 +#else +#define VE_GICC_BASE 0x2c002000 +#endif +#define VE_GICH_BASE 0x2c004000 +#define VE_GICV_BASE 0x2c006000 + +#define FVP_VE_IRQ_TZ_WDOG 56 +#define FVP_VE_IRQ_SEC_SYS_TIMER 57 + +#define V2M_FLASH1_BASE UL(0x0C000000) +#define V2M_FLASH1_SIZE UL(0x04000000) + +#define V2M_MAP_FLASH1_RW MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define V2M_MAP_FLASH1_RO MAP_REGION_FLAT(V2M_FLASH1_BASE,\ + V2M_FLASH1_SIZE, \ + MT_RO_DATA | MT_SECURE) + +#endif /* FVP_VE_DEF_H */ diff --git a/plat/arm/board/fvp_ve/fvp_ve_pm.c b/plat/arm/board/fvp_ve/fvp_ve_pm.c new file mode 100644 index 000000000..a4d627b1d --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_pm.c @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2019, Arm Limited. All rights reserved. +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Export the platform handlers via fvp_ve_psci_pm_ops. The ARM Standard + * platform layer will take care of registering the handlers with PSCI. + ******************************************************************************/ +plat_psci_ops_t fvp_ve_psci_pm_ops = { + /* dummy struct */ + .validate_ns_entrypoint = NULL, +}; + +int __init plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &fvp_ve_psci_pm_ops; + + return 0; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_private.h b/plat/arm/board/fvp_ve/fvp_ve_private.h new file mode 100644 index 000000000..5d396bcc9 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_VE_PRIVATE_H +#define FVP_VE_PRIVATE_H + +#include <plat/arm/common/plat_arm.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_ve_config_setup(void); + +#endif /* FVP_VE_PRIVATE_H */ diff --git a/plat/arm/board/fvp_ve/fvp_ve_security.c b/plat/arm/board/fvp_ve/fvp_ve_security.c new file mode 100644 index 000000000..24465cba2 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_security.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * We assume that all security programming is done by the primary core. + */ +void plat_arm_security_setup(void) +{ + /* + * The Base FVP has a TrustZone address space controller, the Foundation + * FVP does not. Trying to program the device on the foundation FVP will + * cause an abort. + * + * If the platform had additional peripheral specific security + * configurations, those would be configured here. + */ + + return; +} diff --git a/plat/arm/board/fvp_ve/fvp_ve_topology.c b/plat/arm/board/fvp_ve/fvp_ve_topology.c new file mode 100644 index 000000000..51cc9da00 --- /dev/null +++ b/plat/arm/board/fvp_ve/fvp_ve_topology.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <platform_def.h> + +#include <drivers/arm/fvp/fvp_pwrc.h> +#include <plat/arm/common/arm_config.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +/* The FVP VE power domain tree descriptor */ +static const unsigned char fvp_ve_power_domain_tree_desc[] = { + 1, + /* No of children for the root node */ + FVP_VE_CLUSTER_COUNT, + /* No of children for the first cluster node */ + FVP_VE_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the topology according to FVP_VE_CLUSTER_COUNT. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return fvp_ve_power_domain_tree_desc; +} + +/******************************************************************************* + * Currently FVP VE has only been tested with one core, therefore 0 is returned. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + return 0; +} diff --git a/plat/arm/board/fvp_ve/include/platform_def.h b/plat/arm/board/fvp_ve/include/platform_def.h new file mode 100644 index 000000000..1870442f0 --- /dev/null +++ b/plat/arm/board/fvp_ve/include/platform_def.h @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <common/tbbr/tbbr_img_def.h> +#include <lib/utils_def.h> +#include <lib/xlat_tables/xlat_tables_defs.h> +#include <plat/arm/board/common/v2m_def.h> +#include <plat/common/common_def.h> + +#include "../fvp_ve_def.h" + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* Memory location options for TSP */ +#define ARM_DRAM_ID 2 + +#define ARM_DRAM1_BASE UL(0x80000000) +#define ARM_DRAM1_SIZE UL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1) + +#define ARM_DRAM2_BASE UL(0x880000000) +#define ARM_DRAM2_SIZE PLAT_ARM_DRAM2_SIZE +#define ARM_DRAM2_END (ARM_DRAM2_BASE + \ + ARM_DRAM2_SIZE - 1) + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +/* + * The last 2MB is meant to be NOLOAD and will not be zero + * initialized. + */ +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + 0x00200000) + + +/* The first 4KB of NS DRAM1 are used as shared memory */ +#define FVP_VE_SHARED_RAM_BASE ARM_NS_DRAM1_BASE +#define FVP_VE_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */ + +/* The next 252 kB of NS DRAM is used to load the BL images */ +#define ARM_BL_RAM_BASE (FVP_VE_SHARED_RAM_BASE + \ + FVP_VE_SHARED_RAM_SIZE) +#define ARM_BL_RAM_SIZE (PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE - \ + FVP_VE_SHARED_RAM_SIZE) + + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define ARM_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_G0_IRQ_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + FVP_VE_SHARED_RAM_BASE, \ + FVP_VE_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define ARM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + ARM_NS_DRAM1_BASE, \ + ARM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_DRAM2 MAP_REGION_FLAT( \ + ARM_DRAM2_BASE, \ + ARM_DRAM2_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | MT_SECURE), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | MT_SECURE) + +#if USE_COHERENT_MEM +#define ARM_MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \ + BL_COHERENT_RAM_BASE, \ + BL_COHERENT_RAM_END \ + - BL_COHERENT_RAM_BASE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +/* + * The max number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU. + */ +#define ARM_BL_REGIONS 5 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#define FVP_VE_TIMER_BASE_FREQUENCY UL(24000000) +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#define ARM_SYS_CNT_BASE_S UL(0x2a820000) +#define ARM_SYS_CNT_BASE_NS UL(0x2a830000) + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* Trusted Watchdog constants */ +#define ARM_SP805_TWDG_BASE UL(0x1C0F0000) +#define ARM_SP805_TWDG_CLK_HZ 32768 +/* The TBBR document specifies a watchdog timeout of 256 seconds. SP805 + * asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */ +#define ARM_TWDG_TIMEOUT_SEC 128 +#define ARM_TWDG_LOAD_VAL (ARM_SP805_TWDG_CLK_HZ * \ + ARM_TWDG_TIMEOUT_SEC) + +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) + +/* + * This macro defines the deepest retention state possible. A higher state + * id will represent an invalid or a power down state. + */ +#define PLAT_MAX_RET_STATE 1 + +/* + * This macro defines the deepest power down states possible. Any state ID + * higher than this is invalid. + */ +#define PLAT_MAX_OFF_STATE 2 + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_GRANULE (U(1) << ARM_CACHE_WRITEBACK_SHIFT) + +/* + * To enable TB_FW_CONFIG to be loaded by BL1, define the corresponding base + * and limit. Leave enough space of BL2 meminfo. + */ +#define ARM_TB_FW_CONFIG_BASE (ARM_BL_RAM_BASE + sizeof(meminfo_t)) +#define ARM_TB_FW_CONFIG_LIMIT (ARM_BL_RAM_BASE + PAGE_SIZE) + +/******************************************************************************* + * BL1 specific defines. + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + ******************************************************************************/ +#define BL1_RO_BASE 0x00000000 +#define BL1_RO_LIMIT PLAT_ARM_TRUSTED_ROM_SIZE +/* + * Put BL1 RW at the top of the memory allocated for BL images in NS DRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE)) + + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ + +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - FVP_VE_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE + + +/* Put BL32 below BL2 in NS DRAM.*/ +#define ARM_BL2_MEM_DESC_BASE ARM_TB_FW_CONFIG_LIMIT + +#define BL32_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL32_SIZE) +#define BL32_PROGBITS_LIMIT BL2_BASE +#define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +/* Required platform porting definitions */ +#define PLATFORM_CORE_COUNT 1 +#define PLAT_NUM_PWR_DOMAINS ((FVP_VE_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + 1) + +#define PLAT_MAX_PWR_LVL 2 + +/* + * Other platform porting definitions are provided by included headers + */ + +/* + * Required ARM standard platform porting definitions + */ + +#define PLAT_ARM_BL_PLUS_SHARED_RAM_SIZE 0x00040000 /* 256 KB */ + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x04000000 /* 64 MB */ + +#define PLAT_ARM_DRAM2_SIZE ULL(0x80000000) + +/* + * Load address of BL33 for this platform port + */ +#define PLAT_ARM_NS_IMAGE_BASE (ARM_DRAM1_BASE + U(0x8000000)) + +/* + * PLAT_ARM_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 6 +#else +# define PLAT_ARM_MMAP_ENTRIES 12 +# define MAX_XLAT_TABLES 6 +#endif + +/* + * PLAT_ARM_MAX_BL1_RW_SIZE is calculated using the current BL1 RW debug size + * plus a little space for growth. + */ +#define PLAT_ARM_MAX_BL1_RW_SIZE 0xB000 + +/* + * FVP_VE_MAX_BL2_SIZE is calculated using the current BL2 debug size plus a + * little space for growth. + */ +#define FVP_VE_MAX_BL2_SIZE 0x11000 + +/* + * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is + * calculated using the current SP_MIN PROGBITS debug size plus the sizes of + * BL2 and BL1-RW + */ +#define PLAT_ARM_MAX_BL32_SIZE 0x3B000 +/* + + * Size of cacheable stacks + */ +#if defined(IMAGE_BL1) +# define PLATFORM_STACK_SIZE 0x440 +#elif defined(IMAGE_BL2) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +/* Reserve the last block of flash for PSCI MEM PROTECT flag */ +#define PLAT_ARM_FIP_BASE V2M_FLASH1_BASE +#define PLAT_ARM_FIP_MAX_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +#define PLAT_ARM_NVM_BASE V2M_FLASH1_BASE +#define PLAT_ARM_NVM_SIZE (V2M_FLASH1_SIZE - V2M_FLASH_BLOCK_SIZE) + +/* + * PL011 related constants + */ +#define PLAT_ARM_BOOT_UART_BASE V2M_IOFPGA_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE V2M_IOFPGA_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ V2M_IOFPGA_UART1_CLK_IN_HZ + +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 1 + +/* Mailbox base address */ +#define FVP_VE_TRUSTED_MAILBOX_BASE FVP_VE_SHARED_RAM_BASE + +/* + * GIC related constants to cater for GICv2 + */ +#define PLAT_ARM_GICD_BASE VE_GICD_BASE +#define PLAT_ARM_GICC_BASE VE_GICC_BASE + +/* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLAT_ARM_G1S_IRQ_PROPS(grp) \ + ARM_G1S_IRQ_PROPS(grp), \ + INTR_PROP_DESC(FVP_VE_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(FVP_VE_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +#endif /* PLATFORM_H */ diff --git a/plat/arm/board/fvp_ve/platform.mk b/plat/arm/board/fvp_ve/platform.mk new file mode 100644 index 000000000..f9ced2cc3 --- /dev/null +++ b/plat/arm/board/fvp_ve/platform.mk @@ -0,0 +1,125 @@ +# +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifdef ARM_CORTEX_A5 +# Use the SP804 timer instead of the generic one +FVP_VE_USE_SP804_TIMER := 1 +$(eval $(call add_define,FVP_VE_USE_SP804_TIMER)) +BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c +endif + +FVP_VE_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + plat/common/plat_gicv2.c \ + plat/arm/common/arm_gicv2.c + +FVP_VE_SECURITY_SOURCES := plat/arm/board/fvp_ve/fvp_ve_security.c + +PLAT_INCLUDES := -Iplat/arm/board/fvp_ve/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/fvp_ve/fvp_ve_common.c \ + plat/arm/common/${ARCH}/arm_helpers.S \ + plat/arm/common/arm_common.c \ + plat/arm/common/arm_console.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/arm/board/common/${ARCH}/board_arm_helpers.S + +ifdef ARM_CORTEX_A5 +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a5.S +else +FVP_VE_CPU_LIBS := lib/cpus/aarch32/cortex_a7.S +endif + +BL1_SOURCES += drivers/arm/sp805/sp805.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl1_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/common/arm_io_storage.c \ + drivers/cfi/v2m/v2m_flash.c \ + plat/arm/board/fvp_ve/${ARCH}/fvp_ve_helpers.S \ + plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + ${FVP_VE_CPU_LIBS} \ + ${DYN_CFG_SOURCES} + +BL2_SOURCES += plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/cfi/v2m/v2m_flash.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/arm/common/arm_bl2_setup.c \ + plat/arm/common/arm_err.c \ + plat/arm/common/arm_io_storage.c \ + plat/arm/common/${ARCH}/arm_bl2_mem_params_desc.c \ + plat/arm/common/arm_image_load.c \ + common/desc_image_load.c \ + ${DYN_CFG_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} + +# Add the FDT_SOURCES and options for Dynamic Config (only for Unix env) +ifdef UNIX_MK + +FDT_SOURCES += plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts + +FVP_TB_FW_CONFIG := ${BUILD_PLAT}/fdts/fvp_ve_tb_fw_config.dtb + +# Add the TB_FW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_TB_FW_CONFIG},--tb-fw-config)) + +FDT_SOURCES += ${FVP_HW_CONFIG_DTS} +$(eval FVP_HW_CONFIG := ${BUILD_PLAT}/$(patsubst %.dts,%.dtb, \ + fdts/$(notdir ${FVP_HW_CONFIG_DTS}))) +# Add the HW_CONFIG to FIP and specify the same to certtool +$(eval $(call TOOL_ADD_PAYLOAD,${FVP_HW_CONFIG},--hw-config)) +endif + +NEED_BL32 := yes + +# Modification of arm_common.mk + +# Process ARM_DISABLE_TRUSTED_WDOG flag +# By default, Trusted Watchdog is always enabled unless SPIN_ON_BL1_EXIT is set +ARM_DISABLE_TRUSTED_WDOG := 0 +ifeq (${SPIN_ON_BL1_EXIT}, 1) +ARM_DISABLE_TRUSTED_WDOG := 1 +endif +$(eval $(call assert_boolean,ARM_DISABLE_TRUSTED_WDOG)) +$(eval $(call add_define,ARM_DISABLE_TRUSTED_WDOG)) + +# Use translation tables library v1 if using Cortex-A5 +ifdef ARM_CORTEX_A5 +ARM_XLAT_TABLES_LIB_V1 := 1 +else +ARM_XLAT_TABLES_LIB_V1 := 0 +endif +$(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) +$(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1)) + +MULTI_CONSOLE_API := 1 + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + # Only use nonlpae version of xlatv1 otherwise use xlat v2 + PLAT_BL_COMMON_SOURCES += lib/xlat_tables/${ARCH}/nonlpae_tables.c +else + include lib/xlat_tables_v2/xlat_tables.mk + PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} +endif + +# Add `libfdt` and Arm common helpers required for Dynamic Config +include lib/libfdt/libfdt.mk + +DYN_CFG_SOURCES += plat/arm/common/arm_dyn_cfg.c \ + plat/arm/common/arm_dyn_cfg_helpers.c \ + common/fdt_wrappers.c + diff --git a/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c new file mode 100644 index 000000000..e6a1bbec2 --- /dev/null +++ b/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <plat/arm/common/plat_arm.h> + +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + arm_sp_min_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} diff --git a/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk new file mode 100644 index 000000000..4ca810d3f --- /dev/null +++ b/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# SP_MIN source files specific to FVP platform +BL32_SOURCES += drivers/cfi/v2m/v2m_flash.c \ + lib/utils/mem_region.c \ + plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S \ + drivers/arm/fvp/fvp_pwrc.c \ + plat/arm/board/fvp_ve/fvp_ve_pm.c \ + plat/arm/board/fvp_ve/fvp_ve_topology.c \ + plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c \ + lib/aarch32/arm32_aeabi_divmod.c \ + lib/aarch32/arm32_aeabi_divmod_a32.S \ + plat/arm/common/sp_min/arm_sp_min_setup.c \ + plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c \ + ${FVP_VE_CPU_LIBS} \ + ${FVP_VE_GIC_SOURCES} \ + ${FVP_VE_SECURITY_SOURCES} diff --git a/plat/arm/board/n1sdp/include/platform_def.h b/plat/arm/board/n1sdp/include/platform_def.h index 7b8c367a2..83b9f52d2 100644 --- a/plat/arm/board/n1sdp/include/platform_def.h +++ b/plat/arm/board/n1sdp/include/platform_def.h @@ -15,14 +15,14 @@ #define PLAT_ARM_BOOT_UART_BASE 0x2A400000 #define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000 -#define PLAT_ARM_BL31_RUN_UART_BASE 0x2A410000 -#define PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ 50000000 +#define PLAT_ARM_RUN_UART_BASE 0x2A410000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ 50000000 #define PLAT_ARM_SP_MIN_RUN_UART_BASE 0x2A410000 #define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ 50000000 -#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_BL31_RUN_UART_BASE -#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ +#define PLAT_ARM_CRASH_UART_BASE PLAT_ARM_RUN_UART_BASE +#define PLAT_ARM_CRASH_UART_CLK_IN_HZ PLAT_ARM_RUN_UART_CLK_IN_HZ #define PLAT_ARM_DRAM2_SIZE ULL(0x780000000) diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index fd4809c16..1e9edefd5 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -155,8 +155,12 @@ void arm_bl1_platform_setup(void) * Allow access to the System counter timer module and program * counter frequency for non secure images during FWU */ +#ifdef ARM_SYS_TIMCTL_BASE arm_configure_sys_timer(); +#endif +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif } void bl1_platform_setup(void) diff --git a/plat/arm/common/arm_console.c b/plat/arm/common/arm_console.c index 03670858c..84886b470 100644 --- a/plat/arm/common/arm_console.c +++ b/plat/arm/common/arm_console.c @@ -61,8 +61,8 @@ void arm_console_boot_end(void) void arm_console_runtime_init(void) { #if MULTI_CONSOLE_API - int rc = console_pl011_register(PLAT_ARM_BL31_RUN_UART_BASE, - PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, + int rc = console_pl011_register(PLAT_ARM_RUN_UART_BASE, + PLAT_ARM_RUN_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE, &arm_runtime_console); if (rc == 0) @@ -70,8 +70,8 @@ void arm_console_runtime_init(void) console_set_scope(&arm_runtime_console.console, CONSOLE_FLAG_RUNTIME); #else - (void)console_init(PLAT_ARM_BL31_RUN_UART_BASE, - PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, + (void)console_init(PLAT_ARM_RUN_UART_BASE, + PLAT_ARM_RUN_UART_CLK_IN_HZ, ARM_CONSOLE_BAUDRATE); #endif /* MULTI_CONSOLE_API */ } diff --git a/plat/arm/common/arm_dyn_cfg.c b/plat/arm/common/arm_dyn_cfg.c index 1c58649ba..9a5364952 100644 --- a/plat/arm/common/arm_dyn_cfg.c +++ b/plat/arm/common/arm_dyn_cfg.c @@ -243,10 +243,11 @@ void arm_bl2_dyn_cfg_init(void) if (check_uptr_overflow(image_base, image_size)) continue; +#ifdef BL31_BASE /* Ensure the configs don't overlap with BL31 */ if ((image_base > BL31_BASE) || ((image_base + image_size) > BL31_BASE)) continue; - +#endif /* Ensure the configs are loaded in a valid address */ if (image_base < ARM_BL_RAM_BASE) continue; diff --git a/plat/arm/common/sp_min/arm_sp_min_setup.c b/plat/arm/common/sp_min/arm_sp_min_setup.c index c0ea027b8..bb69914ae 100644 --- a/plat/arm/common/sp_min/arm_sp_min_setup.c +++ b/plat/arm/common/sp_min/arm_sp_min_setup.c @@ -193,12 +193,14 @@ void sp_min_platform_setup(void) #endif /* Enable and initialize the System level generic timer */ +#ifdef ARM_SYS_CNTCTL_BASE mmio_write_32(ARM_SYS_CNTCTL_BASE + CNTCR_OFF, CNTCR_FCREQ(0U) | CNTCR_EN); - +#endif +#ifdef ARM_SYS_TIMCTL_BASE /* Allow access to the System counter timer module */ arm_configure_sys_timer(); - +#endif /* Initialize power controller before setting up topology */ plat_arm_pwrc_setup(); } |