memtst.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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. #define FALSE 0
  49. #define TRUE 1
  50. #define TEST_QUIET 8
  51. #define TEST_SHOW_PROG 4
  52. #define TEST_SHOW_ERR 2
  53. #define TEST_SHOW_ALL 1
  54. #define TESTPAT1 0xAA55AA55
  55. #define TESTPAT2 0x55AA55AA
  56. #define TEST_PASSED 0
  57. #define TEST_FAILED 1
  58. #define MEGABYTE (1024*1024)
  59. typedef struct {
  60. volatile unsigned long pat1;
  61. volatile unsigned long pat2;
  62. } RAM_MEMTEST_PATTERN2;
  63. typedef struct {
  64. volatile unsigned long addr;
  65. } RAM_MEMTEST_ADDRLINE;
  66. static __inline unsigned long Swap_32 (unsigned long val)
  67. {
  68. return (((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF));
  69. }
  70. void testm_puts (int quiet, char *buf)
  71. {
  72. if ((quiet & TEST_SHOW_ALL) == TEST_SHOW_ALL)
  73. puts (buf);
  74. }
  75. void Write_Error (int mode, unsigned long addr, unsigned long expected,
  76. unsigned long actual)
  77. {
  78. char dispbuf[64];
  79. sprintf (dispbuf, "\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ",
  80. addr, expected, actual);
  81. testm_puts (((mode & TEST_SHOW_ERR) ==
  82. TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode, dispbuf);
  83. }
  84. /*
  85. * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2
  86. */
  87. void RAM_MemTest_WritePattern2 (unsigned long startaddr,
  88. unsigned long size, unsigned long pat1,
  89. unsigned long pat2)
  90. {
  91. RAM_MEMTEST_PATTERN2 *p, *pe;
  92. p = (RAM_MEMTEST_PATTERN2 *) startaddr;
  93. pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
  94. while (p < pe) {
  95. p->pat1 = pat1;
  96. p->pat2 = pat2;
  97. p++;
  98. } /* endwhile */
  99. }
  100. /*
  101. * checks the memblock of <size> bytes from <startaddr> with pat1 and pat2
  102. * returns the address of the first error or NULL if all is well
  103. */
  104. void *RAM_MemTest_CheckPattern2 (int mode, unsigned long startaddr,
  105. unsigned long size, unsigned long pat1,
  106. unsigned long pat2)
  107. {
  108. RAM_MEMTEST_PATTERN2 *p, *pe;
  109. unsigned long actual1, actual2;
  110. p = (RAM_MEMTEST_PATTERN2 *) startaddr;
  111. pe = (RAM_MEMTEST_PATTERN2 *) (startaddr + size);
  112. while (p < pe) {
  113. actual1 = p->pat1;
  114. actual2 = p->pat2;
  115. if (actual1 != pat1) {
  116. Write_Error (mode, (unsigned long) &(p->pat1), pat1, actual1);
  117. return ((void *) &(p->pat1));
  118. }
  119. /* endif */
  120. if (actual2 != pat2) {
  121. Write_Error (mode, (unsigned long) &(p->pat2), pat2, actual2);
  122. return ((void *) &(p->pat2));
  123. }
  124. /* endif */
  125. p++;
  126. } /* endwhile */
  127. return (NULL);
  128. }
  129. /*
  130. * fills the memblock of <size> bytes from <startaddr> with the address
  131. */
  132. void RAM_MemTest_WriteAddrLine (unsigned long startaddr,
  133. unsigned long size, int swapped)
  134. {
  135. RAM_MEMTEST_ADDRLINE *p, *pe;
  136. p = (RAM_MEMTEST_ADDRLINE *) startaddr;
  137. pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
  138. if (!swapped) {
  139. while (p < pe) {
  140. p->addr = (unsigned long) p;
  141. p++;
  142. } /* endwhile */
  143. } else {
  144. while (p < pe) {
  145. p->addr = Swap_32 ((unsigned long) p);
  146. p++;
  147. } /* endwhile */
  148. } /* endif */
  149. }
  150. /*
  151. * checks the memblock of <size> bytes from <startaddr>
  152. * returns the address of the error or NULL if all is well
  153. */
  154. void *RAM_MemTest_CheckAddrLine (int mode, unsigned long startaddr,
  155. unsigned long size, int swapped)
  156. {
  157. RAM_MEMTEST_ADDRLINE *p, *pe;
  158. unsigned long actual, expected;
  159. p = (RAM_MEMTEST_ADDRLINE *) startaddr;
  160. pe = (RAM_MEMTEST_ADDRLINE *) (startaddr + size);
  161. if (!swapped) {
  162. while (p < pe) {
  163. actual = p->addr;
  164. expected = (unsigned long) p;
  165. if (actual != expected) {
  166. Write_Error (mode, (unsigned long) &(p->addr), expected,
  167. actual);
  168. return ((void *) &(p->addr));
  169. } /* endif */
  170. p++;
  171. } /* endwhile */
  172. } else {
  173. while (p < pe) {
  174. actual = p->addr;
  175. expected = Swap_32 ((unsigned long) p);
  176. if (actual != expected) {
  177. Write_Error (mode, (unsigned long) &(p->addr), expected,
  178. actual);
  179. return ((void *) &(p->addr));
  180. } /* endif */
  181. p++;
  182. } /* endwhile */
  183. } /* endif */
  184. return (NULL);
  185. }
  186. /*
  187. * checks the memblock of <size> bytes from <startaddr+size>
  188. * returns the address of the error or NULL if all is well
  189. */
  190. void *RAM_MemTest_CheckAddrLineReverse (int mode, unsigned long startaddr,
  191. unsigned long size, int swapped)
  192. {
  193. RAM_MEMTEST_ADDRLINE *p, *pe;
  194. unsigned long actual, expected;
  195. p = (RAM_MEMTEST_ADDRLINE *) (startaddr + size - sizeof (p->addr));
  196. pe = (RAM_MEMTEST_ADDRLINE *) startaddr;
  197. if (!swapped) {
  198. while (p > pe) {
  199. actual = p->addr;
  200. expected = (unsigned long) p;
  201. if (actual != expected) {
  202. Write_Error (mode, (unsigned long) &(p->addr), expected,
  203. actual);
  204. return ((void *) &(p->addr));
  205. } /* endif */
  206. p--;
  207. } /* endwhile */
  208. } else {
  209. while (p > pe) {
  210. actual = p->addr;
  211. expected = Swap_32 ((unsigned long) p);
  212. if (actual != expected) {
  213. Write_Error (mode, (unsigned long) &(p->addr), expected,
  214. actual);
  215. return ((void *) &(p->addr));
  216. } /* endif */
  217. p--;
  218. } /* endwhile */
  219. } /* endif */
  220. return (NULL);
  221. }
  222. /*
  223. * fills the memblock of <size> bytes from <startaddr> with walking bit pattern
  224. */
  225. void RAM_MemTest_WriteWalkBit (unsigned long startaddr, unsigned long size)
  226. {
  227. volatile unsigned long *p, *pe;
  228. unsigned long i;
  229. p = (unsigned long *) startaddr;
  230. pe = (unsigned long *) (startaddr + size);
  231. i = 0;
  232. while (p < pe) {
  233. *p = 1UL << i;
  234. i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
  235. p++;
  236. } /* endwhile */
  237. }
  238. /*
  239. * checks the memblock of <size> bytes from <startaddr>
  240. * returns the address of the error or NULL if all is well
  241. */
  242. void *RAM_MemTest_CheckWalkBit (int mode, unsigned long startaddr,
  243. unsigned long size)
  244. {
  245. volatile unsigned long *p, *pe;
  246. unsigned long actual, expected;
  247. unsigned long i;
  248. p = (unsigned long *) startaddr;
  249. pe = (unsigned long *) (startaddr + size);
  250. i = 0;
  251. while (p < pe) {
  252. actual = *p;
  253. expected = (1UL << i);
  254. if (actual != expected) {
  255. Write_Error (mode, (unsigned long) p, expected, actual);
  256. return ((void *) p);
  257. } /* endif */
  258. i = (i + 1 + (((unsigned long) p) >> 7)) % 32;
  259. p++;
  260. } /* endwhile */
  261. return (NULL);
  262. }
  263. /*
  264. * fills the memblock of <size> bytes from <startaddr> with "random" pattern
  265. */
  266. void RAM_MemTest_WriteRandomPattern (unsigned long startaddr,
  267. unsigned long size,
  268. unsigned long *pat)
  269. {
  270. unsigned long i, p;
  271. p = *pat;
  272. for (i = 0; i < (size / 4); i++) {
  273. *(unsigned long *) (startaddr + i * 4) = p;
  274. if ((p % 2) > 0) {
  275. p ^= i;
  276. p >>= 1;
  277. p |= 0x80000000;
  278. } else {
  279. p ^= ~i;
  280. p >>= 1;
  281. } /* endif */
  282. } /* endfor */
  283. *pat = p;
  284. }
  285. /*
  286. * checks the memblock of <size> bytes from <startaddr>
  287. * returns the address of the error or NULL if all is well
  288. */
  289. void *RAM_MemTest_CheckRandomPattern (int mode, unsigned long startaddr,
  290. unsigned long size,
  291. unsigned long *pat)
  292. {
  293. void *perr = NULL;
  294. unsigned long i, p, p1;
  295. p = *pat;
  296. for (i = 0; i < (size / 4); i++) {
  297. p1 = *(unsigned long *) (startaddr + i * 4);
  298. if (p1 != p) {
  299. if (perr == NULL) {
  300. Write_Error (mode, startaddr + i * 4, p, p1);
  301. perr = (void *) (startaddr + i * 4);
  302. } /* endif */
  303. }
  304. /* endif */
  305. if ((p % 2) > 0) {
  306. p ^= i;
  307. p >>= 1;
  308. p |= 0x80000000;
  309. } else {
  310. p ^= ~i;
  311. p >>= 1;
  312. } /* endif */
  313. } /* endfor */
  314. *pat = p;
  315. return (perr);
  316. }
  317. void RAM_MemTest_WriteData1 (unsigned long startaddr, unsigned long size,
  318. unsigned long *pat)
  319. {
  320. RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT1, TESTPAT2);
  321. }
  322. void *RAM_MemTest_CheckData1 (int mode, unsigned long startaddr,
  323. unsigned long size, unsigned long *pat)
  324. {
  325. return (RAM_MemTest_CheckPattern2
  326. (mode, startaddr, size, TESTPAT1, TESTPAT2));
  327. }
  328. void RAM_MemTest_WriteData2 (unsigned long startaddr, unsigned long size,
  329. unsigned long *pat)
  330. {
  331. RAM_MemTest_WritePattern2 (startaddr, size, TESTPAT2, TESTPAT1);
  332. }
  333. void *RAM_MemTest_CheckData2 (int mode, unsigned long startaddr,
  334. unsigned long size, unsigned long *pat)
  335. {
  336. return (RAM_MemTest_CheckPattern2
  337. (mode, startaddr, size, TESTPAT2, TESTPAT1));
  338. }
  339. void RAM_MemTest_WriteAddr1 (unsigned long startaddr, unsigned long size,
  340. unsigned long *pat)
  341. {
  342. RAM_MemTest_WriteAddrLine (startaddr, size, FALSE);
  343. }
  344. void *RAM_MemTest_Check1Addr1 (int mode, unsigned long startaddr,
  345. unsigned long size, unsigned long *pat)
  346. {
  347. return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, FALSE));
  348. }
  349. void *RAM_MemTest_Check2Addr1 (int mode, unsigned long startaddr,
  350. unsigned long size, unsigned long *pat)
  351. {
  352. return (RAM_MemTest_CheckAddrLineReverse
  353. (mode, startaddr, size, FALSE));
  354. }
  355. void RAM_MemTest_WriteAddr2 (unsigned long startaddr, unsigned long size,
  356. unsigned long *pat)
  357. {
  358. RAM_MemTest_WriteAddrLine (startaddr, size, TRUE);
  359. }
  360. void *RAM_MemTest_Check1Addr2 (int mode, unsigned long startaddr,
  361. unsigned long size, unsigned long *pat)
  362. {
  363. return (RAM_MemTest_CheckAddrLine (mode, startaddr, size, TRUE));
  364. }
  365. void *RAM_MemTest_Check2Addr2 (int mode, unsigned long startaddr,
  366. unsigned long size, unsigned long *pat)
  367. {
  368. return (RAM_MemTest_CheckAddrLineReverse
  369. (mode, startaddr, size, TRUE));
  370. }
  371. typedef struct {
  372. void (*test_write) (unsigned long startaddr, unsigned long size,
  373. unsigned long *pat);
  374. char *test_write_desc;
  375. void *(*test_check1) (int mode, unsigned long startaddr,
  376. unsigned long size, unsigned long *pat);
  377. void *(*test_check2) (int mode, unsigned long startaddr,
  378. unsigned long size, unsigned long *pat);
  379. } RAM_MEMTEST_FUNC;
  380. #define TEST_STAGES 5
  381. static RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = {
  382. {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1,
  383. NULL},
  384. {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2,
  385. NULL},
  386. {RAM_MemTest_WriteAddr1, "address line test...\n",
  387. RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1},
  388. {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n",
  389. RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2},
  390. {RAM_MemTest_WriteRandomPattern, "random data test...\n",
  391. RAM_MemTest_CheckRandomPattern, NULL}
  392. };
  393. void mem_test_reloc(void)
  394. {
  395. DECLARE_GLOBAL_DATA_PTR;
  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. }