4xx_ibm_ddr2_autocalib.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. /*
  2. * arch/powerpc/cpu/ppc4xx/4xx_ibm_ddr2_autocalib.c
  3. * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a
  4. * DDR2 controller (non Denali Core). Those currently are:
  5. *
  6. * 405: 405EX
  7. * 440/460: 440SP/440SPe/460EX/460GT/460SX
  8. *
  9. * (C) Copyright 2008 Applied Micro Circuits Corporation
  10. * Adam Graham <agraham@amcc.com>
  11. *
  12. * (C) Copyright 2007-2008
  13. * Stefan Roese, DENX Software Engineering, sr@denx.de.
  14. *
  15. * COPYRIGHT AMCC CORPORATION 2004
  16. *
  17. * SPDX-License-Identifier: GPL-2.0+
  18. */
  19. /* define DEBUG for debugging output (obviously ;-)) */
  20. #undef DEBUG
  21. #include <common.h>
  22. #include <asm/ppc4xx.h>
  23. #include <asm/io.h>
  24. #include <asm/processor.h>
  25. #include "ecc.h"
  26. #define MAXBXCF 4
  27. #define SDRAM_RXBAS_SHIFT_1M 20
  28. #if defined(CONFIG_SYS_DECREMENT_PATTERNS)
  29. #define NUMMEMTESTS 24
  30. #else
  31. #define NUMMEMTESTS 8
  32. #endif /* CONFIG_SYS_DECREMENT_PATTERNS */
  33. #define NUMLOOPS 1 /* configure as you deem approporiate */
  34. #define NUMMEMWORDS 16
  35. #define SDRAM_RDCC_RDSS_VAL(n) SDRAM_RDCC_RDSS_DECODE(ddr_rdss_opt(n))
  36. /* Private Structure Definitions */
  37. struct autocal_regs {
  38. u32 rffd;
  39. u32 rqfd;
  40. };
  41. struct ddrautocal {
  42. u32 rffd;
  43. u32 rffd_min;
  44. u32 rffd_max;
  45. u32 rffd_size;
  46. u32 rqfd;
  47. u32 rqfd_size;
  48. u32 rdcc;
  49. u32 flags;
  50. };
  51. struct sdram_timing_clks {
  52. u32 wrdtr;
  53. u32 clktr;
  54. u32 rdcc;
  55. u32 flags;
  56. };
  57. struct autocal_clks {
  58. struct sdram_timing_clks clocks;
  59. struct ddrautocal autocal;
  60. };
  61. /*--------------------------------------------------------------------------+
  62. * Prototypes
  63. *--------------------------------------------------------------------------*/
  64. #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
  65. static u32 DQS_calibration_methodA(struct ddrautocal *);
  66. static u32 program_DQS_calibration_methodA(struct ddrautocal *);
  67. #else
  68. static u32 DQS_calibration_methodB(struct ddrautocal *);
  69. static u32 program_DQS_calibration_methodB(struct ddrautocal *);
  70. #endif
  71. static int short_mem_test(u32 *);
  72. /*
  73. * To provide an interface for board specific config values in this common
  74. * DDR setup code, we implement he "weak" default functions here. They return
  75. * the default value back to the caller.
  76. *
  77. * Please see include/configs/yucca.h for an example fora board specific
  78. * implementation.
  79. */
  80. #if !defined(CONFIG_SPD_EEPROM)
  81. u32 __ddr_wrdtr(u32 default_val)
  82. {
  83. return default_val;
  84. }
  85. u32 ddr_wrdtr(u32) __attribute__((weak, alias("__ddr_wrdtr")));
  86. u32 __ddr_clktr(u32 default_val)
  87. {
  88. return default_val;
  89. }
  90. u32 ddr_clktr(u32) __attribute__((weak, alias("__ddr_clktr")));
  91. /*
  92. * Board-specific Platform code can reimplement spd_ddr_init_hang () if needed
  93. */
  94. void __spd_ddr_init_hang(void)
  95. {
  96. hang();
  97. }
  98. void
  99. spd_ddr_init_hang(void) __attribute__((weak, alias("__spd_ddr_init_hang")));
  100. #endif /* defined(CONFIG_SPD_EEPROM) */
  101. struct sdram_timing *__ddr_scan_option(struct sdram_timing *default_val)
  102. {
  103. return default_val;
  104. }
  105. struct sdram_timing *ddr_scan_option(struct sdram_timing *)
  106. __attribute__((weak, alias("__ddr_scan_option")));
  107. u32 __ddr_rdss_opt(u32 default_val)
  108. {
  109. return default_val;
  110. }
  111. u32 ddr_rdss_opt(ulong) __attribute__((weak, alias("__ddr_rdss_opt")));
  112. static u32 *get_membase(int bxcr_num)
  113. {
  114. u32 *membase;
  115. #if defined(SDRAM_R0BAS)
  116. /* BAS from Memory Queue rank reg. */
  117. membase =
  118. (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num)));
  119. #else
  120. {
  121. ulong bxcf;
  122. /* BAS from SDRAM_MBxCF mem rank reg. */
  123. mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
  124. membase = (u32 *)((bxcf & 0xfff80000) << 3);
  125. }
  126. #endif
  127. return membase;
  128. }
  129. static inline void ecc_clear_status_reg(void)
  130. {
  131. mtsdram(SDRAM_ECCES, 0xffffffff);
  132. #if defined(SDRAM_R0BAS)
  133. mtdcr(SDRAM_ERRSTATLL, 0xffffffff);
  134. #endif
  135. }
  136. /*
  137. * Reset and relock memory DLL after SDRAM_CLKTR change
  138. */
  139. static inline void relock_memory_DLL(void)
  140. {
  141. u32 reg;
  142. mtsdram(SDRAM_MCOPT2, SDRAM_MCOPT2_IPTR_EXECUTE);
  143. do {
  144. mfsdram(SDRAM_MCSTAT, reg);
  145. } while (!(reg & SDRAM_MCSTAT_MIC_COMP));
  146. mfsdram(SDRAM_MCOPT2, reg);
  147. mtsdram(SDRAM_MCOPT2, reg | SDRAM_MCOPT2_DCEN_ENABLE);
  148. }
  149. static int ecc_check_status_reg(void)
  150. {
  151. u32 ecc_status;
  152. /*
  153. * Compare suceeded, now check
  154. * if got ecc error. If got an
  155. * ecc error, then don't count
  156. * this as a passing value
  157. */
  158. mfsdram(SDRAM_ECCES, ecc_status);
  159. if (ecc_status != 0x00000000) {
  160. /* clear on error */
  161. ecc_clear_status_reg();
  162. /* ecc check failure */
  163. return 0;
  164. }
  165. ecc_clear_status_reg();
  166. sync();
  167. return 1;
  168. }
  169. /* return 1 if passes, 0 if fail */
  170. static int short_mem_test(u32 *base_address)
  171. {
  172. int i, j, l;
  173. u32 ecc_mode = 0;
  174. ulong test[NUMMEMTESTS][NUMMEMWORDS] = {
  175. /* 0 */ {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
  176. 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
  177. 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF,
  178. 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF},
  179. /* 1 */ {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
  180. 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
  181. 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000,
  182. 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000},
  183. /* 2 */ {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
  184. 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
  185. 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555,
  186. 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555},
  187. /* 3 */ {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
  188. 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
  189. 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA,
  190. 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA},
  191. /* 4 */ {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
  192. 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
  193. 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A,
  194. 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A},
  195. /* 5 */ {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
  196. 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
  197. 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5,
  198. 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5},
  199. /* 6 */ {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
  200. 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
  201. 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA,
  202. 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA},
  203. /* 7 */ {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
  204. 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
  205. 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55,
  206. 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55},
  207. #if defined(CONFIG_SYS_DECREMENT_PATTERNS)
  208. /* 8 */ {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  209. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  210. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  211. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff},
  212. /* 9 */ {0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
  213. 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
  214. 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe,
  215. 0xfffefffe, 0xfffefffe, 0xfffefffe, 0xfffefffe},
  216. /* 10 */{0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
  217. 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
  218. 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd,
  219. 0xfffdfffd, 0xfffdfffd, 0xfffdffff, 0xfffdfffd},
  220. /* 11 */{0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
  221. 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
  222. 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc,
  223. 0xfffcfffc, 0xfffcfffc, 0xfffcfffc, 0xfffcfffc},
  224. /* 12 */{0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
  225. 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
  226. 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb,
  227. 0xfffbfffb, 0xfffffffb, 0xfffffffb, 0xfffffffb},
  228. /* 13 */{0xfffafffa, 0xfffafffa, 0xfffffffa, 0xfffafffa,
  229. 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
  230. 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa,
  231. 0xfffafffa, 0xfffafffa, 0xfffafffa, 0xfffafffa},
  232. /* 14 */{0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
  233. 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
  234. 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9,
  235. 0xfff9fff9, 0xfff9fff9, 0xfff9fff9, 0xfff9fff9},
  236. /* 15 */{0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
  237. 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
  238. 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8,
  239. 0xfff8fff8, 0xfff8fff8, 0xfff8fff8, 0xfff8fff8},
  240. /* 16 */{0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
  241. 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
  242. 0xfff7fff7, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7,
  243. 0xfff7ffff, 0xfff7ffff, 0xfff7fff7, 0xfff7fff7},
  244. /* 17 */{0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
  245. 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
  246. 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7,
  247. 0xfff6fff5, 0xfff6ffff, 0xfff6fff6, 0xfff6fff7},
  248. /* 18 */{0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
  249. 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
  250. 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5,
  251. 0xfff5fff4, 0xfff5ffff, 0xfff5fff5, 0xfff5fff5},
  252. /* 19 */{0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
  253. 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
  254. 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4,
  255. 0xfff4fff3, 0xfff4ffff, 0xfff4fff4, 0xfff4fff4},
  256. /* 20 */{0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
  257. 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
  258. 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3,
  259. 0xfff3fff2, 0xfff3ffff, 0xfff3fff3, 0xfff3fff3},
  260. /* 21 */{0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
  261. 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
  262. 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2,
  263. 0xfff2ffff, 0xfff2ffff, 0xfff2fff2, 0xfff2fff2},
  264. /* 22 */{0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
  265. 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
  266. 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1,
  267. 0xfff1ffff, 0xfff1ffff, 0xfff1fff1, 0xfff1fff1},
  268. /* 23 */{0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
  269. 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
  270. 0xfff0fff0, 0xfff0fff0, 0xfff0fff0, 0xfff0fff0,
  271. 0xfff0fff0, 0xfff0fffe, 0xfff0fff0, 0xfff0fff0},
  272. #endif /* CONFIG_SYS_DECREMENT_PATTERNS */
  273. };
  274. mfsdram(SDRAM_MCOPT1, ecc_mode);
  275. if ((ecc_mode & SDRAM_MCOPT1_MCHK_CHK_REP) ==
  276. SDRAM_MCOPT1_MCHK_CHK_REP) {
  277. ecc_clear_status_reg();
  278. sync();
  279. ecc_mode = 1;
  280. } else {
  281. ecc_mode = 0;
  282. }
  283. /*
  284. * Run the short memory test.
  285. */
  286. for (i = 0; i < NUMMEMTESTS; i++) {
  287. for (j = 0; j < NUMMEMWORDS; j++) {
  288. base_address[j] = test[i][j];
  289. ppcDcbf((ulong)&(base_address[j]));
  290. }
  291. sync();
  292. iobarrier_rw();
  293. for (l = 0; l < NUMLOOPS; l++) {
  294. for (j = 0; j < NUMMEMWORDS; j++) {
  295. if (base_address[j] != test[i][j]) {
  296. ppcDcbf((u32)&(base_address[j]));
  297. return 0;
  298. } else {
  299. if (ecc_mode) {
  300. if (!ecc_check_status_reg())
  301. return 0;
  302. }
  303. }
  304. ppcDcbf((u32)&(base_address[j]));
  305. } /* for (j = 0; j < NUMMEMWORDS; j++) */
  306. sync();
  307. iobarrier_rw();
  308. } /* for (l=0; l<NUMLOOPS; l++) */
  309. }
  310. return 1;
  311. }
  312. #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
  313. /*-----------------------------------------------------------------------------+
  314. | program_DQS_calibration_methodA.
  315. +-----------------------------------------------------------------------------*/
  316. static u32 program_DQS_calibration_methodA(struct ddrautocal *ddrcal)
  317. {
  318. u32 pass_result = 0;
  319. #ifdef DEBUG
  320. ulong temp;
  321. mfsdram(SDRAM_RDCC, temp);
  322. debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
  323. #endif
  324. pass_result = DQS_calibration_methodA(ddrcal);
  325. return pass_result;
  326. }
  327. /*
  328. * DQS_calibration_methodA()
  329. *
  330. * Autocalibration Method A
  331. *
  332. * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
  333. * ARRAY [Entire FDBK Range] FDBK_Valid_Window; initialized to all zeros
  334. * MEMWRITE(addr, expected_data);
  335. * for (i = 0; i < Entire DQS Range; i++) { RQDC.RQFD
  336. * for (j = 0; j < Entire FDBK Range; j++) { RFDC.RFFD
  337. * MEMREAD(addr, actual_data);
  338. * if (actual_data == expected_data) {
  339. * DQS_Valid_Window[i] = 1; RQDC.RQFD
  340. * FDBK_Valid_Window[i][j] = 1; RFDC.RFFD
  341. * }
  342. * }
  343. * }
  344. */
  345. static u32 DQS_calibration_methodA(struct ddrautocal *cal)
  346. {
  347. ulong rfdc_reg;
  348. ulong rffd;
  349. ulong rqdc_reg;
  350. ulong rqfd;
  351. u32 *membase;
  352. ulong bxcf;
  353. int rqfd_average;
  354. int bxcr_num;
  355. int rffd_average;
  356. int pass;
  357. u32 passed = 0;
  358. int in_window;
  359. struct autocal_regs curr_win_min;
  360. struct autocal_regs curr_win_max;
  361. struct autocal_regs best_win_min;
  362. struct autocal_regs best_win_max;
  363. struct autocal_regs loop_win_min;
  364. struct autocal_regs loop_win_max;
  365. #ifdef DEBUG
  366. ulong temp;
  367. #endif
  368. ulong rdcc;
  369. char slash[] = "\\|/-\\|/-";
  370. int loopi = 0;
  371. /* start */
  372. in_window = 0;
  373. memset(&curr_win_min, 0, sizeof(curr_win_min));
  374. memset(&curr_win_max, 0, sizeof(curr_win_max));
  375. memset(&best_win_min, 0, sizeof(best_win_min));
  376. memset(&best_win_max, 0, sizeof(best_win_max));
  377. memset(&loop_win_min, 0, sizeof(loop_win_min));
  378. memset(&loop_win_max, 0, sizeof(loop_win_max));
  379. rdcc = 0;
  380. /*
  381. * Program RDCC register
  382. * Read sample cycle auto-update enable
  383. */
  384. mtsdram(SDRAM_RDCC,
  385. ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
  386. #ifdef DEBUG
  387. mfsdram(SDRAM_RDCC, temp);
  388. debug("<%s>SDRAM_RDCC=0x%x\n", __func__, temp);
  389. mfsdram(SDRAM_RTSR, temp);
  390. debug("<%s>SDRAM_RTSR=0x%x\n", __func__, temp);
  391. mfsdram(SDRAM_FCSR, temp);
  392. debug("<%s>SDRAM_FCSR=0x%x\n", __func__, temp);
  393. #endif
  394. /*
  395. * Program RQDC register
  396. * Internal DQS delay mechanism enable
  397. */
  398. mtsdram(SDRAM_RQDC,
  399. SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x00));
  400. #ifdef DEBUG
  401. mfsdram(SDRAM_RQDC, temp);
  402. debug("<%s>SDRAM_RQDC=0x%x\n", __func__, temp);
  403. #endif
  404. /*
  405. * Program RFDC register
  406. * Set Feedback Fractional Oversample
  407. * Auto-detect read sample cycle enable
  408. */
  409. mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
  410. SDRAM_RFDC_RFOS_ENCODE(0) | SDRAM_RFDC_RFFD_ENCODE(0));
  411. #ifdef DEBUG
  412. mfsdram(SDRAM_RFDC, temp);
  413. debug("<%s>SDRAM_RFDC=0x%x\n", __func__, temp);
  414. #endif
  415. putc(' ');
  416. for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
  417. mfsdram(SDRAM_RQDC, rqdc_reg);
  418. rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
  419. mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
  420. putc('\b');
  421. putc(slash[loopi++ % 8]);
  422. curr_win_min.rffd = 0;
  423. curr_win_max.rffd = 0;
  424. in_window = 0;
  425. for (rffd = 0, pass = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
  426. mfsdram(SDRAM_RFDC, rfdc_reg);
  427. rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
  428. mtsdram(SDRAM_RFDC,
  429. rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
  430. for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
  431. mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
  432. /* Banks enabled */
  433. if (bxcf & SDRAM_BXCF_M_BE_MASK) {
  434. /* Bank is enabled */
  435. membase = get_membase(bxcr_num);
  436. pass = short_mem_test(membase);
  437. } /* if bank enabled */
  438. } /* for bxcr_num */
  439. /* If this value passed update RFFD windows */
  440. if (pass && !in_window) { /* at the start of window */
  441. in_window = 1;
  442. curr_win_min.rffd = curr_win_max.rffd = rffd;
  443. curr_win_min.rqfd = curr_win_max.rqfd = rqfd;
  444. mfsdram(SDRAM_RDCC, rdcc); /*record this value*/
  445. } else if (!pass && in_window) { /* at end of window */
  446. in_window = 0;
  447. } else if (pass && in_window) { /* within the window */
  448. curr_win_max.rffd = rffd;
  449. curr_win_max.rqfd = rqfd;
  450. }
  451. /* else if (!pass && !in_window)
  452. skip - no pass, not currently in a window */
  453. if (in_window) {
  454. if ((curr_win_max.rffd - curr_win_min.rffd) >
  455. (best_win_max.rffd - best_win_min.rffd)) {
  456. best_win_min.rffd = curr_win_min.rffd;
  457. best_win_max.rffd = curr_win_max.rffd;
  458. best_win_min.rqfd = curr_win_min.rqfd;
  459. best_win_max.rqfd = curr_win_max.rqfd;
  460. cal->rdcc = rdcc;
  461. }
  462. passed = 1;
  463. }
  464. } /* RFDC.RFFD */
  465. /*
  466. * save-off the best window results of the RFDC.RFFD
  467. * for this RQDC.RQFD setting
  468. */
  469. /*
  470. * if (just ended RFDC.RFDC loop pass window) >
  471. * (prior RFDC.RFFD loop pass window)
  472. */
  473. if ((best_win_max.rffd - best_win_min.rffd) >
  474. (loop_win_max.rffd - loop_win_min.rffd)) {
  475. loop_win_min.rffd = best_win_min.rffd;
  476. loop_win_max.rffd = best_win_max.rffd;
  477. loop_win_min.rqfd = rqfd;
  478. loop_win_max.rqfd = rqfd;
  479. debug("RQFD.min 0x%08x, RQFD.max 0x%08x, "
  480. "RFFD.min 0x%08x, RFFD.max 0x%08x\n",
  481. loop_win_min.rqfd, loop_win_max.rqfd,
  482. loop_win_min.rffd, loop_win_max.rffd);
  483. }
  484. } /* RQDC.RQFD */
  485. putc('\b');
  486. debug("\n");
  487. if ((loop_win_min.rffd == 0) && (loop_win_max.rffd == 0) &&
  488. (best_win_min.rffd == 0) && (best_win_max.rffd == 0) &&
  489. (best_win_min.rqfd == 0) && (best_win_max.rqfd == 0)) {
  490. passed = 0;
  491. }
  492. /*
  493. * Need to program RQDC before RFDC.
  494. */
  495. debug("<%s> RQFD Min: 0x%x\n", __func__, loop_win_min.rqfd);
  496. debug("<%s> RQFD Max: 0x%x\n", __func__, loop_win_max.rqfd);
  497. rqfd_average = loop_win_max.rqfd;
  498. if (rqfd_average < 0)
  499. rqfd_average = 0;
  500. if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
  501. rqfd_average = SDRAM_RQDC_RQFD_MAX;
  502. debug("<%s> RFFD average: 0x%08x\n", __func__, rqfd_average);
  503. mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
  504. SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
  505. debug("<%s> RFFD Min: 0x%08x\n", __func__, loop_win_min.rffd);
  506. debug("<%s> RFFD Max: 0x%08x\n", __func__, loop_win_max.rffd);
  507. rffd_average = ((loop_win_min.rffd + loop_win_max.rffd) / 2);
  508. if (rffd_average < 0)
  509. rffd_average = 0;
  510. if (rffd_average > SDRAM_RFDC_RFFD_MAX)
  511. rffd_average = SDRAM_RFDC_RFFD_MAX;
  512. debug("<%s> RFFD average: 0x%08x\n", __func__, rffd_average);
  513. mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
  514. /* if something passed, then return the size of the largest window */
  515. if (passed != 0) {
  516. passed = loop_win_max.rffd - loop_win_min.rffd;
  517. cal->rqfd = rqfd_average;
  518. cal->rffd = rffd_average;
  519. cal->rffd_min = loop_win_min.rffd;
  520. cal->rffd_max = loop_win_max.rffd;
  521. }
  522. return (u32)passed;
  523. }
  524. #else /* !defined(CONFIG_PPC4xx_DDR_METHOD_A) */
  525. /*-----------------------------------------------------------------------------+
  526. | program_DQS_calibration_methodB.
  527. +-----------------------------------------------------------------------------*/
  528. static u32 program_DQS_calibration_methodB(struct ddrautocal *ddrcal)
  529. {
  530. u32 pass_result = 0;
  531. #ifdef DEBUG
  532. ulong temp;
  533. #endif
  534. /*
  535. * Program RDCC register
  536. * Read sample cycle auto-update enable
  537. */
  538. mtsdram(SDRAM_RDCC,
  539. ddr_rdss_opt(SDRAM_RDCC_RDSS_T2) | SDRAM_RDCC_RSAE_ENABLE);
  540. #ifdef DEBUG
  541. mfsdram(SDRAM_RDCC, temp);
  542. debug("<%s>SDRAM_RDCC=0x%08x\n", __func__, temp);
  543. #endif
  544. /*
  545. * Program RQDC register
  546. * Internal DQS delay mechanism enable
  547. */
  548. mtsdram(SDRAM_RQDC,
  549. #if defined(CONFIG_DDR_RQDC_START_VAL)
  550. SDRAM_RQDC_RQDE_ENABLE |
  551. SDRAM_RQDC_RQFD_ENCODE(CONFIG_DDR_RQDC_START_VAL));
  552. #else
  553. SDRAM_RQDC_RQDE_ENABLE | SDRAM_RQDC_RQFD_ENCODE(0x38));
  554. #endif
  555. #ifdef DEBUG
  556. mfsdram(SDRAM_RQDC, temp);
  557. debug("<%s>SDRAM_RQDC=0x%08x\n", __func__, temp);
  558. #endif
  559. /*
  560. * Program RFDC register
  561. * Set Feedback Fractional Oversample
  562. * Auto-detect read sample cycle enable
  563. */
  564. mtsdram(SDRAM_RFDC, SDRAM_RFDC_ARSE_ENABLE |
  565. SDRAM_RFDC_RFOS_ENCODE(0) |
  566. SDRAM_RFDC_RFFD_ENCODE(0));
  567. #ifdef DEBUG
  568. mfsdram(SDRAM_RFDC, temp);
  569. debug("<%s>SDRAM_RFDC=0x%08x\n", __func__, temp);
  570. #endif
  571. pass_result = DQS_calibration_methodB(ddrcal);
  572. return pass_result;
  573. }
  574. /*
  575. * DQS_calibration_methodB()
  576. *
  577. * Autocalibration Method B
  578. *
  579. * ARRAY [Entire DQS Range] DQS_Valid_Window ; initialized to all zeros
  580. * ARRAY [Entire Feedback Range] FDBK_Valid_Window; initialized to all zeros
  581. * MEMWRITE(addr, expected_data);
  582. * Initialialize the DQS delay to 80 degrees (MCIF0_RRQDC[RQFD]=0x38).
  583. *
  584. * for (j = 0; j < Entire Feedback Range; j++) {
  585. * MEMREAD(addr, actual_data);
  586. * if (actual_data == expected_data) {
  587. * FDBK_Valid_Window[j] = 1;
  588. * }
  589. * }
  590. *
  591. * Set MCIF0_RFDC[RFFD] to the middle of the FDBK_Valid_Window.
  592. *
  593. * for (i = 0; i < Entire DQS Range; i++) {
  594. * MEMREAD(addr, actual_data);
  595. * if (actual_data == expected_data) {
  596. * DQS_Valid_Window[i] = 1;
  597. * }
  598. * }
  599. *
  600. * Set MCIF0_RRQDC[RQFD] to the middle of the DQS_Valid_Window.
  601. */
  602. /*-----------------------------------------------------------------------------+
  603. | DQS_calibration_methodB.
  604. +-----------------------------------------------------------------------------*/
  605. static u32 DQS_calibration_methodB(struct ddrautocal *cal)
  606. {
  607. ulong rfdc_reg;
  608. #ifndef CONFIG_DDR_RFDC_FIXED
  609. ulong rffd;
  610. #endif
  611. ulong rqdc_reg;
  612. ulong rqfd;
  613. ulong rdcc;
  614. u32 *membase;
  615. ulong bxcf;
  616. int rqfd_average;
  617. int bxcr_num;
  618. int rffd_average;
  619. int pass;
  620. uint passed = 0;
  621. int in_window;
  622. u32 curr_win_min, curr_win_max;
  623. u32 best_win_min, best_win_max;
  624. u32 size = 0;
  625. /*------------------------------------------------------------------
  626. | Test to determine the best read clock delay tuning bits.
  627. |
  628. | Before the DDR controller can be used, the read clock delay needs to
  629. | be set. This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD].
  630. | This value cannot be hardcoded into the program because it changes
  631. | depending on the board's setup and environment.
  632. | To do this, all delay values are tested to see if they
  633. | work or not. By doing this, you get groups of fails with groups of
  634. | passing values. The idea is to find the start and end of a passing
  635. | window and take the center of it to use as the read clock delay.
  636. |
  637. | A failure has to be seen first so that when we hit a pass, we know
  638. | that it is truely the start of the window. If we get passing values
  639. | to start off with, we don't know if we are at the start of the window
  640. |
  641. | The code assumes that a failure will always be found.
  642. | If a failure is not found, there is no easy way to get the middle
  643. | of the passing window. I guess we can pretty much pick any value
  644. | but some values will be better than others. Since the lowest speed
  645. | we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed),
  646. | from experimentation it is safe to say you will always have a failure
  647. +-----------------------------------------------------------------*/
  648. debug("\n\n");
  649. #if defined(CONFIG_DDR_RFDC_FIXED)
  650. mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED);
  651. size = 512;
  652. rffd_average = CONFIG_DDR_RFDC_FIXED & SDRAM_RFDC_RFFD_MASK;
  653. mfsdram(SDRAM_RDCC, rdcc); /* record this value */
  654. cal->rdcc = rdcc;
  655. #else /* CONFIG_DDR_RFDC_FIXED */
  656. in_window = 0;
  657. rdcc = 0;
  658. curr_win_min = curr_win_max = 0;
  659. best_win_min = best_win_max = 0;
  660. for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) {
  661. mfsdram(SDRAM_RFDC, rfdc_reg);
  662. rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
  663. mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd));
  664. pass = 1;
  665. for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
  666. mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
  667. /* Banks enabled */
  668. if (bxcf & SDRAM_BXCF_M_BE_MASK) {
  669. /* Bank is enabled */
  670. membase = get_membase(bxcr_num);
  671. pass &= short_mem_test(membase);
  672. } /* if bank enabled */
  673. } /* for bxcf_num */
  674. /* If this value passed */
  675. if (pass && !in_window) { /* start of passing window */
  676. in_window = 1;
  677. curr_win_min = curr_win_max = rffd;
  678. mfsdram(SDRAM_RDCC, rdcc); /* record this value */
  679. } else if (!pass && in_window) { /* end passing window */
  680. in_window = 0;
  681. } else if (pass && in_window) { /* within the passing window */
  682. curr_win_max = rffd;
  683. }
  684. if (in_window) {
  685. if ((curr_win_max - curr_win_min) >
  686. (best_win_max - best_win_min)) {
  687. best_win_min = curr_win_min;
  688. best_win_max = curr_win_max;
  689. cal->rdcc = rdcc;
  690. }
  691. passed = 1;
  692. }
  693. } /* for rffd */
  694. if ((best_win_min == 0) && (best_win_max == 0))
  695. passed = 0;
  696. else
  697. size = best_win_max - best_win_min;
  698. debug("RFFD Min: 0x%x\n", best_win_min);
  699. debug("RFFD Max: 0x%x\n", best_win_max);
  700. rffd_average = ((best_win_min + best_win_max) / 2);
  701. cal->rffd_min = best_win_min;
  702. cal->rffd_max = best_win_max;
  703. if (rffd_average < 0)
  704. rffd_average = 0;
  705. if (rffd_average > SDRAM_RFDC_RFFD_MAX)
  706. rffd_average = SDRAM_RFDC_RFFD_MAX;
  707. mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average));
  708. #endif /* CONFIG_DDR_RFDC_FIXED */
  709. in_window = 0;
  710. curr_win_min = curr_win_max = 0;
  711. best_win_min = best_win_max = 0;
  712. for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) {
  713. mfsdram(SDRAM_RQDC, rqdc_reg);
  714. rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
  715. mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd));
  716. pass = 1;
  717. for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) {
  718. mfsdram(SDRAM_MB0CF + (bxcr_num<<2), bxcf);
  719. /* Banks enabled */
  720. if (bxcf & SDRAM_BXCF_M_BE_MASK) {
  721. /* Bank is enabled */
  722. membase = get_membase(bxcr_num);
  723. pass &= short_mem_test(membase);
  724. } /* if bank enabled */
  725. } /* for bxcf_num */
  726. /* If this value passed */
  727. if (pass && !in_window) {
  728. in_window = 1;
  729. curr_win_min = curr_win_max = rqfd;
  730. } else if (!pass && in_window) {
  731. in_window = 0;
  732. } else if (pass && in_window) {
  733. curr_win_max = rqfd;
  734. }
  735. if (in_window) {
  736. if ((curr_win_max - curr_win_min) >
  737. (best_win_max - best_win_min)) {
  738. best_win_min = curr_win_min;
  739. best_win_max = curr_win_max;
  740. }
  741. passed = 1;
  742. }
  743. } /* for rqfd */
  744. if ((best_win_min == 0) && (best_win_max == 0))
  745. passed = 0;
  746. debug("RQFD Min: 0x%x\n", best_win_min);
  747. debug("RQFD Max: 0x%x\n", best_win_max);
  748. rqfd_average = ((best_win_min + best_win_max) / 2);
  749. if (rqfd_average < 0)
  750. rqfd_average = 0;
  751. if (rqfd_average > SDRAM_RQDC_RQFD_MAX)
  752. rqfd_average = SDRAM_RQDC_RQFD_MAX;
  753. mtsdram(SDRAM_RQDC, (rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) |
  754. SDRAM_RQDC_RQFD_ENCODE(rqfd_average));
  755. mfsdram(SDRAM_RQDC, rqdc_reg);
  756. mfsdram(SDRAM_RFDC, rfdc_reg);
  757. /*
  758. * Need to program RQDC before RFDC. The value is read above.
  759. * That is the reason why auto cal not work.
  760. * See, comments below.
  761. */
  762. mtsdram(SDRAM_RQDC, rqdc_reg);
  763. mtsdram(SDRAM_RFDC, rfdc_reg);
  764. debug("RQDC: 0x%08lX\n", rqdc_reg);
  765. debug("RFDC: 0x%08lX\n", rfdc_reg);
  766. /* if something passed, then return the size of the largest window */
  767. if (passed != 0) {
  768. passed = size;
  769. cal->rqfd = rqfd_average;
  770. cal->rffd = rffd_average;
  771. }
  772. return (uint)passed;
  773. }
  774. #endif /* defined(CONFIG_PPC4xx_DDR_METHOD_A) */
  775. /*
  776. * Default table for DDR auto-calibration of all
  777. * possible WRDTR and CLKTR values.
  778. * Table format is:
  779. * {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]}
  780. *
  781. * Table is terminated with {-1, -1} value pair.
  782. *
  783. * Board vendors can specify their own board specific subset of
  784. * known working {SDRAM_WRDTR.[WDTR], SDRAM_CLKTR.[CKTR]} value
  785. * pairs via a board defined ddr_scan_option() function.
  786. */
  787. static struct sdram_timing full_scan_options[] = {
  788. {0, 0}, {0, 1}, {0, 2}, {0, 3},
  789. {1, 0}, {1, 1}, {1, 2}, {1, 3},
  790. {2, 0}, {2, 1}, {2, 2}, {2, 3},
  791. {3, 0}, {3, 1}, {3, 2}, {3, 3},
  792. {4, 0}, {4, 1}, {4, 2}, {4, 3},
  793. {5, 0}, {5, 1}, {5, 2}, {5, 3},
  794. {6, 0}, {6, 1}, {6, 2}, {6, 3},
  795. {-1, -1}
  796. };
  797. /*---------------------------------------------------------------------------+
  798. | DQS_calibration.
  799. +----------------------------------------------------------------------------*/
  800. u32 DQS_autocalibration(void)
  801. {
  802. u32 wdtr;
  803. u32 clkp;
  804. u32 result = 0;
  805. u32 best_result = 0;
  806. u32 best_rdcc;
  807. struct ddrautocal ddrcal;
  808. struct autocal_clks tcal;
  809. ulong rfdc_reg;
  810. ulong rqdc_reg;
  811. u32 val;
  812. int verbose_lvl = 0;
  813. char *str;
  814. char slash[] = "\\|/-\\|/-";
  815. int loopi = 0;
  816. struct sdram_timing *scan_list;
  817. #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
  818. int i;
  819. char tmp[64]; /* long enough for environment variables */
  820. #endif
  821. memset(&tcal, 0, sizeof(tcal));
  822. scan_list = ddr_scan_option(full_scan_options);
  823. mfsdram(SDRAM_MCOPT1, val);
  824. if ((val & SDRAM_MCOPT1_MCHK_CHK_REP) == SDRAM_MCOPT1_MCHK_CHK_REP)
  825. str = "ECC Auto calibration -";
  826. else
  827. str = "Auto calibration -";
  828. puts(str);
  829. #if defined(DEBUG_PPC4xx_DDR_AUTOCALIBRATION)
  830. i = getenv_f("autocalib", tmp, sizeof(tmp));
  831. if (i < 0)
  832. strcpy(tmp, CONFIG_AUTOCALIB);
  833. if (strcmp(tmp, "final") == 0) {
  834. /* display the final autocalibration results only */
  835. verbose_lvl = 1;
  836. } else if (strcmp(tmp, "loop") == 0) {
  837. /* display summary autocalibration info per iteration */
  838. verbose_lvl = 2;
  839. } else if (strcmp(tmp, "display") == 0) {
  840. /* display full debug autocalibration window info. */
  841. verbose_lvl = 3;
  842. }
  843. #endif /* (DEBUG_PPC4xx_DDR_AUTOCALIBRATION) */
  844. best_rdcc = (SDRAM_RDCC_RDSS_T4 >> 30);
  845. while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) {
  846. wdtr = scan_list->wrdtr;
  847. clkp = scan_list->clktr;
  848. mfsdram(SDRAM_WRDTR, val);
  849. val &= ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK);
  850. mtsdram(SDRAM_WRDTR, (val |
  851. ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC | (wdtr << 25))));
  852. mtsdram(SDRAM_CLKTR, clkp << 30);
  853. relock_memory_DLL();
  854. putc('\b');
  855. putc(slash[loopi++ % 8]);
  856. #ifdef DEBUG
  857. debug("\n");
  858. debug("*** --------------\n");
  859. mfsdram(SDRAM_WRDTR, val);
  860. debug("*** SDRAM_WRDTR set to 0x%08x\n", val);
  861. mfsdram(SDRAM_CLKTR, val);
  862. debug("*** SDRAM_CLKTR set to 0x%08x\n", val);
  863. #endif
  864. debug("\n");
  865. if (verbose_lvl > 2) {
  866. printf("*** SDRAM_WRDTR (wdtr) set to %d\n", wdtr);
  867. printf("*** SDRAM_CLKTR (clkp) set to %d\n", clkp);
  868. }
  869. memset(&ddrcal, 0, sizeof(ddrcal));
  870. /*
  871. * DQS calibration.
  872. */
  873. /*
  874. * program_DQS_calibration_method[A|B]() returns 0 if no
  875. * passing RFDC.[RFFD] window is found or returns the size
  876. * of the best passing window; in the case of a found passing
  877. * window, the ddrcal will contain the values of the best
  878. * window RQDC.[RQFD] and RFDC.[RFFD].
  879. */
  880. /*
  881. * Call PPC4xx SDRAM DDR autocalibration methodA or methodB.
  882. * Default is methodB.
  883. * Defined the autocalibration method in the board specific
  884. * header file.
  885. * Please see include/configs/kilauea.h for an example for
  886. * a board specific implementation.
  887. */
  888. #if defined(CONFIG_PPC4xx_DDR_METHOD_A)
  889. result = program_DQS_calibration_methodA(&ddrcal);
  890. #else
  891. result = program_DQS_calibration_methodB(&ddrcal);
  892. #endif
  893. sync();
  894. /*
  895. * Clear potential errors resulting from auto-calibration.
  896. * If not done, then we could get an interrupt later on when
  897. * exceptions are enabled.
  898. */
  899. set_mcsr(get_mcsr());
  900. val = ddrcal.rdcc; /* RDCC from the best passing window */
  901. udelay(100);
  902. if (verbose_lvl > 1) {
  903. char *tstr;
  904. switch ((val >> 30)) {
  905. case 0:
  906. if (result != 0)
  907. tstr = "T1";
  908. else
  909. tstr = "N/A";
  910. break;
  911. case 1:
  912. tstr = "T2";
  913. break;
  914. case 2:
  915. tstr = "T3";
  916. break;
  917. case 3:
  918. tstr = "T4";
  919. break;
  920. default:
  921. tstr = "unknown";
  922. break;
  923. }
  924. printf("** WRDTR(%d) CLKTR(%d), Wind (%d), best (%d), "
  925. "max-min(0x%04x)(0x%04x), RDCC: %s\n",
  926. wdtr, clkp, result, best_result,
  927. ddrcal.rffd_min, ddrcal.rffd_max, tstr);
  928. }
  929. /*
  930. * The DQS calibration "result" is either "0"
  931. * if no passing window was found, or is the
  932. * size of the RFFD passing window.
  933. */
  934. /*
  935. * want the lowest Read Sample Cycle Select
  936. */
  937. val = SDRAM_RDCC_RDSS_DECODE(val);
  938. debug("*** (%d) (%d) current_rdcc, best_rdcc\n",
  939. val, best_rdcc);
  940. if ((result != 0) &&
  941. (val >= SDRAM_RDCC_RDSS_VAL(SDRAM_RDCC_RDSS_T2))) {
  942. if (((result == best_result) && (val < best_rdcc)) ||
  943. ((result > best_result) && (val <= best_rdcc))) {
  944. tcal.autocal.flags = 1;
  945. debug("*** (%d)(%d) result passed window "
  946. "size: 0x%08x, rqfd = 0x%08x, "
  947. "rffd = 0x%08x, rdcc = 0x%08x\n",
  948. wdtr, clkp, result, ddrcal.rqfd,
  949. ddrcal.rffd, ddrcal.rdcc);
  950. /*
  951. * Save the SDRAM_WRDTR and SDRAM_CLKTR
  952. * settings for the largest returned
  953. * RFFD passing window size.
  954. */
  955. best_rdcc = val;
  956. tcal.clocks.wrdtr = wdtr;
  957. tcal.clocks.clktr = clkp;
  958. tcal.clocks.rdcc = SDRAM_RDCC_RDSS_ENCODE(val);
  959. tcal.autocal.rqfd = ddrcal.rqfd;
  960. tcal.autocal.rffd = ddrcal.rffd;
  961. best_result = result;
  962. if (verbose_lvl > 2) {
  963. printf("** (%d)(%d) "
  964. "best result: 0x%04x\n",
  965. wdtr, clkp,
  966. best_result);
  967. printf("** (%d)(%d) "
  968. "best WRDTR: 0x%04x\n",
  969. wdtr, clkp,
  970. tcal.clocks.wrdtr);
  971. printf("** (%d)(%d) "
  972. "best CLKTR: 0x%04x\n",
  973. wdtr, clkp,
  974. tcal.clocks.clktr);
  975. printf("** (%d)(%d) "
  976. "best RQDC: 0x%04x\n",
  977. wdtr, clkp,
  978. tcal.autocal.rqfd);
  979. printf("** (%d)(%d) "
  980. "best RFDC: 0x%04x\n",
  981. wdtr, clkp,
  982. tcal.autocal.rffd);
  983. printf("** (%d)(%d) "
  984. "best RDCC: 0x%08x\n",
  985. wdtr, clkp,
  986. (u32)tcal.clocks.rdcc);
  987. mfsdram(SDRAM_RTSR, val);
  988. printf("** (%d)(%d) best "
  989. "loop RTSR: 0x%08x\n",
  990. wdtr, clkp, val);
  991. mfsdram(SDRAM_FCSR, val);
  992. printf("** (%d)(%d) best "
  993. "loop FCSR: 0x%08x\n",
  994. wdtr, clkp, val);
  995. }
  996. }
  997. } /* if ((result != 0) && (val >= (ddr_rdss_opt()))) */
  998. scan_list++;
  999. } /* while ((scan_list->wrdtr != -1) && (scan_list->clktr != -1)) */
  1000. if (tcal.autocal.flags == 1) {
  1001. if (verbose_lvl > 0) {
  1002. printf("*** --------------\n");
  1003. printf("*** best_result window size: %d\n",
  1004. best_result);
  1005. printf("*** best_result WRDTR: 0x%04x\n",
  1006. tcal.clocks.wrdtr);
  1007. printf("*** best_result CLKTR: 0x%04x\n",
  1008. tcal.clocks.clktr);
  1009. printf("*** best_result RQFD: 0x%04x\n",
  1010. tcal.autocal.rqfd);
  1011. printf("*** best_result RFFD: 0x%04x\n",
  1012. tcal.autocal.rffd);
  1013. printf("*** best_result RDCC: 0x%04x\n",
  1014. tcal.clocks.rdcc);
  1015. printf("*** --------------\n");
  1016. printf("\n");
  1017. }
  1018. /*
  1019. * if got best passing result window, then lock in the
  1020. * best CLKTR, WRDTR, RQFD, and RFFD values
  1021. */
  1022. mfsdram(SDRAM_WRDTR, val);
  1023. mtsdram(SDRAM_WRDTR, (val &
  1024. ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) |
  1025. ddr_wrdtr(SDRAM_WRDTR_LLWP_1_CYC |
  1026. (tcal.clocks.wrdtr << 25)));
  1027. mtsdram(SDRAM_CLKTR, tcal.clocks.clktr << 30);
  1028. relock_memory_DLL();
  1029. mfsdram(SDRAM_RQDC, rqdc_reg);
  1030. rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK);
  1031. mtsdram(SDRAM_RQDC, rqdc_reg |
  1032. SDRAM_RQDC_RQFD_ENCODE(tcal.autocal.rqfd));
  1033. mfsdram(SDRAM_RQDC, rqdc_reg);
  1034. debug("*** best_result: read value SDRAM_RQDC 0x%08lx\n",
  1035. rqdc_reg);
  1036. #if defined(CONFIG_DDR_RFDC_FIXED)
  1037. mtsdram(SDRAM_RFDC, CONFIG_DDR_RFDC_FIXED);
  1038. #else /* CONFIG_DDR_RFDC_FIXED */
  1039. mfsdram(SDRAM_RFDC, rfdc_reg);
  1040. rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK);
  1041. mtsdram(SDRAM_RFDC, rfdc_reg |
  1042. SDRAM_RFDC_RFFD_ENCODE(tcal.autocal.rffd));
  1043. #endif /* CONFIG_DDR_RFDC_FIXED */
  1044. mfsdram(SDRAM_RFDC, rfdc_reg);
  1045. debug("*** best_result: read value SDRAM_RFDC 0x%08lx\n",
  1046. rfdc_reg);
  1047. mfsdram(SDRAM_RDCC, val);
  1048. debug("*** SDRAM_RDCC 0x%08x\n", val);
  1049. } else {
  1050. /*
  1051. * no valid windows were found
  1052. */
  1053. printf("DQS memory calibration window can not be determined, "
  1054. "terminating u-boot.\n");
  1055. ppc4xx_ibm_ddr2_register_dump();
  1056. spd_ddr_init_hang();
  1057. }
  1058. blank_string(strlen(str));
  1059. return 0;
  1060. }