cmd_mem.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. /*
  8. * Memory Functions
  9. *
  10. * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
  11. */
  12. #include <common.h>
  13. #include <command.h>
  14. #ifdef CONFIG_HAS_DATAFLASH
  15. #include <dataflash.h>
  16. #endif
  17. #include <hash.h>
  18. #include <watchdog.h>
  19. #include <asm/io.h>
  20. #include <linux/compiler.h>
  21. DECLARE_GLOBAL_DATA_PTR;
  22. #ifndef CONFIG_SYS_MEMTEST_SCRATCH
  23. #define CONFIG_SYS_MEMTEST_SCRATCH 0
  24. #endif
  25. static int mod_mem(cmd_tbl_t *, int, int, int, char * const []);
  26. /* Display values from last command.
  27. * Memory modify remembered values are different from display memory.
  28. */
  29. static uint dp_last_addr, dp_last_size;
  30. static uint dp_last_length = 0x40;
  31. static uint mm_last_addr, mm_last_size;
  32. static ulong base_address = 0;
  33. /* Memory Display
  34. *
  35. * Syntax:
  36. * md{.b, .w, .l} {addr} {len}
  37. */
  38. #define DISP_LINE_LEN 16
  39. static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  40. {
  41. ulong addr, length;
  42. #if defined(CONFIG_HAS_DATAFLASH)
  43. ulong nbytes, linebytes;
  44. #endif
  45. int size;
  46. int rc = 0;
  47. /* We use the last specified parameters, unless new ones are
  48. * entered.
  49. */
  50. addr = dp_last_addr;
  51. size = dp_last_size;
  52. length = dp_last_length;
  53. if (argc < 2)
  54. return CMD_RET_USAGE;
  55. if ((flag & CMD_FLAG_REPEAT) == 0) {
  56. /* New command specified. Check for a size specification.
  57. * Defaults to long if no or incorrect specification.
  58. */
  59. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  60. return 1;
  61. /* Address is specified since argc > 1
  62. */
  63. addr = simple_strtoul(argv[1], NULL, 16);
  64. addr += base_address;
  65. /* If another parameter, it is the length to display.
  66. * Length is the number of objects, not number of bytes.
  67. */
  68. if (argc > 2)
  69. length = simple_strtoul(argv[2], NULL, 16);
  70. }
  71. #if defined(CONFIG_HAS_DATAFLASH)
  72. /* Print the lines.
  73. *
  74. * We buffer all read data, so we can make sure data is read only
  75. * once, and all accesses are with the specified bus width.
  76. */
  77. nbytes = length * size;
  78. do {
  79. char linebuf[DISP_LINE_LEN];
  80. void* p;
  81. linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
  82. rc = read_dataflash(addr, (linebytes/size)*size, linebuf);
  83. p = (rc == DATAFLASH_OK) ? linebuf : (void*)addr;
  84. print_buffer(addr, p, size, linebytes/size, DISP_LINE_LEN/size);
  85. nbytes -= linebytes;
  86. addr += linebytes;
  87. if (ctrlc()) {
  88. rc = 1;
  89. break;
  90. }
  91. } while (nbytes > 0);
  92. #else
  93. # if defined(CONFIG_BLACKFIN)
  94. /* See if we're trying to display L1 inst */
  95. if (addr_bfin_on_chip_mem(addr)) {
  96. char linebuf[DISP_LINE_LEN];
  97. ulong linebytes, nbytes = length * size;
  98. do {
  99. linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
  100. memcpy(linebuf, (void *)addr, linebytes);
  101. print_buffer(addr, linebuf, size, linebytes/size, DISP_LINE_LEN/size);
  102. nbytes -= linebytes;
  103. addr += linebytes;
  104. if (ctrlc()) {
  105. rc = 1;
  106. break;
  107. }
  108. } while (nbytes > 0);
  109. } else
  110. # endif
  111. {
  112. ulong bytes = size * length;
  113. const void *buf = map_sysmem(addr, bytes);
  114. /* Print the lines. */
  115. print_buffer(addr, buf, size, length, DISP_LINE_LEN / size);
  116. addr += bytes;
  117. unmap_sysmem(buf);
  118. }
  119. #endif
  120. dp_last_addr = addr;
  121. dp_last_length = length;
  122. dp_last_size = size;
  123. return (rc);
  124. }
  125. static int do_mem_mm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  126. {
  127. return mod_mem (cmdtp, 1, flag, argc, argv);
  128. }
  129. static int do_mem_nm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  130. {
  131. return mod_mem (cmdtp, 0, flag, argc, argv);
  132. }
  133. static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  134. {
  135. ulong addr, writeval, count;
  136. int size;
  137. void *buf;
  138. ulong bytes;
  139. if ((argc < 3) || (argc > 4))
  140. return CMD_RET_USAGE;
  141. /* Check for size specification.
  142. */
  143. if ((size = cmd_get_data_size(argv[0], 4)) < 1)
  144. return 1;
  145. /* Address is specified since argc > 1
  146. */
  147. addr = simple_strtoul(argv[1], NULL, 16);
  148. addr += base_address;
  149. /* Get the value to write.
  150. */
  151. writeval = simple_strtoul(argv[2], NULL, 16);
  152. /* Count ? */
  153. if (argc == 4) {
  154. count = simple_strtoul(argv[3], NULL, 16);
  155. } else {
  156. count = 1;
  157. }
  158. bytes = size * count;
  159. buf = map_sysmem(addr, bytes);
  160. while (count-- > 0) {
  161. if (size == 4)
  162. *((ulong *)buf) = (ulong)writeval;
  163. else if (size == 2)
  164. *((ushort *)buf) = (ushort)writeval;
  165. else
  166. *((u_char *)buf) = (u_char)writeval;
  167. buf += size;
  168. }
  169. unmap_sysmem(buf);
  170. return 0;
  171. }
  172. #ifdef CONFIG_MX_CYCLIC
  173. int do_mem_mdc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  174. {
  175. int i;
  176. ulong count;
  177. if (argc < 4)
  178. return CMD_RET_USAGE;
  179. count = simple_strtoul(argv[3], NULL, 10);
  180. for (;;) {
  181. do_mem_md (NULL, 0, 3, argv);
  182. /* delay for <count> ms... */
  183. for (i=0; i<count; i++)
  184. udelay (1000);
  185. /* check for ctrl-c to abort... */
  186. if (ctrlc()) {
  187. puts("Abort\n");
  188. return 0;
  189. }
  190. }
  191. return 0;
  192. }
  193. int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  194. {
  195. int i;
  196. ulong count;
  197. if (argc < 4)
  198. return CMD_RET_USAGE;
  199. count = simple_strtoul(argv[3], NULL, 10);
  200. for (;;) {
  201. do_mem_mw (NULL, 0, 3, argv);
  202. /* delay for <count> ms... */
  203. for (i=0; i<count; i++)
  204. udelay (1000);
  205. /* check for ctrl-c to abort... */
  206. if (ctrlc()) {
  207. puts("Abort\n");
  208. return 0;
  209. }
  210. }
  211. return 0;
  212. }
  213. #endif /* CONFIG_MX_CYCLIC */
  214. static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  215. {
  216. ulong addr1, addr2, count, ngood, bytes;
  217. int size;
  218. int rcode = 0;
  219. const char *type;
  220. const void *buf1, *buf2, *base;
  221. if (argc != 4)
  222. return CMD_RET_USAGE;
  223. /* Check for size specification.
  224. */
  225. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  226. return 1;
  227. type = size == 4 ? "word" : size == 2 ? "halfword" : "byte";
  228. addr1 = simple_strtoul(argv[1], NULL, 16);
  229. addr1 += base_address;
  230. addr2 = simple_strtoul(argv[2], NULL, 16);
  231. addr2 += base_address;
  232. count = simple_strtoul(argv[3], NULL, 16);
  233. #ifdef CONFIG_HAS_DATAFLASH
  234. if (addr_dataflash(addr1) | addr_dataflash(addr2)){
  235. puts ("Comparison with DataFlash space not supported.\n\r");
  236. return 0;
  237. }
  238. #endif
  239. #ifdef CONFIG_BLACKFIN
  240. if (addr_bfin_on_chip_mem(addr1) || addr_bfin_on_chip_mem(addr2)) {
  241. puts ("Comparison with L1 instruction memory not supported.\n\r");
  242. return 0;
  243. }
  244. #endif
  245. bytes = size * count;
  246. base = buf1 = map_sysmem(addr1, bytes);
  247. buf2 = map_sysmem(addr2, bytes);
  248. for (ngood = 0; ngood < count; ++ngood) {
  249. ulong word1, word2;
  250. if (size == 4) {
  251. word1 = *(ulong *)buf1;
  252. word2 = *(ulong *)buf2;
  253. } else if (size == 2) {
  254. word1 = *(ushort *)buf1;
  255. word2 = *(ushort *)buf2;
  256. } else {
  257. word1 = *(u_char *)buf1;
  258. word2 = *(u_char *)buf2;
  259. }
  260. if (word1 != word2) {
  261. ulong offset = buf1 - base;
  262. printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n",
  263. type, (ulong)(addr1 + offset), size, word1,
  264. type, (ulong)(addr2 + offset), size, word2);
  265. rcode = 1;
  266. break;
  267. }
  268. buf1 += size;
  269. buf2 += size;
  270. /* reset watchdog from time to time */
  271. if ((ngood % (64 << 10)) == 0)
  272. WATCHDOG_RESET();
  273. }
  274. unmap_sysmem(buf1);
  275. unmap_sysmem(buf2);
  276. printf("Total of %ld %s(s) were the same\n", ngood, type);
  277. return rcode;
  278. }
  279. static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  280. {
  281. ulong addr, dest, count, bytes;
  282. int size;
  283. const void *src;
  284. void *buf;
  285. if (argc != 4)
  286. return CMD_RET_USAGE;
  287. /* Check for size specification.
  288. */
  289. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  290. return 1;
  291. addr = simple_strtoul(argv[1], NULL, 16);
  292. addr += base_address;
  293. dest = simple_strtoul(argv[2], NULL, 16);
  294. dest += base_address;
  295. count = simple_strtoul(argv[3], NULL, 16);
  296. if (count == 0) {
  297. puts ("Zero length ???\n");
  298. return 1;
  299. }
  300. #ifndef CONFIG_SYS_NO_FLASH
  301. /* check if we are copying to Flash */
  302. if ( (addr2info(dest) != NULL)
  303. #ifdef CONFIG_HAS_DATAFLASH
  304. && (!addr_dataflash(dest))
  305. #endif
  306. ) {
  307. int rc;
  308. puts ("Copy to Flash... ");
  309. rc = flash_write ((char *)addr, dest, count*size);
  310. if (rc != 0) {
  311. flash_perror (rc);
  312. return (1);
  313. }
  314. puts ("done\n");
  315. return 0;
  316. }
  317. #endif
  318. #ifdef CONFIG_HAS_DATAFLASH
  319. /* Check if we are copying from RAM or Flash to DataFlash */
  320. if (addr_dataflash(dest) && !addr_dataflash(addr)){
  321. int rc;
  322. puts ("Copy to DataFlash... ");
  323. rc = write_dataflash (dest, addr, count*size);
  324. if (rc != 1) {
  325. dataflash_perror (rc);
  326. return (1);
  327. }
  328. puts ("done\n");
  329. return 0;
  330. }
  331. /* Check if we are copying from DataFlash to RAM */
  332. if (addr_dataflash(addr) && !addr_dataflash(dest)
  333. #ifndef CONFIG_SYS_NO_FLASH
  334. && (addr2info(dest) == NULL)
  335. #endif
  336. ){
  337. int rc;
  338. rc = read_dataflash(addr, count * size, (char *) dest);
  339. if (rc != 1) {
  340. dataflash_perror (rc);
  341. return (1);
  342. }
  343. return 0;
  344. }
  345. if (addr_dataflash(addr) && addr_dataflash(dest)){
  346. puts ("Unsupported combination of source/destination.\n\r");
  347. return 1;
  348. }
  349. #endif
  350. #ifdef CONFIG_BLACKFIN
  351. /* See if we're copying to/from L1 inst */
  352. if (addr_bfin_on_chip_mem(dest) || addr_bfin_on_chip_mem(addr)) {
  353. memcpy((void *)dest, (void *)addr, count * size);
  354. return 0;
  355. }
  356. #endif
  357. bytes = size * count;
  358. buf = map_sysmem(dest, bytes);
  359. src = map_sysmem(addr, bytes);
  360. while (count-- > 0) {
  361. if (size == 4)
  362. *((ulong *)buf) = *((ulong *)src);
  363. else if (size == 2)
  364. *((ushort *)buf) = *((ushort *)src);
  365. else
  366. *((u_char *)buf) = *((u_char *)src);
  367. src += size;
  368. buf += size;
  369. /* reset watchdog from time to time */
  370. if ((count % (64 << 10)) == 0)
  371. WATCHDOG_RESET();
  372. }
  373. return 0;
  374. }
  375. static int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc,
  376. char * const argv[])
  377. {
  378. if (argc > 1) {
  379. /* Set new base address.
  380. */
  381. base_address = simple_strtoul(argv[1], NULL, 16);
  382. }
  383. /* Print the current base address.
  384. */
  385. printf("Base Address: 0x%08lx\n", base_address);
  386. return 0;
  387. }
  388. static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc,
  389. char * const argv[])
  390. {
  391. ulong addr, length, i, bytes;
  392. int size;
  393. volatile uint *longp;
  394. volatile ushort *shortp;
  395. volatile u_char *cp;
  396. const void *buf;
  397. if (argc < 3)
  398. return CMD_RET_USAGE;
  399. /*
  400. * Check for a size specification.
  401. * Defaults to long if no or incorrect specification.
  402. */
  403. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  404. return 1;
  405. /* Address is always specified.
  406. */
  407. addr = simple_strtoul(argv[1], NULL, 16);
  408. /* Length is the number of objects, not number of bytes.
  409. */
  410. length = simple_strtoul(argv[2], NULL, 16);
  411. bytes = size * length;
  412. buf = map_sysmem(addr, bytes);
  413. /* We want to optimize the loops to run as fast as possible.
  414. * If we have only one object, just run infinite loops.
  415. */
  416. if (length == 1) {
  417. if (size == 4) {
  418. longp = (uint *)buf;
  419. for (;;)
  420. i = *longp;
  421. }
  422. if (size == 2) {
  423. shortp = (ushort *)buf;
  424. for (;;)
  425. i = *shortp;
  426. }
  427. cp = (u_char *)buf;
  428. for (;;)
  429. i = *cp;
  430. }
  431. if (size == 4) {
  432. for (;;) {
  433. longp = (uint *)buf;
  434. i = length;
  435. while (i-- > 0)
  436. *longp++;
  437. }
  438. }
  439. if (size == 2) {
  440. for (;;) {
  441. shortp = (ushort *)buf;
  442. i = length;
  443. while (i-- > 0)
  444. *shortp++;
  445. }
  446. }
  447. for (;;) {
  448. cp = (u_char *)buf;
  449. i = length;
  450. while (i-- > 0)
  451. *cp++;
  452. }
  453. unmap_sysmem(buf);
  454. return 0;
  455. }
  456. #ifdef CONFIG_LOOPW
  457. int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  458. {
  459. ulong addr, length, i, data, bytes;
  460. int size;
  461. volatile uint *longp;
  462. volatile ushort *shortp;
  463. volatile u_char *cp;
  464. void *buf;
  465. if (argc < 4)
  466. return CMD_RET_USAGE;
  467. /*
  468. * Check for a size specification.
  469. * Defaults to long if no or incorrect specification.
  470. */
  471. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  472. return 1;
  473. /* Address is always specified.
  474. */
  475. addr = simple_strtoul(argv[1], NULL, 16);
  476. /* Length is the number of objects, not number of bytes.
  477. */
  478. length = simple_strtoul(argv[2], NULL, 16);
  479. /* data to write */
  480. data = simple_strtoul(argv[3], NULL, 16);
  481. bytes = size * length;
  482. buf = map_sysmem(addr, bytes);
  483. /* We want to optimize the loops to run as fast as possible.
  484. * If we have only one object, just run infinite loops.
  485. */
  486. if (length == 1) {
  487. if (size == 4) {
  488. longp = (uint *)buf;
  489. for (;;)
  490. *longp = data;
  491. }
  492. if (size == 2) {
  493. shortp = (ushort *)buf;
  494. for (;;)
  495. *shortp = data;
  496. }
  497. cp = (u_char *)buf;
  498. for (;;)
  499. *cp = data;
  500. }
  501. if (size == 4) {
  502. for (;;) {
  503. longp = (uint *)buf;
  504. i = length;
  505. while (i-- > 0)
  506. *longp++ = data;
  507. }
  508. }
  509. if (size == 2) {
  510. for (;;) {
  511. shortp = (ushort *)buf;
  512. i = length;
  513. while (i-- > 0)
  514. *shortp++ = data;
  515. }
  516. }
  517. for (;;) {
  518. cp = (u_char *)buf;
  519. i = length;
  520. while (i-- > 0)
  521. *cp++ = data;
  522. }
  523. }
  524. #endif /* CONFIG_LOOPW */
  525. #ifdef CONFIG_CMD_MEMTEST
  526. static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr,
  527. vu_long *dummy)
  528. {
  529. vu_long *addr;
  530. ulong errs = 0;
  531. ulong val, readback;
  532. int j;
  533. vu_long offset;
  534. vu_long test_offset;
  535. vu_long pattern;
  536. vu_long temp;
  537. vu_long anti_pattern;
  538. vu_long num_words;
  539. static const ulong bitpattern[] = {
  540. 0x00000001, /* single bit */
  541. 0x00000003, /* two adjacent bits */
  542. 0x00000007, /* three adjacent bits */
  543. 0x0000000F, /* four adjacent bits */
  544. 0x00000005, /* two non-adjacent bits */
  545. 0x00000015, /* three non-adjacent bits */
  546. 0x00000055, /* four non-adjacent bits */
  547. 0xaaaaaaaa, /* alternating 1/0 */
  548. };
  549. num_words = (end_addr - start_addr) / sizeof(vu_long);
  550. /*
  551. * Data line test: write a pattern to the first
  552. * location, write the 1's complement to a 'parking'
  553. * address (changes the state of the data bus so a
  554. * floating bus doesn't give a false OK), and then
  555. * read the value back. Note that we read it back
  556. * into a variable because the next time we read it,
  557. * it might be right (been there, tough to explain to
  558. * the quality guys why it prints a failure when the
  559. * "is" and "should be" are obviously the same in the
  560. * error message).
  561. *
  562. * Rather than exhaustively testing, we test some
  563. * patterns by shifting '1' bits through a field of
  564. * '0's and '0' bits through a field of '1's (i.e.
  565. * pattern and ~pattern).
  566. */
  567. addr = buf;
  568. for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
  569. val = bitpattern[j];
  570. for (; val != 0; val <<= 1) {
  571. *addr = val;
  572. *dummy = ~val; /* clear the test data off the bus */
  573. readback = *addr;
  574. if (readback != val) {
  575. printf("FAILURE (data line): "
  576. "expected %08lx, actual %08lx\n",
  577. val, readback);
  578. errs++;
  579. if (ctrlc())
  580. return -1;
  581. }
  582. *addr = ~val;
  583. *dummy = val;
  584. readback = *addr;
  585. if (readback != ~val) {
  586. printf("FAILURE (data line): "
  587. "Is %08lx, should be %08lx\n",
  588. readback, ~val);
  589. errs++;
  590. if (ctrlc())
  591. return -1;
  592. }
  593. }
  594. }
  595. /*
  596. * Based on code whose Original Author and Copyright
  597. * information follows: Copyright (c) 1998 by Michael
  598. * Barr. This software is placed into the public
  599. * domain and may be used for any purpose. However,
  600. * this notice must not be changed or removed and no
  601. * warranty is either expressed or implied by its
  602. * publication or distribution.
  603. */
  604. /*
  605. * Address line test
  606. * Description: Test the address bus wiring in a
  607. * memory region by performing a walking
  608. * 1's test on the relevant bits of the
  609. * address and checking for aliasing.
  610. * This test will find single-bit
  611. * address failures such as stuck-high,
  612. * stuck-low, and shorted pins. The base
  613. * address and size of the region are
  614. * selected by the caller.
  615. * Notes: For best results, the selected base
  616. * address should have enough LSB 0's to
  617. * guarantee single address bit changes.
  618. * For example, to test a 64-Kbyte
  619. * region, select a base address on a
  620. * 64-Kbyte boundary. Also, select the
  621. * region size as a power-of-two if at
  622. * all possible.
  623. *
  624. * Returns: 0 if the test succeeds, 1 if the test fails.
  625. */
  626. pattern = (vu_long) 0xaaaaaaaa;
  627. anti_pattern = (vu_long) 0x55555555;
  628. debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words);
  629. /*
  630. * Write the default pattern at each of the
  631. * power-of-two offsets.
  632. */
  633. for (offset = 1; offset < num_words; offset <<= 1)
  634. addr[offset] = pattern;
  635. /*
  636. * Check for address bits stuck high.
  637. */
  638. test_offset = 0;
  639. addr[test_offset] = anti_pattern;
  640. for (offset = 1; offset < num_words; offset <<= 1) {
  641. temp = addr[offset];
  642. if (temp != pattern) {
  643. printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
  644. " expected 0x%.8lx, actual 0x%.8lx\n",
  645. start_addr + offset, pattern, temp);
  646. errs++;
  647. if (ctrlc())
  648. return -1;
  649. }
  650. }
  651. addr[test_offset] = pattern;
  652. WATCHDOG_RESET();
  653. /*
  654. * Check for addr bits stuck low or shorted.
  655. */
  656. for (test_offset = 1; test_offset < num_words; test_offset <<= 1) {
  657. addr[test_offset] = anti_pattern;
  658. for (offset = 1; offset < num_words; offset <<= 1) {
  659. temp = addr[offset];
  660. if ((temp != pattern) && (offset != test_offset)) {
  661. printf("\nFAILURE: Address bit stuck low or"
  662. " shorted @ 0x%.8lx: expected 0x%.8lx,"
  663. " actual 0x%.8lx\n",
  664. start_addr + offset, pattern, temp);
  665. errs++;
  666. if (ctrlc())
  667. return -1;
  668. }
  669. }
  670. addr[test_offset] = pattern;
  671. }
  672. /*
  673. * Description: Test the integrity of a physical
  674. * memory device by performing an
  675. * increment/decrement test over the
  676. * entire region. In the process every
  677. * storage bit in the device is tested
  678. * as a zero and a one. The base address
  679. * and the size of the region are
  680. * selected by the caller.
  681. *
  682. * Returns: 0 if the test succeeds, 1 if the test fails.
  683. */
  684. num_words++;
  685. /*
  686. * Fill memory with a known pattern.
  687. */
  688. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  689. WATCHDOG_RESET();
  690. addr[offset] = pattern;
  691. }
  692. /*
  693. * Check each location and invert it for the second pass.
  694. */
  695. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  696. WATCHDOG_RESET();
  697. temp = addr[offset];
  698. if (temp != pattern) {
  699. printf("\nFAILURE (read/write) @ 0x%.8lx:"
  700. " expected 0x%.8lx, actual 0x%.8lx)\n",
  701. start_addr + offset, pattern, temp);
  702. errs++;
  703. if (ctrlc())
  704. return -1;
  705. }
  706. anti_pattern = ~pattern;
  707. addr[offset] = anti_pattern;
  708. }
  709. /*
  710. * Check each location for the inverted pattern and zero it.
  711. */
  712. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  713. WATCHDOG_RESET();
  714. anti_pattern = ~pattern;
  715. temp = addr[offset];
  716. if (temp != anti_pattern) {
  717. printf("\nFAILURE (read/write): @ 0x%.8lx:"
  718. " expected 0x%.8lx, actual 0x%.8lx)\n",
  719. start_addr + offset, anti_pattern, temp);
  720. errs++;
  721. if (ctrlc())
  722. return -1;
  723. }
  724. addr[offset] = 0;
  725. }
  726. return 0;
  727. }
  728. static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr,
  729. vu_long pattern, int iteration)
  730. {
  731. vu_long *end;
  732. vu_long *addr;
  733. ulong errs = 0;
  734. ulong incr, length;
  735. ulong val, readback;
  736. /* Alternate the pattern */
  737. incr = 1;
  738. if (iteration & 1) {
  739. incr = -incr;
  740. /*
  741. * Flip the pattern each time to make lots of zeros and
  742. * then, the next time, lots of ones. We decrement
  743. * the "negative" patterns and increment the "positive"
  744. * patterns to preserve this feature.
  745. */
  746. if (pattern & 0x80000000)
  747. pattern = -pattern; /* complement & increment */
  748. else
  749. pattern = ~pattern;
  750. }
  751. length = (end_addr - start_addr) / sizeof(ulong);
  752. end = buf + length;
  753. printf("\rPattern %08lX Writing..."
  754. "%12s"
  755. "\b\b\b\b\b\b\b\b\b\b",
  756. pattern, "");
  757. for (addr = buf, val = pattern; addr < end; addr++) {
  758. WATCHDOG_RESET();
  759. *addr = val;
  760. val += incr;
  761. }
  762. puts("Reading...");
  763. for (addr = buf, val = pattern; addr < end; addr++) {
  764. WATCHDOG_RESET();
  765. readback = *addr;
  766. if (readback != val) {
  767. ulong offset = addr - buf;
  768. printf("\nMem error @ 0x%08X: "
  769. "found %08lX, expected %08lX\n",
  770. (uint)(uintptr_t)(start_addr + offset),
  771. readback, val);
  772. errs++;
  773. if (ctrlc())
  774. return -1;
  775. }
  776. val += incr;
  777. }
  778. return 0;
  779. }
  780. /*
  781. * Perform a memory test. A more complete alternative test can be
  782. * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until
  783. * interrupted by ctrl-c or by a failure of one of the sub-tests.
  784. */
  785. static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc,
  786. char * const argv[])
  787. {
  788. ulong start, end;
  789. vu_long *buf, *dummy;
  790. int iteration_limit;
  791. int ret;
  792. ulong errs = 0; /* number of errors, or -1 if interrupted */
  793. ulong pattern;
  794. int iteration;
  795. #if defined(CONFIG_SYS_ALT_MEMTEST)
  796. const int alt_test = 1;
  797. #else
  798. const int alt_test = 0;
  799. #endif
  800. if (argc > 1)
  801. start = simple_strtoul(argv[1], NULL, 16);
  802. else
  803. start = CONFIG_SYS_MEMTEST_START;
  804. if (argc > 2)
  805. end = simple_strtoul(argv[2], NULL, 16);
  806. else
  807. end = CONFIG_SYS_MEMTEST_END;
  808. if (argc > 3)
  809. pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
  810. else
  811. pattern = 0;
  812. if (argc > 4)
  813. iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16);
  814. else
  815. iteration_limit = 0;
  816. printf("Testing %08x ... %08x:\n", (uint)start, (uint)end);
  817. debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__,
  818. start, end);
  819. buf = map_sysmem(start, end - start);
  820. dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long));
  821. for (iteration = 0;
  822. !iteration_limit || iteration < iteration_limit;
  823. iteration++) {
  824. if (ctrlc()) {
  825. errs = -1UL;
  826. break;
  827. }
  828. printf("Iteration: %6d\r", iteration + 1);
  829. debug("\n");
  830. if (alt_test) {
  831. errs = mem_test_alt(buf, start, end, dummy);
  832. } else {
  833. errs = mem_test_quick(buf, start, end, pattern,
  834. iteration);
  835. }
  836. if (errs == -1UL)
  837. break;
  838. }
  839. /*
  840. * Work-around for eldk-4.2 which gives this warning if we try to
  841. * case in the unmap_sysmem() call:
  842. * warning: initialization discards qualifiers from pointer target type
  843. */
  844. {
  845. void *vbuf = (void *)buf;
  846. void *vdummy = (void *)dummy;
  847. unmap_sysmem(vbuf);
  848. unmap_sysmem(vdummy);
  849. }
  850. if (errs == -1UL) {
  851. /* Memory test was aborted - write a newline to finish off */
  852. putc('\n');
  853. ret = 1;
  854. } else {
  855. printf("Tested %d iteration(s) with %lu errors.\n",
  856. iteration, errs);
  857. ret = errs != 0;
  858. }
  859. return ret; /* not reached */
  860. }
  861. #endif /* CONFIG_CMD_MEMTEST */
  862. /* Modify memory.
  863. *
  864. * Syntax:
  865. * mm{.b, .w, .l} {addr}
  866. * nm{.b, .w, .l} {addr}
  867. */
  868. static int
  869. mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[])
  870. {
  871. ulong addr, i;
  872. int nbytes, size;
  873. void *ptr = NULL;
  874. if (argc != 2)
  875. return CMD_RET_USAGE;
  876. #ifdef CONFIG_BOOT_RETRY_TIME
  877. reset_cmd_timeout(); /* got a good command to get here */
  878. #endif
  879. /* We use the last specified parameters, unless new ones are
  880. * entered.
  881. */
  882. addr = mm_last_addr;
  883. size = mm_last_size;
  884. if ((flag & CMD_FLAG_REPEAT) == 0) {
  885. /* New command specified. Check for a size specification.
  886. * Defaults to long if no or incorrect specification.
  887. */
  888. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  889. return 1;
  890. /* Address is specified since argc > 1
  891. */
  892. addr = simple_strtoul(argv[1], NULL, 16);
  893. addr += base_address;
  894. }
  895. #ifdef CONFIG_HAS_DATAFLASH
  896. if (addr_dataflash(addr)){
  897. puts ("Can't modify DataFlash in place. Use cp instead.\n\r");
  898. return 0;
  899. }
  900. #endif
  901. #ifdef CONFIG_BLACKFIN
  902. if (addr_bfin_on_chip_mem(addr)) {
  903. puts ("Can't modify L1 instruction in place. Use cp instead.\n\r");
  904. return 0;
  905. }
  906. #endif
  907. /* Print the address, followed by value. Then accept input for
  908. * the next value. A non-converted value exits.
  909. */
  910. do {
  911. ptr = map_sysmem(addr, size);
  912. printf("%08lx:", addr);
  913. if (size == 4)
  914. printf(" %08x", *((uint *)ptr));
  915. else if (size == 2)
  916. printf(" %04x", *((ushort *)ptr));
  917. else
  918. printf(" %02x", *((u_char *)ptr));
  919. nbytes = readline (" ? ");
  920. if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
  921. /* <CR> pressed as only input, don't modify current
  922. * location and move to next. "-" pressed will go back.
  923. */
  924. if (incrflag)
  925. addr += nbytes ? -size : size;
  926. nbytes = 1;
  927. #ifdef CONFIG_BOOT_RETRY_TIME
  928. reset_cmd_timeout(); /* good enough to not time out */
  929. #endif
  930. }
  931. #ifdef CONFIG_BOOT_RETRY_TIME
  932. else if (nbytes == -2) {
  933. break; /* timed out, exit the command */
  934. }
  935. #endif
  936. else {
  937. char *endp;
  938. i = simple_strtoul(console_buffer, &endp, 16);
  939. nbytes = endp - console_buffer;
  940. if (nbytes) {
  941. #ifdef CONFIG_BOOT_RETRY_TIME
  942. /* good enough to not time out
  943. */
  944. reset_cmd_timeout();
  945. #endif
  946. if (size == 4)
  947. *((uint *)ptr) = i;
  948. else if (size == 2)
  949. *((ushort *)ptr) = i;
  950. else
  951. *((u_char *)ptr) = i;
  952. if (incrflag)
  953. addr += size;
  954. }
  955. }
  956. } while (nbytes);
  957. if (ptr)
  958. unmap_sysmem(ptr);
  959. mm_last_addr = addr;
  960. mm_last_size = size;
  961. return 0;
  962. }
  963. #ifdef CONFIG_CMD_CRC32
  964. static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  965. {
  966. int flags = 0;
  967. int ac;
  968. char * const *av;
  969. if (argc < 3)
  970. return CMD_RET_USAGE;
  971. av = argv + 1;
  972. ac = argc - 1;
  973. #ifdef CONFIG_HASH_VERIFY
  974. if (strcmp(*av, "-v") == 0) {
  975. flags |= HASH_FLAG_VERIFY;
  976. av++;
  977. ac--;
  978. }
  979. #endif
  980. return hash_command("crc32", flags, cmdtp, flag, ac, av);
  981. }
  982. #endif
  983. /**************************************************/
  984. U_BOOT_CMD(
  985. md, 3, 1, do_mem_md,
  986. "memory display",
  987. "[.b, .w, .l] address [# of objects]"
  988. );
  989. U_BOOT_CMD(
  990. mm, 2, 1, do_mem_mm,
  991. "memory modify (auto-incrementing address)",
  992. "[.b, .w, .l] address"
  993. );
  994. U_BOOT_CMD(
  995. nm, 2, 1, do_mem_nm,
  996. "memory modify (constant address)",
  997. "[.b, .w, .l] address"
  998. );
  999. U_BOOT_CMD(
  1000. mw, 4, 1, do_mem_mw,
  1001. "memory write (fill)",
  1002. "[.b, .w, .l] address value [count]"
  1003. );
  1004. U_BOOT_CMD(
  1005. cp, 4, 1, do_mem_cp,
  1006. "memory copy",
  1007. "[.b, .w, .l] source target count"
  1008. );
  1009. U_BOOT_CMD(
  1010. cmp, 4, 1, do_mem_cmp,
  1011. "memory compare",
  1012. "[.b, .w, .l] addr1 addr2 count"
  1013. );
  1014. #ifdef CONFIG_CMD_CRC32
  1015. #ifndef CONFIG_CRC32_VERIFY
  1016. U_BOOT_CMD(
  1017. crc32, 4, 1, do_mem_crc,
  1018. "checksum calculation",
  1019. "address count [addr]\n - compute CRC32 checksum [save at addr]"
  1020. );
  1021. #else /* CONFIG_CRC32_VERIFY */
  1022. U_BOOT_CMD(
  1023. crc32, 5, 1, do_mem_crc,
  1024. "checksum calculation",
  1025. "address count [addr]\n - compute CRC32 checksum [save at addr]\n"
  1026. "-v address count crc\n - verify crc of memory area"
  1027. );
  1028. #endif /* CONFIG_CRC32_VERIFY */
  1029. #endif
  1030. #ifdef CONFIG_CMD_MEMINFO
  1031. __weak void board_show_dram(ulong size)
  1032. {
  1033. puts("DRAM: ");
  1034. print_size(size, "\n");
  1035. }
  1036. static int do_mem_info(cmd_tbl_t *cmdtp, int flag, int argc,
  1037. char * const argv[])
  1038. {
  1039. board_show_dram(gd->ram_size);
  1040. return 0;
  1041. }
  1042. #endif
  1043. U_BOOT_CMD(
  1044. base, 2, 1, do_mem_base,
  1045. "print or set address offset",
  1046. "\n - print address offset for memory commands\n"
  1047. "base off\n - set address offset for memory commands to 'off'"
  1048. );
  1049. U_BOOT_CMD(
  1050. loop, 3, 1, do_mem_loop,
  1051. "infinite loop on address range",
  1052. "[.b, .w, .l] address number_of_objects"
  1053. );
  1054. #ifdef CONFIG_LOOPW
  1055. U_BOOT_CMD(
  1056. loopw, 4, 1, do_mem_loopw,
  1057. "infinite write loop on address range",
  1058. "[.b, .w, .l] address number_of_objects data_to_write"
  1059. );
  1060. #endif /* CONFIG_LOOPW */
  1061. #ifdef CONFIG_CMD_MEMTEST
  1062. U_BOOT_CMD(
  1063. mtest, 5, 1, do_mem_mtest,
  1064. "simple RAM read/write test",
  1065. "[start [end [pattern [iterations]]]]"
  1066. );
  1067. #endif /* CONFIG_CMD_MEMTEST */
  1068. #ifdef CONFIG_MX_CYCLIC
  1069. U_BOOT_CMD(
  1070. mdc, 4, 1, do_mem_mdc,
  1071. "memory display cyclic",
  1072. "[.b, .w, .l] address count delay(ms)"
  1073. );
  1074. U_BOOT_CMD(
  1075. mwc, 4, 1, do_mem_mwc,
  1076. "memory write cyclic",
  1077. "[.b, .w, .l] address value delay(ms)"
  1078. );
  1079. #endif /* CONFIG_MX_CYCLIC */
  1080. #ifdef CONFIG_CMD_MEMINFO
  1081. U_BOOT_CMD(
  1082. meminfo, 3, 1, do_mem_info,
  1083. "display memory information",
  1084. ""
  1085. );
  1086. #endif