blob: a7e92b3f5c160674870c967bd181b1d609ece676 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: Intel
Bin Meng93b4a392015-02-05 23:42:24 +08002/*
3 * Copyright (C) 2013, Intel Corporation
4 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
5 *
6 * Ported from Intel released Quark UEFI BIOS
7 * QuarkSocPkg/QuarkNorthCluster/MemoryInit/Pei
Bin Meng93b4a392015-02-05 23:42:24 +08008 */
9
Bin Meng93b4a392015-02-05 23:42:24 +080010#include <pci.h>
11#include <asm/arch/device.h>
12#include <asm/arch/mrc.h>
13#include <asm/arch/msg_port.h>
Tom Rini412a0212024-04-27 08:10:56 -060014#include <asm/u-boot-x86.h>
15#include <linux/string.h>
Bin Meng93b4a392015-02-05 23:42:24 +080016#include "mrc_util.h"
17#include "hte.h"
18#include "smc.h"
19
Bin Meng93b4a392015-02-05 23:42:24 +080020/* t_ck clock period in picoseconds per speed index 800, 1066, 1333 */
21static const uint32_t t_ck[3] = {
22 2500,
23 1875,
24 1500
25};
26
27/* Global variables */
28static const uint16_t ddr_wclk[] = {193, 158};
Tom Rini008454f2018-01-27 15:13:47 -050029#ifdef BACKUP_WCTL
Bin Meng93b4a392015-02-05 23:42:24 +080030static const uint16_t ddr_wctl[] = {1, 217};
Tom Rini008454f2018-01-27 15:13:47 -050031#endif
32#ifdef BACKUP_WCMD
Bin Meng93b4a392015-02-05 23:42:24 +080033static const uint16_t ddr_wcmd[] = {1, 220};
Tom Rini008454f2018-01-27 15:13:47 -050034#endif
Bin Meng93b4a392015-02-05 23:42:24 +080035
36#ifdef BACKUP_RCVN
37static const uint16_t ddr_rcvn[] = {129, 498};
38#endif
39
40#ifdef BACKUP_WDQS
41static const uint16_t ddr_wdqs[] = {65, 289};
42#endif
43
44#ifdef BACKUP_RDQS
45static const uint8_t ddr_rdqs[] = {32, 24};
46#endif
47
48#ifdef BACKUP_WDQ
49static const uint16_t ddr_wdq[] = {32, 257};
50#endif
51
52/* Stop self refresh driven by MCU */
53void clear_self_refresh(struct mrc_params *mrc_params)
54{
55 ENTERFN();
56
57 /* clear the PMSTS Channel Self Refresh bits */
Bin Meng15e3f282015-03-10 18:31:20 +080058 mrc_write_mask(MEM_CTLR, PMSTS, PMSTS_DISR, PMSTS_DISR);
Bin Meng93b4a392015-02-05 23:42:24 +080059
60 LEAVEFN();
61}
62
63/* It will initialize timing registers in the MCU (DTR0..DTR4) */
64void prog_ddr_timing_control(struct mrc_params *mrc_params)
65{
66 uint8_t tcl, wl;
67 uint8_t trp, trcd, tras, twr, twtr, trrd, trtp, tfaw;
68 uint32_t tck;
69 u32 dtr0, dtr1, dtr2, dtr3, dtr4;
70 u32 tmp1, tmp2;
71
72 ENTERFN();
73
74 /* mcu_init starts */
75 mrc_post_code(0x02, 0x00);
76
77 dtr0 = msg_port_read(MEM_CTLR, DTR0);
78 dtr1 = msg_port_read(MEM_CTLR, DTR1);
79 dtr2 = msg_port_read(MEM_CTLR, DTR2);
80 dtr3 = msg_port_read(MEM_CTLR, DTR3);
81 dtr4 = msg_port_read(MEM_CTLR, DTR4);
82
83 tck = t_ck[mrc_params->ddr_speed]; /* Clock in picoseconds */
84 tcl = mrc_params->params.cl; /* CAS latency in clocks */
85 trp = tcl; /* Per CAT MRC */
86 trcd = tcl; /* Per CAT MRC */
87 tras = MCEIL(mrc_params->params.ras, tck);
88
89 /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
90 twr = MCEIL(15000, tck);
91
92 twtr = MCEIL(mrc_params->params.wtr, tck);
93 trrd = MCEIL(mrc_params->params.rrd, tck);
94 trtp = 4; /* Valid for 800 and 1066, use 5 for 1333 */
95 tfaw = MCEIL(mrc_params->params.faw, tck);
96
97 wl = 5 + mrc_params->ddr_speed;
98
Bin Meng15e3f282015-03-10 18:31:20 +080099 dtr0 &= ~DTR0_DFREQ_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800100 dtr0 |= mrc_params->ddr_speed;
Bin Meng15e3f282015-03-10 18:31:20 +0800101 dtr0 &= ~DTR0_TCL_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800102 tmp1 = tcl - 5;
103 dtr0 |= ((tcl - 5) << 12);
Bin Meng15e3f282015-03-10 18:31:20 +0800104 dtr0 &= ~DTR0_TRP_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800105 dtr0 |= ((trp - 5) << 4); /* 5 bit DRAM Clock */
Bin Meng15e3f282015-03-10 18:31:20 +0800106 dtr0 &= ~DTR0_TRCD_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800107 dtr0 |= ((trcd - 5) << 8); /* 5 bit DRAM Clock */
108
Bin Meng15e3f282015-03-10 18:31:20 +0800109 dtr1 &= ~DTR1_TWCL_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800110 tmp2 = wl - 3;
111 dtr1 |= (wl - 3);
Bin Meng15e3f282015-03-10 18:31:20 +0800112 dtr1 &= ~DTR1_TWTP_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800113 dtr1 |= ((wl + 4 + twr - 14) << 8); /* Change to tWTP */
Bin Meng15e3f282015-03-10 18:31:20 +0800114 dtr1 &= ~DTR1_TRTP_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800115 dtr1 |= ((MMAX(trtp, 4) - 3) << 28); /* 4 bit DRAM Clock */
Bin Meng15e3f282015-03-10 18:31:20 +0800116 dtr1 &= ~DTR1_TRRD_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800117 dtr1 |= ((trrd - 4) << 24); /* 4 bit DRAM Clock */
Bin Meng15e3f282015-03-10 18:31:20 +0800118 dtr1 &= ~DTR1_TCMD_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800119 dtr1 |= (1 << 4);
Bin Meng15e3f282015-03-10 18:31:20 +0800120 dtr1 &= ~DTR1_TRAS_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800121 dtr1 |= ((tras - 14) << 20); /* 6 bit DRAM Clock */
Bin Meng15e3f282015-03-10 18:31:20 +0800122 dtr1 &= ~DTR1_TFAW_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800123 dtr1 |= ((((tfaw + 1) >> 1) - 5) << 16);/* 4 bit DRAM Clock */
124 /* Set 4 Clock CAS to CAS delay (multi-burst) */
Bin Meng15e3f282015-03-10 18:31:20 +0800125 dtr1 &= ~DTR1_TCCD_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800126
Bin Meng15e3f282015-03-10 18:31:20 +0800127 dtr2 &= ~DTR2_TRRDR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800128 dtr2 |= 1;
Bin Meng15e3f282015-03-10 18:31:20 +0800129 dtr2 &= ~DTR2_TWWDR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800130 dtr2 |= (2 << 8);
Bin Meng15e3f282015-03-10 18:31:20 +0800131 dtr2 &= ~DTR2_TRWDR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800132 dtr2 |= (2 << 16);
133
Bin Meng15e3f282015-03-10 18:31:20 +0800134 dtr3 &= ~DTR3_TWRDR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800135 dtr3 |= 2;
Bin Meng15e3f282015-03-10 18:31:20 +0800136 dtr3 &= ~DTR3_TXXXX_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800137 dtr3 |= (2 << 4);
138
Bin Meng15e3f282015-03-10 18:31:20 +0800139 dtr3 &= ~DTR3_TRWSR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800140 if (mrc_params->ddr_speed == DDRFREQ_800) {
141 /* Extended RW delay (+1) */
142 dtr3 |= ((tcl - 5 + 1) << 8);
143 } else if (mrc_params->ddr_speed == DDRFREQ_1066) {
144 /* Extended RW delay (+1) */
145 dtr3 |= ((tcl - 5 + 1) << 8);
146 }
147
Bin Meng15e3f282015-03-10 18:31:20 +0800148 dtr3 &= ~DTR3_TWRSR_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800149 dtr3 |= ((4 + wl + twtr - 11) << 13);
150
Bin Meng15e3f282015-03-10 18:31:20 +0800151 dtr3 &= ~DTR3_TXP_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800152 if (mrc_params->ddr_speed == DDRFREQ_800)
153 dtr3 |= ((MMAX(0, 1 - 1)) << 22);
154 else
155 dtr3 |= ((MMAX(0, 2 - 1)) << 22);
156
Bin Meng15e3f282015-03-10 18:31:20 +0800157 dtr4 &= ~DTR4_WRODTSTRT_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800158 dtr4 |= 1;
Bin Meng15e3f282015-03-10 18:31:20 +0800159 dtr4 &= ~DTR4_WRODTSTOP_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800160 dtr4 |= (1 << 4);
Bin Meng15e3f282015-03-10 18:31:20 +0800161 dtr4 &= ~DTR4_XXXX1_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800162 dtr4 |= ((1 + tmp1 - tmp2 + 2) << 8);
Bin Meng15e3f282015-03-10 18:31:20 +0800163 dtr4 &= ~DTR4_XXXX2_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800164 dtr4 |= ((1 + tmp1 - tmp2 + 2) << 12);
Bin Meng15e3f282015-03-10 18:31:20 +0800165 dtr4 &= ~(DTR4_ODTDIS | DTR4_TRGSTRDIS);
Bin Meng93b4a392015-02-05 23:42:24 +0800166
167 msg_port_write(MEM_CTLR, DTR0, dtr0);
168 msg_port_write(MEM_CTLR, DTR1, dtr1);
169 msg_port_write(MEM_CTLR, DTR2, dtr2);
170 msg_port_write(MEM_CTLR, DTR3, dtr3);
171 msg_port_write(MEM_CTLR, DTR4, dtr4);
172
173 LEAVEFN();
174}
175
176/* Configure MCU before jedec init sequence */
177void prog_decode_before_jedec(struct mrc_params *mrc_params)
178{
179 u32 drp;
180 u32 drfc;
181 u32 dcal;
182 u32 dsch;
183 u32 dpmc0;
184
185 ENTERFN();
186
187 /* Disable power saving features */
188 dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
Bin Meng15e3f282015-03-10 18:31:20 +0800189 dpmc0 |= (DPMC0_CLKGTDIS | DPMC0_DISPWRDN);
190 dpmc0 &= ~DPMC0_PCLSTO_MASK;
191 dpmc0 &= ~DPMC0_DYNSREN;
Bin Meng93b4a392015-02-05 23:42:24 +0800192 msg_port_write(MEM_CTLR, DPMC0, dpmc0);
193
194 /* Disable out of order transactions */
195 dsch = msg_port_read(MEM_CTLR, DSCH);
Bin Meng15e3f282015-03-10 18:31:20 +0800196 dsch |= (DSCH_OOODIS | DSCH_NEWBYPDIS);
Bin Meng93b4a392015-02-05 23:42:24 +0800197 msg_port_write(MEM_CTLR, DSCH, dsch);
198
199 /* Disable issuing the REF command */
200 drfc = msg_port_read(MEM_CTLR, DRFC);
Bin Meng15e3f282015-03-10 18:31:20 +0800201 drfc &= ~DRFC_TREFI_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800202 msg_port_write(MEM_CTLR, DRFC, drfc);
203
204 /* Disable ZQ calibration short */
205 dcal = msg_port_read(MEM_CTLR, DCAL);
Bin Meng15e3f282015-03-10 18:31:20 +0800206 dcal &= ~DCAL_ZQCINT_MASK;
207 dcal &= ~DCAL_SRXZQCL_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +0800208 msg_port_write(MEM_CTLR, DCAL, dcal);
209
210 /*
211 * Training performed in address mode 0, rank population has limited
212 * impact, however simulator complains if enabled non-existing rank.
213 */
214 drp = 0;
215 if (mrc_params->rank_enables & 1)
Bin Meng15e3f282015-03-10 18:31:20 +0800216 drp |= DRP_RKEN0;
Bin Meng93b4a392015-02-05 23:42:24 +0800217 if (mrc_params->rank_enables & 2)
Bin Meng15e3f282015-03-10 18:31:20 +0800218 drp |= DRP_RKEN1;
Bin Meng93b4a392015-02-05 23:42:24 +0800219 msg_port_write(MEM_CTLR, DRP, drp);
220
221 LEAVEFN();
222}
223
224/*
225 * After Cold Reset, BIOS should set COLDWAKE bit to 1 before
226 * sending the WAKE message to the Dunit.
227 *
228 * For Standby Exit, or any other mode in which the DRAM is in
229 * SR, this bit must be set to 0.
230 */
231void perform_ddr_reset(struct mrc_params *mrc_params)
232{
233 ENTERFN();
234
235 /* Set COLDWAKE bit before sending the WAKE message */
Bin Meng15e3f282015-03-10 18:31:20 +0800236 mrc_write_mask(MEM_CTLR, DRMC, DRMC_COLDWAKE, DRMC_COLDWAKE);
Bin Meng93b4a392015-02-05 23:42:24 +0800237
238 /* Send wake command to DUNIT (MUST be done before JEDEC) */
239 dram_wake_command();
240
241 /* Set default value */
242 msg_port_write(MEM_CTLR, DRMC,
Bin Meng15e3f282015-03-10 18:31:20 +0800243 mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0);
Bin Meng93b4a392015-02-05 23:42:24 +0800244
245 LEAVEFN();
246}
247
248
249/*
250 * This function performs some initialization on the DDRIO unit.
251 * This function is dependent on BOARD_ID, DDR_SPEED, and CHANNEL_ENABLES.
252 */
253void ddrphy_init(struct mrc_params *mrc_params)
254{
255 uint32_t temp;
256 uint8_t ch; /* channel counter */
257 uint8_t rk; /* rank counter */
258 uint8_t bl_grp; /* byte lane group counter (2 BLs per module) */
259 uint8_t bl_divisor = 1; /* byte lane divisor */
260 /* For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333 */
Bin Meng15e3f282015-03-10 18:31:20 +0800261 uint8_t speed = mrc_params->ddr_speed & 3;
Bin Meng93b4a392015-02-05 23:42:24 +0800262 uint8_t cas;
263 uint8_t cwl;
264
265 ENTERFN();
266
267 cas = mrc_params->params.cl;
268 cwl = 5 + mrc_params->ddr_speed;
269
270 /* ddrphy_init starts */
271 mrc_post_code(0x03, 0x00);
272
273 /*
274 * HSD#231531
275 * Make sure IOBUFACT is deasserted before initializing the DDR PHY
276 *
277 * HSD#234845
278 * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
279 */
280 for (ch = 0; ch < NUM_CHANNELS; ch++) {
281 if (mrc_params->channel_enables & (1 << ch)) {
282 /* Deassert DDRPHY Initialization Complete */
283 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800284 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
285 ~(1 << 20), 1 << 20); /* SPID_INIT_COMPLETE=0 */
Bin Meng93b4a392015-02-05 23:42:24 +0800286 /* Deassert IOBUFACT */
287 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800288 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
289 ~(1 << 2), 1 << 2); /* IOBUFACTRST_N=0 */
Bin Meng93b4a392015-02-05 23:42:24 +0800290 /* Disable WRPTR */
291 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800292 CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
293 ~(1 << 0), 1 << 0); /* WRPTRENABLE=0 */
Bin Meng93b4a392015-02-05 23:42:24 +0800294 }
295 }
296
297 /* Put PHY in reset */
Bin Meng15e3f282015-03-10 18:31:20 +0800298 mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, 1);
Bin Meng93b4a392015-02-05 23:42:24 +0800299
300 /* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */
301
302 /* STEP0 */
303 mrc_post_code(0x03, 0x10);
304 for (ch = 0; ch < NUM_CHANNELS; ch++) {
305 if (mrc_params->channel_enables & (1 << ch)) {
306 /* DQ01-DQ23 */
307 for (bl_grp = 0;
Bin Meng15e3f282015-03-10 18:31:20 +0800308 bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
Bin Meng93b4a392015-02-05 23:42:24 +0800309 bl_grp++) {
310 /* Analog MUX select - IO2xCLKSEL */
311 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800312 DQOBSCKEBBCTL +
313 bl_grp * DDRIODQ_BL_OFFSET +
314 ch * DDRIODQ_CH_OFFSET,
315 bl_grp ? 0 : (1 << 22), 1 << 22);
Bin Meng93b4a392015-02-05 23:42:24 +0800316
317 /* ODT Strength */
318 switch (mrc_params->rd_odt_value) {
319 case 1:
320 temp = 0x3;
321 break; /* 60 ohm */
322 case 2:
323 temp = 0x3;
324 break; /* 120 ohm */
325 case 3:
326 temp = 0x3;
327 break; /* 180 ohm */
328 default:
329 temp = 0x3;
330 break; /* 120 ohm */
331 }
332
333 /* ODT strength */
334 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800335 B0RXIOBUFCTL +
336 bl_grp * DDRIODQ_BL_OFFSET +
337 ch * DDRIODQ_CH_OFFSET,
338 temp << 5, 0x60);
Bin Meng93b4a392015-02-05 23:42:24 +0800339 /* ODT strength */
340 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800341 B1RXIOBUFCTL +
342 bl_grp * DDRIODQ_BL_OFFSET +
343 ch * DDRIODQ_CH_OFFSET,
344 temp << 5, 0x60);
Bin Meng93b4a392015-02-05 23:42:24 +0800345
346 /* Dynamic ODT/DIFFAMP */
Bin Meng15e3f282015-03-10 18:31:20 +0800347 temp = (cas << 24) | (cas << 16) |
348 (cas << 8) | (cas << 0);
Bin Meng93b4a392015-02-05 23:42:24 +0800349 switch (speed) {
350 case 0:
351 temp -= 0x01010101;
352 break; /* 800 */
353 case 1:
354 temp -= 0x02020202;
355 break; /* 1066 */
356 case 2:
357 temp -= 0x03030303;
358 break; /* 1333 */
359 case 3:
360 temp -= 0x04040404;
361 break; /* 1600 */
362 }
363
364 /* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
365 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800366 B01LATCTL1 +
367 bl_grp * DDRIODQ_BL_OFFSET +
368 ch * DDRIODQ_CH_OFFSET,
369 temp, 0x1f1f1f1f);
Bin Meng93b4a392015-02-05 23:42:24 +0800370 switch (speed) {
371 /* HSD#234715 */
372 case 0:
Bin Meng15e3f282015-03-10 18:31:20 +0800373 temp = (0x06 << 16) | (0x07 << 8);
Bin Meng93b4a392015-02-05 23:42:24 +0800374 break; /* 800 */
375 case 1:
Bin Meng15e3f282015-03-10 18:31:20 +0800376 temp = (0x07 << 16) | (0x08 << 8);
Bin Meng93b4a392015-02-05 23:42:24 +0800377 break; /* 1066 */
378 case 2:
Bin Meng15e3f282015-03-10 18:31:20 +0800379 temp = (0x09 << 16) | (0x0a << 8);
Bin Meng93b4a392015-02-05 23:42:24 +0800380 break; /* 1333 */
381 case 3:
Bin Meng15e3f282015-03-10 18:31:20 +0800382 temp = (0x0a << 16) | (0x0b << 8);
Bin Meng93b4a392015-02-05 23:42:24 +0800383 break; /* 1600 */
384 }
385
386 /* On Duration: ODT, DIFFAMP */
387 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800388 B0ONDURCTL +
389 bl_grp * DDRIODQ_BL_OFFSET +
390 ch * DDRIODQ_CH_OFFSET,
391 temp, 0x003f3f00);
Bin Meng93b4a392015-02-05 23:42:24 +0800392 /* On Duration: ODT, DIFFAMP */
393 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800394 B1ONDURCTL +
395 bl_grp * DDRIODQ_BL_OFFSET +
396 ch * DDRIODQ_CH_OFFSET,
397 temp, 0x003f3f00);
Bin Meng93b4a392015-02-05 23:42:24 +0800398
399 switch (mrc_params->rd_odt_value) {
400 case 0:
401 /* override DIFFAMP=on, ODT=off */
Bin Meng15e3f282015-03-10 18:31:20 +0800402 temp = (0x3f << 16) | (0x3f << 10);
Bin Meng93b4a392015-02-05 23:42:24 +0800403 break;
404 default:
405 /* override DIFFAMP=on, ODT=on */
Bin Meng15e3f282015-03-10 18:31:20 +0800406 temp = (0x3f << 16) | (0x2a << 10);
Bin Meng93b4a392015-02-05 23:42:24 +0800407 break;
408 }
409
410 /* Override: DIFFAMP, ODT */
411 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800412 B0OVRCTL +
413 bl_grp * DDRIODQ_BL_OFFSET +
414 ch * DDRIODQ_CH_OFFSET,
415 temp, 0x003ffc00);
Bin Meng93b4a392015-02-05 23:42:24 +0800416 /* Override: DIFFAMP, ODT */
417 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800418 B1OVRCTL +
419 bl_grp * DDRIODQ_BL_OFFSET +
420 ch * DDRIODQ_CH_OFFSET,
421 temp, 0x003ffc00);
Bin Meng93b4a392015-02-05 23:42:24 +0800422
423 /* DLL Setup */
424
425 /* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
426 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800427 B0LATCTL0 +
428 bl_grp * DDRIODQ_BL_OFFSET +
429 ch * DDRIODQ_CH_OFFSET,
430 ((cas + 7) << 16) | ((cas - 4) << 8) |
431 ((cwl - 2) << 0), 0x003f1f1f);
Bin Meng93b4a392015-02-05 23:42:24 +0800432 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800433 B1LATCTL0 +
434 bl_grp * DDRIODQ_BL_OFFSET +
435 ch * DDRIODQ_CH_OFFSET,
436 ((cas + 7) << 16) | ((cas - 4) << 8) |
437 ((cwl - 2) << 0), 0x003f1f1f);
Bin Meng93b4a392015-02-05 23:42:24 +0800438
439 /* RCVEN Bypass (PO) */
440 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800441 B0RXIOBUFCTL +
442 bl_grp * DDRIODQ_BL_OFFSET +
443 ch * DDRIODQ_CH_OFFSET,
444 0, 0x81);
Bin Meng93b4a392015-02-05 23:42:24 +0800445 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800446 B1RXIOBUFCTL +
447 bl_grp * DDRIODQ_BL_OFFSET +
448 ch * DDRIODQ_CH_OFFSET,
449 0, 0x81);
Bin Meng93b4a392015-02-05 23:42:24 +0800450
451 /* TX */
452 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800453 DQCTL +
454 bl_grp * DDRIODQ_BL_OFFSET +
455 ch * DDRIODQ_CH_OFFSET,
456 1 << 16, 1 << 16);
Bin Meng93b4a392015-02-05 23:42:24 +0800457 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800458 B01PTRCTL1 +
459 bl_grp * DDRIODQ_BL_OFFSET +
460 ch * DDRIODQ_CH_OFFSET,
461 1 << 8, 1 << 8);
Bin Meng93b4a392015-02-05 23:42:24 +0800462
463 /* RX (PO) */
464 /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
465 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800466 B0VREFCTL +
467 bl_grp * DDRIODQ_BL_OFFSET +
468 ch * DDRIODQ_CH_OFFSET,
469 (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
470 0xff);
Bin Meng93b4a392015-02-05 23:42:24 +0800471 /* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
472 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800473 B1VREFCTL +
474 bl_grp * DDRIODQ_BL_OFFSET +
475 ch * DDRIODQ_CH_OFFSET,
476 (0x03 << 2) | (0x0 << 1) | (0x0 << 0),
477 0xff);
Bin Meng93b4a392015-02-05 23:42:24 +0800478 /* Per-Bit De-Skew Enable */
479 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800480 B0RXIOBUFCTL +
481 bl_grp * DDRIODQ_BL_OFFSET +
482 ch * DDRIODQ_CH_OFFSET,
483 0, 0x10);
Bin Meng93b4a392015-02-05 23:42:24 +0800484 /* Per-Bit De-Skew Enable */
485 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800486 B1RXIOBUFCTL +
487 bl_grp * DDRIODQ_BL_OFFSET +
488 ch * DDRIODQ_CH_OFFSET,
489 0, 0x10);
Bin Meng93b4a392015-02-05 23:42:24 +0800490 }
491
492 /* CLKEBB */
493 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800494 CMDOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
495 0, 1 << 23);
Bin Meng93b4a392015-02-05 23:42:24 +0800496
497 /* Enable tristate control of cmd/address bus */
498 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800499 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
500 0, 0x03);
Bin Meng93b4a392015-02-05 23:42:24 +0800501
502 /* ODT RCOMP */
503 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800504 CMDRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
505 (0x03 << 5) | (0x03 << 0), 0x3ff);
Bin Meng93b4a392015-02-05 23:42:24 +0800506
507 /* CMDPM* registers must be programmed in this order */
508
509 /* Turn On Delays: SFR (regulator), MPLL */
510 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800511 CMDPMDLYREG4 + ch * DDRIOCCC_CH_OFFSET,
512 0xffffffff, 0xffffffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800513 /*
514 * Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3,
515 * VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT
516 * for_PM_MSG_gt0, MDLL Turn On
517 */
518 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800519 CMDPMDLYREG3 + ch * DDRIOCCC_CH_OFFSET,
520 0xfffff616, 0xffffffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800521 /* MPLL Divider Reset Delays */
522 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800523 CMDPMDLYREG2 + ch * DDRIOCCC_CH_OFFSET,
524 0xffffffff, 0xffffffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800525 /* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
526 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800527 CMDPMDLYREG1 + ch * DDRIOCCC_CH_OFFSET,
528 0xffffffff, 0xffffffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800529 /* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
530 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800531 CMDPMDLYREG0 + ch * DDRIOCCC_CH_OFFSET,
532 0xffffffff, 0xffffffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800533 /* Allow PUnit signals */
534 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800535 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
536 (0x6 << 8) | (0x1 << 6) | (0x4 << 0),
537 0xffe00f4f);
Bin Meng93b4a392015-02-05 23:42:24 +0800538 /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
539 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800540 CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
541 (0x3 << 4) | (0x7 << 0), 0x7f);
Bin Meng93b4a392015-02-05 23:42:24 +0800542
543 /* CLK-CTL */
544 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800545 CCOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
546 0, 1 << 24); /* CLKEBB */
Bin Meng93b4a392015-02-05 23:42:24 +0800547 /* Buffer Enable: CS,CKE,ODT,CLK */
548 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800549 CCCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
550 0x1f, 0x000ffff1);
Bin Meng93b4a392015-02-05 23:42:24 +0800551 /* ODT RCOMP */
552 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800553 CCRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
554 (0x03 << 8) | (0x03 << 0), 0x00001f1f);
Bin Meng93b4a392015-02-05 23:42:24 +0800555 /* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
556 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800557 CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
558 (0x3 << 4) | (0x7 << 0), 0x7f);
Bin Meng93b4a392015-02-05 23:42:24 +0800559
560 /*
561 * COMP (RON channel specific)
562 * - DQ/DQS/DM RON: 32 Ohm
563 * - CTRL/CMD RON: 27 Ohm
564 * - CLK RON: 26 Ohm
565 */
566 /* RCOMP Vref PU/PD */
567 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800568 DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
569 (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800570 /* RCOMP Vref PU/PD */
571 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800572 CMDVREFCH0 + ch * DDRCOMP_CH_OFFSET,
573 (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800574 /* RCOMP Vref PU/PD */
575 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800576 CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
577 (0x0F << 24) | (0x03 << 16), 0x3f3f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800578 /* RCOMP Vref PU/PD */
579 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800580 DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
581 (0x08 << 24) | (0x03 << 16), 0x3f3f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800582 /* RCOMP Vref PU/PD */
583 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800584 CTLVREFCH0 + ch * DDRCOMP_CH_OFFSET,
585 (0x0C << 24) | (0x03 << 16), 0x3f3f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800586
587 /* DQS Swapped Input Enable */
588 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800589 COMPEN1CH0 + ch * DDRCOMP_CH_OFFSET,
590 (1 << 19) | (1 << 17), 0xc00ac000);
Bin Meng93b4a392015-02-05 23:42:24 +0800591
592 /* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
593 /* ODT Vref PU/PD */
594 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800595 DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
596 (0x32 << 8) | (0x03 << 0), 0x00003f3f);
Bin Meng93b4a392015-02-05 23:42:24 +0800597 /* ODT Vref PU/PD */
598 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800599 DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
600 (0x32 << 8) | (0x03 << 0), 0x00003f3f);
Bin Meng93b4a392015-02-05 23:42:24 +0800601 /* ODT Vref PU/PD */
602 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800603 CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
604 (0x0E << 8) | (0x05 << 0), 0x00003f3f);
Bin Meng93b4a392015-02-05 23:42:24 +0800605
606 /*
607 * Slew rate settings are frequency specific,
608 * numbers below are for 800Mhz (speed == 0)
609 * - DQ/DQS/DM/CLK SR: 4V/ns,
610 * - CTRL/CMD SR: 1.5V/ns
611 */
Bin Meng15e3f282015-03-10 18:31:20 +0800612 temp = (0x0e << 16) | (0x0e << 12) | (0x08 << 8) |
613 (0x0b << 4) | (0x0b << 0);
Bin Meng93b4a392015-02-05 23:42:24 +0800614 /* DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ */
615 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800616 DLYSELCH0 + ch * DDRCOMP_CH_OFFSET,
617 temp, 0x000fffff);
Bin Meng93b4a392015-02-05 23:42:24 +0800618 /* TCO Vref CLK,DQS,DQ */
619 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800620 TCOVREFCH0 + ch * DDRCOMP_CH_OFFSET,
621 (0x05 << 16) | (0x05 << 8) | (0x05 << 0),
622 0x003f3f3f);
Bin Meng93b4a392015-02-05 23:42:24 +0800623 /* ODTCOMP CMD/CTL PU/PD */
624 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800625 CCBUFODTCH0 + ch * DDRCOMP_CH_OFFSET,
626 (0x03 << 8) | (0x03 << 0),
627 0x00001f1f);
Bin Meng93b4a392015-02-05 23:42:24 +0800628 /* COMP */
629 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800630 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
631 0, 0xc0000100);
Bin Meng93b4a392015-02-05 23:42:24 +0800632
633#ifdef BACKUP_COMPS
634 /* DQ COMP Overrides */
635 /* RCOMP PU */
636 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800637 DQDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
638 (1 << 31) | (0x0a << 16),
639 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800640 /* RCOMP PD */
641 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800642 DQDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
643 (1 << 31) | (0x0a << 16),
644 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800645 /* DCOMP PU */
646 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800647 DQDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
648 (1 << 31) | (0x10 << 16),
649 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800650 /* DCOMP PD */
651 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800652 DQDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
653 (1 << 31) | (0x10 << 16),
654 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800655 /* ODTCOMP PU */
656 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800657 DQODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
658 (1 << 31) | (0x0b << 16),
659 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800660 /* ODTCOMP PD */
661 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800662 DQODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
663 (1 << 31) | (0x0b << 16),
664 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800665 /* TCOCOMP PU */
666 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800667 DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
668 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800669 /* TCOCOMP PD */
670 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800671 DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
672 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800673
674 /* DQS COMP Overrides */
675 /* RCOMP PU */
676 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800677 DQSDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
678 (1 << 31) | (0x0a << 16),
679 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800680 /* RCOMP PD */
681 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800682 DQSDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
683 (1 << 31) | (0x0a << 16),
684 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800685 /* DCOMP PU */
686 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800687 DQSDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
688 (1 << 31) | (0x10 << 16),
689 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800690 /* DCOMP PD */
691 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800692 DQSDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
693 (1 << 31) | (0x10 << 16),
694 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800695 /* ODTCOMP PU */
696 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800697 DQSODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
698 (1 << 31) | (0x0b << 16),
699 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800700 /* ODTCOMP PD */
701 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800702 DQSODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
703 (1 << 31) | (0x0b << 16),
704 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800705 /* TCOCOMP PU */
706 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800707 DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
708 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800709 /* TCOCOMP PD */
710 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800711 DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
712 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800713
714 /* CLK COMP Overrides */
715 /* RCOMP PU */
716 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800717 CLKDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
718 (1 << 31) | (0x0c << 16),
719 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800720 /* RCOMP PD */
721 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800722 CLKDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
723 (1 << 31) | (0x0c << 16),
724 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800725 /* DCOMP PU */
726 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800727 CLKDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
728 (1 << 31) | (0x07 << 16),
729 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800730 /* DCOMP PD */
731 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800732 CLKDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
733 (1 << 31) | (0x07 << 16),
734 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800735 /* ODTCOMP PU */
736 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800737 CLKODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
738 (1 << 31) | (0x0b << 16),
739 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800740 /* ODTCOMP PD */
741 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800742 CLKODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
743 (1 << 31) | (0x0b << 16),
744 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800745 /* TCOCOMP PU */
746 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800747 CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
748 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800749 /* TCOCOMP PD */
750 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800751 CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
752 1 << 31, 1 << 31);
Bin Meng93b4a392015-02-05 23:42:24 +0800753
754 /* CMD COMP Overrides */
755 /* RCOMP PU */
756 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800757 CMDDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
758 (1 << 31) | (0x0d << 16),
759 0x803f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800760 /* RCOMP PD */
761 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800762 CMDDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
763 (1 << 31) | (0x0d << 16),
764 0x803f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800765 /* DCOMP PU */
766 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800767 CMDDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
768 (1 << 31) | (0x0a << 16),
769 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800770 /* DCOMP PD */
771 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800772 CMDDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
773 (1 << 31) | (0x0a << 16),
774 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800775
776 /* CTL COMP Overrides */
777 /* RCOMP PU */
778 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800779 CTLDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
780 (1 << 31) | (0x0d << 16),
781 0x803f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800782 /* RCOMP PD */
783 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800784 CTLDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
785 (1 << 31) | (0x0d << 16),
786 0x803f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800787 /* DCOMP PU */
788 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800789 CTLDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
790 (1 << 31) | (0x0a << 16),
791 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800792 /* DCOMP PD */
793 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800794 CTLDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
795 (1 << 31) | (0x0a << 16),
796 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800797#else
798 /* DQ TCOCOMP Overrides */
799 /* TCOCOMP PU */
800 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800801 DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
802 (1 << 31) | (0x1f << 16),
803 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800804 /* TCOCOMP PD */
805 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800806 DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
807 (1 << 31) | (0x1f << 16),
808 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800809
810 /* DQS TCOCOMP Overrides */
811 /* TCOCOMP PU */
812 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800813 DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
814 (1 << 31) | (0x1f << 16),
815 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800816 /* TCOCOMP PD */
817 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800818 DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
819 (1 << 31) | (0x1f << 16),
820 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800821
822 /* CLK TCOCOMP Overrides */
823 /* TCOCOMP PU */
824 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800825 CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
826 (1 << 31) | (0x1f << 16),
827 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800828 /* TCOCOMP PD */
829 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800830 CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
831 (1 << 31) | (0x1f << 16),
832 0x801f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800833#endif
834
835 /* program STATIC delays */
836#ifdef BACKUP_WCMD
837 set_wcmd(ch, ddr_wcmd[PLATFORM_ID]);
838#else
839 set_wcmd(ch, ddr_wclk[PLATFORM_ID] + HALF_CLK);
840#endif
841
842 for (rk = 0; rk < NUM_RANKS; rk++) {
Bin Meng15e3f282015-03-10 18:31:20 +0800843 if (mrc_params->rank_enables & (1 << rk)) {
Bin Meng93b4a392015-02-05 23:42:24 +0800844 set_wclk(ch, rk, ddr_wclk[PLATFORM_ID]);
845#ifdef BACKUP_WCTL
846 set_wctl(ch, rk, ddr_wctl[PLATFORM_ID]);
847#else
848 set_wctl(ch, rk, ddr_wclk[PLATFORM_ID] + HALF_CLK);
849#endif
850 }
851 }
852 }
853 }
854
855 /* COMP (non channel specific) */
856 /* RCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800857 mrc_alt_write_mask(DDRPHY, DQANADRVPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800858 /* RCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800859 mrc_alt_write_mask(DDRPHY, DQANADRVPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800860 /* RCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800861 mrc_alt_write_mask(DDRPHY, CMDANADRVPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800862 /* RCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800863 mrc_alt_write_mask(DDRPHY, CMDANADRVPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800864 /* RCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800865 mrc_alt_write_mask(DDRPHY, CLKANADRVPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800866 /* RCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800867 mrc_alt_write_mask(DDRPHY, CLKANADRVPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800868 /* RCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800869 mrc_alt_write_mask(DDRPHY, DQSANADRVPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800870 /* RCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800871 mrc_alt_write_mask(DDRPHY, DQSANADRVPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800872 /* RCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800873 mrc_alt_write_mask(DDRPHY, CTLANADRVPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800874 /* RCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800875 mrc_alt_write_mask(DDRPHY, CTLANADRVPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800876 /* ODT: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800877 mrc_alt_write_mask(DDRPHY, DQANAODTPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800878 /* ODT: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800879 mrc_alt_write_mask(DDRPHY, DQANAODTPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800880 /* ODT: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800881 mrc_alt_write_mask(DDRPHY, CLKANAODTPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800882 /* ODT: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800883 mrc_alt_write_mask(DDRPHY, CLKANAODTPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800884 /* ODT: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800885 mrc_alt_write_mask(DDRPHY, DQSANAODTPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800886 /* ODT: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800887 mrc_alt_write_mask(DDRPHY, DQSANAODTPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800888 /* DCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800889 mrc_alt_write_mask(DDRPHY, DQANADLYPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800890 /* DCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800891 mrc_alt_write_mask(DDRPHY, DQANADLYPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800892 /* DCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800893 mrc_alt_write_mask(DDRPHY, CMDANADLYPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800894 /* DCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800895 mrc_alt_write_mask(DDRPHY, CMDANADLYPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800896 /* DCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800897 mrc_alt_write_mask(DDRPHY, CLKANADLYPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800898 /* DCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800899 mrc_alt_write_mask(DDRPHY, CLKANADLYPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800900 /* DCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800901 mrc_alt_write_mask(DDRPHY, DQSANADLYPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800902 /* DCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800903 mrc_alt_write_mask(DDRPHY, DQSANADLYPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800904 /* DCOMP: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800905 mrc_alt_write_mask(DDRPHY, CTLANADLYPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800906 /* DCOMP: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800907 mrc_alt_write_mask(DDRPHY, CTLANADLYPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800908 /* TCO: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800909 mrc_alt_write_mask(DDRPHY, DQANATCOPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800910 /* TCO: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800911 mrc_alt_write_mask(DDRPHY, DQANATCOPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800912 /* TCO: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800913 mrc_alt_write_mask(DDRPHY, CLKANATCOPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800914 /* TCO: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800915 mrc_alt_write_mask(DDRPHY, CLKANATCOPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800916 /* TCO: Dither PU Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800917 mrc_alt_write_mask(DDRPHY, DQSANATCOPUCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800918 /* TCO: Dither PD Enable */
Bin Meng15e3f282015-03-10 18:31:20 +0800919 mrc_alt_write_mask(DDRPHY, DQSANATCOPDCTL, 1 << 30, 1 << 30);
Bin Meng93b4a392015-02-05 23:42:24 +0800920 /* TCOCOMP: Pulse Count */
Bin Meng15e3f282015-03-10 18:31:20 +0800921 mrc_alt_write_mask(DDRPHY, TCOCNTCTRL, 1, 3);
Bin Meng93b4a392015-02-05 23:42:24 +0800922 /* ODT: CMD/CTL PD/PU */
Bin Meng15e3f282015-03-10 18:31:20 +0800923 mrc_alt_write_mask(DDRPHY, CHNLBUFSTATIC,
924 (0x03 << 24) | (0x03 << 16), 0x1f1f0000);
Bin Meng93b4a392015-02-05 23:42:24 +0800925 /* Set 1us counter */
Bin Meng15e3f282015-03-10 18:31:20 +0800926 mrc_alt_write_mask(DDRPHY, MSCNTR, 0x64, 0xff);
927 mrc_alt_write_mask(DDRPHY, LATCH1CTL, 0x1 << 28, 0x70000000);
Bin Meng93b4a392015-02-05 23:42:24 +0800928
929 /* Release PHY from reset */
Bin Meng15e3f282015-03-10 18:31:20 +0800930 mrc_alt_write_mask(DDRPHY, MASTERRSTN, 1, 1);
Bin Meng93b4a392015-02-05 23:42:24 +0800931
932 /* STEP1 */
933 mrc_post_code(0x03, 0x11);
934
935 for (ch = 0; ch < NUM_CHANNELS; ch++) {
936 if (mrc_params->channel_enables & (1 << ch)) {
937 /* DQ01-DQ23 */
938 for (bl_grp = 0;
Bin Meng15e3f282015-03-10 18:31:20 +0800939 bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
Bin Meng93b4a392015-02-05 23:42:24 +0800940 bl_grp++) {
941 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800942 DQMDLLCTL +
943 bl_grp * DDRIODQ_BL_OFFSET +
944 ch * DDRIODQ_CH_OFFSET,
945 1 << 13,
946 1 << 13); /* Enable VREG */
Bin Meng93b4a392015-02-05 23:42:24 +0800947 delay_n(3);
948 }
949
950 /* ECC */
Bin Meng15e3f282015-03-10 18:31:20 +0800951 mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
952 1 << 13, 1 << 13); /* Enable VREG */
Bin Meng93b4a392015-02-05 23:42:24 +0800953 delay_n(3);
954 /* CMD */
955 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800956 CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
957 1 << 13, 1 << 13); /* Enable VREG */
Bin Meng93b4a392015-02-05 23:42:24 +0800958 delay_n(3);
959 /* CLK-CTL */
960 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800961 CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
962 1 << 13, 1 << 13); /* Enable VREG */
Bin Meng93b4a392015-02-05 23:42:24 +0800963 delay_n(3);
964 }
965 }
966
967 /* STEP2 */
968 mrc_post_code(0x03, 0x12);
969 delay_n(200);
970
971 for (ch = 0; ch < NUM_CHANNELS; ch++) {
972 if (mrc_params->channel_enables & (1 << ch)) {
973 /* DQ01-DQ23 */
974 for (bl_grp = 0;
Bin Meng15e3f282015-03-10 18:31:20 +0800975 bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
Bin Meng93b4a392015-02-05 23:42:24 +0800976 bl_grp++) {
977 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800978 DQMDLLCTL +
979 bl_grp * DDRIODQ_BL_OFFSET +
980 ch * DDRIODQ_CH_OFFSET,
981 1 << 17,
982 1 << 17); /* Enable MCDLL */
Bin Meng93b4a392015-02-05 23:42:24 +0800983 delay_n(50);
984 }
985
986 /* ECC */
Bin Meng15e3f282015-03-10 18:31:20 +0800987 mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
988 1 << 17, 1 << 17); /* Enable MCDLL */
Bin Meng93b4a392015-02-05 23:42:24 +0800989 delay_n(50);
990 /* CMD */
991 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800992 CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
993 1 << 18, 1 << 18); /* Enable MCDLL */
Bin Meng93b4a392015-02-05 23:42:24 +0800994 delay_n(50);
995 /* CLK-CTL */
996 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +0800997 CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
998 1 << 18, 1 << 18); /* Enable MCDLL */
Bin Meng93b4a392015-02-05 23:42:24 +0800999 delay_n(50);
1000 }
1001 }
1002
1003 /* STEP3: */
1004 mrc_post_code(0x03, 0x13);
1005 delay_n(100);
1006
1007 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1008 if (mrc_params->channel_enables & (1 << ch)) {
1009 /* DQ01-DQ23 */
1010 for (bl_grp = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08001011 bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
Bin Meng93b4a392015-02-05 23:42:24 +08001012 bl_grp++) {
1013#ifdef FORCE_16BIT_DDRIO
Bin Meng15e3f282015-03-10 18:31:20 +08001014 temp = (bl_grp &&
Bin Meng93b4a392015-02-05 23:42:24 +08001015 (mrc_params->channel_width == X16)) ?
Bin Meng15e3f282015-03-10 18:31:20 +08001016 0x11ff : 0xffff;
Bin Meng93b4a392015-02-05 23:42:24 +08001017#else
Bin Meng15e3f282015-03-10 18:31:20 +08001018 temp = 0xffff;
Bin Meng93b4a392015-02-05 23:42:24 +08001019#endif
1020 /* Enable TXDLL */
1021 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001022 DQDLLTXCTL +
1023 bl_grp * DDRIODQ_BL_OFFSET +
1024 ch * DDRIODQ_CH_OFFSET,
1025 temp, 0xffff);
Bin Meng93b4a392015-02-05 23:42:24 +08001026 delay_n(3);
1027 /* Enable RXDLL */
1028 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001029 DQDLLRXCTL +
1030 bl_grp * DDRIODQ_BL_OFFSET +
1031 ch * DDRIODQ_CH_OFFSET,
1032 0xf, 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001033 delay_n(3);
1034 /* Enable RXDLL Overrides BL0 */
1035 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001036 B0OVRCTL +
1037 bl_grp * DDRIODQ_BL_OFFSET +
1038 ch * DDRIODQ_CH_OFFSET,
1039 0xf, 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001040 }
1041
1042 /* ECC */
Bin Meng15e3f282015-03-10 18:31:20 +08001043 temp = 0xffff;
1044 mrc_alt_write_mask(DDRPHY, ECCDLLTXCTL,
1045 temp, 0xffff);
Bin Meng93b4a392015-02-05 23:42:24 +08001046 delay_n(3);
1047
1048 /* CMD (PO) */
1049 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001050 CMDDLLTXCTL + ch * DDRIOCCC_CH_OFFSET,
1051 temp, 0xffff);
Bin Meng93b4a392015-02-05 23:42:24 +08001052 delay_n(3);
1053 }
1054 }
1055
1056 /* STEP4 */
1057 mrc_post_code(0x03, 0x14);
1058
1059 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1060 if (mrc_params->channel_enables & (1 << ch)) {
1061 /* Host To Memory Clock Alignment (HMC) for 800/1066 */
1062 for (bl_grp = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08001063 bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
Bin Meng93b4a392015-02-05 23:42:24 +08001064 bl_grp++) {
1065 /* CLK_ALIGN_MOD_ID */
1066 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001067 DQCLKALIGNREG2 +
1068 bl_grp * DDRIODQ_BL_OFFSET +
1069 ch * DDRIODQ_CH_OFFSET,
1070 bl_grp ? 3 : 1,
1071 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001072 }
1073
1074 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001075 ECCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1076 0x2, 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001077 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001078 CMDCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1079 0x0, 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001080 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001081 CCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
1082 0x2, 0xf);
Bin Meng93b4a392015-02-05 23:42:24 +08001083 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001084 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
1085 0x20, 0x30);
Bin Meng93b4a392015-02-05 23:42:24 +08001086 /*
1087 * NUM_SAMPLES, MAX_SAMPLES,
1088 * MACRO_PI_STEP, MICRO_PI_STEP
1089 */
1090 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001091 CMDCLKALIGNREG1 + ch * DDRIOCCC_CH_OFFSET,
1092 (0x18 << 16) | (0x10 << 8) |
1093 (0x8 << 2) | (0x1 << 0),
1094 0x007f7fff);
Bin Meng93b4a392015-02-05 23:42:24 +08001095 /* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
1096 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001097 CMDCLKALIGNREG2 + ch * DDRIOCCC_CH_OFFSET,
1098 (0x10 << 16) | (0x4 << 8) | (0x2 << 4),
1099 0x001f0ff0);
Bin Meng93b4a392015-02-05 23:42:24 +08001100#ifdef HMC_TEST
1101 /* START_CLK_ALIGN=1 */
1102 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001103 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
1104 1 << 24, 1 << 24);
Bin Meng93b4a392015-02-05 23:42:24 +08001105 while (msg_port_alt_read(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001106 CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET) &
1107 (1 << 24))
Bin Meng93b4a392015-02-05 23:42:24 +08001108 ; /* wait for START_CLK_ALIGN=0 */
1109#endif
1110
1111 /* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
1112 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001113 CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
1114 1, 1); /* WRPTRENABLE=1 */
Bin Meng93b4a392015-02-05 23:42:24 +08001115
1116 /* COMP initial */
1117 /* enable bypass for CLK buffer (PO) */
1118 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001119 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
1120 1 << 5, 1 << 5);
Bin Meng93b4a392015-02-05 23:42:24 +08001121 /* Initial COMP Enable */
Bin Meng15e3f282015-03-10 18:31:20 +08001122 mrc_alt_write_mask(DDRPHY, CMPCTRL, 1, 1);
Bin Meng93b4a392015-02-05 23:42:24 +08001123 /* wait for Initial COMP Enable = 0 */
Bin Meng15e3f282015-03-10 18:31:20 +08001124 while (msg_port_alt_read(DDRPHY, CMPCTRL) & 1)
Bin Meng93b4a392015-02-05 23:42:24 +08001125 ;
1126 /* disable bypass for CLK buffer (PO) */
1127 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001128 COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
1129 ~(1 << 5), 1 << 5);
Bin Meng93b4a392015-02-05 23:42:24 +08001130
1131 /* IOBUFACT */
1132
1133 /* STEP4a */
1134 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001135 CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
1136 1 << 2, 1 << 2); /* IOBUFACTRST_N=1 */
Bin Meng93b4a392015-02-05 23:42:24 +08001137
1138 /* DDRPHY initialization complete */
1139 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001140 CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
1141 1 << 20, 1 << 20); /* SPID_INIT_COMPLETE=1 */
Bin Meng93b4a392015-02-05 23:42:24 +08001142 }
1143 }
1144
1145 LEAVEFN();
1146}
1147
1148/* This function performs JEDEC initialization on all enabled channels */
1149void perform_jedec_init(struct mrc_params *mrc_params)
1150{
1151 uint8_t twr, wl, rank;
1152 uint32_t tck;
1153 u32 dtr0;
1154 u32 drp;
1155 u32 drmc;
1156 u32 mrs0_cmd = 0;
1157 u32 emrs1_cmd = 0;
1158 u32 emrs2_cmd = 0;
1159 u32 emrs3_cmd = 0;
1160
1161 ENTERFN();
1162
1163 /* jedec_init starts */
1164 mrc_post_code(0x04, 0x00);
1165
1166 /* DDR3_RESET_SET=0, DDR3_RESET_RESET=1 */
Bin Meng15e3f282015-03-10 18:31:20 +08001167 mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 2, 0x102);
Bin Meng93b4a392015-02-05 23:42:24 +08001168
1169 /* Assert RESET# for 200us */
1170 delay_u(200);
1171
1172 /* DDR3_RESET_SET=1, DDR3_RESET_RESET=0 */
Bin Meng15e3f282015-03-10 18:31:20 +08001173 mrc_alt_write_mask(DDRPHY, CCDDR3RESETCTL, 0x100, 0x102);
Bin Meng93b4a392015-02-05 23:42:24 +08001174
1175 dtr0 = msg_port_read(MEM_CTLR, DTR0);
1176
1177 /*
1178 * Set CKEVAL for populated ranks
1179 * then send NOP to each rank (#4550197)
1180 */
1181
1182 drp = msg_port_read(MEM_CTLR, DRP);
1183 drp &= 0x3;
1184
1185 drmc = msg_port_read(MEM_CTLR, DRMC);
Bin Meng15e3f282015-03-10 18:31:20 +08001186 drmc &= 0xfffffffc;
1187 drmc |= (DRMC_CKEMODE | drp);
Bin Meng93b4a392015-02-05 23:42:24 +08001188
1189 msg_port_write(MEM_CTLR, DRMC, drmc);
1190
1191 for (rank = 0; rank < NUM_RANKS; rank++) {
1192 /* Skip to next populated rank */
1193 if ((mrc_params->rank_enables & (1 << rank)) == 0)
1194 continue;
1195
1196 dram_init_command(DCMD_NOP(rank));
1197 }
1198
1199 msg_port_write(MEM_CTLR, DRMC,
Bin Meng15e3f282015-03-10 18:31:20 +08001200 (mrc_params->rd_odt_value == 0 ? DRMC_ODTMODE : 0));
Bin Meng93b4a392015-02-05 23:42:24 +08001201
1202 /*
1203 * setup for emrs 2
1204 * BIT[15:11] --> Always "0"
1205 * BIT[10:09] --> Rtt_WR: want "Dynamic ODT Off" (0)
1206 * BIT[08] --> Always "0"
1207 * BIT[07] --> SRT: use sr_temp_range
1208 * BIT[06] --> ASR: want "Manual SR Reference" (0)
1209 * BIT[05:03] --> CWL: use oem_tCWL
1210 * BIT[02:00] --> PASR: want "Full Array" (0)
1211 */
1212 emrs2_cmd |= (2 << 3);
1213 wl = 5 + mrc_params->ddr_speed;
1214 emrs2_cmd |= ((wl - 5) << 9);
1215 emrs2_cmd |= (mrc_params->sr_temp_range << 13);
1216
1217 /*
1218 * setup for emrs 3
1219 * BIT[15:03] --> Always "0"
1220 * BIT[02] --> MPR: want "Normal Operation" (0)
1221 * BIT[01:00] --> MPR_Loc: want "Predefined Pattern" (0)
1222 */
1223 emrs3_cmd |= (3 << 3);
1224
1225 /*
1226 * setup for emrs 1
1227 * BIT[15:13] --> Always "0"
1228 * BIT[12:12] --> Qoff: want "Output Buffer Enabled" (0)
1229 * BIT[11:11] --> TDQS: want "Disabled" (0)
1230 * BIT[10:10] --> Always "0"
1231 * BIT[09,06,02] --> Rtt_nom: use rtt_nom_value
1232 * BIT[08] --> Always "0"
1233 * BIT[07] --> WR_LVL: want "Disabled" (0)
1234 * BIT[05,01] --> DIC: use ron_value
1235 * BIT[04:03] --> AL: additive latency want "0" (0)
1236 * BIT[00] --> DLL: want "Enable" (0)
1237 *
1238 * (BIT5|BIT1) set Ron value
1239 * 00 --> RZQ/6 (40ohm)
1240 * 01 --> RZQ/7 (34ohm)
1241 * 1* --> RESERVED
1242 *
1243 * (BIT9|BIT6|BIT2) set Rtt_nom value
1244 * 000 --> Disabled
1245 * 001 --> RZQ/4 ( 60ohm)
1246 * 010 --> RZQ/2 (120ohm)
1247 * 011 --> RZQ/6 ( 40ohm)
1248 * 1** --> RESERVED
1249 */
1250 emrs1_cmd |= (1 << 3);
Bin Meng15e3f282015-03-10 18:31:20 +08001251 emrs1_cmd &= ~(1 << 6);
Bin Meng93b4a392015-02-05 23:42:24 +08001252
1253 if (mrc_params->ron_value == 0)
Bin Meng15e3f282015-03-10 18:31:20 +08001254 emrs1_cmd |= (1 << 7);
Bin Meng93b4a392015-02-05 23:42:24 +08001255 else
Bin Meng15e3f282015-03-10 18:31:20 +08001256 emrs1_cmd &= ~(1 << 7);
Bin Meng93b4a392015-02-05 23:42:24 +08001257
1258 if (mrc_params->rtt_nom_value == 0)
1259 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_40 << 6);
1260 else if (mrc_params->rtt_nom_value == 1)
1261 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_60 << 6);
1262 else if (mrc_params->rtt_nom_value == 2)
1263 emrs1_cmd |= (DDR3_EMRS1_RTTNOM_120 << 6);
1264
1265 /* save MRS1 value (excluding control fields) */
1266 mrc_params->mrs1 = emrs1_cmd >> 6;
1267
1268 /*
1269 * setup for mrs 0
1270 * BIT[15:13] --> Always "0"
1271 * BIT[12] --> PPD: for Quark (1)
1272 * BIT[11:09] --> WR: use oem_tWR
1273 * BIT[08] --> DLL: want "Reset" (1, self clearing)
1274 * BIT[07] --> MODE: want "Normal" (0)
1275 * BIT[06:04,02] --> CL: use oem_tCAS
1276 * BIT[03] --> RD_BURST_TYPE: want "Interleave" (1)
1277 * BIT[01:00] --> BL: want "8 Fixed" (0)
1278 * WR:
1279 * 0 --> 16
1280 * 1 --> 5
1281 * 2 --> 6
1282 * 3 --> 7
1283 * 4 --> 8
1284 * 5 --> 10
1285 * 6 --> 12
1286 * 7 --> 14
1287 * CL:
1288 * BIT[02:02] "0" if oem_tCAS <= 11 (1866?)
1289 * BIT[06:04] use oem_tCAS-4
1290 */
Bin Meng15e3f282015-03-10 18:31:20 +08001291 mrs0_cmd |= (1 << 14);
1292 mrs0_cmd |= (1 << 18);
Bin Meng93b4a392015-02-05 23:42:24 +08001293 mrs0_cmd |= ((((dtr0 >> 12) & 7) + 1) << 10);
1294
1295 tck = t_ck[mrc_params->ddr_speed];
1296 /* Per JEDEC: tWR=15000ps DDR2/3 from 800-1600 */
1297 twr = MCEIL(15000, tck);
1298 mrs0_cmd |= ((twr - 4) << 15);
1299
1300 for (rank = 0; rank < NUM_RANKS; rank++) {
1301 /* Skip to next populated rank */
1302 if ((mrc_params->rank_enables & (1 << rank)) == 0)
1303 continue;
1304
1305 emrs2_cmd |= (rank << 22);
1306 dram_init_command(emrs2_cmd);
1307
1308 emrs3_cmd |= (rank << 22);
1309 dram_init_command(emrs3_cmd);
1310
1311 emrs1_cmd |= (rank << 22);
1312 dram_init_command(emrs1_cmd);
1313
1314 mrs0_cmd |= (rank << 22);
1315 dram_init_command(mrs0_cmd);
1316
1317 dram_init_command(DCMD_ZQCL(rank));
1318 }
1319
1320 LEAVEFN();
1321}
1322
1323/*
1324 * Dunit Initialization Complete
1325 *
1326 * Indicates that initialization of the Dunit has completed.
1327 *
1328 * Memory accesses are permitted and maintenance operation begins.
1329 * Until this bit is set to a 1, the memory controller will not accept
1330 * DRAM requests from the MEMORY_MANAGER or HTE.
1331 */
1332void set_ddr_init_complete(struct mrc_params *mrc_params)
1333{
1334 u32 dco;
1335
1336 ENTERFN();
1337
1338 dco = msg_port_read(MEM_CTLR, DCO);
Bin Meng15e3f282015-03-10 18:31:20 +08001339 dco &= ~DCO_PMICTL;
1340 dco |= DCO_IC;
Bin Meng93b4a392015-02-05 23:42:24 +08001341 msg_port_write(MEM_CTLR, DCO, dco);
1342
1343 LEAVEFN();
1344}
1345
1346/*
1347 * This function will retrieve relevant timing data
1348 *
1349 * This data will be used on subsequent boots to speed up boot times
1350 * and is required for Suspend To RAM capabilities.
1351 */
1352void restore_timings(struct mrc_params *mrc_params)
1353{
1354 uint8_t ch, rk, bl;
1355 const struct mrc_timings *mt = &mrc_params->timings;
1356
1357 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1358 for (rk = 0; rk < NUM_RANKS; rk++) {
1359 for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
1360 set_rcvn(ch, rk, bl, mt->rcvn[ch][rk][bl]);
1361 set_rdqs(ch, rk, bl, mt->rdqs[ch][rk][bl]);
1362 set_wdqs(ch, rk, bl, mt->wdqs[ch][rk][bl]);
1363 set_wdq(ch, rk, bl, mt->wdq[ch][rk][bl]);
1364 if (rk == 0) {
1365 /* VREF (RANK0 only) */
1366 set_vref(ch, bl, mt->vref[ch][bl]);
1367 }
1368 }
1369 set_wctl(ch, rk, mt->wctl[ch][rk]);
1370 }
1371 set_wcmd(ch, mt->wcmd[ch]);
1372 }
1373}
1374
1375/*
1376 * Configure default settings normally set as part of read training
1377 *
1378 * Some defaults have to be set earlier as they may affect earlier
1379 * training steps.
1380 */
1381void default_timings(struct mrc_params *mrc_params)
1382{
1383 uint8_t ch, rk, bl;
1384
1385 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1386 for (rk = 0; rk < NUM_RANKS; rk++) {
1387 for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
1388 set_rdqs(ch, rk, bl, 24);
1389 if (rk == 0) {
1390 /* VREF (RANK0 only) */
1391 set_vref(ch, bl, 32);
1392 }
1393 }
1394 }
1395 }
1396}
1397
1398/*
1399 * This function will perform our RCVEN Calibration Algorithm.
1400 * We will only use the 2xCLK domain timings to perform RCVEN Calibration.
1401 * All byte lanes will be calibrated "simultaneously" per channel per rank.
1402 */
1403void rcvn_cal(struct mrc_params *mrc_params)
1404{
1405 uint8_t ch; /* channel counter */
1406 uint8_t rk; /* rank counter */
1407 uint8_t bl; /* byte lane counter */
1408 uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1409
1410#ifdef R2R_SHARING
1411 /* used to find placement for rank2rank sharing configs */
1412 uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1413#ifndef BACKUP_RCVN
1414 /* used to find placement for rank2rank sharing configs */
1415 uint32_t num_ranks_enabled = 0;
1416#endif
1417#endif
1418
1419#ifdef BACKUP_RCVN
1420#else
1421 uint32_t temp;
1422 /* absolute PI value to be programmed on the byte lane */
1423 uint32_t delay[NUM_BYTE_LANES];
1424 u32 dtr1, dtr1_save;
1425#endif
1426
1427 ENTERFN();
1428
1429 /* rcvn_cal starts */
1430 mrc_post_code(0x05, 0x00);
1431
1432#ifndef BACKUP_RCVN
1433 /* need separate burst to sample DQS preamble */
1434 dtr1 = msg_port_read(MEM_CTLR, DTR1);
1435 dtr1_save = dtr1;
Bin Meng15e3f282015-03-10 18:31:20 +08001436 dtr1 |= DTR1_TCCD_12CLK;
Bin Meng93b4a392015-02-05 23:42:24 +08001437 msg_port_write(MEM_CTLR, DTR1, dtr1);
1438#endif
1439
1440#ifdef R2R_SHARING
1441 /* need to set "final_delay[][]" elements to "0" */
1442 memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1443#endif
1444
1445 /* loop through each enabled channel */
1446 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1447 if (mrc_params->channel_enables & (1 << ch)) {
1448 /* perform RCVEN Calibration on a per rank basis */
1449 for (rk = 0; rk < NUM_RANKS; rk++) {
1450 if (mrc_params->rank_enables & (1 << rk)) {
1451 /*
1452 * POST_CODE here indicates the current
1453 * channel and rank being calibrated
1454 */
Bin Meng15e3f282015-03-10 18:31:20 +08001455 mrc_post_code(0x05, 0x10 + ((ch << 4) | rk));
Bin Meng93b4a392015-02-05 23:42:24 +08001456
1457#ifdef BACKUP_RCVN
1458 /* et hard-coded timing values */
1459 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++)
1460 set_rcvn(ch, rk, bl, ddr_rcvn[PLATFORM_ID]);
1461#else
1462 /* enable FIFORST */
1463 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
1464 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001465 B01PTRCTL1 +
1466 (bl >> 1) * DDRIODQ_BL_OFFSET +
1467 ch * DDRIODQ_CH_OFFSET,
1468 0, 1 << 8);
Bin Meng93b4a392015-02-05 23:42:24 +08001469 }
1470 /* initialize the starting delay to 128 PI (cas +1 CLK) */
1471 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1472 /* 1x CLK domain timing is cas-4 */
1473 delay[bl] = (4 + 1) * FULL_CLK;
1474
1475 set_rcvn(ch, rk, bl, delay[bl]);
1476 }
1477
1478 /* now find the rising edge */
1479 find_rising_edge(mrc_params, delay, ch, rk, true);
1480
1481 /* Now increase delay by 32 PI (1/4 CLK) to place in center of high pulse */
1482 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1483 delay[bl] += QRTR_CLK;
1484 set_rcvn(ch, rk, bl, delay[bl]);
1485 }
1486 /* Now decrement delay by 128 PI (1 CLK) until we sample a "0" */
1487 do {
1488 temp = sample_dqs(mrc_params, ch, rk, true);
1489 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1490 if (temp & (1 << bl)) {
1491 if (delay[bl] >= FULL_CLK) {
1492 delay[bl] -= FULL_CLK;
1493 set_rcvn(ch, rk, bl, delay[bl]);
1494 } else {
1495 /* not enough delay */
1496 training_message(ch, rk, bl);
Bin Meng15e3f282015-03-10 18:31:20 +08001497 mrc_post_code(0xee, 0x50);
Bin Meng93b4a392015-02-05 23:42:24 +08001498 }
1499 }
1500 }
Bin Meng15e3f282015-03-10 18:31:20 +08001501 } while (temp & 0xff);
Bin Meng93b4a392015-02-05 23:42:24 +08001502
1503#ifdef R2R_SHARING
1504 /* increment "num_ranks_enabled" */
1505 num_ranks_enabled++;
1506 /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
1507 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1508 delay[bl] += QRTR_CLK;
1509 /* add "delay[]" values to "final_delay[][]" for rolling average */
1510 final_delay[ch][bl] += delay[bl];
1511 /* set timing based on rolling average values */
Bin Meng15e3f282015-03-10 18:31:20 +08001512 set_rcvn(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
Bin Meng93b4a392015-02-05 23:42:24 +08001513 }
1514#else
1515 /* Finally increment delay by 32 PI (1/4 CLK) to place in center of preamble */
1516 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1517 delay[bl] += QRTR_CLK;
1518 set_rcvn(ch, rk, bl, delay[bl]);
1519 }
1520#endif
1521
1522 /* disable FIFORST */
1523 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl += 2) {
1524 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001525 B01PTRCTL1 +
1526 (bl >> 1) * DDRIODQ_BL_OFFSET +
1527 ch * DDRIODQ_CH_OFFSET,
1528 1 << 8, 1 << 8);
Bin Meng93b4a392015-02-05 23:42:24 +08001529 }
1530#endif
1531 }
1532 }
1533 }
1534 }
1535
1536#ifndef BACKUP_RCVN
1537 /* restore original */
1538 msg_port_write(MEM_CTLR, DTR1, dtr1_save);
1539#endif
1540
1541 LEAVEFN();
1542}
1543
1544/*
1545 * This function will perform the Write Levelling algorithm
1546 * (align WCLK and WDQS).
1547 *
1548 * This algorithm will act on each rank in each channel separately.
1549 */
1550void wr_level(struct mrc_params *mrc_params)
1551{
1552 uint8_t ch; /* channel counter */
1553 uint8_t rk; /* rank counter */
1554 uint8_t bl; /* byte lane counter */
1555 uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1556
1557#ifdef R2R_SHARING
1558 /* used to find placement for rank2rank sharing configs */
1559 uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1560#ifndef BACKUP_WDQS
1561 /* used to find placement for rank2rank sharing configs */
1562 uint32_t num_ranks_enabled = 0;
1563#endif
1564#endif
1565
1566#ifdef BACKUP_WDQS
1567#else
1568 /* determines stop condition for CRS_WR_LVL */
1569 bool all_edges_found;
1570 /* absolute PI value to be programmed on the byte lane */
1571 uint32_t delay[NUM_BYTE_LANES];
1572 /*
1573 * static makes it so the data is loaded in the heap once by shadow(),
1574 * where non-static copies the data onto the stack every time this
1575 * function is called
1576 */
1577 uint32_t address; /* address to be checked during COARSE_WR_LVL */
1578 u32 dtr4, dtr4_save;
1579#endif
1580
1581 ENTERFN();
1582
1583 /* wr_level starts */
1584 mrc_post_code(0x06, 0x00);
1585
1586#ifdef R2R_SHARING
1587 /* need to set "final_delay[][]" elements to "0" */
1588 memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1589#endif
1590
1591 /* loop through each enabled channel */
1592 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1593 if (mrc_params->channel_enables & (1 << ch)) {
1594 /* perform WRITE LEVELING algorithm on a per rank basis */
1595 for (rk = 0; rk < NUM_RANKS; rk++) {
1596 if (mrc_params->rank_enables & (1 << rk)) {
1597 /*
1598 * POST_CODE here indicates the current
1599 * rank and channel being calibrated
1600 */
Bin Meng15e3f282015-03-10 18:31:20 +08001601 mrc_post_code(0x06, 0x10 + ((ch << 4) | rk));
Bin Meng93b4a392015-02-05 23:42:24 +08001602
1603#ifdef BACKUP_WDQS
1604 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1605 set_wdqs(ch, rk, bl, ddr_wdqs[PLATFORM_ID]);
Bin Meng15e3f282015-03-10 18:31:20 +08001606 set_wdq(ch, rk, bl, ddr_wdqs[PLATFORM_ID] - QRTR_CLK);
Bin Meng93b4a392015-02-05 23:42:24 +08001607 }
1608#else
1609 /*
1610 * perform a single PRECHARGE_ALL command to
1611 * make DRAM state machine go to IDLE state
1612 */
1613 dram_init_command(DCMD_PREA(rk));
1614
1615 /*
1616 * enable Write Levelling Mode
1617 * (EMRS1 w/ Write Levelling Mode Enable)
1618 */
Bin Meng15e3f282015-03-10 18:31:20 +08001619 dram_init_command(DCMD_MRS1(rk, 0x82));
Bin Meng93b4a392015-02-05 23:42:24 +08001620
1621 /*
1622 * set ODT DRAM Full Time Termination
1623 * disable in MCU
1624 */
1625
1626 dtr4 = msg_port_read(MEM_CTLR, DTR4);
1627 dtr4_save = dtr4;
Bin Meng15e3f282015-03-10 18:31:20 +08001628 dtr4 |= DTR4_ODTDIS;
Bin Meng93b4a392015-02-05 23:42:24 +08001629 msg_port_write(MEM_CTLR, DTR4, dtr4);
1630
Bin Meng15e3f282015-03-10 18:31:20 +08001631 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08001632 /*
1633 * Enable Sandy Bridge Mode (WDQ Tri-State) &
1634 * Ensure 5 WDQS pulses during Write Leveling
1635 */
1636 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001637 DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
1638 0x10000154,
1639 0x100003fc);
Bin Meng93b4a392015-02-05 23:42:24 +08001640 }
1641
1642 /* Write Leveling Mode enabled in IO */
1643 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001644 CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
1645 1 << 16, 1 << 16);
Bin Meng93b4a392015-02-05 23:42:24 +08001646
1647 /* Initialize the starting delay to WCLK */
1648 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1649 /*
1650 * CLK0 --> RK0
1651 * CLK1 --> RK1
1652 */
1653 delay[bl] = get_wclk(ch, rk);
1654
1655 set_wdqs(ch, rk, bl, delay[bl]);
1656 }
1657
1658 /* now find the rising edge */
1659 find_rising_edge(mrc_params, delay, ch, rk, false);
1660
1661 /* disable Write Levelling Mode */
1662 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001663 CCDDR3RESETCTL + DDRIOCCC_CH_OFFSET * ch,
1664 0, 1 << 16);
Bin Meng93b4a392015-02-05 23:42:24 +08001665
Bin Meng15e3f282015-03-10 18:31:20 +08001666 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08001667 /* Disable Sandy Bridge Mode & Ensure 4 WDQS pulses during normal operation */
1668 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08001669 DQCTL + DDRIODQ_BL_OFFSET * bl + DDRIODQ_CH_OFFSET * ch,
1670 0x00000154,
1671 0x100003fc);
Bin Meng93b4a392015-02-05 23:42:24 +08001672 }
1673
1674 /* restore original DTR4 */
1675 msg_port_write(MEM_CTLR, DTR4, dtr4_save);
1676
1677 /*
1678 * restore original value
1679 * (Write Levelling Mode Disable)
1680 */
1681 dram_init_command(DCMD_MRS1(rk, mrc_params->mrs1));
1682
1683 /*
1684 * perform a single PRECHARGE_ALL command to
1685 * make DRAM state machine go to IDLE state
1686 */
1687 dram_init_command(DCMD_PREA(rk));
1688
Bin Meng15e3f282015-03-10 18:31:20 +08001689 mrc_post_code(0x06, 0x30 + ((ch << 4) | rk));
Bin Meng93b4a392015-02-05 23:42:24 +08001690
1691 /*
1692 * COARSE WRITE LEVEL:
1693 * check that we're on the correct clock edge
1694 */
1695
1696 /* hte reconfiguration request */
1697 mrc_params->hte_setup = 1;
1698
1699 /* start CRS_WR_LVL with WDQS = WDQS + 128 PI */
1700 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1701 delay[bl] = get_wdqs(ch, rk, bl) + FULL_CLK;
1702 set_wdqs(ch, rk, bl, delay[bl]);
1703 /*
1704 * program WDQ timings based on WDQS
1705 * (WDQ = WDQS - 32 PI)
1706 */
1707 set_wdq(ch, rk, bl, (delay[bl] - QRTR_CLK));
1708 }
1709
1710 /* get an address in the targeted channel/rank */
1711 address = get_addr(ch, rk);
1712 do {
1713 uint32_t coarse_result = 0x00;
1714 uint32_t coarse_result_mask = byte_lane_mask(mrc_params);
1715 /* assume pass */
1716 all_edges_found = true;
1717
1718 mrc_params->hte_setup = 1;
1719 coarse_result = check_rw_coarse(mrc_params, address);
1720
1721 /* check for failures and margin the byte lane back 128 PI (1 CLK) */
Bin Meng15e3f282015-03-10 18:31:20 +08001722 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08001723 if (coarse_result & (coarse_result_mask << bl)) {
1724 all_edges_found = false;
1725 delay[bl] -= FULL_CLK;
1726 set_wdqs(ch, rk, bl, delay[bl]);
1727 /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
Bin Meng15e3f282015-03-10 18:31:20 +08001728 set_wdq(ch, rk, bl, delay[bl] - QRTR_CLK);
Bin Meng93b4a392015-02-05 23:42:24 +08001729 }
1730 }
1731 } while (!all_edges_found);
1732
1733#ifdef R2R_SHARING
1734 /* increment "num_ranks_enabled" */
1735 num_ranks_enabled++;
1736 /* accumulate "final_delay[][]" values from "delay[]" values for rolling average */
Bin Meng15e3f282015-03-10 18:31:20 +08001737 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08001738 final_delay[ch][bl] += delay[bl];
Bin Meng15e3f282015-03-10 18:31:20 +08001739 set_wdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
Bin Meng93b4a392015-02-05 23:42:24 +08001740 /* program WDQ timings based on WDQS (WDQ = WDQS - 32 PI) */
Bin Meng15e3f282015-03-10 18:31:20 +08001741 set_wdq(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled - QRTR_CLK);
Bin Meng93b4a392015-02-05 23:42:24 +08001742 }
1743#endif
1744#endif
1745 }
1746 }
1747 }
1748 }
1749
1750 LEAVEFN();
1751}
1752
1753void prog_page_ctrl(struct mrc_params *mrc_params)
1754{
1755 u32 dpmc0;
1756
1757 ENTERFN();
1758
1759 dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
Bin Meng15e3f282015-03-10 18:31:20 +08001760 dpmc0 &= ~DPMC0_PCLSTO_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +08001761 dpmc0 |= (4 << 16);
Bin Meng15e3f282015-03-10 18:31:20 +08001762 dpmc0 |= DPMC0_PREAPWDEN;
Bin Meng93b4a392015-02-05 23:42:24 +08001763 msg_port_write(MEM_CTLR, DPMC0, dpmc0);
1764}
1765
1766/*
1767 * This function will perform the READ TRAINING Algorithm on all
1768 * channels/ranks/byte_lanes simultaneously to minimize execution time.
1769 *
1770 * The idea here is to train the VREF and RDQS (and eventually RDQ) values
1771 * to achieve maximum READ margins. The algorithm will first determine the
1772 * X coordinate (RDQS setting). This is done by collapsing the VREF eye
1773 * until we find a minimum required RDQS eye for VREF_MIN and VREF_MAX.
1774 * Then we take the averages of the RDQS eye at VREF_MIN and VREF_MAX,
1775 * then average those; this will be the final X coordinate. The algorithm
1776 * will then determine the Y coordinate (VREF setting). This is done by
1777 * collapsing the RDQS eye until we find a minimum required VREF eye for
1778 * RDQS_MIN and RDQS_MAX. Then we take the averages of the VREF eye at
1779 * RDQS_MIN and RDQS_MAX, then average those; this will be the final Y
1780 * coordinate.
1781 *
1782 * NOTE: this algorithm assumes the eye curves have a one-to-one relationship,
1783 * meaning for each X the curve has only one Y and vice-a-versa.
1784 */
1785void rd_train(struct mrc_params *mrc_params)
1786{
1787 uint8_t ch; /* channel counter */
1788 uint8_t rk; /* rank counter */
1789 uint8_t bl; /* byte lane counter */
1790 uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
1791#ifdef BACKUP_RDQS
1792#else
1793 uint8_t side_x; /* tracks LEFT/RIGHT approach vectors */
1794 uint8_t side_y; /* tracks BOTTOM/TOP approach vectors */
1795 /* X coordinate data (passing RDQS values) for approach vectors */
1796 uint8_t x_coordinate[2][2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
1797 /* Y coordinate data (passing VREF values) for approach vectors */
1798 uint8_t y_coordinate[2][2][NUM_CHANNELS][NUM_BYTE_LANES];
1799 /* centered X (RDQS) */
1800 uint8_t x_center[NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
1801 /* centered Y (VREF) */
1802 uint8_t y_center[NUM_CHANNELS][NUM_BYTE_LANES];
1803 uint32_t address; /* target address for check_bls_ex() */
1804 uint32_t result; /* result of check_bls_ex() */
1805 uint32_t bl_mask; /* byte lane mask for result checking */
1806#ifdef R2R_SHARING
1807 /* used to find placement for rank2rank sharing configs */
1808 uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
1809 /* used to find placement for rank2rank sharing configs */
1810 uint32_t num_ranks_enabled = 0;
1811#endif
1812#endif
1813
1814 /* rd_train starts */
1815 mrc_post_code(0x07, 0x00);
1816
1817 ENTERFN();
1818
1819#ifdef BACKUP_RDQS
1820 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1821 if (mrc_params->channel_enables & (1 << ch)) {
1822 for (rk = 0; rk < NUM_RANKS; rk++) {
1823 if (mrc_params->rank_enables & (1 << rk)) {
1824 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08001825 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08001826 bl++) {
1827 set_rdqs(ch, rk, bl, ddr_rdqs[PLATFORM_ID]);
1828 }
1829 }
1830 }
1831 }
1832 }
1833#else
1834 /* initialize x/y_coordinate arrays */
1835 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1836 if (mrc_params->channel_enables & (1 << ch)) {
1837 for (rk = 0; rk < NUM_RANKS; rk++) {
1838 if (mrc_params->rank_enables & (1 << rk)) {
1839 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08001840 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08001841 bl++) {
1842 /* x_coordinate */
1843 x_coordinate[L][B][ch][rk][bl] = RDQS_MIN;
1844 x_coordinate[R][B][ch][rk][bl] = RDQS_MAX;
1845 x_coordinate[L][T][ch][rk][bl] = RDQS_MIN;
1846 x_coordinate[R][T][ch][rk][bl] = RDQS_MAX;
1847 /* y_coordinate */
1848 y_coordinate[L][B][ch][bl] = VREF_MIN;
1849 y_coordinate[R][B][ch][bl] = VREF_MIN;
1850 y_coordinate[L][T][ch][bl] = VREF_MAX;
1851 y_coordinate[R][T][ch][bl] = VREF_MAX;
1852 }
1853 }
1854 }
1855 }
1856 }
1857
1858 /* initialize other variables */
1859 bl_mask = byte_lane_mask(mrc_params);
1860 address = get_addr(0, 0);
1861
1862#ifdef R2R_SHARING
1863 /* need to set "final_delay[][]" elements to "0" */
1864 memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
1865#endif
1866
1867 /* look for passing coordinates */
1868 for (side_y = B; side_y <= T; side_y++) {
1869 for (side_x = L; side_x <= R; side_x++) {
Bin Meng15e3f282015-03-10 18:31:20 +08001870 mrc_post_code(0x07, 0x10 + side_y * 2 + side_x);
Bin Meng93b4a392015-02-05 23:42:24 +08001871
1872 /* find passing values */
1873 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1874 if (mrc_params->channel_enables & (0x1 << ch)) {
1875 for (rk = 0; rk < NUM_RANKS; rk++) {
1876 if (mrc_params->rank_enables &
1877 (0x1 << rk)) {
1878 /* set x/y_coordinate search starting settings */
1879 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08001880 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08001881 bl++) {
1882 set_rdqs(ch, rk, bl,
1883 x_coordinate[side_x][side_y][ch][rk][bl]);
1884 set_vref(ch, bl,
1885 y_coordinate[side_x][side_y][ch][bl]);
1886 }
1887
1888 /* get an address in the target channel/rank */
1889 address = get_addr(ch, rk);
1890
1891 /* request HTE reconfiguration */
1892 mrc_params->hte_setup = 1;
1893
1894 /* test the settings */
1895 do {
1896 /* result[07:00] == failing byte lane (MAX 8) */
1897 result = check_bls_ex(mrc_params, address);
1898
1899 /* check for failures */
Bin Meng15e3f282015-03-10 18:31:20 +08001900 if (result & 0xff) {
Bin Meng93b4a392015-02-05 23:42:24 +08001901 /* at least 1 byte lane failed */
Bin Meng15e3f282015-03-10 18:31:20 +08001902 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08001903 if (result &
1904 (bl_mask << bl)) {
1905 /* adjust the RDQS values accordingly */
1906 if (side_x == L)
1907 x_coordinate[L][side_y][ch][rk][bl] += RDQS_STEP;
1908 else
1909 x_coordinate[R][side_y][ch][rk][bl] -= RDQS_STEP;
1910
1911 /* check that we haven't closed the RDQS_EYE too much */
1912 if ((x_coordinate[L][side_y][ch][rk][bl] > (RDQS_MAX - MIN_RDQS_EYE)) ||
1913 (x_coordinate[R][side_y][ch][rk][bl] < (RDQS_MIN + MIN_RDQS_EYE)) ||
1914 (x_coordinate[L][side_y][ch][rk][bl] ==
1915 x_coordinate[R][side_y][ch][rk][bl])) {
1916 /*
1917 * not enough RDQS margin available at this VREF
1918 * update VREF values accordingly
1919 */
1920 if (side_y == B)
1921 y_coordinate[side_x][B][ch][bl] += VREF_STEP;
1922 else
1923 y_coordinate[side_x][T][ch][bl] -= VREF_STEP;
1924
1925 /* check that we haven't closed the VREF_EYE too much */
1926 if ((y_coordinate[side_x][B][ch][bl] > (VREF_MAX - MIN_VREF_EYE)) ||
1927 (y_coordinate[side_x][T][ch][bl] < (VREF_MIN + MIN_VREF_EYE)) ||
1928 (y_coordinate[side_x][B][ch][bl] == y_coordinate[side_x][T][ch][bl])) {
1929 /* VREF_EYE collapsed below MIN_VREF_EYE */
1930 training_message(ch, rk, bl);
Bin Meng15e3f282015-03-10 18:31:20 +08001931 mrc_post_code(0xEE, 0x70 + side_y * 2 + side_x);
Bin Meng93b4a392015-02-05 23:42:24 +08001932 } else {
1933 /* update the VREF setting */
1934 set_vref(ch, bl, y_coordinate[side_x][side_y][ch][bl]);
1935 /* reset the X coordinate to begin the search at the new VREF */
1936 x_coordinate[side_x][side_y][ch][rk][bl] =
Bin Meng15e3f282015-03-10 18:31:20 +08001937 (side_x == L) ? RDQS_MIN : RDQS_MAX;
Bin Meng93b4a392015-02-05 23:42:24 +08001938 }
1939 }
1940
1941 /* update the RDQS setting */
1942 set_rdqs(ch, rk, bl, x_coordinate[side_x][side_y][ch][rk][bl]);
1943 }
1944 }
1945 }
Bin Meng15e3f282015-03-10 18:31:20 +08001946 } while (result & 0xff);
Bin Meng93b4a392015-02-05 23:42:24 +08001947 }
1948 }
1949 }
1950 }
1951 }
1952 }
1953
1954 mrc_post_code(0x07, 0x20);
1955
1956 /* find final RDQS (X coordinate) & final VREF (Y coordinate) */
1957 for (ch = 0; ch < NUM_CHANNELS; ch++) {
1958 if (mrc_params->channel_enables & (1 << ch)) {
1959 for (rk = 0; rk < NUM_RANKS; rk++) {
1960 if (mrc_params->rank_enables & (1 << rk)) {
1961 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
1962 uint32_t temp1;
1963 uint32_t temp2;
1964
1965 /* x_coordinate */
1966 DPF(D_INFO,
1967 "RDQS T/B eye rank%d lane%d : %d-%d %d-%d\n",
1968 rk, bl,
1969 x_coordinate[L][T][ch][rk][bl],
1970 x_coordinate[R][T][ch][rk][bl],
1971 x_coordinate[L][B][ch][rk][bl],
1972 x_coordinate[R][B][ch][rk][bl]);
1973
1974 /* average the TOP side LEFT & RIGHT values */
1975 temp1 = (x_coordinate[R][T][ch][rk][bl] + x_coordinate[L][T][ch][rk][bl]) / 2;
1976 /* average the BOTTOM side LEFT & RIGHT values */
1977 temp2 = (x_coordinate[R][B][ch][rk][bl] + x_coordinate[L][B][ch][rk][bl]) / 2;
1978 /* average the above averages */
1979 x_center[ch][rk][bl] = (uint8_t) ((temp1 + temp2) / 2);
1980
1981 /* y_coordinate */
1982 DPF(D_INFO,
1983 "VREF R/L eye lane%d : %d-%d %d-%d\n",
1984 bl,
1985 y_coordinate[R][B][ch][bl],
1986 y_coordinate[R][T][ch][bl],
1987 y_coordinate[L][B][ch][bl],
1988 y_coordinate[L][T][ch][bl]);
1989
1990 /* average the RIGHT side TOP & BOTTOM values */
1991 temp1 = (y_coordinate[R][T][ch][bl] + y_coordinate[R][B][ch][bl]) / 2;
1992 /* average the LEFT side TOP & BOTTOM values */
1993 temp2 = (y_coordinate[L][T][ch][bl] + y_coordinate[L][B][ch][bl]) / 2;
1994 /* average the above averages */
1995 y_center[ch][bl] = (uint8_t) ((temp1 + temp2) / 2);
1996 }
1997 }
1998 }
1999 }
2000 }
2001
2002#ifdef RX_EYE_CHECK
2003 /* perform an eye check */
2004 for (side_y = B; side_y <= T; side_y++) {
2005 for (side_x = L; side_x <= R; side_x++) {
Bin Meng15e3f282015-03-10 18:31:20 +08002006 mrc_post_code(0x07, 0x30 + side_y * 2 + side_x);
Bin Meng93b4a392015-02-05 23:42:24 +08002007
2008 /* update the settings for the eye check */
2009 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2010 if (mrc_params->channel_enables & (1 << ch)) {
2011 for (rk = 0; rk < NUM_RANKS; rk++) {
2012 if (mrc_params->rank_enables & (1 << rk)) {
Bin Meng15e3f282015-03-10 18:31:20 +08002013 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08002014 if (side_x == L)
Bin Meng15e3f282015-03-10 18:31:20 +08002015 set_rdqs(ch, rk, bl, x_center[ch][rk][bl] - (MIN_RDQS_EYE / 2));
Bin Meng93b4a392015-02-05 23:42:24 +08002016 else
Bin Meng15e3f282015-03-10 18:31:20 +08002017 set_rdqs(ch, rk, bl, x_center[ch][rk][bl] + (MIN_RDQS_EYE / 2));
Bin Meng93b4a392015-02-05 23:42:24 +08002018
2019 if (side_y == B)
Bin Meng15e3f282015-03-10 18:31:20 +08002020 set_vref(ch, bl, y_center[ch][bl] - (MIN_VREF_EYE / 2));
Bin Meng93b4a392015-02-05 23:42:24 +08002021 else
Bin Meng15e3f282015-03-10 18:31:20 +08002022 set_vref(ch, bl, y_center[ch][bl] + (MIN_VREF_EYE / 2));
Bin Meng93b4a392015-02-05 23:42:24 +08002023 }
2024 }
2025 }
2026 }
2027 }
2028
2029 /* request HTE reconfiguration */
2030 mrc_params->hte_setup = 1;
2031
2032 /* check the eye */
Bin Meng15e3f282015-03-10 18:31:20 +08002033 if (check_bls_ex(mrc_params, address) & 0xff) {
Bin Meng93b4a392015-02-05 23:42:24 +08002034 /* one or more byte lanes failed */
Bin Meng15e3f282015-03-10 18:31:20 +08002035 mrc_post_code(0xee, 0x74 + side_x * 2 + side_y);
Bin Meng93b4a392015-02-05 23:42:24 +08002036 }
2037 }
2038 }
2039#endif
2040
2041 mrc_post_code(0x07, 0x40);
2042
2043 /* set final placements */
2044 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2045 if (mrc_params->channel_enables & (1 << ch)) {
2046 for (rk = 0; rk < NUM_RANKS; rk++) {
2047 if (mrc_params->rank_enables & (1 << rk)) {
2048#ifdef R2R_SHARING
2049 /* increment "num_ranks_enabled" */
2050 num_ranks_enabled++;
2051#endif
2052 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor); bl++) {
2053 /* x_coordinate */
2054#ifdef R2R_SHARING
2055 final_delay[ch][bl] += x_center[ch][rk][bl];
Bin Meng15e3f282015-03-10 18:31:20 +08002056 set_rdqs(ch, rk, bl, final_delay[ch][bl] / num_ranks_enabled);
Bin Meng93b4a392015-02-05 23:42:24 +08002057#else
2058 set_rdqs(ch, rk, bl, x_center[ch][rk][bl]);
2059#endif
2060 /* y_coordinate */
2061 set_vref(ch, bl, y_center[ch][bl]);
2062 }
2063 }
2064 }
2065 }
2066 }
2067#endif
2068
2069 LEAVEFN();
2070}
2071
2072/*
2073 * This function will perform the WRITE TRAINING Algorithm on all
2074 * channels/ranks/byte_lanes simultaneously to minimize execution time.
2075 *
2076 * The idea here is to train the WDQ timings to achieve maximum WRITE margins.
2077 * The algorithm will start with WDQ at the current WDQ setting (tracks WDQS
2078 * in WR_LVL) +/- 32 PIs (+/- 1/4 CLK) and collapse the eye until all data
2079 * patterns pass. This is because WDQS will be aligned to WCLK by the
2080 * Write Leveling algorithm and WDQ will only ever have a 1/2 CLK window
2081 * of validity.
2082 */
2083void wr_train(struct mrc_params *mrc_params)
2084{
2085 uint8_t ch; /* channel counter */
2086 uint8_t rk; /* rank counter */
2087 uint8_t bl; /* byte lane counter */
2088 uint8_t bl_divisor = (mrc_params->channel_width == X16) ? 2 : 1;
2089#ifdef BACKUP_WDQ
2090#else
2091 uint8_t side; /* LEFT/RIGHT side indicator (0=L, 1=R) */
2092 uint32_t temp; /* temporary DWORD */
2093 /* 2 arrays, for L & R side passing delays */
2094 uint32_t delay[2][NUM_CHANNELS][NUM_RANKS][NUM_BYTE_LANES];
2095 uint32_t address; /* target address for check_bls_ex() */
2096 uint32_t result; /* result of check_bls_ex() */
2097 uint32_t bl_mask; /* byte lane mask for result checking */
2098#ifdef R2R_SHARING
2099 /* used to find placement for rank2rank sharing configs */
2100 uint32_t final_delay[NUM_CHANNELS][NUM_BYTE_LANES];
2101 /* used to find placement for rank2rank sharing configs */
2102 uint32_t num_ranks_enabled = 0;
2103#endif
2104#endif
2105
2106 /* wr_train starts */
2107 mrc_post_code(0x08, 0x00);
2108
2109 ENTERFN();
2110
2111#ifdef BACKUP_WDQ
2112 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2113 if (mrc_params->channel_enables & (1 << ch)) {
2114 for (rk = 0; rk < NUM_RANKS; rk++) {
2115 if (mrc_params->rank_enables & (1 << rk)) {
2116 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08002117 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08002118 bl++) {
2119 set_wdq(ch, rk, bl, ddr_wdq[PLATFORM_ID]);
2120 }
2121 }
2122 }
2123 }
2124 }
2125#else
2126 /* initialize "delay" */
2127 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2128 if (mrc_params->channel_enables & (1 << ch)) {
2129 for (rk = 0; rk < NUM_RANKS; rk++) {
2130 if (mrc_params->rank_enables & (1 << rk)) {
2131 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08002132 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08002133 bl++) {
2134 /*
2135 * want to start with
2136 * WDQ = (WDQS - QRTR_CLK)
2137 * +/- QRTR_CLK
2138 */
2139 temp = get_wdqs(ch, rk, bl) - QRTR_CLK;
2140 delay[L][ch][rk][bl] = temp - QRTR_CLK;
2141 delay[R][ch][rk][bl] = temp + QRTR_CLK;
2142 }
2143 }
2144 }
2145 }
2146 }
2147
2148 /* initialize other variables */
2149 bl_mask = byte_lane_mask(mrc_params);
2150 address = get_addr(0, 0);
2151
2152#ifdef R2R_SHARING
2153 /* need to set "final_delay[][]" elements to "0" */
2154 memset((void *)(final_delay), 0x00, (size_t)sizeof(final_delay));
2155#endif
2156
2157 /*
2158 * start algorithm on the LEFT side and train each channel/bl
2159 * until no failures are observed, then repeat for the RIGHT side.
2160 */
2161 for (side = L; side <= R; side++) {
Bin Meng15e3f282015-03-10 18:31:20 +08002162 mrc_post_code(0x08, 0x10 + side);
Bin Meng93b4a392015-02-05 23:42:24 +08002163
2164 /* set starting values */
2165 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2166 if (mrc_params->channel_enables & (1 << ch)) {
2167 for (rk = 0; rk < NUM_RANKS; rk++) {
2168 if (mrc_params->rank_enables &
2169 (1 << rk)) {
2170 for (bl = 0;
Bin Meng15e3f282015-03-10 18:31:20 +08002171 bl < NUM_BYTE_LANES / bl_divisor;
Bin Meng93b4a392015-02-05 23:42:24 +08002172 bl++) {
2173 set_wdq(ch, rk, bl, delay[side][ch][rk][bl]);
2174 }
2175 }
2176 }
2177 }
2178 }
2179
2180 /* find passing values */
2181 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2182 if (mrc_params->channel_enables & (1 << ch)) {
2183 for (rk = 0; rk < NUM_RANKS; rk++) {
2184 if (mrc_params->rank_enables &
2185 (1 << rk)) {
2186 /* get an address in the target channel/rank */
2187 address = get_addr(ch, rk);
2188
2189 /* request HTE reconfiguration */
2190 mrc_params->hte_setup = 1;
2191
2192 /* check the settings */
2193 do {
2194 /* result[07:00] == failing byte lane (MAX 8) */
2195 result = check_bls_ex(mrc_params, address);
2196 /* check for failures */
Bin Meng15e3f282015-03-10 18:31:20 +08002197 if (result & 0xff) {
Bin Meng93b4a392015-02-05 23:42:24 +08002198 /* at least 1 byte lane failed */
Bin Meng15e3f282015-03-10 18:31:20 +08002199 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08002200 if (result &
2201 (bl_mask << bl)) {
2202 if (side == L)
2203 delay[L][ch][rk][bl] += WDQ_STEP;
2204 else
2205 delay[R][ch][rk][bl] -= WDQ_STEP;
2206
2207 /* check for algorithm failure */
2208 if (delay[L][ch][rk][bl] != delay[R][ch][rk][bl]) {
2209 /*
2210 * margin available
2211 * update delay setting
2212 */
2213 set_wdq(ch, rk, bl,
2214 delay[side][ch][rk][bl]);
2215 } else {
2216 /*
2217 * no margin available
2218 * notify the user and halt
2219 */
2220 training_message(ch, rk, bl);
Bin Meng15e3f282015-03-10 18:31:20 +08002221 mrc_post_code(0xee, 0x80 + side);
Bin Meng93b4a392015-02-05 23:42:24 +08002222 }
2223 }
2224 }
2225 }
2226 /* stop when all byte lanes pass */
Bin Meng15e3f282015-03-10 18:31:20 +08002227 } while (result & 0xff);
Bin Meng93b4a392015-02-05 23:42:24 +08002228 }
2229 }
2230 }
2231 }
2232 }
2233
2234 /* program WDQ to the middle of passing window */
2235 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2236 if (mrc_params->channel_enables & (1 << ch)) {
2237 for (rk = 0; rk < NUM_RANKS; rk++) {
2238 if (mrc_params->rank_enables & (1 << rk)) {
2239#ifdef R2R_SHARING
2240 /* increment "num_ranks_enabled" */
2241 num_ranks_enabled++;
2242#endif
Bin Meng15e3f282015-03-10 18:31:20 +08002243 for (bl = 0; bl < NUM_BYTE_LANES / bl_divisor; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08002244 DPF(D_INFO,
2245 "WDQ eye rank%d lane%d : %d-%d\n",
2246 rk, bl,
2247 delay[L][ch][rk][bl],
2248 delay[R][ch][rk][bl]);
2249
2250 temp = (delay[R][ch][rk][bl] + delay[L][ch][rk][bl]) / 2;
2251
2252#ifdef R2R_SHARING
2253 final_delay[ch][bl] += temp;
2254 set_wdq(ch, rk, bl,
Bin Meng15e3f282015-03-10 18:31:20 +08002255 final_delay[ch][bl] / num_ranks_enabled);
Bin Meng93b4a392015-02-05 23:42:24 +08002256#else
2257 set_wdq(ch, rk, bl, temp);
2258#endif
2259 }
2260 }
2261 }
2262 }
2263 }
2264#endif
2265
2266 LEAVEFN();
2267}
2268
2269/*
2270 * This function will store relevant timing data
2271 *
2272 * This data will be used on subsequent boots to speed up boot times
2273 * and is required for Suspend To RAM capabilities.
2274 */
2275void store_timings(struct mrc_params *mrc_params)
2276{
2277 uint8_t ch, rk, bl;
2278 struct mrc_timings *mt = &mrc_params->timings;
2279
2280 for (ch = 0; ch < NUM_CHANNELS; ch++) {
2281 for (rk = 0; rk < NUM_RANKS; rk++) {
2282 for (bl = 0; bl < NUM_BYTE_LANES; bl++) {
2283 mt->rcvn[ch][rk][bl] = get_rcvn(ch, rk, bl);
2284 mt->rdqs[ch][rk][bl] = get_rdqs(ch, rk, bl);
2285 mt->wdqs[ch][rk][bl] = get_wdqs(ch, rk, bl);
2286 mt->wdq[ch][rk][bl] = get_wdq(ch, rk, bl);
2287
2288 if (rk == 0)
2289 mt->vref[ch][bl] = get_vref(ch, bl);
2290 }
2291
2292 mt->wctl[ch][rk] = get_wctl(ch, rk);
2293 }
2294
2295 mt->wcmd[ch] = get_wcmd(ch);
2296 }
2297
2298 /* need to save for a case of changing frequency after warm reset */
2299 mt->ddr_speed = mrc_params->ddr_speed;
2300}
2301
2302/*
2303 * The purpose of this function is to ensure the SEC comes out of reset
2304 * and IA initiates the SEC enabling Memory Scrambling.
2305 */
2306void enable_scrambling(struct mrc_params *mrc_params)
2307{
2308 uint32_t lfsr = 0;
2309 uint8_t i;
2310
2311 if (mrc_params->scrambling_enables == 0)
2312 return;
2313
2314 ENTERFN();
2315
2316 /* 32 bit seed is always stored in BIOS NVM */
2317 lfsr = mrc_params->timings.scrambler_seed;
2318
2319 if (mrc_params->boot_mode == BM_COLD) {
2320 /*
2321 * factory value is 0 and in first boot,
2322 * a clock based seed is loaded.
2323 */
2324 if (lfsr == 0) {
2325 /*
2326 * get seed from system clock
2327 * and make sure it is not all 1's
2328 */
Bin Meng15e3f282015-03-10 18:31:20 +08002329 lfsr = rdtsc() & 0x0fffffff;
Bin Meng93b4a392015-02-05 23:42:24 +08002330 } else {
2331 /*
2332 * Need to replace scrambler
2333 *
2334 * get next 32bit LFSR 16 times which is the last
2335 * part of the previous scrambler vector
2336 */
2337 for (i = 0; i < 16; i++)
2338 lfsr32(&lfsr);
2339 }
2340
2341 /* save new seed */
2342 mrc_params->timings.scrambler_seed = lfsr;
2343 }
2344
2345 /*
2346 * In warm boot or S3 exit, we have the previous seed.
2347 * In cold boot, we have the last 32bit LFSR which is the new seed.
2348 */
2349 lfsr32(&lfsr); /* shift to next value */
Bin Meng15e3f282015-03-10 18:31:20 +08002350 msg_port_write(MEM_CTLR, SCRMSEED, (lfsr & 0x0003ffff));
Bin Meng93b4a392015-02-05 23:42:24 +08002351
2352 for (i = 0; i < 2; i++)
Bin Meng15e3f282015-03-10 18:31:20 +08002353 msg_port_write(MEM_CTLR, SCRMLO + i, (lfsr & 0xaaaaaaaa));
Bin Meng93b4a392015-02-05 23:42:24 +08002354
2355 LEAVEFN();
2356}
2357
2358/*
2359 * Configure MCU Power Management Control Register
2360 * and Scheduler Control Register
2361 */
2362void prog_ddr_control(struct mrc_params *mrc_params)
2363{
2364 u32 dsch;
2365 u32 dpmc0;
2366
2367 ENTERFN();
2368
2369 dsch = msg_port_read(MEM_CTLR, DSCH);
Bin Meng15e3f282015-03-10 18:31:20 +08002370 dsch &= ~(DSCH_OOODIS | DSCH_OOOST3DIS | DSCH_NEWBYPDIS);
Bin Meng93b4a392015-02-05 23:42:24 +08002371 msg_port_write(MEM_CTLR, DSCH, dsch);
2372
2373 dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
Bin Meng15e3f282015-03-10 18:31:20 +08002374 dpmc0 &= ~DPMC0_DISPWRDN;
Bin Meng93b4a392015-02-05 23:42:24 +08002375 dpmc0 |= (mrc_params->power_down_disable << 25);
Bin Meng15e3f282015-03-10 18:31:20 +08002376 dpmc0 &= ~DPMC0_CLKGTDIS;
2377 dpmc0 &= ~DPMC0_PCLSTO_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +08002378 dpmc0 |= (4 << 16);
Bin Meng15e3f282015-03-10 18:31:20 +08002379 dpmc0 |= DPMC0_PREAPWDEN;
Bin Meng93b4a392015-02-05 23:42:24 +08002380 msg_port_write(MEM_CTLR, DPMC0, dpmc0);
2381
2382 /* CMDTRIST = 2h - CMD/ADDR are tristated when no valid command */
Bin Meng15e3f282015-03-10 18:31:20 +08002383 mrc_write_mask(MEM_CTLR, DPMC1, 0x20, 0x30);
Bin Meng93b4a392015-02-05 23:42:24 +08002384
2385 LEAVEFN();
2386}
2387
2388/*
2389 * After training complete configure MCU Rank Population Register
2390 * specifying: ranks enabled, device width, density, address mode
2391 */
2392void prog_dra_drb(struct mrc_params *mrc_params)
2393{
2394 u32 drp;
2395 u32 dco;
2396 u8 density = mrc_params->params.density;
2397
2398 ENTERFN();
2399
2400 dco = msg_port_read(MEM_CTLR, DCO);
Bin Meng15e3f282015-03-10 18:31:20 +08002401 dco &= ~DCO_IC;
Bin Meng93b4a392015-02-05 23:42:24 +08002402 msg_port_write(MEM_CTLR, DCO, dco);
2403
2404 drp = 0;
2405 if (mrc_params->rank_enables & 1)
Bin Meng15e3f282015-03-10 18:31:20 +08002406 drp |= DRP_RKEN0;
Bin Meng93b4a392015-02-05 23:42:24 +08002407 if (mrc_params->rank_enables & 2)
Bin Meng15e3f282015-03-10 18:31:20 +08002408 drp |= DRP_RKEN1;
Bin Meng93b4a392015-02-05 23:42:24 +08002409 if (mrc_params->dram_width == X16) {
2410 drp |= (1 << 4);
2411 drp |= (1 << 9);
2412 }
2413
2414 /*
2415 * Density encoding in struct dram_params: 0=512Mb, 1=Gb, 2=2Gb, 3=4Gb
2416 * has to be mapped RANKDENSx encoding (0=1Gb)
2417 */
2418 if (density == 0)
2419 density = 4;
2420
2421 drp |= ((density - 1) << 6);
2422 drp |= ((density - 1) << 11);
2423
2424 /* Address mode can be overwritten if ECC enabled */
2425 drp |= (mrc_params->address_mode << 14);
2426
2427 msg_port_write(MEM_CTLR, DRP, drp);
2428
Bin Meng15e3f282015-03-10 18:31:20 +08002429 dco &= ~DCO_PMICTL;
2430 dco |= DCO_IC;
Bin Meng93b4a392015-02-05 23:42:24 +08002431 msg_port_write(MEM_CTLR, DCO, dco);
2432
2433 LEAVEFN();
2434}
2435
2436/* Send DRAM wake command */
2437void perform_wake(struct mrc_params *mrc_params)
2438{
2439 ENTERFN();
2440
2441 dram_wake_command();
2442
2443 LEAVEFN();
2444}
2445
2446/*
2447 * Configure refresh rate and short ZQ calibration interval
2448 * Activate dynamic self refresh
2449 */
2450void change_refresh_period(struct mrc_params *mrc_params)
2451{
2452 u32 drfc;
2453 u32 dcal;
2454 u32 dpmc0;
2455
2456 ENTERFN();
2457
2458 drfc = msg_port_read(MEM_CTLR, DRFC);
Bin Meng15e3f282015-03-10 18:31:20 +08002459 drfc &= ~DRFC_TREFI_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +08002460 drfc |= (mrc_params->refresh_rate << 12);
Bin Meng15e3f282015-03-10 18:31:20 +08002461 drfc |= DRFC_REFDBTCLR;
Bin Meng93b4a392015-02-05 23:42:24 +08002462 msg_port_write(MEM_CTLR, DRFC, drfc);
2463
2464 dcal = msg_port_read(MEM_CTLR, DCAL);
Bin Meng15e3f282015-03-10 18:31:20 +08002465 dcal &= ~DCAL_ZQCINT_MASK;
Bin Meng93b4a392015-02-05 23:42:24 +08002466 dcal |= (3 << 8); /* 63ms */
2467 msg_port_write(MEM_CTLR, DCAL, dcal);
2468
2469 dpmc0 = msg_port_read(MEM_CTLR, DPMC0);
Bin Meng15e3f282015-03-10 18:31:20 +08002470 dpmc0 |= (DPMC0_DYNSREN | DPMC0_ENPHYCLKGATE);
Bin Meng93b4a392015-02-05 23:42:24 +08002471 msg_port_write(MEM_CTLR, DPMC0, dpmc0);
2472
2473 LEAVEFN();
2474}
2475
2476/*
2477 * Configure DDRPHY for Auto-Refresh, Periodic Compensations,
2478 * Dynamic Diff-Amp, ZQSPERIOD, Auto-Precharge, CKE Power-Down
2479 */
2480void set_auto_refresh(struct mrc_params *mrc_params)
2481{
2482 uint32_t channel;
2483 uint32_t rank;
2484 uint32_t bl;
2485 uint32_t bl_divisor = 1;
2486 uint32_t temp;
2487
2488 ENTERFN();
2489
2490 /*
2491 * Enable Auto-Refresh, Periodic Compensations, Dynamic Diff-Amp,
2492 * ZQSPERIOD, Auto-Precharge, CKE Power-Down
2493 */
2494 for (channel = 0; channel < NUM_CHANNELS; channel++) {
2495 if (mrc_params->channel_enables & (1 << channel)) {
2496 /* Enable Periodic RCOMPS */
Bin Meng15e3f282015-03-10 18:31:20 +08002497 mrc_alt_write_mask(DDRPHY, CMPCTRL, 2, 2);
Bin Meng93b4a392015-02-05 23:42:24 +08002498
2499 /* Enable Dynamic DiffAmp & Set Read ODT Value */
2500 switch (mrc_params->rd_odt_value) {
2501 case 0:
Bin Meng15e3f282015-03-10 18:31:20 +08002502 temp = 0x3f; /* OFF */
Bin Meng93b4a392015-02-05 23:42:24 +08002503 break;
2504 default:
2505 temp = 0x00; /* Auto */
2506 break;
2507 }
2508
Bin Meng15e3f282015-03-10 18:31:20 +08002509 for (bl = 0; bl < (NUM_BYTE_LANES / bl_divisor) / 2; bl++) {
Bin Meng93b4a392015-02-05 23:42:24 +08002510 /* Override: DIFFAMP, ODT */
2511 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08002512 B0OVRCTL + bl * DDRIODQ_BL_OFFSET +
2513 channel * DDRIODQ_CH_OFFSET,
2514 temp << 10,
2515 0x003ffc00);
Bin Meng93b4a392015-02-05 23:42:24 +08002516
2517 /* Override: DIFFAMP, ODT */
2518 mrc_alt_write_mask(DDRPHY,
Bin Meng15e3f282015-03-10 18:31:20 +08002519 B1OVRCTL + bl * DDRIODQ_BL_OFFSET +
2520 channel * DDRIODQ_CH_OFFSET,
2521 temp << 10,
2522 0x003ffc00);
Bin Meng93b4a392015-02-05 23:42:24 +08002523 }
2524
2525 /* Issue ZQCS command */
2526 for (rank = 0; rank < NUM_RANKS; rank++) {
2527 if (mrc_params->rank_enables & (1 << rank))
2528 dram_init_command(DCMD_ZQCS(rank));
2529 }
2530 }
2531 }
2532
2533 clear_pointers();
2534
2535 LEAVEFN();
2536}
2537
2538/*
2539 * Depending on configuration enables ECC support
2540 *
2541 * Available memory size is decreased, and updated with 0s
2542 * in order to clear error status. Address mode 2 forced.
2543 */
2544void ecc_enable(struct mrc_params *mrc_params)
2545{
2546 u32 drp;
2547 u32 dsch;
2548 u32 ecc_ctrl;
2549
2550 if (mrc_params->ecc_enables == 0)
2551 return;
2552
2553 ENTERFN();
2554
2555 /* Configuration required in ECC mode */
2556 drp = msg_port_read(MEM_CTLR, DRP);
Bin Meng15e3f282015-03-10 18:31:20 +08002557 drp &= ~DRP_ADDRMAP_MASK;
2558 drp |= DRP_ADDRMAP_MAP1;
2559 drp |= DRP_PRI64BSPLITEN;
Bin Meng93b4a392015-02-05 23:42:24 +08002560 msg_port_write(MEM_CTLR, DRP, drp);
2561
2562 /* Disable new request bypass */
2563 dsch = msg_port_read(MEM_CTLR, DSCH);
Bin Meng15e3f282015-03-10 18:31:20 +08002564 dsch |= DSCH_NEWBYPDIS;
Bin Meng93b4a392015-02-05 23:42:24 +08002565 msg_port_write(MEM_CTLR, DSCH, dsch);
2566
2567 /* Enable ECC */
Bin Meng15e3f282015-03-10 18:31:20 +08002568 ecc_ctrl = (DECCCTRL_SBEEN | DECCCTRL_DBEEN | DECCCTRL_ENCBGEN);
Bin Meng93b4a392015-02-05 23:42:24 +08002569 msg_port_write(MEM_CTLR, DECCCTRL, ecc_ctrl);
2570
2571 /* Assume 8 bank memory, one bank is gone for ECC */
2572 mrc_params->mem_size -= mrc_params->mem_size / 8;
2573
2574 /* For S3 resume memory content has to be preserved */
2575 if (mrc_params->boot_mode != BM_S3) {
2576 select_hte();
2577 hte_mem_init(mrc_params, MRC_MEM_INIT);
2578 select_mem_mgr();
2579 }
2580
2581 LEAVEFN();
2582}
2583
2584/*
2585 * Execute memory test
2586 * if error detected it is indicated in mrc_params->status
2587 */
2588void memory_test(struct mrc_params *mrc_params)
2589{
2590 uint32_t result = 0;
2591
2592 ENTERFN();
2593
2594 select_hte();
2595 result = hte_mem_init(mrc_params, MRC_MEM_TEST);
2596 select_mem_mgr();
2597
2598 DPF(D_INFO, "Memory test result %x\n", result);
2599 mrc_params->status = ((result == 0) ? MRC_SUCCESS : MRC_E_MEMTEST);
2600 LEAVEFN();
2601}
2602
2603/* Lock MCU registers at the end of initialization sequence */
2604void lock_registers(struct mrc_params *mrc_params)
2605{
2606 u32 dco;
2607
2608 ENTERFN();
2609
2610 dco = msg_port_read(MEM_CTLR, DCO);
Bin Meng15e3f282015-03-10 18:31:20 +08002611 dco &= ~(DCO_PMICTL | DCO_PMIDIS);
2612 dco |= (DCO_DRPLOCK | DCO_CPGCLOCK);
Bin Meng93b4a392015-02-05 23:42:24 +08002613 msg_port_write(MEM_CTLR, DCO, dco);
2614
2615 LEAVEFN();
2616}