]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/m68k/lib/board.c
MIPS: mips32/cache.S: use v1 register for indirect function calls
[karo-tx-uboot.git] / arch / m68k / lib / 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  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <watchdog.h>
13 #include <command.h>
14 #include <malloc.h>
15 #include <stdio_dev.h>
16 #include <linux/compiler.h>
17
18 #include <asm/immap.h>
19
20 #if defined(CONFIG_CMD_IDE)
21 #include <ide.h>
22 #endif
23 #if defined(CONFIG_CMD_SCSI)
24 #include <scsi.h>
25 #endif
26 #if defined(CONFIG_CMD_KGDB)
27 #include <kgdb.h>
28 #endif
29 #ifdef CONFIG_STATUS_LED
30 #include <status_led.h>
31 #endif
32 #include <net.h>
33 #include <serial.h>
34 #if defined(CONFIG_CMD_BEDBUG)
35 #include <cmd_bedbug.h>
36 #endif
37 #ifdef CONFIG_SYS_ALLOC_DPRAM
38 #include <commproc.h>
39 #endif
40 #include <version.h>
41
42 #if defined(CONFIG_HARD_I2C) || \
43     defined(CONFIG_SOFT_I2C)
44 #include <i2c.h>
45 #endif
46
47 #ifdef CONFIG_CMD_SPI
48 #include <spi.h>
49 #endif
50
51 #ifdef CONFIG_BITBANGMII
52 #include <miiphy.h>
53 #endif
54
55 #include <nand.h>
56
57 DECLARE_GLOBAL_DATA_PTR;
58
59 static char *failed = "*** failed ***\n";
60
61 #include <environment.h>
62
63 extern ulong __init_end;
64 extern ulong __bss_end;
65
66 #if defined(CONFIG_WATCHDOG)
67 # undef INIT_FUNC_WATCHDOG_INIT
68 # define INIT_FUNC_WATCHDOG_INIT        watchdog_init,
69 # define WATCHDOG_DISABLE               watchdog_disable
70
71 extern int watchdog_init(void);
72 extern int watchdog_disable(void);
73 #else
74 # define INIT_FUNC_WATCHDOG_INIT        /* undef */
75 # define WATCHDOG_DISABLE               /* undef */
76 #endif /* CONFIG_WATCHDOG */
77
78 ulong monitor_flash_len;
79
80 /************************************************************************
81  * Utilities                                                            *
82  ************************************************************************
83  */
84
85 /*
86  * All attempts to come up with a "common" initialization sequence
87  * that works for all boards and architectures failed: some of the
88  * requirements are just _too_ different. To get rid of the resulting
89  * mess of board dependend #ifdef'ed code we now make the whole
90  * initialization sequence configurable to the user.
91  *
92  * The requirements for any new initalization function is simple: it
93  * receives a pointer to the "global data" structure as it's only
94  * argument, and returns an integer return code, where 0 means
95  * "continue" and != 0 means "fatal error, hang the system".
96  */
97 typedef int (init_fnc_t) (void);
98
99 /************************************************************************
100  * Init Utilities
101  ************************************************************************
102  * Some of this code should be moved into the core functions,
103  * but let's get it working (again) first...
104  */
105
106 static int init_baudrate (void)
107 {
108         gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
109         return 0;
110 }
111
112 /***********************************************************************/
113
114 static int init_func_ram (void)
115 {
116         int board_type = 0;     /* use dummy arg */
117         puts ("DRAM:  ");
118
119         if ((gd->ram_size = initdram (board_type)) > 0) {
120                 print_size (gd->ram_size, "\n");
121                 return (0);
122         }
123         puts (failed);
124         return (1);
125 }
126
127 /***********************************************************************/
128
129 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
130 static int init_func_i2c (void)
131 {
132         puts ("I2C:   ");
133         i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
134         puts ("ready\n");
135         return (0);
136 }
137 #endif
138
139 #if defined(CONFIG_HARD_SPI)
140 static int init_func_spi (void)
141 {
142         puts ("SPI:   ");
143         spi_init ();
144         puts ("ready\n");
145         return (0);
146 }
147 #endif
148
149 /***********************************************************************/
150
151 /************************************************************************
152  * Initialization sequence                                              *
153  ************************************************************************
154  */
155
156 init_fnc_t *init_sequence[] = {
157         get_clocks,
158         env_init,
159         init_baudrate,
160         serial_init,
161         console_init_f,
162         display_options,
163         checkcpu,
164         checkboard,
165 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C)
166         init_func_i2c,
167 #endif
168 #if defined(CONFIG_HARD_SPI)
169         init_func_spi,
170 #endif
171         init_func_ram,
172 #if defined(CONFIG_SYS_DRAM_TEST)
173         testdram,
174 #endif /* CONFIG_SYS_DRAM_TEST */
175         INIT_FUNC_WATCHDOG_INIT
176         NULL,                   /* Terminate this list */
177 };
178
179
180 /************************************************************************
181  *
182  * This is the first part of the initialization sequence that is
183  * implemented in C, but still running from ROM.
184  *
185  * The main purpose is to provide a (serial) console interface as
186  * soon as possible (so we can see any error messages), and to
187  * initialize the RAM so that we can relocate the monitor code to
188  * RAM.
189  *
190  * Be aware of the restrictions: global data is read-only, BSS is not
191  * initialized, and stack space is limited to a few kB.
192  *
193  ************************************************************************
194  */
195
196 void
197 board_init_f (ulong bootflag)
198 {
199         bd_t *bd;
200         ulong len, addr, addr_sp;
201         ulong *paddr;
202         gd_t *id;
203         init_fnc_t **init_fnc_ptr;
204 #ifdef CONFIG_PRAM
205         ulong reg;
206 #endif
207
208         /* Pointer is writable since we allocated a register for it */
209         gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
210         /* compiler optimization barrier needed for GCC >= 3.4 */
211         __asm__ __volatile__("": : :"memory");
212
213         /* Clear initial global data */
214         memset ((void *) gd, 0, sizeof (gd_t));
215
216         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
217                 if ((*init_fnc_ptr)() != 0) {
218                         hang ();
219                 }
220         }
221
222         /*
223          * Now that we have DRAM mapped and working, we can
224          * relocate the code and continue running from DRAM.
225          *
226          * Reserve memory at end of RAM for (top down in that order):
227          *      - protected RAM
228          *      - LCD framebuffer
229          *      - monitor code
230          *      - board info struct
231          */
232         len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
233
234         addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
235
236 #ifdef CONFIG_LOGBUFFER
237         /* reserve kernel log buffer */
238         addr -= (LOGBUFF_RESERVE);
239         debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
240 #endif
241
242 #ifdef CONFIG_PRAM
243         /*
244          * reserve protected RAM
245          */
246         reg = getenv_ulong("pram", 10, CONFIG_PRAM);
247         addr -= (reg << 10);            /* size is in kB */
248         debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
249 #endif /* CONFIG_PRAM */
250
251         /* round down to next 4 kB limit */
252         addr &= ~(4096 - 1);
253         debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
254
255 #ifdef CONFIG_LCD
256 #ifdef CONFIG_FB_ADDR
257         gd->fb_base = CONFIG_FB_ADDR;
258 #else
259         /* reserve memory for LCD display (always full pages) */
260         addr = lcd_setmem (addr);
261         gd->fb_base = addr;
262 #endif /* CONFIG_FB_ADDR */
263 #endif /* CONFIG_LCD */
264
265         /*
266          * reserve memory for U-Boot code, data & bss
267          * round down to next 4 kB limit
268          */
269         addr -= len;
270         addr &= ~(4096 - 1);
271
272         debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
273
274         /*
275          * reserve memory for malloc() arena
276          */
277         addr_sp = addr - TOTAL_MALLOC_LEN;
278         debug ("Reserving %dk for malloc() at: %08lx\n",
279                         TOTAL_MALLOC_LEN >> 10, addr_sp);
280
281         /*
282          * (permanently) allocate a Board Info struct
283          * and a permanent copy of the "global" data
284          */
285         addr_sp -= sizeof (bd_t);
286         bd = (bd_t *) addr_sp;
287         gd->bd = bd;
288         debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
289                         sizeof (bd_t), addr_sp);
290         addr_sp -= sizeof (gd_t);
291         id = (gd_t *) addr_sp;
292         debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
293                         sizeof (gd_t), addr_sp);
294
295         /* Reserve memory for boot params. */
296         addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
297         bd->bi_boot_params = addr_sp;
298         debug ("Reserving %dk for boot parameters at: %08lx\n",
299                         CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
300
301         /*
302          * Finally, we set up a new (bigger) stack.
303          *
304          * Leave some safety gap for SP, force alignment on 16 byte boundary
305          * Clear initial stack frame
306          */
307         addr_sp -= 16;
308         addr_sp &= ~0xF;
309
310         paddr = (ulong *)addr_sp;
311         *paddr-- = 0;
312         *paddr-- = 0;
313         addr_sp = (ulong)paddr;
314
315         debug ("Stack Pointer at: %08lx\n", addr_sp);
316
317         /*
318          * Save local variables to board info struct
319          */
320         bd->bi_memstart  = CONFIG_SYS_SDRAM_BASE;       /* start of  DRAM memory      */
321         bd->bi_memsize   = gd->ram_size;        /* size  of  DRAM memory in bytes */
322 #ifdef CONFIG_SYS_INIT_RAM_ADDR
323         bd->bi_sramstart = CONFIG_SYS_INIT_RAM_ADDR;    /* start of  SRAM memory        */
324         bd->bi_sramsize  = CONFIG_SYS_INIT_RAM_SIZE;    /* size  of  SRAM memory        */
325 #endif
326         bd->bi_mbar_base = CONFIG_SYS_MBAR;             /* base of internal registers */
327
328         bd->bi_bootflags = bootflag;            /* boot / reboot flag (for LynxOS)    */
329
330         WATCHDOG_RESET ();
331         bd->bi_intfreq = gd->cpu_clk;   /* Internal Freq, in Hz */
332         bd->bi_busfreq = gd->bus_clk;   /* Bus Freq,      in Hz */
333 #ifdef CONFIG_PCI
334         bd->bi_pcifreq = gd->pci_clk;           /* PCI Freq in Hz */
335 #endif
336 #ifdef CONFIG_EXTRA_CLOCK
337         bd->bi_inpfreq = gd->arch.inp_clk;              /* input Freq in Hz */
338         bd->bi_vcofreq = gd->arch.vco_clk;              /* vco Freq in Hz */
339         bd->bi_flbfreq = gd->arch.flb_clk;              /* flexbus Freq in Hz */
340 #endif
341         bd->bi_baudrate = gd->baudrate; /* Console Baudrate     */
342
343 #ifdef CONFIG_SYS_EXTBDINFO
344         strncpy (bd->bi_s_version, "1.2", sizeof (bd->bi_s_version));
345         strncpy (bd->bi_r_version, U_BOOT_VERSION, sizeof (bd->bi_r_version));
346 #endif
347
348         WATCHDOG_RESET ();
349
350 #ifdef CONFIG_POST
351         post_bootmode_init();
352         post_run (NULL, POST_ROM | post_bootmode_get(0));
353 #endif
354
355         WATCHDOG_RESET();
356
357         memcpy (id, (void *)gd, sizeof (gd_t));
358
359         debug ("Start relocate of code from %08x to %08lx\n", CONFIG_SYS_MONITOR_BASE, addr);
360         relocate_code (addr_sp, id, addr);
361
362         /* NOTREACHED - jump_to_ram() does not return */
363 }
364
365 /************************************************************************
366  *
367  * This is the next part if the initialization sequence: we are now
368  * running from RAM and have a "normal" C environment, i. e. global
369  * data can be written, BSS has been cleared, the stack size in not
370  * that critical any more, etc.
371  *
372  ************************************************************************
373  */
374 void board_init_r (gd_t *id, ulong dest_addr)
375 {
376         char *s __maybe_unused;
377         bd_t *bd;
378
379 #ifndef CONFIG_ENV_IS_NOWHERE
380         extern char * env_name_spec;
381 #endif
382 #ifndef CONFIG_SYS_NO_FLASH
383         ulong flash_size;
384 #endif
385         gd = id;                /* initialize RAM version of global data */
386         bd = gd->bd;
387
388         gd->flags |= GD_FLG_RELOC;      /* tell others: relocation done */
389
390         WATCHDOG_RESET ();
391
392         gd->reloc_off =  dest_addr - CONFIG_SYS_MONITOR_BASE;
393
394         serial_initialize();
395
396         debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
397
398         monitor_flash_len = (ulong)&__init_end - dest_addr;
399
400 #if defined(CONFIG_NEEDS_MANUAL_RELOC)
401         /*
402          * We have to relocate the command table manually
403          */
404         fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
405                         ll_entry_count(cmd_tbl_t, cmd));
406 #endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */
407
408         /* there are some other pointer constants we must deal with */
409 #ifndef CONFIG_ENV_IS_NOWHERE
410         env_name_spec += gd->reloc_off;
411 #endif
412
413         WATCHDOG_RESET ();
414
415 #ifdef CONFIG_LOGBUFFER
416         logbuff_init_ptrs ();
417 #endif
418 #ifdef CONFIG_POST
419         post_output_backlog ();
420         post_reloc ();
421 #endif
422         WATCHDOG_RESET();
423
424 #if 0
425         /* instruction cache enabled in cpu_init_f() for faster relocation */
426         icache_enable ();       /* it's time to enable the instruction cache */
427 #endif
428
429         /*
430          * Setup trap handlers
431          */
432         trap_init (CONFIG_SYS_SDRAM_BASE);
433
434         /* The Malloc area is immediately below the monitor copy in DRAM */
435         mem_malloc_init (CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
436                         TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
437
438 #if !defined(CONFIG_SYS_NO_FLASH)
439         puts ("Flash: ");
440
441         if ((flash_size = flash_init ()) > 0) {
442 # ifdef CONFIG_SYS_FLASH_CHECKSUM
443                 print_size (flash_size, "");
444                 /*
445                  * Compute and print flash CRC if flashchecksum is set to 'y'
446                  *
447                  * NOTE: Maybe we should add some WATCHDOG_RESET()? XXX
448                  */
449                 if (getenv_yesno("flashchecksum") == 1) {
450                         printf ("  CRC: %08X",
451                                         crc32 (0,
452                                                    (const unsigned char *) CONFIG_SYS_FLASH_BASE,
453                                                    flash_size)
454                                         );
455                 }
456                 putc ('\n');
457 # else  /* !CONFIG_SYS_FLASH_CHECKSUM */
458                 print_size (flash_size, "\n");
459 # endif /* CONFIG_SYS_FLASH_CHECKSUM */
460         } else {
461                 puts (failed);
462                 hang ();
463         }
464
465         bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;      /* update start of FLASH memory    */
466         bd->bi_flashsize = flash_size;  /* size of FLASH memory (final value) */
467         bd->bi_flashoffset = 0;
468 #else   /* CONFIG_SYS_NO_FLASH */
469         bd->bi_flashsize = 0;
470         bd->bi_flashstart = 0;
471         bd->bi_flashoffset = 0;
472 #endif /* !CONFIG_SYS_NO_FLASH */
473
474         WATCHDOG_RESET ();
475
476         /* initialize higher level parts of CPU like time base and timers */
477         cpu_init_r ();
478
479         WATCHDOG_RESET ();
480
481 #ifdef CONFIG_SPI
482 # if !defined(CONFIG_ENV_IS_IN_EEPROM)
483         spi_init_f ();
484 # endif
485         spi_init_r ();
486 #endif
487
488         /* relocate environment function pointers etc. */
489         env_relocate ();
490
491         WATCHDOG_RESET ();
492
493 #if defined(CONFIG_PCI)
494         /*
495          * Do pci configuration
496          */
497         pci_init ();
498 #endif
499
500         /** leave this here (after malloc(), environment and PCI are working) **/
501         /* Initialize stdio devices */
502         stdio_init ();
503
504         /* Initialize the jump table for applications */
505         jumptable_init ();
506
507         /* Initialize the console (after the relocation and devices init) */
508         console_init_r ();
509
510 #if defined(CONFIG_MISC_INIT_R)
511         /* miscellaneous platform dependent initialisations */
512         misc_init_r ();
513 #endif
514
515 #if defined(CONFIG_CMD_KGDB)
516         WATCHDOG_RESET ();
517         puts ("KGDB:  ");
518         kgdb_init ();
519 #endif
520
521         debug ("U-Boot relocated to %08lx\n", dest_addr);
522
523         /*
524          * Enable Interrupts
525          */
526         interrupt_init ();
527
528         /* Must happen after interrupts are initialized since
529          * an irq handler gets installed
530          */
531         timer_init();
532
533 #ifdef CONFIG_STATUS_LED
534         status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
535 #endif
536
537         udelay (20);
538
539         /* Insert function pointers now that we have relocated the code */
540
541         /* Initialize from environment */
542         load_addr = getenv_ulong("loadaddr", 16, load_addr);
543
544         WATCHDOG_RESET ();
545
546 #if defined(CONFIG_CMD_DOC)
547         WATCHDOG_RESET ();
548         puts ("DOC:   ");
549         doc_init ();
550 #endif
551
552 #if defined(CONFIG_CMD_NAND)
553         WATCHDOG_RESET ();
554         puts ("NAND:  ");
555         nand_init();            /* go init the NAND */
556 #endif
557
558 #ifdef CONFIG_BITBANGMII
559         bb_miiphy_init();
560 #endif
561 #if defined(CONFIG_CMD_NET)
562         WATCHDOG_RESET();
563 #if defined(FEC_ENET)
564         eth_init(bd);
565 #endif
566         puts ("Net:   ");
567         eth_initialize (bd);
568 #endif
569
570 #ifdef CONFIG_POST
571         post_run (NULL, POST_RAM | post_bootmode_get(0));
572 #endif
573
574 #if defined(CONFIG_CMD_PCMCIA) \
575     && !defined(CONFIG_CMD_IDE)
576         WATCHDOG_RESET ();
577         puts ("PCMCIA:");
578         pcmcia_init ();
579 #endif
580
581 #if defined(CONFIG_CMD_IDE)
582         WATCHDOG_RESET ();
583         puts ("IDE:   ");
584         ide_init ();
585 #endif
586
587 #ifdef CONFIG_LAST_STAGE_INIT
588         WATCHDOG_RESET ();
589         /*
590          * Some parts can be only initialized if all others (like
591          * Interrupts) are up and running (i.e. the PC-style ISA
592          * keyboard).
593          */
594         last_stage_init ();
595 #endif
596
597 #if defined(CONFIG_CMD_BEDBUG)
598         WATCHDOG_RESET ();
599         bedbug_init ();
600 #endif
601
602 #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER)
603         /*
604          * Export available size of memory for Linux,
605          * taking into account the protected RAM at top of memory
606          */
607         {
608                 ulong pram = 0;
609                 char memsz[32];
610
611 #ifdef CONFIG_PRAM
612                 pram = getenv_ulong("pram", 10, CONFIG_PRAM);
613 #endif
614 #ifdef CONFIG_LOGBUFFER
615                 /* Also take the logbuffer into account (pram is in kB) */
616                 pram += (LOGBUFF_LEN+LOGBUFF_OVERHEAD)/1024;
617 #endif
618                 sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
619                 setenv ("mem", memsz);
620         }
621 #endif
622
623 #ifdef CONFIG_MODEM_SUPPORT
624  {
625          extern int do_mdm_init;
626          do_mdm_init = gd->do_mdm_init;
627  }
628 #endif
629
630 #ifdef CONFIG_WATCHDOG
631         /* disable watchdog if environment is set */
632         if ((s = getenv ("watchdog")) != NULL) {
633                 if (strncmp (s, "off", 3) == 0) {
634                         WATCHDOG_DISABLE ();
635                 }
636         }
637 #endif /* CONFIG_WATCHDOG*/
638
639
640         /* Initialization complete - start the monitor */
641
642         /* main_loop() can return to retry autoboot, if so just run it again. */
643         for (;;) {
644                 WATCHDOG_RESET ();
645                 main_loop ();
646         }
647
648         /* NOTREACHED - no way out of command loop except booting */
649 }