blob: 62d47a8bf0bb7e79d3b558729bc485a4466b41e2 [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
Wolfgang Denk11f98842011-12-08 02:01:49 +0000251 extern void malloc_bin_reloc(void);
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200252#ifndef CONFIG_ENV_IS_NOWHERE
Wolfgang Denk11f98842011-12-08 02:01:49 +0000253 extern char *env_name_spec;
wdenkbb1b8262003-03-27 12:09:35 +0000254#endif
wdenkbb1b8262003-03-27 12:09:35 +0000255 bd_t *bd;
wdenkbb1b8262003-03-27 12:09:35 +0000256
257 gd = id;
258 gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
259
Wolfgang Denk11f98842011-12-08 02:01:49 +0000260 debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr);
wdenkbb1b8262003-03-27 12:09:35 +0000261
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200262 gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
wdenkbb1b8262003-03-27 12:09:35 +0000263
wdenkb9a83a92003-05-30 12:48:29 +0000264 monitor_flash_len = (ulong)&uboot_end_data - dest_addr;
265
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200266#if defined(CONFIG_NEEDS_MANUAL_RELOC)
wdenkbb1b8262003-03-27 12:09:35 +0000267 /*
268 * We have to relocate the command table manually
269 */
Heiko Schocher092cf162010-09-17 13:10:33 +0200270 fixup_cmdtable(&__u_boot_cmd_start,
271 (ulong)(&__u_boot_cmd_end - &__u_boot_cmd_start));
Wolfgang Denkd0813e52010-10-28 20:00:11 +0200272#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */
wdenkbb1b8262003-03-27 12:09:35 +0000273
wdenkbb1b8262003-03-27 12:09:35 +0000274 /* there are some other pointer constants we must deal with */
Jean-Christophe PLAGNIOL-VILLARD68a87562008-09-10 22:48:00 +0200275#ifndef CONFIG_ENV_IS_NOWHERE
wdenkbb1b8262003-03-27 12:09:35 +0000276 env_name_spec += gd->reloc_off;
277#endif
wdenk57b2d802003-06-27 21:31:46 +0000278
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100279 bd = gd->bd;
280
Peter Tyser781c9b82009-08-21 23:05:21 -0500281 /* The Malloc area is immediately below the monitor copy in DRAM */
Peter Tysered527702009-08-21 23:05:20 -0500282 mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off -
283 TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN);
Stefan Roeseb81464e2009-05-11 15:50:12 +0200284 malloc_bin_reloc();
285
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200286#ifndef CONFIG_SYS_NO_FLASH
wdenkbb1b8262003-03-27 12:09:35 +0000287 /* configure available FLASH banks */
288 size = flash_init();
Wolfgang Denk11f98842011-12-08 02:01:49 +0000289 display_flash_config(size);
Daniel Schwierzeck0d15d2a2012-04-02 02:57:54 +0000290 bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
Jean-Christophe PLAGNIOL-VILLARD3bd04ce2008-02-17 16:58:04 +0100291 bd->bi_flashsize = size;
wdenkbb1b8262003-03-27 12:09:35 +0000292
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200293#if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE
wdenkb9a83a92003-05-30 12:48:29 +0000294 bd->bi_flashoffset = monitor_flash_len; /* reserved area for U-Boot */
wdenkbb1b8262003-03-27 12:09:35 +0000295#else
296 bd->bi_flashoffset = 0;
297#endif
Daniel Schwierzeck0d15d2a2012-04-02 02:57:54 +0000298#else
299 bd->bi_flashstart = 0;
300 bd->bi_flashsize = 0;
301 bd->bi_flashoffset = 0;
302#endif
wdenkbb1b8262003-03-27 12:09:35 +0000303
Stefan Roese1af2a0d2008-11-12 13:18:19 +0100304#ifdef CONFIG_CMD_NAND
Wolfgang Denk11f98842011-12-08 02:01:49 +0000305 puts("NAND: ");
306 nand_init(); /* go init the NAND */
Stefan Roese1af2a0d2008-11-12 13:18:19 +0100307#endif
308
309#if defined(CONFIG_CMD_ONENAND)
310 onenand_init();
311#endif
312
wdenkbb1b8262003-03-27 12:09:35 +0000313 /* relocate environment function pointers etc. */
314 env_relocate();
315
wdenk5401de42004-02-07 01:27:10 +0000316#if defined(CONFIG_PCI)
317 /*
318 * Do pci configuration
319 */
320 pci_init();
321#endif
322
wdenkbb1b8262003-03-27 12:09:35 +0000323/** leave this here (after malloc(), environment and PCI are working) **/
Jean-Christophe PLAGNIOL-VILLARD2a7a0312009-05-16 12:14:54 +0200324 /* Initialize stdio devices */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000325 stdio_init();
wdenkbb1b8262003-03-27 12:09:35 +0000326
Wolfgang Denk11f98842011-12-08 02:01:49 +0000327 jumptable_init();
wdenkbb1b8262003-03-27 12:09:35 +0000328
329 /* Initialize the console (after the relocation and devices init) */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000330 console_init_r();
wdenkbb1b8262003-03-27 12:09:35 +0000331/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
332
wdenkb02744a2003-04-05 00:53:31 +0000333 /* Initialize from environment */
Simon Glass8ccbef92011-10-13 14:43:11 +0000334 load_addr = getenv_ulong("loadaddr", 16, load_addr);
wdenkb02744a2003-04-05 00:53:31 +0000335
Jason McMullan733ad782008-05-30 00:53:37 +0900336#ifdef CONFIG_CMD_SPI
Wolfgang Denk11f98842011-12-08 02:01:49 +0000337 puts("SPI: ");
338 spi_init(); /* go init the SPI */
339 puts("ready\n");
Jason McMullan733ad782008-05-30 00:53:37 +0900340#endif
341
wdenkb02744a2003-04-05 00:53:31 +0000342#if defined(CONFIG_MISC_INIT_R)
343 /* miscellaneous platform dependent initialisations */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000344 misc_init_r();
wdenkb02744a2003-04-05 00:53:31 +0000345#endif
346
Luigi 'Comio' Mantellini01db1552009-10-10 12:42:21 +0200347#ifdef CONFIG_BITBANGMII
348 bb_miiphy_init();
349#endif
Jon Loeliger6b233052007-07-09 18:02:11 -0500350#if defined(CONFIG_CMD_NET)
Wolfgang Denk11f98842011-12-08 02:01:49 +0000351 puts("Net: ");
wdenkbb1b8262003-03-27 12:09:35 +0000352 eth_initialize(gd->bd);
353#endif
354
355 /* main_loop() can return to retry autoboot, if so just run it again. */
Wolfgang Denk11f98842011-12-08 02:01:49 +0000356 for (;;)
357 main_loop();
wdenkbb1b8262003-03-27 12:09:35 +0000358
359 /* NOTREACHED - no way out of command loop except booting */
360}
361
Wolfgang Denk11f98842011-12-08 02:01:49 +0000362void hang(void)
wdenkbb1b8262003-03-27 12:09:35 +0000363{
Wolfgang Denk11f98842011-12-08 02:01:49 +0000364 puts("### ERROR ### Please RESET the board ###\n");
365 for (;;)
366 ;
wdenkbb1b8262003-03-27 12:09:35 +0000367}