]>
Commit | Line | Data |
---|---|---|
c021880a WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
c021880a WD |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <command.h> | |
10 | #include <malloc.h> | |
f88e09de | 11 | #include <serial.h> |
52cb4d4f | 12 | #include <stdio_dev.h> |
c021880a WD |
13 | #include <version.h> |
14 | #include <net.h> | |
15 | #include <environment.h> | |
e996bc33 | 16 | #include <nand.h> |
9d23fc58 | 17 | #include <onenand_uboot.h> |
89a1550e | 18 | #include <spi.h> |
c021880a | 19 | |
310cecb8 LCM |
20 | #ifdef CONFIG_BITBANGMII |
21 | #include <miiphy.h> | |
22 | #endif | |
23 | ||
c75eba3b WD |
24 | DECLARE_GLOBAL_DATA_PTR; |
25 | ||
3b57fe0a WD |
26 | ulong monitor_flash_len; |
27 | ||
c021880a WD |
28 | static char *failed = "*** failed ***\n"; |
29 | ||
5c15010e JCPV |
30 | /* |
31 | * mips_io_port_base is the begin of the address space to which x86 style | |
32 | * I/O ports are mapped. | |
33 | */ | |
f0c27993 | 34 | const unsigned long mips_io_port_base = -1; |
c021880a | 35 | |
db08ecaa SR |
36 | int __board_early_init_f(void) |
37 | { | |
38 | /* | |
39 | * Nothing to do in this dummy implementation | |
40 | */ | |
41 | return 0; | |
42 | } | |
cc257e42 WD |
43 | int board_early_init_f(void) |
44 | __attribute__((weak, alias("__board_early_init_f"))); | |
c021880a | 45 | |
cc257e42 | 46 | static int init_func_ram(void) |
c021880a | 47 | { |
c021880a WD |
48 | #ifdef CONFIG_BOARD_TYPES |
49 | int board_type = gd->board_type; | |
50 | #else | |
51 | int board_type = 0; /* use dummy arg */ | |
52 | #endif | |
cc257e42 | 53 | puts("DRAM: "); |
c021880a | 54 | |
cc257e42 WD |
55 | gd->ram_size = initdram(board_type); |
56 | if (gd->ram_size > 0) { | |
57 | print_size(gd->ram_size, "\n"); | |
58 | return 0; | |
c021880a | 59 | } |
cc257e42 WD |
60 | puts(failed); |
61 | return 1; | |
c021880a WD |
62 | } |
63 | ||
64 | static int display_banner(void) | |
65 | { | |
66 | ||
cc257e42 WD |
67 | printf("\n\n%s\n\n", version_string); |
68 | return 0; | |
c021880a WD |
69 | } |
70 | ||
6d0f6bcf | 71 | #ifndef CONFIG_SYS_NO_FLASH |
c021880a WD |
72 | static void display_flash_config(ulong size) |
73 | { | |
cc257e42 WD |
74 | puts("Flash: "); |
75 | print_size(size, "\n"); | |
c021880a | 76 | } |
beeccf7a | 77 | #endif |
c021880a | 78 | |
cc257e42 | 79 | static int init_baudrate(void) |
c021880a | 80 | { |
98e4611f SG |
81 | gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE); |
82 | return 0; | |
c021880a WD |
83 | } |
84 | ||
85 | ||
86 | /* | |
87 | * Breath some life into the board... | |
88 | * | |
89 | * The first part of initialization is running from Flash memory; | |
90 | * its main purpose is to initialize the RAM so that we | |
91 | * can relocate the monitor code to RAM. | |
92 | */ | |
93 | ||
94 | /* | |
95 | * All attempts to come up with a "common" initialization sequence | |
96 | * that works for all boards and architectures failed: some of the | |
97 | * requirements are just _too_ different. To get rid of the resulting | |
98 | * mess of board dependend #ifdef'ed code we now make the whole | |
99 | * initialization sequence configurable to the user. | |
100 | * | |
101 | * The requirements for any new initalization function is simple: it | |
102 | * receives a pointer to the "global data" structure as it's only | |
103 | * argument, and returns an integer return code, where 0 means | |
104 | * "continue" and != 0 means "fatal error, hang the system". | |
105 | */ | |
cc257e42 | 106 | typedef int (init_fnc_t)(void); |
c021880a WD |
107 | |
108 | init_fnc_t *init_sequence[] = { | |
db08ecaa | 109 | board_early_init_f, |
c021880a WD |
110 | timer_init, |
111 | env_init, /* initialize environment */ | |
7cb22f97 | 112 | #ifdef CONFIG_INCA_IP |
cc257e42 | 113 | incaip_set_cpuclk, /* set cpu clock according to env. variable */ |
7cb22f97 | 114 | #endif |
cc257e42 | 115 | init_baudrate, /* initialize baudrate settings */ |
c021880a WD |
116 | serial_init, /* serial communications setup */ |
117 | console_init_f, | |
118 | display_banner, /* say that we are here */ | |
85ec0bcc | 119 | checkboard, |
c021880a WD |
120 | init_func_ram, |
121 | NULL, | |
122 | }; | |
123 | ||
124 | ||
125 | void board_init_f(ulong bootflag) | |
126 | { | |
c021880a WD |
127 | gd_t gd_data, *id; |
128 | bd_t *bd; | |
129 | init_fnc_t **init_fnc_ptr; | |
eea8a320 | 130 | ulong addr, addr_sp, len; |
c75eba3b | 131 | ulong *s; |
c021880a | 132 | |
69459791 WD |
133 | /* Pointer is writable since we allocated a register for it. |
134 | */ | |
c021880a | 135 | gd = &gd_data; |
93f6a677 | 136 | /* compiler optimization barrier needed for GCC >= 3.4 */ |
cc257e42 | 137 | __asm__ __volatile__("" : : : "memory"); |
93f6a677 | 138 | |
cc257e42 | 139 | memset((void *)gd, 0, sizeof(gd_t)); |
c021880a WD |
140 | |
141 | for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { | |
cc257e42 WD |
142 | if ((*init_fnc_ptr)() != 0) |
143 | hang(); | |
c021880a WD |
144 | } |
145 | ||
146 | /* | |
147 | * Now that we have DRAM mapped and working, we can | |
148 | * relocate the code and continue running from DRAM. | |
149 | */ | |
6d0f6bcf | 150 | addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; |
c021880a | 151 | |
69459791 WD |
152 | /* We can reserve some RAM "on top" here. |
153 | */ | |
c021880a | 154 | |
69459791 WD |
155 | /* round down to next 4 kB limit. |
156 | */ | |
c021880a | 157 | addr &= ~(4096 - 1); |
cc257e42 | 158 | debug("Top of RAM usable for U-Boot at: %08lx\n", addr); |
8bde7f77 | 159 | |
69459791 WD |
160 | /* Reserve memory for U-Boot code, data & bss |
161 | * round down to next 16 kB limit | |
162 | */ | |
eea8a320 | 163 | len = bss_end() - CONFIG_SYS_MONITOR_BASE; |
c021880a | 164 | addr -= len; |
3b57fe0a | 165 | addr &= ~(16 * 1024 - 1); |
c021880a | 166 | |
cc257e42 | 167 | debug("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr); |
c021880a | 168 | |
69459791 WD |
169 | /* Reserve memory for malloc() arena. |
170 | */ | |
c021880a | 171 | addr_sp = addr - TOTAL_MALLOC_LEN; |
cc257e42 | 172 | debug("Reserving %dk for malloc() at: %08lx\n", |
c021880a | 173 | TOTAL_MALLOC_LEN >> 10, addr_sp); |
c021880a WD |
174 | |
175 | /* | |
176 | * (permanently) allocate a Board Info struct | |
177 | * and a permanent copy of the "global" data | |
178 | */ | |
179 | addr_sp -= sizeof(bd_t); | |
180 | bd = (bd_t *)addr_sp; | |
181 | gd->bd = bd; | |
cc257e42 | 182 | debug("Reserving %zu Bytes for Board Info at: %08lx\n", |
c021880a | 183 | sizeof(bd_t), addr_sp); |
69459791 | 184 | |
c021880a WD |
185 | addr_sp -= sizeof(gd_t); |
186 | id = (gd_t *)addr_sp; | |
cc257e42 WD |
187 | debug("Reserving %zu Bytes for Global Data at: %08lx\n", |
188 | sizeof(gd_t), addr_sp); | |
c021880a | 189 | |
beeccf7a | 190 | /* Reserve memory for boot params. |
69459791 | 191 | */ |
6d0f6bcf | 192 | addr_sp -= CONFIG_SYS_BOOTPARAMS_LEN; |
c021880a | 193 | bd->bi_boot_params = addr_sp; |
cc257e42 | 194 | debug("Reserving %dk for boot params() at: %08lx\n", |
6d0f6bcf | 195 | CONFIG_SYS_BOOTPARAMS_LEN >> 10, addr_sp); |
c021880a WD |
196 | |
197 | /* | |
198 | * Finally, we set up a new (bigger) stack. | |
199 | * | |
200 | * Leave some safety gap for SP, force alignment on 16 byte boundary | |
201 | * Clear initial stack frame | |
202 | */ | |
203 | addr_sp -= 16; | |
204 | addr_sp &= ~0xF; | |
c75eba3b WD |
205 | s = (ulong *)addr_sp; |
206 | *s-- = 0; | |
207 | *s-- = 0; | |
208 | addr_sp = (ulong)s; | |
cc257e42 | 209 | debug("Stack Pointer at: %08lx\n", addr_sp); |
69459791 | 210 | |
c021880a WD |
211 | /* |
212 | * Save local variables to board info struct | |
213 | */ | |
cc257e42 WD |
214 | bd->bi_memstart = CONFIG_SYS_SDRAM_BASE; /* start of DRAM */ |
215 | bd->bi_memsize = gd->ram_size; /* size of DRAM in bytes */ | |
c021880a WD |
216 | bd->bi_baudrate = gd->baudrate; /* Console Baudrate */ |
217 | ||
cc257e42 | 218 | memcpy(id, (void *)gd, sizeof(gd_t)); |
3e38691e | 219 | |
cc257e42 | 220 | relocate_code(addr_sp, id, addr); |
c021880a WD |
221 | |
222 | /* NOTREACHED - relocate_code() does not return */ | |
223 | } | |
cc257e42 WD |
224 | |
225 | /* | |
c021880a WD |
226 | * This is the next part if the initialization sequence: we are now |
227 | * running from RAM and have a "normal" C environment, i. e. global | |
228 | * data can be written, BSS has been cleared, the stack size in not | |
229 | * that critical any more, etc. | |
c021880a WD |
230 | */ |
231 | ||
cc257e42 | 232 | void board_init_r(gd_t *id, ulong dest_addr) |
c021880a | 233 | { |
6d0f6bcf | 234 | #ifndef CONFIG_SYS_NO_FLASH |
c021880a | 235 | ulong size; |
c021880a | 236 | #endif |
c021880a | 237 | bd_t *bd; |
c021880a WD |
238 | |
239 | gd = id; | |
240 | gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ | |
241 | ||
cc257e42 | 242 | debug("Now running in RAM - U-Boot at: %08lx\n", dest_addr); |
c021880a | 243 | |
6d0f6bcf | 244 | gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE; |
c021880a | 245 | |
eea8a320 | 246 | monitor_flash_len = image_copy_end() - dest_addr; |
3b57fe0a | 247 | |
f88e09de JH |
248 | serial_initialize(); |
249 | ||
beeccf7a JCPV |
250 | bd = gd->bd; |
251 | ||
d4e8ada0 | 252 | /* The Malloc area is immediately below the monitor copy in DRAM */ |
a483a167 PT |
253 | mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off - |
254 | TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN); | |
c790b04d | 255 | |
6d0f6bcf | 256 | #ifndef CONFIG_SYS_NO_FLASH |
c021880a WD |
257 | /* configure available FLASH banks */ |
258 | size = flash_init(); | |
cc257e42 | 259 | display_flash_config(size); |
71919cf1 | 260 | bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; |
beeccf7a | 261 | bd->bi_flashsize = size; |
c021880a | 262 | |
6d0f6bcf | 263 | #if CONFIG_SYS_MONITOR_BASE == CONFIG_SYS_FLASH_BASE |
3b57fe0a | 264 | bd->bi_flashoffset = monitor_flash_len; /* reserved area for U-Boot */ |
c021880a WD |
265 | #else |
266 | bd->bi_flashoffset = 0; | |
267 | #endif | |
71919cf1 DS |
268 | #else |
269 | bd->bi_flashstart = 0; | |
270 | bd->bi_flashsize = 0; | |
271 | bd->bi_flashoffset = 0; | |
272 | #endif | |
c021880a | 273 | |
9d23fc58 | 274 | #ifdef CONFIG_CMD_NAND |
cc257e42 WD |
275 | puts("NAND: "); |
276 | nand_init(); /* go init the NAND */ | |
9d23fc58 SR |
277 | #endif |
278 | ||
279 | #if defined(CONFIG_CMD_ONENAND) | |
280 | onenand_init(); | |
281 | #endif | |
282 | ||
c021880a WD |
283 | /* relocate environment function pointers etc. */ |
284 | env_relocate(); | |
285 | ||
f4863a7a WD |
286 | #if defined(CONFIG_PCI) |
287 | /* | |
288 | * Do pci configuration | |
289 | */ | |
290 | pci_init(); | |
291 | #endif | |
292 | ||
c021880a | 293 | /** leave this here (after malloc(), environment and PCI are working) **/ |
52cb4d4f | 294 | /* Initialize stdio devices */ |
cc257e42 | 295 | stdio_init(); |
c021880a | 296 | |
cc257e42 | 297 | jumptable_init(); |
c021880a WD |
298 | |
299 | /* Initialize the console (after the relocation and devices init) */ | |
cc257e42 | 300 | console_init_r(); |
c021880a WD |
301 | /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ |
302 | ||
3e38691e | 303 | /* Initialize from environment */ |
98e4611f | 304 | load_addr = getenv_ulong("loadaddr", 16, load_addr); |
3e38691e | 305 | |
89a1550e | 306 | #ifdef CONFIG_CMD_SPI |
cc257e42 WD |
307 | puts("SPI: "); |
308 | spi_init(); /* go init the SPI */ | |
309 | puts("ready\n"); | |
89a1550e JM |
310 | #endif |
311 | ||
3e38691e WD |
312 | #if defined(CONFIG_MISC_INIT_R) |
313 | /* miscellaneous platform dependent initialisations */ | |
cc257e42 | 314 | misc_init_r(); |
3e38691e WD |
315 | #endif |
316 | ||
310cecb8 LCM |
317 | #ifdef CONFIG_BITBANGMII |
318 | bb_miiphy_init(); | |
319 | #endif | |
7def6b34 | 320 | #if defined(CONFIG_CMD_NET) |
cc257e42 | 321 | puts("Net: "); |
c021880a WD |
322 | eth_initialize(gd->bd); |
323 | #endif | |
324 | ||
325 | /* main_loop() can return to retry autoboot, if so just run it again. */ | |
cc257e42 WD |
326 | for (;;) |
327 | main_loop(); | |
c021880a WD |
328 | |
329 | /* NOTREACHED - no way out of command loop except booting */ | |
330 | } |