cmd_mem.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /*
  24. * Memory Functions
  25. *
  26. * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
  27. */
  28. #include <common.h>
  29. #include <command.h>
  30. #include <cmd_mem.h>
  31. #if (CONFIG_COMMANDS & CFG_CMD_MMC)
  32. #include <mmc.h>
  33. #endif
  34. #ifdef CONFIG_HAS_DATAFLASH
  35. #include <dataflash.h>
  36. #endif
  37. #if (CONFIG_COMMANDS & (CFG_CMD_MEMORY | CFG_CMD_PCI | CFG_CMD_I2C\
  38. | CMD_CMD_PORTIO))
  39. int cmd_get_data_size(char* arg, int default_size)
  40. {
  41. /* Check for a size specification .b, .w or .l.
  42. */
  43. int len = strlen(arg);
  44. if (len > 2 && arg[len-2] == '.') {
  45. switch(arg[len-1]) {
  46. case 'b':
  47. return 1;
  48. case 'w':
  49. return 2;
  50. case 'l':
  51. return 4;
  52. }
  53. }
  54. return default_size;
  55. }
  56. #endif
  57. #if (CONFIG_COMMANDS & CFG_CMD_MEMORY)
  58. #ifdef CMD_MEM_DEBUG
  59. #define PRINTF(fmt,args...) printf (fmt ,##args)
  60. #else
  61. #define PRINTF(fmt,args...)
  62. #endif
  63. static int mod_mem(cmd_tbl_t *, int, int, int, char *[]);
  64. /* Display values from last command.
  65. * Memory modify remembered values are different from display memory.
  66. */
  67. uint dp_last_addr, dp_last_size;
  68. uint dp_last_length = 0x40;
  69. uint mm_last_addr, mm_last_size;
  70. static ulong base_address = 0;
  71. /* Memory Display
  72. *
  73. * Syntax:
  74. * md{.b, .w, .l} {addr} {len}
  75. */
  76. #define DISP_LINE_LEN 16
  77. int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  78. {
  79. ulong addr, size, length;
  80. ulong i, nbytes, linebytes;
  81. u_char *cp;
  82. int rc = 0;
  83. /* We use the last specified parameters, unless new ones are
  84. * entered.
  85. */
  86. addr = dp_last_addr;
  87. size = dp_last_size;
  88. length = dp_last_length;
  89. if (argc < 2) {
  90. printf ("Usage:\n%s\n", cmdtp->usage);
  91. return 1;
  92. }
  93. if ((flag & CMD_FLAG_REPEAT) == 0) {
  94. /* New command specified. Check for a size specification.
  95. * Defaults to long if no or incorrect specification.
  96. */
  97. size = cmd_get_data_size(argv[0], 4);
  98. /* Address is specified since argc > 1
  99. */
  100. addr = simple_strtoul(argv[1], NULL, 16);
  101. addr += base_address;
  102. /* If another parameter, it is the length to display.
  103. * Length is the number of objects, not number of bytes.
  104. */
  105. if (argc > 2)
  106. length = simple_strtoul(argv[2], NULL, 16);
  107. }
  108. /* Print the lines.
  109. *
  110. * We buffer all read data, so we can make sure data is read only
  111. * once, and all accesses are with the specified bus width.
  112. */
  113. nbytes = length * size;
  114. do {
  115. char linebuf[DISP_LINE_LEN];
  116. uint *uip = (uint *)linebuf;
  117. ushort *usp = (ushort *)linebuf;
  118. u_char *ucp = (u_char *)linebuf;
  119. printf("%08lx:", addr);
  120. linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
  121. #ifdef CONFIG_HAS_DATAFLASH
  122. if (read_dataflash(addr, (linebytes/size)*size, linebuf) != -1){
  123. for (i=0; i<linebytes; i+= size) {
  124. if (size == 4) {
  125. printf(" %08x", *uip++);
  126. } else if (size == 2) {
  127. printf(" %04x", *usp++);
  128. } else {
  129. printf(" %02x", *ucp++);
  130. }
  131. addr += size;
  132. }
  133. } else { /* addr does not correspond to DataFlash */
  134. #endif
  135. for (i=0; i<linebytes; i+= size) {
  136. if (size == 4) {
  137. printf(" %08x", (*uip++ = *((uint *)addr)));
  138. } else if (size == 2) {
  139. printf(" %04x", (*usp++ = *((ushort *)addr)));
  140. } else {
  141. printf(" %02x", (*ucp++ = *((u_char *)addr)));
  142. }
  143. addr += size;
  144. }
  145. #ifdef CONFIG_HAS_DATAFLASH
  146. }
  147. #endif
  148. printf(" ");
  149. cp = linebuf;
  150. for (i=0; i<linebytes; i++) {
  151. if ((*cp < 0x20) || (*cp > 0x7e))
  152. printf(".");
  153. else
  154. printf("%c", *cp);
  155. cp++;
  156. }
  157. printf("\n");
  158. nbytes -= linebytes;
  159. if (ctrlc()) {
  160. rc = 1;
  161. break;
  162. }
  163. } while (nbytes > 0);
  164. dp_last_addr = addr;
  165. dp_last_length = length;
  166. dp_last_size = size;
  167. return (rc);
  168. }
  169. int do_mem_mm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  170. {
  171. return mod_mem (cmdtp, 1, flag, argc, argv);
  172. }
  173. int do_mem_nm ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  174. {
  175. return mod_mem (cmdtp, 0, flag, argc, argv);
  176. }
  177. int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  178. {
  179. ulong addr, size, writeval, count;
  180. if ((argc < 3) || (argc > 4)) {
  181. printf ("Usage:\n%s\n", cmdtp->usage);
  182. return 1;
  183. }
  184. /* Check for size specification.
  185. */
  186. size = cmd_get_data_size(argv[0], 4);
  187. /* Address is specified since argc > 1
  188. */
  189. addr = simple_strtoul(argv[1], NULL, 16);
  190. addr += base_address;
  191. /* Get the value to write.
  192. */
  193. writeval = simple_strtoul(argv[2], NULL, 16);
  194. /* Count ? */
  195. if (argc == 4) {
  196. count = simple_strtoul(argv[3], NULL, 16);
  197. } else {
  198. count = 1;
  199. }
  200. while (count-- > 0) {
  201. if (size == 4)
  202. *((ulong *)addr) = (ulong )writeval;
  203. else if (size == 2)
  204. *((ushort *)addr) = (ushort)writeval;
  205. else
  206. *((u_char *)addr) = (u_char)writeval;
  207. addr += size;
  208. }
  209. return 0;
  210. }
  211. int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  212. {
  213. ulong size, addr1, addr2, count, ngood;
  214. int rcode = 0;
  215. if (argc != 4) {
  216. printf ("Usage:\n%s\n", cmdtp->usage);
  217. return 1;
  218. }
  219. /* Check for size specification.
  220. */
  221. size = cmd_get_data_size(argv[0], 4);
  222. addr1 = simple_strtoul(argv[1], NULL, 16);
  223. addr1 += base_address;
  224. addr2 = simple_strtoul(argv[2], NULL, 16);
  225. addr2 += base_address;
  226. count = simple_strtoul(argv[3], NULL, 16);
  227. #ifdef CONFIG_HAS_DATAFLASH
  228. if (addr_dataflash(addr1) | addr_dataflash(addr2)){
  229. printf("Comparison with DataFlash space not supported.\n\r");
  230. return 0;
  231. }
  232. #endif
  233. ngood = 0;
  234. while (count-- > 0) {
  235. if (size == 4) {
  236. ulong word1 = *(ulong *)addr1;
  237. ulong word2 = *(ulong *)addr2;
  238. if (word1 != word2) {
  239. printf("word at 0x%08lx (0x%08lx) "
  240. "!= word at 0x%08lx (0x%08lx)\n",
  241. addr1, word1, addr2, word2);
  242. rcode = 1;
  243. break;
  244. }
  245. }
  246. else if (size == 2) {
  247. ushort hword1 = *(ushort *)addr1;
  248. ushort hword2 = *(ushort *)addr2;
  249. if (hword1 != hword2) {
  250. printf("halfword at 0x%08lx (0x%04x) "
  251. "!= halfword at 0x%08lx (0x%04x)\n",
  252. addr1, hword1, addr2, hword2);
  253. rcode = 1;
  254. break;
  255. }
  256. }
  257. else {
  258. u_char byte1 = *(u_char *)addr1;
  259. u_char byte2 = *(u_char *)addr2;
  260. if (byte1 != byte2) {
  261. printf("byte at 0x%08lx (0x%02x) "
  262. "!= byte at 0x%08lx (0x%02x)\n",
  263. addr1, byte1, addr2, byte2);
  264. rcode = 1;
  265. break;
  266. }
  267. }
  268. ngood++;
  269. addr1 += size;
  270. addr2 += size;
  271. }
  272. printf("Total of %ld %s%s were the same\n",
  273. ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
  274. ngood == 1 ? "" : "s");
  275. return rcode;
  276. }
  277. int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  278. {
  279. ulong addr, size, dest, count;
  280. if (argc != 4) {
  281. printf ("Usage:\n%s\n", cmdtp->usage);
  282. return 1;
  283. }
  284. /* Check for size specification.
  285. */
  286. size = cmd_get_data_size(argv[0], 4);
  287. addr = simple_strtoul(argv[1], NULL, 16);
  288. addr += base_address;
  289. dest = simple_strtoul(argv[2], NULL, 16);
  290. dest += base_address;
  291. count = simple_strtoul(argv[3], NULL, 16);
  292. if (count == 0) {
  293. puts ("Zero length ???\n");
  294. return 1;
  295. }
  296. #ifndef CFG_NO_FLASH
  297. /* check if we are copying to Flash */
  298. if ( (addr2info(dest) != NULL)
  299. #ifdef CONFIG_HAS_DATAFLASH
  300. && (!addr_dataflash(addr))
  301. #endif
  302. ) {
  303. int rc;
  304. printf ("Copy to Flash... ");
  305. rc = flash_write ((uchar *)addr, dest, count*size);
  306. if (rc != 0) {
  307. flash_perror (rc);
  308. return (1);
  309. }
  310. puts ("done\n");
  311. return 0;
  312. }
  313. #endif
  314. #if (CONFIG_COMMANDS & CFG_CMD_MMC)
  315. if (mmc2info(dest)) {
  316. int rc;
  317. printf ("Copy to MMC... ");
  318. switch (rc = mmc_write ((uchar *)addr, dest, count*size)) {
  319. case 0:
  320. printf ("\n");
  321. return 1;
  322. case -1:
  323. printf("failed\n");
  324. return 1;
  325. default:
  326. printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
  327. return 1;
  328. }
  329. puts ("done\n");
  330. return 0;
  331. }
  332. if (mmc2info(addr)) {
  333. int rc;
  334. printf ("Copy from MMC... ");
  335. switch (rc = mmc_read (addr, (uchar *)dest, count*size)) {
  336. case 0:
  337. printf ("\n");
  338. return 1;
  339. case -1:
  340. printf("failed\n");
  341. return 1;
  342. default:
  343. printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
  344. return 1;
  345. }
  346. puts ("done\n");
  347. return 0;
  348. }
  349. #endif
  350. #ifdef CONFIG_HAS_DATAFLASH
  351. /* Check if we are copying from RAM or Flash to DataFlash */
  352. if (addr_dataflash(dest) && !addr_dataflash(addr)){
  353. int rc;
  354. printf ("Copy to DataFlash... ");
  355. rc = write_dataflash (dest, addr, count*size);
  356. if (rc != 1) {
  357. dataflash_perror (rc);
  358. return (1);
  359. }
  360. puts ("done\n");
  361. return 0;
  362. }
  363. /* Check if we are copying from DataFlash to RAM */
  364. if (addr_dataflash(addr) && !addr_dataflash(dest) && (addr2info(dest)==NULL) ){
  365. read_dataflash(addr, count * size, (char *) dest);
  366. return 0;
  367. }
  368. if (addr_dataflash(addr) && addr_dataflash(dest)){
  369. printf("Unsupported combination of source/destination.\n\r");
  370. return 1;
  371. }
  372. #endif
  373. while (count-- > 0) {
  374. if (size == 4)
  375. *((ulong *)dest) = *((ulong *)addr);
  376. else if (size == 2)
  377. *((ushort *)dest) = *((ushort *)addr);
  378. else
  379. *((u_char *)dest) = *((u_char *)addr);
  380. addr += size;
  381. dest += size;
  382. }
  383. return 0;
  384. }
  385. int do_mem_base (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  386. {
  387. if (argc > 1) {
  388. /* Set new base address.
  389. */
  390. base_address = simple_strtoul(argv[1], NULL, 16);
  391. }
  392. /* Print the current base address.
  393. */
  394. printf("Base Address: 0x%08lx\n", base_address);
  395. return 0;
  396. }
  397. int do_mem_loop (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  398. {
  399. ulong addr, size, length, i, junk;
  400. volatile uint *longp;
  401. volatile ushort *shortp;
  402. volatile u_char *cp;
  403. if (argc < 3) {
  404. printf ("Usage:\n%s\n", cmdtp->usage);
  405. return 1;
  406. }
  407. /* Check for a size spefication.
  408. * Defaults to long if no or incorrect specification.
  409. */
  410. size = cmd_get_data_size(argv[0], 4);
  411. /* Address is always specified.
  412. */
  413. addr = simple_strtoul(argv[1], NULL, 16);
  414. /* Length is the number of objects, not number of bytes.
  415. */
  416. length = simple_strtoul(argv[2], NULL, 16);
  417. /* We want to optimize the loops to run as fast as possible.
  418. * If we have only one object, just run infinite loops.
  419. */
  420. if (length == 1) {
  421. if (size == 4) {
  422. longp = (uint *)addr;
  423. for (;;)
  424. i = *longp;
  425. }
  426. if (size == 2) {
  427. shortp = (ushort *)addr;
  428. for (;;)
  429. i = *shortp;
  430. }
  431. cp = (u_char *)addr;
  432. for (;;)
  433. i = *cp;
  434. }
  435. if (size == 4) {
  436. for (;;) {
  437. longp = (uint *)addr;
  438. i = length;
  439. while (i-- > 0)
  440. junk = *longp++;
  441. }
  442. }
  443. if (size == 2) {
  444. for (;;) {
  445. shortp = (ushort *)addr;
  446. i = length;
  447. while (i-- > 0)
  448. junk = *shortp++;
  449. }
  450. }
  451. for (;;) {
  452. cp = (u_char *)addr;
  453. i = length;
  454. while (i-- > 0)
  455. junk = *cp++;
  456. }
  457. }
  458. /*
  459. * Perform a memory test. A more complete alternative test can be
  460. * configured using CFG_ALT_MEMTEST. The complete test loops until
  461. * interrupted by ctrl-c or by a failure of one of the sub-tests.
  462. */
  463. int do_mem_mtest (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  464. {
  465. vu_long *addr, *start, *end;
  466. ulong val;
  467. ulong readback;
  468. #if defined(CFG_ALT_MEMTEST)
  469. vu_long addr_mask;
  470. vu_long offset;
  471. vu_long test_offset;
  472. vu_long pattern;
  473. vu_long temp;
  474. vu_long anti_pattern;
  475. vu_long num_words;
  476. vu_long *dummy = NULL;
  477. int j;
  478. int iterations = 1;
  479. static const ulong bitpattern[] = {
  480. 0x00000001, /* single bit */
  481. 0x00000003, /* two adjacent bits */
  482. 0x00000007, /* three adjacent bits */
  483. 0x0000000F, /* four adjacent bits */
  484. 0x00000005, /* two non-adjacent bits */
  485. 0x00000015, /* three non-adjacent bits */
  486. 0x00000055, /* four non-adjacent bits */
  487. 0xaaaaaaaa, /* alternating 1/0 */
  488. };
  489. #else
  490. ulong incr;
  491. ulong pattern;
  492. int rcode = 0;
  493. #endif
  494. if (argc > 1) {
  495. start = (ulong *)simple_strtoul(argv[1], NULL, 16);
  496. } else {
  497. start = (ulong *)CFG_MEMTEST_START;
  498. }
  499. if (argc > 2) {
  500. end = (ulong *)simple_strtoul(argv[2], NULL, 16);
  501. } else {
  502. end = (ulong *)(CFG_MEMTEST_END);
  503. }
  504. if (argc > 3) {
  505. pattern = (ulong)simple_strtoul(argv[3], NULL, 16);
  506. } else {
  507. pattern = 0;
  508. }
  509. #if defined(CFG_ALT_MEMTEST)
  510. printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end);
  511. PRINTF("%s:%d: start 0x%p end 0x%p\n",
  512. __FUNCTION__, __LINE__, start, end);
  513. for (;;) {
  514. if (ctrlc()) {
  515. putc ('\n');
  516. return 1;
  517. }
  518. printf("Iteration: %6d\r", iterations);
  519. PRINTF("Iteration: %6d\n", iterations);
  520. iterations++;
  521. /*
  522. * Data line test: write a pattern to the first
  523. * location, write the 1's complement to a 'parking'
  524. * address (changes the state of the data bus so a
  525. * floating bus doen't give a false OK), and then
  526. * read the value back. Note that we read it back
  527. * into a variable because the next time we read it,
  528. * it might be right (been there, tough to explain to
  529. * the quality guys why it prints a failure when the
  530. * "is" and "should be" are obviously the same in the
  531. * error message).
  532. *
  533. * Rather than exhaustively testing, we test some
  534. * patterns by shifting '1' bits through a field of
  535. * '0's and '0' bits through a field of '1's (i.e.
  536. * pattern and ~pattern).
  537. */
  538. addr = start;
  539. for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) {
  540. val = bitpattern[j];
  541. for(; val != 0; val <<= 1) {
  542. *addr = val;
  543. *dummy = ~val; /* clear the test data off of the bus */
  544. readback = *addr;
  545. if(readback != val) {
  546. printf ("FAILURE (data line): "
  547. "expected %08lx, actual %08lx\n",
  548. val, readback);
  549. }
  550. *addr = ~val;
  551. *dummy = val;
  552. readback = *addr;
  553. if(readback != ~val) {
  554. printf ("FAILURE (data line): "
  555. "Is %08lx, should be %08lx\n",
  556. val, readback);
  557. }
  558. }
  559. }
  560. /*
  561. * Based on code whose Original Author and Copyright
  562. * information follows: Copyright (c) 1998 by Michael
  563. * Barr. This software is placed into the public
  564. * domain and may be used for any purpose. However,
  565. * this notice must not be changed or removed and no
  566. * warranty is either expressed or implied by its
  567. * publication or distribution.
  568. */
  569. /*
  570. * Address line test
  571. *
  572. * Description: Test the address bus wiring in a
  573. * memory region by performing a walking
  574. * 1's test on the relevant bits of the
  575. * address and checking for aliasing.
  576. * This test will find single-bit
  577. * address failures such as stuck -high,
  578. * stuck-low, and shorted pins. The base
  579. * address and size of the region are
  580. * selected by the caller.
  581. *
  582. * Notes: For best results, the selected base
  583. * address should have enough LSB 0's to
  584. * guarantee single address bit changes.
  585. * For example, to test a 64-Kbyte
  586. * region, select a base address on a
  587. * 64-Kbyte boundary. Also, select the
  588. * region size as a power-of-two if at
  589. * all possible.
  590. *
  591. * Returns: 0 if the test succeeds, 1 if the test fails.
  592. *
  593. * ## NOTE ## Be sure to specify start and end
  594. * addresses such that addr_mask has
  595. * lots of bits set. For example an
  596. * address range of 01000000 02000000 is
  597. * bad while a range of 01000000
  598. * 01ffffff is perfect.
  599. */
  600. addr_mask = ((ulong)end - (ulong)start)/sizeof(vu_long);
  601. pattern = (vu_long) 0xaaaaaaaa;
  602. anti_pattern = (vu_long) 0x55555555;
  603. PRINTF("%s:%d: addr mask = 0x%.8lx\n",
  604. __FUNCTION__, __LINE__,
  605. addr_mask);
  606. /*
  607. * Write the default pattern at each of the
  608. * power-of-two offsets.
  609. */
  610. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  611. start[offset] = pattern;
  612. }
  613. /*
  614. * Check for address bits stuck high.
  615. */
  616. test_offset = 0;
  617. start[test_offset] = anti_pattern;
  618. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  619. temp = start[offset];
  620. if (temp != pattern) {
  621. printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
  622. " expected 0x%.8lx, actual 0x%.8lx\n",
  623. (ulong)&start[offset], pattern, temp);
  624. return 1;
  625. }
  626. }
  627. start[test_offset] = pattern;
  628. /*
  629. * Check for addr bits stuck low or shorted.
  630. */
  631. for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
  632. start[test_offset] = anti_pattern;
  633. for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
  634. temp = start[offset];
  635. if ((temp != pattern) && (offset != test_offset)) {
  636. printf ("\nFAILURE: Address bit stuck low or shorted @"
  637. " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
  638. (ulong)&start[offset], pattern, temp);
  639. return 1;
  640. }
  641. }
  642. start[test_offset] = pattern;
  643. }
  644. /*
  645. * Description: Test the integrity of a physical
  646. * memory device by performing an
  647. * increment/decrement test over the
  648. * entire region. In the process every
  649. * storage bit in the device is tested
  650. * as a zero and a one. The base address
  651. * and the size of the region are
  652. * selected by the caller.
  653. *
  654. * Returns: 0 if the test succeeds, 1 if the test fails.
  655. */
  656. num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1;
  657. /*
  658. * Fill memory with a known pattern.
  659. */
  660. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  661. start[offset] = pattern;
  662. }
  663. /*
  664. * Check each location and invert it for the second pass.
  665. */
  666. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  667. temp = start[offset];
  668. if (temp != pattern) {
  669. printf ("\nFAILURE (read/write) @ 0x%.8lx:"
  670. " expected 0x%.8lx, actual 0x%.8lx)\n",
  671. (ulong)&start[offset], pattern, temp);
  672. return 1;
  673. }
  674. anti_pattern = ~pattern;
  675. start[offset] = anti_pattern;
  676. }
  677. /*
  678. * Check each location for the inverted pattern and zero it.
  679. */
  680. for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
  681. anti_pattern = ~pattern;
  682. temp = start[offset];
  683. if (temp != anti_pattern) {
  684. printf ("\nFAILURE (read/write): @ 0x%.8lx:"
  685. " expected 0x%.8lx, actual 0x%.8lx)\n",
  686. (ulong)&start[offset], anti_pattern, temp);
  687. return 1;
  688. }
  689. start[offset] = 0;
  690. }
  691. }
  692. #else /* The original, quickie test */
  693. incr = 1;
  694. for (;;) {
  695. if (ctrlc()) {
  696. putc ('\n');
  697. return 1;
  698. }
  699. printf ("\rPattern %08lX Writing..."
  700. "%12s"
  701. "\b\b\b\b\b\b\b\b\b\b",
  702. pattern, "");
  703. for (addr=start,val=pattern; addr<end; addr++) {
  704. *addr = val;
  705. val += incr;
  706. }
  707. printf("Reading...");
  708. for (addr=start,val=pattern; addr<end; addr++) {
  709. readback = *addr;
  710. if (readback != val) {
  711. printf ("\nMem error @ 0x%08X: "
  712. "found %08lX, expected %08lX\n",
  713. (uint)addr, readback, val);
  714. rcode = 1;
  715. }
  716. val += incr;
  717. }
  718. /*
  719. * Flip the pattern each time to make lots of zeros and
  720. * then, the next time, lots of ones. We decrement
  721. * the "negative" patterns and increment the "positive"
  722. * patterns to preserve this feature.
  723. */
  724. if(pattern & 0x80000000) {
  725. pattern = -pattern; /* complement & increment */
  726. }
  727. else {
  728. pattern = ~pattern;
  729. }
  730. incr = -incr;
  731. }
  732. return rcode;
  733. #endif
  734. }
  735. /* Modify memory.
  736. *
  737. * Syntax:
  738. * mm{.b, .w, .l} {addr}
  739. * nm{.b, .w, .l} {addr}
  740. */
  741. static int
  742. mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char *argv[])
  743. {
  744. ulong addr, size, i;
  745. int nbytes;
  746. extern char console_buffer[];
  747. if (argc != 2) {
  748. printf ("Usage:\n%s\n", cmdtp->usage);
  749. return 1;
  750. }
  751. #ifdef CONFIG_BOOT_RETRY_TIME
  752. reset_cmd_timeout(); /* got a good command to get here */
  753. #endif
  754. /* We use the last specified parameters, unless new ones are
  755. * entered.
  756. */
  757. addr = mm_last_addr;
  758. size = mm_last_size;
  759. if ((flag & CMD_FLAG_REPEAT) == 0) {
  760. /* New command specified. Check for a size specification.
  761. * Defaults to long if no or incorrect specification.
  762. */
  763. size = cmd_get_data_size(argv[0], 4);
  764. /* Address is specified since argc > 1
  765. */
  766. addr = simple_strtoul(argv[1], NULL, 16);
  767. addr += base_address;
  768. }
  769. #ifdef CONFIG_HAS_DATAFLASH
  770. if (addr_dataflash(addr)){
  771. printf("Can't modify DataFlash in place. Use cp instead.\n\r");
  772. return 0;
  773. }
  774. #endif
  775. /* Print the address, followed by value. Then accept input for
  776. * the next value. A non-converted value exits.
  777. */
  778. do {
  779. printf("%08lx:", addr);
  780. if (size == 4)
  781. printf(" %08x", *((uint *)addr));
  782. else if (size == 2)
  783. printf(" %04x", *((ushort *)addr));
  784. else
  785. printf(" %02x", *((u_char *)addr));
  786. nbytes = readline (" ? ");
  787. if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
  788. /* <CR> pressed as only input, don't modify current
  789. * location and move to next. "-" pressed will go back.
  790. */
  791. if (incrflag)
  792. addr += nbytes ? -size : size;
  793. nbytes = 1;
  794. #ifdef CONFIG_BOOT_RETRY_TIME
  795. reset_cmd_timeout(); /* good enough to not time out */
  796. #endif
  797. }
  798. #ifdef CONFIG_BOOT_RETRY_TIME
  799. else if (nbytes == -2) {
  800. break; /* timed out, exit the command */
  801. }
  802. #endif
  803. else {
  804. char *endp;
  805. i = simple_strtoul(console_buffer, &endp, 16);
  806. nbytes = endp - console_buffer;
  807. if (nbytes) {
  808. #ifdef CONFIG_BOOT_RETRY_TIME
  809. /* good enough to not time out
  810. */
  811. reset_cmd_timeout();
  812. #endif
  813. if (size == 4)
  814. *((uint *)addr) = i;
  815. else if (size == 2)
  816. *((ushort *)addr) = i;
  817. else
  818. *((u_char *)addr) = i;
  819. if (incrflag)
  820. addr += size;
  821. }
  822. }
  823. } while (nbytes);
  824. mm_last_addr = addr;
  825. mm_last_size = size;
  826. return 0;
  827. }
  828. int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
  829. {
  830. ulong addr, length;
  831. ulong crc;
  832. ulong *ptr;
  833. if (argc < 3) {
  834. printf ("Usage:\n%s\n", cmdtp->usage);
  835. return 1;
  836. }
  837. addr = simple_strtoul (argv[1], NULL, 16);
  838. addr += base_address;
  839. length = simple_strtoul (argv[2], NULL, 16);
  840. crc = crc32 (0, (const uchar *) addr, length);
  841. printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
  842. addr, addr + length - 1, crc);
  843. if (argc > 3) {
  844. ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
  845. *ptr = crc;
  846. }
  847. return 0;
  848. }
  849. #endif /* CFG_CMD_MEMORY */