Merge branch 'master' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / board / nokia / rx51 / lowlevel_init.S
1 /*
2  * (C) Copyright 2011-2012
3  * Pali Rohár <pali.rohar@gmail.com>
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <config.h>
25
26 relocaddr:              /* address of this relocaddr section after coping */
27         .word .         /* address of section (calculated at compile time) */
28
29 startaddr:              /* address of u-boot after copying */
30         .word CONFIG_SYS_TEXT_BASE
31
32 kernaddr:               /* address of kernel after copying */
33         .word KERNEL_ADDRESS
34
35 kernsize:               /* maximal size of kernel image */
36         .word KERNEL_MAXSIZE
37
38 kernoffs:               /* offset of kernel image in loaded u-boot */
39         .word KERNEL_OFFSET
40
41 imagesize:              /* maximal size of image */
42         .word IMAGE_MAXSIZE
43
44 ih_magic:               /* IH_MAGIC in big endian from include/image.h */
45         .word 0x56190527
46
47 /*
48  * Routine: save_boot_params (called after reset from start.S)
49  * Description: Copy attached kernel to address KERNEL_ADDRESS
50  *              Copy u-boot to address CONFIG_SYS_TEXT_BASE
51  *              Return to copied u-boot address
52  */
53
54 .global save_boot_params
55 save_boot_params:
56
57
58 /* Copy valid attached kernel to address KERNEL_ADDRESS */
59
60 copy_kernel_start:
61         adr     r0, relocaddr   /* r0 - address of section relocaddr */
62         ldr     r1, relocaddr   /* r1 - address of relocaddr after relocation */
63         cmp     r0, r1
64
65         /* r4 - calculated offset */
66         subhi   r4, r0, r1
67         sublo   r4, r1, r0
68
69         /* r0 - start of kernel before */
70         ldr     r0, startaddr
71         addhi   r0, r0, r4
72         sublo   r0, r0, r4
73         ldr     r1, kernoffs
74         add     r0, r0, r1
75
76         /* r3 - start of kernel after */
77         ldr     r3, kernaddr
78
79         /* r2 - end of kernel after */
80         ldr     r1, kernsize
81         add     r2, r3, r1
82
83         /* r1 - end of kernel before */
84         add     r1, r0, r1
85
86         /* remove header in target kernel */
87         mov     r5, #0
88         str     r5, [r3]
89
90         /* check for valid kernel uImage */
91         ldr     r4, [r0]        /* r4 - 4 bytes header of kernel */
92         ldr     r5, ih_magic    /* r5 - IH_MAGIC */
93         cmp     r4, r5
94         bne     copy_kernel_end /* skip if invalid image */
95
96 copy_kernel_loop:
97         ldmdb   r1!, {r3 - r10}
98         stmdb   r2!, {r3 - r10}
99         cmp     r1, r0
100         bhi     copy_kernel_loop
101
102 copy_kernel_end:
103         mov     r5, #0
104         str     r5, [r0]        /* remove 4 bytes header of kernel */
105
106
107 /* Fix u-boot code */
108
109 fix_start:
110         adr     r0, relocaddr   /* r0 - address of section relocaddr */
111         ldr     r1, relocaddr   /* r1 - address of relocaddr after relocation */
112         cmp     r0, r1
113
114         beq     copy_uboot_end  /* skip if u-boot is on correct address */
115
116         /* r5 - calculated offset */
117         subhi   r5, r0, r1
118         sublo   r5, r1, r0
119
120         /* r6 - maximal u-boot size */
121         ldr     r6, imagesize
122
123         /* fix return address */
124         subhi   lr, lr, r5
125         addlo   lr, lr, r5
126
127         /* r1 - start of u-boot after */
128         ldr     r1, startaddr
129
130         /* r0 - start of u-boot before */
131         addhi   r0, r1, r5
132         sublo   r0, r1, r5
133
134         /* check if we need to move uboot copy code before calling it */
135         cmp     r5, r6
136         bhi     copy_uboot_start /* now coping u-boot code directly is safe */
137
138
139 copy_code_start:
140         /* r0 - start of u-boot before */
141         /* r1 - start of u-boot after */
142         /* r6 - maximal u-boot size */
143
144         /* r7 - maximal kernel size */
145         ldr     r7, kernsize
146
147         /* r4 - end of kernel before */
148         add     r4, r0, r6
149         add     r4, r4, r7
150
151         /* r5 - end of u-boot after */
152         ldr     r5, startaddr
153         add     r5, r5, r6
154
155         /* r2 - start of loop code after */
156         cmp     r4, r5          /* higher address (r4 or r5) */
157         movhs   r2, r4
158         movlo   r2, r5
159
160         /* r3 - end of loop code before */
161         adr     r3, end
162
163         /* r4 - end of loop code after */
164         adr     r4, copy_uboot_start
165         sub     r4, r3, r4
166         add     r4, r2, r4
167
168 copy_code_loop:
169         ldmdb   r3!, {r7 - r10}
170         stmdb   r4!, {r7 - r10}
171         cmp     r4, r2
172         bhi     copy_code_loop
173
174 copy_code_end:
175         mov     pc, r2
176
177
178 /* Copy u-boot to address CONFIG_SYS_TEXT_BASE */
179
180 copy_uboot_start:
181         /* r0 - start of u-boot before */
182         /* r1 - start of u-boot after */
183         /* r6 - maximal u-boot size */
184
185         /* r2 - end of u-boot after */
186         add     r2, r1, r6
187
188         /* condition for copying from left to right */
189         cmp     r0, r1
190         addlo   r1, r0, r6      /* r1 - end of u-boot before */
191         blo     copy_uboot_loop_right
192
193 copy_uboot_loop_left:
194         ldmia   r0!, {r3 - r10}
195         stmia   r1!, {r3 - r10}
196         cmp     r1, r2
197         blo     copy_uboot_loop_left
198         b       copy_uboot_end
199
200 copy_uboot_loop_right:
201         ldmdb   r1!, {r3 - r10}
202         stmdb   r2!, {r3 - r10}
203         cmp     r1, r0
204         bhi     copy_uboot_loop_right
205
206 copy_uboot_end:
207         bx      lr
208
209 end: