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