xref: /plan9/sys/src/9/omap/l.s (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1/*
2 * ti omap3530 SoC machine assist
3 * arm cortex-a8 processor
4 *
5 * loader uses R11 as scratch.
6 * R9 and R10 are used for `extern register' variables.
7 *
8 * ARM v7 arch. ref. man. §B1.3.3 that we don't need barriers
9 * around moves to CPSR.
10 */
11
12#include "arm.s"
13
14/*
15 * MCR and MRC are counter-intuitively named.
16 *	MCR	coproc, opcode1, Rd, CRn, CRm[, opcode2]	# arm -> coproc
17 *	MRC	coproc, opcode1, Rd, CRn, CRm[, opcode2]	# coproc -> arm
18 */
19
20/*
21 * Entered here from Das U-Boot or another Plan 9 kernel with MMU disabled.
22 * Until the MMU is enabled it is OK to call functions provided
23 * they are within ±32MiB relative and do not require any
24 * local variables or more than one argument (i.e. there is
25 * no stack).
26 */
27TEXT _start(SB), 1, $-4
28	MOVW	$setR12(SB), R12		/* load the SB */
29	SUB	$KZERO, R12
30	ADD	$PHYSDRAM, R12
31
32	/* SVC mode, interrupts disabled */
33	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
34	MOVW	R1, CPSR
35	BARRIERS
36
37	DELAY(printloopret, 1)
38PUTC('\r')
39	DELAY(printloopnl, 1)
40PUTC('\n')
41	/*
42	 * work around errata
43	 */
44	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
45	ORR	$(CpACissue1|CpACldstissue1), R1  /* fight omap35x errata 3.1.1.9 */
46	ORR	$CpACibe, R1			/* enable cp15 invalidate */
47	ORR	$CpACl1pe, R1			/* enable l1 parity checking */
48	ORR	$CpCalign, R1			/* catch alignment errors */
49	BIC	$CpACasa, R1			/* no speculative accesses */
50	/* go faster with fewer restrictions */
51	BIC	$(CpACcachenopipe|CpACcp15serial|CpACcp15waitidle|CpACcp15pipeflush), R1
52	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
53	ISB
54
55	MRC	CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
56	ORR	$CpCl2nowralloc, R1		/* fight cortex errata 460075 */
57	ORR	$(CpCl2ecc|CpCl2eccparity), R1
58#ifdef TEDIUM
59	/*
60	 * I don't know why this clobbers the system, but I'm tired
61	 * of arguing with this fussy processor.  To hell with it.
62	 */
63	MCR	CpSC, 1, R1, C(CpCLD), C(CpCLDl2), CpCLDl2aux
64	ISB
65#endif
66	DELAY(printloops, 1)
67PUTC('P')
68	/*
69	 * disable the MMU & caches
70	 */
71	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
72	BIC	$(CpCdcache|CpCicache|CpCmmu), R1
73	ORR	$CpCsbo, R1
74	BIC	$CpCsbz, R1
75	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
76	ISB
77
78	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
79	BIC	$CpACl2en, R1			/* turn l2 cache off */
80	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
81	ISB
82
83PUTC('l')
84	DELAY(printloop3, 1)
85
86PUTC('a')
87	/* clear Mach */
88	MOVW	$PADDR(MACHADDR), R4		/* address of Mach */
89	MOVW	$0, R0
90_machZ:
91	MOVW	R0, (R4)
92	ADD	$4, R4
93	CMP.S	$PADDR(L1+L1X(0)), R4	/* end at top-level page table */
94	BNE	_machZ
95
96	/*
97	 * set up the MMU page table
98	 */
99
100PUTC('n')
101	/* clear all PTEs first, to provide a default */
102//	MOVW	$PADDR(L1+L1X(0)), R4		/* address of PTE for 0 */
103_ptenv0:
104	ZEROPTE()
105	CMP.S	$PADDR(L1+16*KiB), R4
106	BNE	_ptenv0
107
108	DELAY(printloop4, 2)
109PUTC(' ')
110	/*
111	 * set up double map of PHYSDRAM, KZERO to PHYSDRAM for first few MBs,
112	 * but only if KZERO and PHYSDRAM differ.
113	 */
114	MOVW	$PTEDRAM, R2			/* PTE bits */
115	MOVW	$PHYSDRAM, R3			/* pa */
116	CMP	$KZERO, R3
117	BEQ	no2map
118	MOVW	$PADDR(L1+L1X(PHYSDRAM)), R4  /* address of PTE for PHYSDRAM */
119	MOVW	$DOUBLEMAPMBS, R5
120_ptdbl:
121	FILLPTE()
122	SUB.S	$1, R5
123	BNE	_ptdbl
124no2map:
125
126	/*
127	 * back up and fill in PTEs for memory at KZERO.
128	 * beagle has 1 bank of 256MB of SDRAM at PHYSDRAM;
129	 * igepv2 has 1 bank of 512MB at PHYSDRAM.
130	 * Map the maximum (512MB).
131	 */
132PUTC('9')
133	MOVW	$PTEDRAM, R2			/* PTE bits */
134	MOVW	$PHYSDRAM, R3
135	MOVW	$PADDR(L1+L1X(KZERO)), R4	/* start with PTE for KZERO */
136	MOVW	$512, R5			/* inner loop count (MBs) */
137_ptekrw:					/* set PTEs */
138	FILLPTE()
139	SUB.S	$1, R5				/* decrement inner loop count */
140	BNE	_ptekrw
141
142	/*
143	 * back up and fill in PTEs for MMIO
144	 * stop somewhere after uarts
145	 */
146PUTC(' ')
147	MOVW	$PTEIO, R2			/* PTE bits */
148	MOVW	$PHYSIO, R3
149	MOVW	$PADDR(L1+L1X(VIRTIO)), R4	/* start with PTE for VIRTIO */
150_ptenv2:
151	FILLPTE()
152	CMP.S	$PADDR(L1+L1X(PHYSIOEND)), R4
153	BNE	_ptenv2
154
155	/* mmu.c sets up the trap vectors later */
156
157	/*
158	 * set up a temporary stack; avoid data & bss segments
159	 */
160	MOVW	$(PHYSDRAM | (128*1024*1024)), R13
161
162	/* invalidate caches */
163	BL	cachedinv(SB)
164	MOVW	$KZERO, R0
165	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
166	ISB
167	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
168	BARRIERS
169
170PUTC('f')
171	/*
172	 * turn caches on
173	 */
174	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
175	ORR	$CpACl2en, R1			/* turn l2 cache on */
176	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpAuxctl
177	BARRIERS
178
179	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
180	ORR	$(CpCdcache|CpCicache), R1
181	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
182	BARRIERS
183
184PUTC('r')
185	/* set the domain access control */
186	MOVW	$Client, R0
187	BL	dacput(SB)
188
189	DELAY(printloop5, 2)
190PUTC('o')
191	/* set the translation table base */
192	MOVW	$PADDR(L1), R0
193	BL	ttbput(SB)
194
195	MOVW	$0, R0
196	BL	pidput(SB)		/* paranoia */
197
198PUTC('m')
199	/*
200	 * the little dance to turn the MMU on
201	 */
202	BL	cacheuwbinv(SB)
203	BL	mmuinvalidate(SB)
204	BL	mmuenable(SB)
205
206PUTC(' ')
207	/* warp the PC into the virtual map */
208	MOVW	$KZERO, R0
209	BL	_r15warp(SB)
210
211	/*
212	 * now running at KZERO+something!
213	 */
214
215	MOVW	$setR12(SB), R12		/* reload the SB */
216
217	/*
218	 * set up temporary stack again, in case we've just switched
219	 * to a new register set.
220	 */
221	MOVW	$(KZERO|(128*1024*1024)), R13
222
223	/* can now execute arbitrary C code */
224
225	BL	cacheuwbinv(SB)
226
227PUTC('B')
228	MOVW	$PHYSDRAM, R3			/* pa */
229	CMP	$KZERO, R3
230	BEQ	no2unmap
231	/* undo double map of PHYSDRAM, KZERO & first few MBs */
232	MOVW	$(L1+L1X(PHYSDRAM)), R4		/* addr. of PTE for PHYSDRAM */
233	MOVW	$0, R0
234	MOVW	$DOUBLEMAPMBS, R5
235_ptudbl:
236	ZEROPTE()
237	SUB.S	$1, R5
238	BNE	_ptudbl
239no2unmap:
240	BARRIERS
241	MOVW	$KZERO, R0
242	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
243	BARRIERS
244
245#ifdef HIGH_SECURITY				/* i.e., not GP omap */
246	/* hack: set `secure monitor' vector base addr for cortex */
247//	MOVW	$HVECTORS, R0
248	MOVW	$PADDR(L1), R0
249	SUB	$(MACHSIZE+(2*1024)), R0
250	MCR	CpSC, 0, R0, C(CpVECS), C(CpVECSbase), CpVECSmon
251	ISB
252#endif
253
254	/*
255	 * call main in C
256	 * pass Mach to main and set up the stack in it
257	 */
258	MOVW	$(MACHADDR), R0			/* Mach */
259	MOVW	R0, R13
260	ADD	$(MACHSIZE), R13		/* stack pointer */
261	SUB	$4, R13				/* space for link register */
262	MOVW	R0, R10				/* m = MACHADDR */
263PUTC('e')
264	BL	main(SB)			/* void main(Mach*) */
265	/*FALLTHROUGH*/
266
267/*
268 * reset the system
269 */
270
271TEXT _reset(SB), 1, $-4
272	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R0
273	MOVW	R0, CPSR
274	BARRIERS
275
276	DELAY(printloopr, 2)
277PUTC('!')
278PUTC('r')
279PUTC('e')
280PUTC('s')
281PUTC('e')
282PUTC('t')
283PUTC('!')
284PUTC('\r')
285PUTC('\n')
286
287	/* turn the caches off */
288	BL	cacheuwbinv(SB)
289
290	MRC	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
291	BIC	$(CpCicache|CpCdcache|CpCalign), R0
292	ORR	$CpCsw, R0			/* enable SWP */
293	MCR	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
294	BARRIERS
295
296	/* redo double map of PHYSDRAM, KZERO & first few MBs */
297	MOVW	$PTEDRAM, R2			/* PTE bits */
298	MOVW	$PHYSDRAM, R3			/* pa */
299	MOVW	$(L1+L1X(PHYSDRAM)), R4		/* address of PHYSDRAM's PTE */
300	MOVW	$DOUBLEMAPMBS, R5
301_ptrdbl:
302	FILLPTE()
303	SUB.S	$1, R5
304	BNE	_ptrdbl
305
306	MOVW	$PHYSDRAM, R0
307	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
308	BARRIERS
309
310	/* turn the MMU off */
311	MOVW	$PHYSDRAM, R0
312	BL	_r15warp(SB)
313	BL	mmuinvalidate(SB)
314	BL	mmudisable(SB)
315
316	/* set new reset vector */
317	MOVW	$HVECTORS, R2
318	MOVW	$0xe59ff018, R3			/* MOVW 0x18(R15), R15 */
319	MOVW	R3, (R2)
320	BARRIERS
321
322//	MOVW	$PHYSFLASH, R3			/* TODO */
323//	MOVW	R3, 0x20(R2)			/* where $0xe59ff018 jumps to */
324
325	/* ...and jump to it */
326//	MOVW	R2, R15				/* software reboot */
327_limbo:						/* should not get here... */
328	BL	idlehands(SB)
329	B	_limbo				/* ... and can't get out */
330	BL	_div(SB)			/* hack to load _div, etc. */
331
332TEXT _r15warp(SB), 1, $-4
333	BIC	$KSEGM, R14			/* link reg, will become PC */
334	ORR	R0, R14
335	BIC	$KSEGM, R13			/* SP too */
336	ORR	R0, R13
337	RET
338
339/*
340 * `single-element' cache operations.
341 * in arm arch v7, they operate on all cache levels, so separate
342 * l2 functions are unnecessary.
343 */
344
345TEXT cachedwbse(SB), $-4			/* D writeback SE */
346	MOVW	R0, R2
347
348	MOVW	CPSR, R3
349	CPSID					/* splhi */
350
351	BARRIERS			/* force outstanding stores to cache */
352	MOVW	R2, R0
353	MOVW	4(FP), R1
354	ADD	R0, R1				/* R1 is end address */
355	BIC	$(CACHELINESZ-1), R0		/* cache line start */
356_dwbse:
357	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEse
358	/* can't have a BARRIER here since it zeroes R0 */
359	ADD	$CACHELINESZ, R0
360	CMP.S	R0, R1
361	BGT	_dwbse
362	B	_wait
363
364TEXT cachedwbinvse(SB), $-4			/* D writeback+invalidate SE */
365	MOVW	R0, R2
366
367	MOVW	CPSR, R3
368	CPSID					/* splhi */
369
370	BARRIERS			/* force outstanding stores to cache */
371	MOVW	R2, R0
372	MOVW	4(FP), R1
373	ADD	R0, R1				/* R1 is end address */
374	BIC	$(CACHELINESZ-1), R0		/* cache line start */
375_dwbinvse:
376	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEse
377	/* can't have a BARRIER here since it zeroes R0 */
378	ADD	$CACHELINESZ, R0
379	CMP.S	R0, R1
380	BGT	_dwbinvse
381_wait:						/* drain write buffer */
382	BARRIERS
383	/* drain L1 write buffer, also drains L2 eviction buffer on sheeva */
384	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
385	ISB
386
387	MOVW	R3, CPSR			/* splx */
388	RET
389
390TEXT cachedinvse(SB), $-4			/* D invalidate SE */
391	MOVW	R0, R2
392
393	MOVW	CPSR, R3
394	CPSID					/* splhi */
395
396	BARRIERS			/* force outstanding stores to cache */
397	MOVW	R2, R0
398	MOVW	4(FP), R1
399	ADD	R0, R1				/* R1 is end address */
400	BIC	$(CACHELINESZ-1), R0		/* cache line start */
401_dinvse:
402	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvd), CpCACHEse
403	/* can't have a BARRIER here since it zeroes R0 */
404	ADD	$CACHELINESZ, R0
405	CMP.S	R0, R1
406	BGT	_dinvse
407	B	_wait
408
409/*
410 *  enable mmu and high vectors
411 */
412TEXT mmuenable(SB), 1, $-4
413	MRC	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
414	ORR	$(CpChv|CpCmmu), R0
415	MCR	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
416	BARRIERS
417	RET
418
419TEXT mmudisable(SB), 1, $-4
420	MRC	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
421	BIC	$(CpChv|CpCmmu), R0
422	MCR	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
423	BARRIERS
424	RET
425
426/*
427 * If one of these MCR instructions crashes or hangs the machine,
428 * check your Level 1 page table (at TTB) closely.
429 */
430TEXT mmuinvalidate(SB), $-4			/* invalidate all */
431	MOVW	CPSR, R2
432	CPSID					/* interrupts off */
433
434	BARRIERS
435	MOVW	PC, R0				/* some valid virtual address */
436	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
437	BARRIERS
438	MOVW	R2, CPSR			/* interrupts restored */
439	RET
440
441TEXT mmuinvalidateaddr(SB), $-4			/* invalidate single entry */
442	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
443	BARRIERS
444	RET
445
446TEXT cpidget(SB), 1, $-4			/* main ID */
447	MRC	CpSC, 0, R0, C(CpID), C(0), CpIDid
448	RET
449
450TEXT cpctget(SB), 1, $-4			/* cache type */
451	MRC	CpSC, 0, R0, C(CpID), C(0), CpIDct
452	RET
453
454TEXT controlget(SB), 1, $-4			/* control */
455	MRC	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
456	RET
457
458TEXT ttbget(SB), 1, $-4				/* translation table base */
459	MRC	CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
460	RET
461
462TEXT ttbput(SB), 1, $-4				/* translation table base */
463	MCR	CpSC, 0, R0, C(CpTTB), C(0), CpTTB0
464	MCR	CpSC, 0, R0, C(CpTTB), C(0), CpTTB1	/* cortex has two */
465	ISB
466	RET
467
468TEXT dacget(SB), 1, $-4				/* domain access control */
469	MRC	CpSC, 0, R0, C(CpDAC), C(0)
470	RET
471
472TEXT dacput(SB), 1, $-4				/* domain access control */
473	MCR	CpSC, 0, R0, C(CpDAC), C(0)
474	ISB
475	RET
476
477TEXT fsrget(SB), 1, $-4				/* data fault status */
478	MRC	CpSC, 0, R0, C(CpFSR), C(0), CpDFSR
479	RET
480
481TEXT ifsrget(SB), 1, $-4			/* instruction fault status */
482	MRC	CpSC, 0, R0, C(CpFSR), C(0), CpIFSR
483	RET
484
485TEXT farget(SB), 1, $-4				/* fault address */
486	MRC	CpSC, 0, R0, C(CpFAR), C(0x0)
487	RET
488
489TEXT getpsr(SB), 1, $-4
490	MOVW	CPSR, R0
491	RET
492
493TEXT getscr(SB), 1, $-4
494	MRC	CpSC, 0, R0, C(CpCONTROL), C(CpCONTROLscr), CpSCRscr
495	RET
496
497TEXT pidget(SB), 1, $-4				/* address translation pid */
498	MRC	CpSC, 0, R0, C(CpPID), C(0x0)
499	RET
500
501TEXT pidput(SB), 1, $-4				/* address translation pid */
502	MCR	CpSC, 0, R0, C(CpPID), C(0x0)
503	ISB
504	RET
505
506TEXT splhi(SB), 1, $-4
507	MOVW	CPSR, R0
508	CPSID					/* turn off interrupts */
509
510	MOVW	$(MACHADDR+4), R2		/* save caller pc in Mach */
511	MOVW	R14, 0(R2)
512	RET
513
514TEXT spllo(SB), 1, $-4			/* start marker for devkprof.c */
515	MOVW	CPSR, R0
516	CPSIE
517	RET
518
519TEXT splx(SB), 1, $-4
520	MOVW	$(MACHADDR+0x04), R2		/* save caller pc in Mach */
521	MOVW	R14, 0(R2)
522
523	MOVW	CPSR, R3
524	MOVW	R0, CPSR			/* reset interrupt level */
525	MOVW	R3, R0				/* must return old CPSR */
526	RET
527
528TEXT spldone(SB), 1, $0				/* end marker for devkprof.c */
529	RET
530
531TEXT islo(SB), 1, $-4
532	MOVW	CPSR, R0
533	AND	$(PsrDirq), R0
534	EOR	$(PsrDirq), R0
535	RET
536
537TEXT	tas(SB), $-4
538TEXT	_tas(SB), $-4
539	MOVW	R0,R1
540	MOVW	$1,R0
541	SWPW	R0,(R1)			/* fix: deprecated in armv7 */
542	RET
543
544TEXT clz(SB), $-4
545	CLZ(0, 0)			/* 0 is R0 */
546	RET
547
548TEXT setlabel(SB), 1, $-4
549	MOVW	R13, 0(R0)		/* sp */
550	MOVW	R14, 4(R0)		/* pc */
551	MOVW	$0, R0
552	RET
553
554TEXT gotolabel(SB), 1, $-4
555	MOVW	0(R0), R13		/* sp */
556	MOVW	4(R0), R14		/* pc */
557	MOVW	$1, R0
558	RET
559
560TEXT getcallerpc(SB), 1, $-4
561	MOVW	0(R13), R0
562	RET
563
564TEXT idlehands(SB), $-4
565	BARRIERS
566	WFI
567	RET
568
569TEXT coherence(SB), $-4
570	BARRIERS
571	RET
572
573#include "cache.v7.s"
574