mrc_util.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. /*
  2. * Copyright (C) 2013, Intel Corporation
  3. * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
  4. *
  5. * Ported from Intel released Quark UEFI BIOS
  6. * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
  7. *
  8. * SPDX-License-Identifier: Intel
  9. */
  10. #include <common.h>
  11. #include <asm/arch/device.h>
  12. #include <asm/arch/mrc.h>
  13. #include <asm/arch/msg_port.h>
  14. #include "mrc_util.h"
  15. #include "hte.h"
  16. #include "smc.h"
  17. static const uint8_t vref_codes[64] = {
  18. /* lowest to highest */
  19. 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
  20. 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
  21. 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
  22. 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
  23. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  24. 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  25. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  26. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
  27. };
  28. void mrc_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
  29. {
  30. msg_port_write(unit, addr,
  31. (msg_port_read(unit, addr) & ~(mask)) |
  32. ((data) & (mask)));
  33. }
  34. void mrc_alt_write_mask(u32 unit, u32 addr, u32 data, u32 mask)
  35. {
  36. msg_port_alt_write(unit, addr,
  37. (msg_port_alt_read(unit, addr) & ~(mask)) |
  38. ((data) & (mask)));
  39. }
  40. void mrc_post_code(uint8_t major, uint8_t minor)
  41. {
  42. /* send message to UART */
  43. DPF(D_INFO, "POST: 0x%01x%02x\n", major, minor);
  44. /* error check */
  45. if (major == 0xee)
  46. hang();
  47. }
  48. /* Delay number of nanoseconds */
  49. void delay_n(uint32_t ns)
  50. {
  51. /* 1000 MHz clock has 1ns period --> no conversion required */
  52. uint64_t final_tsc = rdtsc();
  53. final_tsc += ((get_tbclk_mhz() * ns) / 1000);
  54. while (rdtsc() < final_tsc)
  55. ;
  56. }
  57. /* Delay number of microseconds */
  58. void delay_u(uint32_t ms)
  59. {
  60. /* 64-bit math is not an option, just use loops */
  61. while (ms--)
  62. delay_n(1000);
  63. }
  64. /* Select Memory Manager as the source for PRI interface */
  65. void select_mem_mgr(void)
  66. {
  67. u32 dco;
  68. ENTERFN();
  69. dco = msg_port_read(MEM_CTLR, DCO);
  70. dco &= ~DCO_PMICTL;
  71. msg_port_write(MEM_CTLR, DCO, dco);
  72. LEAVEFN();
  73. }
  74. /* Select HTE as the source for PRI interface */
  75. void select_hte(void)
  76. {
  77. u32 dco;
  78. ENTERFN();
  79. dco = msg_port_read(MEM_CTLR, DCO);
  80. dco |= DCO_PMICTL;
  81. msg_port_write(MEM_CTLR, DCO, dco);
  82. LEAVEFN();
  83. }
  84. /*
  85. * Send DRAM command
  86. * data should be formated using DCMD_Xxxx macro or emrsXCommand structure
  87. */
  88. void dram_init_command(uint32_t data)
  89. {
  90. pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_DATA_REG, data);
  91. pci_write_config_dword(QUARK_HOST_BRIDGE, MSG_CTRL_EXT_REG, 0);
  92. msg_port_setup(MSG_OP_DRAM_INIT, MEM_CTLR, 0);
  93. DPF(D_REGWR, "WR32 %03X %08X %08X\n", MEM_CTLR, 0, data);
  94. }
  95. /* Send DRAM wake command using special MCU side-band WAKE opcode */
  96. void dram_wake_command(void)
  97. {
  98. ENTERFN();
  99. msg_port_setup(MSG_OP_DRAM_WAKE, MEM_CTLR, 0);
  100. LEAVEFN();
  101. }
  102. void training_message(uint8_t channel, uint8_t rank, uint8_t byte_lane)
  103. {
  104. /* send message to UART */
  105. DPF(D_INFO, "CH%01X RK%01X BL%01X\n", channel, rank, byte_lane);
  106. }
  107. /*
  108. * This function will program the RCVEN delays
  109. *
  110. * (currently doesn't comprehend rank)
  111. */
  112. void set_rcvn(uint8_t channel, uint8_t rank,
  113. uint8_t byte_lane, uint32_t pi_count)
  114. {
  115. uint32_t reg;
  116. uint32_t msk;
  117. uint32_t temp;
  118. ENTERFN();
  119. DPF(D_TRN, "Rcvn ch%d rnk%d ln%d : pi=%03X\n",
  120. channel, rank, byte_lane, pi_count);
  121. /*
  122. * RDPTR (1/2 MCLK, 64 PIs)
  123. * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
  124. * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
  125. */
  126. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  127. channel * DDRIODQ_CH_OFFSET;
  128. msk = (byte_lane & 1) ? 0xf00000 : 0xf00;
  129. temp = (byte_lane & 1) ? (pi_count / HALF_CLK) << 20 :
  130. (pi_count / HALF_CLK) << 8;
  131. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  132. /* Adjust PI_COUNT */
  133. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  134. /*
  135. * PI (1/64 MCLK, 1 PIs)
  136. * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
  137. * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
  138. */
  139. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  140. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  141. channel * DDRIODQ_CH_OFFSET);
  142. msk = 0x3f000000;
  143. temp = pi_count << 24;
  144. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  145. /*
  146. * DEADBAND
  147. * BL0/1 -> B01DBCTL1[08/11] (+1 select)
  148. * BL0/1 -> B01DBCTL1[02/05] (enable)
  149. */
  150. reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  151. channel * DDRIODQ_CH_OFFSET;
  152. msk = 0x00;
  153. temp = 0x00;
  154. /* enable */
  155. msk |= (byte_lane & 1) ? (1 << 5) : (1 << 2);
  156. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  157. temp |= msk;
  158. /* select */
  159. msk |= (byte_lane & 1) ? (1 << 11) : (1 << 8);
  160. if (pi_count < EARLY_DB)
  161. temp |= msk;
  162. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  163. /* error check */
  164. if (pi_count > 0x3f) {
  165. training_message(channel, rank, byte_lane);
  166. mrc_post_code(0xee, 0xe0);
  167. }
  168. LEAVEFN();
  169. }
  170. /*
  171. * This function will return the current RCVEN delay on the given
  172. * channel, rank, byte_lane as an absolute PI count.
  173. *
  174. * (currently doesn't comprehend rank)
  175. */
  176. uint32_t get_rcvn(uint8_t channel, uint8_t rank, uint8_t byte_lane)
  177. {
  178. uint32_t reg;
  179. uint32_t temp;
  180. uint32_t pi_count;
  181. ENTERFN();
  182. /*
  183. * RDPTR (1/2 MCLK, 64 PIs)
  184. * BL0 -> B01PTRCTL0[11:08] (0x0-0xF)
  185. * BL1 -> B01PTRCTL0[23:20] (0x0-0xF)
  186. */
  187. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  188. channel * DDRIODQ_CH_OFFSET;
  189. temp = msg_port_alt_read(DDRPHY, reg);
  190. temp >>= (byte_lane & 1) ? 20 : 8;
  191. temp &= 0xf;
  192. /* Adjust PI_COUNT */
  193. pi_count = temp * HALF_CLK;
  194. /*
  195. * PI (1/64 MCLK, 1 PIs)
  196. * BL0 -> B0DLLPICODER0[29:24] (0x00-0x3F)
  197. * BL1 -> B1DLLPICODER0[29:24] (0x00-0x3F)
  198. */
  199. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  200. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  201. channel * DDRIODQ_CH_OFFSET);
  202. temp = msg_port_alt_read(DDRPHY, reg);
  203. temp >>= 24;
  204. temp &= 0x3f;
  205. /* Adjust PI_COUNT */
  206. pi_count += temp;
  207. LEAVEFN();
  208. return pi_count;
  209. }
  210. /*
  211. * This function will program the RDQS delays based on an absolute
  212. * amount of PIs.
  213. *
  214. * (currently doesn't comprehend rank)
  215. */
  216. void set_rdqs(uint8_t channel, uint8_t rank,
  217. uint8_t byte_lane, uint32_t pi_count)
  218. {
  219. uint32_t reg;
  220. uint32_t msk;
  221. uint32_t temp;
  222. ENTERFN();
  223. DPF(D_TRN, "Rdqs ch%d rnk%d ln%d : pi=%03X\n",
  224. channel, rank, byte_lane, pi_count);
  225. /*
  226. * PI (1/128 MCLK)
  227. * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
  228. * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
  229. */
  230. reg = (byte_lane & 1) ? B1RXDQSPICODE : B0RXDQSPICODE;
  231. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  232. channel * DDRIODQ_CH_OFFSET);
  233. msk = 0x7f;
  234. temp = pi_count << 0;
  235. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  236. /* error check (shouldn't go above 0x3F) */
  237. if (pi_count > 0x47) {
  238. training_message(channel, rank, byte_lane);
  239. mrc_post_code(0xee, 0xe1);
  240. }
  241. LEAVEFN();
  242. }
  243. /*
  244. * This function will return the current RDQS delay on the given
  245. * channel, rank, byte_lane as an absolute PI count.
  246. *
  247. * (currently doesn't comprehend rank)
  248. */
  249. uint32_t get_rdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
  250. {
  251. uint32_t reg;
  252. uint32_t temp;
  253. uint32_t pi_count;
  254. ENTERFN();
  255. /*
  256. * PI (1/128 MCLK)
  257. * BL0 -> B0RXDQSPICODE[06:00] (0x00-0x47)
  258. * BL1 -> B1RXDQSPICODE[06:00] (0x00-0x47)
  259. */
  260. reg = (byte_lane & 1) ? B1RXDQSPICODE : B0RXDQSPICODE;
  261. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  262. channel * DDRIODQ_CH_OFFSET);
  263. temp = msg_port_alt_read(DDRPHY, reg);
  264. /* Adjust PI_COUNT */
  265. pi_count = temp & 0x7f;
  266. LEAVEFN();
  267. return pi_count;
  268. }
  269. /*
  270. * This function will program the WDQS delays based on an absolute
  271. * amount of PIs.
  272. *
  273. * (currently doesn't comprehend rank)
  274. */
  275. void set_wdqs(uint8_t channel, uint8_t rank,
  276. uint8_t byte_lane, uint32_t pi_count)
  277. {
  278. uint32_t reg;
  279. uint32_t msk;
  280. uint32_t temp;
  281. ENTERFN();
  282. DPF(D_TRN, "Wdqs ch%d rnk%d ln%d : pi=%03X\n",
  283. channel, rank, byte_lane, pi_count);
  284. /*
  285. * RDPTR (1/2 MCLK, 64 PIs)
  286. * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
  287. * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
  288. */
  289. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  290. channel * DDRIODQ_CH_OFFSET;
  291. msk = (byte_lane & 1) ? 0xf0000 : 0xf0;
  292. temp = pi_count / HALF_CLK;
  293. temp <<= (byte_lane & 1) ? 16 : 4;
  294. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  295. /* Adjust PI_COUNT */
  296. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  297. /*
  298. * PI (1/64 MCLK, 1 PIs)
  299. * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
  300. * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
  301. */
  302. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  303. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  304. channel * DDRIODQ_CH_OFFSET);
  305. msk = 0x3f0000;
  306. temp = pi_count << 16;
  307. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  308. /*
  309. * DEADBAND
  310. * BL0/1 -> B01DBCTL1[07/10] (+1 select)
  311. * BL0/1 -> B01DBCTL1[01/04] (enable)
  312. */
  313. reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  314. channel * DDRIODQ_CH_OFFSET;
  315. msk = 0x00;
  316. temp = 0x00;
  317. /* enable */
  318. msk |= (byte_lane & 1) ? (1 << 4) : (1 << 1);
  319. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  320. temp |= msk;
  321. /* select */
  322. msk |= (byte_lane & 1) ? (1 << 10) : (1 << 7);
  323. if (pi_count < EARLY_DB)
  324. temp |= msk;
  325. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  326. /* error check */
  327. if (pi_count > 0x3f) {
  328. training_message(channel, rank, byte_lane);
  329. mrc_post_code(0xee, 0xe2);
  330. }
  331. LEAVEFN();
  332. }
  333. /*
  334. * This function will return the amount of WDQS delay on the given
  335. * channel, rank, byte_lane as an absolute PI count.
  336. *
  337. * (currently doesn't comprehend rank)
  338. */
  339. uint32_t get_wdqs(uint8_t channel, uint8_t rank, uint8_t byte_lane)
  340. {
  341. uint32_t reg;
  342. uint32_t temp;
  343. uint32_t pi_count;
  344. ENTERFN();
  345. /*
  346. * RDPTR (1/2 MCLK, 64 PIs)
  347. * BL0 -> B01PTRCTL0[07:04] (0x0-0xF)
  348. * BL1 -> B01PTRCTL0[19:16] (0x0-0xF)
  349. */
  350. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  351. channel * DDRIODQ_CH_OFFSET;
  352. temp = msg_port_alt_read(DDRPHY, reg);
  353. temp >>= (byte_lane & 1) ? 16 : 4;
  354. temp &= 0xf;
  355. /* Adjust PI_COUNT */
  356. pi_count = (temp * HALF_CLK);
  357. /*
  358. * PI (1/64 MCLK, 1 PIs)
  359. * BL0 -> B0DLLPICODER0[21:16] (0x00-0x3F)
  360. * BL1 -> B1DLLPICODER0[21:16] (0x00-0x3F)
  361. */
  362. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  363. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  364. channel * DDRIODQ_CH_OFFSET);
  365. temp = msg_port_alt_read(DDRPHY, reg);
  366. temp >>= 16;
  367. temp &= 0x3f;
  368. /* Adjust PI_COUNT */
  369. pi_count += temp;
  370. LEAVEFN();
  371. return pi_count;
  372. }
  373. /*
  374. * This function will program the WDQ delays based on an absolute
  375. * number of PIs.
  376. *
  377. * (currently doesn't comprehend rank)
  378. */
  379. void set_wdq(uint8_t channel, uint8_t rank,
  380. uint8_t byte_lane, uint32_t pi_count)
  381. {
  382. uint32_t reg;
  383. uint32_t msk;
  384. uint32_t temp;
  385. ENTERFN();
  386. DPF(D_TRN, "Wdq ch%d rnk%d ln%d : pi=%03X\n",
  387. channel, rank, byte_lane, pi_count);
  388. /*
  389. * RDPTR (1/2 MCLK, 64 PIs)
  390. * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
  391. * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
  392. */
  393. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  394. channel * DDRIODQ_CH_OFFSET;
  395. msk = (byte_lane & 1) ? 0xf000 : 0xf;
  396. temp = pi_count / HALF_CLK;
  397. temp <<= (byte_lane & 1) ? 12 : 0;
  398. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  399. /* Adjust PI_COUNT */
  400. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  401. /*
  402. * PI (1/64 MCLK, 1 PIs)
  403. * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
  404. * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
  405. */
  406. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  407. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  408. channel * DDRIODQ_CH_OFFSET);
  409. msk = 0x3f00;
  410. temp = pi_count << 8;
  411. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  412. /*
  413. * DEADBAND
  414. * BL0/1 -> B01DBCTL1[06/09] (+1 select)
  415. * BL0/1 -> B01DBCTL1[00/03] (enable)
  416. */
  417. reg = B01DBCTL1 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  418. channel * DDRIODQ_CH_OFFSET;
  419. msk = 0x00;
  420. temp = 0x00;
  421. /* enable */
  422. msk |= (byte_lane & 1) ? (1 << 3) : (1 << 0);
  423. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  424. temp |= msk;
  425. /* select */
  426. msk |= (byte_lane & 1) ? (1 << 9) : (1 << 6);
  427. if (pi_count < EARLY_DB)
  428. temp |= msk;
  429. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  430. /* error check */
  431. if (pi_count > 0x3f) {
  432. training_message(channel, rank, byte_lane);
  433. mrc_post_code(0xee, 0xe3);
  434. }
  435. LEAVEFN();
  436. }
  437. /*
  438. * This function will return the amount of WDQ delay on the given
  439. * channel, rank, byte_lane as an absolute PI count.
  440. *
  441. * (currently doesn't comprehend rank)
  442. */
  443. uint32_t get_wdq(uint8_t channel, uint8_t rank, uint8_t byte_lane)
  444. {
  445. uint32_t reg;
  446. uint32_t temp;
  447. uint32_t pi_count;
  448. ENTERFN();
  449. /*
  450. * RDPTR (1/2 MCLK, 64 PIs)
  451. * BL0 -> B01PTRCTL0[03:00] (0x0-0xF)
  452. * BL1 -> B01PTRCTL0[15:12] (0x0-0xF)
  453. */
  454. reg = B01PTRCTL0 + (byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  455. channel * DDRIODQ_CH_OFFSET;
  456. temp = msg_port_alt_read(DDRPHY, reg);
  457. temp >>= (byte_lane & 1) ? 12 : 0;
  458. temp &= 0xf;
  459. /* Adjust PI_COUNT */
  460. pi_count = temp * HALF_CLK;
  461. /*
  462. * PI (1/64 MCLK, 1 PIs)
  463. * BL0 -> B0DLLPICODER0[13:08] (0x00-0x3F)
  464. * BL1 -> B1DLLPICODER0[13:08] (0x00-0x3F)
  465. */
  466. reg = (byte_lane & 1) ? B1DLLPICODER0 : B0DLLPICODER0;
  467. reg += ((byte_lane >> 1) * DDRIODQ_BL_OFFSET +
  468. channel * DDRIODQ_CH_OFFSET);
  469. temp = msg_port_alt_read(DDRPHY, reg);
  470. temp >>= 8;
  471. temp &= 0x3f;
  472. /* Adjust PI_COUNT */
  473. pi_count += temp;
  474. LEAVEFN();
  475. return pi_count;
  476. }
  477. /*
  478. * This function will program the WCMD delays based on an absolute
  479. * number of PIs.
  480. */
  481. void set_wcmd(uint8_t channel, uint32_t pi_count)
  482. {
  483. uint32_t reg;
  484. uint32_t msk;
  485. uint32_t temp;
  486. ENTERFN();
  487. /*
  488. * RDPTR (1/2 MCLK, 64 PIs)
  489. * CMDPTRREG[11:08] (0x0-0xF)
  490. */
  491. reg = CMDPTRREG + channel * DDRIOCCC_CH_OFFSET;
  492. msk = 0xf00;
  493. temp = pi_count / HALF_CLK;
  494. temp <<= 8;
  495. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  496. /* Adjust PI_COUNT */
  497. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  498. /*
  499. * PI (1/64 MCLK, 1 PIs)
  500. * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
  501. * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
  502. * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
  503. * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
  504. * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
  505. * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
  506. * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
  507. * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
  508. */
  509. reg = CMDDLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
  510. msk = 0x3f3f3f3f;
  511. temp = (pi_count << 24) | (pi_count << 16) |
  512. (pi_count << 8) | (pi_count << 0);
  513. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  514. reg = CMDDLLPICODER0 + channel * DDRIOCCC_CH_OFFSET; /* PO */
  515. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  516. /*
  517. * DEADBAND
  518. * CMDCFGREG0[17] (+1 select)
  519. * CMDCFGREG0[16] (enable)
  520. */
  521. reg = CMDCFGREG0 + channel * DDRIOCCC_CH_OFFSET;
  522. msk = 0x00;
  523. temp = 0x00;
  524. /* enable */
  525. msk |= (1 << 16);
  526. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  527. temp |= msk;
  528. /* select */
  529. msk |= (1 << 17);
  530. if (pi_count < EARLY_DB)
  531. temp |= msk;
  532. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  533. /* error check */
  534. if (pi_count > 0x3f)
  535. mrc_post_code(0xee, 0xe4);
  536. LEAVEFN();
  537. }
  538. /*
  539. * This function will return the amount of WCMD delay on the given
  540. * channel as an absolute PI count.
  541. */
  542. uint32_t get_wcmd(uint8_t channel)
  543. {
  544. uint32_t reg;
  545. uint32_t temp;
  546. uint32_t pi_count;
  547. ENTERFN();
  548. /*
  549. * RDPTR (1/2 MCLK, 64 PIs)
  550. * CMDPTRREG[11:08] (0x0-0xF)
  551. */
  552. reg = CMDPTRREG + channel * DDRIOCCC_CH_OFFSET;
  553. temp = msg_port_alt_read(DDRPHY, reg);
  554. temp >>= 8;
  555. temp &= 0xf;
  556. /* Adjust PI_COUNT */
  557. pi_count = temp * HALF_CLK;
  558. /*
  559. * PI (1/64 MCLK, 1 PIs)
  560. * CMDDLLPICODER0[29:24] -> CMDSLICE R3 (unused)
  561. * CMDDLLPICODER0[21:16] -> CMDSLICE L3 (unused)
  562. * CMDDLLPICODER0[13:08] -> CMDSLICE R2 (unused)
  563. * CMDDLLPICODER0[05:00] -> CMDSLICE L2 (unused)
  564. * CMDDLLPICODER1[29:24] -> CMDSLICE R1 (unused)
  565. * CMDDLLPICODER1[21:16] -> CMDSLICE L1 (0x00-0x3F)
  566. * CMDDLLPICODER1[13:08] -> CMDSLICE R0 (unused)
  567. * CMDDLLPICODER1[05:00] -> CMDSLICE L0 (unused)
  568. */
  569. reg = CMDDLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
  570. temp = msg_port_alt_read(DDRPHY, reg);
  571. temp >>= 16;
  572. temp &= 0x3f;
  573. /* Adjust PI_COUNT */
  574. pi_count += temp;
  575. LEAVEFN();
  576. return pi_count;
  577. }
  578. /*
  579. * This function will program the WCLK delays based on an absolute
  580. * number of PIs.
  581. */
  582. void set_wclk(uint8_t channel, uint8_t rank, uint32_t pi_count)
  583. {
  584. uint32_t reg;
  585. uint32_t msk;
  586. uint32_t temp;
  587. ENTERFN();
  588. /*
  589. * RDPTR (1/2 MCLK, 64 PIs)
  590. * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
  591. * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
  592. */
  593. reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
  594. msk = 0xff00;
  595. temp = ((pi_count / HALF_CLK) << 12) | ((pi_count / HALF_CLK) << 8);
  596. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  597. /* Adjust PI_COUNT */
  598. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  599. /*
  600. * PI (1/64 MCLK, 1 PIs)
  601. * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
  602. * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
  603. */
  604. reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
  605. reg += (channel * DDRIOCCC_CH_OFFSET);
  606. msk = 0x3f3f00;
  607. temp = (pi_count << 16) | (pi_count << 8);
  608. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  609. reg = rank ? ECCB1DLLPICODER1 : ECCB1DLLPICODER1;
  610. reg += (channel * DDRIOCCC_CH_OFFSET);
  611. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  612. reg = rank ? ECCB1DLLPICODER2 : ECCB1DLLPICODER2;
  613. reg += (channel * DDRIOCCC_CH_OFFSET);
  614. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  615. reg = rank ? ECCB1DLLPICODER3 : ECCB1DLLPICODER3;
  616. reg += (channel * DDRIOCCC_CH_OFFSET);
  617. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  618. /*
  619. * DEADBAND
  620. * CCCFGREG1[11:08] (+1 select)
  621. * CCCFGREG1[03:00] (enable)
  622. */
  623. reg = CCCFGREG1 + channel * DDRIOCCC_CH_OFFSET;
  624. msk = 0x00;
  625. temp = 0x00;
  626. /* enable */
  627. msk |= 0xf;
  628. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  629. temp |= msk;
  630. /* select */
  631. msk |= 0xf00;
  632. if (pi_count < EARLY_DB)
  633. temp |= msk;
  634. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  635. /* error check */
  636. if (pi_count > 0x3f)
  637. mrc_post_code(0xee, 0xe5);
  638. LEAVEFN();
  639. }
  640. /*
  641. * This function will return the amout of WCLK delay on the given
  642. * channel, rank as an absolute PI count.
  643. */
  644. uint32_t get_wclk(uint8_t channel, uint8_t rank)
  645. {
  646. uint32_t reg;
  647. uint32_t temp;
  648. uint32_t pi_count;
  649. ENTERFN();
  650. /*
  651. * RDPTR (1/2 MCLK, 64 PIs)
  652. * CCPTRREG[15:12] -> CLK1 (0x0-0xF)
  653. * CCPTRREG[11:08] -> CLK0 (0x0-0xF)
  654. */
  655. reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
  656. temp = msg_port_alt_read(DDRPHY, reg);
  657. temp >>= rank ? 12 : 8;
  658. temp &= 0xf;
  659. /* Adjust PI_COUNT */
  660. pi_count = temp * HALF_CLK;
  661. /*
  662. * PI (1/64 MCLK, 1 PIs)
  663. * ECCB1DLLPICODER0[13:08] -> CLK0 (0x00-0x3F)
  664. * ECCB1DLLPICODER0[21:16] -> CLK1 (0x00-0x3F)
  665. */
  666. reg = rank ? ECCB1DLLPICODER0 : ECCB1DLLPICODER0;
  667. reg += (channel * DDRIOCCC_CH_OFFSET);
  668. temp = msg_port_alt_read(DDRPHY, reg);
  669. temp >>= rank ? 16 : 8;
  670. temp &= 0x3f;
  671. pi_count += temp;
  672. LEAVEFN();
  673. return pi_count;
  674. }
  675. /*
  676. * This function will program the WCTL delays based on an absolute
  677. * number of PIs.
  678. *
  679. * (currently doesn't comprehend rank)
  680. */
  681. void set_wctl(uint8_t channel, uint8_t rank, uint32_t pi_count)
  682. {
  683. uint32_t reg;
  684. uint32_t msk;
  685. uint32_t temp;
  686. ENTERFN();
  687. /*
  688. * RDPTR (1/2 MCLK, 64 PIs)
  689. * CCPTRREG[31:28] (0x0-0xF)
  690. * CCPTRREG[27:24] (0x0-0xF)
  691. */
  692. reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
  693. msk = 0xff000000;
  694. temp = ((pi_count / HALF_CLK) << 28) | ((pi_count / HALF_CLK) << 24);
  695. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  696. /* Adjust PI_COUNT */
  697. pi_count -= ((pi_count / HALF_CLK) & 0xf) * HALF_CLK;
  698. /*
  699. * PI (1/64 MCLK, 1 PIs)
  700. * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
  701. * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
  702. */
  703. reg = ECCB1DLLPICODER0 + channel * DDRIOCCC_CH_OFFSET;
  704. msk = 0x3f000000;
  705. temp = (pi_count << 24);
  706. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  707. reg = ECCB1DLLPICODER1 + channel * DDRIOCCC_CH_OFFSET;
  708. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  709. reg = ECCB1DLLPICODER2 + channel * DDRIOCCC_CH_OFFSET;
  710. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  711. reg = ECCB1DLLPICODER3 + channel * DDRIOCCC_CH_OFFSET;
  712. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  713. /*
  714. * DEADBAND
  715. * CCCFGREG1[13:12] (+1 select)
  716. * CCCFGREG1[05:04] (enable)
  717. */
  718. reg = CCCFGREG1 + channel * DDRIOCCC_CH_OFFSET;
  719. msk = 0x00;
  720. temp = 0x00;
  721. /* enable */
  722. msk |= 0x30;
  723. if ((pi_count < EARLY_DB) || (pi_count > LATE_DB))
  724. temp |= msk;
  725. /* select */
  726. msk |= 0x3000;
  727. if (pi_count < EARLY_DB)
  728. temp |= msk;
  729. mrc_alt_write_mask(DDRPHY, reg, temp, msk);
  730. /* error check */
  731. if (pi_count > 0x3f)
  732. mrc_post_code(0xee, 0xe6);
  733. LEAVEFN();
  734. }
  735. /*
  736. * This function will return the amount of WCTL delay on the given
  737. * channel, rank as an absolute PI count.
  738. *
  739. * (currently doesn't comprehend rank)
  740. */
  741. uint32_t get_wctl(uint8_t channel, uint8_t rank)
  742. {
  743. uint32_t reg;
  744. uint32_t temp;
  745. uint32_t pi_count;
  746. ENTERFN();
  747. /*
  748. * RDPTR (1/2 MCLK, 64 PIs)
  749. * CCPTRREG[31:28] (0x0-0xF)
  750. * CCPTRREG[27:24] (0x0-0xF)
  751. */
  752. reg = CCPTRREG + channel * DDRIOCCC_CH_OFFSET;
  753. temp = msg_port_alt_read(DDRPHY, reg);
  754. temp >>= 24;
  755. temp &= 0xf;
  756. /* Adjust PI_COUNT */
  757. pi_count = temp * HALF_CLK;
  758. /*
  759. * PI (1/64 MCLK, 1 PIs)
  760. * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
  761. * ECCB1DLLPICODER?[29:24] (0x00-0x3F)
  762. */
  763. reg = ECCB1DLLPICODER0 + channel * DDRIOCCC_CH_OFFSET;
  764. temp = msg_port_alt_read(DDRPHY, reg);
  765. temp >>= 24;
  766. temp &= 0x3f;
  767. /* Adjust PI_COUNT */
  768. pi_count += temp;
  769. LEAVEFN();
  770. return pi_count;
  771. }
  772. /*
  773. * This function will program the internal Vref setting in a given
  774. * byte lane in a given channel.
  775. */
  776. void set_vref(uint8_t channel, uint8_t byte_lane, uint32_t setting)
  777. {
  778. uint32_t reg = (byte_lane & 0x1) ? B1VREFCTL : B0VREFCTL;
  779. ENTERFN();
  780. DPF(D_TRN, "Vref ch%d ln%d : val=%03X\n",
  781. channel, byte_lane, setting);
  782. mrc_alt_write_mask(DDRPHY, reg + channel * DDRIODQ_CH_OFFSET +
  783. (byte_lane >> 1) * DDRIODQ_BL_OFFSET,
  784. vref_codes[setting] << 2, 0xfc);
  785. /*
  786. * need to wait ~300ns for Vref to settle
  787. * (check that this is necessary)
  788. */
  789. delay_n(300);
  790. /* ??? may need to clear pointers ??? */
  791. LEAVEFN();
  792. }
  793. /*
  794. * This function will return the internal Vref setting for the given
  795. * channel, byte_lane.
  796. */
  797. uint32_t get_vref(uint8_t channel, uint8_t byte_lane)
  798. {
  799. uint8_t j;
  800. uint32_t ret_val = sizeof(vref_codes) / 2;
  801. uint32_t reg = (byte_lane & 0x1) ? B1VREFCTL : B0VREFCTL;
  802. uint32_t temp;
  803. ENTERFN();
  804. temp = msg_port_alt_read(DDRPHY, reg + channel * DDRIODQ_CH_OFFSET +
  805. (byte_lane >> 1) * DDRIODQ_BL_OFFSET);
  806. temp >>= 2;
  807. temp &= 0x3f;
  808. for (j = 0; j < sizeof(vref_codes); j++) {
  809. if (vref_codes[j] == temp) {
  810. ret_val = j;
  811. break;
  812. }
  813. }
  814. LEAVEFN();
  815. return ret_val;
  816. }
  817. /*
  818. * This function will return a 32-bit address in the desired
  819. * channel and rank.
  820. */
  821. uint32_t get_addr(uint8_t channel, uint8_t rank)
  822. {
  823. uint32_t offset = 32 * 1024 * 1024; /* 32MB */
  824. /* Begin product specific code */
  825. if (channel > 0) {
  826. DPF(D_ERROR, "ILLEGAL CHANNEL\n");
  827. DEAD_LOOP();
  828. }
  829. if (rank > 1) {
  830. DPF(D_ERROR, "ILLEGAL RANK\n");
  831. DEAD_LOOP();
  832. }
  833. /* use 256MB lowest density as per DRP == 0x0003 */
  834. offset += rank * (256 * 1024 * 1024);
  835. return offset;
  836. }
  837. /*
  838. * This function will sample the DQTRAINSTS registers in the given
  839. * channel/rank SAMPLE_SIZE times looking for a valid '0' or '1'.
  840. *
  841. * It will return an encoded 32-bit date in which each bit corresponds to
  842. * the sampled value on the byte lane.
  843. */
  844. uint32_t sample_dqs(struct mrc_params *mrc_params, uint8_t channel,
  845. uint8_t rank, bool rcvn)
  846. {
  847. uint8_t j; /* just a counter */
  848. uint8_t bl; /* which BL in the module (always 2 per module) */
  849. uint8_t bl_grp; /* which BL module */
  850. /* byte lane divisor */
  851. uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
  852. uint32_t msk[2]; /* BLx in module */
  853. /* DQTRAINSTS register contents for each sample */
  854. uint32_t sampled_val[SAMPLE_SIZE];
  855. uint32_t num_0s; /* tracks the number of '0' samples */
  856. uint32_t num_1s; /* tracks the number of '1' samples */
  857. uint32_t ret_val = 0x00; /* assume all '0' samples */
  858. uint32_t address = get_addr(channel, rank);
  859. /* initialise msk[] */
  860. msk[0] = rcvn ? (1 << 1) : (1 << 9); /* BL0 */
  861. msk[1] = rcvn ? (1 << 0) : (1 << 8); /* BL1 */
  862. /* cycle through each byte lane group */
  863. for (bl_grp = 0; bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2; bl_grp++) {
  864. /* take SAMPLE_SIZE samples */
  865. for (j = 0; j < SAMPLE_SIZE; j++) {
  866. hte_mem_op(address, mrc_params->first_run,
  867. rcvn ? 0 : 1);
  868. mrc_params->first_run = 0;
  869. /*
  870. * record the contents of the proper
  871. * DQTRAINSTS register
  872. */
  873. sampled_val[j] = msg_port_alt_read(DDRPHY,
  874. DQTRAINSTS +
  875. bl_grp * DDRIODQ_BL_OFFSET +
  876. channel * DDRIODQ_CH_OFFSET);
  877. }
  878. /*
  879. * look for a majority value (SAMPLE_SIZE / 2) + 1
  880. * on the byte lane and set that value in the corresponding
  881. * ret_val bit
  882. */
  883. for (bl = 0; bl < 2; bl++) {
  884. num_0s = 0x00; /* reset '0' tracker for byte lane */
  885. num_1s = 0x00; /* reset '1' tracker for byte lane */
  886. for (j = 0; j < SAMPLE_SIZE; j++) {
  887. if (sampled_val[j] & msk[bl])
  888. num_1s++;
  889. else
  890. num_0s++;
  891. }
  892. if (num_1s > num_0s)
  893. ret_val |= (1 << (bl + bl_grp * 2));
  894. }
  895. }
  896. /*
  897. * "ret_val.0" contains the status of BL0
  898. * "ret_val.1" contains the status of BL1
  899. * "ret_val.2" contains the status of BL2
  900. * etc.
  901. */
  902. return ret_val;
  903. }
  904. /* This function will find the rising edge transition on RCVN or WDQS */
  905. void find_rising_edge(struct mrc_params *mrc_params, uint32_t delay[],
  906. uint8_t channel, uint8_t rank, bool rcvn)
  907. {
  908. bool all_edges_found; /* determines stop condition */
  909. bool direction[NUM_BYTE_LANES]; /* direction indicator */
  910. uint8_t sample; /* sample counter */
  911. uint8_t bl; /* byte lane counter */
  912. /* byte lane divisor */
  913. uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
  914. uint32_t sample_result[SAMPLE_CNT]; /* results of sample_dqs() */
  915. uint32_t temp;
  916. uint32_t transition_pattern;
  917. ENTERFN();
  918. /* select hte and request initial configuration */
  919. select_hte();
  920. mrc_params->first_run = 1;
  921. /* Take 3 sample points (T1,T2,T3) to obtain a transition pattern */
  922. for (sample = 0; sample < SAMPLE_CNT; sample++) {
  923. /* program the desired delays for sample */
  924. for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
  925. /* increase sample delay by 26 PI (0.2 CLK) */
  926. if (rcvn) {
  927. set_rcvn(channel, rank, bl,
  928. delay[bl] + sample * SAMPLE_DLY);
  929. } else {
  930. set_wdqs(channel, rank, bl,
  931. delay[bl] + sample * SAMPLE_DLY);
  932. }
  933. }
  934. /* take samples (Tsample_i) */
  935. sample_result[sample] = sample_dqs(mrc_params,
  936. channel, rank, rcvn);
  937. DPF(D_TRN,
  938. "Find rising edge %s ch%d rnk%d: #%d dly=%d dqs=%02X\n",
  939. rcvn ? "RCVN" : "WDQS", channel, rank, sample,
  940. sample * SAMPLE_DLY, sample_result[sample]);
  941. }
  942. /*
  943. * This pattern will help determine where we landed and ultimately
  944. * how to place RCVEN/WDQS.
  945. */
  946. for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
  947. /* build transition_pattern (MSB is 1st sample) */
  948. transition_pattern = 0;
  949. for (sample = 0; sample < SAMPLE_CNT; sample++) {
  950. transition_pattern |=
  951. ((sample_result[sample] & (1 << bl)) >> bl) <<
  952. (SAMPLE_CNT - 1 - sample);
  953. }
  954. DPF(D_TRN, "=== transition pattern %d\n", transition_pattern);
  955. /*
  956. * set up to look for rising edge based on
  957. * transition_pattern
  958. */
  959. switch (transition_pattern) {
  960. case 0: /* sampled 0->0->0 */
  961. /* move forward from T3 looking for 0->1 */
  962. delay[bl] += 2 * SAMPLE_DLY;
  963. direction[bl] = FORWARD;
  964. break;
  965. case 1: /* sampled 0->0->1 */
  966. case 5: /* sampled 1->0->1 (bad duty cycle) *HSD#237503* */
  967. /* move forward from T2 looking for 0->1 */
  968. delay[bl] += 1 * SAMPLE_DLY;
  969. direction[bl] = FORWARD;
  970. break;
  971. case 2: /* sampled 0->1->0 (bad duty cycle) *HSD#237503* */
  972. case 3: /* sampled 0->1->1 */
  973. /* move forward from T1 looking for 0->1 */
  974. delay[bl] += 0 * SAMPLE_DLY;
  975. direction[bl] = FORWARD;
  976. break;
  977. case 4: /* sampled 1->0->0 (assumes BL8, HSD#234975) */
  978. /* move forward from T3 looking for 0->1 */
  979. delay[bl] += 2 * SAMPLE_DLY;
  980. direction[bl] = FORWARD;
  981. break;
  982. case 6: /* sampled 1->1->0 */
  983. case 7: /* sampled 1->1->1 */
  984. /* move backward from T1 looking for 1->0 */
  985. delay[bl] += 0 * SAMPLE_DLY;
  986. direction[bl] = BACKWARD;
  987. break;
  988. default:
  989. mrc_post_code(0xee, 0xee);
  990. break;
  991. }
  992. /* program delays */
  993. if (rcvn)
  994. set_rcvn(channel, rank, bl, delay[bl]);
  995. else
  996. set_wdqs(channel, rank, bl, delay[bl]);
  997. }
  998. /*
  999. * Based on the observed transition pattern on the byte lane,
  1000. * begin looking for a rising edge with single PI granularity.
  1001. */
  1002. do {
  1003. all_edges_found = true; /* assume all byte lanes passed */
  1004. /* take a sample */
  1005. temp = sample_dqs(mrc_params, channel, rank, rcvn);
  1006. /* check all each byte lane for proper edge */
  1007. for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
  1008. if (temp & (1 << bl)) {
  1009. /* sampled "1" */
  1010. if (direction[bl] == BACKWARD) {
  1011. /*
  1012. * keep looking for edge
  1013. * on this byte lane
  1014. */
  1015. all_edges_found = false;
  1016. delay[bl] -= 1;
  1017. if (rcvn) {
  1018. set_rcvn(channel, rank,
  1019. bl, delay[bl]);
  1020. } else {
  1021. set_wdqs(channel, rank,
  1022. bl, delay[bl]);
  1023. }
  1024. }
  1025. } else {
  1026. /* sampled "0" */
  1027. if (direction[bl] == FORWARD) {
  1028. /*
  1029. * keep looking for edge
  1030. * on this byte lane
  1031. */
  1032. all_edges_found = false;
  1033. delay[bl] += 1;
  1034. if (rcvn) {
  1035. set_rcvn(channel, rank,
  1036. bl, delay[bl]);
  1037. } else {
  1038. set_wdqs(channel, rank,
  1039. bl, delay[bl]);
  1040. }
  1041. }
  1042. }
  1043. }
  1044. } while (!all_edges_found);
  1045. /* restore DDR idle state */
  1046. dram_init_command(DCMD_PREA(rank));
  1047. DPF(D_TRN, "Delay %03X %03X %03X %03X\n",
  1048. delay[0], delay[1], delay[2], delay[3]);
  1049. LEAVEFN();
  1050. }
  1051. /*
  1052. * This function will return a 32 bit mask that will be used to
  1053. * check for byte lane failures.
  1054. */
  1055. uint32_t byte_lane_mask(struct mrc_params *mrc_params)
  1056. {
  1057. uint32_t j;
  1058. uint32_t ret_val = 0x00;
  1059. /*
  1060. * set ret_val based on NUM_BYTE_LANES such that you will check
  1061. * only BL0 in result
  1062. *
  1063. * (each bit in result represents a byte lane)
  1064. */
  1065. for (j = 0; j < MAX_BYTE_LANES; j += NUM_BYTE_LANES)
  1066. ret_val |= (1 << ((j / NUM_BYTE_LANES) * NUM_BYTE_LANES));
  1067. /*
  1068. * HSD#235037
  1069. * need to adjust the mask for 16-bit mode
  1070. */
  1071. if (mrc_params->channel_width == X16)
  1072. ret_val |= (ret_val << 2);
  1073. return ret_val;
  1074. }
  1075. /*
  1076. * Check memory executing simple write/read/verify at the specified address.
  1077. *
  1078. * Bits in the result indicate failure on specific byte lane.
  1079. */
  1080. uint32_t check_rw_coarse(struct mrc_params *mrc_params, uint32_t address)
  1081. {
  1082. uint32_t result = 0;
  1083. uint8_t first_run = 0;
  1084. if (mrc_params->hte_setup) {
  1085. mrc_params->hte_setup = 0;
  1086. first_run = 1;
  1087. select_hte();
  1088. }
  1089. result = hte_basic_write_read(mrc_params, address, first_run,
  1090. WRITE_TRAIN);
  1091. DPF(D_TRN, "check_rw_coarse result is %x\n", result);
  1092. return result;
  1093. }
  1094. /*
  1095. * Check memory executing write/read/verify of many data patterns
  1096. * at the specified address. Bits in the result indicate failure
  1097. * on specific byte lane.
  1098. */
  1099. uint32_t check_bls_ex(struct mrc_params *mrc_params, uint32_t address)
  1100. {
  1101. uint32_t result;
  1102. uint8_t first_run = 0;
  1103. if (mrc_params->hte_setup) {
  1104. mrc_params->hte_setup = 0;
  1105. first_run = 1;
  1106. select_hte();
  1107. }
  1108. result = hte_write_stress_bit_lanes(mrc_params, address, first_run);
  1109. DPF(D_TRN, "check_bls_ex result is %x\n", result);
  1110. return result;
  1111. }
  1112. /*
  1113. * 32-bit LFSR with characteristic polynomial: X^32 + X^22 +X^2 + X^1
  1114. *
  1115. * The function takes pointer to previous 32 bit value and
  1116. * modifies it to next value.
  1117. */
  1118. void lfsr32(uint32_t *lfsr_ptr)
  1119. {
  1120. uint32_t bit;
  1121. uint32_t lfsr;
  1122. int i;
  1123. lfsr = *lfsr_ptr;
  1124. for (i = 0; i < 32; i++) {
  1125. bit = 1 ^ (lfsr & 1);
  1126. bit = bit ^ ((lfsr & 2) >> 1);
  1127. bit = bit ^ ((lfsr & 4) >> 2);
  1128. bit = bit ^ ((lfsr & 0x400000) >> 22);
  1129. lfsr = ((lfsr >> 1) | (bit << 31));
  1130. }
  1131. *lfsr_ptr = lfsr;
  1132. }
  1133. /* Clear the pointers in a given byte lane in a given channel */
  1134. void clear_pointers(void)
  1135. {
  1136. uint8_t channel;
  1137. uint8_t bl;
  1138. ENTERFN();
  1139. for (channel = 0; channel < NUM_CHANNELS; channel++) {
  1140. for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
  1141. mrc_alt_write_mask(DDRPHY,
  1142. B01PTRCTL1 +
  1143. channel * DDRIODQ_CH_OFFSET +
  1144. (bl >> 1) * DDRIODQ_BL_OFFSET,
  1145. ~(1 << 8), (1 << 8));
  1146. mrc_alt_write_mask(DDRPHY,
  1147. B01PTRCTL1 +
  1148. channel * DDRIODQ_CH_OFFSET +
  1149. (bl >> 1) * DDRIODQ_BL_OFFSET,
  1150. (1 << 8), (1 << 8));
  1151. }
  1152. }
  1153. LEAVEFN();
  1154. }
  1155. static void print_timings_internal(uint8_t algo, uint8_t channel, uint8_t rank,
  1156. uint8_t bl_divisor)
  1157. {
  1158. uint8_t bl;
  1159. switch (algo) {
  1160. case RCVN:
  1161. DPF(D_INFO, "\nRCVN[%02d:%02d]", channel, rank);
  1162. break;
  1163. case WDQS:
  1164. DPF(D_INFO, "\nWDQS[%02d:%02d]", channel, rank);
  1165. break;
  1166. case WDQX:
  1167. DPF(D_INFO, "\nWDQx[%02d:%02d]", channel, rank);
  1168. break;
  1169. case RDQS:
  1170. DPF(D_INFO, "\nRDQS[%02d:%02d]", channel, rank);
  1171. break;
  1172. case VREF:
  1173. DPF(D_INFO, "\nVREF[%02d:%02d]", channel, rank);
  1174. break;
  1175. case WCMD:
  1176. DPF(D_INFO, "\nWCMD[%02d:%02d]", channel, rank);
  1177. break;
  1178. case WCTL:
  1179. DPF(D_INFO, "\nWCTL[%02d:%02d]", channel, rank);
  1180. break;
  1181. case WCLK:
  1182. DPF(D_INFO, "\nWCLK[%02d:%02d]", channel, rank);
  1183. break;
  1184. default:
  1185. break;
  1186. }
  1187. for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
  1188. switch (algo) {
  1189. case RCVN:
  1190. DPF(D_INFO, " %03d", get_rcvn(channel, rank, bl));
  1191. break;
  1192. case WDQS:
  1193. DPF(D_INFO, " %03d", get_wdqs(channel, rank, bl));
  1194. break;
  1195. case WDQX:
  1196. DPF(D_INFO, " %03d", get_wdq(channel, rank, bl));
  1197. break;
  1198. case RDQS:
  1199. DPF(D_INFO, " %03d", get_rdqs(channel, rank, bl));
  1200. break;
  1201. case VREF:
  1202. DPF(D_INFO, " %03d", get_vref(channel, bl));
  1203. break;
  1204. case WCMD:
  1205. DPF(D_INFO, " %03d", get_wcmd(channel));
  1206. break;
  1207. case WCTL:
  1208. DPF(D_INFO, " %03d", get_wctl(channel, rank));
  1209. break;
  1210. case WCLK:
  1211. DPF(D_INFO, " %03d", get_wclk(channel, rank));
  1212. break;
  1213. default:
  1214. break;
  1215. }
  1216. }
  1217. }
  1218. void print_timings(struct mrc_params *mrc_params)
  1219. {
  1220. uint8_t algo;
  1221. uint8_t channel;
  1222. uint8_t rank;
  1223. uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
  1224. DPF(D_INFO, "\n---------------------------");
  1225. DPF(D_INFO, "\nALGO[CH:RK] BL0 BL1 BL2 BL3");
  1226. DPF(D_INFO, "\n===========================");
  1227. for (algo = 0; algo < MAX_ALGOS; algo++) {
  1228. for (channel = 0; channel < NUM_CHANNELS; channel++) {
  1229. if (mrc_params->channel_enables & (1 << channel)) {
  1230. for (rank = 0; rank < NUM_RANKS; rank++) {
  1231. if (mrc_params->rank_enables &
  1232. (1 << rank)) {
  1233. print_timings_internal(algo,
  1234. channel, rank,
  1235. bl_divisor);
  1236. }
  1237. }
  1238. }
  1239. }
  1240. }
  1241. DPF(D_INFO, "\n---------------------------");
  1242. DPF(D_INFO, "\n");
  1243. }