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