blob: 1274d63f121acd06ac4adcd73024b95986e9c03b [file] [log] [blame]
wdenkbb1b8262003-03-27 12:09:35 +00001/*
2 * (C) Copyright 2003
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 <command.h>
26#include <malloc.h>
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +020027#include <stdio_dev.h>
wdenkbb1b8262003-03-27 12:09:35 +000028#include <version.h>
29#include <net.h>
30#include <environment.h>
Jason McMullan7d32b002008-05-30 00:53:37 +090031#include <nand.h>
Stefan Roese1af2a0d2008-11-12 13:18:19 +010032#include <onenand_uboot.h>
Jason McMullan733ad782008-05-30 00:53:37 +090033#include <spi.h>
wdenkbb1b8262003-03-27 12:09:35 +000034
Luigi 'Comio' Mantellini01db1552009-10-10 12:42:21 +020035#ifdef CONFIG_BITBANGMII
36#include <miiphy.h>
37#endif
38
Wolfgang Denk117b0b12005-12-01 02:15:07 +010039DECLARE_GLOBAL_DATA_PTR;
40
wdenkbb1b8262003-03-27 12:09:35 +000041#undef DEBUG
42
43extern int timer_init(void);
44
wdenk67f13362003-12-27 19:24:54 +000045extern int incaip_set_cpuclk(void);
46
wdenkb9a83a92003-05-30 12:48:29 +000047extern ulong uboot_end_data;
48extern ulong uboot_end;
49
50ulong monitor_flash_len;
51
wdenkbb1b8262003-03-27 12:09:35 +000052static char *failed = "*** failed ***\n";
53
54/*
Jean-Christophe PLAGNIOL-VILLARD089dbb72007-11-13 09:11:05 +010055 * mips_io_port_base is the begin of the address space to which x86 style
56 * I/O ports are mapped.
57 */
58unsigned long mips_io_port_base = -1;
wdenkbb1b8262003-03-27 12:09:35 +000059
Stefan Roese2b1c8152008-11-12 13:18:02 +010060int __board_early_init_f(void)
61{
62 /*
63 * Nothing to do in this dummy implementation
64 */
65 return 0;
66}
67int board_early_init_f(void) __attribute__((weak, alias("__board_early_init_f")));
68
wdenkbb1b8262003-03-27 12:09:35 +000069
70static int init_func_ram (void)
71{
wdenkbb1b8262003-03-27 12:09:35 +000072#ifdef CONFIG_BOARD_TYPES
73 int board_type = gd->board_type;
74#else
75 int board_type = 0; /* use dummy arg */
76#endif
77 puts ("DRAM: ");
78
79 if ((gd->ram_size = initdram (board_type)) > 0) {
80 print_size (gd->ram_size, "\n");
81 return (0);
82 }
83 puts (failed);
84 return (1);
85}
86
87static int display_banner(void)
88{
89
90 printf ("\n\n%s\n\n", version_string);
91 return (0);
92}
93
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020094#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +000095static void display_flash_config(ulong size)
96{
97 puts ("Flash: ");
98 print_size (size, "\n");
99}
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100100#endif
wdenkbb1b8262003-03-27 12:09:35 +0000101
102static int init_baudrate (void)
103{
Simon Glass8ccbef92011-10-13 14:43:11 +0000104 gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
105 return 0;
wdenkbb1b8262003-03-27 12:09:35 +0000106}
107
108
109/*
110 * Breath some life into the board...
111 *
112 * The first part of initialization is running from Flash memory;
113 * its main purpose is to initialize the RAM so that we
114 * can relocate the monitor code to RAM.
115 */
116
117/*
118 * All attempts to come up with a "common" initialization sequence
119 * that works for all boards and architectures failed: some of the
120 * requirements are just _too_ different. To get rid of the resulting
121 * mess of board dependend #ifdef'ed code we now make the whole
122 * initialization sequence configurable to the user.
123 *
124 * The requirements for any new initalization function is simple: it
125 * receives a pointer to the "global data" structure as it's only
126 * argument, and returns an integer return code, where 0 means
127 * "continue" and != 0 means "fatal error, hang the system".
128 */
129typedef int (init_fnc_t) (void);
130
131init_fnc_t *init_sequence[] = {
Stefan Roese2b1c8152008-11-12 13:18:02 +0100132 board_early_init_f,
wdenkbb1b8262003-03-27 12:09:35 +0000133 timer_init,
134 env_init, /* initialize environment */
wdenk67f13362003-12-27 19:24:54 +0000135#ifdef CONFIG_INCA_IP
136 incaip_set_cpuclk, /* set cpu clock according to environment variable */
137#endif
wdenkbb1b8262003-03-27 12:09:35 +0000138 init_baudrate, /* initialze baudrate settings */
139 serial_init, /* serial communications setup */
140 console_init_f,
141 display_banner, /* say that we are here */
wdenk8dba0502003-03-31 16:34:49 +0000142 checkboard,
wdenkbb1b8262003-03-27 12:09:35 +0000143 init_func_ram,
144 NULL,
145};
146
147
148void board_init_f(ulong bootflag)
149{
wdenkbb1b8262003-03-27 12:09:35 +0000150 gd_t gd_data, *id;
151 bd_t *bd;
152 init_fnc_t **init_fnc_ptr;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200153 ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_SYS_MONITOR_BASE;
Wolfgang Denk117b0b12005-12-01 02:15:07 +0100154 ulong *s;
wdenkbb1b8262003-03-27 12:09:35 +0000155
wdenkcd914452004-05-29 16:53:29 +0000156 /* Pointer is writable since we allocated a register for it.
157 */
wdenkbb1b8262003-03-27 12:09:35 +0000158 gd = &gd_data;
wdenk3337af42004-07-01 20:28:03 +0000159 /* compiler optimization barrier needed for GCC >= 3.4 */
160 __asm__ __volatile__("": : :"memory");
161
wdenk874ac262003-07-24 23:38:38 +0000162 memset ((void *)gd, 0, sizeof (gd_t));
wdenkbb1b8262003-03-27 12:09:35 +0000163
164 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
165 if ((*init_fnc_ptr)() != 0) {
166 hang ();
167 }
168 }
169
170 /*
171 * Now that we have DRAM mapped and working, we can
172 * relocate the code and continue running from DRAM.
173 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200174 addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
wdenkbb1b8262003-03-27 12:09:35 +0000175
wdenkcd914452004-05-29 16:53:29 +0000176 /* We can reserve some RAM "on top" here.
177 */
wdenkbb1b8262003-03-27 12:09:35 +0000178
wdenkcd914452004-05-29 16:53:29 +0000179 /* round down to next 4 kB limit.
180 */
wdenkbb1b8262003-03-27 12:09:35 +0000181 addr &= ~(4096 - 1);
wdenkcd914452004-05-29 16:53:29 +0000182 debug ("Top of RAM usable for U-Boot at: %08lx\n", addr);
wdenk57b2d802003-06-27 21:31:46 +0000183
wdenkcd914452004-05-29 16:53:29 +0000184 /* Reserve memory for U-Boot code, data & bss
185 * round down to next 16 kB limit
186 */
wdenkbb1b8262003-03-27 12:09:35 +0000187 addr -= len;
wdenkb9a83a92003-05-30 12:48:29 +0000188 addr &= ~(16 * 1024 - 1);
wdenkbb1b8262003-03-27 12:09:35 +0000189
wdenkcd914452004-05-29 16:53:29 +0000190 debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
wdenkbb1b8262003-03-27 12:09:35 +0000191
wdenkcd914452004-05-29 16:53:29 +0000192 /* Reserve memory for malloc() arena.
193 */
wdenkbb1b8262003-03-27 12:09:35 +0000194 addr_sp = addr - TOTAL_MALLOC_LEN;
wdenkcd914452004-05-29 16:53:29 +0000195 debug ("Reserving %dk for malloc() at: %08lx\n",
wdenkbb1b8262003-03-27 12:09:35 +0000196 TOTAL_MALLOC_LEN >> 10, addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000197
198 /*
199 * (permanently) allocate a Board Info struct
200 * and a permanent copy of the "global" data
201 */
202 addr_sp -= sizeof(bd_t);
203 bd = (bd_t *)addr_sp;
204 gd->bd = bd;
Wolfgang Denk509cd072008-07-14 15:06:35 +0200205 debug ("Reserving %zu Bytes for Board Info at: %08lx\n",
wdenkbb1b8262003-03-27 12:09:35 +0000206 sizeof(bd_t), addr_sp);
wdenkcd914452004-05-29 16:53:29 +0000207
wdenkbb1b8262003-03-27 12:09:35 +0000208 addr_sp -= sizeof(gd_t);
209 id = (gd_t *)addr_sp;
Wolfgang Denk509cd072008-07-14 15:06:35 +0200210 debug ("Reserving %zu Bytes for Global Data at: %08lx\n",
wdenkbb1b8262003-03-27 12:09:35 +0000211 sizeof (gd_t), addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000212
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100213 /* Reserve memory for boot params.
wdenkcd914452004-05-29 16:53:29 +0000214 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200215 addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
wdenkbb1b8262003-03-27 12:09:35 +0000216 bd->bi_boot_params = addr_sp;
wdenkcd914452004-05-29 16:53:29 +0000217 debug ("Reserving %dk for boot params() at: %08lx\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200218 CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000219
220 /*
221 * Finally, we set up a new (bigger) stack.
222 *
223 * Leave some safety gap for SP, force alignment on 16 byte boundary
224 * Clear initial stack frame
225 */
226 addr_sp -= 16;
227 addr_sp &= ~0xF;
Wolfgang Denk117b0b12005-12-01 02:15:07 +0100228 s = (ulong *)addr_sp;
229 *s-- = 0;
230 *s-- = 0;
231 addr_sp = (ulong)s;
wdenkcd914452004-05-29 16:53:29 +0000232 debug ("Stack Pointer at: %08lx\n", addr_sp);
233
wdenkbb1b8262003-03-27 12:09:35 +0000234 /*
235 * Save local variables to board info struct
236 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200237 bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM memory */
wdenkbb1b8262003-03-27 12:09:35 +0000238 bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */
239 bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
240
wdenk874ac262003-07-24 23:38:38 +0000241 memcpy (id, (void *)gd, sizeof (gd_t));
wdenkb02744a2003-04-05 00:53:31 +0000242
wdenkbb1b8262003-03-27 12:09:35 +0000243 relocate_code (addr_sp, id, addr);
244
245 /* NOTREACHED - relocate_code() does not return */
246}
247/************************************************************************
248 *
249 * This is the next part if the initialization sequence: we are now
250 * running from RAM and have a "normal" C environment, i. e. global
251 * data can be written, BSS has been cleared, the stack size in not
252 * that critical any more, etc.
253 *
254 ************************************************************************
255 */
256
257void board_init_r (gd_t *id, ulong dest_addr)
258{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200259#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +0000260 ulong size;
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100261#endif
wdenkbb1b8262003-03-27 12:09:35 +0000262 extern void malloc_bin_reloc (void);
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200263#ifndef CONFIG_ENV_IS_NOWHERE
wdenkbb1b8262003-03-27 12:09:35 +0000264 extern char * env_name_spec;
265#endif
Shinya Kuribayashi31c8c2e2009-05-16 09:12:09 +0900266 char *s;
wdenkbb1b8262003-03-27 12:09:35 +0000267 bd_t *bd;
wdenkbb1b8262003-03-27 12:09:35 +0000268
269 gd = id;
270 gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
271
wdenkcd914452004-05-29 16:53:29 +0000272 debug ("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
wdenkbb1b8262003-03-27 12:09:35 +0000273
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200274 gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
wdenkbb1b8262003-03-27 12:09:35 +0000275
wdenkb9a83a92003-05-30 12:48:29 +0000276 monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
277
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200278#if defined(CONFIG_NEEDS_MANUAL_RELOC)
wdenkbb1b8262003-03-27 12:09:35 +0000279 /*
280 * We have to relocate the command table manually
281 */
Heiko Schocher092cf162010-09-17 13:10:33 +0200282 fixup_cmdtable(&__u_boot_cmd_start,
283 (ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start));
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200284#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */
wdenkbb1b8262003-03-27 12:09:35 +0000285
wdenkbb1b8262003-03-27 12:09:35 +0000286 /* there are some other pointer constants we must deal with */
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200287#ifndef CONFIG_ENV_IS_NOWHERE
wdenkbb1b8262003-03-27 12:09:35 +0000288 env_name_spec += gd->reloc_off;
289#endif
wdenk57b2d802003-06-27 21:31:46 +0000290
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100291 bd = gd->bd;
292
Peter Tyser781c9b82009-08-21 23:05:21 -0500293 /* The Malloc area is immediately below the monitor copy in DRAM */
Peter Tysered527702009-08-21 23:05:20 -0500294 mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
295 TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
Stefan Roeseb81464e2009-05-11 15:50:12 +0200296 malloc_bin_reloc();
297
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200298#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +0000299 /* configure available FLASH banks */
300 size = flash_init();
301 display_flash_config (size);
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100302 bd->bi_flashsize = size;
303#endif
wdenkbb1b8262003-03-27 12:09:35 +0000304
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200305 bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
306#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
wdenkb9a83a92003-05-30 12:48:29 +0000307 bd->bi_flashoffset = monitor_flash_len; /* reserved area for U-Boot */
wdenkbb1b8262003-03-27 12:09:35 +0000308#else
309 bd->bi_flashoffset = 0;
310#endif
311
Stefan Roese1af2a0d2008-11-12 13:18:19 +0100312#ifdef CONFIG_CMD_NAND
313 puts ("NAND: ");
314 nand_init (); /* go init the NAND */
315#endif
316
317#if defined(CONFIG_CMD_ONENAND)
318 onenand_init();
319#endif
320
wdenkbb1b8262003-03-27 12:09:35 +0000321 /* relocate environment function pointers etc. */
322 env_relocate();
323
wdenkbb1b8262003-03-27 12:09:35 +0000324 /* IP Address */
325 bd->bi_ip_addr = getenv_IPaddr("ipaddr");
326
wdenk5401de42004-02-07 01:27:10 +0000327#if defined(CONFIG_PCI)
328 /*
329 * Do pci configuration
330 */
331 pci_init();
332#endif
333
wdenkbb1b8262003-03-27 12:09:35 +0000334/** leave this here (after malloc(), environment and PCI are working) **/
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200335 /* Initialize stdio devices */
336 stdio_init ();
wdenkbb1b8262003-03-27 12:09:35 +0000337
wdenk874ac262003-07-24 23:38:38 +0000338 jumptable_init ();
wdenkbb1b8262003-03-27 12:09:35 +0000339
340 /* Initialize the console (after the relocation and devices init) */
341 console_init_r ();
342/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
343
wdenkb02744a2003-04-05 00:53:31 +0000344 /* Initialize from environment */
Simon Glass8ccbef92011-10-13 14:43:11 +0000345 load_addr = getenv_ulong("loadaddr", 16, load_addr);
Jon Loeliger6b233052007-07-09 18:02:11 -0500346#if defined(CONFIG_CMD_NET)
wdenkb02744a2003-04-05 00:53:31 +0000347 if ((s = getenv ("bootfile")) != NULL) {
348 copy_filename (BootFile, s, sizeof (BootFile));
349 }
Jon Loeliger1670a5b2007-07-10 11:19:50 -0500350#endif
wdenkb02744a2003-04-05 00:53:31 +0000351
Jason McMullan733ad782008-05-30 00:53:37 +0900352#ifdef CONFIG_CMD_SPI
353 puts ("SPI: ");
354 spi_init (); /* go init the SPI */
355 puts ("ready\n");
356#endif
357
wdenkb02744a2003-04-05 00:53:31 +0000358#if defined(CONFIG_MISC_INIT_R)
359 /* miscellaneous platform dependent initialisations */
360 misc_init_r ();
361#endif
362
Luigi 'Comio' Mantellini01db1552009-10-10 12:42:21 +0200363#ifdef CONFIG_BITBANGMII
364 bb_miiphy_init();
365#endif
Jon Loeliger6b233052007-07-09 18:02:11 -0500366#if defined(CONFIG_CMD_NET)
wdenkbb1b8262003-03-27 12:09:35 +0000367 puts ("Net: ");
368 eth_initialize(gd->bd);
369#endif
370
371 /* main_loop() can return to retry autoboot, if so just run it again. */
372 for (;;) {
373 main_loop ();
374 }
375
376 /* NOTREACHED - no way out of command loop except booting */
377}
378
379void hang (void)
380{
381 puts ("### ERROR ### Please RESET the board ###\n");
382 for (;;);
383}