blob: 7ddd77832cc5f165111d5b553d212002fa6d1047 [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
wdenkb9a83a92003-05-30 12:48:29 +000041ulong monitor_flash_len;
42
wdenkbb1b8262003-03-27 12:09:35 +000043static char *failed = "*** failed ***\n";
44
45/*
Jean-Christophe PLAGNIOL-VILLARD089dbb72007-11-13 09:11:05 +010046 * mips_io_port_base is the begin of the address space to which x86 style
47 * I/O ports are mapped.
48 */
49unsigned long mips_io_port_base = -1;
wdenkbb1b8262003-03-27 12:09:35 +000050
Stefan Roese2b1c8152008-11-12 13:18:02 +010051int __board_early_init_f(void)
52{
53 /*
54 * Nothing to do in this dummy implementation
55 */
56 return 0;
57}
Wolfgang Denk11f98842011-12-08 02:01:49 +000058int board_early_init_f(void)
59 __attribute__((weak, alias("__board_early_init_f")));
Stefan Roese2b1c8152008-11-12 13:18:02 +010060
Wolfgang Denk11f98842011-12-08 02:01:49 +000061static int init_func_ram(void)
wdenkbb1b8262003-03-27 12:09:35 +000062{
wdenkbb1b8262003-03-27 12:09:35 +000063#ifdef CONFIG_BOARD_TYPES
64 int board_type = gd->board_type;
65#else
66 int board_type = 0; /* use dummy arg */
67#endif
Wolfgang Denk11f98842011-12-08 02:01:49 +000068 puts("DRAM: ");
wdenkbb1b8262003-03-27 12:09:35 +000069
Wolfgang Denk11f98842011-12-08 02:01:49 +000070 gd->ram_size = initdram(board_type);
71 if (gd->ram_size > 0) {
72 print_size(gd->ram_size, "\n");
73 return 0;
wdenkbb1b8262003-03-27 12:09:35 +000074 }
Wolfgang Denk11f98842011-12-08 02:01:49 +000075 puts(failed);
76 return 1;
wdenkbb1b8262003-03-27 12:09:35 +000077}
78
79static int display_banner(void)
80{
81
Wolfgang Denk11f98842011-12-08 02:01:49 +000082 printf("\n\n%s\n\n", version_string);
83 return 0;
wdenkbb1b8262003-03-27 12:09:35 +000084}
85
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020086#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +000087static void display_flash_config(ulong size)
88{
Wolfgang Denk11f98842011-12-08 02:01:49 +000089 puts("Flash: ");
90 print_size(size, "\n");
wdenkbb1b8262003-03-27 12:09:35 +000091}
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +010092#endif
wdenkbb1b8262003-03-27 12:09:35 +000093
Wolfgang Denk11f98842011-12-08 02:01:49 +000094static int init_baudrate(void)
wdenkbb1b8262003-03-27 12:09:35 +000095{
Simon Glass8ccbef92011-10-13 14:43:11 +000096 gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
97 return 0;
wdenkbb1b8262003-03-27 12:09:35 +000098}
99
100
101/*
102 * Breath some life into the board...
103 *
104 * The first part of initialization is running from Flash memory;
105 * its main purpose is to initialize the RAM so that we
106 * can relocate the monitor code to RAM.
107 */
108
109/*
110 * All attempts to come up with a "common" initialization sequence
111 * that works for all boards and architectures failed: some of the
112 * requirements are just _too_ different. To get rid of the resulting
113 * mess of board dependend #ifdef'ed code we now make the whole
114 * initialization sequence configurable to the user.
115 *
116 * The requirements for any new initalization function is simple: it
117 * receives a pointer to the "global data" structure as it's only
118 * argument, and returns an integer return code, where 0 means
119 * "continue" and != 0 means "fatal error, hang the system".
120 */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000121typedef int (init_fnc_t)(void);
wdenkbb1b8262003-03-27 12:09:35 +0000122
123init_fnc_t *init_sequence[] = {
Stefan Roese2b1c8152008-11-12 13:18:02 +0100124 board_early_init_f,
wdenkbb1b8262003-03-27 12:09:35 +0000125 timer_init,
126 env_init, /* initialize environment */
wdenk67f13362003-12-27 19:24:54 +0000127#ifdef CONFIG_INCA_IP
Wolfgang Denk11f98842011-12-08 02:01:49 +0000128 incaip_set_cpuclk, /* set cpu clock according to env. variable */
wdenk67f13362003-12-27 19:24:54 +0000129#endif
Wolfgang Denk11f98842011-12-08 02:01:49 +0000130 init_baudrate, /* initialize baudrate settings */
wdenkbb1b8262003-03-27 12:09:35 +0000131 serial_init, /* serial communications setup */
132 console_init_f,
133 display_banner, /* say that we are here */
wdenk8dba0502003-03-31 16:34:49 +0000134 checkboard,
wdenkbb1b8262003-03-27 12:09:35 +0000135 init_func_ram,
136 NULL,
137};
138
139
140void board_init_f(ulong bootflag)
141{
wdenkbb1b8262003-03-27 12:09:35 +0000142 gd_t gd_data, *id;
143 bd_t *bd;
144 init_fnc_t **init_fnc_ptr;
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200145 ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_SYS_MONITOR_BASE;
Wolfgang Denk117b0b12005-12-01 02:15:07 +0100146 ulong *s;
wdenkbb1b8262003-03-27 12:09:35 +0000147
wdenkcd914452004-05-29 16:53:29 +0000148 /* Pointer is writable since we allocated a register for it.
149 */
wdenkbb1b8262003-03-27 12:09:35 +0000150 gd = &gd_data;
wdenk3337af42004-07-01 20:28:03 +0000151 /* compiler optimization barrier needed for GCC >= 3.4 */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000152 __asm__ __volatile__("" : : : "memory");
wdenk3337af42004-07-01 20:28:03 +0000153
Wolfgang Denk11f98842011-12-08 02:01:49 +0000154 memset((void *)gd, 0, sizeof(gd_t));
wdenkbb1b8262003-03-27 12:09:35 +0000155
156 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
Wolfgang Denk11f98842011-12-08 02:01:49 +0000157 if ((*init_fnc_ptr)() != 0)
158 hang();
wdenkbb1b8262003-03-27 12:09:35 +0000159 }
160
161 /*
162 * Now that we have DRAM mapped and working, we can
163 * relocate the code and continue running from DRAM.
164 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200165 addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;
wdenkbb1b8262003-03-27 12:09:35 +0000166
wdenkcd914452004-05-29 16:53:29 +0000167 /* We can reserve some RAM "on top" here.
168 */
wdenkbb1b8262003-03-27 12:09:35 +0000169
wdenkcd914452004-05-29 16:53:29 +0000170 /* round down to next 4 kB limit.
171 */
wdenkbb1b8262003-03-27 12:09:35 +0000172 addr &= ~(4096 - 1);
Wolfgang Denk11f98842011-12-08 02:01:49 +0000173 debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
wdenk57b2d802003-06-27 21:31:46 +0000174
wdenkcd914452004-05-29 16:53:29 +0000175 /* Reserve memory for U-Boot code, data & bss
176 * round down to next 16 kB limit
177 */
wdenkbb1b8262003-03-27 12:09:35 +0000178 addr -= len;
wdenkb9a83a92003-05-30 12:48:29 +0000179 addr &= ~(16 * 1024 - 1);
wdenkbb1b8262003-03-27 12:09:35 +0000180
Wolfgang Denk11f98842011-12-08 02:01:49 +0000181 debug("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr);
wdenkbb1b8262003-03-27 12:09:35 +0000182
wdenkcd914452004-05-29 16:53:29 +0000183 /* Reserve memory for malloc() arena.
184 */
wdenkbb1b8262003-03-27 12:09:35 +0000185 addr_sp = addr - TOTAL_MALLOC_LEN;
Wolfgang Denk11f98842011-12-08 02:01:49 +0000186 debug("Reserving %dk for malloc() at: %08lx\n",
wdenkbb1b8262003-03-27 12:09:35 +0000187 TOTAL_MALLOC_LEN >> 10, addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000188
189 /*
190 * (permanently) allocate a Board Info struct
191 * and a permanent copy of the "global" data
192 */
193 addr_sp -= sizeof(bd_t);
194 bd = (bd_t *)addr_sp;
195 gd->bd = bd;
Wolfgang Denk11f98842011-12-08 02:01:49 +0000196 debug("Reserving %zu Bytes for Board Info at: %08lx\n",
wdenkbb1b8262003-03-27 12:09:35 +0000197 sizeof(bd_t), addr_sp);
wdenkcd914452004-05-29 16:53:29 +0000198
wdenkbb1b8262003-03-27 12:09:35 +0000199 addr_sp -= sizeof(gd_t);
200 id = (gd_t *)addr_sp;
Wolfgang Denk11f98842011-12-08 02:01:49 +0000201 debug("Reserving %zu Bytes for Global Data at: %08lx\n",
202 sizeof(gd_t), addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000203
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100204 /* Reserve memory for boot params.
wdenkcd914452004-05-29 16:53:29 +0000205 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200206 addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN;
wdenkbb1b8262003-03-27 12:09:35 +0000207 bd->bi_boot_params = addr_sp;
Wolfgang Denk11f98842011-12-08 02:01:49 +0000208 debug("Reserving %dk for boot params() at: %08lx\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200209 CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp);
wdenkbb1b8262003-03-27 12:09:35 +0000210
211 /*
212 * Finally, we set up a new (bigger) stack.
213 *
214 * Leave some safety gap for SP, force alignment on 16 byte boundary
215 * Clear initial stack frame
216 */
217 addr_sp -= 16;
218 addr_sp &= ~0xF;
Wolfgang Denk117b0b12005-12-01 02:15:07 +0100219 s = (ulong *)addr_sp;
220 *s-- = 0;
221 *s-- = 0;
222 addr_sp = (ulong)s;
Wolfgang Denk11f98842011-12-08 02:01:49 +0000223 debug("Stack Pointer at: %08lx\n", addr_sp);
wdenkcd914452004-05-29 16:53:29 +0000224
wdenkbb1b8262003-03-27 12:09:35 +0000225 /*
226 * Save local variables to board info struct
227 */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000228 bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM */
229 bd->bi_memsize = gd->ram_size; /* size of DRAM in bytes */
wdenkbb1b8262003-03-27 12:09:35 +0000230 bd->bi_baudrate = gd->baudrate; /* Console Baudrate */
231
Wolfgang Denk11f98842011-12-08 02:01:49 +0000232 memcpy(id, (void *)gd, sizeof(gd_t));
wdenkb02744a2003-04-05 00:53:31 +0000233
Wolfgang Denk11f98842011-12-08 02:01:49 +0000234 relocate_code(addr_sp, id, addr);
wdenkbb1b8262003-03-27 12:09:35 +0000235
236 /* NOTREACHED - relocate_code() does not return */
237}
Wolfgang Denk11f98842011-12-08 02:01:49 +0000238
239/*
wdenkbb1b8262003-03-27 12:09:35 +0000240 * This is the next part if the initialization sequence: we are now
241 * running from RAM and have a "normal" C environment, i. e. global
242 * data can be written, BSS has been cleared, the stack size in not
243 * that critical any more, etc.
wdenkbb1b8262003-03-27 12:09:35 +0000244 */
245
Wolfgang Denk11f98842011-12-08 02:01:49 +0000246void board_init_r(gd_t *id, ulong dest_addr)
wdenkbb1b8262003-03-27 12:09:35 +0000247{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200248#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +0000249 ulong size;
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100250#endif
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200251#ifndef CONFIG_ENV_IS_NOWHERE
Wolfgang Denk11f98842011-12-08 02:01:49 +0000252 extern char *env_name_spec;
wdenkbb1b8262003-03-27 12:09:35 +0000253#endif
wdenkbb1b8262003-03-27 12:09:35 +0000254 bd_t *bd;
wdenkbb1b8262003-03-27 12:09:35 +0000255
256 gd = id;
257 gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
258
Wolfgang Denk11f98842011-12-08 02:01:49 +0000259 debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
wdenkbb1b8262003-03-27 12:09:35 +0000260
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200261 gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
wdenkbb1b8262003-03-27 12:09:35 +0000262
wdenkb9a83a92003-05-30 12:48:29 +0000263 monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
264
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200265#if defined(CONFIG_NEEDS_MANUAL_RELOC)
wdenkbb1b8262003-03-27 12:09:35 +0000266 /*
267 * We have to relocate the command table manually
268 */
Marek Vasut69c5e342012-10-12 10:27:04 +0000269 fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd),
270 ll_entry_count(cmd_tbl_t, cmd));
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200271#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */
wdenkbb1b8262003-03-27 12:09:35 +0000272
wdenkbb1b8262003-03-27 12:09:35 +0000273 /* there are some other pointer constants we must deal with */
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200274#ifndef CONFIG_ENV_IS_NOWHERE
wdenkbb1b8262003-03-27 12:09:35 +0000275 env_name_spec += gd->reloc_off;
276#endif
wdenk57b2d802003-06-27 21:31:46 +0000277
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100278 bd = gd->bd;
279
Peter Tyser781c9b82009-08-21 23:05:21 -0500280 /* The Malloc area is immediately below the monitor copy in DRAM */
Peter Tysered527702009-08-21 23:05:20 -0500281 mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
282 TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
Stefan Roeseb81464e2009-05-11 15:50:12 +0200283 malloc_bin_reloc();
284
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200285#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +0000286 /* configure available FLASH banks */
287 size = flash_init();
Wolfgang Denk11f98842011-12-08 02:01:49 +0000288 display_flash_config(size);
Daniel Schwierzeck0d15d2a2012-04-02 02:57:54 +0000289 bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100290 bd->bi_flashsize = size;
wdenkbb1b8262003-03-27 12:09:35 +0000291
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200292#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
wdenkb9a83a92003-05-30 12:48:29 +0000293 bd->bi_flashoffset = monitor_flash_len; /* reserved area for U-Boot */
wdenkbb1b8262003-03-27 12:09:35 +0000294#else
295 bd->bi_flashoffset = 0;
296#endif
Daniel Schwierzeck0d15d2a2012-04-02 02:57:54 +0000297#else
298 bd->bi_flashstart = 0;
299 bd->bi_flashsize = 0;
300 bd->bi_flashoffset = 0;
301#endif
wdenkbb1b8262003-03-27 12:09:35 +0000302
Stefan Roese1af2a0d2008-11-12 13:18:19 +0100303#ifdef CONFIG_CMD_NAND
Wolfgang Denk11f98842011-12-08 02:01:49 +0000304 puts("NAND: ");
305 nand_init(); /* go init the NAND */
Stefan Roese1af2a0d2008-11-12 13:18:19 +0100306#endif
307
308#if defined(CONFIG_CMD_ONENAND)
309 onenand_init();
310#endif
311
wdenkbb1b8262003-03-27 12:09:35 +0000312 /* relocate environment function pointers etc. */
313 env_relocate();
314
wdenk5401de42004-02-07 01:27:10 +0000315#if defined(CONFIG_PCI)
316 /*
317 * Do pci configuration
318 */
319 pci_init();
320#endif
321
wdenkbb1b8262003-03-27 12:09:35 +0000322/** leave this here (after malloc(), environment and PCI are working) **/
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200323 /* Initialize stdio devices */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000324 stdio_init();
wdenkbb1b8262003-03-27 12:09:35 +0000325
Wolfgang Denk11f98842011-12-08 02:01:49 +0000326 jumptable_init();
wdenkbb1b8262003-03-27 12:09:35 +0000327
328 /* Initialize the console (after the relocation and devices init) */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000329 console_init_r();
wdenkbb1b8262003-03-27 12:09:35 +0000330/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
331
wdenkb02744a2003-04-05 00:53:31 +0000332 /* Initialize from environment */
Simon Glass8ccbef92011-10-13 14:43:11 +0000333 load_addr = getenv_ulong("loadaddr", 16, load_addr);
wdenkb02744a2003-04-05 00:53:31 +0000334
Jason McMullan733ad782008-05-30 00:53:37 +0900335#ifdef CONFIG_CMD_SPI
Wolfgang Denk11f98842011-12-08 02:01:49 +0000336 puts("SPI: ");
337 spi_init(); /* go init the SPI */
338 puts("ready\n");
Jason McMullan733ad782008-05-30 00:53:37 +0900339#endif
340
wdenkb02744a2003-04-05 00:53:31 +0000341#if defined(CONFIG_MISC_INIT_R)
342 /* miscellaneous platform dependent initialisations */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000343 misc_init_r();
wdenkb02744a2003-04-05 00:53:31 +0000344#endif
345
Luigi 'Comio' Mantellini01db1552009-10-10 12:42:21 +0200346#ifdef CONFIG_BITBANGMII
347 bb_miiphy_init();
348#endif
Jon Loeliger6b233052007-07-09 18:02:11 -0500349#if defined(CONFIG_CMD_NET)
Wolfgang Denk11f98842011-12-08 02:01:49 +0000350 puts("Net: ");
wdenkbb1b8262003-03-27 12:09:35 +0000351 eth_initialize(gd->bd);
352#endif
353
354 /* main_loop() can return to retry autoboot, if so just run it again. */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000355 for (;;)
356 main_loop();
wdenkbb1b8262003-03-27 12:09:35 +0000357
358 /* NOTREACHED - no way out of command loop except booting */
359}
360
Wolfgang Denk11f98842011-12-08 02:01:49 +0000361void hang(void)
wdenkbb1b8262003-03-27 12:09:35 +0000362{
Wolfgang Denk11f98842011-12-08 02:01:49 +0000363 puts("### ERROR ### Please RESET the board ###\n");
364 for (;;)
365 ;
wdenkbb1b8262003-03-27 12:09:35 +0000366}