memtst.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*
  2. * (C) Copyright 2001
  3. * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
  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. /* NOT Used yet...
  25. add following code to PIP405.c :
  26. int testdram (void)
  27. {
  28. unsigned char s[32];
  29. int i;
  30. i = getenv_r ("testmem", s, 32);
  31. if (i != 0) {
  32. i = (int) simple_strtoul (s, NULL, 10);
  33. if ((i > 0) && (i < 0xf)) {
  34. printf ("testing ");
  35. i = mem_test (0, ramsize, i);
  36. if (i > 0)
  37. printf ("ERROR ");
  38. else
  39. printf ("Ok ");
  40. }
  41. }
  42. return (1);
  43. }
  44. */
  45. #include <common.h>
  46. #include <asm/processor.h>
  47. #include <405gp_i2c.h>
  48. DECLARE_GLOBAL_DATA_PTR;
  49. #define FALSE 0
  50. #define TRUE 1
  51. #define TEST_QUIET 8
  52. #define TEST_SHOW_PROG 4
  53. #define TEST_SHOW_ERR 2
  54. #define TEST_SHOW_ALL 1
  55. #define TESTPAT1 0xAA55AA55
  56. #define TESTPAT2 0x55AA55AA
  57. #define TEST_PASSED 0
  58. #define TEST_FAILED 1
  59. #define MEGABYTE (1024*1024)
  60. typedef struct {
  61. volatile unsigned long pat1;
  62. volatile unsigned long pat2;
  63. } RAM_MEMTEST_PATTERN2;
  64. typedef struct {
  65. volatile unsigned long addr;
  66. } RAM_MEMTEST_ADDRLINE;
  67. static __inline unsigned long Swap_32 (unsigned long val)
  68. {
  69. return (((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF));
  70. }
  71. void testm_puts (int quiet, char *buf)
  72. {
  73. if ((quiet & TEST_SHOW_ALL) == TEST_SHOW_ALL)
  74. puts (buf);
  75. }
  76. void Write_Error (int mode, unsigned long addr, unsigned long expected,
  77. unsigned long actual)
  78. {
  79. char dispbuf[64];
  80. sprintf (dispbuf, "\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ",
  81. addr, expected, actual);
  82. testm_puts (((mode & TEST_SHOW_ERR) ==
  83. TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode, dispbuf);
  84. }
  85. /*
  86. * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2
  87. */
  88. void RAM_MemTest_WritePattern2 (unsigned long startaddr,
  89. unsigned long size, unsigned long pat1,
  90. unsigned long pat2)
  91. {
  92. RAM_MEMTEST_PATTERN2 *p, *pe;
  93. p = (RAM_MEMTEST_PATTERN2 *) startaddr;
  94. pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
  95. while (p < pe) {
  96. p->pat1 = pat1;
  97. p->pat2 = pat2;
  98. p++;
  99. } /* endwhile */
  100. }
  101. /*
  102. * checks the memblock of <size> bytes from <startaddr> with pat1 and pat2
  103. * returns the address of the first error or NULL if all is well
  104. */
  105. void *RAM_MemTest_CheckPattern2 (int mode, unsigned long startaddr,
  106. unsigned long size, unsigned long pat1,
  107. unsigned long pat2)
  108. {
  109. RAM_MEMTEST_PATTERN2 *p, *pe;
  110. unsigned long actual1, actual2;
  111. p = (RAM_MEMTEST_PATTERN2 *) startaddr;
  112. pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
  113. while (p < pe) {
  114. actual1 = p->pat1;
  115. actual2 = p->pat2;
  116. if (actual1 != pat1) {
  117. Write_Error (mode, (unsigned long) &(p->pat1), pat1, actual1);
  118. return ((void *) &(p->pat1));
  119. }
  120. /* endif */
  121. if (actual2 != pat2) {
  122. Write_Error (mode, (unsigned long) &(p->pat2), pat2, actual2);
  123. return ((void *) &(p->pat2));
  124. }
  125. /* endif */
  126. p++;
  127. } /* endwhile */
  128. return (NULL);
  129. }
  130. /*
  131. * fills the memblock of <size> bytes from <startaddr> with the address
  132. */
  133. void RAM_MemTest_WriteAddrLine (unsigned long startaddr,
  134. unsigned long size, int swapped)
  135. {
  136. RAM_MEMTEST_ADDRLINE *p, *pe;
  137. p = (RAM_MEMTEST_ADDRLINE *) startaddr;
  138. pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
  139. if (!swapped) {
  140. while (p < pe) {
  141. p->addr = (unsigned long) p;
  142. p++;
  143. } /* endwhile */
  144. } else {
  145. while (p < pe) {
  146. p->addr = Swap_32 ((unsigned long) p);
  147. p++;
  148. } /* endwhile */
  149. } /* endif */
  150. }
  151. /*
  152. * checks the memblock of <size> bytes from <startaddr>
  153. * returns the address of the error or NULL if all is well
  154. */
  155. void *RAM_MemTest_CheckAddrLine (int mode, unsigned long startaddr,
  156. unsigned long size, int swapped)
  157. {
  158. RAM_MEMTEST_ADDRLINE *p, *pe;
  159. unsigned long actual, expected;
  160. p = (RAM_MEMTEST_ADDRLINE *) startaddr;
  161. pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
  162. if (!swapped) {
  163. while (p < pe) {
  164. actual = p->addr;
  165. expected = (unsigned long) p;
  166. if (actual != expected) {
  167. Write_Error (mode, (unsigned long) &(p->addr), expected,
  168. actual);
  169. return ((void *) &(p->addr));
  170. } /* endif */
  171. p++;
  172. } /* endwhile */
  173. } else {
  174. while (p < pe) {
  175. actual = p->addr;
  176. expected = Swap_32 ((unsigned long) p);
  177. if (actual != expected) {
  178. Write_Error (mode, (unsigned long) &(p->addr), expected,
  179. actual);
  180. return ((void *) &(p->addr));
  181. } /* endif */
  182. p++;
  183. } /* endwhile */
  184. } /* endif */
  185. return (NULL);
  186. }
  187. /*
  188. * checks the memblock of <size> bytes from <startaddr+size>
  189. * returns the address of the error or NULL if all is well
  190. */
  191. void *RAM_MemTest_CheckAddrLineReverse (int mode, unsigned long startaddr,
  192. unsigned long size, int swapped)
  193. {
  194. RAM_MEMTEST_ADDRLINE *p, *pe;
  195. unsigned long actual, expected;
  196. p = (RAM_MEMTEST_ADDRLINE *) (startaddr + size - sizeof (p->addr));
  197. pe = (RAM_MEMTEST_ADDRLINE *) startaddr;
  198. if (!swapped) {
  199. while (p > pe) {
  200. actual = p->addr;
  201. expected = (unsigned long) p;
  202. if (actual != expected) {
  203. Write_Error (mode, (unsigned long) &(p->addr), expected,
  204. actual);
  205. return ((void *) &(p->addr));
  206. } /* endif */
  207. p--;
  208. } /* endwhile */
  209. } else {
  210. while (p > pe) {
  211. actual = p->addr;
  212. expected = Swap_32 ((unsigned long) p);
  213. if (actual != expected) {
  214. Write_Error (mode, (unsigned long) &(p->addr), expected,
  215. actual);
  216. return ((void *) &(p->addr));
  217. } /* endif */
  218. p--;
  219. } /* endwhile */
  220. } /* endif */
  221. return (NULL);
  222. }
  223. /*
  224. * fills the memblock of <size> bytes from <startaddr> with walking bit pattern
  225. */
  226. void RAM_MemTest_WriteWalkBit (unsigned long startaddr, unsigned long size)
  227. {
  228. volatile unsigned long *p, *pe;
  229. unsigned long i;
  230. p = (unsigned long *) startaddr;
  231. pe = (unsigned long *) (startaddr + size);
  232. i = 0;
  233. while (p < pe) {
  234. *p = 1UL << i;
  235. i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
  236. p++;
  237. } /* endwhile */
  238. }
  239. /*
  240. * checks the memblock of <size> bytes from <startaddr>
  241. * returns the address of the error or NULL if all is well
  242. */
  243. void *RAM_MemTest_CheckWalkBit (int mode, unsigned long startaddr,
  244. unsigned long size)
  245. {
  246. volatile unsigned long *p, *pe;
  247. unsigned long actual, expected;
  248. unsigned long i;
  249. p = (unsigned long *) startaddr;
  250. pe = (unsigned long *) (startaddr + size);
  251. i = 0;
  252. while (p < pe) {
  253. actual = *p;
  254. expected = (1UL << i);
  255. if (actual != expected) {
  256. Write_Error (mode, (unsigned long) p, expected, actual);
  257. return ((void *) p);
  258. } /* endif */
  259. i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
  260. p++;
  261. } /* endwhile */
  262. return (NULL);
  263. }
  264. /*
  265. * fills the memblock of <size> bytes from <startaddr> with "random" pattern
  266. */
  267. void RAM_MemTest_WriteRandomPattern (unsigned long startaddr,
  268. unsigned long size,
  269. unsigned long *pat)
  270. {
  271. unsigned long i, p;
  272. p = *pat;
  273. for (i = 0; i < (size / 4); i++) {
  274. *(unsigned long *) (startaddr + i * 4) = p;
  275. if ((p % 2) > 0) {
  276. p ^= i;
  277. p >>= 1;
  278. p |= 0x80000000;
  279. } else {
  280. p ^= ~i;
  281. p >>= 1;
  282. } /* endif */
  283. } /* endfor */
  284. *pat = p;
  285. }
  286. /*
  287. * checks the memblock of <size> bytes from <startaddr>
  288. * returns the address of the error or NULL if all is well
  289. */
  290. void *RAM_MemTest_CheckRandomPattern (int mode, unsigned long startaddr,
  291. unsigned long size,
  292. unsigned long *pat)
  293. {
  294. void *perr = NULL;
  295. unsigned long i, p, p1;
  296. p = *pat;
  297. for (i = 0; i < (size / 4); i++) {
  298. p1 = *(unsigned long *) (startaddr + i * 4);
  299. if (p1 != p) {
  300. if (perr == NULL) {
  301. Write_Error (mode, startaddr + i * 4, p, p1);
  302. perr = (void *) (startaddr + i * 4);
  303. } /* endif */
  304. }
  305. /* endif */
  306. if ((p % 2) > 0) {
  307. p ^= i;
  308. p >>= 1;
  309. p |= 0x80000000;
  310. } else {
  311. p ^= ~i;
  312. p >>= 1;
  313. } /* endif */
  314. } /* endfor */
  315. *pat = p;
  316. return (perr);
  317. }
  318. void RAM_MemTest_WriteData1 (unsigned long startaddr, unsigned long size,
  319. unsigned long *pat)
  320. {
  321. RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT1, TESTPAT2);
  322. }
  323. void *RAM_MemTest_CheckData1 (int mode, unsigned long startaddr,
  324. unsigned long size, unsigned long *pat)
  325. {
  326. return (RAM_MemTest_CheckPattern2
  327. (mode, startaddr, size, TESTPAT1, TESTPAT2));
  328. }
  329. void RAM_MemTest_WriteData2 (unsigned long startaddr, unsigned long size,
  330. unsigned long *pat)
  331. {
  332. RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT2, TESTPAT1);
  333. }
  334. void *RAM_MemTest_CheckData2 (int mode, unsigned long startaddr,
  335. unsigned long size, unsigned long *pat)
  336. {
  337. return (RAM_MemTest_CheckPattern2
  338. (mode, startaddr, size, TESTPAT2, TESTPAT1));
  339. }
  340. void RAM_MemTest_WriteAddr1 (unsigned long startaddr, unsigned long size,
  341. unsigned long *pat)
  342. {
  343. RAM_MemTest_WriteAddrLine (startaddr, size, FALSE);
  344. }
  345. void *RAM_MemTest_Check1Addr1 (int mode, unsigned long startaddr,
  346. unsigned long size, unsigned long *pat)
  347. {
  348. return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, FALSE));
  349. }
  350. void *RAM_MemTest_Check2Addr1 (int mode, unsigned long startaddr,
  351. unsigned long size, unsigned long *pat)
  352. {
  353. return (RAM_MemTest_CheckAddrLineReverse
  354. (mode, startaddr, size, FALSE));
  355. }
  356. void RAM_MemTest_WriteAddr2 (unsigned long startaddr, unsigned long size,
  357. unsigned long *pat)
  358. {
  359. RAM_MemTest_WriteAddrLine (startaddr, size, TRUE);
  360. }
  361. void *RAM_MemTest_Check1Addr2 (int mode, unsigned long startaddr,
  362. unsigned long size, unsigned long *pat)
  363. {
  364. return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, TRUE));
  365. }
  366. void *RAM_MemTest_Check2Addr2 (int mode, unsigned long startaddr,
  367. unsigned long size, unsigned long *pat)
  368. {
  369. return (RAM_MemTest_CheckAddrLineReverse
  370. (mode, startaddr, size, TRUE));
  371. }
  372. typedef struct {
  373. void (*test_write) (unsigned long startaddr, unsigned long size,
  374. unsigned long *pat);
  375. char *test_write_desc;
  376. void *(*test_check1) (int mode, unsigned long startaddr,
  377. unsigned long size, unsigned long *pat);
  378. void *(*test_check2) (int mode, unsigned long startaddr,
  379. unsigned long size, unsigned long *pat);
  380. } RAM_MEMTEST_FUNC;
  381. #define TEST_STAGES 5
  382. static RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = {
  383. {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1,
  384. NULL},
  385. {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2,
  386. NULL},
  387. {RAM_MemTest_WriteAddr1, "address line test...\n",
  388. RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1},
  389. {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n",
  390. RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2},
  391. {RAM_MemTest_WriteRandomPattern, "random data test...\n",
  392. RAM_MemTest_CheckRandomPattern, NULL}
  393. };
  394. void mem_test_reloc(void)
  395. {
  396. unsigned long addr;
  397. int i;
  398. for (i=0; i< TEST_STAGES; i++) {
  399. addr = (ulong) (test_stage[i].test_write) + gd->reloc_off;
  400. test_stage[i].test_write=
  401. (void (*) (unsigned long startaddr, unsigned long size,
  402. unsigned long *pat))addr;
  403. addr = (ulong) (test_stage[i].test_write_desc) + gd->reloc_off;
  404. test_stage[i].test_write_desc=(char *)addr;
  405. if(test_stage[i].test_check1) {
  406. addr = (ulong) (test_stage[i].test_check1) + gd->reloc_off;
  407. test_stage[i].test_check1=
  408. (void *(*) (int mode, unsigned long startaddr,
  409. unsigned long size, unsigned long *pat))addr;
  410. }
  411. if(test_stage[i].test_check2) {
  412. addr = (ulong) (test_stage[i].test_check2) + gd->reloc_off;
  413. test_stage[i].test_check2=
  414. (void *(*) (int mode, unsigned long startaddr,
  415. unsigned long size, unsigned long *pat))addr;
  416. }
  417. }
  418. }
  419. int mem_test (unsigned long start, unsigned long ramsize, int quiet)
  420. {
  421. unsigned long errors, stage;
  422. unsigned long startaddr, size, i;
  423. const unsigned long blocksize = 0x80000; /* check in 512KB blocks */
  424. unsigned long *perr;
  425. unsigned long rdatapat;
  426. char dispbuf[80];
  427. int status = TEST_PASSED;
  428. int prog = 0;
  429. errors = 0;
  430. startaddr = start;
  431. size = ramsize;
  432. if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
  433. prog++;
  434. printf (".");
  435. }
  436. sprintf (dispbuf, "\nMemory Test: addr = 0x%lx size = 0x%lx\n",
  437. startaddr, size);
  438. testm_puts (quiet, dispbuf);
  439. for (stage = 0; stage < TEST_STAGES; stage++) {
  440. sprintf (dispbuf, test_stage[stage].test_write_desc);
  441. testm_puts (quiet, dispbuf);
  442. /* fill SDRAM */
  443. rdatapat = 0x12345678;
  444. sprintf (dispbuf, "writing block: ");
  445. testm_puts (quiet, dispbuf);
  446. for (i = 0; i < size; i += blocksize) {
  447. sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
  448. testm_puts (quiet, dispbuf);
  449. test_stage[stage].test_write (startaddr + i, blocksize,
  450. &rdatapat);
  451. } /* endfor */
  452. sprintf (dispbuf, "\n");
  453. testm_puts (quiet, dispbuf);
  454. if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
  455. prog++;
  456. printf (".");
  457. }
  458. /* check SDRAM */
  459. rdatapat = 0x12345678;
  460. sprintf (dispbuf, "checking block: ");
  461. testm_puts (quiet, dispbuf);
  462. for (i = 0; i < size; i += blocksize) {
  463. sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
  464. testm_puts (quiet, dispbuf);
  465. if ((perr =
  466. test_stage[stage].test_check1 (quiet, startaddr + i,
  467. blocksize,
  468. &rdatapat)) != NULL) {
  469. status = TEST_FAILED;
  470. } /* endif */
  471. } /* endfor */
  472. sprintf (dispbuf, "\n");
  473. testm_puts (quiet, dispbuf);
  474. if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
  475. prog++;
  476. printf (".");
  477. }
  478. if (test_stage[stage].test_check2 != NULL) {
  479. /* check2 SDRAM */
  480. sprintf (dispbuf, "2nd checking block: ");
  481. rdatapat = 0x12345678;
  482. testm_puts (quiet, dispbuf);
  483. for (i = 0; i < size; i += blocksize) {
  484. sprintf (dispbuf, "%04lX\b\b\b\b", i / blocksize);
  485. testm_puts (quiet, dispbuf);
  486. if ((perr =
  487. test_stage[stage].test_check2 (quiet, startaddr + i,
  488. blocksize,
  489. &rdatapat)) != NULL) {
  490. status = TEST_FAILED;
  491. } /* endif */
  492. } /* endfor */
  493. sprintf (dispbuf, "\n");
  494. testm_puts (quiet, dispbuf);
  495. if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
  496. prog++;
  497. printf (".");
  498. }
  499. }
  500. } /* next stage */
  501. if ((quiet & TEST_SHOW_PROG) == TEST_SHOW_PROG) {
  502. while (prog-- > 0)
  503. printf ("\b \b");
  504. }
  505. if (status == TEST_FAILED)
  506. errors++;
  507. return (errors);
  508. }