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