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