1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
/*
* Code that sets up the DRAM registers, calls the
* decompressor to unpack the piggybacked kernel, and jumps.
*
* Copyright (C) 1999 - 2003, Axis Communications AB
*/
#include <linux/config.h>
#define ASSEMBLER_MACROS_ONLY
#include <asm/arch/hwregs/asm/reg_map_asm.h>
#include <asm/arch/hwregs/asm/gio_defs_asm.h>
#include <asm/arch/hwregs/asm/config_defs_asm.h>
#define RAM_INIT_MAGIC 0x56902387
#define COMMAND_LINE_MAGIC 0x87109563
;; Exported symbols
.globl input_data
.text
start:
di
;; Start clocks for used blocks.
move.d REG_ADDR(config, regi_config, rw_clk_ctrl), $r1
move.d [$r1], $r0
or.d REG_STATE(config, rw_clk_ctrl, cpu, yes) | \
REG_STATE(config, rw_clk_ctrl, bif, yes) | \
REG_STATE(config, rw_clk_ctrl, fix_io, yes), $r0
move.d $r0, [$r1]
;; If booting from NAND flash we first have to copy some
;; data from NAND flash to internal RAM to get the code
;; that initializes the SDRAM. Lets copy 20 KB. This
;; code executes at 0x38010000 if booting from NAND and
;; we are guaranted that at least 0x200 bytes are good so
;; lets start from there. The first 8192 bytes in the nand
;; flash is spliced with zeroes and is thus 16384 bytes.
move.d 0x38010200, $r10
move.d 0x14200, $r11 ; Start offset in NAND flash 0x10200 + 16384
move.d 0x5000, $r12 ; Length of copy
;; Before this code the tools add a partitiontable so the PC
;; has an offset from the linked address.
offset1:
lapcq ., $r13 ; get PC
add.d first_copy_complete-offset1, $r13
#include "../../lib/nand_init.S"
first_copy_complete:
;; Initialze the DRAM registers.
cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized?
beq dram_init_finished
nop
#include "../../lib/dram_init.S"
dram_init_finished:
lapcq ., $r13 ; get PC
add.d second_copy_complete-dram_init_finished, $r13
move.d REG_ADDR(config, regi_config, r_bootsel), $r0
move.d [$r0], $r0
and.d REG_MASK(config, r_bootsel, boot_mode), $r0
cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
bne second_copy_complete ; No NAND boot
nop
;; Copy 2MB from NAND flash to SDRAM (at 2-4MB into the SDRAM)
move.d 0x40204000, $r10
move.d 0x8000, $r11
move.d 0x200000, $r12
ba copy_nand_to_ram
nop
second_copy_complete:
;; Initiate the PA port.
move.d CONFIG_ETRAX_DEF_GIO_PA_OUT, $r0
move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r1
move.d $r0, [$r1]
move.d CONFIG_ETRAX_DEF_GIO_PA_OE, $r0
move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r1
move.d $r0, [$r1]
;; Setup the stack to a suitably high address.
;; We assume 8 MB is the minimum DRAM and put
;; the SP at the top for now.
move.d 0x40800000, $sp
;; Figure out where the compressed piggyback image is
;; in the flash (since we wont try to copy it to DRAM
;; before unpacking). It is at _edata, but in flash.
;; Use (_edata - herami) as offset to the current PC.
move.d REG_ADDR(config, regi_config, r_bootsel), $r0
move.d [$r0], $r0
and.d REG_MASK(config, r_bootsel, boot_mode), $r0
cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0
beq hereami2
nop
hereami:
lapcq ., $r5 ; get PC
and.d 0x7fffffff, $r5 ; strip any non-cache bit
move.d $r5, $r0 ; save for later - flash address of 'herami'
add.d _edata, $r5
sub.d hereami, $r5 ; r5 = flash address of '_edata'
move.d hereami, $r1 ; destination
ba 2f
nop
hereami2:
lapcq ., $r5 ; get PC
and.d 0x00ffffff, $r5 ; strip any non-cache bit
move.d $r5, $r6
or.d 0x40200000, $r6
move.d $r6, $r0 ; save for later - flash address of 'herami'
add.d _edata, $r5
sub.d hereami2, $r5 ; r5 = flash address of '_edata'
add.d 0x40200000, $r5
move.d hereami2, $r1 ; destination
2:
;; Copy text+data to DRAM
move.d _edata, $r2 ; end destination
1: move.w [$r0+], $r3
move.w $r3, [$r1+]
cmp.d $r2, $r1
bcs 1b
nop
move.d input_data, $r0 ; for the decompressor
move.d $r5, [$r0] ; for the decompressor
;; Clear the decompressors BSS (between _edata and _end)
moveq 0, $r0
move.d _edata, $r1
move.d _end, $r2
1: move.w $r0, [$r1+]
cmp.d $r2, $r1
bcs 1b
nop
;; Save command line magic and address.
move.d _cmd_line_magic, $r12
move.d $r10, [$r12]
move.d _cmd_line_addr, $r12
move.d $r11, [$r12]
;; Do the decompression and save compressed size in _inptr
jsr decompress_kernel
nop
;; Restore command line magic and address.
move.d _cmd_line_magic, $r10
move.d [$r10], $r10
move.d _cmd_line_addr, $r11
move.d [$r11], $r11
;; Put start address of root partition in r9 so the kernel can use it
;; when mounting from flash
move.d input_data, $r0
move.d [$r0], $r9 ; flash address of compressed kernel
move.d inptr, $r0
add.d [$r0], $r9 ; size of compressed kernel
cmp.d 0x40200000, $r9
blo enter_kernel
nop
sub.d 0x40200000, $r9
add.d 0x4000, $r9
enter_kernel:
;; Enter the decompressed kernel
move.d RAM_INIT_MAGIC, $r8 ; Tell kernel that DRAM is initialized
jump 0x40004000 ; kernel is linked to this address
nop
.data
input_data:
.dword 0 ; used by the decompressor
_cmd_line_magic:
.dword 0
_cmd_line_addr:
.dword 0
is_nand_boot:
.dword 0
#include "../../lib/hw_settings.S"
|