]>
git.ipfire.org Git - people/ms/u-boot.git/blob - arch/x86/cpu/quark/smc.c
2 * Copyright (C) 2013, Intel Corporation
3 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
5 * Ported from Intel released Quark UEFI BIOS
6 * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
8 * SPDX-License-Identifier: Intel
13 #include <asm/arch/device.h>
14 #include <asm/arch/mrc.h>
15 #include <asm/arch/msg_port.h>
20 /* t_rfc values (in picoseconds) per density */
21 static const uint32_t t_rfc
[5] = {
29 /* t_ck clock period in picoseconds per speed index 800, 1066, 1333 */
30 static const uint32_t t_ck
[3] = {
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};
42 static const uint16_t ddr_rcvn
[] = {129, 498};
46 static const uint16_t ddr_wdqs
[] = {65, 289};
50 static const uint8_t ddr_rdqs
[] = {32, 24};
54 static const uint16_t ddr_wdq
[] = {32, 257};
57 /* Stop self refresh driven by MCU */
58 void clear_self_refresh(struct mrc_params
*mrc_params
)
62 /* clear the PMSTS Channel Self Refresh bits */
63 mrc_write_mask(MEM_CTLR
, PMSTS
, BIT0
, BIT0
);
68 /* It will initialize timing registers in the MCU (DTR0..DTR4) */
69 void prog_ddr_timing_control(struct mrc_params
*mrc_params
)
72 uint8_t trp
, trcd
, tras
, twr
, twtr
, trrd
, trtp
, tfaw
;
74 u32 dtr0
, dtr1
, dtr2
, dtr3
, dtr4
;
80 mrc_post_code(0x02, 0x00);
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
);
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
);
94 /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
95 twr
= MCEIL(15000, tck
);
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
);
102 wl
= 5 + mrc_params
->ddr_speed
;
104 dtr0
&= ~(BIT0
| BIT1
);
105 dtr0
|= mrc_params
->ddr_speed
;
106 dtr0
&= ~(BIT12
| BIT13
| BIT14
);
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 */
114 dtr1
&= ~(BIT0
| BIT1
| BIT2
);
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
);
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
);
132 dtr2
&= ~(BIT0
| BIT1
| BIT2
);
134 dtr2
&= ~(BIT8
| BIT9
| BIT10
);
136 dtr2
&= ~(BIT16
| BIT17
| BIT18
| BIT19
);
139 dtr3
&= ~(BIT0
| BIT1
| BIT2
);
141 dtr3
&= ~(BIT4
| BIT5
| BIT6
);
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);
153 dtr3
&= ~(BIT13
| BIT14
| BIT15
| BIT16
);
154 dtr3
|= ((4 + wl
+ twtr
- 11) << 13);
156 dtr3
&= ~(BIT22
| BIT23
);
157 if (mrc_params
->ddr_speed
== DDRFREQ_800
)
158 dtr3
|= ((MMAX(0, 1 - 1)) << 22);
160 dtr3
|= ((MMAX(0, 2 - 1)) << 22);
162 dtr4
&= ~(BIT0
| BIT1
);
164 dtr4
&= ~(BIT4
| BIT5
| BIT6
);
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
);
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
);
181 /* Configure MCU before jedec init sequence */
182 void prog_decode_before_jedec(struct mrc_params
*mrc_params
)
192 /* Disable power saving features */
193 dpmc0
= msg_port_read(MEM_CTLR
, DPMC0
);
194 dpmc0
|= (BIT24
| BIT25
);
195 dpmc0
&= ~(BIT16
| BIT17
| BIT18
);
197 msg_port_write(MEM_CTLR
, DPMC0
, dpmc0
);
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
);
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
);
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
);
216 * Training performed in address mode 0, rank population has limited
217 * impact, however simulator complains if enabled non-existing rank.
220 if (mrc_params
->rank_enables
& 1)
222 if (mrc_params
->rank_enables
& 2)
224 msg_port_write(MEM_CTLR
, DRP
, drp
);
230 * After Cold Reset, BIOS should set COLDWAKE bit to 1 before
231 * sending the WAKE message to the Dunit.
233 * For Standby Exit, or any other mode in which the DRAM is in
234 * SR, this bit must be set to 0.
236 void perform_ddr_reset(struct mrc_params
*mrc_params
)
240 /* Set COLDWAKE bit before sending the WAKE message */
241 mrc_write_mask(MEM_CTLR
, DRMC
, BIT16
, BIT16
);
243 /* Send wake command to DUNIT (MUST be done before JEDEC) */
246 /* Set default value */
247 msg_port_write(MEM_CTLR
, DRMC
,
248 (mrc_params
->rd_odt_value
== 0 ? BIT12
: 0));
255 * This function performs some initialization on the DDRIO unit.
256 * This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
258 void ddrphy_init(struct mrc_params
*mrc_params
)
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
);
272 cas
= mrc_params
->params
.cl
;
273 cwl
= 5 + mrc_params
->ddr_speed
;
275 /* ddrphy_init starts */
276 mrc_post_code(0x03, 0x00);
280 * Make sure IOBUFACT is deasserted before initializing the DDR PHY
283 * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
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 */
296 mrc_alt_write_mask(DDRPHY
,
297 (CMDPTRREG
+ (ch
* DDRIOCCC_CH_OFFSET
)),
298 ~BIT0
, BIT0
); /* WRPTRENABLE=0 */
302 /* Put PHY in reset */
303 mrc_alt_write_mask(DDRPHY
, MASTERRSTN
, 0, BIT0
);
305 /* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */
308 mrc_post_code(0x03, 0x10);
309 for (ch
= 0; ch
< NUM_CHANNELS
; ch
++) {
310 if (mrc_params
->channel_enables
& (1 << ch
)) {
313 bl_grp
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2);
315 /* Analog MUX select - IO2xCLKSEL */
316 mrc_alt_write_mask(DDRPHY
,
318 (bl_grp
* DDRIODQ_BL_OFFSET
) +
319 (ch
* DDRIODQ_CH_OFFSET
)),
320 ((bl_grp
) ? (0x00) : (BIT22
)), (BIT22
));
323 switch (mrc_params
->rd_odt_value
) {
339 mrc_alt_write_mask(DDRPHY
,
341 (bl_grp
* DDRIODQ_BL_OFFSET
) +
342 (ch
* DDRIODQ_CH_OFFSET
)),
343 (temp
<< 5), (BIT6
| BIT5
));
345 mrc_alt_write_mask(DDRPHY
,
347 (bl_grp
* DDRIODQ_BL_OFFSET
) +
348 (ch
* DDRIODQ_CH_OFFSET
)),
349 (temp
<< 5), (BIT6
| BIT5
));
351 /* Dynamic ODT/DIFFAMP */
352 temp
= (((cas
) << 24) | ((cas
) << 16) |
353 ((cas
) << 8) | ((cas
) << 0));
369 /* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
370 mrc_alt_write_mask(DDRPHY
,
372 (bl_grp
* DDRIODQ_BL_OFFSET
) +
373 (ch
* DDRIODQ_CH_OFFSET
)),
375 (BIT28
| BIT27
| BIT26
| BIT25
| BIT24
|
376 BIT20
| BIT19
| BIT18
| BIT17
| BIT16
|
377 BIT12
| BIT11
| BIT10
| BIT9
| BIT8
|
378 BIT4
| BIT3
| BIT2
| BIT1
| BIT0
));
382 temp
= ((0x06 << 16) | (0x07 << 8));
385 temp
= ((0x07 << 16) | (0x08 << 8));
388 temp
= ((0x09 << 16) | (0x0A << 8));
391 temp
= ((0x0A << 16) | (0x0B << 8));
395 /* On Duration: ODT, DIFFAMP */
396 mrc_alt_write_mask(DDRPHY
,
398 (bl_grp
* DDRIODQ_BL_OFFSET
) +
399 (ch
* DDRIODQ_CH_OFFSET
)),
401 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
402 BIT16
| BIT13
| BIT12
| BIT11
| BIT10
|
404 /* On Duration: ODT, DIFFAMP */
405 mrc_alt_write_mask(DDRPHY
,
407 (bl_grp
* DDRIODQ_BL_OFFSET
) +
408 (ch
* DDRIODQ_CH_OFFSET
)),
410 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
411 BIT16
| BIT13
| BIT12
| BIT11
| BIT10
|
414 switch (mrc_params
->rd_odt_value
) {
416 /* override DIFFAMP=on, ODT=off */
417 temp
= ((0x3F << 16) | (0x3f << 10));
420 /* override DIFFAMP=on, ODT=on */
421 temp
= ((0x3F << 16) | (0x2A << 10));
425 /* Override: DIFFAMP, ODT */
426 mrc_alt_write_mask(DDRPHY
,
428 (bl_grp
* DDRIODQ_BL_OFFSET
) +
429 (ch
* DDRIODQ_CH_OFFSET
)),
431 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
432 BIT16
| BIT15
| BIT14
| BIT13
| BIT12
|
434 /* Override: DIFFAMP, ODT */
435 mrc_alt_write_mask(DDRPHY
,
437 (bl_grp
* DDRIODQ_BL_OFFSET
) +
438 (ch
* DDRIODQ_CH_OFFSET
)),
440 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
441 BIT16
| BIT15
| BIT14
| BIT13
| BIT12
|
446 /* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
447 mrc_alt_write_mask(DDRPHY
,
449 (bl_grp
* DDRIODQ_BL_OFFSET
) +
450 (ch
* DDRIODQ_CH_OFFSET
)),
451 (((cas
+ 7) << 16) | ((cas
- 4) << 8) |
453 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
454 BIT16
| BIT12
| BIT11
| BIT10
| BIT9
|
455 BIT8
| BIT4
| BIT3
| BIT2
| BIT1
|
457 mrc_alt_write_mask(DDRPHY
,
459 (bl_grp
* DDRIODQ_BL_OFFSET
) +
460 (ch
* DDRIODQ_CH_OFFSET
)),
461 (((cas
+ 7) << 16) | ((cas
- 4) << 8) |
463 (BIT21
| BIT20
| BIT19
| BIT18
| BIT17
|
464 BIT16
| BIT12
| BIT11
| BIT10
| BIT9
|
465 BIT8
| BIT4
| BIT3
| BIT2
| BIT1
|
468 /* RCVEN Bypass (PO) */
469 mrc_alt_write_mask(DDRPHY
,
471 (bl_grp
* DDRIODQ_BL_OFFSET
) +
472 (ch
* DDRIODQ_CH_OFFSET
)),
473 ((0x0 << 7) | (0x0 << 0)),
475 mrc_alt_write_mask(DDRPHY
,
477 (bl_grp
* DDRIODQ_BL_OFFSET
) +
478 (ch
* DDRIODQ_CH_OFFSET
)),
479 ((0x0 << 7) | (0x0 << 0)),
483 mrc_alt_write_mask(DDRPHY
,
485 (bl_grp
* DDRIODQ_BL_OFFSET
) +
486 (ch
* DDRIODQ_CH_OFFSET
)),
488 mrc_alt_write_mask(DDRPHY
,
490 (bl_grp
* DDRIODQ_BL_OFFSET
) +
491 (ch
* DDRIODQ_CH_OFFSET
)),
495 /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
496 mrc_alt_write_mask(DDRPHY
,
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
,
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
,
514 (bl_grp
* DDRIODQ_BL_OFFSET
) +
515 (ch
* DDRIODQ_CH_OFFSET
)),
517 /* Per-Bit De-Skew Enable */
518 mrc_alt_write_mask(DDRPHY
,
520 (bl_grp
* DDRIODQ_BL_OFFSET
) +
521 (ch
* DDRIODQ_CH_OFFSET
)),
526 mrc_alt_write_mask(DDRPHY
,
527 (CMDOBSCKEBBCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
530 /* Enable tristate control of cmd/address bus */
531 mrc_alt_write_mask(DDRPHY
,
532 (CMDCFGREG0
+ (ch
* DDRIOCCC_CH_OFFSET
)),
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
));
542 /* CMDPM* registers must be programmed in this order */
544 /* Turn On Delays: SFR (regulator), MPLL */
545 mrc_alt_write_mask(DDRPHY
,
546 (CMDPMDLYREG4
+ (ch
* DDRIOCCC_CH_OFFSET
)),
547 ((0xFFFFU
<< 16) | (0xFFFF << 0)),
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
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
|
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
|
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) |
597 (BIT19
| BIT18
| BIT17
| BIT16
| BIT15
| BIT14
|
598 BIT13
| BIT12
| BIT11
| BIT10
| BIT9
| BIT8
|
599 BIT7
| BIT6
| BIT5
| BIT4
| BIT0
));
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
|
614 * COMP (RON channel specific)
615 * - DQ/DQS/DM RON: 32 Ohm
616 * - CTRL/CMD RON: 27 Ohm
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
|
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
|
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
|
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
|
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
|
655 /* DQS Swapped Input Enable */
656 mrc_alt_write_mask(DDRPHY
,
657 (COMPEN1CH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
659 (BIT31
| BIT30
| BIT19
| BIT17
|
662 /* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
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
));
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
));
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
));
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
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
)),
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
|
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
));
713 mrc_alt_write_mask(DDRPHY
,
714 (COMPEN0CH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
715 0, (BIT31
| BIT30
| BIT8
));
718 /* DQ COMP Overrides */
720 mrc_alt_write_mask(DDRPHY
,
721 (DQDRVPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
722 (BIT31
| (0x0A << 16)),
723 (BIT31
| BIT20
| BIT19
|
724 BIT18
| BIT17
| BIT16
));
726 mrc_alt_write_mask(DDRPHY
,
727 (DQDRVPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
728 (BIT31
| (0x0A << 16)),
729 (BIT31
| BIT20
| BIT19
|
730 BIT18
| BIT17
| BIT16
));
732 mrc_alt_write_mask(DDRPHY
,
733 (DQDLYPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
734 (BIT31
| (0x10 << 16)),
735 (BIT31
| BIT20
| BIT19
|
736 BIT18
| BIT17
| BIT16
));
738 mrc_alt_write_mask(DDRPHY
,
739 (DQDLYPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
740 (BIT31
| (0x10 << 16)),
741 (BIT31
| BIT20
| BIT19
|
742 BIT18
| BIT17
| BIT16
));
744 mrc_alt_write_mask(DDRPHY
,
745 (DQODTPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
746 (BIT31
| (0x0B << 16)),
747 (BIT31
| BIT20
| BIT19
|
748 BIT18
| BIT17
| BIT16
));
750 mrc_alt_write_mask(DDRPHY
,
751 (DQODTPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
752 (BIT31
| (0x0B << 16)),
753 (BIT31
| BIT20
| BIT19
|
754 BIT18
| BIT17
| BIT16
));
756 mrc_alt_write_mask(DDRPHY
,
757 (DQTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
760 mrc_alt_write_mask(DDRPHY
,
761 (DQTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
764 /* DQS COMP Overrides */
766 mrc_alt_write_mask(DDRPHY
,
767 (DQSDRVPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
768 (BIT31
| (0x0A << 16)),
769 (BIT31
| BIT20
| BIT19
|
770 BIT18
| BIT17
| BIT16
));
772 mrc_alt_write_mask(DDRPHY
,
773 (DQSDRVPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
774 (BIT31
| (0x0A << 16)),
775 (BIT31
| BIT20
| BIT19
|
776 BIT18
| BIT17
| BIT16
));
778 mrc_alt_write_mask(DDRPHY
,
779 (DQSDLYPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
780 (BIT31
| (0x10 << 16)),
781 (BIT31
| BIT20
| BIT19
|
782 BIT18
| BIT17
| BIT16
));
784 mrc_alt_write_mask(DDRPHY
,
785 (DQSDLYPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
786 (BIT31
| (0x10 << 16)),
787 (BIT31
| BIT20
| BIT19
|
788 BIT18
| BIT17
| BIT16
));
790 mrc_alt_write_mask(DDRPHY
,
791 (DQSODTPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
792 (BIT31
| (0x0B << 16)),
793 (BIT31
| BIT20
| BIT19
|
794 BIT18
| BIT17
| BIT16
));
796 mrc_alt_write_mask(DDRPHY
,
797 (DQSODTPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
798 (BIT31
| (0x0B << 16)),
799 (BIT31
| BIT20
| BIT19
|
800 BIT18
| BIT17
| BIT16
));
802 mrc_alt_write_mask(DDRPHY
,
803 (DQSTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
806 mrc_alt_write_mask(DDRPHY
,
807 (DQSTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
810 /* CLK COMP Overrides */
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
));
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
));
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
));
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
));
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
));
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
));
854 mrc_alt_write_mask(DDRPHY
,
855 (CLKTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
858 mrc_alt_write_mask(DDRPHY
,
859 (CLKTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
862 /* CMD COMP Overrides */
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
));
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
));
876 mrc_alt_write_mask(DDRPHY
,
877 (CMDDLYPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
878 (BIT31
| (0x0A << 16)),
879 (BIT31
| BIT20
| BIT19
|
880 BIT18
| BIT17
| BIT16
));
882 mrc_alt_write_mask(DDRPHY
,
883 (CMDDLYPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
884 (BIT31
| (0x0A << 16)),
885 (BIT31
| BIT20
| BIT19
|
886 BIT18
| BIT17
| BIT16
));
888 /* CTL COMP Overrides */
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
));
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
));
902 mrc_alt_write_mask(DDRPHY
,
903 (CTLDLYPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
904 (BIT31
| (0x0A << 16)),
905 (BIT31
| BIT20
| BIT19
|
906 BIT18
| BIT17
| BIT16
));
908 mrc_alt_write_mask(DDRPHY
,
909 (CTLDLYPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
910 (BIT31
| (0x0A << 16)),
911 (BIT31
| BIT20
| BIT19
|
912 BIT18
| BIT17
| BIT16
));
914 /* DQ TCOCOMP Overrides */
916 mrc_alt_write_mask(DDRPHY
,
917 (DQTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
918 (BIT31
| (0x1F << 16)),
919 (BIT31
| BIT20
| BIT19
|
920 BIT18
| BIT17
| BIT16
));
922 mrc_alt_write_mask(DDRPHY
,
923 (DQTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
924 (BIT31
| (0x1F << 16)),
925 (BIT31
| BIT20
| BIT19
|
926 BIT18
| BIT17
| BIT16
));
928 /* DQS TCOCOMP Overrides */
930 mrc_alt_write_mask(DDRPHY
,
931 (DQSTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
932 (BIT31
| (0x1F << 16)),
933 (BIT31
| BIT20
| BIT19
|
934 BIT18
| BIT17
| BIT16
));
936 mrc_alt_write_mask(DDRPHY
,
937 (DQSTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
938 (BIT31
| (0x1F << 16)),
939 (BIT31
| BIT20
| BIT19
|
940 BIT18
| BIT17
| BIT16
));
942 /* CLK TCOCOMP Overrides */
944 mrc_alt_write_mask(DDRPHY
,
945 (CLKTCOPUCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
946 (BIT31
| (0x1F << 16)),
947 (BIT31
| BIT20
| BIT19
|
948 BIT18
| BIT17
| BIT16
));
950 mrc_alt_write_mask(DDRPHY
,
951 (CLKTCOPDCTLCH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
952 (BIT31
| (0x1F << 16)),
953 (BIT31
| BIT20
| BIT19
|
954 BIT18
| BIT17
| BIT16
));
957 /* program STATIC delays */
959 set_wcmd(ch
, ddr_wcmd
[PLATFORM_ID
]);
961 set_wcmd(ch
, ddr_wclk
[PLATFORM_ID
] + HALF_CLK
);
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
]);
968 set_wctl(ch
, rk
, ddr_wctl
[PLATFORM_ID
]);
970 set_wctl(ch
, rk
, ddr_wclk
[PLATFORM_ID
] + HALF_CLK
);
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
));
1057 /* Release PHY from reset */
1058 mrc_alt_write_mask(DDRPHY
, MASTERRSTN
, BIT0
, BIT0
);
1061 mrc_post_code(0x03, 0x11);
1063 for (ch
= 0; ch
< NUM_CHANNELS
; ch
++) {
1064 if (mrc_params
->channel_enables
& (1 << ch
)) {
1067 bl_grp
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2);
1069 mrc_alt_write_mask(DDRPHY
,
1071 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1072 (ch
* DDRIODQ_CH_OFFSET
)),
1074 (BIT13
)); /* Enable VREG */
1079 mrc_alt_write_mask(DDRPHY
, (ECCMDLLCTL
),
1080 (BIT13
), (BIT13
)); /* Enable VREG */
1083 mrc_alt_write_mask(DDRPHY
,
1084 (CMDMDLLCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1085 (BIT13
), (BIT13
)); /* Enable VREG */
1088 mrc_alt_write_mask(DDRPHY
,
1089 (CCMDLLCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1090 (BIT13
), (BIT13
)); /* Enable VREG */
1096 mrc_post_code(0x03, 0x12);
1099 for (ch
= 0; ch
< NUM_CHANNELS
; ch
++) {
1100 if (mrc_params
->channel_enables
& (1 << ch
)) {
1103 bl_grp
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2);
1105 mrc_alt_write_mask(DDRPHY
,
1107 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1108 (ch
* DDRIODQ_CH_OFFSET
)),
1110 (BIT17
)); /* Enable MCDLL */
1115 mrc_alt_write_mask(DDRPHY
, (ECCMDLLCTL
),
1116 (BIT17
), (BIT17
)); /* Enable MCDLL */
1119 mrc_alt_write_mask(DDRPHY
,
1120 (CMDMDLLCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1121 (BIT18
), (BIT18
)); /* Enable MCDLL */
1124 mrc_alt_write_mask(DDRPHY
,
1125 (CCMDLLCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1126 (BIT18
), (BIT18
)); /* Enable MCDLL */
1132 mrc_post_code(0x03, 0x13);
1135 for (ch
= 0; ch
< NUM_CHANNELS
; ch
++) {
1136 if (mrc_params
->channel_enables
& (1 << ch
)) {
1139 bl_grp
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2);
1141 #ifdef FORCE_16BIT_DDRIO
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));
1149 temp
= ((0xF << 12) | (0xF << 8) |
1150 (0xF << 4) | (0xF << 0));
1153 mrc_alt_write_mask(DDRPHY
,
1155 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1156 (ch
* DDRIODQ_CH_OFFSET
)),
1160 mrc_alt_write_mask(DDRPHY
,
1162 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1163 (ch
* DDRIODQ_CH_OFFSET
)),
1164 (BIT3
| BIT2
| BIT1
| BIT0
),
1165 (BIT3
| BIT2
| BIT1
| BIT0
));
1167 /* Enable RXDLL Overrides BL0 */
1168 mrc_alt_write_mask(DDRPHY
,
1170 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1171 (ch
* DDRIODQ_CH_OFFSET
)),
1172 (BIT3
| BIT2
| BIT1
| BIT0
),
1173 (BIT3
| BIT2
| BIT1
| BIT0
));
1177 temp
= ((0xF << 12) | (0xF << 8) |
1178 (0xF << 4) | (0xF << 0));
1179 mrc_alt_write_mask(DDRPHY
, (ECCDLLTXCTL
),
1184 mrc_alt_write_mask(DDRPHY
,
1185 (CMDDLLTXCTL
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1192 mrc_post_code(0x03, 0x14);
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 */
1198 bl_grp
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2);
1200 /* CLK_ALIGN_MOD_ID */
1201 mrc_alt_write_mask(DDRPHY
,
1203 (bl_grp
* DDRIODQ_BL_OFFSET
) +
1204 (ch
* DDRIODQ_CH_OFFSET
)),
1205 (bl_grp
) ? (0x3) : (0x1),
1206 (BIT3
| BIT2
| BIT1
| BIT0
));
1209 mrc_alt_write_mask(DDRPHY
,
1210 (ECCCLKALIGNREG2
+ (ch
* DDRIODQ_CH_OFFSET
)),
1212 (BIT3
| BIT2
| BIT1
| BIT0
));
1213 mrc_alt_write_mask(DDRPHY
,
1214 (CMDCLKALIGNREG2
+ (ch
* DDRIODQ_CH_OFFSET
)),
1216 (BIT3
| BIT2
| BIT1
| BIT0
));
1217 mrc_alt_write_mask(DDRPHY
,
1218 (CCCLKALIGNREG2
+ (ch
* DDRIODQ_CH_OFFSET
)),
1220 (BIT3
| BIT2
| BIT1
| BIT0
));
1221 mrc_alt_write_mask(DDRPHY
,
1222 (CMDCLKALIGNREG0
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1223 (0x2 << 4), (BIT5
| BIT4
));
1225 * NUM_SAMPLES, MAX_SAMPLES,
1226 * MACRO_PI_STEP, MICRO_PI_STEP
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
|
1244 /* START_CLK_ALIGN=1 */
1245 mrc_alt_write_mask(DDRPHY
,
1246 (CMDCLKALIGNREG0
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1248 while (msg_port_alt_read(DDRPHY
,
1249 (CMDCLKALIGNREG0
+ (ch
* DDRIOCCC_CH_OFFSET
))) &
1251 ; /* wait for START_CLK_ALIGN=0 */
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 */
1260 /* enable bypass for CLK buffer (PO) */
1261 mrc_alt_write_mask(DDRPHY
,
1262 (COMPEN0CH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
1264 /* Initial COMP Enable */
1265 mrc_alt_write_mask(DDRPHY
, (CMPCTRL
),
1267 /* wait for Initial COMP Enable = 0 */
1268 while (msg_port_alt_read(DDRPHY
, (CMPCTRL
)) & BIT0
)
1270 /* disable bypass for CLK buffer (PO) */
1271 mrc_alt_write_mask(DDRPHY
,
1272 (COMPEN0CH0
+ (ch
* DDRCOMP_CH_OFFSET
)),
1278 mrc_alt_write_mask(DDRPHY
,
1279 (CMDCFGREG0
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1280 BIT2
, BIT2
); /* IOBUFACTRST_N=1 */
1282 /* DDRPHY initialization complete */
1283 mrc_alt_write_mask(DDRPHY
,
1284 (CMDPMCONFIG0
+ (ch
* DDRIOCCC_CH_OFFSET
)),
1285 BIT20
, BIT20
); /* SPID_INIT_COMPLETE=1 */
1292 /* This function performs JEDEC initialization on all enabled channels */
1293 void perform_jedec_init(struct mrc_params
*mrc_params
)
1295 uint8_t twr
, wl
, rank
;
1307 /* jedec_init starts */
1308 mrc_post_code(0x04, 0x00);
1310 /* DDR3_RESET_SET=0, DDR3_RESET_RESET=1 */
1311 mrc_alt_write_mask(DDRPHY
, CCDDR3RESETCTL
, BIT1
, (BIT8
| BIT1
));
1313 /* Assert RESET# for 200us */
1316 /* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
1317 mrc_alt_write_mask(DDRPHY
, CCDDR3RESETCTL
, BIT8
, (BIT8
| BIT1
));
1319 dtr0
= msg_port_read(MEM_CTLR
, DTR0
);
1322 * Set CKEVAL for populated ranks
1323 * then send NOP to each rank (#4550197)
1326 drp
= msg_port_read(MEM_CTLR
, DRP
);
1329 drmc
= msg_port_read(MEM_CTLR
, DRMC
);
1331 drmc
|= (BIT4
| drp
);
1333 msg_port_write(MEM_CTLR
, DRMC
, drmc
);
1335 for (rank
= 0; rank
< NUM_RANKS
; rank
++) {
1336 /* Skip to next populated rank */
1337 if ((mrc_params
->rank_enables
& (1 << rank
)) == 0)
1340 dram_init_command(DCMD_NOP(rank
));
1343 msg_port_write(MEM_CTLR
, DRMC
,
1344 (mrc_params
->rd_odt_value
== 0 ? BIT12
: 0));
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)
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);
1363 * BIT[15:03] --> Always "0"
1364 * BIT[02] --> MPR: want "Normal Operation" (0)
1365 * BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
1367 emrs3_cmd
|= (3 << 3);
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)
1382 * (BIT5|BIT1) set Ron value
1383 * 00 --> RZQ/6 (40ohm)
1384 * 01 --> RZQ/7 (34ohm)
1387 * (BIT9|BIT6|BIT2) set Rtt_nom value
1389 * 001 --> RZQ/4 ( 60ohm)
1390 * 010 --> RZQ/2 (120ohm)
1391 * 011 --> RZQ/6 ( 40ohm)
1394 emrs1_cmd
|= (1 << 3);
1397 if (mrc_params
->ron_value
== 0)
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);
1409 /* save MRS1 value (excluding control fields) */
1410 mrc_params
->mrs1
= emrs1_cmd
>> 6;
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)
1432 * BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
1433 * BIT[06:04] use oem_tCAS-4
1437 mrs0_cmd
|= ((((dtr0
>> 12) & 7) + 1) << 10);
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);
1444 for (rank
= 0; rank
< NUM_RANKS
; rank
++) {
1445 /* Skip to next populated rank */
1446 if ((mrc_params
->rank_enables
& (1 << rank
)) == 0)
1449 emrs2_cmd
|= (rank
<< 22);
1450 dram_init_command(emrs2_cmd
);
1452 emrs3_cmd
|= (rank
<< 22);
1453 dram_init_command(emrs3_cmd
);
1455 emrs1_cmd
|= (rank
<< 22);
1456 dram_init_command(emrs1_cmd
);
1458 mrs0_cmd
|= (rank
<< 22);
1459 dram_init_command(mrs0_cmd
);
1461 dram_init_command(DCMD_ZQCL(rank
));
1468 * Dunit Initialization Complete
1470 * Indicates that initialization of the Dunit has completed.
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.
1476 void set_ddr_init_complete(struct mrc_params
*mrc_params
)
1482 dco
= msg_port_read(MEM_CTLR
, DCO
);
1485 msg_port_write(MEM_CTLR
, DCO
, dco
);
1491 * This function will retrieve relevant timing data
1493 * This data will be used on subsequent boots to speed up boot times
1494 * and is required for Suspend To RAM capabilities.
1496 void restore_timings(struct mrc_params
*mrc_params
)
1499 const struct mrc_timings
*mt
= &mrc_params
->timings
;
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
]);
1509 /* VREF (RANK0 only) */
1510 set_vref(ch
, bl
, mt
->vref
[ch
][bl
]);
1513 set_wctl(ch
, rk
, mt
->wctl
[ch
][rk
]);
1515 set_wcmd(ch
, mt
->wcmd
[ch
]);
1520 * Configure default settings normally set as part of read training
1522 * Some defaults have to be set earlier as they may affect earlier
1525 void default_timings(struct mrc_params
*mrc_params
)
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);
1534 /* VREF (RANK0 only) */
1535 set_vref(ch
, bl
, 32);
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.
1547 void rcvn_cal(struct mrc_params
*mrc_params
)
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;
1555 /* used to find placement for rank2rank sharing configs */
1556 uint32_t final_delay
[NUM_CHANNELS
][NUM_BYTE_LANES
];
1558 /* used to find placement for rank2rank sharing configs */
1559 uint32_t num_ranks_enabled
= 0;
1566 /* absolute PI value to be programmed on the byte lane */
1567 uint32_t delay
[NUM_BYTE_LANES
];
1568 u32 dtr1
, dtr1_save
;
1573 /* rcvn_cal starts */
1574 mrc_post_code(0x05, 0x00);
1577 /* need separate burst to sample DQS preamble */
1578 dtr1
= msg_port_read(MEM_CTLR
, DTR1
);
1581 msg_port_write(MEM_CTLR
, DTR1
, dtr1
);
1585 /* need to set "final_delay[][]" elements to "0" */
1586 memset((void *)(final_delay
), 0x00, (size_t)sizeof(final_delay
));
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
)) {
1596 * POST_CODE here indicates the current
1597 * channel and rank being calibrated
1599 mrc_post_code(0x05, (0x10 + ((ch
<< 4) | rk
)));
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
]);
1606 /* enable FIFORST */
1607 for (bl
= 0; bl
< (NUM_BYTE_LANES
/ bl_divisor
); bl
+= 2) {
1608 mrc_alt_write_mask(DDRPHY
,
1610 ((bl
>> 1) * DDRIODQ_BL_OFFSET
) +
1611 (ch
* DDRIODQ_CH_OFFSET
)),
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
;
1619 set_rcvn(ch
, rk
, bl
, delay
[bl
]);
1622 /* now find the rising edge */
1623 find_rising_edge(mrc_params
, delay
, ch
, rk
, true);
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
]);
1630 /* Now decrement delay by 128 PI (1 CLK) until we sample a "0" */
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
]);
1639 /* not enough delay */
1640 training_message(ch
, rk
, bl
);
1641 mrc_post_code(0xEE, 0x50);
1645 } while (temp
& 0xFF);
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
));
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
]);
1666 /* disable FIFORST */
1667 for (bl
= 0; bl
< (NUM_BYTE_LANES
/ bl_divisor
); bl
+= 2) {
1668 mrc_alt_write_mask(DDRPHY
,
1670 ((bl
>> 1) * DDRIODQ_BL_OFFSET
) +
1671 (ch
* DDRIODQ_CH_OFFSET
)),
1681 /* restore original */
1682 msg_port_write(MEM_CTLR
, DTR1
, dtr1_save
);
1689 * This function will perform the Write Levelling algorithm
1690 * (align WCLK and WDQS).
1692 * This algorithm will act on each rank in each channel separately.
1694 void wr_level(struct mrc_params
*mrc_params
)
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;
1702 /* used to find placement for rank2rank sharing configs */
1703 uint32_t final_delay
[NUM_CHANNELS
][NUM_BYTE_LANES
];
1705 /* used to find placement for rank2rank sharing configs */
1706 uint32_t num_ranks_enabled
= 0;
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
];
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
1721 uint32_t address
; /* address to be checked during COARSE_WR_LVL */
1722 u32 dtr4
, dtr4_save
;
1727 /* wr_level starts */
1728 mrc_post_code(0x06, 0x00);
1731 /* need to set "final_delay[][]" elements to "0" */
1732 memset((void *)(final_delay
), 0x00, (size_t)sizeof(final_delay
));
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
)) {
1742 * POST_CODE here indicates the current
1743 * rank and channel being calibrated
1745 mrc_post_code(0x06, (0x10 + ((ch
<< 4) | rk
)));
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
));
1754 * perform a single PRECHARGE_ALL command to
1755 * make DRAM state machine go to IDLE state
1757 dram_init_command(DCMD_PREA(rk
));
1760 * enable Write Levelling Mode
1761 * (EMRS1 w/ Write Levelling Mode Enable)
1763 dram_init_command(DCMD_MRS1(rk
, 0x0082));
1766 * set ODT DRAM Full Time Termination
1770 dtr4
= msg_port_read(MEM_CTLR
, DTR4
);
1773 msg_port_write(MEM_CTLR
, DTR4
, dtr4
);
1775 for (bl
= 0; bl
< ((NUM_BYTE_LANES
/ bl_divisor
) / 2); bl
++) {
1777 * Enable Sandy Bridge Mode (WDQ Tri-State) &
1778 * Ensure 5 WDQS pulses during Write Leveling
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
));
1786 /* Write Leveling Mode enabled in IO */
1787 mrc_alt_write_mask(DDRPHY
,
1788 CCDDR3RESETCTL
+ (DDRIOCCC_CH_OFFSET
* ch
),
1791 /* Initialize the starting delay to WCLK */
1792 for (bl
= 0; bl
< (NUM_BYTE_LANES
/ bl_divisor
); bl
++) {
1797 delay
[bl
] = get_wclk(ch
, rk
);
1799 set_wdqs(ch
, rk
, bl
, delay
[bl
]);
1802 /* now find the rising edge */
1803 find_rising_edge(mrc_params
, delay
, ch
, rk
, false);
1805 /* disable Write Levelling Mode */
1806 mrc_alt_write_mask(DDRPHY
,
1807 CCDDR3RESETCTL
+ (DDRIOCCC_CH_OFFSET
* ch
),
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
));
1818 /* restore original DTR4 */
1819 msg_port_write(MEM_CTLR
, DTR4
, dtr4_save
);
1822 * restore original value
1823 * (Write Levelling Mode Disable)
1825 dram_init_command(DCMD_MRS1(rk
, mrc_params
->mrs1
));
1828 * perform a single PRECHARGE_ALL command to
1829 * make DRAM state machine go to IDLE state
1831 dram_init_command(DCMD_PREA(rk
));
1833 mrc_post_code(0x06, (0x30 + ((ch
<< 4) | rk
)));
1836 * COARSE WRITE LEVEL:
1837 * check that we're on the correct clock edge
1840 /* hte reconfiguration request */
1841 mrc_params
->hte_setup
= 1;
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
]);
1848 * program WDQ timings based on WDQS
1849 * (WDQ = WDQS - 32 PI)
1851 set_wdq(ch
, rk
, bl
, (delay
[bl
] - QRTR_CLK
));
1854 /* get an address in the targeted channel/rank */
1855 address
= get_addr(ch
, rk
);
1857 uint32_t coarse_result
= 0x00;
1858 uint32_t coarse_result_mask
= byte_lane_mask(mrc_params
);
1860 all_edges_found
= true;
1862 mrc_params
->hte_setup
= 1;
1863 coarse_result
= check_rw_coarse(mrc_params
, address
);
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
));
1875 } while (!all_edges_found
);
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
);
1897 void prog_page_ctrl(struct mrc_params
*mrc_params
)
1903 dpmc0
= msg_port_read(MEM_CTLR
, DPMC0
);
1904 dpmc0
&= ~(BIT16
| BIT17
| BIT18
);
1907 msg_port_write(MEM_CTLR
, DPMC0
, dpmc0
);
1911 * This function will perform the READ TRAINING Algorithm on all
1912 * channels/ranks/byte_lanes simultaneously to minimize execution time.
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
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.
1929 void rd_train(struct mrc_params
*mrc_params
)
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;
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 */
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;
1958 /* rd_train starts */
1959 mrc_post_code(0x07, 0x00);
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
)) {
1969 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
1971 set_rdqs(ch
, rk
, bl
, ddr_rdqs
[PLATFORM_ID
]);
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
)) {
1984 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
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
;
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
;
2002 /* initialize other variables */
2003 bl_mask
= byte_lane_mask(mrc_params
);
2004 address
= get_addr(0, 0);
2007 /* need to set "final_delay[][]" elements to "0" */
2008 memset((void *)(final_delay
), 0x00, (size_t)sizeof(final_delay
));
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
)));
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
&
2022 /* set x/y_coordinate search starting settings */
2024 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
2026 set_rdqs(ch
, rk
, bl
,
2027 x_coordinate
[side_x
][side_y
][ch
][rk
][bl
]);
2029 y_coordinate
[side_x
][side_y
][ch
][bl
]);
2032 /* get an address in the target channel/rank */
2033 address
= get_addr(ch
, rk
);
2035 /* request HTE reconfiguration */
2036 mrc_params
->hte_setup
= 1;
2038 /* test the settings */
2040 /* result[07:00] == failing byte lane (MAX 8) */
2041 result
= check_bls_ex(mrc_params
, address
);
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
++) {
2049 /* adjust the RDQS values accordingly */
2051 x_coordinate
[L
][side_y
][ch
][rk
][bl
] += RDQS_STEP
;
2053 x_coordinate
[R
][side_y
][ch
][rk
][bl
] -= RDQS_STEP
;
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
])) {
2061 * not enough RDQS margin available at this VREF
2062 * update VREF values accordingly
2065 y_coordinate
[side_x
][B
][ch
][bl
] += VREF_STEP
;
2067 y_coordinate
[side_x
][T
][ch
][bl
] -= VREF_STEP
;
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
)));
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
);
2085 /* update the RDQS setting */
2086 set_rdqs(ch
, rk
, bl
, x_coordinate
[side_x
][side_y
][ch
][rk
][bl
]);
2090 } while (result
& 0xFF);
2098 mrc_post_code(0x07, 0x20);
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
++) {
2111 "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n",
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
]);
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);
2127 "VREF R/L eye lane%d : %d-%d %d-%d\n",
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
]);
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);
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
)));
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
++) {
2159 set_rdqs(ch
, rk
, bl
, (x_center
[ch
][rk
][bl
] - (MIN_RDQS_EYE
/ 2)));
2161 set_rdqs(ch
, rk
, bl
, (x_center
[ch
][rk
][bl
] + (MIN_RDQS_EYE
/ 2)));
2164 set_vref(ch
, bl
, (y_center
[ch
][bl
] - (MIN_VREF_EYE
/ 2)));
2166 set_vref(ch
, bl
, (y_center
[ch
][bl
] + (MIN_VREF_EYE
/ 2)));
2173 /* request HTE reconfiguration */
2174 mrc_params
->hte_setup
= 1;
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
)));
2185 mrc_post_code(0x07, 0x40);
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
)) {
2193 /* increment "num_ranks_enabled" */
2194 num_ranks_enabled
++;
2196 for (bl
= 0; bl
< (NUM_BYTE_LANES
/ bl_divisor
); bl
++) {
2199 final_delay
[ch
][bl
] += x_center
[ch
][rk
][bl
];
2200 set_rdqs(ch
, rk
, bl
, ((final_delay
[ch
][bl
]) / num_ranks_enabled
));
2202 set_rdqs(ch
, rk
, bl
, x_center
[ch
][rk
][bl
]);
2205 set_vref(ch
, bl
, y_center
[ch
][bl
]);
2217 * This function will perform the WRITE TRAINING Algorithm on all
2218 * channels/ranks/byte_lanes simultaneously to minimize execution time.
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
2227 void wr_train(struct mrc_params
*mrc_params
)
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;
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 */
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;
2250 /* wr_train starts */
2251 mrc_post_code(0x08, 0x00);
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
)) {
2261 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
2263 set_wdq(ch
, rk
, bl
, ddr_wdq
[PLATFORM_ID
]);
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
)) {
2276 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
2279 * want to start with
2280 * WDQ = (WDQS - QRTR_CLK)
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
;
2292 /* initialize other variables */
2293 bl_mask
= byte_lane_mask(mrc_params
);
2294 address
= get_addr(0, 0);
2297 /* need to set "final_delay[][]" elements to "0" */
2298 memset((void *)(final_delay
), 0x00, (size_t)sizeof(final_delay
));
2302 * start algorithm on the LEFT side and train each channel/bl
2303 * until no failures are observed, then repeat for the RIGHT side.
2305 for (side
= L
; side
<= R
; side
++) {
2306 mrc_post_code(0x08, (0x10 + (side
)));
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
&
2315 bl
< (NUM_BYTE_LANES
/ bl_divisor
);
2317 set_wdq(ch
, rk
, bl
, delay
[side
][ch
][rk
][bl
]);
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
&
2330 /* get an address in the target channel/rank */
2331 address
= get_addr(ch
, rk
);
2333 /* request HTE reconfiguration */
2334 mrc_params
->hte_setup
= 1;
2336 /* check the settings */
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
++) {
2347 delay
[L
][ch
][rk
][bl
] += WDQ_STEP
;
2349 delay
[R
][ch
][rk
][bl
] -= WDQ_STEP
;
2351 /* check for algorithm failure */
2352 if (delay
[L
][ch
][rk
][bl
] != delay
[R
][ch
][rk
][bl
]) {
2355 * update delay setting
2358 delay
[side
][ch
][rk
][bl
]);
2361 * no margin available
2362 * notify the user and halt
2364 training_message(ch
, rk
, bl
);
2365 mrc_post_code(0xEE, (0x80 + side
));
2370 /* stop when all byte lanes pass */
2371 } while (result
& 0xFF);
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
)) {
2384 /* increment "num_ranks_enabled" */
2385 num_ranks_enabled
++;
2387 for (bl
= 0; bl
< (NUM_BYTE_LANES
/ bl_divisor
); bl
++) {
2389 "WDQ eye rank%d lane%d : %d-%d\n",
2391 delay
[L
][ch
][rk
][bl
],
2392 delay
[R
][ch
][rk
][bl
]);
2394 temp
= (delay
[R
][ch
][rk
][bl
] + delay
[L
][ch
][rk
][bl
]) / 2;
2397 final_delay
[ch
][bl
] += temp
;
2399 ((final_delay
[ch
][bl
]) / num_ranks_enabled
));
2401 set_wdq(ch
, rk
, bl
, temp
);
2414 * This function will store relevant timing data
2416 * This data will be used on subsequent boots to speed up boot times
2417 * and is required for Suspend To RAM capabilities.
2419 void store_timings(struct mrc_params
*mrc_params
)
2422 struct mrc_timings
*mt
= &mrc_params
->timings
;
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
);
2433 mt
->vref
[ch
][bl
] = get_vref(ch
, bl
);
2436 mt
->wctl
[ch
][rk
] = get_wctl(ch
, rk
);
2439 mt
->wcmd
[ch
] = get_wcmd(ch
);
2442 /* need to save for a case of changing frequency after warm reset */
2443 mt
->ddr_speed
= mrc_params
->ddr_speed
;
2447 * The purpose of this function is to ensure the SEC comes out of reset
2448 * and IA initiates the SEC enabling Memory Scrambling.
2450 void enable_scrambling(struct mrc_params
*mrc_params
)
2455 if (mrc_params
->scrambling_enables
== 0)
2460 /* 32 bit seed is always stored in BIOS NVM */
2461 lfsr
= mrc_params
->timings
.scrambler_seed
;
2463 if (mrc_params
->boot_mode
== BM_COLD
) {
2465 * factory value is 0 and in first boot,
2466 * a clock based seed is loaded.
2470 * get seed from system clock
2471 * and make sure it is not all 1's
2473 lfsr
= rdtsc() & 0x0FFFFFFF;
2476 * Need to replace scrambler
2478 * get next 32bit LFSR 16 times which is the last
2479 * part of the previous scrambler vector
2481 for (i
= 0; i
< 16; i
++)
2486 mrc_params
->timings
.scrambler_seed
= lfsr
;
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.
2493 lfsr32(&lfsr
); /* shift to next value */
2494 msg_port_write(MEM_CTLR
, SCRMSEED
, (lfsr
& 0x0003FFFF));
2496 for (i
= 0; i
< 2; i
++)
2497 msg_port_write(MEM_CTLR
, SCRMLO
+ i
, (lfsr
& 0xAAAAAAAA));
2503 * Configure MCU Power Management Control Register
2504 * and Scheduler Control Register
2506 void prog_ddr_control(struct mrc_params
*mrc_params
)
2513 dsch
= msg_port_read(MEM_CTLR
, DSCH
);
2514 dsch
&= ~(BIT8
| BIT9
| BIT12
);
2515 msg_port_write(MEM_CTLR
, DSCH
, dsch
);
2517 dpmc0
= msg_port_read(MEM_CTLR
, DPMC0
);
2519 dpmc0
|= (mrc_params
->power_down_disable
<< 25);
2521 dpmc0
&= ~(BIT16
| BIT17
| BIT18
);
2524 msg_port_write(MEM_CTLR
, DPMC0
, dpmc0
);
2526 /* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
2527 mrc_write_mask(MEM_CTLR
, DPMC1
, 2 << 4, BIT4
| BIT5
);
2533 * After training complete configure MCU Rank Population Register
2534 * specifying: ranks enabled, device width, density, address mode
2536 void prog_dra_drb(struct mrc_params
*mrc_params
)
2540 u8 density
= mrc_params
->params
.density
;
2544 dco
= msg_port_read(MEM_CTLR
, DCO
);
2546 msg_port_write(MEM_CTLR
, DCO
, dco
);
2549 if (mrc_params
->rank_enables
& 1)
2551 if (mrc_params
->rank_enables
& 2)
2553 if (mrc_params
->dram_width
== X16
) {
2559 * Density encoding in struct dram_params: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
2560 * has to be mapped RANKDENSx encoding (0=1Gb)
2565 drp
|= ((density
- 1) << 6);
2566 drp
|= ((density
- 1) << 11);
2568 /* Address mode can be overwritten if ECC enabled */
2569 drp
|= (mrc_params
->address_mode
<< 14);
2571 msg_port_write(MEM_CTLR
, DRP
, drp
);
2575 msg_port_write(MEM_CTLR
, DCO
, dco
);
2580 /* Send DRAM wake command */
2581 void perform_wake(struct mrc_params
*mrc_params
)
2585 dram_wake_command();
2591 * Configure refresh rate and short ZQ calibration interval
2592 * Activate dynamic self refresh
2594 void change_refresh_period(struct mrc_params
*mrc_params
)
2602 drfc
= msg_port_read(MEM_CTLR
, DRFC
);
2603 drfc
&= ~(BIT12
| BIT13
| BIT14
);
2604 drfc
|= (mrc_params
->refresh_rate
<< 12);
2606 msg_port_write(MEM_CTLR
, DRFC
, drfc
);
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
);
2613 dpmc0
= msg_port_read(MEM_CTLR
, DPMC0
);
2614 dpmc0
|= (BIT23
| BIT29
);
2615 msg_port_write(MEM_CTLR
, DPMC0
, dpmc0
);
2621 * Configure DDRPHY for Auto-Refresh, Periodic Compensations,
2622 * Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
2624 void set_auto_refresh(struct mrc_params
*mrc_params
)
2629 uint32_t bl_divisor
= 1;
2635 * Enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp,
2636 * ZQSPERIOD, Auto-Precharge, CKE Power-Down
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
);
2643 /* Enable Dynamic DiffAmp & Set Read ODT Value */
2644 switch (mrc_params
->rd_odt_value
) {
2646 temp
= 0x3F; /* OFF */
2649 temp
= 0x00; /* Auto */
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
));
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
));
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
));
2687 * Depending on configuration enables ECC support
2689 * Available memory size is decreased, and updated with 0s
2690 * in order to clear error status. Address mode 2 forced.
2692 void ecc_enable(struct mrc_params
*mrc_params
)
2698 if (mrc_params
->ecc_enables
== 0)
2703 /* Configuration required in ECC mode */
2704 drp
= msg_port_read(MEM_CTLR
, DRP
);
2705 drp
&= ~(BIT14
| BIT15
);
2708 msg_port_write(MEM_CTLR
, DRP
, drp
);
2710 /* Disable new request bypass */
2711 dsch
= msg_port_read(MEM_CTLR
, DSCH
);
2713 msg_port_write(MEM_CTLR
, DSCH
, dsch
);
2716 ecc_ctrl
= (BIT0
| BIT1
| BIT17
);
2717 msg_port_write(MEM_CTLR
, DECCCTRL
, ecc_ctrl
);
2719 /* Assume 8 bank memory, one bank is gone for ECC */
2720 mrc_params
->mem_size
-= mrc_params
->mem_size
/ 8;
2722 /* For S3 resume memory content has to be preserved */
2723 if (mrc_params
->boot_mode
!= BM_S3
) {
2725 hte_mem_init(mrc_params
, MRC_MEM_INIT
);
2733 * Execute memory test
2734 * if error detected it is indicated in mrc_params->status
2736 void memory_test(struct mrc_params
*mrc_params
)
2738 uint32_t result
= 0;
2743 result
= hte_mem_init(mrc_params
, MRC_MEM_TEST
);
2746 DPF(D_INFO
, "Memory test result %x\n", result
);
2747 mrc_params
->status
= ((result
== 0) ? MRC_SUCCESS
: MRC_E_MEMTEST
);
2751 /* Lock MCU registers at the end of initialization sequence */
2752 void lock_registers(struct mrc_params
*mrc_params
)
2758 dco
= msg_port_read(MEM_CTLR
, DCO
);
2759 dco
&= ~(BIT28
| BIT29
);
2760 dco
|= (BIT0
| BIT8
);
2761 msg_port_write(MEM_CTLR
, DCO
, dco
);