summaryrefslogtreecommitdiff
path: root/board/nokia/rx51/lowlevel_init.S
diff options
context:
space:
mode:
Diffstat (limited to 'board/nokia/rx51/lowlevel_init.S')
-rw-r--r--board/nokia/rx51/lowlevel_init.S209
1 files changed, 209 insertions, 0 deletions
diff --git a/board/nokia/rx51/lowlevel_init.S b/board/nokia/rx51/lowlevel_init.S
new file mode 100644
index 0000000000..055b1038d1
--- /dev/null
+++ b/board/nokia/rx51/lowlevel_init.S
@@ -0,0 +1,209 @@
+/*
+ * (C) Copyright 2011-2012
+ * Pali Rohár <pali.rohar@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+relocaddr: /* address of this relocaddr section after coping */
+ .word . /* address of section (calculated at compile time) */
+
+startaddr: /* address of u-boot after copying */
+ .word CONFIG_SYS_TEXT_BASE
+
+kernaddr: /* address of kernel after copying */
+ .word KERNEL_ADDRESS
+
+kernsize: /* maximal size of kernel image */
+ .word KERNEL_MAXSIZE
+
+kernoffs: /* offset of kernel image in loaded u-boot */
+ .word KERNEL_OFFSET
+
+imagesize: /* maximal size of image */
+ .word IMAGE_MAXSIZE
+
+ih_magic: /* IH_MAGIC in big endian from include/image.h */
+ .word 0x56190527
+
+/*
+ * Routine: save_boot_params (called after reset from start.S)
+ * Description: Copy attached kernel to address KERNEL_ADDRESS
+ * Copy u-boot to address CONFIG_SYS_TEXT_BASE
+ * Return to copied u-boot address
+ */
+
+.global save_boot_params
+save_boot_params:
+
+
+/* Copy valid attached kernel to address KERNEL_ADDRESS */
+
+copy_kernel_start:
+ adr r0, relocaddr /* r0 - address of section relocaddr */
+ ldr r1, relocaddr /* r1 - address of relocaddr after relocation */
+ cmp r0, r1
+
+ /* r4 - calculated offset */
+ subhi r4, r0, r1
+ sublo r4, r1, r0
+
+ /* r0 - start of kernel before */
+ ldr r0, startaddr
+ addhi r0, r0, r4
+ sublo r0, r0, r4
+ ldr r1, kernoffs
+ add r0, r0, r1
+
+ /* r3 - start of kernel after */
+ ldr r3, kernaddr
+
+ /* r2 - end of kernel after */
+ ldr r1, kernsize
+ add r2, r3, r1
+
+ /* r1 - end of kernel before */
+ add r1, r0, r1
+
+ /* remove header in target kernel */
+ mov r5, #0
+ str r5, [r3]
+
+ /* check for valid kernel uImage */
+ ldr r4, [r0] /* r4 - 4 bytes header of kernel */
+ ldr r5, ih_magic /* r5 - IH_MAGIC */
+ cmp r4, r5
+ bne copy_kernel_end /* skip if invalid image */
+
+copy_kernel_loop:
+ ldmdb r1!, {r3 - r10}
+ stmdb r2!, {r3 - r10}
+ cmp r1, r0
+ bhi copy_kernel_loop
+
+copy_kernel_end:
+ mov r5, #0
+ str r5, [r0] /* remove 4 bytes header of kernel */
+
+
+/* Fix u-boot code */
+
+fix_start:
+ adr r0, relocaddr /* r0 - address of section relocaddr */
+ ldr r1, relocaddr /* r1 - address of relocaddr after relocation */
+ cmp r0, r1
+
+ beq copy_uboot_end /* skip if u-boot is on correct address */
+
+ /* r5 - calculated offset */
+ subhi r5, r0, r1
+ sublo r5, r1, r0
+
+ /* r6 - maximal u-boot size */
+ ldr r6, imagesize
+
+ /* fix return address */
+ subhi lr, lr, r5
+ addlo lr, lr, r5
+
+ /* r1 - start of u-boot after */
+ ldr r1, startaddr
+
+ /* r0 - start of u-boot before */
+ addhi r0, r1, r5
+ sublo r0, r1, r5
+
+ /* check if we need to move uboot copy code before calling it */
+ cmp r5, r6
+ bhi copy_uboot_start /* now coping u-boot code directly is safe */
+
+
+copy_code_start:
+ /* r0 - start of u-boot before */
+ /* r1 - start of u-boot after */
+ /* r6 - maximal u-boot size */
+
+ /* r7 - maximal kernel size */
+ ldr r7, kernsize
+
+ /* r4 - end of kernel before */
+ add r4, r0, r6
+ add r4, r4, r7
+
+ /* r5 - end of u-boot after */
+ ldr r5, startaddr
+ add r5, r5, r6
+
+ /* r2 - start of loop code after */
+ cmp r4, r5 /* higher address (r4 or r5) */
+ movhs r2, r4
+ movlo r2, r5
+
+ /* r3 - end of loop code before */
+ adr r3, end
+
+ /* r4 - end of loop code after */
+ adr r4, copy_uboot_start
+ sub r4, r3, r4
+ add r4, r2, r4
+
+copy_code_loop:
+ ldmdb r3!, {r7 - r10}
+ stmdb r4!, {r7 - r10}
+ cmp r4, r2
+ bhi copy_code_loop
+
+copy_code_end:
+ mov pc, r2
+
+
+/* Copy u-boot to address CONFIG_SYS_TEXT_BASE */
+
+copy_uboot_start:
+ /* r0 - start of u-boot before */
+ /* r1 - start of u-boot after */
+ /* r6 - maximal u-boot size */
+
+ /* r2 - end of u-boot after */
+ add r2, r1, r6
+
+ /* condition for copying from left to right */
+ cmp r0, r1
+ addlo r1, r0, r6 /* r1 - end of u-boot before */
+ blo copy_uboot_loop_right
+
+copy_uboot_loop_left:
+ ldmia r0!, {r3 - r10}
+ stmia r1!, {r3 - r10}
+ cmp r1, r2
+ blo copy_uboot_loop_left
+ b copy_uboot_end
+
+copy_uboot_loop_right:
+ ldmdb r1!, {r3 - r10}
+ stmdb r2!, {r3 - r10}
+ cmp r1, r0
+ bhi copy_uboot_loop_right
+
+copy_uboot_end:
+ bx lr
+
+end: