From 84204047c731b4c6308b5c3de6ad4dd077191536 Mon Sep 17 00:00:00 2001 From: Sarat Chand Savitala Date: Thu, 6 Aug 2015 01:36:31 +0530 Subject: [PATCH] sw_apps:zynqmp_fsbl: Added A53 32-bit support in FSBL This patch adds support for FSBL running in A53 32-bit mode and also supports handing off to A53 32-bit applications from FSBL. Signed-off-by: Sarat Chand Savitala Acked-by: Krishna Chaitanya Patakamuri --- lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl | 31 ++-- lib/sw_apps/zynqmp_fsbl/src/lscript.ld | 7 +- lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S | 19 ++- lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c | 137 ++++++++++++++++-- .../zynqmp_fsbl/src/xfsbl_image_header.h | 1 + .../zynqmp_fsbl/src/xfsbl_initialization.c | 15 +- lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h | 1 + 7 files changed, 182 insertions(+), 29 deletions(-) diff --git a/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl index ea8a8540..b2866862 100755 --- a/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl +++ b/lib/sw_apps/zynqmp_fsbl/data/zynqmp_fsbl.tcl @@ -119,7 +119,7 @@ proc swapp_generate {} { set hw_processor [common::get_property HW_INSTANCE $proc_instance] set proc_type [common::get_property IP_NAME [hsi::get_cells -hier $hw_processor]]; - # based on the CPU (A53 or R5), + # based on the CPU (A53 64-bit, A53 32-bit or R5), # remove unnecesary linker script and retain just one: lscript.ld # set the compiler flags if { $proc_type == "psu_cortexr5" } { @@ -130,16 +130,29 @@ proc swapp_generate {} { -value {-Wall -fmessage-length=0 -mcpu=cortex-r5 -mfloat-abi=softfp} \ -objects [current_sw_design ] } else { - set ld_file "lscript.ld" - file delete -force $ld_file + set compiler [get_property CONFIG.compiler $proc_instance] - set ld_file_a53 "lscript_a53.ld" - set ld_file_new "lscript.ld" - file rename -force $ld_file_a53 $ld_file_new + if {[string compare -nocase $compiler "arm-none-eabi-gcc"] == 0} { + # A53 32-bit : Use same linker script as that of R5 + set ld_file_a53 "lscript_a53.ld" + file delete -force $ld_file_a53 - set_property -name {APP_COMPILER_FLAGS} \ - -value {-Wall -fmessage-length=0 -DXFSBL_A53} \ - -objects [current_sw_design ] + set_property -name {APP_COMPILER_FLAGS} \ + -value {-Wall -fmessage-length=0 -march=armv7-a} \ + -objects [current_sw_design ] + } else { + #A53 64-bit + set ld_file "lscript.ld" + file delete -force $ld_file + + set ld_file_a53 "lscript_a53.ld" + set ld_file_new "lscript.ld" + file rename -force $ld_file_a53 $ld_file_new + + set_property -name {APP_COMPILER_FLAGS} \ + -value {-Wall -fmessage-length=0 -DXFSBL_A53} \ + -objects [current_sw_design ] + } } } diff --git a/lib/sw_apps/zynqmp_fsbl/src/lscript.ld b/lib/sw_apps/zynqmp_fsbl/src/lscript.ld index 03bcc4f2..d32f4933 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/lscript.ld +++ b/lib/sw_apps/zynqmp_fsbl/src/lscript.ld @@ -32,7 +32,7 @@ /*******************************************************************/ /* */ -/* Description : FSBL R5 Linker Script */ +/* Description : FSBL R5 and A53(32-bit) Linker Script */ /* */ /*******************************************************************/ @@ -63,7 +63,7 @@ ENTRY(_vector_table) SECTIONS { .text : { - *(.vectors) + KEEP (*(.vectors)) *(.boot) *(.text) *(.text.*) @@ -76,6 +76,7 @@ SECTIONS *(.vfp11_veneer) *(.ARM.extab) *(.gnu.linkonce.armextab.*) + *(.note.gnu.build-id) } > psu_ram_0_S_AXI_BASEADDR .init : { @@ -235,7 +236,7 @@ SECTIONS *(.sbss.*) *(.gnu.linkonce.sb.*) __sbss_end = .; -} > psu_ram_0_S_AXI_BASEADDR +} > psu_ram_1_S_AXI_BASEADDR .tdata : { __tdata_start = .; diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S index 453576ef..02488bbb 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_exit.S @@ -94,8 +94,19 @@ XFsbl_Exit: mcr 15,0,r4,cr1,cr0,0 isb - cmp r1,#0 - bne XFsbl_StartApp + cmp r1, #0 /* exit to wfe */ + beq XFsbl_Loop + + cmp r1, #2 /* x1 is 2 - exit in aarch32 */ + beq XFsbl_StartApp + + /* x1 is 1 - exit in aarch64 */ + mov r2, #3 /* request for warm reset and aarch64 */ + dsb + isb + mcr p15, 0, r2, c12, c0, 2 /* write to reset management register */ + isb + #else mov x30, x0 /* move the destination address into x30 register */ @@ -120,7 +131,9 @@ XFsbl_Exit: /* x1 is 2 - exit in aarch32 */ - mov x2, #3 /* request for warm reset and aarch32 */ + mov x2, #2 /* request for warm reset and aarch32 */ + dsb sy + isb msr RMR_EL3,x2 /* write to reset management register */ isb #endif diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c index c7e882e3..747a1e77 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_handoff.c @@ -69,6 +69,10 @@ #define APU_CONFIG_0_AA64N32_MASK_CPU2 (0x4U) #define APU_CONFIG_0_AA64N32_MASK_CPU3 (0x8U) +#define OTHER_CPU_HANDOFF (0x0U) +#define A53_0_64_HANDOFF_TO_A53_0_32 (0x1U) +#define A53_0_32_HANDOFF_TO_A53_0_64 (0x2U) + /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ @@ -78,8 +82,9 @@ /************************** Function Prototypes ******************************/ static u32 XFsbl_SetCpuPwrSettings (u32 CpuSettings, u32 Flags); -static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings); -static void XFsbl_CopyIVT(u32 CpuSettings); +static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings, + u32 HandoffType); +static void XFsbl_CopyIVT(u32 CpuSettings, u32 HandoffType); static int XFsbl_Is32BitCpu(u32 CpuSettings); /** @@ -572,7 +577,8 @@ void XFsbl_HandoffExit(u64 HandoffAddress, u32 Flags) * * *****************************************************************************/ -static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings) +static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings, + u32 HandoffType) { u32 HandOffAddressLow=0U; u32 HandOffAddressHigh=0U; @@ -585,7 +591,7 @@ static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings) /** * copy the IVT to 0xffff0000 */ - XFsbl_CopyIVT(CpuSettings); + XFsbl_CopyIVT(CpuSettings, HandoffType); /** * Writing u64/u32 will be decided on the handoff Cpu @@ -593,11 +599,22 @@ static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings) if (XFsbl_Is32BitCpu(CpuSettings) == TRUE) { /** - * for R5 cpu, write 32bit handoff address + * for R5 and A53(32-bit) cpus, write 32bit handoff address + * Hence is also applicable for A53_0_64_TO_A53_0_32 */ XFsbl_Out32(XFSBL_HANDOFF_ADDR_PTR, (u32 )HandOffAddress); - } else { + } else if (HandoffType == A53_0_32_HANDOFF_TO_A53_0_64) { + /** + * for A53_0_32_TO_A53_0_64 case, write 64 bit handoff address + * to the predfined location + */ + XFsbl_Out32(XFSBL_HANDOFF_ADDR_PTR, + (u32 )(HandOffAddress & 0xFFFFFFFFU)); + XFsbl_Out32(XFSBL_HANDOFF_ADDR_PTR+4U, + (u32 )((HandOffAddress>>32) & 0xFFFFFFFFU)); + } + else { /** * for A53 cpu, write 64bit handoff address * to the RVBARADDR in APU @@ -642,14 +659,17 @@ static void XFsbl_UpdateResetVector (u64 HandOffAddress, u32 CpuSettings) * This function will copy the Arm predefined code to the Reset IVT address * * @param CpuId is used to determine which arm predefined code to be loaded - Supports R5, A53/A53 processors + * by checking if the handoff cpu is of 32 bit + * + * @param HandoffType used to determine which arm A53 predefined code to be + * loaded. Supports handoff to A53(32-bit) and A53(64bit) processors * * @return * * @note * *****************************************************************************/ -static void XFsbl_CopyIVT(u32 CpuSettings) +static void XFsbl_CopyIVT(u32 CpuSettings, u32 HandoffType) { u32 Index=0U; const u32 XFsbl_ArmR5PredefinedCode[] = @@ -689,21 +709,89 @@ static void XFsbl_CopyIVT(u32 CpuSettings) 0xE12FFF1EU }; + const u32 XFsbl_ArmA53Cpu32PredefinedCode[] = + { + /** + * 1. Move 0xffffff00 to r0 + * 2. load value stored in r0 to lr + * 3. dsb + * 4. isb + * 5. branch to lr + */ + + /* mvn r0, #255 */ + 0xE3E000FFU, + /* ldr lr, [r0] */ + 0xE590E000U, + /* dsb */ + 0xF57FF04FU, + /* isb */ + 0xF57FF06FU, + /* bx lr */ + 0xE12FFF1EU + }; + + const u32 XFsbl_ArmA53Cpu64PredefinedCode[] = + { + /** + * 1. Move 0xffffff00 to x0 + * 2. load value stored in x0 to x30 + * 3. dsb + * 4. isb + * 5. branch to x30 + */ + + /* mov x0, #0xffffff00 */ + 0xB2785FE0U, + /* ldr x30, [x0] */ + 0xF940001EU, + /* dsb sy */ + 0xD5033F9FU, + /* isb */ + 0xD5033FDFU, + /* br x30 */ + 0xD61F03C0U + }; + + + /** * Load the predefined ARM code to the reset vector address * For R5 load the R5 code otherwise A53 code */ - if (XFsbl_Is32BitCpu(CpuSettings) == TRUE) - { + if ((XFsbl_Is32BitCpu(CpuSettings) == TRUE) && + (HandoffType == OTHER_CPU_HANDOFF)) { /** * Load R5 code */ - for (Index=0U;Index<10U;Index++) + for (Index=0U; + Index < sizeof(XFsbl_ArmR5PredefinedCode)/sizeof(u32); Index++) { XFsbl_Out32(XFSBL_IVT_ADDRESS + (Index*4U), XFsbl_ArmR5PredefinedCode[Index]); } } + else if (HandoffType == A53_0_64_HANDOFF_TO_A53_0_32) { + for (Index=0U; + Index < sizeof(XFsbl_ArmA53Cpu32PredefinedCode)/sizeof(u32); + Index++) { + XFsbl_Out32(XFSBL_IVT_ADDRESS + (Index*4U), + XFsbl_ArmA53Cpu32PredefinedCode[Index]); + } + } + else if (HandoffType == A53_0_32_HANDOFF_TO_A53_0_64) { + for (Index=0U; + Index < sizeof(XFsbl_ArmA53Cpu64PredefinedCode)/sizeof(u32); + Index++) { + XFsbl_Out32(XFSBL_IVT_ADDRESS + (Index*4U), + XFsbl_ArmA53Cpu64PredefinedCode[Index]); + } + } + else { + /* for MISRA C compliance */ + } + + return; } @@ -849,7 +937,8 @@ u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr, u32 PartitionNum, u32 EarlyHandoff /** * Update the handoff address at reset vector address */ - XFsbl_UpdateResetVector(HandoffAddress, CpuSettings); + XFsbl_UpdateResetVector(HandoffAddress, CpuSettings, + OTHER_CPU_HANDOFF); XFsbl_Printf(DEBUG_INFO,"CPU 0x%0lx reset release, " "Exec State 0x%0lx, HandoffAddress: %0lx\n\r", @@ -894,8 +983,30 @@ u32 XFsbl_Handoff (XFsblPs * FsblInstancePtr, u32 PartitionNum, u32 EarlyHandoff */ RunningCpuHandoffAddressPresent = TRUE; RunningCpuHandoffAddress = (u64 ) - FsblInstancePtr->HandoffValues[CpuIndex].HandoffAddress; + FsblInstancePtr->HandoffValues[CpuIndex].HandoffAddress; RunningCpuExecState = ExecState; + + /** + * Update reset vector address for + * - FSBL running on A53-0 (64bit), handoff to A53-0 (32 bit) + * - FSBL running on A53-0 (32bit), handoff to A53-0 (64 bit) + */ + if ((FsblInstancePtr->A53ExecState == + XIH_PH_ATTRB_A53_EXEC_ST_AA64) && + (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA32)) { + XFsbl_UpdateResetVector(RunningCpuHandoffAddress, + CpuSettings, A53_0_64_HANDOFF_TO_A53_0_32); + } + else if ((FsblInstancePtr->A53ExecState == + XIH_PH_ATTRB_A53_EXEC_ST_AA32) && + (ExecState == XIH_PH_ATTRB_A53_EXEC_ST_AA64)) { + XFsbl_UpdateResetVector(RunningCpuHandoffAddress, + CpuSettings, A53_0_32_HANDOFF_TO_A53_0_64); + } + else + { + /* for MISRA C compliance */ + } } } diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h index 2f72a0ed..b27d8a25 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_image_header.h @@ -170,6 +170,7 @@ extern "C" { #define XIH_PH_ATTRB_A53_EXEC_ST_AA32 (0x0008U) #define XIH_PH_ATTRB_A53_EXEC_ST_AA64 (0x0000U) +#define XIH_INVALID_EXEC_ST (0xFFFFU) /** * Below is the bit mapping of fields in the ATF Handoff parameters * with that of Partition header. The number of bits shifted is diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c index 91a7b3ee..0ea0ff7a 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_initialization.c @@ -259,10 +259,23 @@ static u32 XFsbl_ProcessorInit(XFsblPs * FsblInstancePtr) * Need a check for unsupported Cluster ID */ if ((ClusterId & XFSBL_CLUSTER_ID_MASK) == XFSBL_A53_PROCESSOR) { - XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 Processor \n\r"); + XFsbl_Printf(DEBUG_GENERAL,"Running on A53-0 "); FsblInstancePtr->ProcessorID = XIH_PH_ATTRB_DEST_CPU_A53_0; +#ifndef __aarch32__ + /* Running on A53 64-bit */ + XFsbl_Printf(DEBUG_GENERAL,"(64-bit) Processor \n\r"); + FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA64; +#else + /* Running on A53 32-bit */ + XFsbl_Printf(DEBUG_GENERAL,"(32-bit) Processor \n\r"); + FsblInstancePtr->A53ExecState = XIH_PH_ATTRB_A53_EXEC_ST_AA32; +#endif + } else { + /* A53ExecState is not valid for R5 */ + FsblInstancePtr->A53ExecState = XIH_INVALID_EXEC_ST; + RegValue = XFsbl_In32(RPU_RPU_GLBL_CNTL); if ((RegValue & RPU_RPU_GLBL_CNTL_SLSPLIT_MASK) == 0U) { XFsbl_Printf(DEBUG_GENERAL, diff --git a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h index 82f0fada..db1d0373 100644 --- a/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h +++ b/lib/sw_apps/zynqmp_fsbl/src/xfsbl_main.h @@ -81,6 +81,7 @@ typedef struct { u32 Version; /**< FSBL Version */ u32 PresentStage; /**< Stage */ u32 ProcessorID; /**< One of R5-0, R5-LS, A53-0 */ + u32 A53ExecState; /**< One of A53 64-bit, A53 32-bit */ u32 BootHdrAttributes; /**< Boot Header attributes */ u32 ImageOffsetAddress; /**< Flash offset address */ XFsblPs_ImageHeader ImageHeader; /** Image header */