1 /******************************************************************************
3 * Copyright (C) 2010 - 2016 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
36 * @addtogroup a9_boot_code Cortex A9 Processor Boot Code
39 * The boot code performs minimum configuration which is required for an
40 * application to run starting from processor's reset state. Below is a
41 * sequence illustrating what all configuration is performed before control
42 * reaches to main function.
44 * 1. Program vector table base for exception handling
45 * 2. Invalidate instruction cache, data cache and TLBs
46 * 3. Program stack pointer for various modes (IRQ, FIQ, supervisor, undefine,
48 * 4. Configure MMU with short descriptor translation table format and program
49 * base address of translation table
50 * 5. Enable data cache, instruction cache and MMU
51 * 6. Enable Floating point unit
52 * 7. Transfer control to _start which clears BSS sections, initializes
53 * global timer and runs global constructor before jumping to main
57 * MODIFICATION HISTORY:
59 * Ver Who Date Changes
60 * ----- ------- -------- ---------------------------------------------------
61 * 1.00a ecm/sdm 10/20/09 Initial version
62 * 3.06a sgd 05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
64 * 3.06a asa 06/17/12 Modified the TTBR settings and L2 Cache auxiliary
66 * 3.07a asa 07/16/12 Modified the L2 Cache controller settings to improve
67 * performance. Changed the property of the ".boot"
69 * 3.07a sgd 08/21/12 Modified the L2 Cache controller and cp15 Aux Control
71 * 3.09a sgd 02/06/13 Updated SLCR l2c Ram Control register to a
72 * value of 0x00020202. Fix for CR 697094 (SI#687034).
73 * 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
74 * 'xil_errata.h' for errata description
75 * 4.2 pkp 06/19/14 Enabled asynchronous abort exception
76 * 5.0 pkp 16/15/14 Modified initialization code to enable scu after
78 * 5.1 pkp 05/13/15 Changed the initialization order so to first invalidate
79 * caches and TLB, enable MMU and caches, then enable SMP
80 * bit in ACTLR. L2Cache invalidation and enabling of L2Cache
82 * 5.4 asa 12/6/15 Added code to initialize SPSR for all relevant modes.
83 * 6.0 mus 08/04/16 Added code to detect zynq-7000 base silicon configuration and
84 * attempt to enable dual core behavior on single cpu zynq-7000s
85 * devices is prevented from corrupting system behavior.
86 * 6.0 mus 08/24/16 Check CPU core before putting cpu1 to reset for single core
95 ******************************************************************************/
97 #include "xparameters.h"
98 #include "xil_errata.h"
105 .global __supervisor_stack
106 .global __abort_stack
108 .global __undef_stack
109 .global _vector_table
111 .set PSS_L2CC_BASE_ADDR, 0xF8F02000
112 .set PSS_SLCR_BASE_ADDR, 0xF8000000
114 .set RESERVED, 0x0fffff00
115 .set TblBase , MMUTable
116 .set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */
117 .set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/
118 .set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/
119 .set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/
120 .set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/
121 .set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/
122 .set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/
123 .set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/
124 .set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/
126 .set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/
127 .set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/
128 .set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/
129 .set SLCRCPURSTReg, (0xF8000000 + 0x244) /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/
130 .set EFUSEStaus, (0xF800D000 + 0x10) /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/
132 /* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */
134 .set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */
136 .set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */
139 .set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */
141 .set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable,
142 Event monitor bus enable and Way Size (64 KB) */
143 .set L2CCControl, 0x01 /* Enable L2CC */
144 .set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */
145 .set L2CCDataLatency, 0x0121 /* latency for DATA RAM */
147 .set SLCRlockKey, 0x767B /* SLCR lock key */
148 .set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */
149 .set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */
151 /* Stack Pointer locations for boot code */
152 .set Undef_stack, __undef_stack
153 .set FIQ_stack, __fiq_stack
154 .set Abort_stack, __abort_stack
155 .set SPV_stack, __supervisor_stack
156 .set IRQ_stack, __irq_stack
157 .set SYS_stack, __stack
159 .set vector_base, _vector_table
161 .set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */
166 /* this initializes the various processor modes */
172 /* only allow cpu0 through */
183 ldr r1,[r0] /* Read eFuse setting */
184 ands r1,r1,#0x80 /* Check whether device is having single core */
187 /* single core device, reset cpu1 */
188 ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */
189 ldr r1,=SLCRUnlockKey /* set unlock key */
190 str r1, [r0] /* Unlock SLCR */
192 ldr r0,=SLCRCPURSTReg
193 ldr r1,[r0] /* Read CPU Software Reset Control register */
195 str r1,[r0] /* Reset CPU1 */
197 ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */
198 ldr r1,=SLCRlockKey /* set lock key */
199 str r1, [r0] /* lock SLCR */
202 /* only allow cpu1 through */
211 ldr r1,[r0] /* Read eFuse setting */
212 ands r1,r1,#0x80 /* Check whether device is having single core */
220 mrc p15, 0, r0, c0, c0, 0 /* Get the revision */
221 and r5, r0, #0x00f00000
222 and r6, r0, #0x0000000f
223 orr r6, r6, r5, lsr #20-4
225 #ifdef CONFIG_ARM_ERRATA_742230
226 cmp r6, #0x22 /* only present up to r2p2 */
227 mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */
228 orrle r10, r10, #1 << 4 /* set bit #4 */
229 mcrle p15, 0, r10, c15, c0, 1 /* write diagnostic register */
232 #ifdef CONFIG_ARM_ERRATA_743622
233 teq r5, #0x00200000 /* only present in r2p* */
234 mrceq p15, 0, r10, c15, c0, 1 /* read diagnostic register */
235 orreq r10, r10, #1 << 6 /* set bit #6 */
236 mcreq p15, 0, r10, c15, c0, 1 /* write diagnostic register */
239 /* set VBAR to the _vector_table address in linker script */
241 mcr p15, 0, r0, c12, c0, 0
248 /* Invalidate caches and TLBs */
249 mov r0,#0 /* r0 = 0 */
250 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */
251 mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */
252 mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */
253 bl invalidate_dcache /* invalidate dcache */
255 /* Disable MMU, if enabled */
256 mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */
257 bic r0, r0, #0x1 /* clear bit 0 */
258 mcr p15, 0, r0, c1, c0, 0 /* write value back */
261 /* Mark the entire DDR memory as shareable */
262 ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */
263 ldr r0, =TblBase /* MMU Table address in memory */
264 ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */
266 str r2, [r0] /* write the entry to MMU table */
267 add r0, r0, #0x4 /* next entry in the table */
268 add r2, r2, #0x100000 /* next section */
270 bge shareable_loop /* loop till 1G is covered */
273 mrs r0, cpsr /* get the current PSR */
274 mvn r1, #0x1f /* set up the irq stack pointer */
276 orr r2, r2, #0x12 /* IRQ mode */
278 ldr r13,=IRQ_stack /* IRQ stack pointer */
279 bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */
282 mrs r0, cpsr /* get the current PSR */
283 mvn r1, #0x1f /* set up the supervisor stack pointer */
285 orr r2, r2, #0x13 /* supervisor mode */
287 ldr r13,=SPV_stack /* Supervisor stack pointer */
288 bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */
291 mrs r0, cpsr /* get the current PSR */
292 mvn r1, #0x1f /* set up the Abort stack pointer */
294 orr r2, r2, #0x17 /* Abort mode */
296 ldr r13,=Abort_stack /* Abort stack pointer */
297 bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */
300 mrs r0, cpsr /* get the current PSR */
301 mvn r1, #0x1f /* set up the FIQ stack pointer */
303 orr r2, r2, #0x11 /* FIQ mode */
305 ldr r13,=FIQ_stack /* FIQ stack pointer */
306 bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */
309 mrs r0, cpsr /* get the current PSR */
310 mvn r1, #0x1f /* set up the Undefine stack pointer */
312 orr r2, r2, #0x1b /* Undefine mode */
314 ldr r13,=Undef_stack /* Undefine stack pointer */
315 bic r2, r2, #(0x1 << 9) /* Set EE bit to little-endian */
318 mrs r0, cpsr /* get the current PSR */
319 mvn r1, #0x1f /* set up the system stack pointer */
321 orr r2, r2, #0x1F /* SYS mode */
323 ldr r13,=SYS_stack /* SYS stack pointer */
325 /*set scu enable bit in scu*/
331 /* enable MMU and cache */
333 ldr r0,=TblBase /* Load MMU translation table base */
334 orr r0, r0, #0x5B /* Outer-cacheable, WB */
335 mcr 15, 0, r0, c2, c0, 0 /* TTB0 */
337 mvn r0,#0 /* Load MMU domains -- all ones=manager */
340 /* Enable mmu, icahce and dcache */
342 mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */
343 dsb /* dsb allow the MMU to start up */
344 isb /* isb flush prefetch buffer */
347 mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
348 orr r0, r0, #(0x01 << 6) /* set SMP bit */
349 orr r0, r0, #(0x01 ) /* Cache/TLB maintenance broadcast */
350 mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
352 /* Invalidate L2 Cache and enable L2 Cache*/
353 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
355 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
356 mov r1, #0 /* force the disable bit */
357 str r1, [r0] /* disable the L2 Caches */
359 ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */
360 ldr r1,[r0] /* read the register */
361 ldr r2,=L2CCAuxControl /* set the default bits */
363 str r1, [r0] /* store the Aux Control Register */
365 ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */
366 ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/
367 str r1, [r0] /* store the TAG Latency register Register */
369 ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */
370 ldr r1,=L2CCDataLatency /* set the latencies for the Data*/
371 str r1, [r0] /* store the Data Latency register Register */
373 ldr r0,=L2CCWay /* Load L2CC base address base + way register*/
375 str r2, [r0] /* force invalidate */
377 ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */
378 /* Load L2CC base address base + sync register*/
379 /* poll for completion */
384 ldr r0,=L2CCIntRaw /* clear pending interrupts */
389 ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */
390 ldr r1,=SLCRUnlockKey /* set unlock key */
391 str r1, [r0] /* Unlock SLCR */
393 ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */
394 ldr r1,=SLCRL2cRamConfig /* set the configuration value */
395 str r1, [r0] /* store the L2c Ram Control Register */
397 ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */
398 ldr r1,=SLCRlockKey /* set lock key */
399 str r1, [r0] /* lock SLCR */
401 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
402 ldr r1,[r0] /* read the register */
403 mov r2, #L2CCControl /* set the enable bit */
405 str r1, [r0] /* enable the L2 Caches */
409 mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */
410 orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */
411 mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */
414 fmrx r1, FPEXC /* read the exception register */
415 orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */
416 fmxr FPEXC, r1 /* write back the exception register */
418 mrc p15,0,r0,c1,c0,0 /* flow prediction enable */
419 orr r0, r0, #(0x01 << 11) /* #0x8000 */
422 mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */
423 orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */
424 orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */
425 mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */
427 mrs r0, cpsr /* get the current PSR */
428 bic r0, r0, #0x100 /* enable asynchronous abort exception */
432 b _start /* jump to C startup code */
433 and r0, r0, r0 /* no op */
435 .Ldone: b .Ldone /* Paranoia: we should never get here */
439 *************************************************************************
441 * invalidate_dcache - invalidate the entire d-cache by set/way
443 * Note: for Cortex-A9, there is no cp instruction for invalidating
444 * the whole D-cache. Need to invalidate each line.
446 *************************************************************************
449 mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */
450 ands r3, r0, #0x7000000
451 mov r3, r3, lsr #23 /* cache level value (naturally aligned) */
453 mov r10, #0 /* start with level 0 */
455 add r2, r10, r10, lsr #1 /* work out 3xcachelevel */
456 mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */
457 and r1, r1, #7 /* get those 3 bits alone */
459 blt skip /* no cache or only instruction cache at this level */
460 mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */
461 isb /* isb to sync the change to the CacheSizeID reg */
462 mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */
463 and r2, r1, #7 /* extract the line length field */
464 add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */
466 ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */
467 clz r5, r4 /* r5 is the bit position of the way size increment */
469 ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */
471 mov r9, r4 /* r9 working copy of the max way size (right aligned) */
473 orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */
474 orr r11, r11, r7, lsl r2 /* factor in the index number */
475 mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */
476 subs r9, r9, #1 /* decrement the way number */
478 subs r7, r7, #1 /* decrement the index */
481 add r10, r10, #2 /* increment the cache number */
486 mov r10, #0 /* swith back to cache level 0 */
487 mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */
495 * @} End of "addtogroup a9_boot_code".