Commit | Line | Data |
---|---|---|
c368d921 MG |
1 | /* |
2 | * Motorola ECC prpmc280/f101 & prpmc2800/f101e platform code. | |
3 | * | |
4 | * Author: Mark A. Greer <mgreer@mvista.com> | |
5 | * | |
6 | * 2007 (c) MontaVista, Software, Inc. This file is licensed under | |
7 | * the terms of the GNU General Public License version 2. This program | |
8 | * is licensed "as is" without any warranty of any kind, whether express | |
9 | * or implied. | |
10 | */ | |
11 | ||
12 | #include <stdarg.h> | |
13 | #include <stddef.h> | |
14 | #include "types.h" | |
15 | #include "elf.h" | |
16 | #include "page.h" | |
17 | #include "string.h" | |
18 | #include "stdio.h" | |
19 | #include "io.h" | |
20 | #include "ops.h" | |
21 | #include "gunzip_util.h" | |
22 | #include "mv64x60.h" | |
23 | ||
c368d921 MG |
24 | #define KB 1024U |
25 | #define MB (KB*KB) | |
26 | #define GB (KB*MB) | |
27 | #define MHz (1000U*1000U) | |
28 | #define GHz (1000U*MHz) | |
29 | ||
30 | #define BOARD_MODEL "PrPMC2800" | |
31 | #define BOARD_MODEL_MAX 32 /* max strlen(BOARD_MODEL) + 1 */ | |
32 | ||
33 | #define EEPROM2_ADDR 0xa4 | |
34 | #define EEPROM3_ADDR 0xa8 | |
35 | ||
36 | BSS_STACK(16*KB); | |
37 | ||
38 | static u8 *bridge_base; | |
39 | ||
40 | typedef enum { | |
41 | BOARD_MODEL_PRPMC280, | |
42 | BOARD_MODEL_PRPMC2800, | |
43 | } prpmc2800_board_model; | |
44 | ||
45 | typedef enum { | |
46 | BRIDGE_TYPE_MV64360, | |
47 | BRIDGE_TYPE_MV64362, | |
48 | } prpmc2800_bridge_type; | |
49 | ||
50 | struct prpmc2800_board_info { | |
51 | prpmc2800_board_model model; | |
52 | char variant; | |
53 | prpmc2800_bridge_type bridge_type; | |
54 | u8 subsys0; | |
55 | u8 subsys1; | |
56 | u8 vpd4; | |
57 | u8 vpd4_mask; | |
58 | u32 core_speed; | |
59 | u32 mem_size; | |
60 | u32 boot_flash; | |
61 | u32 user_flash; | |
62 | }; | |
63 | ||
64 | static struct prpmc2800_board_info prpmc2800_board_info[] = { | |
65 | { | |
66 | .model = BOARD_MODEL_PRPMC280, | |
67 | .variant = 'a', | |
68 | .bridge_type = BRIDGE_TYPE_MV64360, | |
69 | .subsys0 = 0xff, | |
70 | .subsys1 = 0xff, | |
71 | .vpd4 = 0x00, | |
72 | .vpd4_mask = 0x0f, | |
73 | .core_speed = 1*GHz, | |
74 | .mem_size = 512*MB, | |
75 | .boot_flash = 1*MB, | |
76 | .user_flash = 64*MB, | |
77 | }, | |
78 | { | |
79 | .model = BOARD_MODEL_PRPMC280, | |
80 | .variant = 'b', | |
81 | .bridge_type = BRIDGE_TYPE_MV64362, | |
82 | .subsys0 = 0xff, | |
83 | .subsys1 = 0xff, | |
84 | .vpd4 = 0x01, | |
85 | .vpd4_mask = 0x0f, | |
86 | .core_speed = 1*GHz, | |
87 | .mem_size = 512*MB, | |
88 | .boot_flash = 0, | |
89 | .user_flash = 0, | |
90 | }, | |
91 | { | |
92 | .model = BOARD_MODEL_PRPMC280, | |
93 | .variant = 'c', | |
94 | .bridge_type = BRIDGE_TYPE_MV64360, | |
95 | .subsys0 = 0xff, | |
96 | .subsys1 = 0xff, | |
97 | .vpd4 = 0x02, | |
98 | .vpd4_mask = 0x0f, | |
99 | .core_speed = 733*MHz, | |
100 | .mem_size = 512*MB, | |
101 | .boot_flash = 1*MB, | |
102 | .user_flash = 64*MB, | |
103 | }, | |
104 | { | |
105 | .model = BOARD_MODEL_PRPMC280, | |
106 | .variant = 'd', | |
107 | .bridge_type = BRIDGE_TYPE_MV64360, | |
108 | .subsys0 = 0xff, | |
109 | .subsys1 = 0xff, | |
110 | .vpd4 = 0x03, | |
111 | .vpd4_mask = 0x0f, | |
112 | .core_speed = 1*GHz, | |
113 | .mem_size = 1*GB, | |
114 | .boot_flash = 1*MB, | |
115 | .user_flash = 64*MB, | |
116 | }, | |
117 | { | |
118 | .model = BOARD_MODEL_PRPMC280, | |
119 | .variant = 'e', | |
120 | .bridge_type = BRIDGE_TYPE_MV64360, | |
121 | .subsys0 = 0xff, | |
122 | .subsys1 = 0xff, | |
123 | .vpd4 = 0x04, | |
124 | .vpd4_mask = 0x0f, | |
125 | .core_speed = 1*GHz, | |
126 | .mem_size = 512*MB, | |
127 | .boot_flash = 1*MB, | |
128 | .user_flash = 64*MB, | |
129 | }, | |
130 | { | |
131 | .model = BOARD_MODEL_PRPMC280, | |
132 | .variant = 'f', | |
133 | .bridge_type = BRIDGE_TYPE_MV64362, | |
134 | .subsys0 = 0xff, | |
135 | .subsys1 = 0xff, | |
136 | .vpd4 = 0x05, | |
137 | .vpd4_mask = 0x0f, | |
138 | .core_speed = 733*MHz, | |
139 | .mem_size = 128*MB, | |
140 | .boot_flash = 1*MB, | |
141 | .user_flash = 0, | |
142 | }, | |
143 | { | |
144 | .model = BOARD_MODEL_PRPMC280, | |
145 | .variant = 'g', | |
146 | .bridge_type = BRIDGE_TYPE_MV64360, | |
147 | .subsys0 = 0xff, | |
148 | .subsys1 = 0xff, | |
149 | .vpd4 = 0x06, | |
150 | .vpd4_mask = 0x0f, | |
151 | .core_speed = 1*GHz, | |
152 | .mem_size = 256*MB, | |
153 | .boot_flash = 1*MB, | |
154 | .user_flash = 0, | |
155 | }, | |
156 | { | |
157 | .model = BOARD_MODEL_PRPMC280, | |
158 | .variant = 'h', | |
159 | .bridge_type = BRIDGE_TYPE_MV64360, | |
160 | .subsys0 = 0xff, | |
161 | .subsys1 = 0xff, | |
162 | .vpd4 = 0x07, | |
163 | .vpd4_mask = 0x0f, | |
164 | .core_speed = 1*GHz, | |
165 | .mem_size = 1*GB, | |
166 | .boot_flash = 1*MB, | |
167 | .user_flash = 64*MB, | |
168 | }, | |
169 | { | |
170 | .model = BOARD_MODEL_PRPMC2800, | |
171 | .variant = 'a', | |
172 | .bridge_type = BRIDGE_TYPE_MV64360, | |
173 | .subsys0 = 0xb2, | |
174 | .subsys1 = 0x8c, | |
175 | .vpd4 = 0x00, | |
176 | .vpd4_mask = 0x00, | |
177 | .core_speed = 1*GHz, | |
178 | .mem_size = 512*MB, | |
179 | .boot_flash = 2*MB, | |
180 | .user_flash = 64*MB, | |
181 | }, | |
182 | { | |
183 | .model = BOARD_MODEL_PRPMC2800, | |
184 | .variant = 'b', | |
185 | .bridge_type = BRIDGE_TYPE_MV64362, | |
186 | .subsys0 = 0xb2, | |
187 | .subsys1 = 0x8d, | |
188 | .vpd4 = 0x00, | |
189 | .vpd4_mask = 0x00, | |
190 | .core_speed = 1*GHz, | |
191 | .mem_size = 512*MB, | |
192 | .boot_flash = 0, | |
193 | .user_flash = 0, | |
194 | }, | |
195 | { | |
196 | .model = BOARD_MODEL_PRPMC2800, | |
197 | .variant = 'c', | |
198 | .bridge_type = BRIDGE_TYPE_MV64360, | |
199 | .subsys0 = 0xb2, | |
200 | .subsys1 = 0x8e, | |
201 | .vpd4 = 0x00, | |
202 | .vpd4_mask = 0x00, | |
203 | .core_speed = 733*MHz, | |
204 | .mem_size = 512*MB, | |
205 | .boot_flash = 2*MB, | |
206 | .user_flash = 64*MB, | |
207 | }, | |
208 | { | |
209 | .model = BOARD_MODEL_PRPMC2800, | |
210 | .variant = 'd', | |
211 | .bridge_type = BRIDGE_TYPE_MV64360, | |
212 | .subsys0 = 0xb2, | |
213 | .subsys1 = 0x8f, | |
214 | .vpd4 = 0x00, | |
215 | .vpd4_mask = 0x00, | |
216 | .core_speed = 1*GHz, | |
217 | .mem_size = 1*GB, | |
218 | .boot_flash = 2*MB, | |
219 | .user_flash = 64*MB, | |
220 | }, | |
221 | { | |
222 | .model = BOARD_MODEL_PRPMC2800, | |
223 | .variant = 'e', | |
224 | .bridge_type = BRIDGE_TYPE_MV64360, | |
225 | .subsys0 = 0xa2, | |
226 | .subsys1 = 0x8a, | |
227 | .vpd4 = 0x00, | |
228 | .vpd4_mask = 0x00, | |
229 | .core_speed = 1*GHz, | |
230 | .mem_size = 512*MB, | |
231 | .boot_flash = 2*MB, | |
232 | .user_flash = 64*MB, | |
233 | }, | |
234 | { | |
235 | .model = BOARD_MODEL_PRPMC2800, | |
236 | .variant = 'f', | |
237 | .bridge_type = BRIDGE_TYPE_MV64362, | |
238 | .subsys0 = 0xa2, | |
239 | .subsys1 = 0x8b, | |
240 | .vpd4 = 0x00, | |
241 | .vpd4_mask = 0x00, | |
242 | .core_speed = 733*MHz, | |
243 | .mem_size = 128*MB, | |
244 | .boot_flash = 2*MB, | |
245 | .user_flash = 0, | |
246 | }, | |
247 | { | |
248 | .model = BOARD_MODEL_PRPMC2800, | |
249 | .variant = 'g', | |
250 | .bridge_type = BRIDGE_TYPE_MV64360, | |
251 | .subsys0 = 0xa2, | |
252 | .subsys1 = 0x8c, | |
253 | .vpd4 = 0x00, | |
254 | .vpd4_mask = 0x00, | |
255 | .core_speed = 1*GHz, | |
256 | .mem_size = 2*GB, | |
257 | .boot_flash = 2*MB, | |
258 | .user_flash = 64*MB, | |
259 | }, | |
260 | { | |
261 | .model = BOARD_MODEL_PRPMC2800, | |
262 | .variant = 'h', | |
263 | .bridge_type = BRIDGE_TYPE_MV64360, | |
264 | .subsys0 = 0xa2, | |
265 | .subsys1 = 0x8d, | |
266 | .vpd4 = 0x00, | |
267 | .vpd4_mask = 0x00, | |
268 | .core_speed = 733*MHz, | |
269 | .mem_size = 1*GB, | |
270 | .boot_flash = 2*MB, | |
271 | .user_flash = 64*MB, | |
272 | }, | |
273 | }; | |
274 | ||
275 | static struct prpmc2800_board_info *prpmc2800_get_board_info(u8 *vpd) | |
276 | { | |
277 | struct prpmc2800_board_info *bip; | |
278 | int i; | |
279 | ||
280 | for (i=0,bip=prpmc2800_board_info; i<ARRAY_SIZE(prpmc2800_board_info); | |
281 | i++,bip++) | |
282 | if ((vpd[0] == bip->subsys0) && (vpd[1] == bip->subsys1) | |
283 | && ((vpd[4] & bip->vpd4_mask) == bip->vpd4)) | |
284 | return bip; | |
285 | ||
286 | return NULL; | |
287 | } | |
288 | ||
289 | /* Get VPD from i2c eeprom 2, then match it to a board info entry */ | |
290 | static struct prpmc2800_board_info *prpmc2800_get_bip(void) | |
291 | { | |
292 | struct prpmc2800_board_info *bip; | |
293 | u8 vpd[5]; | |
294 | int rc; | |
295 | ||
296 | if (mv64x60_i2c_open()) | |
297 | fatal("Error: Can't open i2c device\n\r"); | |
298 | ||
299 | /* Get VPD from i2c eeprom-2 */ | |
300 | memset(vpd, 0, sizeof(vpd)); | |
301 | rc = mv64x60_i2c_read(EEPROM2_ADDR, vpd, 0x1fde, 2, sizeof(vpd)); | |
302 | if (rc < 0) | |
303 | fatal("Error: Couldn't read eeprom2\n\r"); | |
304 | mv64x60_i2c_close(); | |
305 | ||
306 | /* Get board type & related info */ | |
307 | bip = prpmc2800_get_board_info(vpd); | |
308 | if (bip == NULL) { | |
309 | printf("Error: Unsupported board or corrupted VPD:\n\r"); | |
310 | printf(" 0x%x 0x%x 0x%x 0x%x 0x%x\n\r", | |
311 | vpd[0], vpd[1], vpd[2], vpd[3], vpd[4]); | |
312 | printf("Using device tree defaults...\n\r"); | |
313 | } | |
314 | ||
315 | return bip; | |
316 | } | |
317 | ||
318 | static void prpmc2800_bridge_setup(u32 mem_size) | |
319 | { | |
320 | u32 i, v[12], enables, acc_bits; | |
321 | u32 pci_base_hi, pci_base_lo, size, buf[2]; | |
322 | unsigned long cpu_base; | |
323 | int rc; | |
324 | void *devp; | |
325 | u8 *bridge_pbase, is_coherent; | |
326 | struct mv64x60_cpu2pci_win *tbl; | |
327 | ||
328 | bridge_pbase = mv64x60_get_bridge_pbase(); | |
329 | is_coherent = mv64x60_is_coherent(); | |
330 | ||
331 | if (is_coherent) | |
332 | acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB | |
333 | | MV64x60_PCI_ACC_CNTL_SWAP_NONE | |
334 | | MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES | |
335 | | MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES; | |
336 | else | |
337 | acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE | |
338 | | MV64x60_PCI_ACC_CNTL_SWAP_NONE | |
339 | | MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES | |
340 | | MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES; | |
341 | ||
342 | mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent); | |
343 | mv64x60_config_pci_windows(bridge_base, bridge_pbase, 0, 0, mem_size, | |
344 | acc_bits); | |
345 | ||
346 | /* Get the cpu -> pci i/o & mem mappings from the device tree */ | |
a05ce88a | 347 | devp = find_node_by_compatible(NULL, "marvell,mv64360-pci"); |
c368d921 | 348 | if (devp == NULL) |
a05ce88a | 349 | fatal("Error: Missing marvell,mv64360-pci" |
c368d921 MG |
350 | " device tree node\n\r"); |
351 | ||
352 | rc = getprop(devp, "ranges", v, sizeof(v)); | |
353 | if (rc != sizeof(v)) | |
a05ce88a | 354 | fatal("Error: Can't find marvell,mv64360-pci ranges" |
c368d921 MG |
355 | " property\n\r"); |
356 | ||
357 | /* Get the cpu -> pci i/o & mem mappings from the device tree */ | |
a05ce88a | 358 | devp = find_node_by_compatible(NULL, "marvell,mv64360"); |
c368d921 | 359 | if (devp == NULL) |
a05ce88a | 360 | fatal("Error: Missing marvell,mv64360 device tree node\n\r"); |
c368d921 MG |
361 | |
362 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)); | |
363 | enables |= 0x0007fe00; /* Disable all cpu->pci windows */ | |
364 | out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables); | |
365 | ||
366 | for (i=0; i<12; i+=6) { | |
367 | switch (v[i] & 0xff000000) { | |
368 | case 0x01000000: /* PCI I/O Space */ | |
369 | tbl = mv64x60_cpu2pci_io; | |
370 | break; | |
371 | case 0x02000000: /* PCI MEM Space */ | |
372 | tbl = mv64x60_cpu2pci_mem; | |
373 | break; | |
374 | default: | |
375 | continue; | |
376 | } | |
377 | ||
378 | pci_base_hi = v[i+1]; | |
379 | pci_base_lo = v[i+2]; | |
380 | cpu_base = v[i+3]; | |
381 | size = v[i+5]; | |
382 | ||
383 | buf[0] = cpu_base; | |
384 | buf[1] = size; | |
385 | ||
386 | if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base)) | |
387 | fatal("Error: Can't translate PCI address 0x%x\n\r", | |
388 | (u32)cpu_base); | |
389 | ||
390 | mv64x60_config_cpu2pci_window(bridge_base, 0, pci_base_hi, | |
391 | pci_base_lo, cpu_base, size, tbl); | |
392 | } | |
393 | ||
394 | enables &= ~0x00000600; /* Enable cpu->pci0 i/o, cpu->pci0 mem0 */ | |
395 | out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables); | |
396 | } | |
397 | ||
398 | static void prpmc2800_fixups(void) | |
399 | { | |
400 | u32 v[2], l, mem_size; | |
401 | int rc; | |
402 | void *devp; | |
403 | char model[BOARD_MODEL_MAX]; | |
404 | struct prpmc2800_board_info *bip; | |
405 | ||
406 | bip = prpmc2800_get_bip(); /* Get board info based on VPD */ | |
407 | ||
408 | mem_size = (bip) ? bip->mem_size : mv64x60_get_mem_size(bridge_base); | |
409 | prpmc2800_bridge_setup(mem_size); /* Do necessary bridge setup */ | |
410 | ||
411 | /* If the VPD doesn't match what we know about, just use the | |
412 | * defaults already in the device tree. | |
413 | */ | |
414 | if (!bip) | |
415 | return; | |
416 | ||
417 | /* Know the board type so override device tree defaults */ | |
418 | /* Set /model appropriately */ | |
419 | devp = finddevice("/"); | |
420 | if (devp == NULL) | |
421 | fatal("Error: Missing '/' device tree node\n\r"); | |
422 | memset(model, 0, BOARD_MODEL_MAX); | |
423 | strncpy(model, BOARD_MODEL, BOARD_MODEL_MAX - 2); | |
424 | l = strlen(model); | |
425 | if (bip->model == BOARD_MODEL_PRPMC280) | |
426 | l--; | |
427 | model[l++] = bip->variant; | |
428 | model[l++] = '\0'; | |
429 | setprop(devp, "model", model, l); | |
430 | ||
431 | /* Set /cpus/PowerPC,7447/clock-frequency */ | |
a05ce88a | 432 | devp = find_node_by_prop_value_str(NULL, "device_type", "cpu"); |
c368d921 | 433 | if (devp == NULL) |
a05ce88a | 434 | fatal("Error: Missing proper cpu device tree node\n\r"); |
c368d921 MG |
435 | v[0] = bip->core_speed; |
436 | setprop(devp, "clock-frequency", &v[0], sizeof(v[0])); | |
437 | ||
438 | /* Set /memory/reg size */ | |
439 | devp = finddevice("/memory"); | |
440 | if (devp == NULL) | |
441 | fatal("Error: Missing /memory device tree node\n\r"); | |
442 | v[0] = 0; | |
443 | v[1] = bip->mem_size; | |
444 | setprop(devp, "reg", v, sizeof(v)); | |
445 | ||
a05ce88a | 446 | /* Update model, if this is a mv64362 */ |
c368d921 | 447 | if (bip->bridge_type == BRIDGE_TYPE_MV64362) { |
a05ce88a | 448 | devp = find_node_by_compatible(NULL, "marvell,mv64360"); |
c368d921 | 449 | if (devp == NULL) |
a05ce88a DF |
450 | fatal("Error: Missing marvell,mv64360" |
451 | " device tree node\n\r"); | |
c368d921 MG |
452 | setprop(devp, "model", "mv64362", strlen("mv64362") + 1); |
453 | } | |
454 | ||
455 | /* Set User FLASH size */ | |
a05ce88a | 456 | devp = find_node_by_compatible(NULL, "direct-mapped"); |
c368d921 MG |
457 | if (devp == NULL) |
458 | fatal("Error: Missing User FLASH device tree node\n\r"); | |
459 | rc = getprop(devp, "reg", v, sizeof(v)); | |
460 | if (rc != sizeof(v)) | |
461 | fatal("Error: Can't find User FLASH reg property\n\r"); | |
462 | v[1] = bip->user_flash; | |
463 | setprop(devp, "reg", v, sizeof(v)); | |
464 | } | |
465 | ||
466 | #define MV64x60_MPP_CNTL_0 0xf000 | |
467 | #define MV64x60_MPP_CNTL_2 0xf008 | |
468 | #define MV64x60_GPP_IO_CNTL 0xf100 | |
469 | #define MV64x60_GPP_LEVEL_CNTL 0xf110 | |
470 | #define MV64x60_GPP_VALUE_SET 0xf118 | |
471 | ||
472 | static void prpmc2800_reset(void) | |
473 | { | |
474 | u32 temp; | |
475 | ||
476 | udelay(5000000); | |
477 | ||
478 | if (bridge_base != 0) { | |
479 | temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0)); | |
480 | temp &= 0xFFFF0FFF; | |
481 | out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp); | |
482 | ||
483 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); | |
484 | temp |= 0x00000004; | |
485 | out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); | |
486 | ||
487 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); | |
488 | temp |= 0x00000004; | |
489 | out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); | |
490 | ||
491 | temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2)); | |
492 | temp &= 0xFFFF0FFF; | |
493 | out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp); | |
494 | ||
495 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); | |
496 | temp |= 0x00080000; | |
497 | out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); | |
498 | ||
499 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); | |
500 | temp |= 0x00080000; | |
501 | out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); | |
502 | ||
503 | out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET), | |
504 | 0x00080004); | |
505 | } | |
506 | ||
507 | for (;;); | |
508 | } | |
509 | ||
510 | #define HEAP_SIZE (16*MB) | |
511 | static struct gunzip_state gzstate; | |
512 | ||
513 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | |
514 | unsigned long r6, unsigned long r7) | |
515 | { | |
516 | struct elf_info ei; | |
517 | char *heap_start, *dtb; | |
518 | int dt_size = _dtb_end - _dtb_start; | |
519 | void *vmlinuz_addr = _vmlinux_start; | |
520 | unsigned long vmlinuz_size = _vmlinux_end - _vmlinux_start; | |
521 | char elfheader[256]; | |
522 | ||
523 | if (dt_size <= 0) /* No fdt */ | |
524 | exit(); | |
525 | ||
526 | /* | |
527 | * Start heap after end of the kernel (after decompressed to | |
528 | * address 0) or the end of the zImage, whichever is higher. | |
529 | * That's so things allocated by simple_alloc won't overwrite | |
530 | * any part of the zImage and the kernel won't overwrite the dtb | |
531 | * when decompressed & relocated. | |
532 | */ | |
533 | gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size); | |
534 | gunzip_exactly(&gzstate, elfheader, sizeof(elfheader)); | |
535 | ||
536 | if (!parse_elf32(elfheader, &ei)) | |
537 | exit(); | |
538 | ||
539 | heap_start = (char *)(ei.memsize + ei.elfoffset); /* end of kernel*/ | |
540 | heap_start = max(heap_start, (char *)_end); /* end of zImage */ | |
541 | ||
542 | if ((unsigned)simple_alloc_init(heap_start, HEAP_SIZE, 2*KB, 16) | |
543 | > (128*MB)) | |
544 | exit(); | |
545 | ||
546 | /* Relocate dtb to safe area past end of zImage & kernel */ | |
547 | dtb = malloc(dt_size); | |
548 | if (!dtb) | |
549 | exit(); | |
550 | memmove(dtb, _dtb_start, dt_size); | |
2f0dfeaa | 551 | fdt_init(dtb); |
c368d921 MG |
552 | |
553 | bridge_base = mv64x60_get_bridge_base(); | |
554 | ||
555 | platform_ops.fixups = prpmc2800_fixups; | |
556 | platform_ops.exit = prpmc2800_reset; | |
557 | ||
558 | if (serial_console_init() < 0) | |
559 | exit(); | |
560 | } | |
561 | ||
562 | /* _zimage_start called very early--need to turn off external interrupts */ | |
563 | asm (" .globl _zimage_start\n\ | |
564 | _zimage_start:\n\ | |
565 | mfmsr 10\n\ | |
566 | rlwinm 10,10,0,~(1<<15) /* Clear MSR_EE */\n\ | |
567 | sync\n\ | |
568 | mtmsr 10\n\ | |
569 | isync\n\ | |
570 | b _zimage_start_lib\n\ | |
571 | "); |