添加了牛皮藓,主要方便不知情的人联系我。有洁癖者自己去除代码,在
[ddnasgpl.git] / lib_arm / board.c
bloba2d7b52523975f7378cf3ba6dc120cc51a41d067
1 /*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * (C) Copyright 2002
6 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Marius Groeger <mgroeger@sysgo.de>
9 * See file CREDITS for list of people who contributed to this
10 * project.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
28 #include <common.h>
29 #include <command.h>
30 #include <malloc.h>
31 #include <devices.h>
32 #include <version.h>
33 #include <net.h>
35 #if defined(CONFIG_MARVELL)
36 extern int PTexist(void);
37 extern unsigned long mvFlash_init (void);
38 extern unsigned int whoAmI(void);
39 extern int cpuMapInit (void);
40 #if defined(MV78200)
41 extern void second_cpu_realloc_and_load(void);
42 #include "../board/mv_feroceon/common/mvTypes.h"
43 #include "../board/mv_feroceon/mv_dd/dd_family/mv78200/mvSocUnitMap.h"
44 #endif
45 #endif
46 #ifdef CONFIG_DRIVER_SMC91111
47 #include "../drivers/smc91111.h"
48 #endif
49 #ifdef CONFIG_DRIVER_LAN91C96
50 #include "../drivers/lan91c96.h"
51 #endif
53 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
54 void nand_init (void);
55 #endif
57 ulong monitor_flash_len;
59 #ifdef CONFIG_HAS_DATAFLASH
60 extern int AT91F_DataflashInit(void);
61 extern void dataflash_print_info(void);
62 #endif
64 #ifndef CONFIG_IDENT_STRING
65 #define CONFIG_IDENT_STRING ""
66 #endif
68 const char version_string[] =
69 U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"CONFIG_IDENT_STRING;
71 #ifdef CONFIG_DRIVER_CS8900
72 extern void cs8900_get_enetaddr (uchar * addr);
73 #endif
75 #ifdef CONFIG_DRIVER_RTL8019
76 extern void rtl8019_get_enetaddr (uchar * addr);
77 #endif
79 #if (CONFIG_COMMANDS & CFG_CMD_RCVR)
80 extern void recoveryCheck(void);
81 #endif
84 * Begin and End of memory area for malloc(), and current "brk"
86 static ulong mem_malloc_start = 0;
87 static ulong mem_malloc_end = 0;
88 static ulong mem_malloc_brk = 0;
90 static
91 void mem_malloc_init (ulong dest_addr)
93 #ifndef CONFIG_MARVELL
94 mem_malloc_start = dest_addr;
95 mem_malloc_end = dest_addr + CFG_MALLOC_LEN;
96 mem_malloc_brk = mem_malloc_start;
98 memset ((void *) mem_malloc_start, 0,
99 mem_malloc_end - mem_malloc_start);
100 #else
101 unsigned int malloc_len;
102 char *env;
104 #if defined(CONFIG_MARVELL) && defined(MV78200) && defined(DUAL_OS_SHARED_MEM_78200)
105 unsigned int cfg_malloc_len = CFG_MALLOC_LEN/2;
106 unsigned int cfg_malloc_base = CFG_MALLOC_BASE+(whoAmI()*cfg_malloc_len);
107 #else
108 unsigned int cfg_malloc_len = CFG_MALLOC_LEN;
109 unsigned int cfg_malloc_base = CFG_MALLOC_BASE;
110 #endif
112 env = getenv("MALLOC_len");
113 malloc_len = simple_strtoul(env, NULL, 10) << 20;
114 if(malloc_len == 0)
115 malloc_len = cfg_malloc_len;
117 mem_malloc_end = cfg_malloc_base + malloc_len;
118 printf("Addresses %dM - 0M are saved for the U-Boot usage.\n",mem_malloc_end >> 20);
120 mem_malloc_start = cfg_malloc_base;
121 mem_malloc_brk = mem_malloc_start;
123 printf("Mem malloc Initialization (%dM - %dM):",mem_malloc_end >> 20,
124 mem_malloc_start >>20 );
125 memset ((void *) mem_malloc_start,0,mem_malloc_end - mem_malloc_start);
127 printf(" Done\n");
129 #endif
132 void *sbrk (ptrdiff_t increment)
134 ulong old = mem_malloc_brk;
135 ulong new = old + increment;
137 if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
138 return (NULL);
140 mem_malloc_brk = new;
142 return ((void *) old);
145 /************************************************************************
146 * Init Utilities *
147 ************************************************************************
148 * Some of this code should be moved into the core functions,
149 * or dropped completely,
150 * but let's get it working (again) first...
153 static int init_baudrate (void)
155 DECLARE_GLOBAL_DATA_PTR;
157 uchar tmp[64]; /* long enough for environment variables */
158 int i = getenv_r ("baudrate", tmp, sizeof (tmp));
159 gd->bd->bi_baudrate = gd->baudrate = (i > 0)
160 ? (int) simple_strtoul (tmp, NULL, 10)
161 : CONFIG_BAUDRATE;
163 return (0);
166 static int display_banner (void)
168 printf ("\n\n%s\n\n", version_string);
169 printf ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n",
170 _armboot_start, _bss_start, _bss_end);
171 #ifdef CONFIG_MODEM_SUPPORT
172 puts ("Modem Support enabled\n");
173 #endif
174 #ifdef CONFIG_USE_IRQ
175 printf ("IRQ Stack: %08lx\n", IRQ_STACK_START);
176 printf ("FIQ Stack: %08lx\n", FIQ_STACK_START);
177 #endif
179 return (0);
183 * WARNING: this code looks "cleaner" than the PowerPC version, but
184 * has the disadvantage that you either get nothing, or everything.
185 * On PowerPC, you might see "DRAM: " before the system hangs - which
186 * gives a simple yet clear indication which part of the
187 * initialization if failing.
189 #ifndef CONFIG_MARVELL
191 static int display_dram_config (void)
193 DECLARE_GLOBAL_DATA_PTR;
194 int i;
196 puts ("RAM Configuration:\n");
198 for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
199 printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
200 print_size (gd->bd->bi_dram[i].size, "\n");
203 return (0);
206 #endif
208 static void display_flash_config (ulong size)
210 puts ("Flash: ");
211 print_size (size, "\n");
216 * Breathe some life into the board...
218 * Initialize a serial port as console, and carry out some hardware
219 * tests.
221 * The first part of initialization is running from Flash memory;
222 * its main purpose is to initialize the RAM so that we
223 * can relocate the monitor code to RAM.
227 * All attempts to come up with a "common" initialization sequence
228 * that works for all boards and architectures failed: some of the
229 * requirements are just _too_ different. To get rid of the resulting
230 * mess of board dependent #ifdef'ed code we now make the whole
231 * initialization sequence configurable to the user.
233 * The requirements for any new initalization function is simple: it
234 * receives a pointer to the "global data" structure as it's only
235 * argument, and returns an integer return code, where 0 means
236 * "continue" and != 0 means "fatal error, hang the system".
238 typedef int (init_fnc_t) (void);
240 init_fnc_t *init_sequence[] = {
241 cpu_init, /* basic cpu dependent setup */
242 board_init, /* basic board dependent setup */
243 interrupt_init, /* set up exceptions */
244 env_init, /* initialize environment */
245 init_baudrate, /* initialze baudrate settings */
246 serial_init, /* serial communications setup */
247 console_init_f, /* stage 1 init of console */
248 display_banner, /* say that we are here */
249 #if defined(CONFIG_MARVELL) && defined(MV78XX0)
250 cpuMapInit,
251 #endif
252 dram_init, /* configure available RAM banks */
253 #ifndef CONFIG_MARVELL
254 display_dram_config,
255 #endif
256 #if defined(CONFIG_VCMA9) || defined (CONFIG_CMC_PU2)
257 checkboard,
258 #endif
259 NULL,
262 #if defined(CONFIG_MARVELL) && defined(MV78200)
263 init_fnc_t *init_sequence_slave[] = {
264 cpu_init, /* basic cpu dependent setup */
265 board_init, /* basic board dependent setup */
266 interrupt_init, /* set up exceptions */
267 env_init,
268 serial_init, /* serial communications setup */
269 console_init_f, /* stage 1 init of console */
270 display_banner, /* say that we are here */
271 NULL, /* Terminate this list */
273 #endif
275 void start_armboot (void)
277 DECLARE_GLOBAL_DATA_PTR;
279 ulong size;
280 init_fnc_t **init_fnc_ptr;
281 char *s;
282 char *env;
283 volatile unsigned int cpu = 0;
284 int nand_access = 0;
285 #if defined(CONFIG_VFD) || defined(CONFIG_LCD)
286 unsigned long addr;
287 #endif
288 /* Pointer is writable since we allocated a register for it */
289 #ifndef CONFIG_MARVELL
290 gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
291 #else
292 #if defined(CONFIG_MARVELL) && defined(MV78200)
293 /* Marvell Master CPU Boot */
294 cpu = whoAmI();
295 #if !defined(DUAL_OS_78200)
296 if(cpu == 0)
297 #endif
298 #endif
299 gd = (gd_t*)(_armboot_start - sizeof(gd_t));
300 #endif
301 /* compiler optimization barrier needed for GCC >= 3.4 */
302 __asm__ __volatile__("": : :"memory");
304 #if defined(CONFIG_MARVELL) && defined(MV78200)
305 /* Marvell Master CPU Boot */
306 #if !defined(DUAL_OS_78200)
307 if(cpu == 0)
309 #endif
310 #endif
311 memset ((void*)gd, 0, sizeof (gd_t));
312 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
313 memset (gd->bd, 0, sizeof (bd_t));
315 monitor_flash_len = _bss_start - _armboot_start;
317 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
318 if ((*init_fnc_ptr)() != 0) {
319 hang ();
322 /* armboot_start is defined in the board-specific linker script */
323 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
326 #if !(defined(MV78200) && (defined(DUAL_OS_78200) || \
327 (defined(DUAL_OS_SHARED_MEM_78200) && !defined(MV_NAND_BOOT))))
328 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
329 puts ("NAND:");
330 nand_init(); /* go init the NAND */
331 #endif
332 #endif
333 /* initialize environment */
334 env_relocate ();
336 #if defined(MV78200) && (defined(DUAL_OS_78200) || defined(DUAL_OS_SHARED_MEM_78200))
337 env = getenv("cpu0_res");
338 if (env)
339 mvSocUnitMapFillTable(env, MASTER_CPU, strstr);
340 env = getenv("cpu1_res");
341 if (env)
342 mvSocUnitMapFillTable(env, SLAVE_CPU, strstr);
343 #endif
345 #ifndef CFG_NO_FLASH
346 /* configure available FLASH banks */
347 size = flash_init ();
348 #if defined(CONFIG_MARVELL)
349 size += mvFlash_init ();
350 #endif
351 display_flash_config (size);
352 #endif /* CFG_NO_FLASH */
354 #ifdef CONFIG_VFD
355 # ifndef PAGE_SIZE
356 # define PAGE_SIZE 4096
357 # endif
359 * reserve memory for VFD display (always full pages)
361 /* bss_end is defined in the board-specific linker script */
362 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
363 size = vfd_setmem (addr);
364 gd->fb_base = addr;
365 #endif /* CONFIG_VFD */
367 #ifdef CONFIG_LCD
368 # ifndef PAGE_SIZE
369 # define PAGE_SIZE 4096
370 # endif
372 * reserve memory for LCD display (always full pages)
374 /* bss_end is defined in the board-specific linker script */
375 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
376 size = lcd_setmem (addr);
377 gd->fb_base = addr;
378 #endif /* CONFIG_LCD */
380 #if defined(MV78200) && (defined(DUAL_OS_78200) || \
381 (defined(DUAL_OS_SHARED_MEM_78200) && !defined(MV_NAND_BOOT)))
382 #if (CONFIG_COMMANDS & CFG_CMD_NAND)
383 /* Check in dual CPU system which CPU use nand */
384 if (mvSocUnitIsMappedToThisCpu(NAND_FLASH))
386 puts ("NAND:");
387 nand_init(); /* go init the NAND */
389 #endif
390 #endif
392 #ifdef CONFIG_HAS_DATAFLASH
393 AT91F_DataflashInit();
394 dataflash_print_info();
395 #endif
397 #ifdef CFG_DIAG
398 #define DIAGNOSTICS
399 #ifdef DIAGNOSTICS
400 if( !strcmp(getenv("run_diag"), "yes") ||
401 !strcmp(getenv("run_diag"), "YES"))
402 run_diag();
403 #endif
404 #endif
406 #ifdef CONFIG_VFD
407 /* must do this after the framebuffer is allocated */
408 drv_vfd_init();
409 #endif /* CONFIG_VFD */
411 /* IP Address */
412 #if defined(CONFIG_MARVELL) && defined(DUAL_OS_78200)
413 if(cpu == 0)
414 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
415 else
416 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr2");
417 #else
418 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
419 #endif
421 /* MAC Address */
423 int i;
424 ulong reg;
425 char *s, *e;
426 uchar tmp[64];
428 i = getenv_r ("ethaddr", tmp, sizeof (tmp));
429 s = (i > 0) ? tmp : NULL;
431 for (reg = 0; reg < 6; ++reg) {
432 gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
433 if (s)
434 s = (*e) ? e + 1 : e;
438 devices_init (); /* get the devices list going. */
440 #ifdef CONFIG_CMC_PU2
441 load_sernum_ethaddr ();
442 #endif /* CONFIG_CMC_PU2 */
444 jumptable_init ();
446 console_init_r (); /* fully init console as a device */
448 #if defined(CONFIG_MISC_INIT_R)
449 /* miscellaneous platform dependent initialisations */
450 misc_init_r ();
451 #endif
452 /* enable exceptions */
453 enable_interrupts ();
455 /* Perform network card initialisation if necessary */
456 #ifdef CONFIG_DRIVER_CS8900
457 cs8900_get_enetaddr (gd->bd->bi_enetaddr);
458 #endif
460 #if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
461 if (getenv ("ethaddr")) {
462 smc_set_mac_addr(gd->bd->bi_enetaddr);
464 #endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */
466 /* Initialize from environment */
467 if ((s = getenv ("loadaddr")) != NULL) {
468 load_addr = simple_strtoul (s, NULL, 16);
470 #if (CONFIG_COMMANDS & CFG_CMD_NET)
471 if ((s = getenv ("bootfile")) != NULL) {
472 copy_filename (BootFile, s, sizeof (BootFile));
474 #endif /* CFG_CMD_NET */
476 #ifdef BOARD_LATE_INIT
477 board_late_init ();
478 #endif
479 #if (CONFIG_COMMANDS & CFG_CMD_SCSI)
480 puts ("SCSI: ");
481 scsi_init ();
482 #endif
483 #if (CONFIG_COMMANDS & CFG_CMD_NET)
484 #if defined(CONFIG_NET_MULTI)
485 puts ("Net: ");
486 #endif
487 eth_initialize(gd->bd);
488 #endif
489 #if (CONFIG_COMMANDS & CFG_CMD_RCVR)
490 recoveryCheck();
491 #endif
492 /* Cancle SILENT mode for prompt only */
493 #if defined(CONFIG_MARVELL) && defined(CONFIG_SILENT_CONSOLE)
494 DECLARE_GLOBAL_DATA_PTR;
495 gd->flags &= ~GD_FLG_SILENT;
496 #endif
497 #if defined(CONFIG_MARVELL) && defined(MV78200)
498 #if !defined(DUAL_OS_78200)
499 /* Marvell Second CPU Boot */
501 else
503 /* Master CPU global data */
504 gd_t *gd_master;
505 gd_master = (gd_t*)(_armboot_start - sizeof(gd_t));
506 /* Slave CPU global data */
507 gd = (gd_t*)(_armboot_start - _1M - sizeof(gd_t));
508 memset ((void *) gd, 0, sizeof (gd_t));
509 memcpy ((void *)gd, (const void *)gd_master, sizeof (gd_t));
510 gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
511 memset ((void *) gd->bd, 0, sizeof (bd_t));
513 /*copy the Global Data from the Master. */
514 memcpy ((void *)gd->bd, (const void *)gd_master->bd, sizeof (bd_t));
515 for (init_fnc_ptr = init_sequence_slave; *init_fnc_ptr; ++init_fnc_ptr) {
516 if ((*init_fnc_ptr)() != 0) {
517 hang ();
520 gd->env_addr = gd_master->env_addr;
521 #if defined(DUAL_OS_SHARED_MEM_78200)
522 /* armboot_start is defined in the board-specific linker script */
523 mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);
524 env = getenv("cpu0_res");
525 if (env)
526 mvSocUnitMapFillTable(env, MASTER_CPU, strstr);
527 env = getenv("cpu1_res");
528 if (env)
529 mvSocUnitMapFillTable(env, SLAVE_CPU, strstr);
530 gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr2");
531 #endif
532 misc_init_r ();
533 #if (CONFIG_COMMANDS & CFG_CMD_SCSI)
534 puts ("SCSI: ");
535 scsi_init ();
536 #endif
538 #if (CONFIG_COMMANDS & CFG_CMD_NET)
539 #if defined(CONFIG_NET_MULTI)
540 puts ("Net: ");
541 #endif
542 eth_initialize(gd->bd);
543 #endif
546 #endif
547 if (cpu == 0) {
548 second_cpu_realloc_and_load();
550 #endif
551 puts ("*****contact with me*****\n");
552 puts ("e-mail:linetkux@gmail.com\n");/*FIXME:If you see this line, then you may know how to contact
553 me. So, just remove this line!*/
554 puts ("*************************\n");
555 /* main_loop() can return to retry autoboot, if so just run it again. */
556 for (;;) {
557 main_loop ();
560 /* NOTREACHED - no way out of command loop except booting */
563 void hang (void)
565 puts ("### ERROR ### Please RESET the board ###\n");
566 for (;;);
569 #ifdef CONFIG_MODEM_SUPPORT
570 /* called from main loop (common/main.c) */
571 extern void dbg(const char *fmt, ...);
572 int mdm_init (void)
574 char env_str[16];
575 char *init_str;
576 int i;
577 extern char console_buffer[];
578 static inline void mdm_readline(char *buf, int bufsiz);
579 extern void enable_putc(void);
580 extern int hwflow_onoff(int);
582 enable_putc(); /* enable serial_putc() */
584 #ifdef CONFIG_HWFLOW
585 init_str = getenv("mdm_flow_control");
586 if (init_str && (strcmp(init_str, "rts/cts") == 0))
587 hwflow_onoff (1);
588 else
589 hwflow_onoff(-1);
590 #endif
592 for (i = 1;;i++) {
593 sprintf(env_str, "mdm_init%d", i);
594 if ((init_str = getenv(env_str)) != NULL) {
595 serial_puts(init_str);
596 serial_puts("\n");
597 for(;;) {
598 mdm_readline(console_buffer, CFG_CBSIZE);
599 dbg("ini%d: [%s]", i, console_buffer);
601 if ((strcmp(console_buffer, "OK") == 0) ||
602 (strcmp(console_buffer, "ERROR") == 0)) {
603 dbg("ini%d: cmd done", i);
604 break;
605 } else /* in case we are originating call ... */
606 if (strncmp(console_buffer, "CONNECT", 7) == 0) {
607 dbg("ini%d: connect", i);
608 return 0;
611 } else
612 break; /* no init string - stop modem init */
614 udelay(100000);
617 udelay(100000);
619 /* final stage - wait for connect */
620 for(;i > 1;) { /* if 'i' > 1 - wait for connection
621 message from modem */
622 mdm_readline(console_buffer, CFG_CBSIZE);
623 dbg("ini_f: [%s]", console_buffer);
624 if (strncmp(console_buffer, "CONNECT", 7) == 0) {
625 dbg("ini_f: connected");
626 return 0;
630 return 0;
633 /* 'inline' - We have to do it fast */
634 static inline void mdm_readline(char *buf, int bufsiz)
636 char c;
637 char *p;
638 int n;
640 n = 0;
641 p = buf;
642 for(;;) {
643 c = serial_getc();
645 /* dbg("(%c)", c); */
647 switch(c) {
648 case '\r':
649 break;
650 case '\n':
651 *p = '\0';
652 return;
654 default:
655 if(n++ > bufsiz) {
656 *p = '\0';
657 return; /* sanity check */
659 *p = c;
660 p++;
661 break;
665 #endif /* CONFIG_MODEM_SUPPORT */