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