]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm/armv7.s
audiohda: fix syntax error
[plan9front.git] / sys / src / 9 / bcm / armv7.s
1 /*
2  * Broadcom bcm2836 SoC, as used in Raspberry Pi 2
3  * 4 x Cortex-A7 processor (armv7)
4  */
5
6 #include "arm.s"
7
8 #define CACHELINESZ     64
9 #define ICACHELINESZ    32
10
11 #undef DSB
12 #undef DMB
13 #undef ISB
14 #define DSB     WORD    $0xf57ff04f     /* data synch. barrier; last f = SY */
15 #define DMB     WORD    $0xf57ff05f     /* data mem. barrier; last f = SY */
16 #define ISB     WORD    $0xf57ff06f     /* instr. sync. barrier; last f = SY */
17 #define WFI     WORD    $0xe320f003     /* wait for interrupt */
18 #define WFI_EQ  WORD    $0x0320f003     /* wait for interrupt if eq */
19 #define ERET    WORD    $0xe160006e     /* exception return from HYP */
20 #define SEV     WORD    $0xe320f004     /* send event */
21
22 /* tas/cas strex debugging limits; started at 10000 */
23 #define MAXSC 1000000
24
25 TEXT armstart(SB), 1, $-4
26
27         /*
28          * if not cpu0, go to secondary startup
29          */
30         CPUID(R1)
31         BNE     reset
32
33         /*
34          * go to SVC mode, interrupts disabled
35          */
36         BL      svcmode(SB)
37
38         /*
39          * disable the mmu and caches
40          */
41         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
42         BIC     $(CpCdcache|CpCicache|CpCmmu), R1
43         ORR     $(CpCsbo|CpCsw), R1
44         BIC     $CpCsbz, R1
45         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
46         BARRIERS
47
48         /*
49          * turn SMP off
50          */
51         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
52         BIC     $CpACsmp, R1
53         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
54         BARRIERS
55
56         /*
57          * clear mach and page tables
58          */
59         MOVW    $PADDR(MACHADDR), R1
60         MOVW    $PADDR(KTZERO), R2
61         MOVW    $0, R0
62 _ramZ:
63         MOVW    R0, (R1)
64         ADD     $4, R1
65         CMP     R1, R2
66         BNE     _ramZ   
67
68         /*
69          * start stack at top of mach (physical addr)
70          * set up page tables for kernel
71          */
72         MOVW    $PADDR(MACHADDR+MACHSIZE-4), R13
73
74         MOVW    $PADDR(L1), R0
75         BL      mmuinit(SB)
76         BL      mmuinvalidate(SB)
77
78         /*
79          * set up domain access control and page table base
80          */
81         MOVW    $Client, R1
82         MCR     CpSC, 0, R1, C(CpDAC), C(0)
83         MOVW    $PADDR(L1), R1
84         ORR     $(CpTTBs|CpTTBowba|CpTTBiwba), R1
85         MCR     CpSC, 0, R1, C(CpTTB), C(0)
86         MCR     CpSC, 0, R1, C(CpTTB), C(0), CpTTB1     /* cortex has two */
87
88         /*
89          * invalidate my caches before enabling
90          */
91         BL      cachedinv(SB)
92         BL      cacheiinv(SB)
93         BL      l2cacheuinv(SB)
94         BARRIERS
95
96         /*
97          * turn SMP on
98          */
99         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
100         ORR     $CpACsmp, R1
101         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
102         BARRIERS
103
104         /*
105          * enable caches, mmu, and high vectors
106          */
107         MRC     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
108         ORR     $(CpChv|CpCdcache|CpCicache|CpCmmu), R0
109         MCR     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
110         BARRIERS
111
112         /*
113          * switch SB, SP, and PC into KZERO space
114          */
115         MOVW    $setR12(SB), R12
116         MOVW    $(MACHADDR+MACHSIZE-4), R13
117         MOVW    $_startpg(SB), R15
118
119 TEXT _startpg(SB), 1, $-4
120
121         /*
122          * enable cycle counter
123          */
124         MOVW    $(1<<31), R1
125         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc
126         MOVW    $1, R1
127         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc
128
129         /* first arg to main is saved R2 */
130         MOVW    R10, R0
131
132         /*
133          * call main and loop forever if it returns
134          */
135         BL      ,main(SB)
136         B       ,0(PC)
137
138         BL      _div(SB)                /* hack to load _div, etc. */
139
140 /*
141  * startup entry for cpu(s) other than 0
142  */
143 TEXT cpureset(SB), 1, $-4
144 reset:
145         /*
146          * load physical base for SB addressing while mmu is off
147          */
148         MOVW    $setR12(SB), R12
149         SUB     $KZERO, R12
150         ADD     $PHYSDRAM, R12
151
152         /*
153          * SVC mode, interrupts disabled
154          */
155         BL      svcmode(SB)
156
157         /*
158          * disable the mmu and caches
159          */
160         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
161         BIC     $(CpCdcache|CpCicache|CpCmmu), R1
162         ORR     $(CpCsbo|CpCsw), R1
163         BIC     $CpCsbz, R1
164         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
165         BARRIERS
166
167         /*
168          * turn SMP off
169          */
170         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
171         BIC     $CpACsmp, R1
172         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
173         BARRIERS
174
175         /*
176          * find Mach for this cpu
177          */
178         MRC     CpSC, 0, R2, C(CpID), C(CpIDidct), CpIDmpid
179         AND     $(MAXMACH-1), R2        /* mask out non-cpu-id bits */
180         SLL     $2, R2                  /* convert to word index */
181         MOVW    $machaddr(SB), R0
182         BIC     $KSEGM, R0
183         ORR     $PHYSDRAM, R0
184         ADD     R2, R0                  /* R0 = &machaddr[cpuid] */
185         MOVW    (R0), R0                /* R0 = machaddr[cpuid] */
186         CMP     $0, R0
187         BEQ     0(PC)                   /* must not be zero */
188         SUB     $KZERO, R0, R(MACH)     /* m = PADDR(machaddr[cpuid]) */
189
190         /*
191          * start stack at top of local Mach
192          */
193         ADD     $(MACHSIZE-4), R(MACH), R13
194
195         BL      mmuinvalidate(SB)
196
197         /*
198          * set up domain access control and page table base
199          */
200         MOVW    $Client, R1
201         MCR     CpSC, 0, R1, C(CpDAC), C(0)
202         MOVW    12(R(MACH)), R1 /* m->mmul1 */
203         SUB     $KZERO, R1              /* phys addr */
204         ORR     $(CpTTBs|CpTTBowba|CpTTBiwba), R1
205         MCR     CpSC, 0, R1, C(CpTTB), C(0)
206         MCR     CpSC, 0, R1, C(CpTTB), C(0), CpTTB1     /* cortex has two */
207
208         /*
209          * invalidate my caches before enabling
210          */
211         BL      cachedinv(SB)
212         BL      cacheiinv(SB)
213         BARRIERS
214
215         /*
216          * turn SMP on
217          */
218         MRC     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
219         ORR     $CpACsmp, R1
220         MCR     CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
221         BARRIERS
222
223         /*
224          * enable caches, mmu, and high vectors
225          */
226         MRC     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
227         ORR     $(CpChv|CpCdcache|CpCicache|CpCmmu), R0
228         MCR     CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
229         BARRIERS
230
231         /*
232          * switch MACH, SB, SP, and PC into KZERO space
233          */
234         ADD     $KZERO, R(MACH)
235         MOVW    $setR12(SB), R12
236         ADD     $KZERO, R13
237         MOVW    $_startpg2(SB), R15
238
239 TEXT _startpg2(SB), 1, $-4
240
241         /*
242          * enable cycle counter
243          */
244         MOVW    $(1<<31), R1
245         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenacyc
246         MOVW    $1, R1
247         MCR     CpSC, 0, R1, C(CpCLD), C(CpCLDena), CpCLDenapmnc
248
249         /*
250          * call cpustart and loop forever if it returns
251          */
252         MRC     CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDmpid
253         AND     $(MAXMACH-1), R0                /* mask out non-cpu-id bits */
254         BL      ,cpustart(SB)
255         B       ,0(PC)
256
257 /*
258  * get into SVC mode with interrupts disabled
259  * raspberry pi firmware since 29 Sept 2015 starts in HYP mode
260  */
261 TEXT svcmode(SB), 1, $-4
262         MOVW    CPSR, R1
263         AND     $PsrMask, R1
264         MOVW    $PsrMhyp, R2
265         CMP     R2, R1
266         MOVW    $(PsrDirq|PsrDfiq|PsrMsvc), R1
267         BNE     nothyp
268         MSR(1, 1, 1, 0xe)       /* MOVW R1, SPSR_HYP */
269         MSR(0, 14, 1, 0xe)      /* MOVW R14, ELR_HYP */
270         ERET
271 nothyp:
272         MOVW    R1, CPSR
273         RET
274
275 TEXT cpidget(SB), 1, $-4                        /* main ID */
276         MRC     CpSC, 0, R0, C(CpID), C(0), CpIDid
277         RET
278
279 TEXT fsrget(SB), 1, $-4                         /* data fault status */
280         MRC     CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata
281         RET
282
283 TEXT ifsrget(SB), 1, $-4                        /* instruction fault status */
284         MRC     CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst
285         RET
286
287 TEXT farget(SB), 1, $-4                         /* fault address */
288         MRC     CpSC, 0, R0, C(CpFAR), C(0x0)
289         RET
290
291 TEXT cpctget(SB), 1, $-4                        /* cache type */
292         MRC     CpSC, 0, R0, C(CpID), C(CpIDidct), CpIDct
293         RET
294
295 TEXT lcycles(SB), 1, $-4
296         MRC     CpSC, 0, R0, C(CpCLD), C(CpCLDcyc), 0
297         RET
298
299 TEXT splhi(SB), 1, $-4
300         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
301
302         MOVW    CPSR, R0                        /* turn off irqs (but not fiqs) */
303         ORR     $(PsrDirq), R0, R1
304         MOVW    R1, CPSR
305         RET
306
307 TEXT splfhi(SB), 1, $-4
308         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
309
310         MOVW    CPSR, R0                        /* turn off irqs and fiqs */
311         ORR     $(PsrDirq|PsrDfiq), R0, R1
312         MOVW    R1, CPSR
313         RET
314
315 TEXT splflo(SB), 1, $-4
316         MOVW    CPSR, R0                        /* turn on fiqs */
317         BIC     $(PsrDfiq), R0, R1
318         MOVW    R1, CPSR
319         RET
320
321 TEXT spllo(SB), 1, $-4
322         MOVW    CPSR, R0                        /* turn on irqs and fiqs */
323         MOVW    $0, R1
324         CMP.S   R1, R(MACH)
325         MOVW.NE R1, 4(R(MACH))                  /* clear m->splpc */
326         BIC     $(PsrDirq|PsrDfiq), R0, R1
327         MOVW    R1, CPSR
328         RET
329
330 TEXT splx(SB), 1, $-4
331         MOVW    R14, 4(R(MACH))         /* save caller pc in m->splpc */
332
333         MOVW    R0, R1                          /* reset interrupt level */
334         MOVW    CPSR, R0
335         MOVW    R1, CPSR
336         RET
337
338 TEXT spldone(SB), 1, $0                         /* end marker for devkprof.c */
339         RET
340
341 TEXT islo(SB), 1, $-4
342         MOVW    CPSR, R0
343         AND     $(PsrDirq), R0
344         EOR     $(PsrDirq), R0
345         RET
346
347 TEXT cas(SB), $0
348 TEXT cmpswap(SB), $0
349         MOVW    ov+4(FP), R1
350         MOVW    nv+8(FP), R2
351 spincas:
352         LDREX   (R0), R3
353         CMP.S   R3, R1
354         BNE     fail
355         STREX   R2, (R0), R4
356         CMP.S   $0, R4
357         BNE     spincas
358         MOVW    $1, R0
359         DMB
360         RET
361 fail:
362         CLREX
363         MOVW    $0, R0
364         RET
365
366 TEXT    tas(SB), $-4
367 TEXT    _tas(SB), $-4                   /* _tas(ulong *) */
368         /* returns old (R0) after modifying (R0) */
369         MOVW    R0,R5
370         DMB
371
372         MOVW    $1,R2           /* new value of (R0) */
373         MOVW    $MAXSC, R8
374 tas1:
375         LDREX (R5), R7
376         CMP.S   $0, R7          /* old value non-zero (lock taken)? */
377         BNE     lockbusy        /* we lose */
378         SUB.S   $1, R8
379         BEQ     lockloop2
380         STREX R2,(R5),R4
381         CMP.S   $0, R4
382         BNE     tas1            /* strex failed? try again */
383         DMB
384         B       tas0
385 lockloop2:
386         BL      abort(SB)
387 lockbusy:
388         CLREX
389 tas0:
390         MOVW    R7, R0          /* return old value */
391         RET
392
393 TEXT setlabel(SB), 1, $-4
394         MOVW    R13, 0(R0)              /* sp */
395         MOVW    R14, 4(R0)              /* pc */
396         MOVW    $0, R0
397         RET
398
399 TEXT gotolabel(SB), 1, $-4
400         MOVW    0(R0), R13              /* sp */
401         MOVW    4(R0), R14              /* pc */
402         MOVW    $1, R0
403         RET
404
405 TEXT getcallerpc(SB), 1, $-4
406         MOVW    0(R13), R0
407         RET
408
409 TEXT idlehands(SB), $-4
410         MOVW    CPSR, R3
411         ORR     $(PsrDirq|PsrDfiq), R3, R1              /* splfhi */
412         MOVW    R1, CPSR
413
414         DSB
415         MOVW    nrdy(SB), R0
416         CMP     $0, R0
417         WFI_EQ
418         DSB
419
420         MOVW    R3, CPSR                        /* splx */
421         RET
422
423
424 TEXT coherence(SB), $-4
425         BARRIERS
426         RET
427
428 TEXT sev(SB), $-4
429         SEV
430         RET
431
432 /*
433  * invalidate tlb
434  */
435 TEXT mmuinvalidate(SB), 1, $-4
436         DSB
437         MOVW    $0, R0
438         MCR     CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
439         BARRIERS
440         RET
441
442 /*
443  * mmuinvalidateaddr(va)
444  *   invalidate tlb entry for virtual page address va, ASID 0
445  */
446 TEXT mmuinvalidateaddr(SB), 1, $-4
447         DSB
448         MCR     CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
449         BARRIERS
450         RET
451
452 /*
453  * `single-element' cache operations.
454  * in arm arch v7, if effective to PoC, they operate on all cache levels, so separate
455  * l2 functions are unnecessary.
456  */
457
458 TEXT cachedwbse(SB), $-4                        /* D writeback SE */
459         MOVW    R0, R2
460
461         MOVW    CPSR, R3
462         CPSID                                   /* splhi */
463
464         BARRIERS                        /* force outstanding stores to cache */
465         MOVW    R2, R0
466         MOVW    4(FP), R1
467         ADD     R0, R1                          /* R1 is end address */
468         BIC     $(CACHELINESZ-1), R0            /* cache line start */
469 _dwbse:
470         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
471         /* can't have a BARRIER here since it zeroes R0 */
472         ADD     $CACHELINESZ, R0
473         CMP.S   R0, R1
474         BGT     _dwbse
475         B       _wait
476
477 /*
478  * TLB on armv7 loads from cache, so no need for writeback
479  */
480 TEXT cachedwbtlb(SB), $-4
481         DSB
482         ISB
483         RET
484
485 TEXT cachedwbinvse(SB), $-4                     /* D writeback+invalidate SE */
486         MOVW    R0, R2
487
488         MOVW    CPSR, R3
489         CPSID                                   /* splhi */
490
491         BARRIERS                        /* force outstanding stores to cache */
492         MOVW    R2, R0
493         MOVW    4(FP), R1
494         ADD     R0, R1                          /* R1 is end address */
495         BIC     $(CACHELINESZ-1), R0            /* cache line start */
496 _dwbinvse:
497         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
498         /* can't have a BARRIER here since it zeroes R0 */
499         ADD     $CACHELINESZ, R0
500         CMP.S   R0, R1
501         BGT     _dwbinvse
502 _wait:                                          /* drain write buffer */
503         BARRIERS
504
505         MOVW    R3, CPSR                        /* splx */
506         RET
507
508 TEXT cachedinvse(SB), $-4                       /* D invalidate SE */
509         MOVW    R0, R2
510
511         MOVW    CPSR, R3
512         CPSID                                   /* splhi */
513
514         BARRIERS                        /* force outstanding stores to cache */
515         MOVW    R2, R0
516         MOVW    4(FP), R1
517         ADD     R0, R1                          /* R1 is end address */
518         BIC     $(CACHELINESZ-1), R0            /* cache line start */
519 _dinvse:
520         MCR     CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
521         /* can't have a BARRIER here since it zeroes R0 */
522         ADD     $CACHELINESZ, R0
523         CMP.S   R0, R1
524         BGT     _dinvse
525         B       _wait
526
527 #include "cache.v7.s"