Merge branch 'next' of git://git.denx.de/u-boot-avr32
[platform/kernel/u-boot.git] / lib_m68k / board.c
1 /*
2  * (C) Copyright 2003
3  * Josef Baumgartner <josef.baumgartner@telex.de>
4  *
5  * (C) Copyright 2000-2002
6  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
7  *
8  * See file CREDITS for list of people who contributed to this
9  * project.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24  * MA 02111-1307 USA
25  */
26
27 #include <common.h>
28 #include <watchdog.h>
29 #include <command.h>
30 #include <malloc.h>
31 #include <devices.h>
32
33 #include <asm/immap.h>
34
35 #if defined(CONFIG_CMD_IDE)
36 #include <ide.h>
37 #endif
38 #if defined(CONFIG_CMD_SCSI)
39 #include <scsi.h>
40 #endif
41 #if defined(CONFIG_CMD_KGDB)
42 #include <kgdb.h>
43 #endif
44 #ifdef CONFIG_STATUS_LED
45 #include <status_led.h>
46 #endif
47 #include <net.h>
48 #include <serial.h>
49 #if defined(CONFIG_CMD_BEDBUG)
50 #include <cmd_bedbug.h>
51 #endif
52 #ifdef CFG_ALLOC_DPRAM
53 #include <commproc.h>
54 #endif
55 #include <version.h>
56
57 #if defined(CONFIG_HARD_I2C) || \
58     defined(CONFIG_SOFT_I2C)
59 #include <i2c.h>
60 #endif
61
62 #ifdef CONFIG_CMD_SPI
63 #include <spi.h>
64 #endif
65
66 DECLARE_GLOBAL_DATA_PTR;
67
68 static char *failed = "*** failed ***\n";
69
70 #ifdef  CONFIG_PCU_E
71 extern flash_info_t flash_info[];
72 #endif
73
74 #include <environment.h>
75
76 #if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < CFG_MONITOR_BASE) || \
77       (CFG_ENV_ADDR >= (CFG_MONITOR_BASE + CFG_MONITOR_LEN)) ) || \
78     defined(CFG_ENV_IS_IN_NVRAM)
79 #define TOTAL_MALLOC_LEN        (CFG_MALLOC_LEN + CFG_ENV_SIZE)
80 #else
81 #define TOTAL_MALLOC_LEN        CFG_MALLOC_LEN
82 #endif
83
84 extern ulong __init_end;
85 extern ulong _end;
86
87 extern  void timer_init(void);
88
89 #if defined(CONFIG_WATCHDOG)
90 # define INIT_FUNC_WATCHDOG_INIT        watchdog_init,
91 # define WATCHDOG_DISABLE               watchdog_disable
92
93 extern int watchdog_init(void);
94 extern int watchdog_disable(void);
95 #else
96 # define INIT_FUNC_WATCHDOG_INIT        /* undef */
97 # define WATCHDOG_DISABLE               /* undef */
98 #endif /* CONFIG_WATCHDOG */
99
100 ulong monitor_flash_len;
101
102 /*
103  * Begin and End of memory area for malloc(), and current "brk"
104  */
105 static  ulong   mem_malloc_start = 0;
106 static  ulong   mem_malloc_end   = 0;
107 static  ulong   mem_malloc_brk   = 0;
108
109 /************************************************************************
110  * Utilities                                                            *
111  ************************************************************************
112  */
113
114 /*
115  * The Malloc area is immediately below the monitor copy in DRAM
116  */
117 static void mem_malloc_init (void)
118 {
119         ulong dest_addr = CFG_MONITOR_BASE + gd->reloc_off;
120
121         mem_malloc_end = dest_addr;
122         mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN;
123         mem_malloc_brk = mem_malloc_start;
124
125         memset ((void *) mem_malloc_start,
126                 0,
127                 mem_malloc_end - mem_malloc_start);
128 }
129
130 void *sbrk (ptrdiff_t increment)
131 {
132         ulong old = mem_malloc_brk;
133         ulong new = old + increment;
134
135         if ((new < mem_malloc_start) ||
136             (new > mem_malloc_end) ) {
137                 return (NULL);
138         }
139         mem_malloc_brk = new;
140         return ((void *)old);
141 }
142
143 char *strmhz(char *buf, long hz)
144 {
145         long l, n;
146         long m;
147
148         n = hz / 1000000L;
149
150         l = sprintf (buf, "%ld", n);
151
152         m = (hz % 1000000L) / 1000L;
153
154         if (m != 0)
155                 sprintf (buf+l, ".%03ld", m);
156
157         return (buf);
158 }
159
160 /*
161  * All attempts to come up with a "common" initialization sequence
162  * that works for all boards and architectures failed: some of the
163  * requirements are just _too_ different. To get rid of the resulting
164  * mess of board dependend #ifdef'ed code we now make the whole
165  * initialization sequence configurable to the user.
166  *
167  * The requirements for any new initalization function is simple: it
168  * receives a pointer to the "global data" structure as it's only
169  * argument, and returns an integer return code, where 0 means
170  * "continue" and != 0 means "fatal error, hang the system".
171  */
172 typedef int (init_fnc_t) (void);
173
174 /************************************************************************
175  * Init Utilities
176  ************************************************************************
177  * Some of this code should be moved into the core functions,
178  * but let's get it working (again) first...
179  */
180
181 static int init_baudrate (void)
182 {
183         char tmp[64];   /* long enough for environment variables */
184         int i = getenv_r ("baudrate", tmp, sizeof (tmp));
185
186         gd->baudrate = (i > 0)
187                         ? (int) simple_strtoul (tmp, NULL, 10)
188                         : CONFIG_BAUDRATE;
189         return (0);
190 }
191
192 /***********************************************************************/
193
194 static int init_func_ram (void)
195 {
196         int board_type = 0;     /* use dummy arg */
197         puts ("DRAM:  ");
198
199         if ((gd->ram_size = initdram (board_type)) > 0) {
200                 print_size (gd->ram_size, "\n");
201                 return (0);
202         }
203         puts (failed);
204         return (1);
205 }
206
207 /***********************************************************************/
208
209 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
210 static int init_func_i2c (void)
211 {
212         puts ("I2C:   ");
213         i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
214         puts ("ready\n");
215         return (0);
216 }
217 #endif
218
219 #if defined(CONFIG_HARD_SPI)
220 static int init_func_spi (void)
221 {
222         puts ("SPI:   ");
223         spi_init ();
224         puts ("ready\n");
225         return (0);
226 }
227 #endif
228
229 /***********************************************************************/
230
231 /************************************************************************
232  * Initialization sequence                                              *
233  ************************************************************************
234  */
235
236 init_fnc_t *init_sequence[] = {
237         get_clocks,
238         env_init,
239         init_baudrate,
240         serial_init,
241         console_init_f,
242         display_options,
243         checkcpu,
244         checkboard,
245 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
246         init_func_i2c,
247 #endif
248 #if defined(CONFIG_HARD_SPI)
249         init_func_spi,
250 #endif
251         init_func_ram,
252 #if defined(CFG_DRAM_TEST)
253         testdram,
254 #endif /* CFG_DRAM_TEST */
255         INIT_FUNC_WATCHDOG_INIT
256         NULL,                   /* Terminate this list */
257 };
258
259
260 /************************************************************************
261  *
262  * This is the first part of the initialization sequence that is
263  * implemented in C, but still running from ROM.
264  *
265  * The main purpose is to provide a (serial) console interface as
266  * soon as possible (so we can see any error messages), and to
267  * initialize the RAM so that we can relocate the monitor code to
268  * RAM.
269  *
270  * Be aware of the restrictions: global data is read-only, BSS is not
271  * initialized, and stack space is limited to a few kB.
272  *
273  ************************************************************************
274  */
275
276 void
277 board_init_f (ulong bootflag)
278 {
279         bd_t *bd;
280         ulong len, addr, addr_sp;
281         ulong *paddr;
282         gd_t *id;
283         init_fnc_t **init_fnc_ptr;
284 #ifdef CONFIG_PRAM
285         int i;
286         ulong reg;
287         char tmp[64];           /* long enough for environment variables */
288 #endif
289
290         /* Pointer is writable since we allocated a register for it */
291         gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
292         /* compiler optimization barrier needed for GCC >= 3.4 */
293         __asm__ __volatile__("": : :"memory");
294
295         /* Clear initial global data */
296         memset ((void *) gd, 0, sizeof (gd_t));
297
298         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
299                 if ((*init_fnc_ptr)() != 0) {
300                         hang ();
301                 }
302         }
303
304         /*
305          * Now that we have DRAM mapped and working, we can
306          * relocate the code and continue running from DRAM.
307          *
308          * Reserve memory at end of RAM for (top down in that order):
309          *      - protected RAM
310          *      - LCD framebuffer
311          *      - monitor code
312          *      - board info struct
313          */
314         len = (ulong)&_end - CFG_MONITOR_BASE;
315
316         addr = CFG_SDRAM_BASE + gd->ram_size;
317
318 #ifdef CONFIG_LOGBUFFER
319         /* reserve kernel log buffer */
320         addr -= (LOGBUFF_RESERVE);
321         debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
322 #endif
323
324 #ifdef CONFIG_PRAM
325         /*
326          * reserve protected RAM
327          */
328         i = getenv_r ("pram", tmp, sizeof (tmp));
329         reg = (i > 0) ? simple_strtoul (tmp, NULL, 10) : CONFIG_PRAM;
330         addr -= (reg << 10);            /* size is in kB */
331         debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
332 #endif /* CONFIG_PRAM */
333
334         /* round down to next 4 kB limit */
335         addr &= ~(4096 - 1);
336         debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
337
338 #ifdef CONFIG_LCD
339         /* reserve memory for LCD display (always full pages) */
340         addr = lcd_setmem (addr);
341         gd->fb_base = addr;
342 #endif /* CONFIG_LCD */
343
344         /*
345          * reserve memory for U-Boot code, data & bss
346          * round down to next 4 kB limit
347          */
348         addr -= len;
349         addr &= ~(4096 - 1);
350
351         debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
352
353         /*
354          * reserve memory for malloc() arena
355          */
356         addr_sp = addr - TOTAL_MALLOC_LEN;
357         debug ("Reserving %dk for malloc() at: %08lx\n",
358                         TOTAL_MALLOC_LEN >> 10, addr_sp);
359
360         /*
361          * (permanently) allocate a Board Info struct
362          * and a permanent copy of the "global" data
363          */
364         addr_sp -= sizeof (bd_t);
365         bd = (bd_t *) addr_sp;
366         gd->bd = bd;
367         debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
368                         sizeof (bd_t), addr_sp);
369         addr_sp -= sizeof (gd_t);
370         id = (gd_t *) addr_sp;
371         debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
372                         sizeof (gd_t), addr_sp);
373
374         /* Reserve memory for boot params. */
375         addr_sp -= CFG_BOOTPARAMS_LEN;
376         bd->bi_boot_params = addr_sp;
377         debug ("Reserving %dk for boot parameters at: %08lx\n",
378                         CFG_BOOTPARAMS_LEN >> 10, addr_sp);
379
380         /*
381          * Finally, we set up a new (bigger) stack.
382          *
383          * Leave some safety gap for SP, force alignment on 16 byte boundary
384          * Clear initial stack frame
385          */
386         addr_sp -= 16;
387         addr_sp &= ~0xF;
388
389         paddr = (ulong *)addr_sp;
390         *paddr-- = 0;
391         *paddr-- = 0;
392         addr_sp = (ulong)paddr;
393
394         debug ("Stack Pointer at: %08lx\n", addr_sp);
395
396         /*
397          * Save local variables to board info struct
398          */
399         bd->bi_memstart  = CFG_SDRAM_BASE;      /* start of  DRAM memory      */
400         bd->bi_memsize   = gd->ram_size;        /* size  of  DRAM memory in bytes */
401 #ifdef CFG_INIT_RAM_ADDR
402         bd->bi_sramstart = CFG_INIT_RAM_ADDR;   /* start of  SRAM memory        */
403         bd->bi_sramsize  = CFG_INIT_RAM_END;    /* size  of  SRAM memory        */
404 #endif
405         bd->bi_mbar_base = CFG_MBAR;            /* base of internal registers */
406
407         bd->bi_bootflags = bootflag;            /* boot / reboot flag (for LynxOS)    */
408
409         WATCHDOG_RESET ();
410         bd->bi_intfreq = gd->cpu_clk;   /* Internal Freq, in Hz */
411         bd->bi_busfreq = gd->bus_clk;   /* Bus Freq,      in Hz */
412 #ifdef CONFIG_PCI
413         bd->bi_pcifreq = gd->pci_clk;           /* PCI Freq in Hz */
414 #endif
415 #ifdef CONFIG_EXTRA_CLOCK
416         bd->bi_inpfreq = gd->inp_clk;           /* input Freq in Hz */
417         bd->bi_vcofreq = gd->vco_clk;           /* vco Freq in Hz */
418         bd->bi_flbfreq = gd->flb_clk;           /* flexbus Freq in Hz */
419 #endif
420         bd->bi_baudrate = gd->baudrate; /* Console Baudrate     */
421
422 #ifdef CFG_EXTBDINFO
423         strncpy (bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
424         strncpy (bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
425 #endif
426
427         WATCHDOG_RESET ();
428
429 #ifdef CONFIG_POST
430         post_bootmode_init();
431         post_run (NULL, POST_ROM | post_bootmode_get(0));
432 #endif
433
434         WATCHDOG_RESET();
435
436         memcpy (id, (void *)gd, sizeof (gd_t));
437
438         debug ("Start relocate of code from %08x to %08lx\n", CFG_MONITOR_BASE, addr);
439         relocate_code (addr_sp, id, addr);
440
441         /* NOTREACHED - jump_to_ram() does not return */
442 }
443
444 /************************************************************************
445  *
446  * This is the next part if the initialization sequence: we are now
447  * running from RAM and have a "normal" C environment, i. e. global
448  * data can be written, BSS has been cleared, the stack size in not
449  * that critical any more, etc.
450  *
451  ************************************************************************
452  */
453 void board_init_r (gd_t *id, ulong dest_addr)
454 {
455         cmd_tbl_t *cmdtp;
456         char *s, *e;
457         bd_t *bd;
458         int i;
459         extern void malloc_bin_reloc (void);
460
461 #ifndef CFG_ENV_IS_NOWHERE
462         extern char * env_name_spec;
463 #endif
464 #ifndef CFG_NO_FLASH
465         ulong flash_size;
466 #endif
467         gd = id;                /* initialize RAM version of global data */
468         bd = gd->bd;
469
470         gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
471
472 #ifdef CONFIG_SERIAL_MULTI
473         serial_initialize();
474 #endif
475
476         debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
477
478         WATCHDOG_RESET ();
479
480         gd->reloc_off =  dest_addr - CFG_MONITOR_BASE;
481
482         monitor_flash_len = (ulong)&__init_end - dest_addr;
483
484         /*
485          * We have to relocate the command table manually
486          */
487         for (cmdtp = &__u_boot_cmd_start; cmdtp !=  &__u_boot_cmd_end; cmdtp++) {
488                 ulong addr;
489                 addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
490 #if 0
491                 printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
492                                 cmdtp->name, (ulong) (cmdtp->cmd), addr);
493 #endif
494                 cmdtp->cmd =
495                         (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
496
497                 addr = (ulong)(cmdtp->name) + gd->reloc_off;
498                 cmdtp->name = (char *)addr;
499
500                 if (cmdtp->usage) {
501                         addr = (ulong)(cmdtp->usage) + gd->reloc_off;
502                         cmdtp->usage = (char *)addr;
503                 }
504 #ifdef  CFG_LONGHELP
505                 if (cmdtp->help) {
506                         addr = (ulong)(cmdtp->help) + gd->reloc_off;
507                         cmdtp->help = (char *)addr;
508                 }
509 #endif
510         }
511         /* there are some other pointer constants we must deal with */
512 #ifndef CFG_ENV_IS_NOWHERE
513         env_name_spec += gd->reloc_off;
514 #endif
515
516         WATCHDOG_RESET ();
517
518 #ifdef CONFIG_LOGBUFFER
519         logbuff_init_ptrs ();
520 #endif
521 #ifdef CONFIG_POST
522         post_output_backlog ();
523         post_reloc ();
524 #endif
525         WATCHDOG_RESET();
526
527 #if 0
528         /* instruction cache enabled in cpu_init_f() for faster relocation */
529         icache_enable ();       /* it's time to enable the instruction cache */
530 #endif
531
532         /*
533          * Setup trap handlers
534          */
535         trap_init (CFG_SDRAM_BASE);
536
537 #if !defined(CFG_NO_FLASH)
538         puts ("FLASH: ");
539
540         if ((flash_size = flash_init ()) > 0) {
541 # ifdef CFG_FLASH_CHECKSUM
542                 print_size (flash_size, "");
543                 /*
544                  * Compute and print flash CRC if flashchecksum is set to 'y'
545                  *
546                  * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
547                  */
548                 s = getenv ("flashchecksum");
549                 if (s && (*s == 'y')) {
550                         printf ("  CRC: %08lX",
551                                         crc32 (0,
552                                                    (const unsigned char *) CFG_FLASH_BASE,
553                                                    flash_size)
554                                         );
555                 }
556                 putc ('\n');
557 # else  /* !CFG_FLASH_CHECKSUM */
558                 print_size (flash_size, "\n");
559 # endif /* CFG_FLASH_CHECKSUM */
560         } else {
561                 puts (failed);
562                 hang ();
563         }
564
565         bd->bi_flashstart = CFG_FLASH_BASE;     /* update start of FLASH memory    */
566         bd->bi_flashsize = flash_size;  /* size of FLASH memory (final value) */
567         bd->bi_flashoffset = 0;
568 #else   /* CFG_NO_FLASH */
569         bd->bi_flashsize = 0;
570         bd->bi_flashstart = 0;
571         bd->bi_flashoffset = 0;
572 #endif /* !CFG_NO_FLASH */
573
574         WATCHDOG_RESET ();
575
576         /* initialize higher level parts of CPU like time base and timers */
577         cpu_init_r ();
578
579         WATCHDOG_RESET ();
580
581         /* initialize malloc() area */
582         mem_malloc_init ();
583         malloc_bin_reloc ();
584
585 #ifdef CONFIG_SPI
586 # if !defined(CFG_ENV_IS_IN_EEPROM)
587         spi_init_f ();
588 # endif
589         spi_init_r ();
590 #endif
591
592         /* relocate environment function pointers etc. */
593         env_relocate ();
594
595         /*
596          * Fill in missing fields of bd_info.
597          * We do this here, where we have "normal" access to the
598          * environment; we used to do this still running from ROM,
599          * where had to use getenv_r(), which can be pretty slow when
600          * the environment is in EEPROM.
601          */
602         s = getenv ("ethaddr");
603         for (i = 0; i < 6; ++i) {
604                 bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
605                 if (s)
606                         s = (*e) ? e + 1 : e;
607         }
608 #ifdef CONFIG_HAS_ETH1
609         /* handle the 2nd ethernet address */
610
611         s = getenv ("eth1addr");
612         for (i = 0; i < 6; ++i) {
613                 bd->bi_enet1addr[i] = s ? simple_strtoul (s, &e, 16) : 0;
614                 if (s)
615                         s = (*e) ? e + 1 : e;
616         }
617 #endif
618 #ifdef CONFIG_HAS_ETH2
619         /* handle the 3rd ethernet address */
620
621         s = getenv ("eth2addr");
622         for (i = 0; i < 6; ++i) {
623                 bd->bi_enet2addr[i] = s ? simple_strtoul (s, &e, 16) : 0;
624                 if (s)
625                         s = (*e) ? e + 1 : e;
626         }
627 #endif
628
629 #ifdef CONFIG_HAS_ETH3
630         /* handle 4th ethernet address */
631         s = getenv("eth3addr");
632         for (i = 0; i < 6; ++i) {
633                 bd->bi_enet3addr[i] = s ? simple_strtoul (s, &e, 16) : 0;
634                 if (s)
635                         s = (*e) ? e + 1 : e;
636         }
637 #endif
638
639         /* IP Address */
640         bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
641
642         WATCHDOG_RESET ();
643
644 #if defined(CONFIG_PCI)
645         /*
646          * Do pci configuration
647          */
648         pci_init ();
649 #endif
650
651         /** leave this here (after malloc(), environment and PCI are working) **/
652         /* Initialize devices */
653         devices_init ();
654
655         /* Initialize the jump table for applications */
656         jumptable_init ();
657
658         /* Initialize the console (after the relocation and devices init) */
659         console_init_r ();
660
661 #if defined(CONFIG_MISC_INIT_R)
662         /* miscellaneous platform dependent initialisations */
663         misc_init_r ();
664 #endif
665
666 #if defined(CONFIG_CMD_KGDB)
667         WATCHDOG_RESET ();
668         puts ("KGDB:  ");
669         kgdb_init ();
670 #endif
671
672         debug ("U-Boot relocated to %08lx\n", dest_addr);
673
674         /*
675          * Enable Interrupts
676          */
677         interrupt_init ();
678
679         /* Must happen after interrupts are initialized since
680          * an irq handler gets installed
681          */
682         timer_init();
683
684 #ifdef CONFIG_SERIAL_SOFTWARE_FIFO
685         serial_buffered_init();
686 #endif
687
688 #ifdef CONFIG_STATUS_LED
689         status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
690 #endif
691
692         udelay (20);
693
694         set_timer (0);
695
696         /* Insert function pointers now that we have relocated the code */
697
698         /* Initialize from environment */
699         if ((s = getenv ("loadaddr")) != NULL) {
700                 load_addr = simple_strtoul (s, NULL, 16);
701         }
702 #if defined(CONFIG_CMD_NET)
703         if ((s = getenv ("bootfile")) != NULL) {
704                 copy_filename (BootFile, s, sizeof (BootFile));
705         }
706 #endif
707
708         WATCHDOG_RESET ();
709
710 #if defined(CONFIG_CMD_DOC)
711         WATCHDOG_RESET ();
712         puts ("DOC:   ");
713         doc_init ();
714 #endif
715
716 #if defined(CONFIG_CMD_NAND)
717         WATCHDOG_RESET ();
718         puts ("NAND:  ");
719         nand_init();            /* go init the NAND */
720 #endif
721
722 #if defined(CONFIG_CMD_NET)
723         WATCHDOG_RESET();
724 #if defined(FEC_ENET)
725         eth_init(bd);
726 #endif
727 #if defined(CONFIG_NET_MULTI)
728         puts ("Net:   ");
729         eth_initialize (bd);
730 #endif
731 #endif
732
733 #ifdef CONFIG_POST
734         post_run (NULL, POST_RAM | post_bootmode_get(0));
735 #endif
736
737 #if defined(CONFIG_CMD_PCMCIA) \
738     && !defined(CONFIG_CMD_IDE)
739         WATCHDOG_RESET ();
740         puts ("PCMCIA:");
741         pcmcia_init ();
742 #endif
743
744 #if defined(CONFIG_CMD_IDE)
745         WATCHDOG_RESET ();
746         puts ("IDE:   ");
747         ide_init ();
748 #endif
749
750 #ifdef CONFIG_LAST_STAGE_INIT
751         WATCHDOG_RESET ();
752         /*
753          * Some parts can be only initialized if all others (like
754          * Interrupts) are up and running (i.e. the PC-style ISA
755          * keyboard).
756          */
757         last_stage_init ();
758 #endif
759
760 #if defined(CONFIG_CMD_BEDBUG)
761         WATCHDOG_RESET ();
762         bedbug_init ();
763 #endif
764
765 #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
766         /*
767          * Export available size of memory for Linux,
768          * taking into account the protected RAM at top of memory
769          */
770         {
771                 ulong pram;
772                 char memsz[32];
773 #ifdef CONFIG_PRAM
774                 char *s;
775
776                 if ((s = getenv ("pram")) != NULL) {
777                         pram = simple_strtoul (s, NULL, 10);
778                 } else {
779                         pram = CONFIG_PRAM;
780                 }
781 #else
782                 pram=0;
783 #endif
784 #ifdef CONFIG_LOGBUFFER
785                 /* Also take the logbuffer into account (pram is in kB) */
786                 pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
787 #endif
788                 sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
789                 setenv ("mem", memsz);
790         }
791 #endif
792
793 #ifdef CONFIG_MODEM_SUPPORT
794  {
795          extern int do_mdm_init;
796          do_mdm_init = gd->do_mdm_init;
797  }
798 #endif
799
800 #ifdef CONFIG_WATCHDOG
801         /* disable watchdog if environment is set */
802         if ((s = getenv ("watchdog")) != NULL) {
803                 if (strncmp (s, "off", 3) == 0) {
804                         WATCHDOG_DISABLE ();
805                 }
806         }
807 #endif /* CONFIG_WATCHDOG*/
808
809
810         /* Initialization complete - start the monitor */
811
812         /* main_loop() can return to retry autoboot, if so just run it again. */
813         for (;;) {
814                 WATCHDOG_RESET ();
815                 main_loop ();
816         }
817
818         /* NOTREACHED - no way out of command loop except booting */
819 }
820
821
822 void hang(void)
823 {
824         puts ("### ERROR ### Please RESET the board ###\n");
825         for (;;);
826 }