]>
Commit | Line | Data |
---|---|---|
7b64fef3 WD |
1 | /* |
2 | * Copyright (C) 2004-2006 Atmel Corporation | |
3 | * | |
4 | * See file CREDITS for list of people who contributed to this | |
5 | * project. | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License as | |
9 | * published by the Free Software Foundation; either version 2 of | |
10 | * the License, or (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
20 | * MA 02111-1307 USA | |
21 | */ | |
22 | #include <common.h> | |
23 | #include <command.h> | |
24 | #include <malloc.h> | |
25 | #include <devices.h> | |
26 | #include <version.h> | |
27 | #include <net.h> | |
28 | ||
29 | #include <asm/initcalls.h> | |
30 | #include <asm/sections.h> | |
31 | ||
32 | #ifndef CONFIG_IDENT_STRING | |
33 | #define CONFIG_IDENT_STRING "" | |
34 | #endif | |
35 | ||
36 | DECLARE_GLOBAL_DATA_PTR; | |
37 | ||
38 | const char version_string[] = | |
39 | U_BOOT_VERSION " (" __DATE__ " - " __TIME__ ") " CONFIG_IDENT_STRING; | |
40 | ||
41 | unsigned long monitor_flash_len; | |
42 | ||
43 | /* | |
44 | * Begin and end of memory area for malloc(), and current "brk" | |
45 | */ | |
46 | static unsigned long mem_malloc_start = 0; | |
47 | static unsigned long mem_malloc_end = 0; | |
48 | static unsigned long mem_malloc_brk = 0; | |
49 | ||
1f4f2121 | 50 | /* The malloc area is right below the monitor image in RAM */ |
7b64fef3 WD |
51 | static void mem_malloc_init(void) |
52 | { | |
1f4f2121 HS |
53 | unsigned long monitor_addr; |
54 | ||
55 | monitor_addr = CFG_MONITOR_BASE + gd->reloc_off; | |
56 | mem_malloc_end = monitor_addr; | |
57 | mem_malloc_start = mem_malloc_end - CFG_MALLOC_LEN; | |
7b64fef3 WD |
58 | mem_malloc_brk = mem_malloc_start; |
59 | ||
60 | printf("malloc: Using memory from 0x%08lx to 0x%08lx\n", | |
61 | mem_malloc_start, mem_malloc_end); | |
62 | ||
63 | memset ((void *)mem_malloc_start, 0, | |
64 | mem_malloc_end - mem_malloc_start); | |
65 | } | |
66 | ||
67 | void *sbrk(ptrdiff_t increment) | |
68 | { | |
69 | unsigned long old = mem_malloc_brk; | |
70 | unsigned long new = old + increment; | |
71 | ||
72 | if ((new < mem_malloc_start) || (new > mem_malloc_end)) | |
73 | return NULL; | |
74 | ||
75 | mem_malloc_brk = new; | |
76 | return ((void *)old); | |
77 | } | |
78 | ||
d5acb95b HS |
79 | #ifdef CFG_DMA_ALLOC_LEN |
80 | #include <asm/cacheflush.h> | |
81 | #include <asm/io.h> | |
82 | ||
83 | static unsigned long dma_alloc_start; | |
84 | static unsigned long dma_alloc_end; | |
85 | static unsigned long dma_alloc_brk; | |
86 | ||
87 | static void dma_alloc_init(void) | |
88 | { | |
89 | unsigned long monitor_addr; | |
90 | ||
91 | monitor_addr = CFG_MONITOR_BASE + gd->reloc_off; | |
92 | dma_alloc_end = monitor_addr - CFG_MALLOC_LEN; | |
93 | dma_alloc_start = dma_alloc_end - CFG_DMA_ALLOC_LEN; | |
94 | dma_alloc_brk = dma_alloc_start; | |
95 | ||
96 | printf("DMA: Using memory from 0x%08lx to 0x%08lx\n", | |
97 | dma_alloc_start, dma_alloc_end); | |
98 | ||
99 | dcache_invalidate_range(cached(dma_alloc_start), | |
100 | dma_alloc_end - dma_alloc_start); | |
101 | } | |
102 | ||
103 | void *dma_alloc_coherent(size_t len, unsigned long *handle) | |
104 | { | |
105 | unsigned long paddr = dma_alloc_brk; | |
106 | ||
107 | if (dma_alloc_brk + len > dma_alloc_end) | |
108 | return NULL; | |
109 | ||
110 | dma_alloc_brk = ((paddr + len + CFG_DCACHE_LINESZ - 1) | |
111 | & ~(CFG_DCACHE_LINESZ - 1)); | |
112 | ||
113 | *handle = paddr; | |
114 | return uncached(paddr); | |
115 | } | |
116 | #else | |
117 | static inline void dma_alloc_init(void) | |
118 | { | |
119 | ||
120 | } | |
121 | #endif | |
122 | ||
7b64fef3 WD |
123 | static int init_baudrate(void) |
124 | { | |
125 | char tmp[64]; | |
126 | int i; | |
127 | ||
128 | i = getenv_r("baudrate", tmp, sizeof(tmp)); | |
129 | if (i > 0) { | |
130 | gd->baudrate = simple_strtoul(tmp, NULL, 10); | |
131 | } else { | |
132 | gd->baudrate = CONFIG_BAUDRATE; | |
133 | } | |
134 | return 0; | |
135 | } | |
136 | ||
137 | ||
138 | static int display_banner (void) | |
139 | { | |
140 | printf ("\n\n%s\n\n", version_string); | |
141 | printf ("U-Boot code: %p -> %p data: %p -> %p\n", | |
142 | _text, _etext, _data, _end); | |
143 | return 0; | |
144 | } | |
145 | ||
146 | void hang(void) | |
147 | { | |
148 | for (;;) ; | |
149 | } | |
150 | ||
151 | static int display_dram_config (void) | |
152 | { | |
153 | int i; | |
154 | ||
155 | puts ("DRAM Configuration:\n"); | |
156 | ||
157 | for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { | |
158 | printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); | |
159 | print_size (gd->bd->bi_dram[i].size, "\n"); | |
160 | } | |
161 | ||
162 | return 0; | |
163 | } | |
164 | ||
165 | static void display_flash_config (void) | |
166 | { | |
167 | puts ("Flash: "); | |
168 | print_size(gd->bd->bi_flashsize, " "); | |
169 | printf("at address 0x%08lx\n", gd->bd->bi_flashstart); | |
170 | } | |
171 | ||
12f099c0 | 172 | void board_init_f(ulong board_type) |
7b64fef3 WD |
173 | { |
174 | gd_t gd_data; | |
1f4f2121 HS |
175 | gd_t *new_gd; |
176 | bd_t *bd; | |
177 | unsigned long *new_sp; | |
178 | unsigned long monitor_len; | |
179 | unsigned long monitor_addr; | |
180 | unsigned long addr; | |
12f099c0 | 181 | long sdram_size; |
7b64fef3 WD |
182 | |
183 | /* Initialize the global data pointer */ | |
184 | memset(&gd_data, 0, sizeof(gd_data)); | |
185 | gd = &gd_data; | |
186 | ||
7b64fef3 | 187 | /* Perform initialization sequence */ |
df548d3c | 188 | board_early_init_f(); |
7b64fef3 | 189 | cpu_init(); |
7b64fef3 WD |
190 | env_init(); |
191 | init_baudrate(); | |
192 | serial_init(); | |
193 | console_init_f(); | |
194 | display_banner(); | |
12f099c0 | 195 | sdram_size = initdram(board_type); |
7b64fef3 | 196 | |
1f4f2121 | 197 | /* If we have no SDRAM, we can't go on */ |
12f099c0 | 198 | if (sdram_size <= 0) |
1f4f2121 HS |
199 | panic("No working SDRAM available\n"); |
200 | ||
201 | /* | |
202 | * Now that we have DRAM mapped and working, we can | |
203 | * relocate the code and continue running from DRAM. | |
204 | * | |
205 | * Reserve memory at end of RAM for (top down in that order): | |
206 | * - u-boot image | |
207 | * - heap for malloc() | |
208 | * - board info struct | |
209 | * - global data struct | |
210 | * - stack | |
211 | */ | |
12f099c0 | 212 | addr = CFG_SDRAM_BASE + sdram_size; |
1f4f2121 HS |
213 | monitor_len = _end - _text; |
214 | ||
215 | /* | |
216 | * Reserve memory for u-boot code, data and bss. | |
217 | * Round down to next 4 kB limit. | |
218 | */ | |
219 | addr -= monitor_len; | |
220 | addr &= ~(4096UL - 1); | |
221 | monitor_addr = addr; | |
222 | ||
223 | /* Reserve memory for malloc() */ | |
224 | addr -= CFG_MALLOC_LEN; | |
225 | ||
d5acb95b HS |
226 | #ifdef CFG_DMA_ALLOC_LEN |
227 | /* Reserve DMA memory (must be cache aligned) */ | |
228 | addr &= ~(CFG_DCACHE_LINESZ - 1); | |
229 | addr -= CFG_DMA_ALLOC_LEN; | |
230 | #endif | |
231 | ||
1f4f2121 HS |
232 | /* Allocate a Board Info struct on a word boundary */ |
233 | addr -= sizeof(bd_t); | |
234 | addr &= ~3UL; | |
235 | gd->bd = bd = (bd_t *)addr; | |
236 | ||
237 | /* Allocate a new global data copy on a 8-byte boundary. */ | |
238 | addr -= sizeof(gd_t); | |
239 | addr &= ~7UL; | |
240 | new_gd = (gd_t *)addr; | |
241 | ||
242 | /* And finally, a new, bigger stack. */ | |
243 | new_sp = (unsigned long *)addr; | |
244 | gd->stack_end = addr; | |
245 | *(--new_sp) = 0; | |
246 | *(--new_sp) = 0; | |
247 | ||
248 | /* | |
249 | * Initialize the board information struct with the | |
250 | * information we have. | |
251 | */ | |
252 | bd->bi_dram[0].start = CFG_SDRAM_BASE; | |
12f099c0 | 253 | bd->bi_dram[0].size = sdram_size; |
1f4f2121 HS |
254 | bd->bi_baudrate = gd->baudrate; |
255 | ||
256 | memcpy(new_gd, gd, sizeof(gd_t)); | |
257 | ||
258 | relocate_code((unsigned long)new_sp, new_gd, monitor_addr); | |
c841beed HS |
259 | } |
260 | ||
261 | void board_init_r(gd_t *new_gd, ulong dest_addr) | |
262 | { | |
1f4f2121 HS |
263 | extern void malloc_bin_reloc (void); |
264 | #ifndef CFG_ENV_IS_NOWHERE | |
265 | extern char * env_name_spec; | |
266 | #endif | |
e006927a | 267 | char *s; |
1f4f2121 HS |
268 | cmd_tbl_t *cmdtp; |
269 | bd_t *bd; | |
270 | ||
c841beed | 271 | gd = new_gd; |
1f4f2121 HS |
272 | bd = gd->bd; |
273 | ||
274 | gd->flags |= GD_FLG_RELOC; | |
275 | gd->reloc_off = dest_addr - CFG_MONITOR_BASE; | |
c841beed HS |
276 | |
277 | monitor_flash_len = _edata - _text; | |
278 | ||
1f4f2121 HS |
279 | /* |
280 | * We have to relocate the command table manually | |
281 | */ | |
282 | for (cmdtp = &__u_boot_cmd_start; | |
283 | cmdtp != &__u_boot_cmd_end; cmdtp++) { | |
284 | unsigned long addr; | |
285 | ||
286 | addr = (unsigned long)cmdtp->cmd + gd->reloc_off; | |
287 | cmdtp->cmd = (typeof(cmdtp->cmd))addr; | |
288 | ||
289 | addr = (unsigned long)cmdtp->name + gd->reloc_off; | |
290 | cmdtp->name = (typeof(cmdtp->name))addr; | |
291 | ||
292 | if (cmdtp->usage) { | |
293 | addr = (unsigned long)cmdtp->usage + gd->reloc_off; | |
294 | cmdtp->usage = (typeof(cmdtp->usage))addr; | |
295 | } | |
296 | #ifdef CFG_LONGHELP | |
297 | if (cmdtp->help) { | |
298 | addr = (unsigned long)cmdtp->help + gd->reloc_off; | |
299 | cmdtp->help = (typeof(cmdtp->help))addr; | |
300 | } | |
301 | #endif | |
302 | } | |
303 | ||
304 | /* there are some other pointer constants we must deal with */ | |
305 | #ifndef CFG_ENV_IS_NOWHERE | |
306 | env_name_spec += gd->reloc_off; | |
307 | #endif | |
7b64fef3 | 308 | |
1f4f2121 HS |
309 | timer_init(); |
310 | mem_malloc_init(); | |
311 | malloc_bin_reloc(); | |
d5acb95b | 312 | dma_alloc_init(); |
7b64fef3 | 313 | board_init_info(); |
7b624ad2 | 314 | |
acac4752 HS |
315 | enable_interrupts(); |
316 | ||
7b624ad2 HS |
317 | bd->bi_flashstart = 0; |
318 | bd->bi_flashsize = 0; | |
319 | bd->bi_flashoffset = 0; | |
320 | ||
321 | #ifndef CFG_NO_FLASH | |
322 | bd->bi_flashstart = CFG_FLASH_BASE; | |
323 | bd->bi_flashsize = flash_init(); | |
324 | bd->bi_flashoffset = (unsigned long)_edata - (unsigned long)_text; | |
7b64fef3 | 325 | |
1f4f2121 | 326 | if (bd->bi_flashsize) |
7b64fef3 | 327 | display_flash_config(); |
7b624ad2 HS |
328 | #endif |
329 | ||
1f4f2121 | 330 | if (bd->bi_dram[0].size) |
7b64fef3 WD |
331 | display_dram_config(); |
332 | ||
333 | gd->bd->bi_boot_params = malloc(CFG_BOOTPARAMS_LEN); | |
334 | if (!gd->bd->bi_boot_params) | |
335 | puts("WARNING: Cannot allocate space for boot parameters\n"); | |
336 | ||
337 | /* initialize environment */ | |
338 | env_relocate(); | |
339 | ||
e006927a HS |
340 | bd->bi_ip_addr = getenv_IPaddr ("ipaddr"); |
341 | ||
7b64fef3 WD |
342 | devices_init(); |
343 | jumptable_init(); | |
344 | console_init_r(); | |
345 | ||
e006927a HS |
346 | s = getenv("loadaddr"); |
347 | if (s) | |
348 | load_addr = simple_strtoul(s, NULL, 16); | |
349 | ||
67350568 | 350 | #if defined(CONFIG_CMD_NET) |
e006927a HS |
351 | s = getenv("bootfile"); |
352 | if (s) | |
353 | copy_filename(BootFile, s, sizeof(BootFile)); | |
9a24f477 HS |
354 | #if defined(CONFIG_NET_MULTI) |
355 | puts("Net: "); | |
356 | #endif | |
357 | eth_initialize(gd->bd); | |
358 | #endif | |
359 | ||
7b64fef3 WD |
360 | for (;;) { |
361 | main_loop(); | |
362 | } | |
363 | } |