Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
prpmc2800.c
Go to the documentation of this file.
1 /*
2  * Motorola ECC prpmc280/f101 & prpmc2800/f101e platform code.
3  *
4  * Author: Mark A. Greer <[email protected]>
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 {
44 
45 typedef enum {
49 
52  char variant;
62 };
63 
65  {
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");
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)
336  else
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 
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 
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);
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 ");