lantiq: bring back okli loader
[openwrt/openwrt.git] / target / linux / lantiq / image / lzma-loader / src / head.S
1 /*
2 * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
3 *
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * Some parts of this code was based on the OpenWrt specific lzma-loader
7 * for the BCM47xx and ADM5120 based boards:
8 * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org)
9 * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 */
15
16 #include <asm/asm.h>
17 #include <asm/regdef.h>
18 #include "cp0regdef.h"
19 #include "cacheops.h"
20 #include "config.h"
21
22 #define KSEG0 0x80000000
23
24 .macro ehb
25 sll zero, 3
26 .endm
27
28 .text
29
30 LEAF(startup)
31 .set noreorder
32 .set mips32
33
34 mtc0 zero, CP0_WATCHLO # clear watch registers
35 mtc0 zero, CP0_WATCHHI
36 mtc0 zero, CP0_CAUSE # clear before writing status register
37
38 mfc0 t0, CP0_STATUS
39 li t1, 0x1000001f
40 or t0, t1
41 xori t0, 0x1f
42 mtc0 t0, CP0_STATUS
43 ehb
44
45 /*
46 * Some bootloaders set the 'Kseg0 coherency algorithm' to
47 * 'Cacheable, noncoherent, write-through, no write allocate'
48 * and this cause performance issues. Let's go and change it to
49 * 'Cacheable, noncoherent, write-back, write allocate'
50 */
51 mfc0 t0, CP0_CONFIG
52 li t1, ~7 #~CONF_CM_CMASK
53 and t0, t1
54 ori t0, 3 #CONF_CM_CACHABLE_NONCOHERENT
55 mtc0 t0, CP0_CONFIG
56 nop
57
58 mtc0 zero, CP0_COUNT
59 mtc0 zero, CP0_COMPARE
60 ehb
61
62 la t0, __reloc_label # get linked address of label
63 bal __reloc_label # branch and link to label to
64 nop # get actual address
65 __reloc_label:
66 subu t0, ra, t0 # get reloc_delta
67
68 beqz t0, __reloc_done # if delta is 0 we are in the right place
69 nop
70
71 /* Copy our code to the right place */
72 la t1, _code_start # get linked address of _code_start
73 la t2, _code_end # get linked address of _code_end
74 addu t0, t0, t1 # calculate actual address of _code_start
75
76 __reloc_copy:
77 lw t3, 0(t0)
78 sw t3, 0(t1)
79 add t1, 4
80 blt t1, t2, __reloc_copy
81 add t0, 4
82
83 /* flush cache */
84 la t0, _code_start
85 la t1, _code_end
86
87 li t2, ~(CONFIG_CACHELINE_SIZE - 1)
88 and t0, t2
89 and t1, t2
90 li t2, CONFIG_CACHELINE_SIZE
91
92 b __flush_check
93 nop
94
95 __flush_line:
96 cache Hit_Writeback_Inv_D, 0(t0)
97 cache Hit_Invalidate_I, 0(t0)
98 add t0, t2
99
100 __flush_check:
101 bne t0, t1, __flush_line
102 nop
103
104 sync
105
106 __reloc_done:
107
108 /* clear bss */
109 la t0, _bss_start
110 la t1, _bss_end
111 b __bss_check
112 nop
113
114 __bss_fill:
115 sw zero, 0(t0)
116 addi t0, 4
117
118 __bss_check:
119 bne t0, t1, __bss_fill
120 nop
121
122 /* Setup new "C" stack */
123 la sp, _stack
124
125 /* reserve stack space for a0-a3 registers */
126 subu sp, 16
127
128 /* jump to the decompressor routine */
129 la t0, loader_main
130 jr t0
131 nop
132
133 .set reorder
134 END(startup)