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