cmd_mem.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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_RET_USAGE;
  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. if (argc != 2)
  859. return CMD_RET_USAGE;
  860. #ifdef CONFIG_BOOT_RETRY_TIME
  861. reset_cmd_timeout(); /* got a good command to get here */
  862. #endif
  863. /* We use the last specified parameters, unless new ones are
  864. * entered.
  865. */
  866. addr = mm_last_addr;
  867. size = mm_last_size;
  868. if ((flag & CMD_FLAG_REPEAT) == 0) {
  869. /* New command specified. Check for a size specification.
  870. * Defaults to long if no or incorrect specification.
  871. */
  872. if ((size = cmd_get_data_size(argv[0], 4)) < 0)
  873. return 1;
  874. /* Address is specified since argc > 1
  875. */
  876. addr = simple_strtoul(argv[1], NULL, 16);
  877. addr += base_address;
  878. }
  879. #ifdef CONFIG_HAS_DATAFLASH
  880. if (addr_dataflash(addr)){
  881. puts ("Can't modify DataFlash in place. Use cp instead.\n\r");
  882. return 0;
  883. }
  884. #endif
  885. #ifdef CONFIG_BLACKFIN
  886. if (addr_bfin_on_chip_mem(addr)) {
  887. puts ("Can't modify L1 instruction in place. Use cp instead.\n\r");
  888. return 0;
  889. }
  890. #endif
  891. /* Print the address, followed by value. Then accept input for
  892. * the next value. A non-converted value exits.
  893. */
  894. do {
  895. printf("%08lx:", addr);
  896. if (size == 4)
  897. printf(" %08x", *((uint *)addr));
  898. else if (size == 2)
  899. printf(" %04x", *((ushort *)addr));
  900. else
  901. printf(" %02x", *((u_char *)addr));
  902. nbytes = readline (" ? ");
  903. if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) {
  904. /* <CR> pressed as only input, don't modify current
  905. * location and move to next. "-" pressed will go back.
  906. */
  907. if (incrflag)
  908. addr += nbytes ? -size : size;
  909. nbytes = 1;
  910. #ifdef CONFIG_BOOT_RETRY_TIME
  911. reset_cmd_timeout(); /* good enough to not time out */
  912. #endif
  913. }
  914. #ifdef CONFIG_BOOT_RETRY_TIME
  915. else if (nbytes == -2) {
  916. break; /* timed out, exit the command */
  917. }
  918. #endif
  919. else {
  920. char *endp;
  921. i = simple_strtoul(console_buffer, &endp, 16);
  922. nbytes = endp - console_buffer;
  923. if (nbytes) {
  924. #ifdef CONFIG_BOOT_RETRY_TIME
  925. /* good enough to not time out
  926. */
  927. reset_cmd_timeout();
  928. #endif
  929. if (size == 4)
  930. *((uint *)addr) = i;
  931. else if (size == 2)
  932. *((ushort *)addr) = i;
  933. else
  934. *((u_char *)addr) = i;
  935. if (incrflag)
  936. addr += size;
  937. }
  938. }
  939. } while (nbytes);
  940. mm_last_addr = addr;
  941. mm_last_size = size;
  942. return 0;
  943. }
  944. #ifdef CONFIG_CMD_CRC32
  945. #ifndef CONFIG_CRC32_VERIFY
  946. int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  947. {
  948. ulong addr, length;
  949. ulong crc;
  950. ulong *ptr;
  951. if (argc < 3)
  952. return CMD_RET_USAGE;
  953. addr = simple_strtoul (argv[1], NULL, 16);
  954. addr += base_address;
  955. length = simple_strtoul (argv[2], NULL, 16);
  956. crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32);
  957. printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
  958. addr, addr + length - 1, crc);
  959. if (argc > 3) {
  960. ptr = (ulong *) simple_strtoul (argv[3], NULL, 16);
  961. *ptr = crc;
  962. }
  963. return 0;
  964. }
  965. #else /* CONFIG_CRC32_VERIFY */
  966. int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  967. {
  968. ulong addr, length;
  969. ulong crc;
  970. ulong *ptr;
  971. ulong vcrc;
  972. int verify;
  973. int ac;
  974. char * const *av;
  975. if (argc < 3) {
  976. usage:
  977. return CMD_RET_USAGE;
  978. }
  979. av = argv + 1;
  980. ac = argc - 1;
  981. if (strcmp(*av, "-v") == 0) {
  982. verify = 1;
  983. av++;
  984. ac--;
  985. if (ac < 3)
  986. goto usage;
  987. } else
  988. verify = 0;
  989. addr = simple_strtoul(*av++, NULL, 16);
  990. addr += base_address;
  991. length = simple_strtoul(*av++, NULL, 16);
  992. crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32);
  993. if (!verify) {
  994. printf ("CRC32 for %08lx ... %08lx ==> %08lx\n",
  995. addr, addr + length - 1, crc);
  996. if (ac > 2) {
  997. ptr = (ulong *) simple_strtoul (*av++, NULL, 16);
  998. *ptr = crc;
  999. }
  1000. } else {
  1001. vcrc = simple_strtoul(*av++, NULL, 16);
  1002. if (vcrc != crc) {
  1003. printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n",
  1004. addr, addr + length - 1, crc, vcrc);
  1005. return 1;
  1006. }
  1007. }
  1008. return 0;
  1009. }
  1010. #endif /* CONFIG_CRC32_VERIFY */
  1011. #endif
  1012. /**************************************************/
  1013. U_BOOT_CMD(
  1014. md, 3, 1, do_mem_md,
  1015. "memory display",
  1016. "[.b, .w, .l] address [# of objects]"
  1017. );
  1018. U_BOOT_CMD(
  1019. mm, 2, 1, do_mem_mm,
  1020. "memory modify (auto-incrementing address)",
  1021. "[.b, .w, .l] address"
  1022. );
  1023. U_BOOT_CMD(
  1024. nm, 2, 1, do_mem_nm,
  1025. "memory modify (constant address)",
  1026. "[.b, .w, .l] address"
  1027. );
  1028. U_BOOT_CMD(
  1029. mw, 4, 1, do_mem_mw,
  1030. "memory write (fill)",
  1031. "[.b, .w, .l] address value [count]"
  1032. );
  1033. U_BOOT_CMD(
  1034. cp, 4, 1, do_mem_cp,
  1035. "memory copy",
  1036. "[.b, .w, .l] source target count"
  1037. );
  1038. U_BOOT_CMD(
  1039. cmp, 4, 1, do_mem_cmp,
  1040. "memory compare",
  1041. "[.b, .w, .l] addr1 addr2 count"
  1042. );
  1043. #ifdef CONFIG_CMD_CRC32
  1044. #ifndef CONFIG_CRC32_VERIFY
  1045. U_BOOT_CMD(
  1046. crc32, 4, 1, do_mem_crc,
  1047. "checksum calculation",
  1048. "address count [addr]\n - compute CRC32 checksum [save at addr]"
  1049. );
  1050. #else /* CONFIG_CRC32_VERIFY */
  1051. U_BOOT_CMD(
  1052. crc32, 5, 1, do_mem_crc,
  1053. "checksum calculation",
  1054. "address count [addr]\n - compute CRC32 checksum [save at addr]\n"
  1055. "-v address count crc\n - verify crc of memory area"
  1056. );
  1057. #endif /* CONFIG_CRC32_VERIFY */
  1058. #endif
  1059. U_BOOT_CMD(
  1060. base, 2, 1, do_mem_base,
  1061. "print or set address offset",
  1062. "\n - print address offset for memory commands\n"
  1063. "base off\n - set address offset for memory commands to 'off'"
  1064. );
  1065. U_BOOT_CMD(
  1066. loop, 3, 1, do_mem_loop,
  1067. "infinite loop on address range",
  1068. "[.b, .w, .l] address number_of_objects"
  1069. );
  1070. #ifdef CONFIG_LOOPW
  1071. U_BOOT_CMD(
  1072. loopw, 4, 1, do_mem_loopw,
  1073. "infinite write loop on address range",
  1074. "[.b, .w, .l] address number_of_objects data_to_write"
  1075. );
  1076. #endif /* CONFIG_LOOPW */
  1077. U_BOOT_CMD(
  1078. mtest, 5, 1, do_mem_mtest,
  1079. "simple RAM read/write test",
  1080. "[start [end [pattern [iterations]]]]"
  1081. );
  1082. #ifdef CONFIG_MX_CYCLIC
  1083. U_BOOT_CMD(
  1084. mdc, 4, 1, do_mem_mdc,
  1085. "memory display cyclic",
  1086. "[.b, .w, .l] address count delay(ms)"
  1087. );
  1088. U_BOOT_CMD(
  1089. mwc, 4, 1, do_mem_mwc,
  1090. "memory write cyclic",
  1091. "[.b, .w, .l] address value delay(ms)"
  1092. );
  1093. #endif /* CONFIG_MX_CYCLIC */