1 /******************************************************************************
3 * (c) Copyright 2010-2013 Xilinx, Inc. All rights reserved.
5 * This file contains confidential and proprietary information of Xilinx, Inc.
6 * and is protected under U.S. and international copyright and other
7 * intellectual property laws.
10 * This disclaimer is not a license and does not grant any rights to the
11 * materials distributed herewith. Except as otherwise provided in a valid
12 * license issued to you by Xilinx, and to the maximum extent permitted by
13 * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
14 * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
15 * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
16 * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
17 * and (2) Xilinx shall not be liable (whether in contract or tort, including
18 * negligence, or under any other theory of liability) for any loss or damage
19 * of any kind or nature related to, arising under or in connection with these
20 * materials, including for any direct, or any indirect, special, incidental,
21 * or consequential loss or damage (including loss of data, profits, goodwill,
22 * or any type of loss or damage suffered as a result of any action brought by
23 * a third party) even if such damage or loss was reasonably foreseeable or
24 * Xilinx had been advised of the possibility of the same.
26 * CRITICAL APPLICATIONS
27 * Xilinx products are not designed or intended to be fail-safe, or for use in
28 * any application requiring fail-safe performance, such as life-support or
29 * safety devices or systems, Class III medical devices, nuclear facilities,
30 * applications related to the deployment of airbags, or any other applications
31 * that could lead to death, personal injury, or severe property or
32 * environmental damage (individually and collectively, "Critical
33 * Applications"). Customer assumes the sole risk and liability of any use of
34 * Xilinx products in Critical Applications, subject only to applicable laws
35 * and regulations governing limitations on product liability.
37 * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
40 ******************************************************************************/
41 /*****************************************************************************/
45 * This file contains the initial startup code for the Cortex A9 processor
48 * MODIFICATION HISTORY:
50 * Ver Who Date Changes
51 * ----- ------- -------- ---------------------------------------------------
52 * 1.00a ecm/sdm 10/20/09 Initial version
53 * 3.06a sgd 05/15/12 Updated L2CC Auxiliary and Tag RAM Latency control
55 * 3.06a asa 06/17/12 Modified the TTBR settings and L2 Cache auxiliary
57 * 3.07a asa 07/16/12 Modified the L2 Cache controller settings to improve
58 * performance. Changed the property of the ".boot"
60 * 3.07a sgd 08/21/12 Modified the L2 Cache controller and cp15 Aux Control
62 * 3.09a sgd 02/06/13 Updated SLCR l2c Ram Control register to a
63 * value of 0x00020202. Fix for CR 697094 (SI#687034).
64 * 3.10a srt 04/18/13 Implemented ARM Erratas. Please refer to file
65 * 'xil_errata.h' for errata description
72 ******************************************************************************/
74 #include "xparameters.h"
75 #include "xil_errata.h"
82 .global __supervisor_stack
88 .set PSS_L2CC_BASE_ADDR, 0xF8F02000
89 .set PSS_SLCR_BASE_ADDR, 0xF8000000
91 .set RESERVED, 0x0fffff00
92 .set TblBase , MMUTable
93 .set LRemap, 0xFE00000F /* set the base address of the peripheral block as not shared */
94 .set L2CCWay, (PSS_L2CC_BASE_ADDR + 0x077C) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_INVLD_WAY_OFFSET)*/
95 .set L2CCSync, (PSS_L2CC_BASE_ADDR + 0x0730) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CACHE_SYNC_OFFSET)*/
96 .set L2CCCrtl, (PSS_L2CC_BASE_ADDR + 0x0100) /*(PSS_L2CC_BASE_ADDR + PSS_L2CC_CNTRL_OFFSET)*/
97 .set L2CCAuxCrtl, (PSS_L2CC_BASE_ADDR + 0x0104) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_AUX_CNTRL_OFFSET)*/
98 .set L2CCTAGLatReg, (PSS_L2CC_BASE_ADDR + 0x0108) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_TAG_RAM_CNTRL_OFFSET)*/
99 .set L2CCDataLatReg, (PSS_L2CC_BASE_ADDR + 0x010C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_DATA_RAM_CNTRL_OFFSET)*/
100 .set L2CCIntClear, (PSS_L2CC_BASE_ADDR + 0x0220) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_IAR_OFFSET)*/
101 .set L2CCIntRaw, (PSS_L2CC_BASE_ADDR + 0x021C) /*(PSS_L2CC_BASE_ADDR + XPSS_L2CC_ISR_OFFSET)*/
103 .set SLCRlockReg, (PSS_SLCR_BASE_ADDR + 0x04) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_LOCK_OFFSET)*/
104 .set SLCRUnlockReg, (PSS_SLCR_BASE_ADDR + 0x08) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_UNLOCK_OFFSET)*/
105 .set SLCRL2cRamReg, (PSS_SLCR_BASE_ADDR + 0xA1C) /*(PSS_SLCR_BASE_ADDR + XPSS_SLCR_L2C_RAM_OFFSET)*/
107 /* workaround for simulation not working when L1 D and I caches,MMU and L2 cache enabled - DT568997 */
109 .set CRValMmuCac, 0b00000000000000 /* Disable IDC, and MMU */
111 .set CRValMmuCac, 0b01000000000101 /* Enable IDC, and MMU */
114 .set CRValHiVectorAddr, 0b10000000000000 /* Set the Vector address to high, 0xFFFF0000 */
116 .set L2CCAuxControl, 0x72360000 /* Enable all prefetching, Cache replacement policy, Parity enable,
117 Event monitor bus enable and Way Size (64 KB) */
118 .set L2CCControl, 0x01 /* Enable L2CC */
119 .set L2CCTAGLatency, 0x0111 /* latency for TAG RAM */
120 .set L2CCDataLatency, 0x0121 /* latency for DATA RAM */
122 .set SLCRlockKey, 0x767B /* SLCR lock key */
123 .set SLCRUnlockKey, 0xDF0D /* SLCR unlock key */
124 .set SLCRL2cRamConfig, 0x00020202 /* SLCR L2C ram configuration */
126 /* Stack Pointer locations for boot code */
127 .set Undef_stack, __undef_stack
128 .set FIQ_stack, __fiq_stack
129 .set Abort_stack, __abort_stack
130 .set SPV_stack, __supervisor_stack
131 .set IRQ_stack, __irq_stack
132 .set SYS_stack, __stack
134 .set vector_base, _vector_table
136 .set FPEXC_EN, 0x40000000 /* FPU enable bit, (1 << 30) */
141 /* this initializes the various processor modes */
147 /* only allow cpu0 through */
157 /* only allow cpu1 through */
168 mrc p15, 0, r0, c0, c0, 0 /* Get the revision */
169 and r5, r0, #0x00f00000
170 and r6, r0, #0x0000000f
171 orr r6, r6, r5, lsr #20-4
173 #ifdef CONFIG_ARM_ERRATA_742230
174 cmp r6, #0x22 /* only present up to r2p2 */
175 mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */
176 orrle r10, r10, #1 << 4 /* set bit #4 */
177 mcrle p15, 0, r10, c15, c0, 1 /* write diagnostic register */
180 #ifdef CONFIG_ARM_ERRATA_743622
181 teq r5, #0x00200000 /* only present in r2p* */
182 mrceq p15, 0, r10, c15, c0, 1 /* read diagnostic register */
183 orreq r10, r10, #1 << 6 /* set bit #6 */
184 mcreq p15, 0, r10, c15, c0, 1 /* write diagnostic register */
187 /* set VBAR to the _vector_table address in linker script */
189 mcr p15, 0, r0, c12, c0, 0
191 /*set scu enable bit in scu*/
203 mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
204 orr r0, r0, #(0x01 << 6) /* set SMP bit */
205 orr r0, r0, #(0x01 ) /* */
206 mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
208 /* Invalidate caches and TLBs */
209 mov r0,#0 /* r0 = 0 */
210 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLBs */
211 mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */
212 mcr p15, 0, r0, c7, c5, 6 /* Invalidate branch predictor array */
213 bl invalidate_dcache /* invalidate dcache */
215 /* Invalidate L2c Cache */
216 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
218 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
219 mov r1, #0 /* force the disable bit */
220 str r1, [r0] /* disable the L2 Caches */
222 ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */
223 ldr r1,[r0] /* read the register */
224 ldr r2,=L2CCAuxControl /* set the default bits */
226 str r1, [r0] /* store the Aux Control Register */
228 ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */
229 ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/
230 str r1, [r0] /* store the TAG Latency register Register */
232 ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */
233 ldr r1,=L2CCDataLatency /* set the latencies for the Data*/
234 str r1, [r0] /* store the Data Latency register Register */
236 ldr r0,=L2CCWay /* Load L2CC base address base + way register*/
238 str r2, [r0] /* force invalidate */
240 ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET */
241 /* Load L2CC base address base + sync register*/
242 /* poll for completion */
247 ldr r0,=L2CCIntRaw /* clear pending interrupts */
253 /* Disable MMU, if enabled */
254 mrc p15, 0, r0, c1, c0, 0 /* read CP15 register 1 */
255 bic r0, r0, #0x1 /* clear bit 0 */
256 mcr p15, 0, r0, c1, c0, 0 /* write value back */
259 /* Mark the entire DDR memory as shareable */
260 ldr r3, =0x3ff /* 1024 entries to cover 1G DDR */
261 ldr r0, =TblBase /* MMU Table address in memory */
262 ldr r2, =0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */
264 str r2, [r0] /* write the entry to MMU table */
265 add r0, r0, #0x4 /* next entry in the table */
266 add r2, r2, #0x100000 /* next section */
268 bge shareable_loop /* loop till 1G is covered */
271 /* In case of AMP, map virtual address 0x20000000 to 0x00000000 and mark it as non-cacheable */
273 ldr r3, =0x1ff /* 512 entries to cover 512MB DDR */
274 ldr r0, =TblBase /* MMU Table address in memory */
275 add r0, r0, #0x800 /* Address of entry in MMU table, for 0x20000000 */
276 ldr r2, =0x0c02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */
278 str r2, [r0] /* write the entry to MMU table */
279 add r0, r0, #0x4 /* next entry in the table */
280 add r2, r2, #0x100000 /* next section */
282 bge mmu_loop /* loop till 512MB is covered */
285 mrs r0, cpsr /* get the current PSR */
286 mvn r1, #0x1f /* set up the irq stack pointer */
288 orr r2, r2, #0x12 /* IRQ mode */
290 ldr r13,=IRQ_stack /* IRQ stack pointer */
292 mrs r0, cpsr /* get the current PSR */
293 mvn r1, #0x1f /* set up the supervisor stack pointer */
295 orr r2, r2, #0x13 /* supervisor mode */
297 ldr r13,=SPV_stack /* Supervisor stack pointer */
299 mrs r0, cpsr /* get the current PSR */
300 mvn r1, #0x1f /* set up the Abort stack pointer */
302 orr r2, r2, #0x17 /* Abort mode */
304 ldr r13,=Abort_stack /* Abort stack pointer */
306 mrs r0, cpsr /* get the current PSR */
307 mvn r1, #0x1f /* set up the FIQ stack pointer */
309 orr r2, r2, #0x11 /* FIQ mode */
311 ldr r13,=FIQ_stack /* FIQ stack pointer */
313 mrs r0, cpsr /* get the current PSR */
314 mvn r1, #0x1f /* set up the Undefine stack pointer */
316 orr r2, r2, #0x1b /* Undefine mode */
318 ldr r13,=Undef_stack /* Undefine stack pointer */
320 mrs r0, cpsr /* get the current PSR */
321 mvn r1, #0x1f /* set up the system stack pointer */
323 orr r2, r2, #0x1F /* SYS mode */
325 ldr r13,=SYS_stack /* SYS stack pointer */
327 /* enable MMU and cache */
329 ldr r0,=TblBase /* Load MMU translation table base */
330 orr r0, r0, #0x5B /* Outer-cacheable, WB */
331 mcr 15, 0, r0, c2, c0, 0 /* TTB0 */
334 mvn r0,#0 /* Load MMU domains -- all ones=manager */
337 /* Enable mmu, icahce and dcache */
340 mcr p15,0,r0,c1,c0,0 /* Enable cache and MMU */
341 dsb /* dsb allow the MMU to start up */
343 isb /* isb flush prefetch buffer */
345 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
347 ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */
348 ldr r1,=SLCRUnlockKey /* set unlock key */
349 str r1, [r0] /* Unlock SLCR */
351 ldr r0,=SLCRL2cRamReg /* Load SLCR base address base + l2c Ram Control register */
352 ldr r1,=SLCRL2cRamConfig /* set the configuration value */
353 str r1, [r0] /* store the L2c Ram Control Register */
355 ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */
356 ldr r1,=SLCRlockKey /* set lock key */
357 str r1, [r0] /* lock SLCR */
359 ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */
360 ldr r1,[r0] /* read the register */
361 mov r2, #L2CCControl /* set the enable bit */
363 str r1, [r0] /* enable the L2 Caches */
367 mrc p15, 0, r1, c1, c0, 2 /* read cp access control register (CACR) into r1 */
368 orr r1, r1, #(0xf << 20) /* enable full access for p10 & p11 */
369 mcr p15, 0, r1, c1, c0, 2 /* write back into CACR */
372 fmrx r1, FPEXC /* read the exception register */
373 orr r1,r1, #FPEXC_EN /* set VFP enable bit, leave the others in orig state */
374 fmxr FPEXC, r1 /* write back the exception register */
376 mrc p15,0,r0,c1,c0,0 /* flow prediction enable */
377 orr r0, r0, #(0x01 << 11) /* #0x8000 */
380 mrc p15,0,r0,c1,c0,1 /* read Auxiliary Control Register */
381 orr r0, r0, #(0x1 << 2) /* enable Dside prefetch */
382 orr r0, r0, #(0x1 << 1) /* enable L2 Prefetch hint */
383 mcr p15,0,r0,c1,c0,1 /* write Auxiliary Control Register */
385 b _start /* jump to C startup code */
386 and r0, r0, r0 /* no op */
388 .Ldone: b .Ldone /* Paranoia: we should never get here */
392 *************************************************************************
394 * invalidate_dcache - invalidate the entire d-cache by set/way
396 * Note: for Cortex-A9, there is no cp instruction for invalidating
397 * the whole D-cache. Need to invalidate each line.
399 *************************************************************************
402 mrc p15, 1, r0, c0, c0, 1 /* read CLIDR */
403 ands r3, r0, #0x7000000
404 mov r3, r3, lsr #23 /* cache level value (naturally aligned) */
406 mov r10, #0 /* start with level 0 */
408 add r2, r10, r10, lsr #1 /* work out 3xcachelevel */
409 mov r1, r0, lsr r2 /* bottom 3 bits are the Cache type for this level */
410 and r1, r1, #7 /* get those 3 bits alone */
412 blt skip /* no cache or only instruction cache at this level */
413 mcr p15, 2, r10, c0, c0, 0 /* write the Cache Size selection register */
414 isb /* isb to sync the change to the CacheSizeID reg */
415 mrc p15, 1, r1, c0, c0, 0 /* reads current Cache Size ID register */
416 and r2, r1, #7 /* extract the line length field */
417 add r2, r2, #4 /* add 4 for the line length offset (log2 16 bytes) */
419 ands r4, r4, r1, lsr #3 /* r4 is the max number on the way size (right aligned) */
420 clz r5, r4 /* r5 is the bit position of the way size increment */
422 ands r7, r7, r1, lsr #13 /* r7 is the max number of the index size (right aligned) */
424 mov r9, r4 /* r9 working copy of the max way size (right aligned) */
426 orr r11, r10, r9, lsl r5 /* factor in the way number and cache number into r11 */
427 orr r11, r11, r7, lsl r2 /* factor in the index number */
428 mcr p15, 0, r11, c7, c6, 2 /* invalidate by set/way */
429 subs r9, r9, #1 /* decrement the way number */
431 subs r7, r7, #1 /* decrement the index */
434 add r10, r10, #2 /* increment the cache number */
439 mov r10, #0 /* swith back to cache level 0 */
440 mcr p15, 2, r10, c0, c0, 0 /* select current cache level in cssr */