move ifxmips uboot to package/
[openwrt.git] / package / uboot-ifxmips / files / lib_bootstrap / bootstrap_board_danube.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <command.h>
26 #include <malloc.h>
27 #include <devices.h>
28 #include <version.h>
29 #include <net.h>
30 #include <environment.h>
31 #ifdef CONFIG_DANUBE
32 #include <asm-mips/danube.h>
33 #include <configs/danube.h>
34 #endif
35 #include "LzmaWrapper.h"
36
37 //#define DEBUG_ENABLE_BOOTSTRAP_PRINTF
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 #if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < BOOTSTRAP_CFG_MONITOR_BASE) || \
42       (CFG_ENV_ADDR >= (BOOTSTRAP_CFG_MONITOR_BASE + CFG_MONITOR_LEN)) ) || \
43     defined(CFG_ENV_IS_IN_NVRAM)
44 #define TOTAL_MALLOC_LEN        (CFG_MALLOC_LEN + CFG_ENV_SIZE)
45 #else
46 #define TOTAL_MALLOC_LEN        CFG_MALLOC_LEN
47 #endif
48
49 #undef DEBUG
50
51 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
52 extern unsigned long nand_init(void);
53 #endif
54
55 #ifdef CONFIG_SERIAL_FLASH
56 extern int serial_flash_init (void);
57 #endif
58
59 extern int timer_init(void);
60
61 extern int incaip_set_cpuclk(void);
62
63 extern ulong uboot_end_data_bootstrap;
64 extern ulong uboot_end_bootstrap;
65
66 ulong monitor_flash_len;
67
68 const char version_string[] =
69         U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")";
70
71 static char *failed = "*** failed ***\n";
72
73 /*
74  * Begin and End of memory area for malloc(), and current "brk"
75  */
76 static ulong mem_malloc_start;
77 static ulong mem_malloc_end;
78 static ulong mem_malloc_brk;
79
80
81 /*
82  * The Malloc area is immediately below the monitor copy in DRAM
83  */
84 static void mem_malloc_init (ulong dest_addr)
85 {
86 //      ulong dest_addr = BOOTSTRAP_CFG_MONITOR_BASE + gd->reloc_off;
87
88         mem_malloc_end = dest_addr;
89         mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN;
90         mem_malloc_brk = mem_malloc_start;
91
92         memset ((void *) mem_malloc_start,
93                 0,
94                 mem_malloc_end - mem_malloc_start);
95 }
96
97 void *malloc(unsigned int size)
98 {
99         if(size < (mem_malloc_end - mem_malloc_start))
100         {
101                 mem_malloc_start += size;
102                 return (void *)(mem_malloc_start - size);
103         }
104         return NULL;
105 }
106
107 void *realloc(void *src,unsigned int size)
108 {
109         return NULL;
110 }
111
112 void free(void *src)
113 {
114         return;
115 }
116
117
118 void *sbrk (ptrdiff_t increment)
119 {
120         ulong old = mem_malloc_brk;
121         ulong new = old + increment;
122
123         if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
124                 return (NULL);
125         }
126         mem_malloc_brk = new;
127         return ((void *) old);
128 }
129
130
131 static int init_func_ram (void)
132 {
133 #ifdef  CONFIG_BOARD_TYPES
134         int board_type = gd->board_type;
135 #else
136         int board_type = 0;     /* use dummy arg */
137 #endif
138
139 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
140         puts ("DRAM:  ");
141 #endif
142
143         if ((gd->ram_size = initdram (board_type)) > 0) {
144 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
145                 print_size (gd->ram_size, "\n");
146 #endif
147                 return (0);
148         }
149 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
150         puts (failed);
151 #endif
152         return (1);
153 }
154
155 static int display_banner(void)
156 {
157 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
158         printf ("\n\n%s\n\n", version_string);
159 #endif
160         return (0);
161 }
162
163 static int init_baudrate (void)
164 {
165 #if 0
166         char tmp[64];   /* long enough for environment variables */
167         int i = getenv_r ("baudrate", tmp, sizeof (tmp));
168
169         gd->baudrate = (i > 0)
170                         ? (int) simple_strtoul (tmp, NULL, 10)
171                         : CONFIG_BAUDRATE;
172 #endif
173
174         gd->baudrate = CONFIG_BAUDRATE;
175
176         return (0);
177 }
178 #ifdef CONFIG_DANUBE
179 static void init_led(void)
180 {
181
182   *(unsigned long *)0xBE100B18 |=  0x70;
183   *(unsigned long *)0xBE100B1C |=  0x70;
184   *(unsigned long *)0xBE100B20 &= ~0x70;
185   *(unsigned long *)0xBE100B24 |=  0x70;
186 #ifdef USE_REFERENCE_BOARD
187
188   *DANUBE_LED_CON1 = 0x00000003;
189   *DANUBE_LED_CPU0 = 0x0000010;
190   *DANUBE_LED_CPU1 = 0x00000000;
191   *DANUBE_LED_AR   = 0x00000000;
192   *DANUBE_LED_CON0 = 0x84000000;
193
194 #else
195
196   *DANUBE_LED_CON1 = 0x00000007;
197   *DANUBE_LED_CPU0 = 0x00001000;
198   *DANUBE_LED_CPU1 = 0x00000000;
199   *DANUBE_LED_AR   = 0x00000000;
200   *DANUBE_LED_CON0 = 0x84000000;
201
202 #endif
203
204 }
205 #endif
206 /*
207  * Breath some life into the board...
208  *
209  * The first part of initialization is running from Flash memory;
210  * its main purpose is to initialize the RAM so that we
211  * can relocate the monitor code to RAM.
212  */
213
214 /*
215  * All attempts to come up with a "common" initialization sequence
216  * that works for all boards and architectures failed: some of the
217  * requirements are just _too_ different. To get rid of the resulting
218  * mess of board dependend #ifdef'ed code we now make the whole
219  * initialization sequence configurable to the user.
220  *
221  * The requirements for any new initalization function is simple: it
222  * receives a pointer to the "global data" structure as it's only
223  * argument, and returns an integer return code, where 0 means
224  * "continue" and != 0 means "fatal error, hang the system".
225  */
226 typedef int (init_fnc_t) (void);
227
228 init_fnc_t *init_sequence[] = {
229         //timer_init,
230         //env_init,             /* initialize environment */
231 #ifdef CONFIG_INCA_IP
232         incaip_set_cpuclk,      /* set cpu clock according to environment variable */
233 #endif
234 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
235         init_baudrate,          /* initialze baudrate settings */
236         serial_init,            /* serial communications setup */
237         console_init_f,
238         display_banner,         /* say that we are here */
239 #endif
240         init_func_ram,
241         //checkboard,
242         NULL,
243 };
244
245
246 void bootstrap_board_init_f(ulong bootflag)
247 {
248         gd_t gd_data, *id;
249         bd_t *bd;
250         init_fnc_t **init_fnc_ptr;
251         ulong addr, addr_sp, len = (ulong)&uboot_end_bootstrap - BOOTSTRAP_CFG_MONITOR_BASE;
252         ulong *s;
253         ulong lzmaImageaddr  = 0;
254 #ifdef CONFIG_PURPLE
255         void copy_code (ulong);
256 #endif
257
258         /* Pointer is writable since we allocated a register for it.
259          */
260         gd = &gd_data;
261         /* compiler optimization barrier needed for GCC >= 3.4 */
262         __asm__ __volatile__("": : :"memory");
263
264         memset ((void *)gd, 0, sizeof (gd_t));
265
266         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
267                 if ((*init_fnc_ptr)() != 0) {
268                         hang ();
269                 }
270         }
271
272         /*
273          * Now that we have DRAM mapped and working, we can
274          * relocate the code and continue running from DRAM.
275          */
276         addr = CFG_SDRAM_BASE + gd->ram_size;
277
278         /* We can reserve some RAM "on top" here.
279          */
280
281         /* round down to next 4 kB limit.
282          */
283         addr &= ~(4096 - 1);
284         debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
285
286         /* Reserve memory for U-Boot code, data & bss
287          * round down to next 16 kB limit
288          */
289         addr -= len;
290         addr &= ~(16 * 1024 - 1);
291
292         debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
293
294          /* Reserve memory for malloc() arena.
295          */
296         addr_sp = addr - TOTAL_MALLOC_LEN;
297         debug ("Reserving %dk for malloc() at: %08lx\n",
298                         TOTAL_MALLOC_LEN >> 10, addr_sp);
299
300         /*
301          * (permanently) allocate a Board Info struct
302          * and a permanent copy of the "global" data
303          */
304         addr_sp -= sizeof(bd_t);
305         bd = (bd_t *)addr_sp;
306         gd->bd = bd;
307         debug ("Reserving %d Bytes for Board Info at: %08lx\n",
308                         sizeof(bd_t), addr_sp);
309
310         addr_sp -= sizeof(gd_t);
311         id = (gd_t *)addr_sp;
312         debug ("Reserving %d Bytes for Global Data at: %08lx\n",
313                         sizeof (gd_t), addr_sp);
314
315         /* Reserve memory for boot params.
316          */
317         addr_sp -= CFG_BOOTPARAMS_LEN;
318         bd->bi_boot_params = addr_sp;
319         debug ("Reserving %dk for boot params() at: %08lx\n",
320                         CFG_BOOTPARAMS_LEN >> 10, addr_sp);
321
322         /*
323          * Finally, we set up a new (bigger) stack.
324          *
325          * Leave some safety gap for SP, force alignment on 16 byte boundary
326          * Clear initial stack frame
327          */
328         addr_sp -= 16;
329         addr_sp &= ~0xF;
330         s = (ulong *)addr_sp;
331         *s-- = 0;
332         *s-- = 0;
333         addr_sp = (ulong)s;
334         debug ("Stack Pointer at: %08lx\n", addr_sp);
335
336         /*
337          * Save local variables to board info struct
338          */
339         bd->bi_memstart = CFG_SDRAM_BASE;       /* start of  DRAM memory */
340         bd->bi_memsize  = gd->ram_size;         /* size  of  DRAM memory in bytes */
341         bd->bi_baudrate = gd->baudrate;         /* Console Baudrate */
342
343         memcpy (id, (void *)gd, sizeof (gd_t));
344
345         /* On the purple board we copy the code in a special way
346          * in order to solve flash problems
347          */
348 #ifdef CONFIG_PURPLE
349         copy_code(addr);
350 #endif
351
352         lzmaImageaddr = (ulong)&uboot_end_data_bootstrap;
353
354 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
355         printf ("\n relocating to address %08x ", addr);
356 #endif
357
358         bootstrap_relocate_code (addr_sp, id, addr);
359
360         /* NOTREACHED - relocate_code() does not return */
361 }
362 /************************************************************************
363  *
364  * This is the next part if the initialization sequence: we are now
365  * running from RAM and have a "normal" C environment, i. e. global
366  * data can be written, BSS has been cleared, the stack size in not
367  * that critical any more, etc.
368  *
369  ************************************************************************
370  */
371 #define CONFIG_LZMA 
372
373 void bootstrap_board_init_r (gd_t *id, ulong dest_addr)
374 {
375         int i;
376
377         ulong   addr;
378         ulong   data, len, checksum;
379         ulong  *len_ptr;
380         image_header_t header;
381         image_header_t *hdr = &header;
382         unsigned int destLen;
383         int (*fn)();
384
385 #if 1
386 #endif
387
388
389
390         /* initialize malloc() area */
391         mem_malloc_init(dest_addr);
392
393 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
394         printf("\n Compressed Image at %08x \n ", (BOOTSTRAP_CFG_MONITOR_BASE + ((ulong)&uboot_end_data_bootstrap - dest_addr)));
395 #endif
396         
397         addr = (char *)(BOOTSTRAP_CFG_MONITOR_BASE + ((ulong)&uboot_end_data_bootstrap - dest_addr));
398         memmove (&header, (char *)addr, sizeof(image_header_t));
399
400         if (ntohl(hdr->ih_magic) != IH_MAGIC) {
401 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
402                 printf ("Bad Magic Number at address 0x%08lx\n",addr);
403 #endif
404                 return;
405         }
406
407         data = (ulong)&header;
408         len  = sizeof(image_header_t);
409
410         checksum = ntohl(hdr->ih_hcrc);
411         hdr->ih_hcrc = 0;
412         if (crc32 (0, (char *)data, len) != checksum) {
413 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
414                 printf ("Bad Header Checksum\n");
415 #endif
416                 return;
417         }
418         
419         data = addr + sizeof(image_header_t);
420         len  = ntohl(hdr->ih_size);
421
422         len_ptr = (ulong *)data;
423
424     
425
426 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
427         printf ("Disabling all the interrupts\n");
428 #endif
429         disable_interrupts();
430 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
431         printf ("   Uncompressing UBoot Image ... \n" );
432 #endif
433
434         /*
435          * If we've got less than 4 MB of malloc() space,
436          * use slower decompression algorithm which requires
437          * at most 2300 KB of memory.
438          */
439         destLen = 0x0;
440
441 #ifdef CONFIG_BZIP2
442         i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),
443                                         0x400000, (char *)data, len,
444                                         CFG_MALLOC_LEN < (4096 * 1024), 0);
445         if (i != BZ_OK) {
446 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
447                         printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i);
448 #endif
449                         return;
450         }
451 #endif /* CONFIG_BZIP2 */
452         
453 #ifdef CONFIG_MICROBZIP2 
454         i = micro_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),
455                                         &destLen, (char *)data, len,
456                                         CFG_MALLOC_LEN < (4096 * 1024), 0);
457         if (i != RETVAL_OK) {
458 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
459                 printf ("MICRO_BUNZIP2 ERROR %d - must RESET board to recover\n", i);
460 #endif
461                 //do_reset (cmdtp, flag, argc, argv);
462                 return;
463         }
464 #endif
465         
466 #ifdef CONFIG_LZMA 
467 #if 0
468         i = lzmaBuffToBuffDecompress ((char*)ntohl(hdr->ih_load),
469                                         &destLen, (char *)data, len);
470 #endif
471
472         i = lzma_inflate ((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), &destLen);
473         if (i != LZMA_RESULT_OK) {
474 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
475                 printf ("LZMA ERROR %d - must RESET board to recover\n", i);
476 #endif
477                 //do_reset (cmdtp, flag, argc, argv);
478                 return;
479         }
480 #endif
481
482 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
483         printf ("   Uncompression completed successfully with destLen %d\n ",destLen );
484 #endif
485
486     fn = ntohl(hdr->ih_load);
487
488         (*fn)();
489
490         hang ();
491
492 }
493
494 void hang (void)
495 {
496
497 #ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF
498         puts ("### ERROR ### Please RESET the board ###\n");
499 #endif
500         for (;;);
501 }