xref: /OK3568_Linux_fs/u-boot/board/nokia/rx51/lowlevel_init.S (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun/*
2*4882a593Smuzhiyun * (C) Copyright 2011-2012
3*4882a593Smuzhiyun * Pali Rohár <pali.rohar@gmail.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun#include <config.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyunrelocaddr:		/* address of this relocaddr section after coping */
11*4882a593Smuzhiyun	.word .		/* address of section (calculated at compile time) */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyunstartaddr:		/* address of u-boot after copying */
14*4882a593Smuzhiyun	.word CONFIG_SYS_TEXT_BASE
15*4882a593Smuzhiyun
16*4882a593Smuzhiyunkernaddr:		/* address of kernel after copying */
17*4882a593Smuzhiyun	.word KERNEL_ADDRESS
18*4882a593Smuzhiyun
19*4882a593Smuzhiyunkernsize:		/* maximal size of kernel image */
20*4882a593Smuzhiyun	.word KERNEL_MAXSIZE
21*4882a593Smuzhiyun
22*4882a593Smuzhiyunkernoffs:		/* offset of kernel image in loaded u-boot */
23*4882a593Smuzhiyun	.word KERNEL_OFFSET
24*4882a593Smuzhiyun
25*4882a593Smuzhiyunimagesize:		/* maximal size of image */
26*4882a593Smuzhiyun	.word IMAGE_MAXSIZE
27*4882a593Smuzhiyun
28*4882a593Smuzhiyunih_magic:		/* IH_MAGIC in big endian from include/image.h */
29*4882a593Smuzhiyun	.word 0x56190527
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun/*
32*4882a593Smuzhiyun * Routine: save_boot_params (called after reset from start.S)
33*4882a593Smuzhiyun * Description: Copy attached kernel to address KERNEL_ADDRESS
34*4882a593Smuzhiyun *              Copy u-boot to address CONFIG_SYS_TEXT_BASE
35*4882a593Smuzhiyun *              Return to copied u-boot address
36*4882a593Smuzhiyun */
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun.global save_boot_params
39*4882a593Smuzhiyunsave_boot_params:
40*4882a593Smuzhiyun	/* Get return address */
41*4882a593Smuzhiyun	ldr	lr, =save_boot_params_ret
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun/* Copy valid attached kernel to address KERNEL_ADDRESS */
44*4882a593Smuzhiyun
45*4882a593Smuzhiyuncopy_kernel_start:
46*4882a593Smuzhiyun	adr	r0, relocaddr	/* r0 - address of section relocaddr */
47*4882a593Smuzhiyun	ldr	r1, relocaddr	/* r1 - address of relocaddr after relocation */
48*4882a593Smuzhiyun	cmp	r0, r1
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun	/* r4 - calculated offset */
51*4882a593Smuzhiyun	subhi	r4, r0, r1
52*4882a593Smuzhiyun	sublo	r4, r1, r0
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun	/* r0 - start of kernel before */
55*4882a593Smuzhiyun	ldr	r0, startaddr
56*4882a593Smuzhiyun	addhi	r0, r0, r4
57*4882a593Smuzhiyun	sublo	r0, r0, r4
58*4882a593Smuzhiyun	ldr	r1, kernoffs
59*4882a593Smuzhiyun	add	r0, r0, r1
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun	/* r3 - start of kernel after */
62*4882a593Smuzhiyun	ldr	r3, kernaddr
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun	/* r2 - end of kernel after */
65*4882a593Smuzhiyun	ldr	r1, kernsize
66*4882a593Smuzhiyun	add	r2, r3, r1
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun	/* r1 - end of kernel before */
69*4882a593Smuzhiyun	add	r1, r0, r1
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun	/* remove header in target kernel */
72*4882a593Smuzhiyun	mov	r5, #0
73*4882a593Smuzhiyun	str	r5, [r3]
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun	/* check for valid kernel uImage */
76*4882a593Smuzhiyun	ldr	r4, [r0]	/* r4 - 4 bytes header of kernel */
77*4882a593Smuzhiyun	ldr	r5, ih_magic	/* r5 - IH_MAGIC */
78*4882a593Smuzhiyun	cmp	r4, r5
79*4882a593Smuzhiyun	bne	copy_kernel_end	/* skip if invalid image */
80*4882a593Smuzhiyun
81*4882a593Smuzhiyuncopy_kernel_loop:
82*4882a593Smuzhiyun	ldmdb	r1!, {r3 - r10}
83*4882a593Smuzhiyun	stmdb	r2!, {r3 - r10}
84*4882a593Smuzhiyun	cmp	r1, r0
85*4882a593Smuzhiyun	bhi	copy_kernel_loop
86*4882a593Smuzhiyun
87*4882a593Smuzhiyuncopy_kernel_end:
88*4882a593Smuzhiyun	mov	r5, #0
89*4882a593Smuzhiyun	str	r5, [r0]	/* remove 4 bytes header of kernel */
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun/* Fix u-boot code */
93*4882a593Smuzhiyun
94*4882a593Smuzhiyunfix_start:
95*4882a593Smuzhiyun	adr	r0, relocaddr	/* r0 - address of section relocaddr */
96*4882a593Smuzhiyun	ldr	r1, relocaddr	/* r1 - address of relocaddr after relocation */
97*4882a593Smuzhiyun	cmp	r0, r1
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun	beq	copy_uboot_end	/* skip if u-boot is on correct address */
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun	/* r5 - calculated offset */
102*4882a593Smuzhiyun	subhi	r5, r0, r1
103*4882a593Smuzhiyun	sublo	r5, r1, r0
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun	/* r6 - maximal u-boot size */
106*4882a593Smuzhiyun	ldr	r6, imagesize
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun	/* r1 - start of u-boot after */
109*4882a593Smuzhiyun	ldr	r1, startaddr
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun	/* r0 - start of u-boot before */
112*4882a593Smuzhiyun	addhi	r0, r1, r5
113*4882a593Smuzhiyun	sublo	r0, r1, r5
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun	/* check if we need to move uboot copy code before calling it */
116*4882a593Smuzhiyun	cmp	r5, r6
117*4882a593Smuzhiyun	bhi	copy_uboot_start /* now coping u-boot code directly is safe */
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun
120*4882a593Smuzhiyuncopy_code_start:
121*4882a593Smuzhiyun	/* r0 - start of u-boot before */
122*4882a593Smuzhiyun	/* r1 - start of u-boot after */
123*4882a593Smuzhiyun	/* r6 - maximal u-boot size */
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun	/* r7 - maximal kernel size */
126*4882a593Smuzhiyun	ldr	r7, kernsize
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun	/* r4 - end of kernel before */
129*4882a593Smuzhiyun	add	r4, r0, r6
130*4882a593Smuzhiyun	add	r4, r4, r7
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun	/* r5 - end of u-boot after */
133*4882a593Smuzhiyun	ldr	r5, startaddr
134*4882a593Smuzhiyun	add	r5, r5, r6
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun	/* r2 - start of loop code after */
137*4882a593Smuzhiyun	cmp	r4, r5		/* higher address (r4 or r5) */
138*4882a593Smuzhiyun	movhs	r2, r4
139*4882a593Smuzhiyun	movlo	r2, r5
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun	/* r3 - end of loop code before */
142*4882a593Smuzhiyun	adr	r3, end
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun	/* r4 - end of loop code after */
145*4882a593Smuzhiyun	adr	r4, copy_uboot_start
146*4882a593Smuzhiyun	sub	r4, r3, r4
147*4882a593Smuzhiyun	add	r4, r2, r4
148*4882a593Smuzhiyun
149*4882a593Smuzhiyuncopy_code_loop:
150*4882a593Smuzhiyun	ldmdb	r3!, {r7 - r10}
151*4882a593Smuzhiyun	stmdb	r4!, {r7 - r10}
152*4882a593Smuzhiyun	cmp	r4, r2
153*4882a593Smuzhiyun	bhi	copy_code_loop
154*4882a593Smuzhiyun
155*4882a593Smuzhiyuncopy_code_end:
156*4882a593Smuzhiyun	mov	pc, r2
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun/* Copy u-boot to address CONFIG_SYS_TEXT_BASE */
160*4882a593Smuzhiyun
161*4882a593Smuzhiyuncopy_uboot_start:
162*4882a593Smuzhiyun	/* r0 - start of u-boot before */
163*4882a593Smuzhiyun	/* r1 - start of u-boot after */
164*4882a593Smuzhiyun	/* r6 - maximal u-boot size */
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun	/* r2 - end of u-boot after */
167*4882a593Smuzhiyun	add	r2, r1, r6
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun	/* condition for copying from left to right */
170*4882a593Smuzhiyun	cmp	r0, r1
171*4882a593Smuzhiyun	addlo	r1, r0, r6	/* r1 - end of u-boot before */
172*4882a593Smuzhiyun	blo	copy_uboot_loop_right
173*4882a593Smuzhiyun
174*4882a593Smuzhiyuncopy_uboot_loop_left:
175*4882a593Smuzhiyun	ldmia	r0!, {r3 - r10}
176*4882a593Smuzhiyun	stmia	r1!, {r3 - r10}
177*4882a593Smuzhiyun	cmp	r1, r2
178*4882a593Smuzhiyun	blo	copy_uboot_loop_left
179*4882a593Smuzhiyun	b	copy_uboot_end
180*4882a593Smuzhiyun
181*4882a593Smuzhiyuncopy_uboot_loop_right:
182*4882a593Smuzhiyun	ldmdb	r1!, {r3 - r10}
183*4882a593Smuzhiyun	stmdb	r2!, {r3 - r10}
184*4882a593Smuzhiyun	cmp	r1, r0
185*4882a593Smuzhiyun	bhi	copy_uboot_loop_right
186*4882a593Smuzhiyun
187*4882a593Smuzhiyuncopy_uboot_end:
188*4882a593Smuzhiyun	bx	lr
189*4882a593Smuzhiyun
190*4882a593Smuzhiyunend:
191