mrc_util.c 34 KB

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