• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
prpmc2800_get_board_info(u8 * vpd)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 */
prpmc2800_get_bip(void)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 
prpmc2800_bridge_setup(u32 mem_size)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 */
347 	devp = find_node_by_compatible(NULL, "marvell,mv64360-pci");
348 	if (devp == NULL)
349 		fatal("Error: Missing marvell,mv64360-pci"
350 				" device tree node\n\r");
351 
352 	rc = getprop(devp, "ranges", v, sizeof(v));
353 	if (rc != sizeof(v))
354 		fatal("Error: Can't find marvell,mv64360-pci ranges"
355 				" property\n\r");
356 
357 	/* Get the cpu -> pci i/o & mem mappings from the device tree */
358 	devp = find_node_by_compatible(NULL, "marvell,mv64360");
359 	if (devp == NULL)
360 		fatal("Error: Missing marvell,mv64360 device tree node\n\r");
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 
prpmc2800_fixups(void)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 */
432 	devp = find_node_by_prop_value_str(NULL, "device_type", "cpu");
433 	if (devp == NULL)
434 		fatal("Error: Missing proper cpu device tree node\n\r");
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 
446 	/* Update model, if this is a mv64362 */
447 	if (bip->bridge_type == BRIDGE_TYPE_MV64362) {
448 		devp = find_node_by_compatible(NULL, "marvell,mv64360");
449 		if (devp == NULL)
450 			fatal("Error: Missing marvell,mv64360"
451 					" device tree node\n\r");
452 		setprop(devp, "model", "mv64362", strlen("mv64362") + 1);
453 	}
454 
455 	/* Set User FLASH size */
456 	devp = find_node_by_compatible(NULL, "direct-mapped");
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 
prpmc2800_reset(void)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 
platform_init(unsigned long r3,unsigned long r4,unsigned long r5,unsigned long r6,unsigned long r7)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);
551 	fdt_init(dtb);
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 ");
572