mrc_util.c 34 KB

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