head.S revision d4d9959c099751158c5cf14813fe378e206339c6
1/*
2 *  linux/arch/arm/boot/compressed/head.S
3 *
4 *  Copyright (C) 1996-2002 Russell King
5 *  Copyright (C) 2004 Hyok S. Choi (MPU support)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/linkage.h>
12
13/*
14 * Debugging stuff
15 *
16 * Note that these macros must not contain any code which is not
17 * 100% relocatable.  Any attempt to do so will result in a crash.
18 * Please select one of the following when turning on debugging.
19 */
20#ifdef DEBUG
21
22#if defined(CONFIG_DEBUG_ICEDCC)
23
24#ifdef CONFIG_CPU_V6
25		.macro	loadsp, rb, tmp
26		.endm
27		.macro	writeb, ch, rb
28		mcr	p14, 0, \ch, c0, c5, 0
29		.endm
30#elif defined(CONFIG_CPU_V7)
31		.macro	loadsp, rb, tmp
32		.endm
33		.macro	writeb, ch, rb
34wait:		mrc	p14, 0, pc, c0, c1, 0
35		bcs	wait
36		mcr	p14, 0, \ch, c0, c5, 0
37		.endm
38#elif defined(CONFIG_CPU_XSCALE)
39		.macro	loadsp, rb, tmp
40		.endm
41		.macro	writeb, ch, rb
42		mcr	p14, 0, \ch, c8, c0, 0
43		.endm
44#else
45		.macro	loadsp, rb, tmp
46		.endm
47		.macro	writeb, ch, rb
48		mcr	p14, 0, \ch, c1, c0, 0
49		.endm
50#endif
51
52#else
53
54#include <mach/debug-macro.S>
55
56		.macro	writeb,	ch, rb
57		senduart \ch, \rb
58		.endm
59
60#if defined(CONFIG_ARCH_SA1100)
61		.macro	loadsp, rb, tmp
62		mov	\rb, #0x80000000	@ physical base address
63#ifdef CONFIG_DEBUG_LL_SER3
64		add	\rb, \rb, #0x00050000	@ Ser3
65#else
66		add	\rb, \rb, #0x00010000	@ Ser1
67#endif
68		.endm
69#elif defined(CONFIG_ARCH_S3C2410)
70		.macro loadsp, rb, tmp
71		mov	\rb, #0x50000000
72		add	\rb, \rb, #0x4000 * CONFIG_S3C_LOWLEVEL_UART_PORT
73		.endm
74#else
75		.macro	loadsp,	rb, tmp
76		addruart \rb, \tmp
77		.endm
78#endif
79#endif
80#endif
81
82		.macro	kputc,val
83		mov	r0, \val
84		bl	putc
85		.endm
86
87		.macro	kphex,val,len
88		mov	r0, \val
89		mov	r1, #\len
90		bl	phex
91		.endm
92
93		.macro	debug_reloc_start
94#ifdef DEBUG
95		kputc	#'\n'
96		kphex	r6, 8		/* processor id */
97		kputc	#':'
98		kphex	r7, 8		/* architecture id */
99#ifdef CONFIG_CPU_CP15
100		kputc	#':'
101		mrc	p15, 0, r0, c1, c0
102		kphex	r0, 8		/* control reg */
103#endif
104		kputc	#'\n'
105		kphex	r5, 8		/* decompressed kernel start */
106		kputc	#'-'
107		kphex	r9, 8		/* decompressed kernel end  */
108		kputc	#'>'
109		kphex	r4, 8		/* kernel execution address */
110		kputc	#'\n'
111#endif
112		.endm
113
114		.macro	debug_reloc_end
115#ifdef DEBUG
116		kphex	r5, 8		/* end of kernel */
117		kputc	#'\n'
118		mov	r0, r4
119		bl	memdump		/* dump 256 bytes at start of kernel */
120#endif
121		.endm
122
123		.section ".start", #alloc, #execinstr
124/*
125 * sort out different calling conventions
126 */
127		.align
128start:
129		.type	start,#function
130		.rept	8
131		mov	r0, r0
132		.endr
133
134		b	1f
135		.word	0x016f2818		@ Magic numbers to help the loader
136		.word	start			@ absolute load/run zImage address
137		.word	_edata			@ zImage end address
1381:		mov	r7, r1			@ save architecture ID
139		mov	r8, r2			@ save atags pointer
140
141#ifndef __ARM_ARCH_2__
142		/*
143		 * Booting from Angel - need to enter SVC mode and disable
144		 * FIQs/IRQs (numeric definitions from angel arm.h source).
145		 * We only do this if we were in user mode on entry.
146		 */
147		mrs	r2, cpsr		@ get current mode
148		tst	r2, #3			@ not user?
149		bne	not_angel
150		mov	r0, #0x17		@ angel_SWIreason_EnterSVC
151 ARM(		swi	0x123456	)	@ angel_SWI_ARM
152 THUMB(		svc	0xab		)	@ angel_SWI_THUMB
153not_angel:
154		mrs	r2, cpsr		@ turn off interrupts to
155		orr	r2, r2, #0xc0		@ prevent angel from running
156		msr	cpsr_c, r2
157#else
158		teqp	pc, #0x0c000003		@ turn off interrupts
159#endif
160
161		/*
162		 * Note that some cache flushing and other stuff may
163		 * be needed here - is there an Angel SWI call for this?
164		 */
165
166		/*
167		 * some architecture specific code can be inserted
168		 * by the linker here, but it should preserve r7, r8, and r9.
169		 */
170
171		.text
172		adr	r0, LC0
173 ARM(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
174 THUMB(		ldmia	r0, {r1, r2, r3, r4, r5, r6, r11, ip}	)
175 THUMB(		ldr	sp, [r0, #32]				)
176		subs	r0, r0, r1		@ calculate the delta offset
177
178						@ if delta is zero, we are
179		beq	not_relocated		@ running at the address we
180						@ were linked at.
181
182		/*
183		 * We're running at a different address.  We need to fix
184		 * up various pointers:
185		 *   r5 - zImage base address (_start)
186		 *   r6 - size of decompressed image
187		 *   r11 - GOT start
188		 *   ip - GOT end
189		 */
190		add	r5, r5, r0
191		add	r11, r11, r0
192		add	ip, ip, r0
193
194#ifndef CONFIG_ZBOOT_ROM
195		/*
196		 * If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
197		 * we need to fix up pointers into the BSS region.
198		 *   r2 - BSS start
199		 *   r3 - BSS end
200		 *   sp - stack pointer
201		 */
202		add	r2, r2, r0
203		add	r3, r3, r0
204		add	sp, sp, r0
205
206		/*
207		 * Relocate all entries in the GOT table.
208		 */
2091:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
210		add	r1, r1, r0		@ table.  This fixes up the
211		str	r1, [r11], #4		@ C references.
212		cmp	r11, ip
213		blo	1b
214#else
215
216		/*
217		 * Relocate entries in the GOT table.  We only relocate
218		 * the entries that are outside the (relocated) BSS region.
219		 */
2201:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
221		cmp	r1, r2			@ entry < bss_start ||
222		cmphs	r3, r1			@ _end < entry
223		addlo	r1, r1, r0		@ table.  This fixes up the
224		str	r1, [r11], #4		@ C references.
225		cmp	r11, ip
226		blo	1b
227#endif
228
229not_relocated:	mov	r0, #0
2301:		str	r0, [r2], #4		@ clear bss
231		str	r0, [r2], #4
232		str	r0, [r2], #4
233		str	r0, [r2], #4
234		cmp	r2, r3
235		blo	1b
236
237		/*
238		 * The C runtime environment should now be setup
239		 * sufficiently.  Turn the cache on, set up some
240		 * pointers, and start decompressing.
241		 */
242		bl	cache_on
243
244		mov	r1, sp			@ malloc space above stack
245		add	r2, sp, #0x10000	@ 64k max
246
247/*
248 * Check to see if we will overwrite ourselves.
249 *   r4 = final kernel address
250 *   r5 = start of this image
251 *   r6 = size of decompressed image
252 *   r2 = end of malloc space (and therefore this image)
253 * We basically want:
254 *   r4 >= r2 -> OK
255 *   r4 + image length <= r5 -> OK
256 */
257		cmp	r4, r2
258		bhs	wont_overwrite
259		add	r0, r4, r6
260		cmp	r0, r5
261		bls	wont_overwrite
262
263		mov	r5, r2			@ decompress after malloc space
264		mov	r0, r5
265		mov	r3, r7
266		bl	decompress_kernel
267
268		add	r0, r0, #127 + 128	@ alignment + stack
269		bic	r0, r0, #127		@ align the kernel length
270/*
271 * r0     = decompressed kernel length
272 * r1-r3  = unused
273 * r4     = kernel execution address
274 * r5     = decompressed kernel start
275 * r7     = architecture ID
276 * r8     = atags pointer
277 * r9-r12,r14 = corrupted
278 */
279		add	r1, r5, r0		@ end of decompressed kernel
280		adr	r2, reloc_start
281		ldr	r3, LC1
282		add	r3, r2, r3
2831:		ldmia	r2!, {r9 - r12, r14}	@ copy relocation code
284		stmia	r1!, {r9 - r12, r14}
285		ldmia	r2!, {r9 - r12, r14}
286		stmia	r1!, {r9 - r12, r14}
287		cmp	r2, r3
288		blo	1b
289		mov	sp, r1
290		add	sp, sp, #128		@ relocate the stack
291
292		bl	cache_clean_flush
293 ARM(		add	pc, r5, r0		) @ call relocation code
294 THUMB(		add	r12, r5, r0		)
295 THUMB(		mov	pc, r12			) @ call relocation code
296
297/*
298 * We're not in danger of overwriting ourselves.  Do this the simple way.
299 *
300 * r4     = kernel execution address
301 * r7     = architecture ID
302 */
303wont_overwrite:	mov	r0, r4
304		mov	r3, r7
305		bl	decompress_kernel
306		b	call_kernel
307
308		.align	2
309		.type	LC0, #object
310LC0:		.word	LC0			@ r1
311		.word	__bss_start		@ r2
312		.word	_end			@ r3
313		.word	zreladdr		@ r4
314		.word	_start			@ r5
315		.word	_image_size		@ r6
316		.word	_got_start		@ r11
317		.word	_got_end		@ ip
318		.word	user_stack+4096		@ sp
319LC1:		.word	reloc_end - reloc_start
320		.size	LC0, . - LC0
321
322#ifdef CONFIG_ARCH_RPC
323		.globl	params
324params:		ldr	r0, =params_phys
325		mov	pc, lr
326		.ltorg
327		.align
328#endif
329
330/*
331 * Turn on the cache.  We need to setup some page tables so that we
332 * can have both the I and D caches on.
333 *
334 * We place the page tables 16k down from the kernel execution address,
335 * and we hope that nothing else is using it.  If we're using it, we
336 * will go pop!
337 *
338 * On entry,
339 *  r4 = kernel execution address
340 *  r7 = architecture number
341 *  r8 = atags pointer
342 *  r9 = run-time address of "start"  (???)
343 * On exit,
344 *  r1, r2, r3, r9, r10, r12 corrupted
345 * This routine must preserve:
346 *  r4, r5, r6, r7, r8
347 */
348		.align	5
349cache_on:	mov	r3, #8			@ cache_on function
350		b	call_cache_fn
351
352/*
353 * Initialize the highest priority protection region, PR7
354 * to cover all 32bit address and cacheable and bufferable.
355 */
356__armv4_mpu_cache_on:
357		mov	r0, #0x3f		@ 4G, the whole
358		mcr	p15, 0, r0, c6, c7, 0	@ PR7 Area Setting
359		mcr 	p15, 0, r0, c6, c7, 1
360
361		mov	r0, #0x80		@ PR7
362		mcr	p15, 0, r0, c2, c0, 0	@ D-cache on
363		mcr	p15, 0, r0, c2, c0, 1	@ I-cache on
364		mcr	p15, 0, r0, c3, c0, 0	@ write-buffer on
365
366		mov	r0, #0xc000
367		mcr	p15, 0, r0, c5, c0, 1	@ I-access permission
368		mcr	p15, 0, r0, c5, c0, 0	@ D-access permission
369
370		mov	r0, #0
371		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
372		mcr	p15, 0, r0, c7, c5, 0	@ flush(inval) I-Cache
373		mcr	p15, 0, r0, c7, c6, 0	@ flush(inval) D-Cache
374		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
375						@ ...I .... ..D. WC.M
376		orr	r0, r0, #0x002d		@ .... .... ..1. 11.1
377		orr	r0, r0, #0x1000		@ ...1 .... .... ....
378
379		mcr	p15, 0, r0, c1, c0, 0	@ write control reg
380
381		mov	r0, #0
382		mcr	p15, 0, r0, c7, c5, 0	@ flush(inval) I-Cache
383		mcr	p15, 0, r0, c7, c6, 0	@ flush(inval) D-Cache
384		mov	pc, lr
385
386__armv3_mpu_cache_on:
387		mov	r0, #0x3f		@ 4G, the whole
388		mcr	p15, 0, r0, c6, c7, 0	@ PR7 Area Setting
389
390		mov	r0, #0x80		@ PR7
391		mcr	p15, 0, r0, c2, c0, 0	@ cache on
392		mcr	p15, 0, r0, c3, c0, 0	@ write-buffer on
393
394		mov	r0, #0xc000
395		mcr	p15, 0, r0, c5, c0, 0	@ access permission
396
397		mov	r0, #0
398		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
399		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
400						@ .... .... .... WC.M
401		orr	r0, r0, #0x000d		@ .... .... .... 11.1
402		mov	r0, #0
403		mcr	p15, 0, r0, c1, c0, 0	@ write control reg
404
405		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
406		mov	pc, lr
407
408__setup_mmu:	sub	r3, r4, #16384		@ Page directory size
409		bic	r3, r3, #0xff		@ Align the pointer
410		bic	r3, r3, #0x3f00
411/*
412 * Initialise the page tables, turning on the cacheable and bufferable
413 * bits for the RAM area only.
414 */
415		mov	r0, r3
416		mov	r9, r0, lsr #18
417		mov	r9, r9, lsl #18		@ start of RAM
418		add	r10, r9, #0x10000000	@ a reasonable RAM size
419		mov	r1, #0x12
420		orr	r1, r1, #3 << 10
421		add	r2, r3, #16384
4221:		cmp	r1, r9			@ if virt > start of RAM
423		orrhs	r1, r1, #0x0c		@ set cacheable, bufferable
424		cmp	r1, r10			@ if virt > end of RAM
425		bichs	r1, r1, #0x0c		@ clear cacheable, bufferable
426		str	r1, [r0], #4		@ 1:1 mapping
427		add	r1, r1, #1048576
428		teq	r0, r2
429		bne	1b
430/*
431 * If ever we are running from Flash, then we surely want the cache
432 * to be enabled also for our execution instance...  We map 2MB of it
433 * so there is no map overlap problem for up to 1 MB compressed kernel.
434 * If the execution is in RAM then we would only be duplicating the above.
435 */
436		mov	r1, #0x1e
437		orr	r1, r1, #3 << 10
438		mov	r2, pc, lsr #20
439		orr	r1, r1, r2, lsl #20
440		add	r0, r3, r2, lsl #2
441		str	r1, [r0], #4
442		add	r1, r1, #1048576
443		str	r1, [r0]
444		mov	pc, lr
445ENDPROC(__setup_mmu)
446
447__armv4_mmu_cache_on:
448		mov	r12, lr
449#ifdef CONFIG_MMU
450		bl	__setup_mmu
451		mov	r0, #0
452		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
453		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
454		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
455		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
456		orr	r0, r0, #0x0030
457#ifdef CONFIG_CPU_ENDIAN_BE8
458		orr	r0, r0, #1 << 25	@ big-endian page tables
459#endif
460		bl	__common_mmu_cache_on
461		mov	r0, #0
462		mcr	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
463#endif
464		mov	pc, r12
465
466__armv7_mmu_cache_on:
467		mov	r12, lr
468#ifdef CONFIG_MMU
469		mrc	p15, 0, r11, c0, c1, 4	@ read ID_MMFR0
470		tst	r11, #0xf		@ VMSA
471		blne	__setup_mmu
472		mov	r0, #0
473		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
474		tst	r11, #0xf		@ VMSA
475		mcrne	p15, 0, r0, c8, c7, 0	@ flush I,D TLBs
476#endif
477		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
478		orr	r0, r0, #0x5000		@ I-cache enable, RR cache replacement
479		orr	r0, r0, #0x003c		@ write buffer
480#ifdef CONFIG_MMU
481#ifdef CONFIG_CPU_ENDIAN_BE8
482		orr	r0, r0, #1 << 25	@ big-endian page tables
483#endif
484		orrne	r0, r0, #1		@ MMU enabled
485		movne	r1, #-1
486		mcrne	p15, 0, r3, c2, c0, 0	@ load page table pointer
487		mcrne	p15, 0, r1, c3, c0, 0	@ load domain access control
488#endif
489		mcr	p15, 0, r0, c1, c0, 0	@ load control register
490		mrc	p15, 0, r0, c1, c0, 0	@ and read it back
491		mov	r0, #0
492		mcr	p15, 0, r0, c7, c5, 4	@ ISB
493		mov	pc, r12
494
495__fa526_cache_on:
496		mov	r12, lr
497		bl	__setup_mmu
498		mov	r0, #0
499		mcr	p15, 0, r0, c7, c7, 0	@ Invalidate whole cache
500		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
501		mcr	p15, 0, r0, c8, c7, 0	@ flush UTLB
502		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
503		orr	r0, r0, #0x1000		@ I-cache enable
504		bl	__common_mmu_cache_on
505		mov	r0, #0
506		mcr	p15, 0, r0, c8, c7, 0	@ flush UTLB
507		mov	pc, r12
508
509__arm6_mmu_cache_on:
510		mov	r12, lr
511		bl	__setup_mmu
512		mov	r0, #0
513		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
514		mcr	p15, 0, r0, c5, c0, 0	@ invalidate whole TLB v3
515		mov	r0, #0x30
516		bl	__common_mmu_cache_on
517		mov	r0, #0
518		mcr	p15, 0, r0, c5, c0, 0	@ invalidate whole TLB v3
519		mov	pc, r12
520
521__common_mmu_cache_on:
522#ifndef CONFIG_THUMB2_KERNEL
523#ifndef DEBUG
524		orr	r0, r0, #0x000d		@ Write buffer, mmu
525#endif
526		mov	r1, #-1
527		mcr	p15, 0, r3, c2, c0, 0	@ load page table pointer
528		mcr	p15, 0, r1, c3, c0, 0	@ load domain access control
529		b	1f
530		.align	5			@ cache line aligned
5311:		mcr	p15, 0, r0, c1, c0, 0	@ load control register
532		mrc	p15, 0, r0, c1, c0, 0	@ and read it back to
533		sub	pc, lr, r0, lsr #32	@ properly flush pipeline
534#endif
535
536/*
537 * All code following this line is relocatable.  It is relocated by
538 * the above code to the end of the decompressed kernel image and
539 * executed there.  During this time, we have no stacks.
540 *
541 * r0     = decompressed kernel length
542 * r1-r3  = unused
543 * r4     = kernel execution address
544 * r5     = decompressed kernel start
545 * r7     = architecture ID
546 * r8     = atags pointer
547 * r9-r12,r14 = corrupted
548 */
549		.align	5
550reloc_start:	add	r9, r5, r0
551		sub	r9, r9, #128		@ do not copy the stack
552		debug_reloc_start
553		mov	r1, r4
5541:
555		.rept	4
556		ldmia	r5!, {r0, r2, r3, r10 - r12, r14}	@ relocate kernel
557		stmia	r1!, {r0, r2, r3, r10 - r12, r14}
558		.endr
559
560		cmp	r5, r9
561		blo	1b
562		mov	sp, r1
563		add	sp, sp, #128		@ relocate the stack
564		debug_reloc_end
565
566call_kernel:	bl	cache_clean_flush
567		bl	cache_off
568		mov	r0, #0			@ must be zero
569		mov	r1, r7			@ restore architecture number
570		mov	r2, r8			@ restore atags pointer
571		mov	pc, r4			@ call kernel
572
573/*
574 * Here follow the relocatable cache support functions for the
575 * various processors.  This is a generic hook for locating an
576 * entry and jumping to an instruction at the specified offset
577 * from the start of the block.  Please note this is all position
578 * independent code.
579 *
580 *  r1  = corrupted
581 *  r2  = corrupted
582 *  r3  = block offset
583 *  r9  = corrupted
584 *  r12 = corrupted
585 */
586
587call_cache_fn:	adr	r12, proc_types
588#ifdef CONFIG_CPU_CP15
589		mrc	p15, 0, r9, c0, c0	@ get processor ID
590#else
591		ldr	r9, =CONFIG_PROCESSOR_ID
592#endif
5931:		ldr	r1, [r12, #0]		@ get value
594		ldr	r2, [r12, #4]		@ get mask
595		eor	r1, r1, r9		@ (real ^ match)
596		tst	r1, r2			@       & mask
597 ARM(		addeq	pc, r12, r3		) @ call cache function
598 THUMB(		addeq	r12, r3			)
599 THUMB(		moveq	pc, r12			) @ call cache function
600		add	r12, r12, #4*5
601		b	1b
602
603/*
604 * Table for cache operations.  This is basically:
605 *   - CPU ID match
606 *   - CPU ID mask
607 *   - 'cache on' method instruction
608 *   - 'cache off' method instruction
609 *   - 'cache flush' method instruction
610 *
611 * We match an entry using: ((real_id ^ match) & mask) == 0
612 *
613 * Writethrough caches generally only need 'on' and 'off'
614 * methods.  Writeback caches _must_ have the flush method
615 * defined.
616 */
617		.align	2
618		.type	proc_types,#object
619proc_types:
620		.word	0x41560600		@ ARM6/610
621		.word	0xffffffe0
622		W(b)	__arm6_mmu_cache_off	@ works, but slow
623		W(b)	__arm6_mmu_cache_off
624		mov	pc, lr
625 THUMB(		nop				)
626@		b	__arm6_mmu_cache_on		@ untested
627@		b	__arm6_mmu_cache_off
628@		b	__armv3_mmu_cache_flush
629
630		.word	0x00000000		@ old ARM ID
631		.word	0x0000f000
632		mov	pc, lr
633 THUMB(		nop				)
634		mov	pc, lr
635 THUMB(		nop				)
636		mov	pc, lr
637 THUMB(		nop				)
638
639		.word	0x41007000		@ ARM7/710
640		.word	0xfff8fe00
641		W(b)	__arm7_mmu_cache_off
642		W(b)	__arm7_mmu_cache_off
643		mov	pc, lr
644 THUMB(		nop				)
645
646		.word	0x41807200		@ ARM720T (writethrough)
647		.word	0xffffff00
648		W(b)	__armv4_mmu_cache_on
649		W(b)	__armv4_mmu_cache_off
650		mov	pc, lr
651 THUMB(		nop				)
652
653		.word	0x41007400		@ ARM74x
654		.word	0xff00ff00
655		W(b)	__armv3_mpu_cache_on
656		W(b)	__armv3_mpu_cache_off
657		W(b)	__armv3_mpu_cache_flush
658
659		.word	0x41009400		@ ARM94x
660		.word	0xff00ff00
661		W(b)	__armv4_mpu_cache_on
662		W(b)	__armv4_mpu_cache_off
663		W(b)	__armv4_mpu_cache_flush
664
665		.word	0x00007000		@ ARM7 IDs
666		.word	0x0000f000
667		mov	pc, lr
668 THUMB(		nop				)
669		mov	pc, lr
670 THUMB(		nop				)
671		mov	pc, lr
672 THUMB(		nop				)
673
674		@ Everything from here on will be the new ID system.
675
676		.word	0x4401a100		@ sa110 / sa1100
677		.word	0xffffffe0
678		W(b)	__armv4_mmu_cache_on
679		W(b)	__armv4_mmu_cache_off
680		W(b)	__armv4_mmu_cache_flush
681
682		.word	0x6901b110		@ sa1110
683		.word	0xfffffff0
684		W(b)	__armv4_mmu_cache_on
685		W(b)	__armv4_mmu_cache_off
686		W(b)	__armv4_mmu_cache_flush
687
688		.word	0x56056930
689		.word	0xff0ffff0		@ PXA935
690		W(b)	__armv4_mmu_cache_on
691		W(b)	__armv4_mmu_cache_off
692		W(b)	__armv4_mmu_cache_flush
693
694		.word	0x56158000		@ PXA168
695		.word	0xfffff000
696		W(b)	__armv4_mmu_cache_on
697		W(b)	__armv4_mmu_cache_off
698		W(b)	__armv5tej_mmu_cache_flush
699
700		.word	0x56056930
701		.word	0xff0ffff0		@ PXA935
702		W(b)	__armv4_mmu_cache_on
703		W(b)	__armv4_mmu_cache_off
704		W(b)	__armv4_mmu_cache_flush
705
706		.word	0x56050000		@ Feroceon
707		.word	0xff0f0000
708		W(b)	__armv4_mmu_cache_on
709		W(b)	__armv4_mmu_cache_off
710		W(b)	__armv5tej_mmu_cache_flush
711
712#ifdef CONFIG_CPU_FEROCEON_OLD_ID
713		/* this conflicts with the standard ARMv5TE entry */
714		.long	0x41009260		@ Old Feroceon
715		.long	0xff00fff0
716		b	__armv4_mmu_cache_on
717		b	__armv4_mmu_cache_off
718		b	__armv5tej_mmu_cache_flush
719#endif
720
721		.word	0x66015261		@ FA526
722		.word	0xff01fff1
723		W(b)	__fa526_cache_on
724		W(b)	__armv4_mmu_cache_off
725		W(b)	__fa526_cache_flush
726
727		@ These match on the architecture ID
728
729		.word	0x00020000		@ ARMv4T
730		.word	0x000f0000
731		W(b)	__armv4_mmu_cache_on
732		W(b)	__armv4_mmu_cache_off
733		W(b)	__armv4_mmu_cache_flush
734
735		.word	0x00050000		@ ARMv5TE
736		.word	0x000f0000
737		W(b)	__armv4_mmu_cache_on
738		W(b)	__armv4_mmu_cache_off
739		W(b)	__armv4_mmu_cache_flush
740
741		.word	0x00060000		@ ARMv5TEJ
742		.word	0x000f0000
743		W(b)	__armv4_mmu_cache_on
744		W(b)	__armv4_mmu_cache_off
745		W(b)	__armv5tej_mmu_cache_flush
746
747		.word	0x0007b000		@ ARMv6
748		.word	0x000ff000
749		W(b)	__armv4_mmu_cache_on
750		W(b)	__armv4_mmu_cache_off
751		W(b)	__armv6_mmu_cache_flush
752
753		.word	0x560f5810		@ Marvell PJ4 ARMv6
754		.word	0xff0ffff0
755		W(b)	__armv4_mmu_cache_on
756		W(b)	__armv4_mmu_cache_off
757		W(b)	__armv6_mmu_cache_flush
758
759		.word	0x000f0000		@ new CPU Id
760		.word	0x000f0000
761		W(b)	__armv7_mmu_cache_on
762		W(b)	__armv7_mmu_cache_off
763		W(b)	__armv7_mmu_cache_flush
764
765		.word	0			@ unrecognised type
766		.word	0
767		mov	pc, lr
768 THUMB(		nop				)
769		mov	pc, lr
770 THUMB(		nop				)
771		mov	pc, lr
772 THUMB(		nop				)
773
774		.size	proc_types, . - proc_types
775
776/*
777 * Turn off the Cache and MMU.  ARMv3 does not support
778 * reading the control register, but ARMv4 does.
779 *
780 * On exit, r0, r1, r2, r3, r9, r12 corrupted
781 * This routine must preserve: r4, r6, r7
782 */
783		.align	5
784cache_off:	mov	r3, #12			@ cache_off function
785		b	call_cache_fn
786
787__armv4_mpu_cache_off:
788		mrc	p15, 0, r0, c1, c0
789		bic	r0, r0, #0x000d
790		mcr	p15, 0, r0, c1, c0	@ turn MPU and cache off
791		mov	r0, #0
792		mcr	p15, 0, r0, c7, c10, 4	@ drain write buffer
793		mcr	p15, 0, r0, c7, c6, 0	@ flush D-Cache
794		mcr	p15, 0, r0, c7, c5, 0	@ flush I-Cache
795		mov	pc, lr
796
797__armv3_mpu_cache_off:
798		mrc	p15, 0, r0, c1, c0
799		bic	r0, r0, #0x000d
800		mcr	p15, 0, r0, c1, c0, 0	@ turn MPU and cache off
801		mov	r0, #0
802		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
803		mov	pc, lr
804
805__armv4_mmu_cache_off:
806#ifdef CONFIG_MMU
807		mrc	p15, 0, r0, c1, c0
808		bic	r0, r0, #0x000d
809		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
810		mov	r0, #0
811		mcr	p15, 0, r0, c7, c7	@ invalidate whole cache v4
812		mcr	p15, 0, r0, c8, c7	@ invalidate whole TLB v4
813#endif
814		mov	pc, lr
815
816__armv7_mmu_cache_off:
817		mrc	p15, 0, r0, c1, c0
818#ifdef CONFIG_MMU
819		bic	r0, r0, #0x000d
820#else
821		bic	r0, r0, #0x000c
822#endif
823		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
824		mov	r12, lr
825		bl	__armv7_mmu_cache_flush
826		mov	r0, #0
827#ifdef CONFIG_MMU
828		mcr	p15, 0, r0, c8, c7, 0	@ invalidate whole TLB
829#endif
830		mcr	p15, 0, r0, c7, c5, 6	@ invalidate BTC
831		mcr	p15, 0, r0, c7, c10, 4	@ DSB
832		mcr	p15, 0, r0, c7, c5, 4	@ ISB
833		mov	pc, r12
834
835__arm6_mmu_cache_off:
836		mov	r0, #0x00000030		@ ARM6 control reg.
837		b	__armv3_mmu_cache_off
838
839__arm7_mmu_cache_off:
840		mov	r0, #0x00000070		@ ARM7 control reg.
841		b	__armv3_mmu_cache_off
842
843__armv3_mmu_cache_off:
844		mcr	p15, 0, r0, c1, c0, 0	@ turn MMU and cache off
845		mov	r0, #0
846		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
847		mcr	p15, 0, r0, c5, c0, 0	@ invalidate whole TLB v3
848		mov	pc, lr
849
850/*
851 * Clean and flush the cache to maintain consistency.
852 *
853 * On exit,
854 *  r1, r2, r3, r9, r11, r12 corrupted
855 * This routine must preserve:
856 *  r0, r4, r5, r6, r7
857 */
858		.align	5
859cache_clean_flush:
860		mov	r3, #16
861		b	call_cache_fn
862
863__armv4_mpu_cache_flush:
864		mov	r2, #1
865		mov	r3, #0
866		mcr	p15, 0, ip, c7, c6, 0	@ invalidate D cache
867		mov	r1, #7 << 5		@ 8 segments
8681:		orr	r3, r1, #63 << 26	@ 64 entries
8692:		mcr	p15, 0, r3, c7, c14, 2	@ clean & invalidate D index
870		subs	r3, r3, #1 << 26
871		bcs	2b			@ entries 63 to 0
872		subs 	r1, r1, #1 << 5
873		bcs	1b			@ segments 7 to 0
874
875		teq	r2, #0
876		mcrne	p15, 0, ip, c7, c5, 0	@ invalidate I cache
877		mcr	p15, 0, ip, c7, c10, 4	@ drain WB
878		mov	pc, lr
879
880__fa526_cache_flush:
881		mov	r1, #0
882		mcr	p15, 0, r1, c7, c14, 0	@ clean and invalidate D cache
883		mcr	p15, 0, r1, c7, c5, 0	@ flush I cache
884		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
885		mov	pc, lr
886
887__armv6_mmu_cache_flush:
888		mov	r1, #0
889		mcr	p15, 0, r1, c7, c14, 0	@ clean+invalidate D
890		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I+BTB
891		mcr	p15, 0, r1, c7, c15, 0	@ clean+invalidate unified
892		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
893		mov	pc, lr
894
895__armv7_mmu_cache_flush:
896		mrc	p15, 0, r10, c0, c1, 5	@ read ID_MMFR1
897		tst	r10, #0xf << 16		@ hierarchical cache (ARMv7)
898		mov	r10, #0
899		beq	hierarchical
900		mcr	p15, 0, r10, c7, c14, 0	@ clean+invalidate D
901		b	iflush
902hierarchical:
903		mcr	p15, 0, r10, c7, c10, 5	@ DMB
904		stmfd	sp!, {r0-r7, r9-r11}
905		mrc	p15, 1, r0, c0, c0, 1	@ read clidr
906		ands	r3, r0, #0x7000000	@ extract loc from clidr
907		mov	r3, r3, lsr #23		@ left align loc bit field
908		beq	finished		@ if loc is 0, then no need to clean
909		mov	r10, #0			@ start clean at cache level 0
910loop1:
911		add	r2, r10, r10, lsr #1	@ work out 3x current cache level
912		mov	r1, r0, lsr r2		@ extract cache type bits from clidr
913		and	r1, r1, #7		@ mask of the bits for current cache only
914		cmp	r1, #2			@ see what cache we have at this level
915		blt	skip			@ skip if no cache, or just i-cache
916		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
917		mcr	p15, 0, r10, c7, c5, 4	@ isb to sych the new cssr&csidr
918		mrc	p15, 1, r1, c0, c0, 0	@ read the new csidr
919		and	r2, r1, #7		@ extract the length of the cache lines
920		add	r2, r2, #4		@ add 4 (line length offset)
921		ldr	r4, =0x3ff
922		ands	r4, r4, r1, lsr #3	@ find maximum number on the way size
923		clz	r5, r4			@ find bit position of way size increment
924		ldr	r7, =0x7fff
925		ands	r7, r7, r1, lsr #13	@ extract max number of the index size
926loop2:
927		mov	r9, r4			@ create working copy of max way size
928loop3:
929 ARM(		orr	r11, r10, r9, lsl r5	) @ factor way and cache number into r11
930 ARM(		orr	r11, r11, r7, lsl r2	) @ factor index number into r11
931 THUMB(		lsl	r6, r9, r5		)
932 THUMB(		orr	r11, r10, r6		) @ factor way and cache number into r11
933 THUMB(		lsl	r6, r7, r2		)
934 THUMB(		orr	r11, r11, r6		) @ factor index number into r11
935		mcr	p15, 0, r11, c7, c14, 2	@ clean & invalidate by set/way
936		subs	r9, r9, #1		@ decrement the way
937		bge	loop3
938		subs	r7, r7, #1		@ decrement the index
939		bge	loop2
940skip:
941		add	r10, r10, #2		@ increment cache number
942		cmp	r3, r10
943		bgt	loop1
944finished:
945		ldmfd	sp!, {r0-r7, r9-r11}
946		mov	r10, #0			@ swith back to cache level 0
947		mcr	p15, 2, r10, c0, c0, 0	@ select current cache level in cssr
948iflush:
949		mcr	p15, 0, r10, c7, c10, 4	@ DSB
950		mcr	p15, 0, r10, c7, c5, 0	@ invalidate I+BTB
951		mcr	p15, 0, r10, c7, c10, 4	@ DSB
952		mcr	p15, 0, r10, c7, c5, 4	@ ISB
953		mov	pc, lr
954
955__armv5tej_mmu_cache_flush:
9561:		mrc	p15, 0, r15, c7, c14, 3	@ test,clean,invalidate D cache
957		bne	1b
958		mcr	p15, 0, r0, c7, c5, 0	@ flush I cache
959		mcr	p15, 0, r0, c7, c10, 4	@ drain WB
960		mov	pc, lr
961
962__armv4_mmu_cache_flush:
963		mov	r2, #64*1024		@ default: 32K dcache size (*2)
964		mov	r11, #32		@ default: 32 byte line size
965		mrc	p15, 0, r3, c0, c0, 1	@ read cache type
966		teq	r3, r9			@ cache ID register present?
967		beq	no_cache_id
968		mov	r1, r3, lsr #18
969		and	r1, r1, #7
970		mov	r2, #1024
971		mov	r2, r2, lsl r1		@ base dcache size *2
972		tst	r3, #1 << 14		@ test M bit
973		addne	r2, r2, r2, lsr #1	@ +1/2 size if M == 1
974		mov	r3, r3, lsr #12
975		and	r3, r3, #3
976		mov	r11, #8
977		mov	r11, r11, lsl r3	@ cache line size in bytes
978no_cache_id:
979		mov	r1, pc
980		bic	r1, r1, #63		@ align to longest cache line
981		add	r2, r1, r2
9821:
983 ARM(		ldr	r3, [r1], r11		) @ s/w flush D cache
984 THUMB(		ldr     r3, [r1]		) @ s/w flush D cache
985 THUMB(		add     r1, r1, r11		)
986		teq	r1, r2
987		bne	1b
988
989		mcr	p15, 0, r1, c7, c5, 0	@ flush I cache
990		mcr	p15, 0, r1, c7, c6, 0	@ flush D cache
991		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
992		mov	pc, lr
993
994__armv3_mmu_cache_flush:
995__armv3_mpu_cache_flush:
996		mov	r1, #0
997		mcr	p15, 0, r0, c7, c0, 0	@ invalidate whole cache v3
998		mov	pc, lr
999
1000/*
1001 * Various debugging routines for printing hex characters and
1002 * memory, which again must be relocatable.
1003 */
1004#ifdef DEBUG
1005		.align	2
1006		.type	phexbuf,#object
1007phexbuf:	.space	12
1008		.size	phexbuf, . - phexbuf
1009
1010phex:		adr	r3, phexbuf
1011		mov	r2, #0
1012		strb	r2, [r3, r1]
10131:		subs	r1, r1, #1
1014		movmi	r0, r3
1015		bmi	puts
1016		and	r2, r0, #15
1017		mov	r0, r0, lsr #4
1018		cmp	r2, #10
1019		addge	r2, r2, #7
1020		add	r2, r2, #'0'
1021		strb	r2, [r3, r1]
1022		b	1b
1023
1024puts:		loadsp	r3, r1
10251:		ldrb	r2, [r0], #1
1026		teq	r2, #0
1027		moveq	pc, lr
10282:		writeb	r2, r3
1029		mov	r1, #0x00020000
10303:		subs	r1, r1, #1
1031		bne	3b
1032		teq	r2, #'\n'
1033		moveq	r2, #'\r'
1034		beq	2b
1035		teq	r0, #0
1036		bne	1b
1037		mov	pc, lr
1038putc:
1039		mov	r2, r0
1040		mov	r0, #0
1041		loadsp	r3, r1
1042		b	2b
1043
1044memdump:	mov	r12, r0
1045		mov	r10, lr
1046		mov	r11, #0
10472:		mov	r0, r11, lsl #2
1048		add	r0, r0, r12
1049		mov	r1, #8
1050		bl	phex
1051		mov	r0, #':'
1052		bl	putc
10531:		mov	r0, #' '
1054		bl	putc
1055		ldr	r0, [r12, r11, lsl #2]
1056		mov	r1, #8
1057		bl	phex
1058		and	r0, r11, #7
1059		teq	r0, #3
1060		moveq	r0, #' '
1061		bleq	putc
1062		and	r0, r11, #7
1063		add	r11, r11, #1
1064		teq	r0, #7
1065		bne	1b
1066		mov	r0, #'\n'
1067		bl	putc
1068		cmp	r11, #64
1069		blt	2b
1070		mov	pc, r10
1071#endif
1072
1073		.ltorg
1074reloc_end:
1075
1076		.align
1077		.section ".stack", "w"
1078user_stack:	.space	4096
1079