]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/m68k/lib/board.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[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 #ifdef CONFIG_SYS_ALLOC_DPRAM
35 #include <commproc.h>
36 #endif
37 #include <version.h>
38
39 #if defined(CONFIG_HARD_I2C) || \
40         defined(CONFIG_SYS_I2C)
41 #include <i2c.h>
42 #endif
43
44 #ifdef CONFIG_CMD_SPI
45 #include <spi.h>
46 #endif
47
48 #ifdef CONFIG_BITBANGMII
49 #include <miiphy.h>
50 #endif
51
52 #include <nand.h>
53
54 DECLARE_GLOBAL_DATA_PTR;
55
56 static char *failed = "*** failed ***\n";
57
58 #include <environment.h>
59
60 extern ulong __init_end;
61 extern ulong __bss_end;
62
63 #if defined(CONFIG_WATCHDOG)
64 # undef INIT_FUNC_WATCHDOG_INIT
65 # define INIT_FUNC_WATCHDOG_INIT        watchdog_init,
66 # define WATCHDOG_DISABLE               watchdog_disable
67
68 extern int watchdog_init(void);
69 extern int watchdog_disable(void);
70 #else
71 # define INIT_FUNC_WATCHDOG_INIT        /* undef */
72 # define WATCHDOG_DISABLE               /* undef */
73 #endif /* CONFIG_WATCHDOG */
74
75 ulong monitor_flash_len;
76
77 /************************************************************************
78  * Utilities                                                            *
79  ************************************************************************
80  */
81
82 /*
83  * All attempts to come up with a "common" initialization sequence
84  * that works for all boards and architectures failed: some of the
85  * requirements are just _too_ different. To get rid of the resulting
86  * mess of board dependend #ifdef'ed code we now make the whole
87  * initialization sequence configurable to the user.
88  *
89  * The requirements for any new initalization function is simple: it
90  * receives a pointer to the "global data" structure as it's only
91  * argument, and returns an integer return code, where 0 means
92  * "continue" and != 0 means "fatal error, hang the system".
93  */
94 typedef int (init_fnc_t) (void);
95
96 /************************************************************************
97  * Init Utilities
98  ************************************************************************
99  * Some of this code should be moved into the core functions,
100  * but let's get it working (again) first...
101  */
102
103 static int init_baudrate (void)
104 {
105         gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
106         return 0;
107 }
108
109 /***********************************************************************/
110
111 static int init_func_ram (void)
112 {
113         int board_type = 0;     /* use dummy arg */
114         puts ("DRAM:  ");
115
116         if ((gd->ram_size = initdram (board_type)) > 0) {
117                 print_size (gd->ram_size, "\n");
118                 return (0);
119         }
120         puts (failed);
121         return (1);
122 }
123
124 /***********************************************************************/
125
126 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
127 static int init_func_i2c (void)
128 {
129         puts ("I2C:   ");
130 #ifdef CONFIG_SYS_I2C
131         i2c_init_all();
132 #else
133         i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
134 #endif
135         puts ("ready\n");
136         return (0);
137 }
138 #endif
139
140 #if defined(CONFIG_HARD_SPI)
141 static int init_func_spi (void)
142 {
143         puts ("SPI:   ");
144         spi_init ();
145         puts ("ready\n");
146         return (0);
147 }
148 #endif
149
150 /***********************************************************************/
151
152 /************************************************************************
153  * Initialization sequence                                              *
154  ************************************************************************
155  */
156
157 init_fnc_t *init_sequence[] = {
158         get_clocks,
159         env_init,
160         init_baudrate,
161         serial_init,
162         console_init_f,
163         display_options,
164         checkcpu,
165         checkboard,
166 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
167         init_func_i2c,
168 #endif
169 #if defined(CONFIG_HARD_SPI)
170         init_func_spi,
171 #endif
172         init_func_ram,
173 #if defined(CONFIG_SYS_DRAM_TEST)
174         testdram,
175 #endif /* CONFIG_SYS_DRAM_TEST */
176         INIT_FUNC_WATCHDOG_INIT
177         NULL,                   /* Terminate this list */
178 };
179
180
181 /************************************************************************
182  *
183  * This is the first part of the initialization sequence that is
184  * implemented in C, but still running from ROM.
185  *
186  * The main purpose is to provide a (serial) console interface as
187  * soon as possible (so we can see any error messages), and to
188  * initialize the RAM so that we can relocate the monitor code to
189  * RAM.
190  *
191  * Be aware of the restrictions: global data is read-only, BSS is not
192  * initialized, and stack space is limited to a few kB.
193  *
194  ************************************************************************
195  */
196
197 void
198 board_init_f (ulong bootflag)
199 {
200         bd_t *bd;
201         ulong len, addr, addr_sp;
202         ulong *paddr;
203         gd_t *id;
204         init_fnc_t **init_fnc_ptr;
205 #ifdef CONFIG_PRAM
206         ulong reg;
207 #endif
208
209         /* Pointer is writable since we allocated a register for it */
210         gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET);
211         /* compiler optimization barrier needed for GCC >= 3.4 */
212         __asm__ __volatile__("": : :"memory");
213
214         /* Clear initial global data */
215         memset ((void *) gd, 0, sizeof (gd_t));
216
217         for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
218                 if ((*init_fnc_ptr)() != 0) {
219                         hang ();
220                 }
221         }
222
223         /*
224          * Now that we have DRAM mapped and working, we can
225          * relocate the code and continue running from DRAM.
226          *
227          * Reserve memory at end of RAM for (top down in that order):
228          *      - protected RAM
229          *      - LCD framebuffer
230          *      - monitor code
231          *      - board info struct
232          */
233         len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE;
234
235         addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
236
237 #ifdef CONFIG_LOGBUFFER
238         /* reserve kernel log buffer */
239         addr -= (LOGBUFF_RESERVE);
240         debug ("Reserving %dk for kernel logbuffer at %08lx\n", LOGBUFF_LEN, addr);
241 #endif
242
243 #ifdef CONFIG_PRAM
244         /*
245          * reserve protected RAM
246          */
247         reg = getenv_ulong("pram", 10, CONFIG_PRAM);
248         addr -= (reg << 10);            /* size is in kB */
249         debug ("Reserving %ldk for protected RAM at %08lx\n", reg, addr);
250 #endif /* CONFIG_PRAM */
251
252         /* round down to next 4 kB limit */
253         addr &= ~(4096 - 1);
254         debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
255
256 #ifdef CONFIG_LCD
257 #ifdef CONFIG_FB_ADDR
258         gd->fb_base = CONFIG_FB_ADDR;
259 #else
260         /* reserve memory for LCD display (always full pages) */
261         addr = lcd_setmem (addr);
262         gd->fb_base = addr;
263 #endif /* CONFIG_FB_ADDR */
264 #endif /* CONFIG_LCD */
265
266         /*
267          * reserve memory for U-Boot code, data & bss
268          * round down to next 4 kB limit
269          */
270         addr -= len;
271         addr &= ~(4096 - 1);
272
273         debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
274
275         /*
276          * reserve memory for malloc() arena
277          */
278         addr_sp = addr - TOTAL_MALLOC_LEN;
279         debug ("Reserving %dk for malloc() at: %08lx\n",
280                         TOTAL_MALLOC_LEN >> 10, addr_sp);
281
282         /*
283          * (permanently) allocate a Board Info struct
284          * and a permanent copy of the "global" data
285          */
286         addr_sp -= sizeof (bd_t);
287         bd = (bd_t *) addr_sp;
288         gd->bd = bd;
289         debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
290                         sizeof (bd_t), addr_sp);
291         addr_sp -= sizeof (gd_t);
292         id = (gd_t *) addr_sp;
293         debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
294                         sizeof (gd_t), addr_sp);
295
296         /* Reserve memory for boot params. */
297         addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
298         bd->bi_boot_params = addr_sp;
299         debug ("Reserving %dk for boot parameters at: %08lx\n",
300                         CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
301
302         /*
303          * Finally, we set up a new (bigger) stack.
304          *
305          * Leave some safety gap for SP, force alignment on 16 byte boundary
306          * Clear initial stack frame
307          */
308         addr_sp -= 16;
309         addr_sp &= ~0xF;
310
311         paddr = (ulong *)addr_sp;
312         *paddr-- = 0;
313         *paddr-- = 0;
314         addr_sp = (ulong)paddr;
315
316         debug ("Stack Pointer at: %08lx\n", addr_sp);
317
318         /*
319          * Save local variables to board info struct
320          */
321         bd->bi_memstart  = CONFIG_SYS_SDRAM_BASE;       /* start of  DRAM memory      */
322         bd->bi_memsize   = gd->ram_size;        /* size  of  DRAM memory in bytes */
323 #ifdef CONFIG_SYS_INIT_RAM_ADDR
324         bd->bi_sramstart = CONFIG_SYS_INIT_RAM_ADDR;    /* start of  SRAM memory        */
325         bd->bi_sramsize  = CONFIG_SYS_INIT_RAM_SIZE;    /* size  of  SRAM memory        */
326 #endif
327         bd->bi_mbar_base = CONFIG_SYS_MBAR;             /* base of internal registers */
328
329         bd->bi_bootflags = bootflag;            /* boot / reboot flag (for LynxOS)    */
330
331         WATCHDOG_RESET ();
332         bd->bi_intfreq = gd->cpu_clk;   /* Internal Freq, in Hz */
333         bd->bi_busfreq = gd->bus_clk;   /* Bus Freq,      in Hz */
334 #ifdef CONFIG_PCI
335         bd->bi_pcifreq = gd->pci_clk;           /* PCI Freq in Hz */
336 #endif
337 #ifdef CONFIG_EXTRA_CLOCK
338         bd->bi_inpfreq = gd->arch.inp_clk;              /* input Freq in Hz */
339         bd->bi_vcofreq = gd->arch.vco_clk;              /* vco Freq in Hz */
340         bd->bi_flbfreq = gd->arch.flb_clk;              /* flexbus Freq in Hz */
341 #endif
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 #if defined(CONFIG_SYS_I2C)
489         /* Adjust I2C subsystem pointers after relocation */
490         i2c_reloc_fixup();
491 #endif
492
493         /* relocate environment function pointers etc. */
494         env_relocate ();
495
496         WATCHDOG_RESET ();
497
498 #if defined(CONFIG_PCI)
499         /*
500          * Do pci configuration
501          */
502         pci_init ();
503 #endif
504
505         /** leave this here (after malloc(), environment and PCI are working) **/
506         /* Initialize stdio devices */
507         stdio_init ();
508
509         /* Initialize the jump table for applications */
510         jumptable_init ();
511
512         /* Initialize the console (after the relocation and devices init) */
513         console_init_r ();
514
515 #if defined(CONFIG_MISC_INIT_R)
516         /* miscellaneous platform dependent initialisations */
517         misc_init_r ();
518 #endif
519
520 #if defined(CONFIG_CMD_KGDB)
521         WATCHDOG_RESET ();
522         puts ("KGDB:  ");
523         kgdb_init ();
524 #endif
525
526         debug ("U-Boot relocated to %08lx\n", dest_addr);
527
528         /*
529          * Enable Interrupts
530          */
531         interrupt_init ();
532
533         /* Must happen after interrupts are initialized since
534          * an irq handler gets installed
535          */
536         timer_init();
537
538 #ifdef CONFIG_STATUS_LED
539         status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
540 #endif
541
542         udelay (20);
543
544         /* Insert function pointers now that we have relocated the code */
545
546         /* Initialize from environment */
547         load_addr = getenv_ulong("loadaddr", 16, load_addr);
548
549         WATCHDOG_RESET ();
550
551 #if defined(CONFIG_CMD_DOC)
552         WATCHDOG_RESET ();
553         puts ("DOC:   ");
554         doc_init ();
555 #endif
556
557 #if defined(CONFIG_CMD_NAND)
558         WATCHDOG_RESET ();
559         puts ("NAND:  ");
560         nand_init();            /* go init the NAND */
561 #endif
562
563 #ifdef CONFIG_BITBANGMII
564         bb_miiphy_init();
565 #endif
566 #if defined(CONFIG_CMD_NET)
567         WATCHDOG_RESET();
568 #if defined(FEC_ENET)
569         eth_init(bd);
570 #endif
571         puts ("Net:   ");
572         eth_initialize (bd);
573 #endif
574
575 #ifdef CONFIG_POST
576         post_run (NULL, POST_RAM | post_bootmode_get(0));
577 #endif
578
579 #if defined(CONFIG_CMD_PCMCIA) \
580     && !defined(CONFIG_CMD_IDE)
581         WATCHDOG_RESET ();
582         puts ("PCMCIA:");
583         pcmcia_init ();
584 #endif
585
586 #if defined(CONFIG_CMD_IDE)
587         WATCHDOG_RESET ();
588         puts ("IDE:   ");
589         ide_init ();
590 #endif
591
592 #ifdef CONFIG_LAST_STAGE_INIT
593         WATCHDOG_RESET ();
594         /*
595          * Some parts can be only initialized if all others (like
596          * Interrupts) are up and running (i.e. the PC-style ISA
597          * keyboard).
598          */
599         last_stage_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_WATCHDOG
624         /* disable watchdog if environment is set */
625         if ((s = getenv ("watchdog")) != NULL) {
626                 if (strncmp (s, "off", 3) == 0) {
627                         WATCHDOG_DISABLE ();
628                 }
629         }
630 #endif /* CONFIG_WATCHDOG*/
631
632
633         /* Initialization complete - start the monitor */
634
635         /* main_loop() can return to retry autoboot, if so just run it again. */
636         for (;;) {
637                 WATCHDOG_RESET ();
638                 main_loop ();
639         }
640
641         /* NOTREACHED - no way out of command loop except booting */
642 }