sc520_sdram.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * (C) Copyright 2010,2011
  3. * Graeme Russ, <graeme.russ@gmail.com>
  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. #include <common.h>
  24. #include <asm/io.h>
  25. #include <asm/processor-flags.h>
  26. #include <asm/arch/sc520.h>
  27. DECLARE_GLOBAL_DATA_PTR;
  28. struct sc520_sdram_info {
  29. u8 banks;
  30. u8 columns;
  31. u8 rows;
  32. u8 size;
  33. };
  34. static void sc520_sizemem(void);
  35. static void sc520_set_dram_timing(void);
  36. static void sc520_set_dram_refresh_rate(void);
  37. static void sc520_enable_dram_refresh(void);
  38. static void sc520_enable_sdram(void);
  39. #if CONFIG_SYS_SDRAM_ECC_ENABLE
  40. static void sc520_enable_ecc(void)
  41. #endif
  42. int dram_init_f(void)
  43. {
  44. sc520_sizemem();
  45. sc520_set_dram_timing();
  46. sc520_set_dram_refresh_rate();
  47. sc520_enable_dram_refresh();
  48. sc520_enable_sdram();
  49. #if CONFIG_SYS_SDRAM_ECC_ENABLE
  50. sc520_enable_ecc();
  51. #endif
  52. return 0;
  53. }
  54. static inline void sc520_dummy_write(void)
  55. {
  56. writew(0x0000, CACHELINESZ);
  57. }
  58. static inline void sc520_issue_sdram_op_mode_select(u8 command)
  59. {
  60. writeb(command, &sc520_mmcr->drcctl);
  61. sc520_dummy_write();
  62. }
  63. static inline int check_long(u32 test_long)
  64. {
  65. u8 i;
  66. u8 tmp_byte = (u8)(test_long & 0x000000ff);
  67. for (i = 1; i < 4; i++) {
  68. if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
  69. return -1;
  70. }
  71. return 0;
  72. }
  73. static inline int write_and_test(u32 data, u32 address)
  74. {
  75. writel(data, address);
  76. if (readl(address) == data)
  77. return 0; /* Good */
  78. else
  79. return -1; /* Bad */
  80. }
  81. static void sc520_enable_sdram(void)
  82. {
  83. u32 par_config;
  84. /* Enable Writes, Caching and Code Execution to SDRAM */
  85. par_config = readl(&sc520_mmcr->par[3]);
  86. par_config &= ~(SC520_PAR_EXEC_DIS |
  87. SC520_PAR_CACHE_DIS |
  88. SC520_PAR_WRITE_DIS);
  89. writel(par_config, &sc520_mmcr->par[3]);
  90. par_config = readl(&sc520_mmcr->par[4]);
  91. par_config &= ~(SC520_PAR_EXEC_DIS |
  92. SC520_PAR_CACHE_DIS |
  93. SC520_PAR_WRITE_DIS);
  94. writel(par_config, &sc520_mmcr->par[4]);
  95. }
  96. static void sc520_set_dram_timing(void)
  97. {
  98. u8 drctmctl = 0x00;
  99. #if defined CONFIG_SYS_SDRAM_DRCTMCTL
  100. /* just have your hardware designer _GIVE_ you what you need here! */
  101. drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
  102. #else
  103. switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
  104. case 2:
  105. break;
  106. case 3:
  107. drctmctl |= 0x01;
  108. break;
  109. case 4:
  110. default:
  111. drctmctl |= 0x02;
  112. break;
  113. }
  114. switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
  115. case 2:
  116. break;
  117. case 3:
  118. drctmctl |= 0x04;
  119. break;
  120. case 4:
  121. default:
  122. drctmctl |= 0x08;
  123. break;
  124. case 6:
  125. drctmctl |= 0x0c;
  126. break;
  127. }
  128. switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
  129. case 2:
  130. break;
  131. case 3:
  132. default:
  133. drctmctl |= 0x10;
  134. break;
  135. }
  136. #endif
  137. writeb(drctmctl, &sc520_mmcr->drctmctl);
  138. /* Issue load mode register command */
  139. sc520_issue_sdram_op_mode_select(0x03);
  140. }
  141. static void sc520_set_dram_refresh_rate(void)
  142. {
  143. u8 drctl;
  144. drctl = readb(&sc520_mmcr->drcctl);
  145. drctl &= 0xcf;
  146. switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
  147. case 78:
  148. break;
  149. case 156:
  150. default:
  151. drctl |= 0x10;
  152. break;
  153. case 312:
  154. drctl |= 0x20;
  155. break;
  156. case 624:
  157. drctl |= 0x30;
  158. break;
  159. }
  160. writeb(drctl, &sc520_mmcr->drcctl);
  161. }
  162. static void sc520_enable_dram_refresh(void)
  163. {
  164. u8 drctl;
  165. drctl = readb(&sc520_mmcr->drcctl);
  166. drctl &= 0x30; /* keep refresh rate */
  167. drctl |= 0x08; /* enable refresh, normal mode */
  168. writeb(drctl, &sc520_mmcr->drcctl);
  169. }
  170. static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
  171. {
  172. u32 col_data;
  173. u32 row_data;
  174. u32 drcbendadr;
  175. u16 drccfg;
  176. u8 banks = 0x00;
  177. u8 columns = 0x00;
  178. u8 rows = 0x00;
  179. bank_info->banks = 0x00;
  180. bank_info->columns = 0x00;
  181. bank_info->rows = 0x00;
  182. bank_info->size = 0x00;
  183. if ((bank < 0) || (bank > 3)) {
  184. printf("Bad Bank ID\n");
  185. return;
  186. }
  187. /* Save configuration */
  188. drcbendadr = readl(&sc520_mmcr->drcbendadr);
  189. drccfg = readw(&sc520_mmcr->drccfg);
  190. /* Setup SDRAM Bank to largest possible size */
  191. writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
  192. /* Set ending address for this bank */
  193. writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
  194. /* write col 11 wrap adr */
  195. if (write_and_test(COL11_DATA, COL11_ADR) != 0)
  196. goto restore_and_exit;
  197. /* write col 10 wrap adr */
  198. if (write_and_test(COL10_DATA, COL10_ADR) != 0)
  199. goto restore_and_exit;
  200. /* write col 9 wrap adr */
  201. if (write_and_test(COL09_DATA, COL09_ADR) != 0)
  202. goto restore_and_exit;
  203. /* write col 8 wrap adr */
  204. if (write_and_test(COL08_DATA, COL08_ADR) != 0)
  205. goto restore_and_exit;
  206. col_data = readl(COL11_ADR);
  207. /* All four bytes in the read long must be the same */
  208. if (check_long(col_data) < 0)
  209. goto restore_and_exit;
  210. if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
  211. columns = (u8)(col_data & 0x000000ff);
  212. else
  213. goto restore_and_exit;
  214. /* write row 14 wrap adr */
  215. if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
  216. goto restore_and_exit;
  217. /* write row 13 wrap adr */
  218. if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
  219. goto restore_and_exit;
  220. /* write row 12 wrap adr */
  221. if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
  222. goto restore_and_exit;
  223. /* write row 11 wrap adr */
  224. if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
  225. goto restore_and_exit;
  226. if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
  227. goto restore_and_exit;
  228. /*
  229. * read data @ row 12 wrap adr to determine number of banks,
  230. * and read data @ row 14 wrap adr to determine number of rows.
  231. * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
  232. * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
  233. * if data @ row 12 wrap == 11 or 12, we have 4 banks,
  234. */
  235. row_data = readl(ROW12_ADR);
  236. /* All four bytes in the read long must be the same */
  237. if (check_long(row_data) != 0)
  238. goto restore_and_exit;
  239. switch (row_data) {
  240. case ROW10_DATA:
  241. banks = 2;
  242. break;
  243. case ROW11_DATA:
  244. case ROW12_DATA:
  245. banks = 4;
  246. break;
  247. default:
  248. goto restore_and_exit;
  249. }
  250. row_data = readl(ROW14_ADR);
  251. /* All four bytes in the read long must be the same */
  252. if (check_long(row_data) != 0)
  253. goto restore_and_exit;
  254. switch (row_data) {
  255. case ROW11_DATA:
  256. case ROW12_DATA:
  257. case ROW13_DATA:
  258. case ROW14_DATA:
  259. rows = (u8)(row_data & 0x000000ff);
  260. break;
  261. default:
  262. goto restore_and_exit;
  263. }
  264. bank_info->banks = banks;
  265. bank_info->columns = columns;
  266. bank_info->rows = rows;
  267. if ((bank_info->banks != 0) &&
  268. (bank_info->columns != 0) &&
  269. (bank_info->rows != 0)) {
  270. bank_info->size = bank_info->rows;
  271. bank_info->size >>= (11 - bank_info->columns);
  272. bank_info->size++;
  273. }
  274. restore_and_exit:
  275. /* Restore configuration */
  276. writel(drcbendadr, &sc520_mmcr->drcbendadr);
  277. writew(drccfg, &sc520_mmcr->drccfg);
  278. }
  279. static void sc520_setup_sizemem(void)
  280. {
  281. u8 i;
  282. /* Disable write buffer */
  283. writeb(0x00, &sc520_mmcr->dbctl);
  284. /* Disable ECC */
  285. writeb(0x00, &sc520_mmcr->eccctl);
  286. /* Set slowest SDRAM timing */
  287. writeb(0x1e, &sc520_mmcr->drctmctl);
  288. /* Issue a NOP to all SDRAM banks */
  289. sc520_issue_sdram_op_mode_select(0x01);
  290. /* Delay for 100 microseconds */
  291. udelay(100);
  292. /* Issue 'All Banks Precharge' command */
  293. sc520_issue_sdram_op_mode_select(0x02);
  294. /* Issue 2 'Auto Refresh Enable' command */
  295. sc520_issue_sdram_op_mode_select(0x04);
  296. sc520_dummy_write();
  297. /* Issue 'Load Mode Register' command */
  298. sc520_issue_sdram_op_mode_select(0x03);
  299. /* Issue 8 more 'Auto Refresh Enable' commands */
  300. sc520_issue_sdram_op_mode_select(0x04);
  301. for (i = 0; i < 7; i++)
  302. sc520_dummy_write();
  303. /* Set control register to 'Normal Mode' */
  304. writeb(0x00, &sc520_mmcr->drcctl);
  305. }
  306. static void sc520_sizemem(void)
  307. {
  308. struct sc520_sdram_info sdram_info[4];
  309. u8 bank_config = 0x00;
  310. u8 end_addr = 0x00;
  311. u16 drccfg = 0x0000;
  312. u32 drcbendadr = 0x00000000;
  313. u8 i;
  314. /* Use PARs to disable caching of maximum allowable 256MB SDRAM */
  315. writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
  316. writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
  317. sc520_setup_sizemem();
  318. gd->ram_size = 0;
  319. /* Size each SDRAM bank */
  320. for (i = 0; i <= 3; i++) {
  321. sc520_get_bank_info(i, &sdram_info[i]);
  322. if (sdram_info[i].banks != 0) {
  323. /* Update Configuration register */
  324. bank_config = sdram_info[i].columns - 8;
  325. if (sdram_info[i].banks == 4)
  326. bank_config |= 0x08;
  327. drccfg |= bank_config << (i * 4);
  328. /* Update End Address register */
  329. end_addr += sdram_info[i].size;
  330. drcbendadr |= (end_addr | 0x80) << (i * 8);
  331. gd->ram_size += sdram_info[i].size << 22;
  332. }
  333. /* Issue 'All Banks Precharge' command */
  334. sc520_issue_sdram_op_mode_select(0x02);
  335. /* Set control register to 'Normal Mode' */
  336. writeb(0x00, &sc520_mmcr->drcctl);
  337. }
  338. writel(drcbendadr, &sc520_mmcr->drcbendadr);
  339. writew(drccfg, &sc520_mmcr->drccfg);
  340. /* Clear PARs preventing caching of SDRAM */
  341. writel(0x00000000, &sc520_mmcr->par[3]);
  342. writel(0x00000000, &sc520_mmcr->par[4]);
  343. }
  344. #if CONFIG_SYS_SDRAM_ECC_ENABLE
  345. static void sc520_enable_ecc(void)
  346. /* A nominal memory test: just a byte at each address line */
  347. movl %eax, %ecx
  348. shrl $0x1, %ecx
  349. movl $0x1, %edi
  350. memtest0:
  351. movb $0xa5, (%edi)
  352. cmpb $0xa5, (%edi)
  353. jne out
  354. shrl $0x1, %ecx
  355. andl %ecx, %ecx
  356. jz set_ecc
  357. shll $0x1, %edi
  358. jmp memtest0
  359. set_ecc:
  360. /* clear all ram with a memset */
  361. movl %eax, %ecx
  362. xorl %esi, %esi
  363. xorl %edi, %edi
  364. xorl %eax, %eax
  365. shrl $0x2, %ecx
  366. cld
  367. rep stosl
  368. /* enable read, write buffers */
  369. movb $0x11, %al
  370. movl $DBCTL, %edi
  371. movb %al, (%edi)
  372. /* enable NMI mapping for ECC */
  373. movl $ECCINT, %edi
  374. movb $0x10, %al
  375. movb %al, (%edi)
  376. /* Turn on ECC */
  377. movl $ECCCTL, %edi
  378. movb $0x05, %al
  379. movb %al,(%edi)
  380. out:
  381. jmp init_ecc_ret
  382. }
  383. #endif
  384. int dram_init(void)
  385. {
  386. ulong dram_ctrl;
  387. ulong dram_present = 0x00000000;
  388. /*
  389. * We read-back the configuration of the dram
  390. * controller that the assembly code wrote
  391. */
  392. dram_ctrl = readl(&sc520_mmcr->drcbendadr);
  393. gd->bd->bi_dram[0].start = 0;
  394. if (dram_ctrl & 0x80) {
  395. /* bank 0 enabled */
  396. gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
  397. dram_present = gd->bd->bi_dram[1].start;
  398. gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
  399. } else {
  400. gd->bd->bi_dram[0].size = 0;
  401. gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
  402. }
  403. if (dram_ctrl & 0x8000) {
  404. /* bank 1 enabled */
  405. gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
  406. dram_present = gd->bd->bi_dram[2].start;
  407. gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
  408. gd->bd->bi_dram[1].start;
  409. } else {
  410. gd->bd->bi_dram[1].size = 0;
  411. gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
  412. }
  413. if (dram_ctrl & 0x800000) {
  414. /* bank 2 enabled */
  415. gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
  416. dram_present = gd->bd->bi_dram[3].start;
  417. gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
  418. gd->bd->bi_dram[2].start;
  419. } else {
  420. gd->bd->bi_dram[2].size = 0;
  421. gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
  422. }
  423. if (dram_ctrl & 0x80000000) {
  424. /* bank 3 enabled */
  425. dram_present = (dram_ctrl & 0x7f000000) >> 2;
  426. gd->bd->bi_dram[3].size = dram_present -
  427. gd->bd->bi_dram[3].start;
  428. } else {
  429. gd->bd->bi_dram[3].size = 0;
  430. }
  431. gd->ram_size = dram_present;
  432. return 0;
  433. }