blob: a11288d4307d57bdc476ea5210b71955ed764106 [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*
2 * (C) Copyright 2000-2002
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 <watchdog.h>
26#include <command.h>
27#include <malloc.h>
28#include <devices.h>
29#include <syscall.h>
30#ifdef CONFIG_8xx
31#include <mpc8xx.h>
32#endif
wdenk0db5bca2003-03-31 17:27:09 +000033#ifdef CONFIG_5xx
34#include <mpc5xx.h>
35#endif
wdenkfe8c2802002-11-03 00:38:21 +000036#if (CONFIG_COMMANDS & CFG_CMD_IDE)
37#include <ide.h>
38#endif
39#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
40#include <scsi.h>
41#endif
42#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
43#include <kgdb.h>
44#endif
45#ifdef CONFIG_STATUS_LED
46#include <status_led.h>
47#endif
48#include <net.h>
49#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
50#include <cmd_bedbug.h>
51#endif
52#ifdef CFG_ALLOC_DPRAM
wdenk7aa78612003-05-03 15:50:43 +000053#if !defined(CONFIG_8260)
wdenkfe8c2802002-11-03 00:38:21 +000054#include <commproc.h>
55#endif
wdenk7aa78612003-05-03 15:50:43 +000056#endif
wdenkfe8c2802002-11-03 00:38:21 +000057#include <version.h>
58#if defined(CONFIG_BAB7xx)
59#include <w83c553f.h>
60#endif
61#include <dtt.h>
62#if defined(CONFIG_POST)
63#include <post.h>
64#endif
wdenk56f94be2002-11-05 16:35:14 +000065#if defined(CONFIG_LOGBUFFER)
66#include <logbuff.h>
67#endif
wdenkfe8c2802002-11-03 00:38:21 +000068
69#if (CONFIG_COMMANDS & CFG_CMD_DOC)
70void doc_init (void);
71#endif
72#if defined(CONFIG_HARD_I2C) || \
73 defined(CONFIG_SOFT_I2C)
74#include <i2c.h>
75#endif
76
77static char *failed = "*** failed ***\n";
78
79#if defined(CONFIG_PCU_E) || defined(CONFIG_OXC)
80extern flash_info_t flash_info[];
81#endif
82
83#include <environment.h>
84
85#if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < CFG_MONITOR_BASE) || \
86 (CFG_ENV_ADDR >= (CFG_MONITOR_BASE + CFG_MONITOR_LEN)) ) || \
87 defined(CFG_ENV_IS_IN_NVRAM)
88#define TOTAL_MALLOC_LEN (CFG_MALLOC_LEN + CFG_ENV_SIZE)
89#else
90#define TOTAL_MALLOC_LEN CFG_MALLOC_LEN
91#endif
92
93/*
94 * Begin and End of memory area for malloc(), and current "brk"
95 */
96static ulong mem_malloc_start = 0;
97static ulong mem_malloc_end = 0;
98static ulong mem_malloc_brk = 0;
99
100/************************************************************************
101 * Utilities *
102 ************************************************************************
103 */
104
105/*
106 * The Malloc area is immediately below the monitor copy in DRAM
107 */
108static void mem_malloc_init (void)
109{
110 DECLARE_GLOBAL_DATA_PTR;
111
112 ulong dest_addr = CFG_MONITOR_BASE + gd->reloc_off;
113
114 mem_malloc_end = dest_addr;
115 mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN;
116 mem_malloc_brk = mem_malloc_start;
117
118 memset ((void *) mem_malloc_start,
119 0,
120 mem_malloc_end - mem_malloc_start);
121}
122
123void *sbrk (ptrdiff_t increment)
124{
125 ulong old = mem_malloc_brk;
126 ulong new = old + increment;
127
128 if ((new < mem_malloc_start) || (new > mem_malloc_end)) {
129 return (NULL);
130 }
131 mem_malloc_brk = new;
132 return ((void *) old);
133}
134
135char *strmhz (char *buf, long hz)
136{
137 long l, n;
138 long m;
139
140 n = hz / 1000000L;
141 l = sprintf (buf, "%ld", n);
142 m = (hz % 1000000L) / 1000L;
143 if (m != 0)
144 sprintf (buf + l, ".%03ld", m);
145 return (buf);
146}
147
148static void syscalls_init (void)
149{
150 ulong *addr;
151
152 syscall_tbl[SYSCALL_MALLOC] = (void *) malloc;
153 syscall_tbl[SYSCALL_FREE] = (void *) free;
154
155 syscall_tbl[SYSCALL_INSTALL_HDLR] = (void *) irq_install_handler;
156 syscall_tbl[SYSCALL_FREE_HDLR] = (void *) irq_free_handler;
wdenkc7de8292002-11-19 11:04:11 +0000157 syscall_tbl[SYSCALL_GET_TIMER] = (void *)get_timer;
158 syscall_tbl[SYSCALL_UDELAY] = (void *)udelay;
wdenkfe8c2802002-11-03 00:38:21 +0000159
160 addr = (ulong *) 0xc00; /* syscall ISR addr */
161
162 /* patch ISR code */
163 *addr++ |= (ulong) syscall_tbl >> 16;
164 *addr++ |= (ulong) syscall_tbl & 0xFFFF;
165 *addr++ |= NR_SYSCALLS >> 16;
166 *addr++ |= NR_SYSCALLS & 0xFFFF;
167
wdenk0db5bca2003-03-31 17:27:09 +0000168#ifndef CONFIG_5XX
wdenkfe8c2802002-11-03 00:38:21 +0000169 flush_cache (0x0C00, 0x10);
wdenk0db5bca2003-03-31 17:27:09 +0000170#endif
wdenk7c7a23b2002-12-07 00:20:59 +0000171 /* Initialize syscalls stack pointer */
172 addr = (ulong *) 0xCFC;
173 *addr = (ulong)addr;
wdenk0db5bca2003-03-31 17:27:09 +0000174#ifndef CONFIG_5xx
wdenk7c7a23b2002-12-07 00:20:59 +0000175 flush_cache ((ulong)addr, 0x10);
wdenk0db5bca2003-03-31 17:27:09 +0000176#endif
wdenkfe8c2802002-11-03 00:38:21 +0000177}
178
179/*
180 * All attempts to come up with a "common" initialization sequence
181 * that works for all boards and architectures failed: some of the
182 * requirements are just _too_ different. To get rid of the resulting
183 * mess of board dependend #ifdef'ed code we now make the whole
184 * initialization sequence configurable to the user.
185 *
186 * The requirements for any new initalization function is simple: it
187 * receives a pointer to the "global data" structure as it's only
188 * argument, and returns an integer return code, where 0 means
189 * "continue" and != 0 means "fatal error, hang the system".
190 */
191typedef int (init_fnc_t) (void);
192
193/************************************************************************
194 * Init Utilities *
195 ************************************************************************
196 * Some of this code should be moved into the core functions,
197 * but let's get it working (again) first...
198 */
199
200static int init_baudrate (void)
201{
202 DECLARE_GLOBAL_DATA_PTR;
203
204 uchar tmp[64]; /* long enough for environment variables */
205 int i = getenv_r ("baudrate", tmp, sizeof (tmp));
206
207 gd->baudrate = (i > 0)
208 ? (int) simple_strtoul (tmp, NULL, 10)
209 : CONFIG_BAUDRATE;
wdenkfe8c2802002-11-03 00:38:21 +0000210 return (0);
211}
212
213/***********************************************************************/
214
215static int init_func_ram (void)
216{
217 DECLARE_GLOBAL_DATA_PTR;
218
219#ifdef CONFIG_BOARD_TYPES
220 int board_type = gd->board_type;
221#else
222 int board_type = 0; /* use dummy arg */
223#endif
224 puts ("DRAM: ");
225
226 if ((gd->ram_size = initdram (board_type)) > 0) {
227 print_size (gd->ram_size, "\n");
228 return (0);
229 }
230 puts (failed);
231 return (1);
232}
233
234/***********************************************************************/
235
236#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
237static int init_func_i2c (void)
238{
239 puts ("I2C: ");
240 i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
241 puts ("ready\n");
242 return (0);
243}
244#endif
245
246/***********************************************************************/
247
248#if defined(CONFIG_WATCHDOG)
249static int init_func_watchdog_init (void)
250{
251 puts (" Watchdog enabled\n");
252 WATCHDOG_RESET ();
253 return (0);
254}
255# define INIT_FUNC_WATCHDOG_INIT init_func_watchdog_init,
256
257static int init_func_watchdog_reset (void)
258{
259 WATCHDOG_RESET ();
260 return (0);
261}
262# define INIT_FUNC_WATCHDOG_RESET init_func_watchdog_reset,
263#else
264# define INIT_FUNC_WATCHDOG_INIT /* undef */
265# define INIT_FUNC_WATCHDOG_RESET /* undef */
266#endif /* CONFIG_WATCHDOG */
267
268/************************************************************************
269 * Initialization sequence *
270 ************************************************************************
271 */
272
273init_fnc_t *init_sequence[] = {
274
275#if defined(CONFIG_BOARD_PRE_INIT)
276 board_pre_init, /* very early board init code (fpga boot, etc.) */
277#endif
278
279 get_clocks, /* get CPU and bus clocks (etc.) */
280 init_timebase,
281#ifdef CFG_ALLOC_DPRAM
wdenk7aa78612003-05-03 15:50:43 +0000282#if !defined(CONFIG_8260)
wdenkfe8c2802002-11-03 00:38:21 +0000283 dpram_init,
284#endif
wdenk7aa78612003-05-03 15:50:43 +0000285#endif
wdenkfe8c2802002-11-03 00:38:21 +0000286#if defined(CONFIG_BOARD_POSTCLK_INIT)
287 board_postclk_init,
288#endif
289 env_init,
290 init_baudrate,
291 serial_init,
292 console_init_f,
293 display_options,
294#if defined(CONFIG_8260)
295 prt_8260_rsr,
296 prt_8260_clks,
297#endif /* CONFIG_8260 */
298 checkcpu,
299 checkboard,
300 INIT_FUNC_WATCHDOG_INIT
301#if defined(CONFIG_BMW) || \
302 defined(CONFIG_COGENT) || \
303 defined(CONFIG_HYMOD) || \
304 defined(CONFIG_RSD_PROTO) || \
305 defined(CONFIG_W7O)
306 misc_init_f,
307#endif
308 INIT_FUNC_WATCHDOG_RESET
309#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
310 init_func_i2c,
311#endif
312#if defined(CONFIG_DTT) /* Digital Thermometers and Thermostats */
313 dtt_init,
314#endif
wdenk4532cb62003-04-27 22:52:51 +0000315#ifdef CONFIG_POST
316 post_init_f,
317#endif
wdenkfe8c2802002-11-03 00:38:21 +0000318 INIT_FUNC_WATCHDOG_RESET
319 init_func_ram,
320#if defined(CFG_DRAM_TEST)
321 testdram,
322#endif /* CFG_DRAM_TEST */
323 INIT_FUNC_WATCHDOG_RESET
324
325 NULL, /* Terminate this list */
326};
327
328/************************************************************************
329 *
330 * This is the first part of the initialization sequence that is
331 * implemented in C, but still running from ROM.
332 *
333 * The main purpose is to provide a (serial) console interface as
334 * soon as possible (so we can see any error messages), and to
335 * initialize the RAM so that we can relocate the monitor code to
336 * RAM.
337 *
338 * Be aware of the restrictions: global data is read-only, BSS is not
339 * initialized, and stack space is limited to a few kB.
340 *
341 ************************************************************************
342 */
343
344void board_init_f (ulong bootflag)
345{
346 DECLARE_GLOBAL_DATA_PTR;
347
348 bd_t *bd;
349 ulong len, addr, addr_sp;
350 gd_t *id;
351 init_fnc_t **init_fnc_ptr;
352#ifdef CONFIG_PRAM
353 int i;
354 ulong reg;
355 uchar tmp[64]; /* long enough for environment variables */
356#endif
357
358 /* Pointer is writable since we allocated a register for it */
359 gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
360
361#ifndef CONFIG_8260
362 /* Clear initial global data */
363 memset ((void *) gd, 0, sizeof (gd_t));
364#endif
365
366 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
367 if ((*init_fnc_ptr) () != 0) {
368 hang ();
369 }
370 }
371
372 /*
373 * Now that we have DRAM mapped and working, we can
374 * relocate the code and continue running from DRAM.
375 *
376 * Reserve memory at end of RAM for (top down in that order):
wdenk228f29a2002-12-08 09:53:23 +0000377 * - kernel log buffer
wdenkfe8c2802002-11-03 00:38:21 +0000378 * - protected RAM
379 * - LCD framebuffer
380 * - monitor code
381 * - board info struct
382 */
383 len = get_endaddr () - CFG_MONITOR_BASE;
384
385 if (len > CFG_MONITOR_LEN) {
386 printf ("*** U-Boot size %ld > reserved memory (%d)\n",
387 len, CFG_MONITOR_LEN);
388 hang ();
389 }
390
391 if (CFG_MONITOR_LEN > len)
392 len = CFG_MONITOR_LEN;
393
394#ifndef CONFIG_VERY_BIG_RAM
395 addr = CFG_SDRAM_BASE + gd->ram_size;
396#else
397 /* only allow stack below 256M */
398 addr = CFG_SDRAM_BASE +
399 (gd->ram_size > 256 << 20) ? 256 << 20 : gd->ram_size;
400#endif
401
wdenk228f29a2002-12-08 09:53:23 +0000402#ifdef CONFIG_LOGBUFFER
403 /* reserve kernel log buffer */
404 addr -= (LOGBUFF_RESERVE);
405# ifdef DEBUG
406 printf ("Reserving %ldk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
407# endif
408#endif
409
wdenkfe8c2802002-11-03 00:38:21 +0000410#ifdef CONFIG_PRAM
411 /*
412 * reserve protected RAM
413 */
414 i = getenv_r ("pram", tmp, sizeof (tmp));
415 reg = (i > 0) ? simple_strtoul (tmp, NULL, 10) : CONFIG_PRAM;
416 addr -= (reg << 10); /* size is in kB */
417# ifdef DEBUG
418 printf ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
419# endif
420#endif /* CONFIG_PRAM */
421
422 /* round down to next 4 kB limit */
423 addr &= ~(4096 - 1);
424#ifdef DEBUG
425 printf ("Top of RAM usable for U-Boot at: %08lx\n", addr);
426#endif
427
428#ifdef CONFIG_LCD
429 /* reserve memory for LCD display (always full pages) */
430 addr = lcd_setmem (addr);
431 gd->fb_base = addr;
432#endif /* CONFIG_LCD */
433
434#if defined(CONFIG_VIDEO) && defined(CONFIG_8xx)
435 /* reserve memory for video display (always full pages) */
436 addr = video_setmem (addr);
437 gd->fb_base = addr;
438#endif /* CONFIG_VIDEO */
439
440 /*
441 * reserve memory for U-Boot code, data & bss
442 * round down to next 4 kB limit
443 */
444 addr -= len;
445 addr &= ~(4096 - 1);
446
447#ifdef DEBUG
448 printf ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
449#endif
450
wdenkc7de8292002-11-19 11:04:11 +0000451#ifdef CONFIG_AMIGAONEG3SE
452 gd->relocaddr = addr;
453#endif
454
wdenkfe8c2802002-11-03 00:38:21 +0000455 /*
456 * reserve memory for malloc() arena
457 */
458 addr_sp = addr - TOTAL_MALLOC_LEN;
459#ifdef DEBUG
460 printf ("Reserving %dk for malloc() at: %08lx\n",
461 TOTAL_MALLOC_LEN >> 10, addr_sp);
462#endif
463
464 /*
465 * (permanently) allocate a Board Info struct
466 * and a permanent copy of the "global" data
467 */
468 addr_sp -= sizeof (bd_t);
469 bd = (bd_t *) addr_sp;
470 gd->bd = bd;
471#ifdef DEBUG
472 printf ("Reserving %d Bytes for Board Info at: %08lx\n",
473 sizeof (bd_t), addr_sp);
474#endif
475 addr_sp -= sizeof (gd_t);
476 id = (gd_t *) addr_sp;
477#ifdef DEBUG
478 printf ("Reserving %d Bytes for Global Data at: %08lx\n",
479 sizeof (gd_t), addr_sp);
480#endif
481
482 /*
483 * Finally, we set up a new (bigger) stack.
484 *
485 * Leave some safety gap for SP, force alignment on 16 byte boundary
486 * Clear initial stack frame
487 */
488 addr_sp -= 16;
489 addr_sp &= ~0xF;
490 *((ulong *) addr_sp)-- = 0;
491 *((ulong *) addr_sp)-- = 0;
492#ifdef DEBUG
493 printf ("Stack Pointer at: %08lx\n", addr_sp);
494#endif
495
496 /*
497 * Save local variables to board info struct
498 */
499
500 bd->bi_memstart = CFG_SDRAM_BASE; /* start of DRAM memory */
501 bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */
502
503#ifdef CONFIG_IP860
504 bd->bi_sramstart = SRAM_BASE; /* start of SRAM memory */
505 bd->bi_sramsize = SRAM_SIZE; /* size of SRAM memory */
506#else
507 bd->bi_sramstart = 0; /* FIXME */ /* start of SRAM memory */
508 bd->bi_sramsize = 0; /* FIXME */ /* size of SRAM memory */
509#endif
510
wdenk0db5bca2003-03-31 17:27:09 +0000511#if defined(CONFIG_8xx) || defined(CONFIG_8260) || defined(CONFIG_5xx)
wdenkfe8c2802002-11-03 00:38:21 +0000512 bd->bi_immr_base = CFG_IMMR; /* base of IMMR register */
513#endif
514
515 bd->bi_bootflags = bootflag; /* boot / reboot flag (for LynxOS) */
516
517 WATCHDOG_RESET ();
518 bd->bi_intfreq = gd->cpu_clk; /* Internal Freq, in Hz */
519 bd->bi_busfreq = gd->bus_clk; /* Bus Freq, in Hz */
520#if defined(CONFIG_8260)
521 bd->bi_cpmfreq = gd->cpm_clk;
522 bd->bi_brgfreq = gd->brg_clk;
523 bd->bi_sccfreq = gd->scc_clk;
524 bd->bi_vco = gd->vco_out;
525#endif /* CONFIG_8260 */
526
527 bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
528
529#ifdef CFG_EXTBDINFO
530 strncpy (bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
531 strncpy (bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
532
533 bd->bi_procfreq = gd->cpu_clk; /* Processor Speed, In Hz */
534 bd->bi_plb_busfreq = gd->bus_clk;
535#ifdef CONFIG_405GP
536 bd->bi_pci_busfreq = get_PCI_freq ();
537#endif
538#endif
539
540#ifdef DEBUG
541 printf ("New Stack Pointer is: %08lx\n", addr_sp);
542#endif
543
544 WATCHDOG_RESET ();
545
546#ifdef CONFIG_POST
547 post_bootmode_init();
548 post_run (NULL, POST_ROM | post_bootmode_get(0));
549#endif
550
551 WATCHDOG_RESET();
552
553 memcpy (id, gd, sizeof (gd_t));
554
555 relocate_code (addr_sp, id, addr);
556
557 /* NOTREACHED - relocate_code() does not return */
558}
559
560
561/************************************************************************
562 *
563 * This is the next part if the initialization sequence: we are now
564 * running from RAM and have a "normal" C environment, i. e. global
565 * data can be written, BSS has been cleared, the stack size in not
566 * that critical any more, etc.
567 *
568 ************************************************************************
569 */
570
571void board_init_r (gd_t *id, ulong dest_addr)
572{
573 DECLARE_GLOBAL_DATA_PTR;
574
575 cmd_tbl_t *cmdtp;
576 char *s, *e;
577 bd_t *bd;
578 int i;
579 extern void malloc_bin_reloc (void);
580#ifndef CFG_ENV_IS_NOWHERE
581 extern char * env_name_spec;
582#endif
583
584#ifndef CFG_NO_FLASH
585 ulong flash_size;
586#endif
587
588 gd = id; /* initialize RAM version of global data */
589 bd = gd->bd;
590
591 gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
592
593#ifdef DEBUG
594 printf ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
595#endif
596
597 WATCHDOG_RESET ();
598
599 gd->reloc_off = dest_addr - CFG_MONITOR_BASE;
600
601 /*
602 * We have to relocate the command table manually
603 */
604 for (cmdtp = &cmd_tbl[0]; cmdtp->name; cmdtp++) {
605 ulong addr;
606
607 addr = (ulong) (cmdtp->cmd) + gd->reloc_off;
608#if 0
609 printf ("Command \"%s\": 0x%08lx => 0x%08lx\n",
610 cmdtp->name, (ulong) (cmdtp->cmd), addr);
611#endif
612 cmdtp->cmd =
613 (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr;
614
615 addr = (ulong)(cmdtp->name) + gd->reloc_off;
616 cmdtp->name = (char *)addr;
617
618 if (cmdtp->usage) {
619 addr = (ulong)(cmdtp->usage) + gd->reloc_off;
620 cmdtp->usage = (char *)addr;
621 }
622#ifdef CFG_LONGHELP
623 if (cmdtp->help) {
624 addr = (ulong)(cmdtp->help) + gd->reloc_off;
625 cmdtp->help = (char *)addr;
626 }
627#endif
628 }
629 /* there are some other pointer constants we must deal with */
630#ifndef CFG_ENV_IS_NOWHERE
631 env_name_spec += gd->reloc_off;
632#endif
633
634 WATCHDOG_RESET ();
635
wdenk56f94be2002-11-05 16:35:14 +0000636#ifdef CONFIG_LOGBUFFER
wdenk228f29a2002-12-08 09:53:23 +0000637 logbuff_init_ptrs ();
wdenk56f94be2002-11-05 16:35:14 +0000638#endif
wdenkfe8c2802002-11-03 00:38:21 +0000639#ifdef CONFIG_POST
wdenk228f29a2002-12-08 09:53:23 +0000640 post_output_backlog ();
wdenkfe8c2802002-11-03 00:38:21 +0000641 post_reloc ();
642#endif
643
644 WATCHDOG_RESET();
645
646#if defined(CONFIG_IP860) || defined(CONFIG_PCU_E) || defined (CONFIG_FLAGADM)
647 icache_enable (); /* it's time to enable the instruction cache */
648#endif
649
wdenk3bac3512003-03-12 10:41:04 +0000650#if defined(CONFIG_BAB7xx) || defined(CONFIG_CPC45)
wdenkfe8c2802002-11-03 00:38:21 +0000651 /*
wdenk3bac3512003-03-12 10:41:04 +0000652 * Do PCI configuration on BAB7xx and CPC45 _before_ the flash
653 * gets initialised, because we need the ISA resp. PCI_to_LOCAL bus
654 * bridge there.
wdenkfe8c2802002-11-03 00:38:21 +0000655 */
656 pci_init ();
wdenk3bac3512003-03-12 10:41:04 +0000657#endif
658#if defined(CONFIG_BAB7xx)
wdenkfe8c2802002-11-03 00:38:21 +0000659 /*
660 * Initialise the ISA bridge
661 */
662 initialise_w83c553f ();
663#endif
664
665 asm ("sync ; isync");
666
667 /*
668 * Setup trap handlers
669 */
670 trap_init (dest_addr);
671
672#if !defined(CFG_NO_FLASH)
673 puts ("FLASH: ");
674
675 if ((flash_size = flash_init ()) > 0) {
676#ifdef CFG_FLASH_CHECKSUM
677 print_size (flash_size, "");
678 /*
679 * Compute and print flash CRC if flashchecksum is set to 'y'
680 *
681 * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
682 */
683 s = getenv ("flashchecksum");
684 if (s && (*s == 'y')) {
685 printf (" CRC: %08lX",
686 crc32 (0,
687 (const unsigned char *) CFG_FLASH_BASE,
688 flash_size)
689 );
690 }
691 putc ('\n');
692#else
693 print_size (flash_size, "\n");
694#endif /* CFG_FLASH_CHECKSUM */
695 } else {
696 puts (failed);
697 hang ();
698 }
699
700 bd->bi_flashstart = CFG_FLASH_BASE; /* update start of FLASH memory */
701 bd->bi_flashsize = flash_size; /* size of FLASH memory (final value) */
702#if defined(CONFIG_PCU_E) || defined(CONFIG_OXC)
703 bd->bi_flashoffset = 0;
704#elif CFG_MONITOR_BASE == CFG_FLASH_BASE
705 bd->bi_flashoffset = CFG_MONITOR_LEN; /* reserved area for startup monitor */
706#else
707 bd->bi_flashoffset = 0;
708#endif
709#else
710
711 bd->bi_flashsize = 0;
712 bd->bi_flashstart = 0;
713 bd->bi_flashoffset = 0;
714#endif /* !CFG_NO_FLASH */
715
716 WATCHDOG_RESET ();
717
718 /* initialize higher level parts of CPU like time base and timers */
719 cpu_init_r ();
720
721 WATCHDOG_RESET ();
722
723 /* initialize malloc() area */
724 mem_malloc_init ();
725 malloc_bin_reloc ();
726
727#ifdef CONFIG_SPI
728# if !defined(CFG_ENV_IS_IN_EEPROM)
729 spi_init_f ();
730# endif
731 spi_init_r ();
732#endif
733
734 /* relocate environment function pointers etc. */
735 env_relocate ();
736
737 /*
738 * Fill in missing fields of bd_info.
739 * We do this here, where we have "normal" access to the
740 * environment; we used to do this still running from ROM,
741 * where had to use getenv_r(), which can be pretty slow when
742 * the environment is in EEPROM.
743 */
744 s = getenv ("ethaddr");
745#if defined (CONFIG_MBX) || defined (CONFIG_RPXCLASSIC) || defined(CONFIG_IAD210)
746 if (s == NULL)
747 board_get_enetaddr (bd->bi_enetaddr);
748 else
749#endif
750 for (i = 0; i < 6; ++i) {
751 bd->bi_enetaddr[i] = s ? simple_strtoul (s, &e, 16) : 0;
752 if (s)
753 s = (*e) ? e + 1 : e;
754 }
755#ifdef CONFIG_HERMES
756 if ((gd->board_type >> 16) == 2)
757 bd->bi_ethspeed = gd->board_type & 0xFFFF;
758 else
759 bd->bi_ethspeed = 0xFFFF;
760#endif
761
762#ifdef CONFIG_NX823
763 load_sernum_ethaddr ();
764#endif
765
766#if defined(CFG_GT_6426x) || defined(CONFIG_PN62)
767 /* handle the 2nd ethernet address */
768
769 s = getenv ("eth1addr");
770
771 for (i = 0; i < 6; ++i) {
772 bd->bi_enet1addr[i] = s ? simple_strtoul (s, &e, 16) : 0;
773 if (s)
774 s = (*e) ? e + 1 : e;
775 }
776#endif
777#if defined(CFG_GT_6426x)
778 /* handle the 3rd ethernet address */
779
780 s = getenv ("eth2addr");
781
782 for (i = 0; i < 6; ++i) {
783 bd->bi_enet2addr[i] = s ? simple_strtoul (s, &e, 16) : 0;
784 if (s)
785 s = (*e) ? e + 1 : e;
786 }
787#endif
788
789
790#if defined(CONFIG_TQM8xxL) || defined(CONFIG_TQM8260) || \
791 defined(CONFIG_CCM)
792 load_sernum_ethaddr ();
793#endif
794 /* IP Address */
795 bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
796
797 WATCHDOG_RESET ();
798
799#if defined(CONFIG_PCI) && !defined(CONFIG_BAB7xx)
800 /*
801 * Do pci configuration
802 */
803 pci_init ();
804#endif
805
806/** leave this here (after malloc(), environment and PCI are working) **/
807 /* Initialize devices */
808 devices_init ();
809
810 /* allocate syscalls table (console_init_r will fill it in */
811 syscall_tbl = (void **) malloc (NR_SYSCALLS * sizeof (void *));
812
813 /* Initialize the console (after the relocation and devices init) */
814 console_init_r ();
815/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
816 syscalls_init ();
817
818#if defined(CONFIG_CCM) || \
819 defined(CONFIG_COGENT) || \
820 defined(CONFIG_CPCI405) || \
821 defined(CONFIG_EVB64260) || \
822 defined(CONFIG_HYMOD) || \
wdenk56f94be2002-11-05 16:35:14 +0000823 defined(CONFIG_KUP4K) || \
wdenkfe8c2802002-11-03 00:38:21 +0000824 defined(CONFIG_LWMON) || \
825 defined(CONFIG_PCU_E) || \
826 defined(CONFIG_W7O) || \
827 defined(CONFIG_MISC_INIT_R)
828 /* miscellaneous platform dependent initialisations */
829 misc_init_r ();
830#endif
831
832#ifdef CONFIG_HERMES
833 if (bd->bi_ethspeed != 0xFFFF)
834 hermes_start_lxt980 ((int) bd->bi_ethspeed);
835#endif
836
837#if (CONFIG_COMMANDS & CFG_CMD_NET) && ( \
838 defined(CONFIG_CCM) || \
wdenk3bac3512003-03-12 10:41:04 +0000839 defined(CONFIG_ELPT860) || \
wdenkfe8c2802002-11-03 00:38:21 +0000840 defined(CONFIG_EP8260) || \
841 defined(CONFIG_IP860) || \
842 defined(CONFIG_IVML24) || \
843 defined(CONFIG_IVMS8) || \
844 defined(CONFIG_LWMON) || \
845 defined(CONFIG_MPC8260ADS) || \
wdenk5d232d02003-05-22 22:52:13 +0000846 defined(CONFIG_MPC8266ADS) || \
wdenkfe8c2802002-11-03 00:38:21 +0000847 defined(CONFIG_PCU_E) || \
848 defined(CONFIG_RPXSUPER) || \
849 defined(CONFIG_SPD823TS) )
850
851 WATCHDOG_RESET ();
852# ifdef DEBUG
853 puts ("Reset Ethernet PHY\n");
854# endif
855 reset_phy ();
856#endif
857
858#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
859 WATCHDOG_RESET ();
860 puts ("KGDB: ");
861 kgdb_init ();
862#endif
863
864#ifdef DEBUG
865 printf ("U-Boot relocated to %08lx\n", dest_addr);
866#endif
867
868 /*
869 * Enable Interrupts
870 */
871 interrupt_init ();
872
873 /* Must happen after interrupts are initialized since
874 * an irq handler gets installed
875 */
876#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
877 serial_buffered_init();
878#endif
879
880#ifdef CONFIG_STATUS_LED
881 status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
882#endif
883
884 udelay (20);
885
886 set_timer (0);
887
888 /* Insert function pointers now that we have relocated the code */
889
890 /* Initialize from environment */
891 if ((s = getenv ("loadaddr")) != NULL) {
892 load_addr = simple_strtoul (s, NULL, 16);
893 }
894#if (CONFIG_COMMANDS & CFG_CMD_NET)
895 if ((s = getenv ("bootfile")) != NULL) {
896 copy_filename (BootFile, s, sizeof (BootFile));
897 }
898#endif /* CFG_CMD_NET */
899
900 WATCHDOG_RESET ();
901
902#if (CONFIG_COMMANDS & CFG_CMD_SCSI)
903 WATCHDOG_RESET ();
904 puts ("SCSI: ");
905 scsi_init ();
906#endif
907
908#if (CONFIG_COMMANDS & CFG_CMD_DOC)
909 WATCHDOG_RESET ();
910 puts ("DOC: ");
911 doc_init ();
912#endif
913
914#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI)
915 WATCHDOG_RESET ();
916 puts ("Net: ");
917 eth_initialize (bd);
918#endif
919
920#ifdef CONFIG_POST
921 post_run (NULL, POST_RAM | post_bootmode_get(0));
922 if (post_bootmode_get(0) & POST_POWERFAIL) {
923 post_bootmode_clear();
924 board_poweroff();
925 }
926#endif
927
928#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) && !(CONFIG_COMMANDS & CFG_CMD_IDE)
929 WATCHDOG_RESET ();
930 puts ("PCMCIA:");
931 pcmcia_init ();
932#endif
933
934#if (CONFIG_COMMANDS & CFG_CMD_IDE)
935 WATCHDOG_RESET ();
936# ifdef CONFIG_IDE_8xx_PCCARD
937 puts ("PCMCIA:");
938# else
939 puts ("IDE: ");
940#endif
941 ide_init ();
942#endif /* CFG_CMD_IDE */
943
944#ifdef CONFIG_LAST_STAGE_INIT
945 WATCHDOG_RESET ();
946 /*
947 * Some parts can be only initialized if all others (like
948 * Interrupts) are up and running (i.e. the PC-style ISA
949 * keyboard).
950 */
951 last_stage_init ();
952#endif
953
954#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
955 WATCHDOG_RESET ();
956 bedbug_init ();
957#endif
958
wdenk228f29a2002-12-08 09:53:23 +0000959#if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
wdenkfe8c2802002-11-03 00:38:21 +0000960 /*
961 * Export available size of memory for Linux,
962 * taking into account the protected RAM at top of memory
963 */
964 {
965 ulong pram;
wdenkfe8c2802002-11-03 00:38:21 +0000966 uchar memsz[32];
wdenk228f29a2002-12-08 09:53:23 +0000967#ifdef CONFIG_PRAM
968 char *s;
wdenkfe8c2802002-11-03 00:38:21 +0000969
970 if ((s = getenv ("pram")) != NULL) {
971 pram = simple_strtoul (s, NULL, 10);
972 } else {
973 pram = CONFIG_PRAM;
974 }
wdenk228f29a2002-12-08 09:53:23 +0000975#else
976 pram=0;
977#endif
978#ifdef CONFIG_LOGBUFFER
979 /* Also take the logbuffer into account (pram is in kB) */
980 pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
981#endif
wdenkfe8c2802002-11-03 00:38:21 +0000982 sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
983 setenv ("mem", memsz);
984 }
985#endif
986
wdenk4532cb62003-04-27 22:52:51 +0000987#ifdef CONFIG_MODEM_SUPPORT
988 {
989 extern int do_mdm_init;
990 do_mdm_init = gd->do_mdm_init;
991 }
992#endif
993
wdenkfe8c2802002-11-03 00:38:21 +0000994 /* Initialization complete - start the monitor */
995
996 /* main_loop() can return to retry autoboot, if so just run it again. */
997 for (;;) {
998 WATCHDOG_RESET ();
999 main_loop ();
1000 }
1001
1002 /* NOTREACHED - no way out of command loop except booting */
1003}
1004
1005void hang (void)
1006{
1007 puts ("### ERROR ### Please RESET the board ###\n");
1008 for (;;);
1009}
1010
wdenk4532cb62003-04-27 22:52:51 +00001011#ifdef CONFIG_MODEM_SUPPORT
1012/* called from main loop (common/main.c) */
1013extern void dbg(const char *fmt, ...);
1014int mdm_init (void)
1015{
1016 char env_str[16];
1017 char *init_str;
1018 int i;
1019 extern char console_buffer[];
1020 static inline void mdm_readline(char *buf, int bufsiz);
1021 extern void enable_putc(void);
1022 extern int hwflow_onoff(int);
1023
1024 enable_putc(); /* enable serial_putc() */
1025
1026#ifdef CONFIG_HWFLOW
1027 init_str = getenv("mdm_flow_control");
1028 if (init_str && (strcmp(init_str, "rts/cts") == 0))
1029 hwflow_onoff (1);
1030 else
1031 hwflow_onoff(-1);
1032#endif
1033
1034 for (i = 1;;i++) {
1035 sprintf(env_str, "mdm_init%d", i);
1036 if ((init_str = getenv(env_str)) != NULL) {
1037 serial_puts(init_str);
1038 serial_puts("\n");
1039 for(;;) {
1040 mdm_readline(console_buffer, CFG_CBSIZE);
1041 dbg("ini%d: [%s]", i, console_buffer);
1042
1043 if ((strcmp(console_buffer, "OK") == 0) ||
1044 (strcmp(console_buffer, "ERROR") == 0)) {
1045 dbg("ini%d: cmd done", i);
1046 break;
1047 } else /* in case we are originating call ... */
1048 if (strncmp(console_buffer, "CONNECT", 7) == 0) {
1049 dbg("ini%d: connect", i);
1050 return 0;
1051 }
1052 }
1053 } else
1054 break; /* no init string - stop modem init */
1055
1056 udelay(100000);
1057 }
1058
1059 udelay(100000);
1060
1061 /* final stage - wait for connect */
1062 for(;i > 1;) { /* if 'i' > 1 - wait for connection
1063 message from modem */
1064 mdm_readline(console_buffer, CFG_CBSIZE);
1065 dbg("ini_f: [%s]", console_buffer);
1066 if (strncmp(console_buffer, "CONNECT", 7) == 0) {
1067 dbg("ini_f: connected");
1068 return 0;
1069 }
1070 }
1071
1072 return 0;
1073}
1074
1075/* 'inline' - We have to do it fast */
1076static inline void mdm_readline(char *buf, int bufsiz)
1077{
1078 char c;
1079 char *p;
1080 int n;
1081
1082 n = 0;
1083 p = buf;
1084 for(;;) {
1085 c = serial_getc();
1086
1087 /* dbg("(%c)", c); */
1088
1089 switch(c) {
1090 case '\r':
1091 break;
1092 case '\n':
1093 *p = '\0';
1094 return;
1095
1096 default:
1097 if(n++ > bufsiz) {
1098 *p = '\0';
1099 return; /* sanity check */
1100 }
1101 *p = c;
1102 p++;
1103 break;
1104 }
1105 }
1106}
1107#endif
1108
wdenkfe8c2802002-11-03 00:38:21 +00001109#if 0 /* We could use plain global data, but the resulting code is bigger */
1110/*
1111 * Pointer to initial global data area
1112 *
1113 * Here we initialize it.
1114 */
1115#undef XTRN_DECLARE_GLOBAL_DATA_PTR
1116#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */
1117DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
1118#endif /* 0 */
1119
1120/************************************************************************/