1#include <asm/ppc_asm.h>
2#include <asm/processor.h>
3#include <asm/cache.h>
4
5	.text
6
7/*
8 * Boot loader philosophy:
9 *      ROM loads us to some arbitrary location
10 *      Move the boot code to the link address (8M)
11 *      Call decompress_kernel()
12 *         Relocate the initrd, zimage and residual data to 8M
13 *         Decompress the kernel to 0
14 *      Jump to the kernel entry
15 *            -- Cort
16 */
17	.globl	start
18start:
19	bl	start_
20start_:
21
22        /* Enable, invalidate, Disable L1 icache/dcache */
23	li	r8, 0
24	ori	r8, r8, (HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
25	mfspr	r11,HID0
26	or	r11,r11,r8
27	andc	r10,r11,r8
28	isync
29	mtspr	HID0,r8
30	sync
31	isync
32	mtspr	HID0,r10
33	sync
34	isync
35
36	mr	r11,r3		/* Save pointer to residual/board data */
37
38/*
39 * Save the OF pointer to r25, but only if the entry point is in a sane
40 * location; if not we store 0.  If there is no entry point, or it is
41 * invalid, we establish the default MSR value immediately.  Otherwise,
42 * we defer doing that, to allow OF functions to be called, until we
43 * begin uncompressing the kernel.
44 */
45	lis	r3,0x0fff		/* r3 = 0x0fffffff */
46	ori	r3,r3,0xffff
47
48	subc	r3,r3,r5		/* r3 = (r5 <= r3) ? ~0 : 0 */
49	subfe	r3,r3,r3
50	nand	r3,r3,r3
51
52	and.	r5,r5,r3		/* r5 will be cleared if (r5 > r3) */
53	bne+	haveOF
54
55	li	r3,MSR_IP|MSR_FP	/* Not OF: set MSR immediately */
56  	mtmsr	r3
57	isync
58haveOF:
59	mr	r25,r5
60
61	/* compute the size of the whole image in words. */
62	lis	r4,start@h
63	ori	r4,r4,start@l
64	lis	r5,end@h
65	ori	r5,r5,end@l
66	addi	r5,r5,3		/* round up */
67	sub	r5,r5,r4	/* end - start */
68	srwi	r5,r5,2
69	mr	r7,r5		/* Save for later use. */
70
71	/* check if we need to relocate ourselves to the link addr or were
72	 * we loaded there to begin with -- Cort */
73	mflr	r3
74	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
75	mr	r8,r3
76	cmp	0,r3,r4
77	beq	start_ldr	/* If 0, we don't need to relocate */
78/*
79 * no matter where we're loaded, move ourselves to -Ttext address
80 */
81relocate:
82	mflr	r3		/* Compute code bias */
83	subi	r3,r3,4
84	mr	r8,r3
85	lis	r4,start@h
86	ori	r4,r4,start@l
87	mr	r5,r7		/* Get the # of longwords again */
88	mtctr	r5		/* Setup for loop */
89	li	r6,0
90	subi	r3,r3,4
91	subi	r4,r4,4
9200:	lwzu	r5,4(r3)
93	stwu	r5,4(r4)
94	xor	r6,r6,r5
95	bdnz	00b
96  	lis	r3,start_ldr@h
97	ori	r3,r3,start_ldr@l
98	mtlr	r3		/* Easiest way to do an absolute jump */
99	blr
100
101start_ldr:
102/* Some boards don't boot up with the I-cache enabled.  Do that
103 * now because the decompress runs much faster that way.
104 * As a side effect, we have to ensure the data cache is not enabled
105 * so we can access the serial I/O without trouble.
106 */
107	bl	flush_instruction_cache
108
109/* Clear all of BSS */
110	lis	r3,edata@h
111	ori	r3,r3,edata@l
112	lis	r4,end@h
113	ori	r4,r4,end@l
114	subi	r3,r3,4
115	subi	r4,r4,4
116	li	r0,0
11750:	stwu	r0,4(r3)
118	cmp	0,r3,r4
119	bne	50b
12090:	mr	r9,r1			/* Save old stack pointer (in case it matters) */
121	lis	r1,.stack@h
122	ori	r1,r1,.stack@l
123	addi	r1,r1,4096*2
124	subi	r1,r1,256
125	li	r2,0x000F		/* Mask pointer to 16-byte boundary */
126	andc	r1,r1,r2
127
128/* Run loader */
129	mr	r3,r8			/* Load point */
130	mr	r4,r7			/* Program length */
131	mr	r5,r6			/* Checksum */
132	mr	r6,r11			/* Residual data */
133	mr      r7,r25                  /* Validated OFW interface */
134	bl	decompress_kernel
135
136	/*
137	 * We have to do this after decompress_kernel, just to make
138	 * sure we don't wipe out things mapped in BATs which we need.
139	 * -- Tom
140	 */
141	li      r6,0
142	/* Test for a 601 */
143	mfspr	r9,PVR
144	srwi	r9,r9,16
145	cmpi	0,r9,1          /* 601 ? */
146	beq	.clearbats_601
147
148	/* Clear BATS */
149	mtspr   DBAT0U,r6
150	mtspr	DBAT0L,r6
151	mtspr   DBAT1U,r6
152	mtspr	DBAT1L,r6
153	mtspr   DBAT2U,r6
154	mtspr	DBAT2L,r6
155	mtspr   DBAT3U,r6
156	mtspr	DBAT3L,r6
157.clearbats_601:
158	mtspr   IBAT0U,r6
159	mtspr	IBAT0L,r6
160	mtspr   IBAT1U,r6
161	mtspr	IBAT1L,r6
162	mtspr	IBAT2U,r6
163	mtspr   IBAT2L,r6
164	mtspr   IBAT3U,r6
165	mtspr	IBAT3L,r6
166	isync
167	sync
168	sync
169
170	/* Set segment registers */
171	li	r6,16		/* load up segment register values */
172	mtctr	r6		/* for context 0 */
173	lis	r6,0x2000	/* Ku = 1, VSID = 0 */
174	li	r10,0
1753:	mtsrin	r6,r10
176	addi	r6,r6,0x111	/* increment VSID */
177	addis	r10,r10,0x1000	/* address of next segment */
178	bdnz	3b
179
180	/* tell kernel we're prep, by putting 0xdeadc0de at KERNELLOAD,
181	 * and tell the kernel to start on the 4th instruction since we
182	 * overwrite the first 3 sometimes (which are 'nop').
183	 */
184	li	r9,0xc
185	mtlr	r9
186	lis	r10,0xdeadc0de@h
187	ori	r10,r10,0xdeadc0de@l
188	li	r9,0
189	stw	r10,0(r9)
190	blr
191
192	.comm	.stack,4096*2,4
193