cpu.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. * Copyright (C) 2004-2006 Freescale Semiconductor, Inc.
  3. *
  4. * See file CREDITS for list of people who contributed to this
  5. * project.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. /*
  23. * CPU specific code for the MPC83xx family.
  24. *
  25. * Derived from the MPC8260 and MPC85xx.
  26. */
  27. #include <common.h>
  28. #include <watchdog.h>
  29. #include <command.h>
  30. #include <mpc83xx.h>
  31. #include <asm/processor.h>
  32. #if defined(CONFIG_OF_FLAT_TREE)
  33. #include <ft_build.h>
  34. #elif defined(CONFIG_OF_LIBFDT)
  35. #include <libfdt.h>
  36. #endif
  37. DECLARE_GLOBAL_DATA_PTR;
  38. int checkcpu(void)
  39. {
  40. volatile immap_t *immr;
  41. ulong clock = gd->cpu_clk;
  42. u32 pvr = get_pvr();
  43. u32 spridr;
  44. char buf[32];
  45. immr = (immap_t *)CFG_IMMR;
  46. puts("CPU: ");
  47. switch (pvr & 0xffff0000) {
  48. case PVR_E300C1:
  49. printf("e300c1, ");
  50. break;
  51. case PVR_E300C2:
  52. printf("e300c2, ");
  53. break;
  54. case PVR_E300C3:
  55. printf("e300c3, ");
  56. break;
  57. default:
  58. printf("Unknown core, ");
  59. }
  60. spridr = immr->sysconf.spridr;
  61. switch(spridr) {
  62. case SPR_8349E_REV10:
  63. case SPR_8349E_REV11:
  64. case SPR_8349E_REV31:
  65. puts("MPC8349E, ");
  66. break;
  67. case SPR_8349_REV10:
  68. case SPR_8349_REV11:
  69. case SPR_8349_REV31:
  70. puts("MPC8349, ");
  71. break;
  72. case SPR_8347E_REV10_TBGA:
  73. case SPR_8347E_REV11_TBGA:
  74. case SPR_8347E_REV31_TBGA:
  75. case SPR_8347E_REV10_PBGA:
  76. case SPR_8347E_REV11_PBGA:
  77. case SPR_8347E_REV31_PBGA:
  78. puts("MPC8347E, ");
  79. break;
  80. case SPR_8347_REV10_TBGA:
  81. case SPR_8347_REV11_TBGA:
  82. case SPR_8347_REV31_TBGA:
  83. case SPR_8347_REV10_PBGA:
  84. case SPR_8347_REV11_PBGA:
  85. case SPR_8347_REV31_PBGA:
  86. puts("MPC8347, ");
  87. break;
  88. case SPR_8343E_REV10:
  89. case SPR_8343E_REV11:
  90. case SPR_8343E_REV31:
  91. puts("MPC8343E, ");
  92. break;
  93. case SPR_8343_REV10:
  94. case SPR_8343_REV11:
  95. case SPR_8343_REV31:
  96. puts("MPC8343, ");
  97. break;
  98. case SPR_8360E_REV10:
  99. case SPR_8360E_REV11:
  100. case SPR_8360E_REV12:
  101. case SPR_8360E_REV20:
  102. case SPR_8360E_REV21:
  103. puts("MPC8360E, ");
  104. break;
  105. case SPR_8360_REV10:
  106. case SPR_8360_REV11:
  107. case SPR_8360_REV12:
  108. case SPR_8360_REV20:
  109. case SPR_8360_REV21:
  110. puts("MPC8360, ");
  111. break;
  112. case SPR_8323E_REV10:
  113. case SPR_8323E_REV11:
  114. puts("MPC8323E, ");
  115. break;
  116. case SPR_8323_REV10:
  117. case SPR_8323_REV11:
  118. puts("MPC8323, ");
  119. break;
  120. case SPR_8321E_REV10:
  121. case SPR_8321E_REV11:
  122. puts("MPC8321E, ");
  123. break;
  124. case SPR_8321_REV10:
  125. case SPR_8321_REV11:
  126. puts("MPC8321, ");
  127. break;
  128. case SPR_8311_REV10:
  129. puts("MPC8311, ");
  130. break;
  131. case SPR_8311E_REV10:
  132. puts("MPC8311E, ");
  133. break;
  134. case SPR_8313_REV10:
  135. puts("MPC8313, ");
  136. break;
  137. case SPR_8313E_REV10:
  138. puts("MPC8313E, ");
  139. break;
  140. default:
  141. printf("Rev: Unknown revision number:%08x\n"
  142. "Warning: Unsupported cpu revision!\n",spridr);
  143. return 0;
  144. }
  145. #if defined(CONFIG_MPC834X)
  146. /* Multiple revisons of 834x processors may have the same SPRIDR value.
  147. * So use PVR to identify the revision number.
  148. */
  149. printf("Rev: %02x at %s MHz", PVR_MAJ(pvr)<<4 | PVR_MIN(pvr), strmhz(buf, clock));
  150. #else
  151. printf("Rev: %02x at %s MHz", spridr & 0x0000FFFF, strmhz(buf, clock));
  152. #endif
  153. printf(", CSB: %4d MHz\n", gd->csb_clk / 1000000);
  154. return 0;
  155. }
  156. /*
  157. * Program a UPM with the code supplied in the table.
  158. *
  159. * The 'dummy' variable is used to increment the MAD. 'dummy' is
  160. * supposed to be a pointer to the memory of the device being
  161. * programmed by the UPM. The data in the MDR is written into
  162. * memory and the MAD is incremented every time there's a read
  163. * from 'dummy'. Unfortunately, the current prototype for this
  164. * function doesn't allow for passing the address of this
  165. * device, and changing the prototype will break a number lots
  166. * of other code, so we need to use a round-about way of finding
  167. * the value for 'dummy'.
  168. *
  169. * The value can be extracted from the base address bits of the
  170. * Base Register (BR) associated with the specific UPM. To find
  171. * that BR, we need to scan all 8 BRs until we find the one that
  172. * has its MSEL bits matching the UPM we want. Once we know the
  173. * right BR, we can extract the base address bits from it.
  174. *
  175. * The MxMR and the BR and OR of the chosen bank should all be
  176. * configured before calling this function.
  177. *
  178. * Parameters:
  179. * upm: 0=UPMA, 1=UPMB, 2=UPMC
  180. * table: Pointer to an array of values to program
  181. * size: Number of elements in the array. Must be 64 or less.
  182. */
  183. void upmconfig (uint upm, uint *table, uint size)
  184. {
  185. #if defined(CONFIG_MPC834X)
  186. volatile immap_t *immap = (immap_t *) CFG_IMMR;
  187. volatile lbus83xx_t *lbus = &immap->lbus;
  188. volatile uchar *dummy = NULL;
  189. const u32 msel = (upm + 4) << BR_MSEL_SHIFT; /* What the MSEL field in BRn should be */
  190. volatile u32 *mxmr = &lbus->mamr + upm; /* Pointer to mamr, mbmr, or mcmr */
  191. uint i;
  192. /* Scan all the banks to determine the base address of the device */
  193. for (i = 0; i < 8; i++) {
  194. if ((lbus->bank[i].br & BR_MSEL) == msel) {
  195. dummy = (uchar *) (lbus->bank[i].br & BR_BA);
  196. break;
  197. }
  198. }
  199. if (!dummy) {
  200. printf("Error: %s() could not find matching BR\n", __FUNCTION__);
  201. hang();
  202. }
  203. /* Set the OP field in the MxMR to "write" and the MAD field to 000000 */
  204. *mxmr = (*mxmr & 0xCFFFFFC0) | 0x10000000;
  205. for (i = 0; i < size; i++) {
  206. lbus->mdr = table[i];
  207. __asm__ __volatile__ ("sync");
  208. *dummy; /* Write the value to memory and increment MAD */
  209. __asm__ __volatile__ ("sync");
  210. }
  211. /* Set the OP field in the MxMR to "normal" and the MAD field to 000000 */
  212. *mxmr &= 0xCFFFFFC0;
  213. #else
  214. printf("Error: %s() not defined for this configuration.\n", __FUNCTION__);
  215. hang();
  216. #endif
  217. }
  218. int
  219. do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
  220. {
  221. ulong msr;
  222. #ifndef MPC83xx_RESET
  223. ulong addr;
  224. #endif
  225. volatile immap_t *immap = (immap_t *) CFG_IMMR;
  226. #ifdef MPC83xx_RESET
  227. /* Interrupts and MMU off */
  228. __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
  229. msr &= ~( MSR_EE | MSR_IR | MSR_DR);
  230. __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
  231. /* enable Reset Control Reg */
  232. immap->reset.rpr = 0x52535445;
  233. __asm__ __volatile__ ("sync");
  234. __asm__ __volatile__ ("isync");
  235. /* confirm Reset Control Reg is enabled */
  236. while(!((immap->reset.rcer) & RCER_CRE));
  237. printf("Resetting the board.");
  238. printf("\n");
  239. udelay(200);
  240. /* perform reset, only one bit */
  241. immap->reset.rcr = RCR_SWHR;
  242. #else /* ! MPC83xx_RESET */
  243. immap->reset.rmr = RMR_CSRE; /* Checkstop Reset enable */
  244. /* Interrupts and MMU off */
  245. __asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
  246. msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
  247. __asm__ __volatile__ ("mtmsr %0"::"r" (msr));
  248. /*
  249. * Trying to execute the next instruction at a non-existing address
  250. * should cause a machine check, resulting in reset
  251. */
  252. addr = CFG_RESET_ADDRESS;
  253. printf("resetting the board.");
  254. printf("\n");
  255. ((void (*)(void)) addr) ();
  256. #endif /* MPC83xx_RESET */
  257. return 1;
  258. }
  259. /*
  260. * Get timebase clock frequency (like cpu_clk in Hz)
  261. */
  262. unsigned long get_tbclk(void)
  263. {
  264. ulong tbclk;
  265. tbclk = (gd->bus_clk + 3L) / 4L;
  266. return tbclk;
  267. }
  268. #if defined(CONFIG_WATCHDOG)
  269. void watchdog_reset (void)
  270. {
  271. int re_enable = disable_interrupts();
  272. /* Reset the 83xx watchdog */
  273. volatile immap_t *immr = (immap_t *) CFG_IMMR;
  274. immr->wdt.swsrr = 0x556c;
  275. immr->wdt.swsrr = 0xaa39;
  276. if (re_enable)
  277. enable_interrupts ();
  278. }
  279. #endif
  280. #if defined(CONFIG_OF_LIBFDT)
  281. /*
  282. * "Setter" functions used to add/modify FDT entries.
  283. */
  284. static int fdt_set_eth0(void *blob, int nodeoffset, const char *name, bd_t *bd)
  285. {
  286. /* Fix it up if it exists, don't create it if it doesn't exist */
  287. if (fdt_get_property(blob, nodeoffset, name, 0)) {
  288. return fdt_setprop(blob, nodeoffset, name, bd->bi_enetaddr, 6);
  289. }
  290. return 0;
  291. }
  292. #ifdef CONFIG_HAS_ETH1
  293. /* second onboard ethernet port */
  294. static int fdt_set_eth1(void *blob, int nodeoffset, const char *name, bd_t *bd)
  295. {
  296. /* Fix it up if it exists, don't create it if it doesn't exist */
  297. if (fdt_get_property(blob, nodeoffset, name, 0)) {
  298. return fdt_setprop(blob, nodeoffset, name, bd->bi_enet1addr, 6);
  299. }
  300. return 0;
  301. }
  302. #endif
  303. #ifdef CONFIG_HAS_ETH2
  304. /* third onboard ethernet port */
  305. static int fdt_set_eth2(void *blob, int nodeoffset, const char *name, bd_t *bd)
  306. {
  307. /* Fix it up if it exists, don't create it if it doesn't exist */
  308. if (fdt_get_property(blob, nodeoffset, name, 0)) {
  309. return fdt_setprop(blob, nodeoffset, name, bd->bi_enet2addr, 6);
  310. }
  311. return 0;
  312. }
  313. #endif
  314. #ifdef CONFIG_HAS_ETH3
  315. /* fourth onboard ethernet port */
  316. static int fdt_set_eth3(void *blob, int nodeoffset, const char *name, bd_t *bd)
  317. {
  318. /* Fix it up if it exists, don't create it if it doesn't exist */
  319. if (fdt_get_property(blob, nodeoffset, name, 0)) {
  320. return fdt_setprop(blob, nodeoffset, name, bd->bi_enet3addr, 6);
  321. }
  322. return 0;
  323. }
  324. #endif
  325. static int fdt_set_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
  326. {
  327. u32 tmp;
  328. /* Create or update the property */
  329. tmp = cpu_to_be32(bd->bi_busfreq);
  330. return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
  331. }
  332. static int fdt_set_tbfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
  333. {
  334. u32 tmp;
  335. /* Create or update the property */
  336. tmp = cpu_to_be32(OF_TBCLK);
  337. return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
  338. }
  339. static int fdt_set_clockfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
  340. {
  341. u32 tmp;
  342. /* Create or update the property */
  343. tmp = cpu_to_be32(gd->core_clk);
  344. return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
  345. }
  346. #ifdef CONFIG_QE
  347. static int fdt_set_qe_busfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
  348. {
  349. u32 tmp;
  350. /* Create or update the property */
  351. tmp = cpu_to_be32(gd->qe_clk);
  352. return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
  353. }
  354. static int fdt_set_qe_brgfreq(void *blob, int nodeoffset, const char *name, bd_t *bd)
  355. {
  356. u32 tmp;
  357. /* Create or update the property */
  358. tmp = cpu_to_be32(gd->brg_clk);
  359. return fdt_setprop(blob, nodeoffset, name, &tmp, sizeof(tmp));
  360. }
  361. #endif
  362. /*
  363. * Fixups to the fdt.
  364. */
  365. static const struct {
  366. char *node;
  367. char *prop;
  368. int (*set_fn)(void *blob, int nodeoffset, const char *name, bd_t *bd);
  369. } fixup_props[] = {
  370. { "/cpus/" OF_CPU,
  371. "timebase-frequency",
  372. fdt_set_tbfreq
  373. },
  374. { "/cpus/" OF_CPU,
  375. "bus-frequency",
  376. fdt_set_busfreq
  377. },
  378. { "/cpus/" OF_CPU,
  379. "clock-frequency",
  380. fdt_set_clockfreq
  381. },
  382. { "/" OF_SOC,
  383. "bus-frequency",
  384. fdt_set_busfreq
  385. },
  386. { "/" OF_SOC "/serial@4500",
  387. "clock-frequency",
  388. fdt_set_busfreq
  389. },
  390. { "/" OF_SOC "/serial@4600",
  391. "clock-frequency",
  392. fdt_set_busfreq
  393. },
  394. #ifdef CONFIG_TSEC1
  395. { "/" OF_SOC "/ethernet@24000",
  396. "mac-address",
  397. fdt_set_eth0
  398. },
  399. { "/" OF_SOC "/ethernet@24000",
  400. "local-mac-address",
  401. fdt_set_eth0
  402. },
  403. #endif
  404. #ifdef CONFIG_TSEC2
  405. { "/" OF_SOC "/ethernet@25000",
  406. "mac-address",
  407. fdt_set_eth1
  408. },
  409. { "/" OF_SOC "/ethernet@25000",
  410. "local-mac-address",
  411. fdt_set_eth1
  412. },
  413. #endif
  414. #ifdef CONFIG_QE
  415. { "/" OF_QE,
  416. "brg-frequency",
  417. fdt_set_qe_brgfreq
  418. },
  419. { "/" OF_QE,
  420. "bus-frequency",
  421. fdt_set_qe_busfreq
  422. },
  423. #ifdef CONFIG_UEC_ETH1
  424. #if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
  425. { "/" OF_QE "/ucc@2000",
  426. "mac-address",
  427. fdt_set_eth0
  428. },
  429. { "/" OF_QE "/ucc@2000",
  430. "local-mac-address",
  431. fdt_set_eth0
  432. },
  433. #elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
  434. { "/" OF_QE "/ucc@2200",
  435. "mac-address",
  436. fdt_set_eth0
  437. },
  438. { "/" OF_QE "/ucc@2200",
  439. "local-mac-address",
  440. fdt_set_eth0
  441. },
  442. #endif
  443. #endif /* CONFIG_UEC_ETH1 */
  444. #ifdef CONFIG_UEC_ETH2
  445. #if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
  446. { "/" OF_QE "/ucc@3000",
  447. "mac-address",
  448. fdt_set_eth1
  449. },
  450. { "/" OF_QE "/ucc@3000",
  451. "local-mac-address",
  452. fdt_set_eth1
  453. },
  454. #elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */
  455. { "/" OF_QE "/ucc@3200",
  456. "mac-address",
  457. fdt_set_eth1
  458. },
  459. { "/" OF_QE "/ucc@3200",
  460. "local-mac-address",
  461. fdt_set_eth1
  462. },
  463. #endif
  464. #endif /* CONFIG_UEC_ETH2 */
  465. #endif /* CONFIG_QE */
  466. };
  467. void
  468. ft_cpu_setup(void *blob, bd_t *bd)
  469. {
  470. int nodeoffset;
  471. int err;
  472. int j;
  473. int tmp[2];
  474. for (j = 0; j < (sizeof(fixup_props) / sizeof(fixup_props[0])); j++) {
  475. nodeoffset = fdt_path_offset(blob, fixup_props[j].node);
  476. if (nodeoffset >= 0) {
  477. err = fixup_props[j].set_fn(blob, nodeoffset,
  478. fixup_props[j].prop, bd);
  479. if (err < 0)
  480. debug("Problem setting %s = %s: %s\n",
  481. fixup_props[j].node, fixup_props[j].prop,
  482. fdt_strerror(err));
  483. } else {
  484. debug("Couldn't find %s: %s\n",
  485. fixup_props[j].node, fdt_strerror(nodeoffset));
  486. }
  487. }
  488. /* update, or add and update /memory node */
  489. nodeoffset = fdt_path_offset(blob, "/memory");
  490. if (nodeoffset < 0) {
  491. nodeoffset = fdt_add_subnode(blob, 0, "memory");
  492. if (nodeoffset < 0)
  493. debug("failed to add /memory node: %s\n",
  494. fdt_strerror(nodeoffset));
  495. }
  496. if (nodeoffset >= 0) {
  497. fdt_setprop(blob, nodeoffset, "device_type",
  498. "memory", sizeof("memory"));
  499. tmp[0] = cpu_to_be32(bd->bi_memstart);
  500. tmp[1] = cpu_to_be32(bd->bi_memsize);
  501. fdt_setprop(blob, nodeoffset, "reg", tmp, sizeof(tmp));
  502. }
  503. }
  504. #elif defined(CONFIG_OF_FLAT_TREE)
  505. void
  506. ft_cpu_setup(void *blob, bd_t *bd)
  507. {
  508. u32 *p;
  509. int len;
  510. ulong clock;
  511. clock = bd->bi_busfreq;
  512. p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
  513. if (p != NULL)
  514. *p = cpu_to_be32(clock);
  515. p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
  516. if (p != NULL)
  517. *p = cpu_to_be32(clock);
  518. p = ft_get_prop(blob, "/" OF_SOC "/serial@4500/clock-frequency", &len);
  519. if (p != NULL)
  520. *p = cpu_to_be32(clock);
  521. p = ft_get_prop(blob, "/" OF_SOC "/serial@4600/clock-frequency", &len);
  522. if (p != NULL)
  523. *p = cpu_to_be32(clock);
  524. #ifdef CONFIG_TSEC1
  525. p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/mac-address", &len);
  526. if (p != NULL)
  527. memcpy(p, bd->bi_enetaddr, 6);
  528. p = ft_get_prop(blob, "/" OF_SOC "/ethernet@24000/local-mac-address", &len);
  529. if (p != NULL)
  530. memcpy(p, bd->bi_enetaddr, 6);
  531. #endif
  532. #ifdef CONFIG_TSEC2
  533. p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/mac-address", &len);
  534. if (p != NULL)
  535. memcpy(p, bd->bi_enet1addr, 6);
  536. p = ft_get_prop(blob, "/" OF_SOC "/ethernet@25000/local-mac-address", &len);
  537. if (p != NULL)
  538. memcpy(p, bd->bi_enet1addr, 6);
  539. #endif
  540. #ifdef CONFIG_UEC_ETH1
  541. #if CFG_UEC1_UCC_NUM == 0 /* UCC1 */
  542. p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/mac-address", &len);
  543. if (p != NULL)
  544. memcpy(p, bd->bi_enetaddr, 6);
  545. p = ft_get_prop(blob, "/" OF_QE "/ucc@2000/local-mac-address", &len);
  546. if (p != NULL)
  547. memcpy(p, bd->bi_enetaddr, 6);
  548. #elif CFG_UEC1_UCC_NUM == 2 /* UCC3 */
  549. p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/mac-address", &len);
  550. if (p != NULL)
  551. memcpy(p, bd->bi_enetaddr, 6);
  552. p = ft_get_prop(blob, "/" OF_QE "/ucc@2200/local-mac-address", &len);
  553. if (p != NULL)
  554. memcpy(p, bd->bi_enetaddr, 6);
  555. #endif
  556. #endif
  557. #ifdef CONFIG_UEC_ETH2
  558. #if CFG_UEC2_UCC_NUM == 1 /* UCC2 */
  559. p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/mac-address", &len);
  560. if (p != NULL)
  561. memcpy(p, bd->bi_enet1addr, 6);
  562. p = ft_get_prop(blob, "/" OF_QE "/ucc@3000/local-mac-address", &len);
  563. if (p != NULL)
  564. memcpy(p, bd->bi_enet1addr, 6);
  565. #elif CFG_UEC2_UCC_NUM == 3 /* UCC4 */
  566. p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/mac-address", &len);
  567. if (p != NULL)
  568. memcpy(p, bd->bi_enet1addr, 6);
  569. p = ft_get_prop(blob, "/" OF_QE "/ucc@3200/local-mac-address", &len);
  570. if (p != NULL)
  571. memcpy(p, bd->bi_enet1addr, 6);
  572. #endif
  573. #endif
  574. }
  575. #endif
  576. #if defined(CONFIG_DDR_ECC)
  577. void dma_init(void)
  578. {
  579. volatile immap_t *immap = (immap_t *)CFG_IMMR;
  580. volatile dma83xx_t *dma = &immap->dma;
  581. volatile u32 status = swab32(dma->dmasr0);
  582. volatile u32 dmamr0 = swab32(dma->dmamr0);
  583. debug("DMA-init\n");
  584. /* initialize DMASARn, DMADAR and DMAABCRn */
  585. dma->dmadar0 = (u32)0;
  586. dma->dmasar0 = (u32)0;
  587. dma->dmabcr0 = 0;
  588. __asm__ __volatile__ ("sync");
  589. __asm__ __volatile__ ("isync");
  590. /* clear CS bit */
  591. dmamr0 &= ~DMA_CHANNEL_START;
  592. dma->dmamr0 = swab32(dmamr0);
  593. __asm__ __volatile__ ("sync");
  594. __asm__ __volatile__ ("isync");
  595. /* while the channel is busy, spin */
  596. while(status & DMA_CHANNEL_BUSY) {
  597. status = swab32(dma->dmasr0);
  598. }
  599. debug("DMA-init end\n");
  600. }
  601. uint dma_check(void)
  602. {
  603. volatile immap_t *immap = (immap_t *)CFG_IMMR;
  604. volatile dma83xx_t *dma = &immap->dma;
  605. volatile u32 status = swab32(dma->dmasr0);
  606. volatile u32 byte_count = swab32(dma->dmabcr0);
  607. /* while the channel is busy, spin */
  608. while (status & DMA_CHANNEL_BUSY) {
  609. status = swab32(dma->dmasr0);
  610. }
  611. if (status & DMA_CHANNEL_TRANSFER_ERROR) {
  612. printf ("DMA Error: status = %x @ %d\n", status, byte_count);
  613. }
  614. return status;
  615. }
  616. int dma_xfer(void *dest, u32 count, void *src)
  617. {
  618. volatile immap_t *immap = (immap_t *)CFG_IMMR;
  619. volatile dma83xx_t *dma = &immap->dma;
  620. volatile u32 dmamr0;
  621. /* initialize DMASARn, DMADAR and DMAABCRn */
  622. dma->dmadar0 = swab32((u32)dest);
  623. dma->dmasar0 = swab32((u32)src);
  624. dma->dmabcr0 = swab32(count);
  625. __asm__ __volatile__ ("sync");
  626. __asm__ __volatile__ ("isync");
  627. /* init direct transfer, clear CS bit */
  628. dmamr0 = (DMA_CHANNEL_TRANSFER_MODE_DIRECT |
  629. DMA_CHANNEL_SOURCE_ADDRESS_HOLD_8B |
  630. DMA_CHANNEL_SOURCE_ADRESSS_HOLD_EN);
  631. dma->dmamr0 = swab32(dmamr0);
  632. __asm__ __volatile__ ("sync");
  633. __asm__ __volatile__ ("isync");
  634. /* set CS to start DMA transfer */
  635. dmamr0 |= DMA_CHANNEL_START;
  636. dma->dmamr0 = swab32(dmamr0);
  637. __asm__ __volatile__ ("sync");
  638. __asm__ __volatile__ ("isync");
  639. return ((int)dma_check());
  640. }
  641. #endif /*CONFIG_DDR_ECC*/