x86: quark: Fix unused warnings
[oweals/u-boot.git] / arch / x86 / cpu / quark / smc.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 <pci.h>
13 #include <asm/arch/device.h>
14 #include <asm/arch/mrc.h>
15 #include <asm/arch/msg_port.h>
16 #include "mrc_util.h"
17 #include "hte.h"
18 #include "smc.h"
19
20 /* t_ck clock period in picoseconds per speed index 800, 1066, 1333 */
21 static const uint32_t t_ck[3] = {
22         2500,
23         1875,
24         1500
25 };
26
27 /* Global variables */
28 static const uint16_t ddr_wclk[] = {193, 158};
29 #ifdef BACKUP_WCTL
30 static const uint16_t ddr_wctl[] = {1, 217};
31 #endif
32 #ifdef BACKUP_WCMD
33 static const uint16_t ddr_wcmd[] = {1, 220};
34 #endif
35
36 #ifdef BACKUP_RCVN
37 static const uint16_t ddr_rcvn[] = {129, 498};
38 #endif
39
40 #ifdef BACKUP_WDQS
41 static const uint16_t ddr_wdqs[] = {65, 289};
42 #endif
43
44 #ifdef BACKUP_RDQS
45 static const uint8_t ddr_rdqs[] = {32, 24};
46 #endif
47
48 #ifdef BACKUP_WDQ
49 static const uint16_t ddr_wdq[] = {32, 257};
50 #endif
51
52 /* Stop self refresh driven by MCU */
53 void clear_self_refresh(struct mrc_params *mrc_params)
54 {
55         ENTERFN();
56
57         /* clear the PMSTS Channel Self Refresh bits */
58         mrc_write_mask(MEM_CTLR, PMSTS, PMSTS_DISR, PMSTS_DISR);
59
60         LEAVEFN();
61 }
62
63 /* It will initialize timing registers in the MCU (DTR0..DTR4) */
64 void prog_ddr_timing_control(struct mrc_params *mrc_params)
65 {
66         uint8_t tcl, wl;
67         uint8_t trp, trcd, tras, twr, twtr, trrd, trtp, tfaw;
68         uint32_t tck;
69         u32 dtr0, dtr1, dtr2, dtr3, dtr4;
70         u32 tmp1, tmp2;
71
72         ENTERFN();
73
74         /* mcu_init starts */
75         mrc_post_code(0x02, 0x00);
76
77         dtr0 = msg_port_read(MEM_CTLR, DTR0);
78         dtr1 = msg_port_read(MEM_CTLR, DTR1);
79         dtr2 = msg_port_read(MEM_CTLR, DTR2);
80         dtr3 = msg_port_read(MEM_CTLR, DTR3);
81         dtr4 = msg_port_read(MEM_CTLR, DTR4);
82
83         tck = t_ck[mrc_params->ddr_speed];      /* Clock in picoseconds */
84         tcl = mrc_params->params.cl;            /* CAS latency in clocks */
85         trp = tcl;      /* Per CAT MRC */
86         trcd = tcl;     /* Per CAT MRC */
87         tras = MCEIL(mrc_params->params.ras, tck);
88
89         /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
90         twr = MCEIL(15000, tck);
91
92         twtr = MCEIL(mrc_params->params.wtr, tck);
93         trrd = MCEIL(mrc_params->params.rrd, tck);
94         trtp = 4;       /* Valid for 800 and 1066, use 5 for 1333 */
95         tfaw = MCEIL(mrc_params->params.faw, tck);
96
97         wl = 5 + mrc_params->ddr_speed;
98
99         dtr0 &= ~DTR0_DFREQ_MASK;
100         dtr0 |= mrc_params->ddr_speed;
101         dtr0 &= ~DTR0_TCL_MASK;
102         tmp1 = tcl - 5;
103         dtr0 |= ((tcl - 5) << 12);
104         dtr0 &= ~DTR0_TRP_MASK;
105         dtr0 |= ((trp - 5) << 4);       /* 5 bit DRAM Clock */
106         dtr0 &= ~DTR0_TRCD_MASK;
107         dtr0 |= ((trcd - 5) << 8);      /* 5 bit DRAM Clock */
108
109         dtr1 &= ~DTR1_TWCL_MASK;
110         tmp2 = wl - 3;
111         dtr1 |= (wl - 3);
112         dtr1 &= ~DTR1_TWTP_MASK;
113         dtr1 |= ((wl + 4 + twr - 14) << 8);     /* Change to tWTP */
114         dtr1 &= ~DTR1_TRTP_MASK;
115         dtr1 |= ((MMAX(trtp, 4) - 3) << 28);    /* 4 bit DRAM Clock */
116         dtr1 &= ~DTR1_TRRD_MASK;
117         dtr1 |= ((trrd - 4) << 24);             /* 4 bit DRAM Clock */
118         dtr1 &= ~DTR1_TCMD_MASK;
119         dtr1 |= (1 << 4);
120         dtr1 &= ~DTR1_TRAS_MASK;
121         dtr1 |= ((tras - 14) << 20);            /* 6 bit DRAM Clock */
122         dtr1 &= ~DTR1_TFAW_MASK;
123         dtr1 |= ((((tfaw + 1) >> 1) - 5) << 16);/* 4 bit DRAM Clock */
124         /* Set 4 Clock CAS to CAS delay (multi-burst) */
125         dtr1 &= ~DTR1_TCCD_MASK;
126
127         dtr2 &= ~DTR2_TRRDR_MASK;
128         dtr2 |= 1;
129         dtr2 &= ~DTR2_TWWDR_MASK;
130         dtr2 |= (2 << 8);
131         dtr2 &= ~DTR2_TRWDR_MASK;
132         dtr2 |= (2 << 16);
133
134         dtr3 &= ~DTR3_TWRDR_MASK;
135         dtr3 |= 2;
136         dtr3 &= ~DTR3_TXXXX_MASK;
137         dtr3 |= (2 << 4);
138
139         dtr3 &= ~DTR3_TRWSR_MASK;
140         if (mrc_params->ddr_speed == DDRFREQ_800) {
141                 /* Extended RW delay (+1) */
142                 dtr3 |= ((tcl - 5 + 1) << 8);
143         } else if (mrc_params->ddr_speed == DDRFREQ_1066) {
144                 /* Extended RW delay (+1) */
145                 dtr3 |= ((tcl - 5 + 1) << 8);
146         }
147
148         dtr3 &= ~DTR3_TWRSR_MASK;
149         dtr3 |= ((4 + wl + twtr - 11) << 13);
150
151         dtr3 &= ~DTR3_TXP_MASK;
152         if (mrc_params->ddr_speed == DDRFREQ_800)
153                 dtr3 |= ((MMAX(0, 1 - 1)) << 22);
154         else
155                 dtr3 |= ((MMAX(0, 2 - 1)) << 22);
156
157         dtr4 &= ~DTR4_WRODTSTRT_MASK;
158         dtr4 |= 1;
159         dtr4 &= ~DTR4_WRODTSTOP_MASK;
160         dtr4 |= (1 << 4);
161         dtr4 &= ~DTR4_XXXX1_MASK;
162         dtr4 |= ((1 + tmp1 - tmp2 + 2) << 8);
163         dtr4 &= ~DTR4_XXXX2_MASK;
164         dtr4 |= ((1 + tmp1 - tmp2 + 2) << 12);
165         dtr4 &= ~(DTR4_ODTDIS | DTR4_TRGSTRDIS);
166
167         msg_port_write(MEM_CTLR, DTR0, dtr0);
168         msg_port_write(MEM_CTLR, DTR1, dtr1);
169         msg_port_write(MEM_CTLR, DTR2, dtr2);
170         msg_port_write(MEM_CTLR, DTR3, dtr3);
171         msg_port_write(MEM_CTLR, DTR4, dtr4);
172
173         LEAVEFN();
174 }
175
176 /* Configure MCU before jedec init sequence */
177 void prog_decode_before_jedec(struct mrc_params *mrc_params)
178 {
179         u32 drp;
180         u32 drfc;
181         u32 dcal;
182         u32 dsch;
183         u32 dpmc0;
184
185         ENTERFN();
186
187         /* Disable power saving features */
188         dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
189         dpmc0 |= (DPMC0_CLKGTDIS | DPMC0_DISPWRDN);
190         dpmc0 &= ~DPMC0_PCLSTO_MASK;
191         dpmc0 &= ~DPMC0_DYNSREN;
192         msg_port_write(MEM_CTLR, DPMC0, dpmc0);
193
194         /* Disable out of order transactions */
195         dsch = msg_port_read(MEM_CTLR, DSCH);
196         dsch |= (DSCH_OOODIS | DSCH_NEWBYPDIS);
197         msg_port_write(MEM_CTLR, DSCH, dsch);
198
199         /* Disable issuing the REF command */
200         drfc = msg_port_read(MEM_CTLR, DRFC);
201         drfc &= ~DRFC_TREFI_MASK;
202         msg_port_write(MEM_CTLR, DRFC, drfc);
203
204         /* Disable ZQ calibration short */
205         dcal = msg_port_read(MEM_CTLR, DCAL);
206         dcal &= ~DCAL_ZQCINT_MASK;
207         dcal &= ~DCAL_SRXZQCL_MASK;
208         msg_port_write(MEM_CTLR, DCAL, dcal);
209
210         /*
211          * Training performed in address mode 0, rank population has limited
212          * impact, however simulator complains if enabled non-existing rank.
213          */
214         drp = 0;
215         if (mrc_params->rank_enables & 1)
216                 drp |= DRP_RKEN0;
217         if (mrc_params->rank_enables & 2)
218                 drp |= DRP_RKEN1;
219         msg_port_write(MEM_CTLR, DRP, drp);
220
221         LEAVEFN();
222 }
223
224 /*
225  * After Cold Reset, BIOS should set COLDWAKE bit to 1 before
226  * sending the WAKE message to the Dunit.
227  *
228  * For Standby Exit, or any other mode in which the DRAM is in
229  * SR, this bit must be set to 0.
230  */
231 void perform_ddr_reset(struct mrc_params *mrc_params)
232 {
233         ENTERFN();
234
235         /* Set COLDWAKE bit before sending the WAKE message */
236         mrc_write_mask(MEM_CTLR, DRMC, DRMC_COLDWAKE, DRMC_COLDWAKE);
237
238         /* Send wake command to DUNIT (MUST be done before JEDEC) */
239         dram_wake_command();
240
241         /* Set default value */
242         msg_port_write(MEM_CTLR, DRMC,
243                        mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0);
244
245         LEAVEFN();
246 }
247
248
249 /*
250  * This function performs some initialization on the DDRIO unit.
251  * This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
252  */
253 void ddrphy_init(struct mrc_params *mrc_params)
254 {
255         uint32_t temp;
256         uint8_t ch;     /* channel counter */
257         uint8_t rk;     /* rank counter */
258         uint8_t bl_grp; /*  byte lane group counter (2 BLs per module) */
259         uint8_t bl_divisor = 1; /* byte lane divisor */
260         /* For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333 */
261         uint8_t speed = mrc_params->ddr_speed & 3;
262         uint8_t cas;
263         uint8_t cwl;
264
265         ENTERFN();
266
267         cas = mrc_params->params.cl;
268         cwl = 5 + mrc_params->ddr_speed;
269
270         /* ddrphy_init starts */
271         mrc_post_code(0x03, 0x00);
272
273         /*
274          * HSD#231531
275          * Make sure IOBUFACT is deasserted before initializing the DDR PHY
276          *
277          * HSD#234845
278          * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
279          */
280         for (ch = 0; ch < NUM_CHANNELS; ch++) {
281                 if (mrc_params->channel_enables & (1 << ch)) {
282                         /* Deassert DDRPHY Initialization Complete */
283                         mrc_alt_write_mask(DDRPHY,
284                                 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
285                                 ~(1 << 20), 1 << 20);   /* SPID_INIT_COMPLETE=0 */
286                         /* Deassert IOBUFACT */
287                         mrc_alt_write_mask(DDRPHY,
288                                 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
289                                 ~(1 << 2), 1 << 2);     /* IOBUFACTRST_N=0 */
290                         /* Disable WRPTR */
291                         mrc_alt_write_mask(DDRPHY,
292                                 CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
293                                 ~(1 << 0), 1 << 0);     /* WRPTRENABLE=0 */
294                 }
295         }
296
297         /* Put PHY in reset */
298         mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, 1);
299
300         /* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */
301
302         /* STEP0 */
303         mrc_post_code(0x03, 0x10);
304         for (ch = 0; ch < NUM_CHANNELS; ch++) {
305                 if (mrc_params->channel_enables & (1 << ch)) {
306                         /* DQ01-DQ23 */
307                         for (bl_grp = 0;
308                              bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
309                              bl_grp++) {
310                                 /* Analog MUX select - IO2xCLKSEL */
311                                 mrc_alt_write_mask(DDRPHY,
312                                         DQOBSCKEBBCTL +
313                                         bl_grp * DDRIODQ_BL_OFFSET +
314                                         ch * DDRIODQ_CH_OFFSET,
315                                         bl_grp ? 0 : (1 << 22), 1 << 22);
316
317                                 /* ODT Strength */
318                                 switch (mrc_params->rd_odt_value) {
319                                 case 1:
320                                         temp = 0x3;
321                                         break;  /* 60 ohm */
322                                 case 2:
323                                         temp = 0x3;
324                                         break;  /* 120 ohm */
325                                 case 3:
326                                         temp = 0x3;
327                                         break;  /* 180 ohm */
328                                 default:
329                                         temp = 0x3;
330                                         break;  /* 120 ohm */
331                                 }
332
333                                 /* ODT strength */
334                                 mrc_alt_write_mask(DDRPHY,
335                                         B0RXIOBUFCTL +
336                                         bl_grp * DDRIODQ_BL_OFFSET +
337                                         ch * DDRIODQ_CH_OFFSET,
338                                         temp << 5, 0x60);
339                                 /* ODT strength */
340                                 mrc_alt_write_mask(DDRPHY,
341                                         B1RXIOBUFCTL +
342                                         bl_grp * DDRIODQ_BL_OFFSET +
343                                         ch * DDRIODQ_CH_OFFSET,
344                                         temp << 5, 0x60);
345
346                                 /* Dynamic ODT/DIFFAMP */
347                                 temp = (cas << 24) | (cas << 16) |
348                                         (cas << 8) | (cas << 0);
349                                 switch (speed) {
350                                 case 0:
351                                         temp -= 0x01010101;
352                                         break;  /* 800 */
353                                 case 1:
354                                         temp -= 0x02020202;
355                                         break;  /* 1066 */
356                                 case 2:
357                                         temp -= 0x03030303;
358                                         break;  /* 1333 */
359                                 case 3:
360                                         temp -= 0x04040404;
361                                         break;  /* 1600 */
362                                 }
363
364                                 /* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
365                                 mrc_alt_write_mask(DDRPHY,
366                                         B01LATCTL1 +
367                                         bl_grp * DDRIODQ_BL_OFFSET +
368                                         ch * DDRIODQ_CH_OFFSET,
369                                         temp, 0x1f1f1f1f);
370                                 switch (speed) {
371                                 /* HSD#234715 */
372                                 case 0:
373                                         temp = (0x06 << 16) | (0x07 << 8);
374                                         break;  /* 800 */
375                                 case 1:
376                                         temp = (0x07 << 16) | (0x08 << 8);
377                                         break;  /* 1066 */
378                                 case 2:
379                                         temp = (0x09 << 16) | (0x0a << 8);
380                                         break;  /* 1333 */
381                                 case 3:
382                                         temp = (0x0a << 16) | (0x0b << 8);
383                                         break;  /* 1600 */
384                                 }
385
386                                 /* On Duration: ODT, DIFFAMP */
387                                 mrc_alt_write_mask(DDRPHY,
388                                         B0ONDURCTL +
389                                         bl_grp * DDRIODQ_BL_OFFSET +
390                                         ch * DDRIODQ_CH_OFFSET,
391                                         temp, 0x003f3f00);
392                                 /* On Duration: ODT, DIFFAMP */
393                                 mrc_alt_write_mask(DDRPHY,
394                                         B1ONDURCTL +
395                                         bl_grp * DDRIODQ_BL_OFFSET +
396                                         ch * DDRIODQ_CH_OFFSET,
397                                         temp, 0x003f3f00);
398
399                                 switch (mrc_params->rd_odt_value) {
400                                 case 0:
401                                         /* override DIFFAMP=on, ODT=off */
402                                         temp = (0x3f << 16) | (0x3f << 10);
403                                         break;
404                                 default:
405                                         /* override DIFFAMP=on, ODT=on */
406                                         temp = (0x3f << 16) | (0x2a << 10);
407                                         break;
408                                 }
409
410                                 /* Override: DIFFAMP, ODT */
411                                 mrc_alt_write_mask(DDRPHY,
412                                         B0OVRCTL +
413                                         bl_grp * DDRIODQ_BL_OFFSET +
414                                         ch * DDRIODQ_CH_OFFSET,
415                                         temp, 0x003ffc00);
416                                 /* Override: DIFFAMP, ODT */
417                                 mrc_alt_write_mask(DDRPHY,
418                                         B1OVRCTL +
419                                         bl_grp * DDRIODQ_BL_OFFSET +
420                                         ch * DDRIODQ_CH_OFFSET,
421                                         temp, 0x003ffc00);
422
423                                 /* DLL Setup */
424
425                                 /* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
426                                 mrc_alt_write_mask(DDRPHY,
427                                         B0LATCTL0 +
428                                         bl_grp * DDRIODQ_BL_OFFSET +
429                                         ch * DDRIODQ_CH_OFFSET,
430                                         ((cas + 7) << 16) | ((cas - 4) << 8) |
431                                         ((cwl - 2) << 0), 0x003f1f1f);
432                                 mrc_alt_write_mask(DDRPHY,
433                                         B1LATCTL0 +
434                                         bl_grp * DDRIODQ_BL_OFFSET +
435                                         ch * DDRIODQ_CH_OFFSET,
436                                         ((cas + 7) << 16) | ((cas - 4) << 8) |
437                                         ((cwl - 2) << 0), 0x003f1f1f);
438
439                                 /* RCVEN Bypass (PO) */
440                                 mrc_alt_write_mask(DDRPHY,
441                                         B0RXIOBUFCTL +
442                                         bl_grp * DDRIODQ_BL_OFFSET +
443                                         ch * DDRIODQ_CH_OFFSET,
444                                         0, 0x81);
445                                 mrc_alt_write_mask(DDRPHY,
446                                         B1RXIOBUFCTL +
447                                         bl_grp * DDRIODQ_BL_OFFSET +
448                                         ch * DDRIODQ_CH_OFFSET,
449                                         0, 0x81);
450
451                                 /* TX */
452                                 mrc_alt_write_mask(DDRPHY,
453                                         DQCTL +
454                                         bl_grp * DDRIODQ_BL_OFFSET +
455                                         ch * DDRIODQ_CH_OFFSET,
456                                         1 << 16, 1 << 16);
457                                 mrc_alt_write_mask(DDRPHY,
458                                         B01PTRCTL1 +
459                                         bl_grp * DDRIODQ_BL_OFFSET +
460                                         ch * DDRIODQ_CH_OFFSET,
461                                         1 << 8, 1 << 8);
462
463                                 /* RX (PO) */
464                                 /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
465                                 mrc_alt_write_mask(DDRPHY,
466                                         B0VREFCTL +
467                                         bl_grp * DDRIODQ_BL_OFFSET +
468                                         ch * DDRIODQ_CH_OFFSET,
469                                         (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
470                                         0xff);
471                                 /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
472                                 mrc_alt_write_mask(DDRPHY,
473                                         B1VREFCTL +
474                                         bl_grp * DDRIODQ_BL_OFFSET +
475                                         ch * DDRIODQ_CH_OFFSET,
476                                         (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
477                                         0xff);
478                                 /* Per-Bit De-Skew Enable */
479                                 mrc_alt_write_mask(DDRPHY,
480                                         B0RXIOBUFCTL +
481                                         bl_grp * DDRIODQ_BL_OFFSET +
482                                         ch * DDRIODQ_CH_OFFSET,
483                                         0, 0x10);
484                                 /* Per-Bit De-Skew Enable */
485                                 mrc_alt_write_mask(DDRPHY,
486                                         B1RXIOBUFCTL +
487                                         bl_grp * DDRIODQ_BL_OFFSET +
488                                         ch * DDRIODQ_CH_OFFSET,
489                                         0, 0x10);
490                         }
491
492                         /* CLKEBB */
493                         mrc_alt_write_mask(DDRPHY,
494                                 CMDOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
495                                 0, 1 << 23);
496
497                         /* Enable tristate control of cmd/address bus */
498                         mrc_alt_write_mask(DDRPHY,
499                                 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
500                                 0, 0x03);
501
502                         /* ODT RCOMP */
503                         mrc_alt_write_mask(DDRPHY,
504                                 CMDRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
505                                 (0x03 << 5) | (0x03 << 0), 0x3ff);
506
507                         /* CMDPM* registers must be programmed in this order */
508
509                         /* Turn On Delays: SFR (regulator), MPLL */
510                         mrc_alt_write_mask(DDRPHY,
511                                 CMDPMDLYREG4 + ch * DDRIOCCC_CH_OFFSET,
512                                 0xffffffff, 0xffffffff);
513                         /*
514                          * Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3,
515                          * VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT
516                          * for_PM_MSG_gt0, MDLL Turn On
517                          */
518                         mrc_alt_write_mask(DDRPHY,
519                                 CMDPMDLYREG3 + ch * DDRIOCCC_CH_OFFSET,
520                                 0xfffff616, 0xffffffff);
521                         /* MPLL Divider Reset Delays */
522                         mrc_alt_write_mask(DDRPHY,
523                                 CMDPMDLYREG2 + ch * DDRIOCCC_CH_OFFSET,
524                                 0xffffffff, 0xffffffff);
525                         /* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
526                         mrc_alt_write_mask(DDRPHY,
527                                 CMDPMDLYREG1 + ch * DDRIOCCC_CH_OFFSET,
528                                 0xffffffff, 0xffffffff);
529                         /* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
530                         mrc_alt_write_mask(DDRPHY,
531                                 CMDPMDLYREG0 + ch * DDRIOCCC_CH_OFFSET,
532                                 0xffffffff, 0xffffffff);
533                         /* Allow PUnit signals */
534                         mrc_alt_write_mask(DDRPHY,
535                                 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
536                                 (0x6 << 8) | (0x1 << 6) | (0x4 << 0),
537                                 0xffe00f4f);
538                         /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
539                         mrc_alt_write_mask(DDRPHY,
540                                 CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
541                                 (0x3 << 4) | (0x7 << 0), 0x7f);
542
543                         /* CLK-CTL */
544                         mrc_alt_write_mask(DDRPHY,
545                                 CCOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
546                                 0, 1 << 24);    /* CLKEBB */
547                         /* Buffer Enable: CS,CKE,ODT,CLK */
548                         mrc_alt_write_mask(DDRPHY,
549                                 CCCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
550                                 0x1f, 0x000ffff1);
551                         /* ODT RCOMP */
552                         mrc_alt_write_mask(DDRPHY,
553                                 CCRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
554                                 (0x03 << 8) | (0x03 << 0), 0x00001f1f);
555                         /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
556                         mrc_alt_write_mask(DDRPHY,
557                                 CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
558                                 (0x3 << 4) | (0x7 << 0), 0x7f);
559
560                         /*
561                          * COMP (RON channel specific)
562                          * - DQ/DQS/DM RON: 32 Ohm
563                          * - CTRL/CMD RON: 27 Ohm
564                          * - CLK RON: 26 Ohm
565                          */
566                         /* RCOMP Vref PU/PD */
567                         mrc_alt_write_mask(DDRPHY,
568                                 DQVREFCH0 +  ch * DDRCOMP_CH_OFFSET,
569                                 (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
570                         /* RCOMP Vref PU/PD */
571                         mrc_alt_write_mask(DDRPHY,
572                                 CMDVREFCH0 + ch * DDRCOMP_CH_OFFSET,
573                                 (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
574                         /* RCOMP Vref PU/PD */
575                         mrc_alt_write_mask(DDRPHY,
576                                 CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
577                                 (0x0F << 24) | (0x03 << 16), 0x3f3f0000);
578                         /* RCOMP Vref PU/PD */
579                         mrc_alt_write_mask(DDRPHY,
580                                 DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
581                                 (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
582                         /* RCOMP Vref PU/PD */
583                         mrc_alt_write_mask(DDRPHY,
584                                 CTLVREFCH0 + ch * DDRCOMP_CH_OFFSET,
585                                 (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
586
587                         /* DQS Swapped Input Enable */
588                         mrc_alt_write_mask(DDRPHY,
589                                 COMPEN1CH0 + ch * DDRCOMP_CH_OFFSET,
590                                 (1 << 19) | (1 << 17), 0xc00ac000);
591
592                         /* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
593                         /* ODT Vref PU/PD */
594                         mrc_alt_write_mask(DDRPHY,
595                                 DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
596                                 (0x32 << 8) | (0x03 << 0), 0x00003f3f);
597                         /* ODT Vref PU/PD */
598                         mrc_alt_write_mask(DDRPHY,
599                                 DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
600                                 (0x32 << 8) | (0x03 << 0), 0x00003f3f);
601                         /* ODT Vref PU/PD */
602                         mrc_alt_write_mask(DDRPHY,
603                                 CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
604                                 (0x0E << 8) | (0x05 << 0), 0x00003f3f);
605
606                         /*
607                          * Slew rate settings are frequency specific,
608                          * numbers below are for 800Mhz (speed == 0)
609                          * - DQ/DQS/DM/CLK SR: 4V/ns,
610                          * - CTRL/CMD SR: 1.5V/ns
611                          */
612                         temp = (0x0e << 16) | (0x0e << 12) | (0x08 << 8) |
613                                 (0x0b << 4) | (0x0b << 0);
614                         /* DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ */
615                         mrc_alt_write_mask(DDRPHY,
616                                 DLYSELCH0 + ch * DDRCOMP_CH_OFFSET,
617                                 temp, 0x000fffff);
618                         /* TCO Vref CLK,DQS,DQ */
619                         mrc_alt_write_mask(DDRPHY,
620                                 TCOVREFCH0 + ch * DDRCOMP_CH_OFFSET,
621                                 (0x05 << 16) | (0x05 << 8) | (0x05 << 0),
622                                 0x003f3f3f);
623                         /* ODTCOMP CMD/CTL PU/PD */
624                         mrc_alt_write_mask(DDRPHY,
625                                 CCBUFODTCH0 + ch * DDRCOMP_CH_OFFSET,
626                                 (0x03 << 8) | (0x03 << 0),
627                                 0x00001f1f);
628                         /* COMP */
629                         mrc_alt_write_mask(DDRPHY,
630                                 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
631                                 0, 0xc0000100);
632
633 #ifdef BACKUP_COMPS
634                         /* DQ COMP Overrides */
635                         /* RCOMP PU */
636                         mrc_alt_write_mask(DDRPHY,
637                                 DQDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
638                                 (1 << 31) | (0x0a << 16),
639                                 0x801f0000);
640                         /* RCOMP PD */
641                         mrc_alt_write_mask(DDRPHY,
642                                 DQDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
643                                 (1 << 31) | (0x0a << 16),
644                                 0x801f0000);
645                         /* DCOMP PU */
646                         mrc_alt_write_mask(DDRPHY,
647                                 DQDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
648                                 (1 << 31) | (0x10 << 16),
649                                 0x801f0000);
650                         /* DCOMP PD */
651                         mrc_alt_write_mask(DDRPHY,
652                                 DQDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
653                                 (1 << 31) | (0x10 << 16),
654                                 0x801f0000);
655                         /* ODTCOMP PU */
656                         mrc_alt_write_mask(DDRPHY,
657                                 DQODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
658                                 (1 << 31) | (0x0b << 16),
659                                 0x801f0000);
660                         /* ODTCOMP PD */
661                         mrc_alt_write_mask(DDRPHY,
662                                 DQODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
663                                 (1 << 31) | (0x0b << 16),
664                                 0x801f0000);
665                         /* TCOCOMP PU */
666                         mrc_alt_write_mask(DDRPHY,
667                                 DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
668                                 1 << 31, 1 << 31);
669                         /* TCOCOMP PD */
670                         mrc_alt_write_mask(DDRPHY,
671                                 DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
672                                 1 << 31, 1 << 31);
673
674                         /* DQS COMP Overrides */
675                         /* RCOMP PU */
676                         mrc_alt_write_mask(DDRPHY,
677                                 DQSDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
678                                 (1 << 31) | (0x0a << 16),
679                                 0x801f0000);
680                         /* RCOMP PD */
681                         mrc_alt_write_mask(DDRPHY,
682                                 DQSDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
683                                 (1 << 31) | (0x0a << 16),
684                                 0x801f0000);
685                         /* DCOMP PU */
686                         mrc_alt_write_mask(DDRPHY,
687                                 DQSDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
688                                 (1 << 31) | (0x10 << 16),
689                                 0x801f0000);
690                         /* DCOMP PD */
691                         mrc_alt_write_mask(DDRPHY,
692                                 DQSDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
693                                 (1 << 31) | (0x10 << 16),
694                                 0x801f0000);
695                         /* ODTCOMP PU */
696                         mrc_alt_write_mask(DDRPHY,
697                                 DQSODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
698                                 (1 << 31) | (0x0b << 16),
699                                 0x801f0000);
700                         /* ODTCOMP PD */
701                         mrc_alt_write_mask(DDRPHY,
702                                 DQSODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
703                                 (1 << 31) | (0x0b << 16),
704                                 0x801f0000);
705                         /* TCOCOMP PU */
706                         mrc_alt_write_mask(DDRPHY,
707                                 DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
708                                 1 << 31, 1 << 31);
709                         /* TCOCOMP PD */
710                         mrc_alt_write_mask(DDRPHY,
711                                 DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
712                                 1 << 31, 1 << 31);
713
714                         /* CLK COMP Overrides */
715                         /* RCOMP PU */
716                         mrc_alt_write_mask(DDRPHY,
717                                 CLKDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
718                                 (1 << 31) | (0x0c << 16),
719                                 0x801f0000);
720                         /* RCOMP PD */
721                         mrc_alt_write_mask(DDRPHY,
722                                 CLKDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
723                                 (1 << 31) | (0x0c << 16),
724                                 0x801f0000);
725                         /* DCOMP PU */
726                         mrc_alt_write_mask(DDRPHY,
727                                 CLKDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
728                                 (1 << 31) | (0x07 << 16),
729                                 0x801f0000);
730                         /* DCOMP PD */
731                         mrc_alt_write_mask(DDRPHY,
732                                 CLKDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
733                                 (1 << 31) | (0x07 << 16),
734                                 0x801f0000);
735                         /* ODTCOMP PU */
736                         mrc_alt_write_mask(DDRPHY,
737                                 CLKODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
738                                 (1 << 31) | (0x0b << 16),
739                                 0x801f0000);
740                         /* ODTCOMP PD */
741                         mrc_alt_write_mask(DDRPHY,
742                                 CLKODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
743                                 (1 << 31) | (0x0b << 16),
744                                 0x801f0000);
745                         /* TCOCOMP PU */
746                         mrc_alt_write_mask(DDRPHY,
747                                 CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
748                                 1 << 31, 1 << 31);
749                         /* TCOCOMP PD */
750                         mrc_alt_write_mask(DDRPHY,
751                                 CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
752                                 1 << 31, 1 << 31);
753
754                         /* CMD COMP Overrides */
755                         /* RCOMP PU */
756                         mrc_alt_write_mask(DDRPHY,
757                                 CMDDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
758                                 (1 << 31) | (0x0d << 16),
759                                 0x803f0000);
760                         /* RCOMP PD */
761                         mrc_alt_write_mask(DDRPHY,
762                                 CMDDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
763                                 (1 << 31) | (0x0d << 16),
764                                 0x803f0000);
765                         /* DCOMP PU */
766                         mrc_alt_write_mask(DDRPHY,
767                                 CMDDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
768                                 (1 << 31) | (0x0a << 16),
769                                 0x801f0000);
770                         /* DCOMP PD */
771                         mrc_alt_write_mask(DDRPHY,
772                                 CMDDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
773                                 (1 << 31) | (0x0a << 16),
774                                 0x801f0000);
775
776                         /* CTL COMP Overrides */
777                         /* RCOMP PU */
778                         mrc_alt_write_mask(DDRPHY,
779                                 CTLDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
780                                 (1 << 31) | (0x0d << 16),
781                                 0x803f0000);
782                         /* RCOMP PD */
783                         mrc_alt_write_mask(DDRPHY,
784                                 CTLDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
785                                 (1 << 31) | (0x0d << 16),
786                                 0x803f0000);
787                         /* DCOMP PU */
788                         mrc_alt_write_mask(DDRPHY,
789                                 CTLDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
790                                 (1 << 31) | (0x0a << 16),
791                                 0x801f0000);
792                         /* DCOMP PD */
793                         mrc_alt_write_mask(DDRPHY,
794                                 CTLDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
795                                 (1 << 31) | (0x0a << 16),
796                                 0x801f0000);
797 #else
798                         /* DQ TCOCOMP Overrides */
799                         /* TCOCOMP PU */
800                         mrc_alt_write_mask(DDRPHY,
801                                 DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
802                                 (1 << 31) | (0x1f << 16),
803                                 0x801f0000);
804                         /* TCOCOMP PD */
805                         mrc_alt_write_mask(DDRPHY,
806                                 DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
807                                 (1 << 31) | (0x1f << 16),
808                                 0x801f0000);
809
810                         /* DQS TCOCOMP Overrides */
811                         /* TCOCOMP PU */
812                         mrc_alt_write_mask(DDRPHY,
813                                 DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
814                                 (1 << 31) | (0x1f << 16),
815                                 0x801f0000);
816                         /* TCOCOMP PD */
817                         mrc_alt_write_mask(DDRPHY,
818                                 DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
819                                 (1 << 31) | (0x1f << 16),
820                                 0x801f0000);
821
822                         /* CLK TCOCOMP Overrides */
823                         /* TCOCOMP PU */
824                         mrc_alt_write_mask(DDRPHY,
825                                 CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
826                                 (1 << 31) | (0x1f << 16),
827                                 0x801f0000);
828                         /* TCOCOMP PD */
829                         mrc_alt_write_mask(DDRPHY,
830                                 CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
831                                 (1 << 31) | (0x1f << 16),
832                                 0x801f0000);
833 #endif
834
835                         /* program STATIC delays */
836 #ifdef BACKUP_WCMD
837                         set_wcmd(ch, ddr_wcmd[PLATFORM_ID]);
838 #else
839                         set_wcmd(ch, ddr_wclk[PLATFORM_ID] + HALF_CLK);
840 #endif
841
842                         for (rk = 0; rk < NUM_RANKS; rk++) {
843                                 if (mrc_params->rank_enables & (1 << rk)) {
844                                         set_wclk(ch, rk, ddr_wclk[PLATFORM_ID]);
845 #ifdef BACKUP_WCTL
846                                         set_wctl(ch, rk, ddr_wctl[PLATFORM_ID]);
847 #else
848                                         set_wctl(ch, rk, ddr_wclk[PLATFORM_ID] + HALF_CLK);
849 #endif
850                                 }
851                         }
852                 }
853         }
854
855         /* COMP (non channel specific) */
856         /* RCOMP: Dither PU Enable */
857         mrc_alt_write_mask(DDRPHY, DQANADRVPUCTL, 1 << 30, 1 << 30);
858         /* RCOMP: Dither PD Enable */
859         mrc_alt_write_mask(DDRPHY, DQANADRVPDCTL, 1 << 30, 1 << 30);
860         /* RCOMP: Dither PU Enable */
861         mrc_alt_write_mask(DDRPHY, CMDANADRVPUCTL, 1 << 30, 1 << 30);
862         /* RCOMP: Dither PD Enable */
863         mrc_alt_write_mask(DDRPHY, CMDANADRVPDCTL, 1 << 30, 1 << 30);
864         /* RCOMP: Dither PU Enable */
865         mrc_alt_write_mask(DDRPHY, CLKANADRVPUCTL, 1 << 30, 1 << 30);
866         /* RCOMP: Dither PD Enable */
867         mrc_alt_write_mask(DDRPHY, CLKANADRVPDCTL, 1 << 30, 1 << 30);
868         /* RCOMP: Dither PU Enable */
869         mrc_alt_write_mask(DDRPHY, DQSANADRVPUCTL, 1 << 30, 1 << 30);
870         /* RCOMP: Dither PD Enable */
871         mrc_alt_write_mask(DDRPHY, DQSANADRVPDCTL, 1 << 30, 1 << 30);
872         /* RCOMP: Dither PU Enable */
873         mrc_alt_write_mask(DDRPHY, CTLANADRVPUCTL, 1 << 30, 1 << 30);
874         /* RCOMP: Dither PD Enable */
875         mrc_alt_write_mask(DDRPHY, CTLANADRVPDCTL, 1 << 30, 1 << 30);
876         /* ODT: Dither PU Enable */
877         mrc_alt_write_mask(DDRPHY, DQANAODTPUCTL, 1 << 30, 1 << 30);
878         /* ODT: Dither PD Enable */
879         mrc_alt_write_mask(DDRPHY, DQANAODTPDCTL, 1 << 30, 1 << 30);
880         /* ODT: Dither PU Enable */
881         mrc_alt_write_mask(DDRPHY, CLKANAODTPUCTL, 1 << 30, 1 << 30);
882         /* ODT: Dither PD Enable */
883         mrc_alt_write_mask(DDRPHY, CLKANAODTPDCTL, 1 << 30, 1 << 30);
884         /* ODT: Dither PU Enable */
885         mrc_alt_write_mask(DDRPHY, DQSANAODTPUCTL, 1 << 30, 1 << 30);
886         /* ODT: Dither PD Enable */
887         mrc_alt_write_mask(DDRPHY, DQSANAODTPDCTL, 1 << 30, 1 << 30);
888         /* DCOMP: Dither PU Enable */
889         mrc_alt_write_mask(DDRPHY, DQANADLYPUCTL, 1 << 30, 1 << 30);
890         /* DCOMP: Dither PD Enable */
891         mrc_alt_write_mask(DDRPHY, DQANADLYPDCTL, 1 << 30, 1 << 30);
892         /* DCOMP: Dither PU Enable */
893         mrc_alt_write_mask(DDRPHY, CMDANADLYPUCTL, 1 << 30, 1 << 30);
894         /* DCOMP: Dither PD Enable */
895         mrc_alt_write_mask(DDRPHY, CMDANADLYPDCTL, 1 << 30, 1 << 30);
896         /* DCOMP: Dither PU Enable */
897         mrc_alt_write_mask(DDRPHY, CLKANADLYPUCTL, 1 << 30, 1 << 30);
898         /* DCOMP: Dither PD Enable */
899         mrc_alt_write_mask(DDRPHY, CLKANADLYPDCTL, 1 << 30, 1 << 30);
900         /* DCOMP: Dither PU Enable */
901         mrc_alt_write_mask(DDRPHY, DQSANADLYPUCTL, 1 << 30, 1 << 30);
902         /* DCOMP: Dither PD Enable */
903         mrc_alt_write_mask(DDRPHY, DQSANADLYPDCTL, 1 << 30, 1 << 30);
904         /* DCOMP: Dither PU Enable */
905         mrc_alt_write_mask(DDRPHY, CTLANADLYPUCTL, 1 << 30, 1 << 30);
906         /* DCOMP: Dither PD Enable */
907         mrc_alt_write_mask(DDRPHY, CTLANADLYPDCTL, 1 << 30, 1 << 30);
908         /* TCO: Dither PU Enable */
909         mrc_alt_write_mask(DDRPHY, DQANATCOPUCTL, 1 << 30, 1 << 30);
910         /* TCO: Dither PD Enable */
911         mrc_alt_write_mask(DDRPHY, DQANATCOPDCTL, 1 << 30, 1 << 30);
912         /* TCO: Dither PU Enable */
913         mrc_alt_write_mask(DDRPHY, CLKANATCOPUCTL, 1 << 30, 1 << 30);
914         /* TCO: Dither PD Enable */
915         mrc_alt_write_mask(DDRPHY, CLKANATCOPDCTL, 1 << 30, 1 << 30);
916         /* TCO: Dither PU Enable */
917         mrc_alt_write_mask(DDRPHY, DQSANATCOPUCTL, 1 << 30, 1 << 30);
918         /* TCO: Dither PD Enable */
919         mrc_alt_write_mask(DDRPHY, DQSANATCOPDCTL, 1 << 30, 1 << 30);
920         /* TCOCOMP: Pulse Count */
921         mrc_alt_write_mask(DDRPHY, TCOCNTCTRL, 1, 3);
922         /* ODT: CMD/CTL PD/PU */
923         mrc_alt_write_mask(DDRPHY, CHNLBUFSTATIC,
924                 (0x03 << 24) | (0x03 << 16), 0x1f1f0000);
925         /* Set 1us counter */
926         mrc_alt_write_mask(DDRPHY, MSCNTR, 0x64, 0xff);
927         mrc_alt_write_mask(DDRPHY, LATCH1CTL, 0x1 << 28, 0x70000000);
928
929         /* Release PHY from reset */
930         mrc_alt_write_mask(DDRPHY, MASTERRSTN, 1, 1);
931
932         /* STEP1 */
933         mrc_post_code(0x03, 0x11);
934
935         for (ch = 0; ch < NUM_CHANNELS; ch++) {
936                 if (mrc_params->channel_enables & (1 << ch)) {
937                         /* DQ01-DQ23 */
938                         for (bl_grp = 0;
939                              bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
940                              bl_grp++) {
941                                 mrc_alt_write_mask(DDRPHY,
942                                         DQMDLLCTL +
943                                         bl_grp * DDRIODQ_BL_OFFSET +
944                                         ch * DDRIODQ_CH_OFFSET,
945                                         1 << 13,
946                                         1 << 13);       /* Enable VREG */
947                                 delay_n(3);
948                         }
949
950                         /* ECC */
951                         mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
952                                 1 << 13, 1 << 13);      /* Enable VREG */
953                         delay_n(3);
954                         /* CMD */
955                         mrc_alt_write_mask(DDRPHY,
956                                 CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
957                                 1 << 13, 1 << 13);      /* Enable VREG */
958                         delay_n(3);
959                         /* CLK-CTL */
960                         mrc_alt_write_mask(DDRPHY,
961                                 CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
962                                 1 << 13, 1 << 13);      /* Enable VREG */
963                         delay_n(3);
964                 }
965         }
966
967         /* STEP2 */
968         mrc_post_code(0x03, 0x12);
969         delay_n(200);
970
971         for (ch = 0; ch < NUM_CHANNELS; ch++) {
972                 if (mrc_params->channel_enables & (1 << ch)) {
973                         /* DQ01-DQ23 */
974                         for (bl_grp = 0;
975                              bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
976                              bl_grp++) {
977                                 mrc_alt_write_mask(DDRPHY,
978                                         DQMDLLCTL +
979                                         bl_grp * DDRIODQ_BL_OFFSET +
980                                         ch * DDRIODQ_CH_OFFSET,
981                                         1 << 17,
982                                         1 << 17);       /* Enable MCDLL */
983                                 delay_n(50);
984                         }
985
986                 /* ECC */
987                 mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
988                         1 << 17, 1 << 17);      /* Enable MCDLL */
989                 delay_n(50);
990                 /* CMD */
991                 mrc_alt_write_mask(DDRPHY,
992                         CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
993                         1 << 18, 1 << 18);      /* Enable MCDLL */
994                 delay_n(50);
995                 /* CLK-CTL */
996                 mrc_alt_write_mask(DDRPHY,
997                         CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
998                         1 << 18, 1 << 18);      /* Enable MCDLL */
999                 delay_n(50);
1000                 }
1001         }
1002
1003         /* STEP3: */
1004         mrc_post_code(0x03, 0x13);
1005         delay_n(100);
1006
1007         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1008                 if (mrc_params->channel_enables & (1 << ch)) {
1009                         /* DQ01-DQ23 */
1010                         for (bl_grp = 0;
1011                              bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
1012                              bl_grp++) {
1013 #ifdef FORCE_16BIT_DDRIO
1014                                 temp = (bl_grp &&
1015                                         (mrc_params->channel_width == X16)) ?
1016                                         0x11ff : 0xffff;
1017 #else
1018                                 temp = 0xffff;
1019 #endif
1020                                 /* Enable TXDLL */
1021                                 mrc_alt_write_mask(DDRPHY,
1022                                         DQDLLTXCTL +
1023                                         bl_grp * DDRIODQ_BL_OFFSET +
1024                                         ch * DDRIODQ_CH_OFFSET,
1025                                         temp, 0xffff);
1026                                 delay_n(3);
1027                                 /* Enable RXDLL */
1028                                 mrc_alt_write_mask(DDRPHY,
1029                                         DQDLLRXCTL +
1030                                         bl_grp * DDRIODQ_BL_OFFSET +
1031                                         ch * DDRIODQ_CH_OFFSET,
1032                                         0xf, 0xf);
1033                                 delay_n(3);
1034                                 /* Enable RXDLL Overrides BL0 */
1035                                 mrc_alt_write_mask(DDRPHY,
1036                                         B0OVRCTL +
1037                                         bl_grp * DDRIODQ_BL_OFFSET +
1038                                         ch * DDRIODQ_CH_OFFSET,
1039                                         0xf, 0xf);
1040                         }
1041
1042                         /* ECC */
1043                         temp = 0xffff;
1044                         mrc_alt_write_mask(DDRPHY, ECCDLLTXCTL,
1045                                 temp, 0xffff);
1046                         delay_n(3);
1047
1048                         /* CMD (PO) */
1049                         mrc_alt_write_mask(DDRPHY,
1050                                 CMDDLLTXCTL + ch * DDRIOCCC_CH_OFFSET,
1051                                 temp, 0xffff);
1052                         delay_n(3);
1053                 }
1054         }
1055
1056         /* STEP4 */
1057         mrc_post_code(0x03, 0x14);
1058
1059         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1060                 if (mrc_params->channel_enables & (1 << ch)) {
1061                         /* Host To Memory Clock Alignment (HMC) for 800/1066 */
1062                         for (bl_grp = 0;
1063                              bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
1064                              bl_grp++) {
1065                                 /* CLK_ALIGN_MOD_ID */
1066                                 mrc_alt_write_mask(DDRPHY,
1067                                         DQCLKALIGNREG2 +
1068                                         bl_grp * DDRIODQ_BL_OFFSET +
1069                                         ch * DDRIODQ_CH_OFFSET,
1070                                         bl_grp ? 3 : 1,
1071                                         0xf);
1072                         }
1073
1074                         mrc_alt_write_mask(DDRPHY,
1075                                 ECCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1076                                 0x2, 0xf);
1077                         mrc_alt_write_mask(DDRPHY,
1078                                 CMDCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1079                                 0x0, 0xf);
1080                         mrc_alt_write_mask(DDRPHY,
1081                                 CCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1082                                 0x2, 0xf);
1083                         mrc_alt_write_mask(DDRPHY,
1084                                 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
1085                                 0x20, 0x30);
1086                         /*
1087                          * NUM_SAMPLES, MAX_SAMPLES,
1088                          * MACRO_PI_STEP, MICRO_PI_STEP
1089                          */
1090                         mrc_alt_write_mask(DDRPHY,
1091                                 CMDCLKALIGNREG1 + ch * DDRIOCCC_CH_OFFSET,
1092                                 (0x18 << 16) | (0x10 << 8) |
1093                                 (0x8 << 2) | (0x1 << 0),
1094                                 0x007f7fff);
1095                         /* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
1096                         mrc_alt_write_mask(DDRPHY,
1097                                 CMDCLKALIGNREG2 + ch * DDRIOCCC_CH_OFFSET,
1098                                 (0x10 << 16) | (0x4 << 8) | (0x2 << 4),
1099                                 0x001f0ff0);
1100 #ifdef HMC_TEST
1101                         /* START_CLK_ALIGN=1 */
1102                         mrc_alt_write_mask(DDRPHY,
1103                                 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
1104                                 1 << 24, 1 << 24);
1105                         while (msg_port_alt_read(DDRPHY,
1106                                 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET) &
1107                                 (1 << 24))
1108                                 ;       /* wait for START_CLK_ALIGN=0 */
1109 #endif
1110
1111                         /* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
1112                         mrc_alt_write_mask(DDRPHY,
1113                                 CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
1114                                 1, 1);  /* WRPTRENABLE=1 */
1115
1116                         /* COMP initial */
1117                         /* enable bypass for CLK buffer (PO) */
1118                         mrc_alt_write_mask(DDRPHY,
1119                                 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
1120                                 1 << 5, 1 << 5);
1121                         /* Initial COMP Enable */
1122                         mrc_alt_write_mask(DDRPHY, CMPCTRL, 1, 1);
1123                         /* wait for Initial COMP Enable = 0 */
1124                         while (msg_port_alt_read(DDRPHY, CMPCTRL) & 1)
1125                                 ;
1126                         /* disable bypass for CLK buffer (PO) */
1127                         mrc_alt_write_mask(DDRPHY,
1128                                 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
1129                                 ~(1 << 5), 1 << 5);
1130
1131                         /* IOBUFACT */
1132
1133                         /* STEP4a */
1134                         mrc_alt_write_mask(DDRPHY,
1135                                 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
1136                                 1 << 2, 1 << 2);        /* IOBUFACTRST_N=1 */
1137
1138                         /* DDRPHY initialization complete */
1139                         mrc_alt_write_mask(DDRPHY,
1140                                 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
1141                                 1 << 20, 1 << 20);      /* SPID_INIT_COMPLETE=1 */
1142                 }
1143         }
1144
1145         LEAVEFN();
1146 }
1147
1148 /* This function performs JEDEC initialization on all enabled channels */
1149 void perform_jedec_init(struct mrc_params *mrc_params)
1150 {
1151         uint8_t twr, wl, rank;
1152         uint32_t tck;
1153         u32 dtr0;
1154         u32 drp;
1155         u32 drmc;
1156         u32 mrs0_cmd = 0;
1157         u32 emrs1_cmd = 0;
1158         u32 emrs2_cmd = 0;
1159         u32 emrs3_cmd = 0;
1160
1161         ENTERFN();
1162
1163         /* jedec_init starts */
1164         mrc_post_code(0x04, 0x00);
1165
1166         /* DDR3_RESET_SET=0, DDR3_RESET_RESET=1 */
1167         mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 2, 0x102);
1168
1169         /* Assert RESET# for 200us */
1170         delay_u(200);
1171
1172         /* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
1173         mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 0x100, 0x102);
1174
1175         dtr0 = msg_port_read(MEM_CTLR, DTR0);
1176
1177         /*
1178          * Set CKEVAL for populated ranks
1179          * then send NOP to each rank (#4550197)
1180          */
1181
1182         drp = msg_port_read(MEM_CTLR, DRP);
1183         drp &= 0x3;
1184
1185         drmc = msg_port_read(MEM_CTLR, DRMC);
1186         drmc &= 0xfffffffc;
1187         drmc |= (DRMC_CKEMODE | drp);
1188
1189         msg_port_write(MEM_CTLR, DRMC, drmc);
1190
1191         for (rank = 0; rank < NUM_RANKS; rank++) {
1192                 /* Skip to next populated rank */
1193                 if ((mrc_params->rank_enables & (1 << rank)) == 0)
1194                         continue;
1195
1196                 dram_init_command(DCMD_NOP(rank));
1197         }
1198
1199         msg_port_write(MEM_CTLR, DRMC,
1200                 (mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0));
1201
1202         /*
1203          * setup for emrs 2
1204          * BIT[15:11] --> Always "0"
1205          * BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)
1206          * BIT[08]    --> Always "0"
1207          * BIT[07]    --> SRT: use sr_temp_range
1208          * BIT[06]    --> ASR: want "Manual SR Reference" (0)
1209          * BIT[05:03] --> CWL: use oem_tCWL
1210          * BIT[02:00] --> PASR: want "Full Array" (0)
1211          */
1212         emrs2_cmd |= (2 << 3);
1213         wl = 5 + mrc_params->ddr_speed;
1214         emrs2_cmd |= ((wl - 5) << 9);
1215         emrs2_cmd |= (mrc_params->sr_temp_range << 13);
1216
1217         /*
1218          * setup for emrs 3
1219          * BIT[15:03] --> Always "0"
1220          * BIT[02]    --> MPR: want "Normal Operation" (0)
1221          * BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
1222          */
1223         emrs3_cmd |= (3 << 3);
1224
1225         /*
1226          * setup for emrs 1
1227          * BIT[15:13]     --> Always "0"
1228          * BIT[12:12]     --> Qoff: want "Output Buffer Enabled" (0)
1229          * BIT[11:11]     --> TDQS: want "Disabled" (0)
1230          * BIT[10:10]     --> Always "0"
1231          * BIT[09,06,02]  --> Rtt_nom: use rtt_nom_value
1232          * BIT[08]        --> Always "0"
1233          * BIT[07]        --> WR_LVL: want "Disabled" (0)
1234          * BIT[05,01]     --> DIC: use ron_value
1235          * BIT[04:03]     --> AL: additive latency want "0" (0)
1236          * BIT[00]        --> DLL: want "Enable" (0)
1237          *
1238          * (BIT5|BIT1) set Ron value
1239          * 00 --> RZQ/6 (40ohm)
1240          * 01 --> RZQ/7 (34ohm)
1241          * 1* --> RESERVED
1242          *
1243          * (BIT9|BIT6|BIT2) set Rtt_nom value
1244          * 000 --> Disabled
1245          * 001 --> RZQ/4 ( 60ohm)
1246          * 010 --> RZQ/2 (120ohm)
1247          * 011 --> RZQ/6 ( 40ohm)
1248          * 1** --> RESERVED
1249          */
1250         emrs1_cmd |= (1 << 3);
1251         emrs1_cmd &= ~(1 << 6);
1252
1253         if (mrc_params->ron_value == 0)
1254                 emrs1_cmd |= (1 << 7);
1255         else
1256                 emrs1_cmd &= ~(1 << 7);
1257
1258         if (mrc_params->rtt_nom_value == 0)
1259                 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_40 << 6);
1260         else if (mrc_params->rtt_nom_value == 1)
1261                 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_60 << 6);
1262         else if (mrc_params->rtt_nom_value == 2)
1263                 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_120 << 6);
1264
1265         /* save MRS1 value (excluding control fields) */
1266         mrc_params->mrs1 = emrs1_cmd >> 6;
1267
1268         /*
1269          * setup for mrs 0
1270          * BIT[15:13]     --> Always "0"
1271          * BIT[12]        --> PPD: for Quark (1)
1272          * BIT[11:09]     --> WR: use oem_tWR
1273          * BIT[08]        --> DLL: want "Reset" (1, self clearing)
1274          * BIT[07]        --> MODE: want "Normal" (0)
1275          * BIT[06:04,02]  --> CL: use oem_tCAS
1276          * BIT[03]        --> RD_BURST_TYPE: want "Interleave" (1)
1277          * BIT[01:00]     --> BL: want "8 Fixed" (0)
1278          * WR:
1279          * 0 --> 16
1280          * 1 --> 5
1281          * 2 --> 6
1282          * 3 --> 7
1283          * 4 --> 8
1284          * 5 --> 10
1285          * 6 --> 12
1286          * 7 --> 14
1287          * CL:
1288          * BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
1289          * BIT[06:04] use oem_tCAS-4
1290          */
1291         mrs0_cmd |= (1 << 14);
1292         mrs0_cmd |= (1 << 18);
1293         mrs0_cmd |= ((((dtr0 >> 12) & 7) + 1) << 10);
1294
1295         tck = t_ck[mrc_params->ddr_speed];
1296         /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
1297         twr = MCEIL(15000, tck);
1298         mrs0_cmd |= ((twr - 4) << 15);
1299
1300         for (rank = 0; rank < NUM_RANKS; rank++) {
1301                 /* Skip to next populated rank */
1302                 if ((mrc_params->rank_enables & (1 << rank)) == 0)
1303                         continue;
1304
1305                 emrs2_cmd |= (rank << 22);
1306                 dram_init_command(emrs2_cmd);
1307
1308                 emrs3_cmd |= (rank << 22);
1309                 dram_init_command(emrs3_cmd);
1310
1311                 emrs1_cmd |= (rank << 22);
1312                 dram_init_command(emrs1_cmd);
1313
1314                 mrs0_cmd |= (rank << 22);
1315                 dram_init_command(mrs0_cmd);
1316
1317                 dram_init_command(DCMD_ZQCL(rank));
1318         }
1319
1320         LEAVEFN();
1321 }
1322
1323 /*
1324  * Dunit Initialization Complete
1325  *
1326  * Indicates that initialization of the Dunit has completed.
1327  *
1328  * Memory accesses are permitted and maintenance operation begins.
1329  * Until this bit is set to a 1, the memory controller will not accept
1330  * DRAM requests from the MEMORY_MANAGER or HTE.
1331  */
1332 void set_ddr_init_complete(struct mrc_params *mrc_params)
1333 {
1334         u32 dco;
1335
1336         ENTERFN();
1337
1338         dco = msg_port_read(MEM_CTLR, DCO);
1339         dco &= ~DCO_PMICTL;
1340         dco |= DCO_IC;
1341         msg_port_write(MEM_CTLR, DCO, dco);
1342
1343         LEAVEFN();
1344 }
1345
1346 /*
1347  * This function will retrieve relevant timing data
1348  *
1349  * This data will be used on subsequent boots to speed up boot times
1350  * and is required for Suspend To RAM capabilities.
1351  */
1352 void restore_timings(struct mrc_params *mrc_params)
1353 {
1354         uint8_t ch, rk, bl;
1355         const struct mrc_timings *mt = &mrc_params->timings;
1356
1357         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1358                 for (rk = 0; rk < NUM_RANKS; rk++) {
1359                         for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
1360                                 set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]);
1361                                 set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]);
1362                                 set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]);
1363                                 set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);
1364                                 if (rk == 0) {
1365                                         /* VREF (RANK0 only) */
1366                                         set_vref(ch, bl, mt->vref[ch][bl]);
1367                                 }
1368                         }
1369                         set_wctl(ch, rk, mt->wctl[ch][rk]);
1370                 }
1371                 set_wcmd(ch, mt->wcmd[ch]);
1372         }
1373 }
1374
1375 /*
1376  * Configure default settings normally set as part of read training
1377  *
1378  * Some defaults have to be set earlier as they may affect earlier
1379  * training steps.
1380  */
1381 void default_timings(struct mrc_params *mrc_params)
1382 {
1383         uint8_t ch, rk, bl;
1384
1385         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1386                 for (rk = 0; rk < NUM_RANKS; rk++) {
1387                         for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
1388                                 set_rdqs(ch, rk, bl, 24);
1389                                 if (rk == 0) {
1390                                         /* VREF (RANK0 only) */
1391                                         set_vref(ch, bl, 32);
1392                                 }
1393                         }
1394                 }
1395         }
1396 }
1397
1398 /*
1399  * This function will perform our RCVEN Calibration Algorithm.
1400  * We will only use the 2xCLK domain timings to perform RCVEN Calibration.
1401  * All byte lanes will be calibrated "simultaneously" per channel per rank.
1402  */
1403 void rcvn_cal(struct mrc_params *mrc_params)
1404 {
1405         uint8_t ch;     /* channel counter */
1406         uint8_t rk;     /* rank counter */
1407         uint8_t bl;     /* byte lane counter */
1408         uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1409
1410 #ifdef R2R_SHARING
1411         /* used to find placement for rank2rank sharing configs */
1412         uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1413 #ifndef BACKUP_RCVN
1414         /* used to find placement for rank2rank sharing configs */
1415         uint32_t num_ranks_enabled = 0;
1416 #endif
1417 #endif
1418
1419 #ifdef BACKUP_RCVN
1420 #else
1421         uint32_t temp;
1422         /* absolute PI value to be programmed on the byte lane */
1423         uint32_t delay[NUM_BYTE_LANES];
1424         u32 dtr1, dtr1_save;
1425 #endif
1426
1427         ENTERFN();
1428
1429         /* rcvn_cal starts */
1430         mrc_post_code(0x05, 0x00);
1431
1432 #ifndef BACKUP_RCVN
1433         /* need separate burst to sample DQS preamble */
1434         dtr1 = msg_port_read(MEM_CTLR, DTR1);
1435         dtr1_save = dtr1;
1436         dtr1 |= DTR1_TCCD_12CLK;
1437         msg_port_write(MEM_CTLR, DTR1, dtr1);
1438 #endif
1439
1440 #ifdef R2R_SHARING
1441         /* need to set "final_delay[][]" elements to "0" */
1442         memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1443 #endif
1444
1445         /* loop through each enabled channel */
1446         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1447                 if (mrc_params->channel_enables & (1 << ch)) {
1448                         /* perform RCVEN Calibration on a per rank basis */
1449                         for (rk = 0; rk < NUM_RANKS; rk++) {
1450                                 if (mrc_params->rank_enables & (1 << rk)) {
1451                                         /*
1452                                          * POST_CODE here indicates the current
1453                                          * channel and rank being calibrated
1454                                          */
1455                                         mrc_post_code(0x05, 0x10 + ((ch << 4) | rk));
1456
1457 #ifdef BACKUP_RCVN
1458                                         /* et hard-coded timing values */
1459                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++)
1460                                                 set_rcvn(ch, rk, bl, ddr_rcvn[PLATFORM_ID]);
1461 #else
1462                                         /* enable FIFORST */
1463                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
1464                                                 mrc_alt_write_mask(DDRPHY,
1465                                                         B01PTRCTL1 +
1466                                                         (bl >> 1) * DDRIODQ_BL_OFFSET +
1467                                                         ch * DDRIODQ_CH_OFFSET,
1468                                                         0, 1 << 8);
1469                                         }
1470                                         /* initialize the starting delay to 128 PI (cas +1 CLK) */
1471                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1472                                                 /* 1x CLK domain timing is cas-4 */
1473                                                 delay[bl] = (4 + 1) * FULL_CLK;
1474
1475                                                 set_rcvn(ch, rk, bl, delay[bl]);
1476                                         }
1477
1478                                         /* now find the rising edge */
1479                                         find_rising_edge(mrc_params, delay, ch, rk, true);
1480
1481                                         /* Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse */
1482                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1483                                                 delay[bl] += QRTR_CLK;
1484                                                 set_rcvn(ch, rk, bl, delay[bl]);
1485                                         }
1486                                         /* Now decrement delay by 128 PI (1 CLK) until we sample a "0" */
1487                                         do {
1488                                                 temp = sample_dqs(mrc_params, ch, rk, true);
1489                                                 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1490                                                         if (temp & (1 << bl)) {
1491                                                                 if (delay[bl] >= FULL_CLK) {
1492                                                                         delay[bl] -= FULL_CLK;
1493                                                                         set_rcvn(ch, rk, bl, delay[bl]);
1494                                                                 } else {
1495                                                                         /* not enough delay */
1496                                                                         training_message(ch, rk, bl);
1497                                                                         mrc_post_code(0xee, 0x50);
1498                                                                 }
1499                                                         }
1500                                                 }
1501                                         } while (temp & 0xff);
1502
1503 #ifdef R2R_SHARING
1504                                         /* increment "num_ranks_enabled" */
1505                                         num_ranks_enabled++;
1506                                         /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
1507                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1508                                                 delay[bl] += QRTR_CLK;
1509                                                 /* add "delay[]" values to "final_delay[][]" for rolling average */
1510                                                 final_delay[ch][bl] += delay[bl];
1511                                                 /* set timing based on rolling average values */
1512                                                 set_rcvn(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
1513                                         }
1514 #else
1515                                         /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
1516                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1517                                                 delay[bl] += QRTR_CLK;
1518                                                 set_rcvn(ch, rk, bl, delay[bl]);
1519                                         }
1520 #endif
1521
1522                                         /* disable FIFORST */
1523                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
1524                                                 mrc_alt_write_mask(DDRPHY,
1525                                                         B01PTRCTL1 +
1526                                                         (bl >> 1) * DDRIODQ_BL_OFFSET +
1527                                                         ch * DDRIODQ_CH_OFFSET,
1528                                                         1 << 8, 1 << 8);
1529                                         }
1530 #endif
1531                                 }
1532                         }
1533                 }
1534         }
1535
1536 #ifndef BACKUP_RCVN
1537         /* restore original */
1538         msg_port_write(MEM_CTLR, DTR1, dtr1_save);
1539 #endif
1540
1541         LEAVEFN();
1542 }
1543
1544 /*
1545  * This function will perform the Write Levelling algorithm
1546  * (align WCLK and WDQS).
1547  *
1548  * This algorithm will act on each rank in each channel separately.
1549  */
1550 void wr_level(struct mrc_params *mrc_params)
1551 {
1552         uint8_t ch;     /* channel counter */
1553         uint8_t rk;     /* rank counter */
1554         uint8_t bl;     /* byte lane counter */
1555         uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1556
1557 #ifdef R2R_SHARING
1558         /* used to find placement for rank2rank sharing configs */
1559         uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1560 #ifndef BACKUP_WDQS
1561         /* used to find placement for rank2rank sharing configs */
1562         uint32_t num_ranks_enabled = 0;
1563 #endif
1564 #endif
1565
1566 #ifdef BACKUP_WDQS
1567 #else
1568         /* determines stop condition for CRS_WR_LVL */
1569         bool all_edges_found;
1570         /* absolute PI value to be programmed on the byte lane */
1571         uint32_t delay[NUM_BYTE_LANES];
1572         /*
1573          * static makes it so the data is loaded in the heap once by shadow(),
1574          * where non-static copies the data onto the stack every time this
1575          * function is called
1576          */
1577         uint32_t address;       /* address to be checked during COARSE_WR_LVL */
1578         u32 dtr4, dtr4_save;
1579 #endif
1580
1581         ENTERFN();
1582
1583         /* wr_level starts */
1584         mrc_post_code(0x06, 0x00);
1585
1586 #ifdef R2R_SHARING
1587         /* need to set "final_delay[][]" elements to "0" */
1588         memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1589 #endif
1590
1591         /* loop through each enabled channel */
1592         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1593                 if (mrc_params->channel_enables & (1 << ch)) {
1594                         /* perform WRITE LEVELING algorithm on a per rank basis */
1595                         for (rk = 0; rk < NUM_RANKS; rk++) {
1596                                 if (mrc_params->rank_enables & (1 << rk)) {
1597                                         /*
1598                                          * POST_CODE here indicates the current
1599                                          * rank and channel being calibrated
1600                                          */
1601                                         mrc_post_code(0x06, 0x10 + ((ch << 4) | rk));
1602
1603 #ifdef BACKUP_WDQS
1604                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1605                                                 set_wdqs(ch, rk, bl, ddr_wdqs[PLATFORM_ID]);
1606                                                 set_wdq(ch, rk, bl, ddr_wdqs[PLATFORM_ID] - QRTR_CLK);
1607                                         }
1608 #else
1609                                         /*
1610                                          * perform a single PRECHARGE_ALL command to
1611                                          * make DRAM state machine go to IDLE state
1612                                          */
1613                                         dram_init_command(DCMD_PREA(rk));
1614
1615                                         /*
1616                                          * enable Write Levelling Mode
1617                                          * (EMRS1 w/ Write Levelling Mode Enable)
1618                                          */
1619                                         dram_init_command(DCMD_MRS1(rk, 0x82));
1620
1621                                         /*
1622                                          * set ODT DRAM Full Time Termination
1623                                          * disable in MCU
1624                                          */
1625
1626                                         dtr4 = msg_port_read(MEM_CTLR, DTR4);
1627                                         dtr4_save = dtr4;
1628                                         dtr4 |= DTR4_ODTDIS;
1629                                         msg_port_write(MEM_CTLR, DTR4, dtr4);
1630
1631                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
1632                                                 /*
1633                                                  * Enable Sandy Bridge Mode (WDQ Tri-State) &
1634                                                  * Ensure 5 WDQS pulses during Write Leveling
1635                                                  */
1636                                                 mrc_alt_write_mask(DDRPHY,
1637                                                         DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
1638                                                         0x10000154,
1639                                                         0x100003fc);
1640                                         }
1641
1642                                         /* Write Leveling Mode enabled in IO */
1643                                         mrc_alt_write_mask(DDRPHY,
1644                                                 CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
1645                                                 1 << 16, 1 << 16);
1646
1647                                         /* Initialize the starting delay to WCLK */
1648                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1649                                                 /*
1650                                                  * CLK0 --> RK0
1651                                                  * CLK1 --> RK1
1652                                                  */
1653                                                 delay[bl] = get_wclk(ch, rk);
1654
1655                                                 set_wdqs(ch, rk, bl, delay[bl]);
1656                                         }
1657
1658                                         /* now find the rising edge */
1659                                         find_rising_edge(mrc_params, delay, ch, rk, false);
1660
1661                                         /* disable Write Levelling Mode */
1662                                         mrc_alt_write_mask(DDRPHY,
1663                                                 CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
1664                                                 0, 1 << 16);
1665
1666                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
1667                                                 /* Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation */
1668                                                 mrc_alt_write_mask(DDRPHY,
1669                                                         DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
1670                                                         0x00000154,
1671                                                         0x100003fc);
1672                                         }
1673
1674                                         /* restore original DTR4 */
1675                                         msg_port_write(MEM_CTLR, DTR4, dtr4_save);
1676
1677                                         /*
1678                                          * restore original value
1679                                          * (Write Levelling Mode Disable)
1680                                          */
1681                                         dram_init_command(DCMD_MRS1(rk, mrc_params->mrs1));
1682
1683                                         /*
1684                                          * perform a single PRECHARGE_ALL command to
1685                                          * make DRAM state machine go to IDLE state
1686                                          */
1687                                         dram_init_command(DCMD_PREA(rk));
1688
1689                                         mrc_post_code(0x06, 0x30 + ((ch << 4) | rk));
1690
1691                                         /*
1692                                          * COARSE WRITE LEVEL:
1693                                          * check that we're on the correct clock edge
1694                                          */
1695
1696                                         /* hte reconfiguration request */
1697                                         mrc_params->hte_setup = 1;
1698
1699                                         /* start CRS_WR_LVL with WDQS = WDQS + 128 PI */
1700                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1701                                                 delay[bl] = get_wdqs(ch, rk, bl) + FULL_CLK;
1702                                                 set_wdqs(ch, rk, bl, delay[bl]);
1703                                                 /*
1704                                                  * program WDQ timings based on WDQS
1705                                                  * (WDQ = WDQS - 32 PI)
1706                                                  */
1707                                                 set_wdq(ch, rk, bl, (delay[bl] - QRTR_CLK));
1708                                         }
1709
1710                                         /* get an address in the targeted channel/rank */
1711                                         address = get_addr(ch, rk);
1712                                         do {
1713                                                 uint32_t coarse_result = 0x00;
1714                                                 uint32_t coarse_result_mask = byte_lane_mask(mrc_params);
1715                                                 /* assume pass */
1716                                                 all_edges_found = true;
1717
1718                                                 mrc_params->hte_setup = 1;
1719                                                 coarse_result = check_rw_coarse(mrc_params, address);
1720
1721                                                 /* check for failures and margin the byte lane back 128 PI (1 CLK) */
1722                                                 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
1723                                                         if (coarse_result & (coarse_result_mask << bl)) {
1724                                                                 all_edges_found = false;
1725                                                                 delay[bl] -= FULL_CLK;
1726                                                                 set_wdqs(ch, rk, bl, delay[bl]);
1727                                                                 /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
1728                                                                 set_wdq(ch, rk, bl, delay[bl] - QRTR_CLK);
1729                                                         }
1730                                                 }
1731                                         } while (!all_edges_found);
1732
1733 #ifdef R2R_SHARING
1734                                         /* increment "num_ranks_enabled" */
1735                                          num_ranks_enabled++;
1736                                         /* accumulate "final_delay[][]" values from "delay[]" values for rolling average */
1737                                         for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
1738                                                 final_delay[ch][bl] += delay[bl];
1739                                                 set_wdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
1740                                                 /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
1741                                                 set_wdq(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled - QRTR_CLK);
1742                                         }
1743 #endif
1744 #endif
1745                                 }
1746                         }
1747                 }
1748         }
1749
1750         LEAVEFN();
1751 }
1752
1753 void prog_page_ctrl(struct mrc_params *mrc_params)
1754 {
1755         u32 dpmc0;
1756
1757         ENTERFN();
1758
1759         dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
1760         dpmc0 &= ~DPMC0_PCLSTO_MASK;
1761         dpmc0 |= (4 << 16);
1762         dpmc0 |= DPMC0_PREAPWDEN;
1763         msg_port_write(MEM_CTLR, DPMC0, dpmc0);
1764 }
1765
1766 /*
1767  * This function will perform the READ TRAINING Algorithm on all
1768  * channels/ranks/byte_lanes simultaneously to minimize execution time.
1769  *
1770  * The idea here is to train the VREF and RDQS (and eventually RDQ) values
1771  * to achieve maximum READ margins. The algorithm will first determine the
1772  * X coordinate (RDQS setting). This is done by collapsing the VREF eye
1773  * until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.
1774  * Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX,
1775  * then average those; this will be the final X coordinate. The algorithm
1776  * will then determine the Y coordinate (VREF setting). This is done by
1777  * collapsing the RDQS eye until we find a minimum required VREF eye for
1778  * RDQS_MIN and RDQS_MAX. Then we take the averages of the VREF eye at
1779  * RDQS_MIN and RDQS_MAX, then average those; this will be the final Y
1780  * coordinate.
1781  *
1782  * NOTE: this algorithm assumes the eye curves have a one-to-one relationship,
1783  * meaning for each X the curve has only one Y and vice-a-versa.
1784  */
1785 void rd_train(struct mrc_params *mrc_params)
1786 {
1787         uint8_t ch;     /* channel counter */
1788         uint8_t rk;     /* rank counter */
1789         uint8_t bl;     /* byte lane counter */
1790         uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1791 #ifdef BACKUP_RDQS
1792 #else
1793         uint8_t side_x; /* tracks LEFT/RIGHT approach vectors */
1794         uint8_t side_y; /* tracks BOTTOM/TOP approach vectors */
1795         /* X coordinate data (passing RDQS values) for approach vectors */
1796         uint8_t x_coordinate[2][2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
1797         /* Y coordinate data (passing VREF values) for approach vectors */
1798         uint8_t y_coordinate[2][2][NUM_CHANNELS][NUM_BYTE_LANES];
1799         /* centered X (RDQS) */
1800         uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
1801         /* centered Y (VREF) */
1802         uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES];
1803         uint32_t address;       /* target address for check_bls_ex() */
1804         uint32_t result;        /* result of check_bls_ex() */
1805         uint32_t bl_mask;       /* byte lane mask for result checking */
1806 #ifdef R2R_SHARING
1807         /* used to find placement for rank2rank sharing configs */
1808         uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1809         /* used to find placement for rank2rank sharing configs */
1810         uint32_t num_ranks_enabled = 0;
1811 #endif
1812 #endif
1813
1814         /* rd_train starts */
1815         mrc_post_code(0x07, 0x00);
1816
1817         ENTERFN();
1818
1819 #ifdef BACKUP_RDQS
1820         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1821                 if (mrc_params->channel_enables & (1 << ch)) {
1822                         for (rk = 0; rk < NUM_RANKS; rk++) {
1823                                 if (mrc_params->rank_enables & (1 << rk)) {
1824                                         for (bl = 0;
1825                                              bl < NUM_BYTE_LANES / bl_divisor;
1826                                              bl++) {
1827                                                 set_rdqs(ch, rk, bl, ddr_rdqs[PLATFORM_ID]);
1828                                         }
1829                                 }
1830                         }
1831                 }
1832         }
1833 #else
1834         /* initialize x/y_coordinate arrays */
1835         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1836                 if (mrc_params->channel_enables & (1 << ch)) {
1837                         for (rk = 0; rk < NUM_RANKS; rk++) {
1838                                 if (mrc_params->rank_enables & (1 << rk)) {
1839                                         for (bl = 0;
1840                                              bl < NUM_BYTE_LANES / bl_divisor;
1841                                              bl++) {
1842                                                 /* x_coordinate */
1843                                                 x_coordinate[L][B][ch][rk][bl] = RDQS_MIN;
1844                                                 x_coordinate[R][B][ch][rk][bl] = RDQS_MAX;
1845                                                 x_coordinate[L][T][ch][rk][bl] = RDQS_MIN;
1846                                                 x_coordinate[R][T][ch][rk][bl] = RDQS_MAX;
1847                                                 /* y_coordinate */
1848                                                 y_coordinate[L][B][ch][bl] = VREF_MIN;
1849                                                 y_coordinate[R][B][ch][bl] = VREF_MIN;
1850                                                 y_coordinate[L][T][ch][bl] = VREF_MAX;
1851                                                 y_coordinate[R][T][ch][bl] = VREF_MAX;
1852                                         }
1853                                 }
1854                         }
1855                 }
1856         }
1857
1858         /* initialize other variables */
1859         bl_mask = byte_lane_mask(mrc_params);
1860         address = get_addr(0, 0);
1861
1862 #ifdef R2R_SHARING
1863         /* need to set "final_delay[][]" elements to "0" */
1864         memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1865 #endif
1866
1867         /* look for passing coordinates */
1868         for (side_y = B; side_y <= T; side_y++) {
1869                 for (side_x = L; side_x <= R; side_x++) {
1870                         mrc_post_code(0x07, 0x10 + side_y * 2 + side_x);
1871
1872                         /* find passing values */
1873                         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1874                                 if (mrc_params->channel_enables & (0x1 << ch)) {
1875                                         for (rk = 0; rk < NUM_RANKS; rk++) {
1876                                                 if (mrc_params->rank_enables &
1877                                                         (0x1 << rk)) {
1878                                                         /* set x/y_coordinate search starting settings */
1879                                                         for (bl = 0;
1880                                                              bl < NUM_BYTE_LANES / bl_divisor;
1881                                                              bl++) {
1882                                                                 set_rdqs(ch, rk, bl,
1883                                                                          x_coordinate[side_x][side_y][ch][rk][bl]);
1884                                                                 set_vref(ch, bl,
1885                                                                          y_coordinate[side_x][side_y][ch][bl]);
1886                                                         }
1887
1888                                                         /* get an address in the target channel/rank */
1889                                                         address = get_addr(ch, rk);
1890
1891                                                         /* request HTE reconfiguration */
1892                                                         mrc_params->hte_setup = 1;
1893
1894                                                         /* test the settings */
1895                                                         do {
1896                                                                 /* result[07:00] == failing byte lane (MAX 8) */
1897                                                                 result = check_bls_ex(mrc_params, address);
1898
1899                                                                 /* check for failures */
1900                                                                 if (result & 0xff) {
1901                                                                         /* at least 1 byte lane failed */
1902                                                                         for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
1903                                                                                 if (result &
1904                                                                                         (bl_mask << bl)) {
1905                                                                                         /* adjust the RDQS values accordingly */
1906                                                                                         if (side_x == L)
1907                                                                                                 x_coordinate[L][side_y][ch][rk][bl] += RDQS_STEP;
1908                                                                                         else
1909                                                                                                 x_coordinate[R][side_y][ch][rk][bl] -= RDQS_STEP;
1910
1911                                                                                         /* check that we haven't closed the RDQS_EYE too much */
1912                                                                                         if ((x_coordinate[L][side_y][ch][rk][bl] > (RDQS_MAX - MIN_RDQS_EYE)) ||
1913                                                                                                 (x_coordinate[R][side_y][ch][rk][bl] < (RDQS_MIN + MIN_RDQS_EYE)) ||
1914                                                                                                 (x_coordinate[L][side_y][ch][rk][bl] ==
1915                                                                                                 x_coordinate[R][side_y][ch][rk][bl])) {
1916                                                                                                 /*
1917                                                                                                  * not enough RDQS margin available at this VREF
1918                                                                                                  * update VREF values accordingly
1919                                                                                                  */
1920                                                                                                 if (side_y == B)
1921                                                                                                         y_coordinate[side_x][B][ch][bl] += VREF_STEP;
1922                                                                                                 else
1923                                                                                                         y_coordinate[side_x][T][ch][bl] -= VREF_STEP;
1924
1925                                                                                                 /* check that we haven't closed the VREF_EYE too much */
1926                                                                                                 if ((y_coordinate[side_x][B][ch][bl] > (VREF_MAX - MIN_VREF_EYE)) ||
1927                                                                                                         (y_coordinate[side_x][T][ch][bl] < (VREF_MIN + MIN_VREF_EYE)) ||
1928                                                                                                         (y_coordinate[side_x][B][ch][bl] == y_coordinate[side_x][T][ch][bl])) {
1929                                                                                                         /* VREF_EYE collapsed below MIN_VREF_EYE */
1930                                                                                                         training_message(ch, rk, bl);
1931                                                                                                         mrc_post_code(0xEE, 0x70 + side_y * 2 + side_x);
1932                                                                                                 } else {
1933                                                                                                         /* update the VREF setting */
1934                                                                                                         set_vref(ch, bl, y_coordinate[side_x][side_y][ch][bl]);
1935                                                                                                         /* reset the X coordinate to begin the search at the new VREF */
1936                                                                                                         x_coordinate[side_x][side_y][ch][rk][bl] =
1937                                                                                                                 (side_x == L) ? RDQS_MIN : RDQS_MAX;
1938                                                                                                 }
1939                                                                                         }
1940
1941                                                                                         /* update the RDQS setting */
1942                                                                                         set_rdqs(ch, rk, bl, x_coordinate[side_x][side_y][ch][rk][bl]);
1943                                                                                 }
1944                                                                         }
1945                                                                 }
1946                                                         } while (result & 0xff);
1947                                                 }
1948                                         }
1949                                 }
1950                         }
1951                 }
1952         }
1953
1954         mrc_post_code(0x07, 0x20);
1955
1956         /* find final RDQS (X coordinate) & final VREF (Y coordinate) */
1957         for (ch = 0; ch < NUM_CHANNELS; ch++) {
1958                 if (mrc_params->channel_enables & (1 << ch)) {
1959                         for (rk = 0; rk < NUM_RANKS; rk++) {
1960                                 if (mrc_params->rank_enables & (1 << rk)) {
1961                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1962                                                 uint32_t temp1;
1963                                                 uint32_t temp2;
1964
1965                                                 /* x_coordinate */
1966                                                 DPF(D_INFO,
1967                                                     "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n",
1968                                                     rk, bl,
1969                                                     x_coordinate[L][T][ch][rk][bl],
1970                                                     x_coordinate[R][T][ch][rk][bl],
1971                                                     x_coordinate[L][B][ch][rk][bl],
1972                                                     x_coordinate[R][B][ch][rk][bl]);
1973
1974                                                 /* average the TOP side LEFT & RIGHT values */
1975                                                 temp1 = (x_coordinate[R][T][ch][rk][bl] + x_coordinate[L][T][ch][rk][bl]) / 2;
1976                                                 /* average the BOTTOM side LEFT & RIGHT values */
1977                                                 temp2 = (x_coordinate[R][B][ch][rk][bl] + x_coordinate[L][B][ch][rk][bl]) / 2;
1978                                                 /* average the above averages */
1979                                                 x_center[ch][rk][bl] = (uint8_t) ((temp1 + temp2) / 2);
1980
1981                                                 /* y_coordinate */
1982                                                 DPF(D_INFO,
1983                                                     "VREF R/L eye lane%d : %d-%d %d-%d\n",
1984                                                     bl,
1985                                                     y_coordinate[R][B][ch][bl],
1986                                                     y_coordinate[R][T][ch][bl],
1987                                                     y_coordinate[L][B][ch][bl],
1988                                                     y_coordinate[L][T][ch][bl]);
1989
1990                                                 /* average the RIGHT side TOP & BOTTOM values */
1991                                                 temp1 = (y_coordinate[R][T][ch][bl] + y_coordinate[R][B][ch][bl]) / 2;
1992                                                 /* average the LEFT side TOP & BOTTOM values */
1993                                                 temp2 = (y_coordinate[L][T][ch][bl] + y_coordinate[L][B][ch][bl]) / 2;
1994                                                 /* average the above averages */
1995                                                 y_center[ch][bl] = (uint8_t) ((temp1 + temp2) / 2);
1996                                         }
1997                                 }
1998                         }
1999                 }
2000         }
2001
2002 #ifdef RX_EYE_CHECK
2003         /* perform an eye check */
2004         for (side_y = B; side_y <= T; side_y++) {
2005                 for (side_x = L; side_x <= R; side_x++) {
2006                         mrc_post_code(0x07, 0x30 + side_y * 2 + side_x);
2007
2008                         /* update the settings for the eye check */
2009                         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2010                                 if (mrc_params->channel_enables & (1 << ch)) {
2011                                         for (rk = 0; rk < NUM_RANKS; rk++) {
2012                                                 if (mrc_params->rank_enables & (1 << rk)) {
2013                                                         for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
2014                                                                 if (side_x == L)
2015                                                                         set_rdqs(ch, rk, bl, x_center[ch][rk][bl] - (MIN_RDQS_EYE / 2));
2016                                                                 else
2017                                                                         set_rdqs(ch, rk, bl, x_center[ch][rk][bl] + (MIN_RDQS_EYE / 2));
2018
2019                                                                 if (side_y == B)
2020                                                                         set_vref(ch, bl, y_center[ch][bl] - (MIN_VREF_EYE / 2));
2021                                                                 else
2022                                                                         set_vref(ch, bl, y_center[ch][bl] + (MIN_VREF_EYE / 2));
2023                                                         }
2024                                                 }
2025                                         }
2026                                 }
2027                         }
2028
2029                         /* request HTE reconfiguration */
2030                         mrc_params->hte_setup = 1;
2031
2032                         /* check the eye */
2033                         if (check_bls_ex(mrc_params, address) & 0xff) {
2034                                 /* one or more byte lanes failed */
2035                                 mrc_post_code(0xee, 0x74 + side_x * 2 + side_y);
2036                         }
2037                 }
2038         }
2039 #endif
2040
2041         mrc_post_code(0x07, 0x40);
2042
2043         /* set final placements */
2044         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2045                 if (mrc_params->channel_enables & (1 << ch)) {
2046                         for (rk = 0; rk < NUM_RANKS; rk++) {
2047                                 if (mrc_params->rank_enables & (1 << rk)) {
2048 #ifdef R2R_SHARING
2049                                         /* increment "num_ranks_enabled" */
2050                                         num_ranks_enabled++;
2051 #endif
2052                                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
2053                                                 /* x_coordinate */
2054 #ifdef R2R_SHARING
2055                                                 final_delay[ch][bl] += x_center[ch][rk][bl];
2056                                                 set_rdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
2057 #else
2058                                                 set_rdqs(ch, rk, bl, x_center[ch][rk][bl]);
2059 #endif
2060                                                 /* y_coordinate */
2061                                                 set_vref(ch, bl, y_center[ch][bl]);
2062                                         }
2063                                 }
2064                         }
2065                 }
2066         }
2067 #endif
2068
2069         LEAVEFN();
2070 }
2071
2072 /*
2073  * This function will perform the WRITE TRAINING Algorithm on all
2074  * channels/ranks/byte_lanes simultaneously to minimize execution time.
2075  *
2076  * The idea here is to train the WDQ timings to achieve maximum WRITE margins.
2077  * The algorithm will start with WDQ at the current WDQ setting (tracks WDQS
2078  * in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data
2079  * patterns pass. This is because WDQS will be aligned to WCLK by the
2080  * Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window
2081  * of validity.
2082  */
2083 void wr_train(struct mrc_params *mrc_params)
2084 {
2085         uint8_t ch;     /* channel counter */
2086         uint8_t rk;     /* rank counter */
2087         uint8_t bl;     /* byte lane counter */
2088         uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
2089 #ifdef BACKUP_WDQ
2090 #else
2091         uint8_t side;           /* LEFT/RIGHT side indicator (0=L, 1=R) */
2092         uint32_t temp;          /* temporary DWORD */
2093         /* 2 arrays, for L & R side passing delays */
2094         uint32_t delay[2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
2095         uint32_t address;       /* target address for check_bls_ex() */
2096         uint32_t result;        /* result of check_bls_ex() */
2097         uint32_t bl_mask;       /* byte lane mask for result checking */
2098 #ifdef R2R_SHARING
2099         /* used to find placement for rank2rank sharing configs */
2100         uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
2101         /* used to find placement for rank2rank sharing configs */
2102         uint32_t num_ranks_enabled = 0;
2103 #endif
2104 #endif
2105
2106         /* wr_train starts */
2107         mrc_post_code(0x08, 0x00);
2108
2109         ENTERFN();
2110
2111 #ifdef BACKUP_WDQ
2112         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2113                 if (mrc_params->channel_enables & (1 << ch)) {
2114                         for (rk = 0; rk < NUM_RANKS; rk++) {
2115                                 if (mrc_params->rank_enables & (1 << rk)) {
2116                                         for (bl = 0;
2117                                              bl < NUM_BYTE_LANES / bl_divisor;
2118                                              bl++) {
2119                                                 set_wdq(ch, rk, bl, ddr_wdq[PLATFORM_ID]);
2120                                         }
2121                                 }
2122                         }
2123                 }
2124         }
2125 #else
2126         /* initialize "delay" */
2127         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2128                 if (mrc_params->channel_enables & (1 << ch)) {
2129                         for (rk = 0; rk < NUM_RANKS; rk++) {
2130                                 if (mrc_params->rank_enables & (1 << rk)) {
2131                                         for (bl = 0;
2132                                              bl < NUM_BYTE_LANES / bl_divisor;
2133                                              bl++) {
2134                                                 /*
2135                                                  * want to start with
2136                                                  * WDQ = (WDQS - QRTR_CLK)
2137                                                  * +/- QRTR_CLK
2138                                                  */
2139                                                 temp = get_wdqs(ch, rk, bl) - QRTR_CLK;
2140                                                 delay[L][ch][rk][bl] = temp - QRTR_CLK;
2141                                                 delay[R][ch][rk][bl] = temp + QRTR_CLK;
2142                                         }
2143                                 }
2144                         }
2145                 }
2146         }
2147
2148         /* initialize other variables */
2149         bl_mask = byte_lane_mask(mrc_params);
2150         address = get_addr(0, 0);
2151
2152 #ifdef R2R_SHARING
2153         /* need to set "final_delay[][]" elements to "0" */
2154         memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
2155 #endif
2156
2157         /*
2158          * start algorithm on the LEFT side and train each channel/bl
2159          * until no failures are observed, then repeat for the RIGHT side.
2160          */
2161         for (side = L; side <= R; side++) {
2162                 mrc_post_code(0x08, 0x10 + side);
2163
2164                 /* set starting values */
2165                 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2166                         if (mrc_params->channel_enables & (1 << ch)) {
2167                                 for (rk = 0; rk < NUM_RANKS; rk++) {
2168                                         if (mrc_params->rank_enables &
2169                                                 (1 << rk)) {
2170                                                 for (bl = 0;
2171                                                      bl < NUM_BYTE_LANES / bl_divisor;
2172                                                      bl++) {
2173                                                         set_wdq(ch, rk, bl, delay[side][ch][rk][bl]);
2174                                                 }
2175                                         }
2176                                 }
2177                         }
2178                 }
2179
2180                 /* find passing values */
2181                 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2182                         if (mrc_params->channel_enables & (1 << ch)) {
2183                                 for (rk = 0; rk < NUM_RANKS; rk++) {
2184                                         if (mrc_params->rank_enables &
2185                                                 (1 << rk)) {
2186                                                 /* get an address in the target channel/rank */
2187                                                 address = get_addr(ch, rk);
2188
2189                                                 /* request HTE reconfiguration */
2190                                                 mrc_params->hte_setup = 1;
2191
2192                                                 /* check the settings */
2193                                                 do {
2194                                                         /* result[07:00] == failing byte lane (MAX 8) */
2195                                                         result = check_bls_ex(mrc_params, address);
2196                                                         /* check for failures */
2197                                                         if (result & 0xff) {
2198                                                                 /* at least 1 byte lane failed */
2199                                                                 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
2200                                                                         if (result &
2201                                                                                 (bl_mask << bl)) {
2202                                                                                 if (side == L)
2203                                                                                         delay[L][ch][rk][bl] += WDQ_STEP;
2204                                                                                 else
2205                                                                                         delay[R][ch][rk][bl] -= WDQ_STEP;
2206
2207                                                                                 /* check for algorithm failure */
2208                                                                                 if (delay[L][ch][rk][bl] != delay[R][ch][rk][bl]) {
2209                                                                                         /*
2210                                                                                          * margin available
2211                                                                                          * update delay setting
2212                                                                                          */
2213                                                                                         set_wdq(ch, rk, bl,
2214                                                                                                 delay[side][ch][rk][bl]);
2215                                                                                 } else {
2216                                                                                         /*
2217                                                                                          * no margin available
2218                                                                                          * notify the user and halt
2219                                                                                          */
2220                                                                                         training_message(ch, rk, bl);
2221                                                                                         mrc_post_code(0xee, 0x80 + side);
2222                                                                                 }
2223                                                                         }
2224                                                                 }
2225                                                         }
2226                                                 /* stop when all byte lanes pass */
2227                                                 } while (result & 0xff);
2228                                         }
2229                                 }
2230                         }
2231                 }
2232         }
2233
2234         /* program WDQ to the middle of passing window */
2235         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2236                 if (mrc_params->channel_enables & (1 << ch)) {
2237                         for (rk = 0; rk < NUM_RANKS; rk++) {
2238                                 if (mrc_params->rank_enables & (1 << rk)) {
2239 #ifdef R2R_SHARING
2240                                         /* increment "num_ranks_enabled" */
2241                                         num_ranks_enabled++;
2242 #endif
2243                                         for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
2244                                                 DPF(D_INFO,
2245                                                     "WDQ eye rank%d lane%d : %d-%d\n",
2246                                                     rk, bl,
2247                                                     delay[L][ch][rk][bl],
2248                                                     delay[R][ch][rk][bl]);
2249
2250                                                 temp = (delay[R][ch][rk][bl] + delay[L][ch][rk][bl]) / 2;
2251
2252 #ifdef R2R_SHARING
2253                                                 final_delay[ch][bl] += temp;
2254                                                 set_wdq(ch, rk, bl,
2255                                                         final_delay[ch][bl] / num_ranks_enabled);
2256 #else
2257                                                 set_wdq(ch, rk, bl, temp);
2258 #endif
2259                                         }
2260                                 }
2261                         }
2262                 }
2263         }
2264 #endif
2265
2266         LEAVEFN();
2267 }
2268
2269 /*
2270  * This function will store relevant timing data
2271  *
2272  * This data will be used on subsequent boots to speed up boot times
2273  * and is required for Suspend To RAM capabilities.
2274  */
2275 void store_timings(struct mrc_params *mrc_params)
2276 {
2277         uint8_t ch, rk, bl;
2278         struct mrc_timings *mt = &mrc_params->timings;
2279
2280         for (ch = 0; ch < NUM_CHANNELS; ch++) {
2281                 for (rk = 0; rk < NUM_RANKS; rk++) {
2282                         for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
2283                                 mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl);
2284                                 mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl);
2285                                 mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl);
2286                                 mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);
2287
2288                                 if (rk == 0)
2289                                         mt->vref[ch][bl] = get_vref(ch, bl);
2290                         }
2291
2292                         mt->wctl[ch][rk] = get_wctl(ch, rk);
2293                 }
2294
2295                 mt->wcmd[ch] = get_wcmd(ch);
2296         }
2297
2298         /* need to save for a case of changing frequency after warm reset */
2299         mt->ddr_speed = mrc_params->ddr_speed;
2300 }
2301
2302 /*
2303  * The purpose of this function is to ensure the SEC comes out of reset
2304  * and IA initiates the SEC enabling Memory Scrambling.
2305  */
2306 void enable_scrambling(struct mrc_params *mrc_params)
2307 {
2308         uint32_t lfsr = 0;
2309         uint8_t i;
2310
2311         if (mrc_params->scrambling_enables == 0)
2312                 return;
2313
2314         ENTERFN();
2315
2316         /* 32 bit seed is always stored in BIOS NVM */
2317         lfsr = mrc_params->timings.scrambler_seed;
2318
2319         if (mrc_params->boot_mode == BM_COLD) {
2320                 /*
2321                  * factory value is 0 and in first boot,
2322                  * a clock based seed is loaded.
2323                  */
2324                 if (lfsr == 0) {
2325                         /*
2326                          * get seed from system clock
2327                          * and make sure it is not all 1's
2328                          */
2329                         lfsr = rdtsc() & 0x0fffffff;
2330                 } else {
2331                         /*
2332                          * Need to replace scrambler
2333                          *
2334                          * get next 32bit LFSR 16 times which is the last
2335                          * part of the previous scrambler vector
2336                          */
2337                         for (i = 0; i < 16; i++)
2338                                 lfsr32(&lfsr);
2339                 }
2340
2341                 /* save new seed */
2342                 mrc_params->timings.scrambler_seed = lfsr;
2343         }
2344
2345         /*
2346          * In warm boot or S3 exit, we have the previous seed.
2347          * In cold boot, we have the last 32bit LFSR which is the new seed.
2348          */
2349         lfsr32(&lfsr);  /* shift to next value */
2350         msg_port_write(MEM_CTLR, SCRMSEED, (lfsr & 0x0003ffff));
2351
2352         for (i = 0; i < 2; i++)
2353                 msg_port_write(MEM_CTLR, SCRMLO + i, (lfsr & 0xaaaaaaaa));
2354
2355         LEAVEFN();
2356 }
2357
2358 /*
2359  * Configure MCU Power Management Control Register
2360  * and Scheduler Control Register
2361  */
2362 void prog_ddr_control(struct mrc_params *mrc_params)
2363 {
2364         u32 dsch;
2365         u32 dpmc0;
2366
2367         ENTERFN();
2368
2369         dsch = msg_port_read(MEM_CTLR, DSCH);
2370         dsch &= ~(DSCH_OOODIS | DSCH_OOOST3DIS | DSCH_NEWBYPDIS);
2371         msg_port_write(MEM_CTLR, DSCH, dsch);
2372
2373         dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
2374         dpmc0 &= ~DPMC0_DISPWRDN;
2375         dpmc0 |= (mrc_params->power_down_disable << 25);
2376         dpmc0 &= ~DPMC0_CLKGTDIS;
2377         dpmc0 &= ~DPMC0_PCLSTO_MASK;
2378         dpmc0 |= (4 << 16);
2379         dpmc0 |= DPMC0_PREAPWDEN;
2380         msg_port_write(MEM_CTLR, DPMC0, dpmc0);
2381
2382         /* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
2383         mrc_write_mask(MEM_CTLR, DPMC1, 0x20, 0x30);
2384
2385         LEAVEFN();
2386 }
2387
2388 /*
2389  * After training complete configure MCU Rank Population Register
2390  * specifying: ranks enabled, device width, density, address mode
2391  */
2392 void prog_dra_drb(struct mrc_params *mrc_params)
2393 {
2394         u32 drp;
2395         u32 dco;
2396         u8 density = mrc_params->params.density;
2397
2398         ENTERFN();
2399
2400         dco = msg_port_read(MEM_CTLR, DCO);
2401         dco &= ~DCO_IC;
2402         msg_port_write(MEM_CTLR, DCO, dco);
2403
2404         drp = 0;
2405         if (mrc_params->rank_enables & 1)
2406                 drp |= DRP_RKEN0;
2407         if (mrc_params->rank_enables & 2)
2408                 drp |= DRP_RKEN1;
2409         if (mrc_params->dram_width == X16) {
2410                 drp |= (1 << 4);
2411                 drp |= (1 << 9);
2412         }
2413
2414         /*
2415          * Density encoding in struct dram_params: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
2416          * has to be mapped RANKDENSx encoding (0=1Gb)
2417          */
2418         if (density == 0)
2419                 density = 4;
2420
2421         drp |= ((density - 1) << 6);
2422         drp |= ((density - 1) << 11);
2423
2424         /* Address mode can be overwritten if ECC enabled */
2425         drp |= (mrc_params->address_mode << 14);
2426
2427         msg_port_write(MEM_CTLR, DRP, drp);
2428
2429         dco &= ~DCO_PMICTL;
2430         dco |= DCO_IC;
2431         msg_port_write(MEM_CTLR, DCO, dco);
2432
2433         LEAVEFN();
2434 }
2435
2436 /* Send DRAM wake command */
2437 void perform_wake(struct mrc_params *mrc_params)
2438 {
2439         ENTERFN();
2440
2441         dram_wake_command();
2442
2443         LEAVEFN();
2444 }
2445
2446 /*
2447  * Configure refresh rate and short ZQ calibration interval
2448  * Activate dynamic self refresh
2449  */
2450 void change_refresh_period(struct mrc_params *mrc_params)
2451 {
2452         u32 drfc;
2453         u32 dcal;
2454         u32 dpmc0;
2455
2456         ENTERFN();
2457
2458         drfc = msg_port_read(MEM_CTLR, DRFC);
2459         drfc &= ~DRFC_TREFI_MASK;
2460         drfc |= (mrc_params->refresh_rate << 12);
2461         drfc |= DRFC_REFDBTCLR;
2462         msg_port_write(MEM_CTLR, DRFC, drfc);
2463
2464         dcal = msg_port_read(MEM_CTLR, DCAL);
2465         dcal &= ~DCAL_ZQCINT_MASK;
2466         dcal |= (3 << 8);       /* 63ms */
2467         msg_port_write(MEM_CTLR, DCAL, dcal);
2468
2469         dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
2470         dpmc0 |= (DPMC0_DYNSREN | DPMC0_ENPHYCLKGATE);
2471         msg_port_write(MEM_CTLR, DPMC0, dpmc0);
2472
2473         LEAVEFN();
2474 }
2475
2476 /*
2477  * Configure DDRPHY for Auto-Refresh, Periodic Compensations,
2478  * Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
2479  */
2480 void set_auto_refresh(struct mrc_params *mrc_params)
2481 {
2482         uint32_t channel;
2483         uint32_t rank;
2484         uint32_t bl;
2485         uint32_t bl_divisor = 1;
2486         uint32_t temp;
2487
2488         ENTERFN();
2489
2490         /*
2491          * Enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp,
2492          * ZQSPERIOD, Auto-Precharge, CKE Power-Down
2493          */
2494         for (channel = 0; channel < NUM_CHANNELS; channel++) {
2495                 if (mrc_params->channel_enables & (1 << channel)) {
2496                         /* Enable Periodic RCOMPS */
2497                         mrc_alt_write_mask(DDRPHY, CMPCTRL, 2, 2);
2498
2499                         /* Enable Dynamic DiffAmp & Set Read ODT Value */
2500                         switch (mrc_params->rd_odt_value) {
2501                         case 0:
2502                                 temp = 0x3f;    /* OFF */
2503                                 break;
2504                         default:
2505                                 temp = 0x00;    /* Auto */
2506                                 break;
2507                         }
2508
2509                         for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
2510                                 /* Override: DIFFAMP, ODT */
2511                                 mrc_alt_write_mask(DDRPHY,
2512                                         B0OVRCTL + bl * DDRIODQ_BL_OFFSET +
2513                                         channel * DDRIODQ_CH_OFFSET,
2514                                         temp << 10,
2515                                         0x003ffc00);
2516
2517                                 /* Override: DIFFAMP, ODT */
2518                                 mrc_alt_write_mask(DDRPHY,
2519                                         B1OVRCTL + bl * DDRIODQ_BL_OFFSET +
2520                                         channel * DDRIODQ_CH_OFFSET,
2521                                         temp << 10,
2522                                         0x003ffc00);
2523                         }
2524
2525                         /* Issue ZQCS command */
2526                         for (rank = 0; rank < NUM_RANKS; rank++) {
2527                                 if (mrc_params->rank_enables & (1 << rank))
2528                                         dram_init_command(DCMD_ZQCS(rank));
2529                         }
2530                 }
2531         }
2532
2533         clear_pointers();
2534
2535         LEAVEFN();
2536 }
2537
2538 /*
2539  * Depending on configuration enables ECC support
2540  *
2541  * Available memory size is decreased, and updated with 0s
2542  * in order to clear error status. Address mode 2 forced.
2543  */
2544 void ecc_enable(struct mrc_params *mrc_params)
2545 {
2546         u32 drp;
2547         u32 dsch;
2548         u32 ecc_ctrl;
2549
2550         if (mrc_params->ecc_enables == 0)
2551                 return;
2552
2553         ENTERFN();
2554
2555         /* Configuration required in ECC mode */
2556         drp = msg_port_read(MEM_CTLR, DRP);
2557         drp &= ~DRP_ADDRMAP_MASK;
2558         drp |= DRP_ADDRMAP_MAP1;
2559         drp |= DRP_PRI64BSPLITEN;
2560         msg_port_write(MEM_CTLR, DRP, drp);
2561
2562         /* Disable new request bypass */
2563         dsch = msg_port_read(MEM_CTLR, DSCH);
2564         dsch |= DSCH_NEWBYPDIS;
2565         msg_port_write(MEM_CTLR, DSCH, dsch);
2566
2567         /* Enable ECC */
2568         ecc_ctrl = (DECCCTRL_SBEEN | DECCCTRL_DBEEN | DECCCTRL_ENCBGEN);
2569         msg_port_write(MEM_CTLR, DECCCTRL, ecc_ctrl);
2570
2571         /* Assume 8 bank memory, one bank is gone for ECC */
2572         mrc_params->mem_size -= mrc_params->mem_size / 8;
2573
2574         /* For S3 resume memory content has to be preserved */
2575         if (mrc_params->boot_mode != BM_S3) {
2576                 select_hte();
2577                 hte_mem_init(mrc_params, MRC_MEM_INIT);
2578                 select_mem_mgr();
2579         }
2580
2581         LEAVEFN();
2582 }
2583
2584 /*
2585  * Execute memory test
2586  * if error detected it is indicated in mrc_params->status
2587  */
2588 void memory_test(struct mrc_params *mrc_params)
2589 {
2590         uint32_t result = 0;
2591
2592         ENTERFN();
2593
2594         select_hte();
2595         result = hte_mem_init(mrc_params, MRC_MEM_TEST);
2596         select_mem_mgr();
2597
2598         DPF(D_INFO, "Memory test result %x\n", result);
2599         mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);
2600         LEAVEFN();
2601 }
2602
2603 /* Lock MCU registers at the end of initialization sequence */
2604 void lock_registers(struct mrc_params *mrc_params)
2605 {
2606         u32 dco;
2607
2608         ENTERFN();
2609
2610         dco = msg_port_read(MEM_CTLR, DCO);
2611         dco &= ~(DCO_PMICTL | DCO_PMIDIS);
2612         dco |= (DCO_DRPLOCK | DCO_CPGCLOCK);
2613         msg_port_write(MEM_CTLR, DCO, dco);
2614
2615         LEAVEFN();
2616 }