1 /******************************************************************************
3 * Copyright (C) 2010 - 2014 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 * This file contains the initial startup code for the Cortex A9 processor
39 * MODIFICATION HISTORY:
41 * Ver Who Date Changes
42 * ----- ------- -------- ---------------------------------------------------
43 * 1.00a ecm/sdm 10/20/09 Initial version
44 * 3.06a sgd 05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
46 * 3.06a asa 06/17/12 Modified the TTBR settings and L2 Cache auxiliary
48 * 3.07a asa 07/16/12 Modified the L2 Cache controller settings to improve
49 * performance. Changed the property of the ".boot"
51 * 3.07a sgd 08/21/12 Modified the L2 Cache controller and cp15 Aux Control
53 * 3.09a sgd 02/06/13 Updated SLCR l2c Ram Control register to a
54 * value of 0x00020202. Fix for CR 697094 (SI#687034).
55 * 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
56 * 'xil_errata.h' for errata description
63 ******************************************************************************/
65 #include "xparameters.h"
66 #include "xil_errata.h"
73 .global __supervisor_stack
79 .set PSS_L2CC_BASE_ADDR, 0xF8F02000
80 .set PSS_SLCR_BASE_ADDR, 0xF8000000
82 .set RESERVED, 0x0fffff00
83 .set TblBase , MMUTable
84 .set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */
85 .set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/
86 .set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/
87 .set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/
88 .set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/
89 .set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/
90 .set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/
91 .set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/
92 .set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/
94 .set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/
95 .set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/
96 .set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/
98 /* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */
100 .set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */
102 .set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */
105 .set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */
107 .set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable,
108 Event monitor bus enable and Way Size (64 KB) */
109 .set L2CCControl, 0x01 /* Enable L2CC */
110 .set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */
111 .set L2CCDataLatency, 0x0121 /* latency for DATA RAM */
113 .set SLCRlockKey, 0x767B /* SLCR lock key */
114 .set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */
115 .set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */
117 /* Stack Pointer locations for boot code */
118 .set Undef_stack, __undef_stack
119 .set FIQ_stack, __fiq_stack
120 .set Abort_stack, __abort_stack
121 .set SPV_stack, __supervisor_stack
122 .set IRQ_stack, __irq_stack
123 .set SYS_stack, __stack
125 .set vector_base, _vector_table
127 .set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */
132 /* this initializes the various processor modes */
138 /* only allow cpu0 through */
148 /* only allow cpu1 through */
159 mrc p15, 0, r0, c0, c0, 0 /* Get the revision */
160 and r5, r0, #0x00f00000
161 and r6, r0, #0x0000000f
162 orr r6, r6, r5, lsr #20-4
164 #ifdef CONFIG_ARM_ERRATA_742230
165 cmp r6, #0x22 /* only present up to r2p2 */
166 mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */
167 orrle r10, r10, #1 << 4 /* set bit #4 */
168 mcrle p15, 0, r10, c15, c0, 1 /* write diagnostic register */
171 #ifdef CONFIG_ARM_ERRATA_743622
172 teq r5, #0x00200000 /* only present in r2p* */
173 mrceq p15, 0, r10, c15, c0, 1 /* read diagnostic register */
174 orreq r10, r10, #1 << 6 /* set bit #6 */
175 mcreq p15, 0, r10, c15, c0, 1 /* write diagnostic register */
178 /* set VBAR to the _vector_table address in linker script */
180 mcr p15, 0, r0, c12, c0, 0
182 /*set scu enable bit in scu*/
194 mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
195 orr r0, r0, #(0x01 << 6) /* set SMP bit */
196 orr r0, r0, #(0x01 ) /* */
197 mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
199 /* Invalidate caches and TLBs */
200 mov r0,#0 /* r0 = 0 */
201 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */
202 mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */
203 mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */
204 bl invalidate_dcache /* invalidate dcache */
206 /* Invalidate L2c Cache */
207 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
209 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
210 mov r1, #0 /* force the disable bit */
211 str r1, [r0] /* disable the L2 Caches */
213 ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */
214 ldr r1,[r0] /* read the register */
215 ldr r2,=L2CCAuxControl /* set the default bits */
217 str r1, [r0] /* store the Aux Control Register */
219 ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */
220 ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/
221 str r1, [r0] /* store the TAG Latency register Register */
223 ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */
224 ldr r1,=L2CCDataLatency /* set the latencies for the Data*/
225 str r1, [r0] /* store the Data Latency register Register */
227 ldr r0,=L2CCWay /* Load L2CC base address base + way register*/
229 str r2, [r0] /* force invalidate */
231 ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */
232 /* Load L2CC base address base + sync register*/
233 /* poll for completion */
238 ldr r0,=L2CCIntRaw /* clear pending interrupts */
244 /* Disable MMU, if enabled */
245 mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */
246 bic r0, r0, #0x1 /* clear bit 0 */
247 mcr p15, 0, r0, c1, c0, 0 /* write value back */
250 /* Mark the entire DDR memory as shareable */
251 ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */
252 ldr r0, =TblBase /* MMU Table address in memory */
253 ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */
255 str r2, [r0] /* write the entry to MMU table */
256 add r0, r0, #0x4 /* next entry in the table */
257 add r2, r2, #0x100000 /* next section */
259 bge shareable_loop /* loop till 1G is covered */
262 /* In case of AMP, map virtual address 0x20000000 to 0x00000000 and mark it as non-cacheable */
264 ldr r3, =0x1ff /* 512 entries to cover 512MB DDR */
265 ldr r0, =TblBase /* MMU Table address in memory */
266 add r0, r0, #0x800 /* Address of entry in MMU table, for 0x20000000 */
267 ldr r2, =0x0c02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */
269 str r2, [r0] /* write the entry to MMU table */
270 add r0, r0, #0x4 /* next entry in the table */
271 add r2, r2, #0x100000 /* next section */
273 bge mmu_loop /* loop till 512MB is covered */
276 mrs r0, cpsr /* get the current PSR */
277 mvn r1, #0x1f /* set up the irq stack pointer */
279 orr r2, r2, #0x12 /* IRQ mode */
281 ldr r13,=IRQ_stack /* IRQ stack pointer */
283 mrs r0, cpsr /* get the current PSR */
284 mvn r1, #0x1f /* set up the supervisor stack pointer */
286 orr r2, r2, #0x13 /* supervisor mode */
288 ldr r13,=SPV_stack /* Supervisor stack pointer */
290 mrs r0, cpsr /* get the current PSR */
291 mvn r1, #0x1f /* set up the Abort stack pointer */
293 orr r2, r2, #0x17 /* Abort mode */
295 ldr r13,=Abort_stack /* Abort stack pointer */
297 mrs r0, cpsr /* get the current PSR */
298 mvn r1, #0x1f /* set up the FIQ stack pointer */
300 orr r2, r2, #0x11 /* FIQ mode */
302 ldr r13,=FIQ_stack /* FIQ stack pointer */
304 mrs r0, cpsr /* get the current PSR */
305 mvn r1, #0x1f /* set up the Undefine stack pointer */
307 orr r2, r2, #0x1b /* Undefine mode */
309 ldr r13,=Undef_stack /* Undefine stack pointer */
311 mrs r0, cpsr /* get the current PSR */
312 mvn r1, #0x1f /* set up the system stack pointer */
314 orr r2, r2, #0x1F /* SYS mode */
316 ldr r13,=SYS_stack /* SYS stack pointer */
318 /* enable MMU and cache */
320 ldr r0,=TblBase /* Load MMU translation table base */
321 orr r0, r0, #0x5B /* Outer-cacheable, WB */
322 mcr 15, 0, r0, c2, c0, 0 /* TTB0 */
325 mvn r0,#0 /* Load MMU domains -- all ones=manager */
328 /* Enable mmu, icahce and dcache */
331 mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */
332 dsb /* dsb allow the MMU to start up */
334 isb /* isb flush prefetch buffer */
336 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
338 ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */
339 ldr r1,=SLCRUnlockKey /* set unlock key */
340 str r1, [r0] /* Unlock SLCR */
342 ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */
343 ldr r1,=SLCRL2cRamConfig /* set the configuration value */
344 str r1, [r0] /* store the L2c Ram Control Register */
346 ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */
347 ldr r1,=SLCRlockKey /* set lock key */
348 str r1, [r0] /* lock SLCR */
350 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
351 ldr r1,[r0] /* read the register */
352 mov r2, #L2CCControl /* set the enable bit */
354 str r1, [r0] /* enable the L2 Caches */
358 mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */
359 orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */
360 mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */
363 fmrx r1, FPEXC /* read the exception register */
364 orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */
365 fmxr FPEXC, r1 /* write back the exception register */
367 mrc p15,0,r0,c1,c0,0 /* flow prediction enable */
368 orr r0, r0, #(0x01 << 11) /* #0x8000 */
371 mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */
372 orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */
373 orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */
374 mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */
376 b _start /* jump to C startup code */
377 and r0, r0, r0 /* no op */
379 .Ldone: b .Ldone /* Paranoia: we should never get here */
383 *************************************************************************
385 * invalidate_dcache - invalidate the entire d-cache by set/way
387 * Note: for Cortex-A9, there is no cp instruction for invalidating
388 * the whole D-cache. Need to invalidate each line.
390 *************************************************************************
393 mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */
394 ands r3, r0, #0x7000000
395 mov r3, r3, lsr #23 /* cache level value (naturally aligned) */
397 mov r10, #0 /* start with level 0 */
399 add r2, r10, r10, lsr #1 /* work out 3xcachelevel */
400 mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */
401 and r1, r1, #7 /* get those 3 bits alone */
403 blt skip /* no cache or only instruction cache at this level */
404 mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */
405 isb /* isb to sync the change to the CacheSizeID reg */
406 mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */
407 and r2, r1, #7 /* extract the line length field */
408 add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */
410 ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */
411 clz r5, r4 /* r5 is the bit position of the way size increment */
413 ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */
415 mov r9, r4 /* r9 working copy of the max way size (right aligned) */
417 orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */
418 orr r11, r11, r7, lsl r2 /* factor in the index number */
419 mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */
420 subs r9, r9, #1 /* decrement the way number */
422 subs r7, r7, #1 /* decrement the index */
425 add r10, r10, #2 /* increment the cache number */
430 mov r10, #0 /* swith back to cache level 0 */
431 mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */