]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/standalone_v4_1/src/boot.S
3269a05b75ecc3aaebafe033d9d2316eb1ed7be9
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / standalone_v4_1 / src / boot.S
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2014 Xilinx, Inc.  All rights reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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.
18 *
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
25 * SOFTWARE.
26 *
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.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 * @file boot.S
35 *
36 * This file contains the initial startup code for the Cortex A9 processor
37 *
38 * <pre>
39 * MODIFICATION HISTORY:
40 *
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 
45 *                        register settings.
46 * 3.06a asa     06/17/12 Modified the TTBR settings and L2 Cache auxiliary
47 *                        register settings.
48 * 3.07a asa     07/16/12 Modified the L2 Cache controller settings to improve
49 *                        performance. Changed the property of the ".boot"
50 *                        section.
51 * 3.07a sgd     08/21/12 Modified the L2 Cache controller and cp15 Aux Control 
52 *               Register settings
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
57 * </pre>
58 *
59 * @note
60 *
61 * None.
62 *
63 ******************************************************************************/
64
65 #include "xparameters.h"
66 #include "xil_errata.h"
67
68 .globl MMUTable
69 .global _prestart
70 .global _boot
71 .global __stack
72 .global __irq_stack
73 .global __supervisor_stack
74 .global __abort_stack
75 .global __fiq_stack
76 .global __undef_stack
77 .global _vector_table
78
79 .set PSS_L2CC_BASE_ADDR, 0xF8F02000
80 .set PSS_SLCR_BASE_ADDR, 0xF8000000
81
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)*/
93
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)*/
97
98 /* workaround for simulation not working when L1 D and I caches,MMU and  L2 cache enabled - DT568997 */
99 .if SIM_MODE == 1
100 .set CRValMmuCac,       0b00000000000000        /* Disable IDC, and MMU */
101 .else 
102 .set CRValMmuCac,       0b01000000000101        /* Enable IDC, and MMU */
103 .endif
104
105 .set CRValHiVectorAddr, 0b10000000000000        /* Set the Vector address to high, 0xFFFF0000 */
106
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 */
112
113 .set SLCRlockKey,               0x767B                  /* SLCR lock key */
114 .set SLCRUnlockKey,             0xDF0D                  /* SLCR unlock key */
115 .set SLCRL2cRamConfig,      0x00020202      /* SLCR L2C ram configuration */
116
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
124
125 .set vector_base,       _vector_table
126
127 .set FPEXC_EN,          0x40000000              /* FPU enable bit, (1 << 30) */
128
129 .section .boot,"ax"
130
131
132 /* this initializes the various processor modes */
133
134 _prestart:
135 _boot:
136
137 #if XPAR_CPU_ID==0
138 /* only allow cpu0 through */
139         mrc     p15,0,r1,c0,c0,5
140         and     r1, r1, #0xf
141         cmp     r1, #0
142         beq     OKToRun
143 EndlessLoop0:
144         wfe
145         b       EndlessLoop0
146
147 #elif XPAR_CPU_ID==1
148 /* only allow cpu1 through */
149         mrc     p15,0,r1,c0,c0,5
150         and     r1, r1, #0xf
151         cmp     r1, #1
152         beq     OKToRun
153 EndlessLoop1:
154         wfe
155         b       EndlessLoop1
156 #endif
157
158 OKToRun:
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
163
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 */
169 #endif
170
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 */
176 #endif
177
178         /* set VBAR to the _vector_table address in linker script */
179         ldr     r0, =vector_base
180         mcr     p15, 0, r0, c12, c0, 0
181
182         /*set scu enable bit in scu*/
183         ldr     r7, =0xf8f00000
184         ldr     r0, [r7]
185         orr     r0, r0, #0x1  
186         str     r0, [r7]
187
188         /*invalidate scu*/
189         ldr     r7, =0xf8f0000c
190         ldr     r6, =0xffff
191         str     r6, [r7]
192
193         /* Write to ACTLR */
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*/
198
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 */
205
206 /* Invalidate L2c Cache */
207 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
208 #if USE_AMP!=1
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 */
212
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 */
216         orr     r1,r1,r2
217         str     r1, [r0]                        /* store the Aux Control Register */
218
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 */
222
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 */
226
227         ldr     r0,=L2CCWay                     /* Load L2CC base address base + way register*/
228         ldr     r2, =0xFFFF
229         str     r2, [r0]                        /* force invalidate */
230
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 */
234 Sync:   ldr     r1, [r0]
235         cmp     r1, #0
236         bne     Sync
237
238         ldr     r0,=L2CCIntRaw                  /* clear pending interrupts */
239         ldr     r1,[r0]
240         ldr     r0,=L2CCIntClear        
241         str     r1,[r0]
242 #endif
243
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 */
248
249 #ifdef SHAREABLE_DDR
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 */
254 shareable_loop:
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 */
258         subs    r3, r3, #1
259         bge     shareable_loop                  /* loop till 1G is covered */
260 #endif
261
262         /* In case of AMP, map virtual address 0x20000000 to 0x00000000  and mark it as non-cacheable */
263 #if USE_AMP==1
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 */
268 mmu_loop:
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 */
272         subs    r3, r3, #1
273         bge     mmu_loop                        /* loop till 512MB is covered */
274 #endif
275
276         mrs     r0, cpsr                        /* get the current PSR */
277         mvn     r1, #0x1f                       /* set up the irq stack pointer */
278         and     r2, r1, r0
279         orr     r2, r2, #0x12                   /* IRQ mode */
280         msr     cpsr, r2
281         ldr     r13,=IRQ_stack                  /* IRQ stack pointer */
282
283         mrs     r0, cpsr                        /* get the current PSR */
284         mvn     r1, #0x1f                       /* set up the supervisor stack pointer */
285         and     r2, r1, r0
286         orr     r2, r2, #0x13                   /* supervisor mode */
287         msr     cpsr, r2
288         ldr     r13,=SPV_stack                  /* Supervisor stack pointer */
289
290         mrs     r0, cpsr                        /* get the current PSR */
291         mvn     r1, #0x1f                       /* set up the Abort  stack pointer */
292         and     r2, r1, r0
293         orr     r2, r2, #0x17                   /* Abort mode */
294         msr     cpsr, r2
295         ldr     r13,=Abort_stack                /* Abort stack pointer */
296
297         mrs     r0, cpsr                        /* get the current PSR */
298         mvn     r1, #0x1f                       /* set up the FIQ stack pointer */
299         and     r2, r1, r0
300         orr     r2, r2, #0x11                   /* FIQ mode */
301         msr     cpsr, r2
302         ldr     r13,=FIQ_stack                  /* FIQ stack pointer */
303
304         mrs     r0, cpsr                        /* get the current PSR */
305         mvn     r1, #0x1f                       /* set up the Undefine stack pointer */
306         and     r2, r1, r0
307         orr     r2, r2, #0x1b                   /* Undefine mode */
308         msr     cpsr, r2
309         ldr     r13,=Undef_stack                /* Undefine stack pointer */
310
311         mrs     r0, cpsr                        /* get the current PSR */
312         mvn     r1, #0x1f                       /* set up the system stack pointer */
313         and     r2, r1, r0
314         orr     r2, r2, #0x1F                   /* SYS mode */
315         msr     cpsr, r2
316         ldr     r13,=SYS_stack                  /* SYS stack pointer */
317
318         /* enable MMU and cache */
319
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 */
323         
324         
325         mvn     r0,#0                           /* Load MMU domains -- all ones=manager */
326         mcr     p15,0,r0,c3,c0,0
327
328         /* Enable mmu, icahce and dcache */
329         ldr     r0,=CRValMmuCac
330
331         mcr     p15,0,r0,c1,c0,0                /* Enable cache and MMU */
332         dsb                                     /* dsb  allow the MMU to start up */
333
334         isb                                     /* isb  flush prefetch buffer */
335
336 /* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */
337 #if USE_AMP!=1
338         ldr     r0,=SLCRUnlockReg               /* Load SLCR base address base + unlock register */
339         ldr     r1,=SLCRUnlockKey           /* set unlock key */
340         str     r1, [r0]                    /* Unlock SLCR */
341
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 */
345
346         ldr     r0,=SLCRlockReg         /* Load SLCR base address base + lock register */
347         ldr     r1,=SLCRlockKey         /* set lock key */
348         str     r1, [r0]                /* lock SLCR */
349
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 */
353         orr     r1,r1,r2
354         str     r1, [r0]                        /* enable the L2 Caches */
355 #endif
356
357         mov     r0, r0
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 */
361
362         /* enable vfp */
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 */
366
367         mrc     p15,0,r0,c1,c0,0                /* flow prediction enable */
368         orr     r0, r0, #(0x01 << 11)           /* #0x8000 */           
369         mcr     p15,0,r0,c1,c0,0
370
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 */
375
376         b       _start                          /* jump to C startup code */
377         and     r0, r0, r0                      /* no op */
378         
379 .Ldone: b       .Ldone                          /* Paranoia: we should never get here */
380
381
382 /*
383  *************************************************************************
384  *
385  * invalidate_dcache - invalidate the entire d-cache by set/way
386  *
387  * Note: for Cortex-A9, there is no cp instruction for invalidating
388  * the whole D-cache. Need to invalidate each line.
389  *
390  *************************************************************************
391  */
392 invalidate_dcache:
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) */
396         beq     finished
397         mov     r10, #0                         /* start with level 0 */
398 loop1:
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 */
402         cmp     r1, #2
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) */
409         ldr     r4, =0x3ff
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 */
412         ldr     r7, =0x7fff
413         ands    r7, r7, r1, lsr #13             /* r7 is the max number of the index size (right aligned) */
414 loop2:
415         mov     r9, r4                          /* r9 working copy of the max way size (right aligned) */
416 loop3:
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 */
421         bge     loop3
422         subs    r7, r7, #1                      /* decrement the index */
423         bge     loop2
424 skip:
425         add     r10, r10, #2                    /* increment the cache number */
426         cmp     r3, r10
427         bgt     loop1
428
429 finished:
430         mov     r10, #0                         /* swith back to cache level 0 */
431         mcr     p15, 2, r10, c0, c0, 0          /* select current cache level in cssr */
432         dsb
433         isb
434
435         bx      lr
436
437 .end
438
439