prpmc2800.c 14 KB

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