cmd_mem.c 28 KB

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