blob: 760994948a0a421e4dbc4aed3d4be2294054d266 [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2014 - 2018 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file boot.S
*
* @addtogroup a53_64_boot_code Cortex A53 64bit Processor Boot Code
* @{
* <h2> boot.S </h2>
*
* The boot code performs minimum configuration which is required for an
* application. Cortex-A53 starts by checking current exception level. If the
* current exception level is EL3 and BSP is built for EL3, it will do
* initialization required for application execution at EL3. Below is a
* sequence illustrating what all configuration is performed before control
* reaches to main function for EL3 execution.
*
* 1. Program vector table base for exception handling
* 2. Set reset vector table base address
* 3. Program stack pointer for EL3
* 4. Routing of interrupts to EL3
* 5. Enable ECC protection
* 6. Program generic counter frequency
* 7. Invalidate instruction cache, data cache and TLBs
* 8. Configure MMU registers and program base address of translation table
* 9. Transfer control to _start which clears BSS sections and runs global
* constructor before jumping to main application
*
* If the current exception level is EL1 and BSP is also built for EL1_NONSECURE
* it will perform initialization required for application execution at EL1
* non-secure. For all other combination, the execution will go into infinite
* loop. Below is a sequence illustrating what all configuration is performed
* before control reaches to main function for EL1 execution.
*
* 1. Program vector table base for exception handling
* 2. Program stack pointer for EL1
* 3. Invalidate instruction cache, data cache and TLBs
* 4. Configure MMU registers and program base address of translation table
* 5. Transfer control to _start which clears BSS sections and runs global
* constructor before jumping to main application
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- ---------------------------------------------------
* 5.00 pkp 05/21/14 Initial version
* 6.00 pkp 07/25/16 Program the counter frequency
* 6.02 pkp 01/22/17 Added support for EL1 non-secure
* 6.02 pkp 01/24/17 Clearing status of FPUStatus variable to ensure it
* holds correct value.
* 6.3 mus 04/20/17 CPU Cache protection bit in the L2CTLR_EL1 will be in
* set state on reset. So, setting that bit through boot
* code is redundant, hence removed the code which sets
* CPU cache protection bit.
* 6.4 mus 08/11/17 Implemented ARM erratum 855873.It fixes
* CR#982209.
* 6.6 mus 01/19/18 Added isb after writing to the cpacr_el1/cptr_el3,
* to ensure floating-point unit is disabled, before
* any subsequent instruction.
*
*
******************************************************************************/
#include "xparameters.h"
#include "bspconfig.h"
#include "xil_errata.h"
.globl MMUTableL0
.globl MMUTableL1
.globl MMUTableL2
.global _prestart
.global _boot
.global __el3_stack
.global __el2_stack
.global __el1_stack
.global __el0_stack
.global _vector_table
.set EL3_stack, __el3_stack
.set EL2_stack, __el2_stack
.set EL1_stack, __el1_stack
.set EL0_stack, __el0_stack
.set TT_S1_FAULT, 0x0
.set TT_S1_TABLE, 0x3
.set L0Table, MMUTableL0
.set L1Table, MMUTableL1
.set L2Table, MMUTableL2
.set vector_base, _vector_table
.set rvbar_base, 0xFD5C0040
.set counterfreq, XPAR_CPU_CORTEXA53_0_TIMESTAMP_CLK_FREQ
.set MODE_EL1, 0x5
.set DAIF_BIT, 0x1C0
.section .boot,"ax"
/* this initializes the various processor modes */
_prestart:
_boot:
mov x0, #0
mov x1, #0
mov x2, #0
mov x3, #0
mov x4, #0
mov x5, #0
mov x6, #0
mov x7, #0
mov x8, #0
mov x9, #0
mov x10, #0
mov x11, #0
mov x12, #0
mov x13, #0
mov x14, #0
mov x15, #0
mov x16, #0
mov x17, #0
mov x18, #0
mov x19, #0
mov x20, #0
mov x21, #0
mov x22, #0
mov x23, #0
mov x24, #0
mov x25, #0
mov x26, #0
mov x27, #0
mov x28, #0
mov x29, #0
mov x30, #0
#if 0 //dont put other a53 cpus in wfi
//Which core am I
// ----------------
mrs x0, MPIDR_EL1
and x0, x0, #0xFF //Mask off to leave Aff0
cbz x0, OKToRun //If core 0, run the primary init code
EndlessLoop0:
wfi
b EndlessLoop0
#endif
OKToRun:
mrs x0, currentEL
cmp x0, #0xC
beq InitEL3
cmp x0, #0x4
beq InitEL1
b error // go to error if current exception level is neither EL3 nor EL1
InitEL3:
.if (EL3 == 1)
/*Set vector table base address*/
ldr x1, =vector_base
msr VBAR_EL3,x1
/* Set reset vector address */
/* Get the cpu ID */
mrs x0, MPIDR_EL1
and x0, x0, #0xFF
mov w0, w0
ldr w2, =rvbar_base
/* calculate the rvbar base address for particular CPU core */
mov w3, #0x8
mul w0, w0, w3
add w2, w2, w0
/* store vector base address to RVBAR */
str x1, [x2]
/*Define stack pointer for current exception level*/
ldr x2,=EL3_stack
mov sp,x2
/* Enable Trapping of SIMD/FPU register for standalone BSP */
mov x0, #0
#ifndef FREERTOS_BSP
orr x0, x0, #(0x1 << 10)
#endif
msr CPTR_EL3, x0
isb
/*
* Clear FPUStatus variable to make sure that it contains current
* status of FPU i.e. disabled. In case of a warm restart execution
* when bss sections are not cleared, it may contain previously updated
* value which does not hold true now.
*/
#ifndef FREERTOS_BSP
ldr x0,=FPUStatus
str xzr, [x0]
#endif
/* Configure SCR_EL3 */
mov w1, #0 //; Initial value of register is unknown
orr w1, w1, #(1 << 11) //; Set ST bit (Secure EL1 can access CNTPS_TVAL_EL1, CNTPS_CTL_EL1 & CNTPS_CVAL_EL1)
orr w1, w1, #(1 << 10) //; Set RW bit (EL1 is AArch64, as this is the Secure world)
orr w1, w1, #(1 << 3) //; Set EA bit (SError routed to EL3)
orr w1, w1, #(1 << 2) //; Set FIQ bit (FIQs routed to EL3)
orr w1, w1, #(1 << 1) //; Set IRQ bit (IRQs routed to EL3)
msr SCR_EL3, x1
/*configure cpu auxiliary control register EL1 */
ldr x0,=0x80CA000 // L1 Data prefetch control - 5, Enable device split throttle, 2 independent data prefetch streams
#if CONFIG_ARM_ERRATA_855873
/*
* Set ENDCCASCI bit in CPUACTLR_EL1 register, to execute data
* cache clean operations as data cache clean and invalidate
*
*/
orr x0, x0, #(1 << 44) //; Set ENDCCASCI bit
#endif
msr S3_1_C15_C2_0, x0 //CPUACTLR_EL1
/* program the counter frequency */
ldr x0,=counterfreq
msr CNTFRQ_EL0, x0
/*Enable hardware coherency between cores*/
mrs x0, S3_1_c15_c2_1 //Read EL1 CPU Extended Control Register
orr x0, x0, #(1 << 6) //Set the SMPEN bit
msr S3_1_c15_c2_1, x0 //Write EL1 CPU Extended Control Register
isb
tlbi ALLE3
ic IALLU //; Invalidate I cache to PoU
bl invalidate_dcaches
dsb sy
isb
ldr x1, =L0Table //; Get address of level 0 for TTBR0_EL3
msr TTBR0_EL3, x1 //; Set TTBR0_EL3
/**********************************************
* Set up memory attributes
* This equates to:
* 0 = b01000100 = Normal, Inner/Outer Non-Cacheable
* 1 = b11111111 = Normal, Inner/Outer WB/WA/RA
* 2 = b00000000 = Device-nGnRnE
* 3 = b00000100 = Device-nGnRE
* 4 = b10111011 = Normal, Inner/Outer WT/WA/RA
**********************************************/
ldr x1, =0x000000BB0400FF44
msr MAIR_EL3, x1
/**********************************************
* Set up TCR_EL3
* Physical Address Size PS = 010 -> 40bits 1TB
* Granual Size TG0 = 00 -> 4KB
* size offset of the memory region T0SZ = 24 -> (region size 2^(64-24) = 2^40)
***************************************************/
ldr x1,=0x80823518
msr TCR_EL3, x1
isb
/* Enable SError Exception for asynchronous abort */
mrs x1,DAIF
bic x1,x1,#(0x1<<8)
msr DAIF,x1
/* Configure SCTLR_EL3 */
mov x1, #0 //Most of the SCTLR_EL3 bits are unknown at reset
orr x1, x1, #(1 << 12) //Enable I cache
orr x1, x1, #(1 << 3) //Enable SP alignment check
orr x1, x1, #(1 << 2) //Enable caches
orr x1, x1, #(1 << 0) //Enable MMU
msr SCTLR_EL3, x1
dsb sy
isb
b _startup //jump to start
.else
b error // present exception level and selected exception level mismatch
.endif
InitEL1:
.if (EL1_NONSECURE == 1)
/*Set vector table base address*/
ldr x1, =vector_base
msr VBAR_EL1,x1
mrs x0, CPACR_EL1
bic x0, x0, #(0x3 << 0x20)
msr CPACR_EL1, x0
isb
/*
* Clear FPUStatus variable to make sure that it contains current
* status of FPU i.e. disabled. In case of a warm restart execution
* when bss sections are not cleared, it may contain previously updated
* value which does not hold true now.
*/
#ifndef FREERTOS_BSP
ldr x0,=FPUStatus
str xzr, [x0]
#endif
/*Define stack pointer for current exception level*/
ldr x2,=EL1_stack
mov sp,x2
/* Disable MMU first */
mov x1,#0x0
msr SCTLR_EL1, x1
isb
TLBI VMALLE1
ic IALLU //; Invalidate I cache to PoU
bl invalidate_dcaches
dsb sy
isb
ldr x1, =L0Table //; Get address of level 0 for TTBR0_EL1
msr TTBR0_EL1, x1 //; Set TTBR0_EL1
/**********************************************
* Set up memory attributes
* This equates to:
* 0 = b01000100 = Normal, Inner/Outer Non-Cacheable
* 1 = b11111111 = Normal, Inner/Outer WB/WA/RA
* 2 = b00000000 = Device-nGnRnE
* 3 = b00000100 = Device-nGnRE
* 4 = b10111011 = Normal, Inner/Outer WT/WA/RA
**********************************************/
ldr x1, =0x000000BB0400FF44
msr MAIR_EL1, x1
/**********************************************
* Set up TCR_EL1
* Physical Address Size PS = 010 -> 40bits 1TB
* Granual Size TG0 = 00 -> 4KB
* size offset of the memory region T0SZ = 24 -> (region size 2^(64-24) = 2^40)
***************************************************/
ldr x1,=0x285800518
msr TCR_EL1, x1
isb
/* Enable SError Exception for asynchronous abort */
mrs x1,DAIF
bic x1,x1,#(0x1<<8)
msr DAIF,x1
//; Enable MMU
mov x1,#0x0
orr x1, x1, #(1 << 18) // ; Set WFE non trapping
orr x1, x1, #(1 << 17) // ; Set WFI non trapping
orr x1, x1, #(1 << 5) // ; Set CP15 barrier enabled
orr x1, x1, #(1 << 12) // ; Set I bit
orr x1, x1, #(1 << 2) // ; Set C bit
orr x1, x1, #(1 << 0) // ; Set M bit
msr SCTLR_EL1, x1
isb
bl _startup //jump to start
.else
b error // present exception level and selected exception level mismatch
.endif
error: b error
invalidate_dcaches:
dmb ISH
mrs x0, CLIDR_EL1 //; x0 = CLIDR
ubfx w2, w0, #24, #3 //; w2 = CLIDR.LoC
cmp w2, #0 //; LoC is 0?
b.eq invalidateCaches_end //; No cleaning required and enable MMU
mov w1, #0 //; w1 = level iterator
invalidateCaches_flush_level:
add w3, w1, w1, lsl #1 //; w3 = w1 * 3 (right-shift for cache type)
lsr w3, w0, w3 //; w3 = w0 >> w3
ubfx w3, w3, #0, #3 //; w3 = cache type of this level
cmp w3, #2 //; No cache at this level?
b.lt invalidateCaches_next_level
lsl w4, w1, #1
msr CSSELR_EL1, x4 //; Select current cache level in CSSELR
isb //; ISB required to reflect new CSIDR
mrs x4, CCSIDR_EL1 //; w4 = CSIDR
ubfx w3, w4, #0, #3
add w3, w3, #2 //; w3 = log2(line size)
ubfx w5, w4, #13, #15
ubfx w4, w4, #3, #10 //; w4 = Way number
clz w6, w4 //; w6 = 32 - log2(number of ways)
invalidateCaches_flush_set:
mov w8, w4 //; w8 = Way number
invalidateCaches_flush_way:
lsl w7, w1, #1 //; Fill level field
lsl w9, w5, w3
orr w7, w7, w9 //; Fill index field
lsl w9, w8, w6
orr w7, w7, w9 //; Fill way field
dc CISW, x7 //; Invalidate by set/way to point of coherency
subs w8, w8, #1 //; Decrement way
b.ge invalidateCaches_flush_way
subs w5, w5, #1 //; Descrement set
b.ge invalidateCaches_flush_set
invalidateCaches_next_level:
add w1, w1, #1 //; Next level
cmp w2, w1
b.gt invalidateCaches_flush_level
invalidateCaches_end:
ret
.end
/**
* @} End of "addtogroup a53_64_boot_code".
*/