xref: /rk3399_ARM-atf/drivers/nxp/ddr/nxp-ddr/regs.c (revision b35ce0c413a71689a2b46453b9c30596128f13dc)
1*b35ce0c4SPankaj Gupta /*
2*b35ce0c4SPankaj Gupta  * Copyright 2021 NXP
3*b35ce0c4SPankaj Gupta  *
4*b35ce0c4SPankaj Gupta  * SPDX-License-Identifier: BSD-3-Clause
5*b35ce0c4SPankaj Gupta  *
6*b35ce0c4SPankaj Gupta  */
7*b35ce0c4SPankaj Gupta 
8*b35ce0c4SPankaj Gupta #include <errno.h>
9*b35ce0c4SPankaj Gupta #include <stdbool.h>
10*b35ce0c4SPankaj Gupta #include <stdint.h>
11*b35ce0c4SPankaj Gupta #include <stdio.h>
12*b35ce0c4SPankaj Gupta #include <stdlib.h>
13*b35ce0c4SPankaj Gupta 
14*b35ce0c4SPankaj Gupta #include <common/debug.h>
15*b35ce0c4SPankaj Gupta #include <ddr.h>
16*b35ce0c4SPankaj Gupta #include <lib/utils.h>
17*b35ce0c4SPankaj Gupta 
18*b35ce0c4SPankaj Gupta static inline unsigned int cal_cwl(const unsigned long clk)
19*b35ce0c4SPankaj Gupta {
20*b35ce0c4SPankaj Gupta 	const unsigned int mclk_ps = get_memory_clk_ps(clk);
21*b35ce0c4SPankaj Gupta 
22*b35ce0c4SPankaj Gupta 	return mclk_ps >= 1250U ? 9U :
23*b35ce0c4SPankaj Gupta 		(mclk_ps >= 1070U ? 10U :
24*b35ce0c4SPankaj Gupta 		 (mclk_ps >= 935U ? 11U :
25*b35ce0c4SPankaj Gupta 		  (mclk_ps >= 833U ? 12U :
26*b35ce0c4SPankaj Gupta 		   (mclk_ps >= 750U ? 14U :
27*b35ce0c4SPankaj Gupta 		    (mclk_ps >= 625U ? 16U : 18U)))));
28*b35ce0c4SPankaj Gupta }
29*b35ce0c4SPankaj Gupta 
30*b35ce0c4SPankaj Gupta static void cal_csn_config(int i,
31*b35ce0c4SPankaj Gupta 			   struct ddr_cfg_regs *regs,
32*b35ce0c4SPankaj Gupta 			   const struct memctl_opt *popts,
33*b35ce0c4SPankaj Gupta 			   const struct dimm_params *pdimm)
34*b35ce0c4SPankaj Gupta {
35*b35ce0c4SPankaj Gupta 	unsigned int intlv_en = 0U;
36*b35ce0c4SPankaj Gupta 	unsigned int intlv_ctl = 0U;
37*b35ce0c4SPankaj Gupta 	const unsigned int cs_n_en = 1U;
38*b35ce0c4SPankaj Gupta 	const unsigned int ap_n_en = popts->cs_odt[i].auto_precharge;
39*b35ce0c4SPankaj Gupta 	const unsigned int odt_rd_cfg = popts->cs_odt[i].odt_rd_cfg;
40*b35ce0c4SPankaj Gupta 	const unsigned int odt_wr_cfg = popts->cs_odt[i].odt_wr_cfg;
41*b35ce0c4SPankaj Gupta 	const unsigned int ba_bits_cs_n = pdimm->bank_addr_bits;
42*b35ce0c4SPankaj Gupta 	const unsigned int row_bits_cs_n = pdimm->n_row_addr - 12U;
43*b35ce0c4SPankaj Gupta 	const unsigned int col_bits_cs_n = pdimm->n_col_addr - 8U;
44*b35ce0c4SPankaj Gupta 	const unsigned int bg_bits_cs_n = pdimm->bank_group_bits;
45*b35ce0c4SPankaj Gupta 
46*b35ce0c4SPankaj Gupta 	if (i == 0) {
47*b35ce0c4SPankaj Gupta 		/* These fields only available in CS0_CONFIG */
48*b35ce0c4SPankaj Gupta 		if (popts->ctlr_intlv != 0) {
49*b35ce0c4SPankaj Gupta 			switch (popts->ctlr_intlv_mode) {
50*b35ce0c4SPankaj Gupta 			case DDR_256B_INTLV:
51*b35ce0c4SPankaj Gupta 				intlv_en = popts->ctlr_intlv;
52*b35ce0c4SPankaj Gupta 				intlv_ctl = popts->ctlr_intlv_mode;
53*b35ce0c4SPankaj Gupta 				break;
54*b35ce0c4SPankaj Gupta 			default:
55*b35ce0c4SPankaj Gupta 				break;
56*b35ce0c4SPankaj Gupta 			}
57*b35ce0c4SPankaj Gupta 		}
58*b35ce0c4SPankaj Gupta 	}
59*b35ce0c4SPankaj Gupta 	regs->cs[i].config = ((cs_n_en & 0x1) << 31)		|
60*b35ce0c4SPankaj Gupta 			    ((intlv_en & 0x3) << 29)		|
61*b35ce0c4SPankaj Gupta 			    ((intlv_ctl & 0xf) << 24)		|
62*b35ce0c4SPankaj Gupta 			    ((ap_n_en & 0x1) << 23)		|
63*b35ce0c4SPankaj Gupta 			    ((odt_rd_cfg & 0x7) << 20)		|
64*b35ce0c4SPankaj Gupta 			    ((odt_wr_cfg & 0x7) << 16)		|
65*b35ce0c4SPankaj Gupta 			    ((ba_bits_cs_n & 0x3) << 14)	|
66*b35ce0c4SPankaj Gupta 			    ((row_bits_cs_n & 0x7) << 8)	|
67*b35ce0c4SPankaj Gupta 			    ((bg_bits_cs_n & 0x3) << 4)		|
68*b35ce0c4SPankaj Gupta 			    ((col_bits_cs_n & 0x7) << 0);
69*b35ce0c4SPankaj Gupta 	debug("cs%d\n", i);
70*b35ce0c4SPankaj Gupta 	debug("   _config = 0x%x\n", regs->cs[i].config);
71*b35ce0c4SPankaj Gupta }
72*b35ce0c4SPankaj Gupta 
73*b35ce0c4SPankaj Gupta static inline int avoid_odt_overlap(const struct ddr_conf *conf,
74*b35ce0c4SPankaj Gupta 				    const struct dimm_params *pdimm)
75*b35ce0c4SPankaj Gupta {
76*b35ce0c4SPankaj Gupta 	if ((conf->cs_in_use == 0xf) != 0) {
77*b35ce0c4SPankaj Gupta 		return 2;
78*b35ce0c4SPankaj Gupta 	}
79*b35ce0c4SPankaj Gupta 
80*b35ce0c4SPankaj Gupta #if DDRC_NUM_DIMM >= 2
81*b35ce0c4SPankaj Gupta 	if (conf->dimm_in_use[0] != 0 && conf->dimm_in_use[1] != 0) {
82*b35ce0c4SPankaj Gupta 		return 1;
83*b35ce0c4SPankaj Gupta 	}
84*b35ce0c4SPankaj Gupta #endif
85*b35ce0c4SPankaj Gupta 	return 0;
86*b35ce0c4SPankaj Gupta }
87*b35ce0c4SPankaj Gupta 
88*b35ce0c4SPankaj Gupta /* Requires rcw2 set first */
89*b35ce0c4SPankaj Gupta static void cal_timing_cfg(const unsigned long clk,
90*b35ce0c4SPankaj Gupta 			   struct ddr_cfg_regs *regs,
91*b35ce0c4SPankaj Gupta 			   const struct memctl_opt *popts,
92*b35ce0c4SPankaj Gupta 			   const struct dimm_params *pdimm,
93*b35ce0c4SPankaj Gupta 			   const struct ddr_conf *conf,
94*b35ce0c4SPankaj Gupta 			   unsigned int cas_latency,
95*b35ce0c4SPankaj Gupta 			   unsigned int additive_latency)
96*b35ce0c4SPankaj Gupta {
97*b35ce0c4SPankaj Gupta 	const unsigned int mclk_ps = get_memory_clk_ps(clk);
98*b35ce0c4SPankaj Gupta 	/* tXP=max(4nCK, 6ns) */
99*b35ce0c4SPankaj Gupta 	const int txp = max((int)mclk_ps * 4, 6000);
100*b35ce0c4SPankaj Gupta 	/* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
101*b35ce0c4SPankaj Gupta 	static const int wrrec_table[] = {
102*b35ce0c4SPankaj Gupta 		10, 10, 10, 10, 10,
103*b35ce0c4SPankaj Gupta 		10, 10, 10, 10, 10,
104*b35ce0c4SPankaj Gupta 		12, 12, 14, 14, 16,
105*b35ce0c4SPankaj Gupta 		16, 18, 18, 20, 20,
106*b35ce0c4SPankaj Gupta 		24, 24, 24, 24,
107*b35ce0c4SPankaj Gupta 	};
108*b35ce0c4SPankaj Gupta 	int trwt_mclk = (clk / 1000000 > 1900) ? 3 : 2;
109*b35ce0c4SPankaj Gupta 	int twrt_mclk;
110*b35ce0c4SPankaj Gupta 	int trrt_mclk;
111*b35ce0c4SPankaj Gupta 	int twwt_mclk;
112*b35ce0c4SPankaj Gupta 	const int act_pd_exit_mclk = picos_to_mclk(clk, txp);
113*b35ce0c4SPankaj Gupta 	const int pre_pd_exit_mclk = act_pd_exit_mclk;
114*b35ce0c4SPankaj Gupta 	const int taxpd_mclk = 0;
115*b35ce0c4SPankaj Gupta 	/*
116*b35ce0c4SPankaj Gupta 	 * MRS_CYC = max(tMRD, tMOD)
117*b35ce0c4SPankaj Gupta 	 * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
118*b35ce0c4SPankaj Gupta 	 */
119*b35ce0c4SPankaj Gupta 	const int tmrd_mclk = max(24U, picos_to_mclk(clk, 15000));
120*b35ce0c4SPankaj Gupta 	const int pretoact_mclk = picos_to_mclk(clk, pdimm->trp_ps);
121*b35ce0c4SPankaj Gupta 	const int acttopre_mclk = picos_to_mclk(clk, pdimm->tras_ps);
122*b35ce0c4SPankaj Gupta 	const int acttorw_mclk = picos_to_mclk(clk, pdimm->trcd_ps);
123*b35ce0c4SPankaj Gupta 	const int caslat_ctrl = (cas_latency - 1) << 1;
124*b35ce0c4SPankaj Gupta 	const int trfc1_min = pdimm->die_density >= 0x3 ? 16000 :
125*b35ce0c4SPankaj Gupta 			      (pdimm->die_density == 0x4 ? 26000 :
126*b35ce0c4SPankaj Gupta 			       (pdimm->die_density == 0x5 ? 35000 :
127*b35ce0c4SPankaj Gupta 				55000));
128*b35ce0c4SPankaj Gupta 	const int refrec_ctrl = picos_to_mclk(clk,
129*b35ce0c4SPankaj Gupta 							pdimm->trfc1_ps) - 8;
130*b35ce0c4SPankaj Gupta 	int wrrec_mclk = picos_to_mclk(clk, pdimm->twr_ps);
131*b35ce0c4SPankaj Gupta 	const int acttoact_mclk = max(picos_to_mclk(clk,
132*b35ce0c4SPankaj Gupta 							      pdimm->trrds_ps),
133*b35ce0c4SPankaj Gupta 						4U);
134*b35ce0c4SPankaj Gupta 	int wrtord_mclk = max(2U, picos_to_mclk(clk, 2500));
135*b35ce0c4SPankaj Gupta 	const unsigned int cpo = 0U;
136*b35ce0c4SPankaj Gupta 	const int wr_lat = cal_cwl(clk);
137*b35ce0c4SPankaj Gupta 	int rd_to_pre = picos_to_mclk(clk, 7500);
138*b35ce0c4SPankaj Gupta 	const int wr_data_delay = popts->wr_data_delay;
139*b35ce0c4SPankaj Gupta 	const int cke_pls = max(3U, picos_to_mclk(clk, 5000));
140*b35ce0c4SPankaj Gupta #ifdef ERRATA_DDR_A050450
141*b35ce0c4SPankaj Gupta 	const unsigned short four_act = ((popts->twot_en == 0) &&
142*b35ce0c4SPankaj Gupta 					 (popts->threet_en == 0) &&
143*b35ce0c4SPankaj Gupta 					 (popts->tfaw_ps % 2 == 0)) ?
144*b35ce0c4SPankaj Gupta 						(picos_to_mclk(clk, popts->tfaw_ps) + 1) :
145*b35ce0c4SPankaj Gupta 						picos_to_mclk(clk, popts->tfaw_ps);
146*b35ce0c4SPankaj Gupta #else
147*b35ce0c4SPankaj Gupta 	const unsigned short four_act = picos_to_mclk(clk,
148*b35ce0c4SPankaj Gupta 					 popts->tfaw_ps);
149*b35ce0c4SPankaj Gupta #endif
150*b35ce0c4SPankaj Gupta 	const unsigned int cntl_adj = 0U;
151*b35ce0c4SPankaj Gupta 	const unsigned int ext_pretoact = picos_to_mclk(clk,
152*b35ce0c4SPankaj Gupta 							pdimm->trp_ps) >> 4U;
153*b35ce0c4SPankaj Gupta 	const unsigned int ext_acttopre = picos_to_mclk(clk,
154*b35ce0c4SPankaj Gupta 							pdimm->tras_ps) >> 4U;
155*b35ce0c4SPankaj Gupta 	const unsigned int ext_acttorw = picos_to_mclk(clk,
156*b35ce0c4SPankaj Gupta 						       pdimm->trcd_ps) >> 4U;
157*b35ce0c4SPankaj Gupta 	const unsigned int ext_caslat = (2U * cas_latency - 1U) >> 4U;
158*b35ce0c4SPankaj Gupta 	const unsigned int ext_add_lat = additive_latency >> 4U;
159*b35ce0c4SPankaj Gupta 	const unsigned int ext_refrec = (picos_to_mclk(clk,
160*b35ce0c4SPankaj Gupta 					       pdimm->trfc1_ps) - 8U) >> 4U;
161*b35ce0c4SPankaj Gupta 	const unsigned int ext_wrrec = (picos_to_mclk(clk, pdimm->twr_ps) +
162*b35ce0c4SPankaj Gupta 				  (popts->otf_burst_chop_en ? 2U : 0U)) >> 4U;
163*b35ce0c4SPankaj Gupta 	const unsigned int rwt_same_cs = 0U;
164*b35ce0c4SPankaj Gupta 	const unsigned int wrt_same_cs = 0U;
165*b35ce0c4SPankaj Gupta 	const unsigned int rrt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U;
166*b35ce0c4SPankaj Gupta 	const unsigned int wwt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U;
167*b35ce0c4SPankaj Gupta 	const unsigned int dll_lock = 2U;
168*b35ce0c4SPankaj Gupta 	unsigned int rodt_on = 0U;
169*b35ce0c4SPankaj Gupta 	const unsigned int rodt_off = 4U;
170*b35ce0c4SPankaj Gupta 	const unsigned int wodt_on = 1U;
171*b35ce0c4SPankaj Gupta 	const unsigned int wodt_off = 4U;
172*b35ce0c4SPankaj Gupta 	const unsigned int hs_caslat = 0U;
173*b35ce0c4SPankaj Gupta 	const unsigned int hs_wrlat = 0U;
174*b35ce0c4SPankaj Gupta 	const unsigned int hs_wrrec = 0U;
175*b35ce0c4SPankaj Gupta 	const unsigned int hs_clkadj = 0U;
176*b35ce0c4SPankaj Gupta 	const unsigned int hs_wrlvl_start = 0U;
177*b35ce0c4SPankaj Gupta 	const unsigned int txpr = max(5U,
178*b35ce0c4SPankaj Gupta 				      picos_to_mclk(clk,
179*b35ce0c4SPankaj Gupta 						    pdimm->trfc1_ps + 10000U));
180*b35ce0c4SPankaj Gupta 	const unsigned int tcksre = max(5U, picos_to_mclk(clk, 10000U));
181*b35ce0c4SPankaj Gupta 	const unsigned int tcksrx = max(5U, picos_to_mclk(clk, 10000U));
182*b35ce0c4SPankaj Gupta 	const unsigned int cs_to_cmd = 0U;
183*b35ce0c4SPankaj Gupta 	const unsigned int cke_rst = txpr <= 200U ? 0U :
184*b35ce0c4SPankaj Gupta 				     (txpr <= 256U ? 1U :
185*b35ce0c4SPankaj Gupta 				      (txpr <= 512U ? 2U : 3U));
186*b35ce0c4SPankaj Gupta 	const unsigned int cksre = tcksre <= 19U ? tcksre - 5U : 15U;
187*b35ce0c4SPankaj Gupta 	const unsigned int cksrx = tcksrx <= 19U ? tcksrx - 5U : 15U;
188*b35ce0c4SPankaj Gupta 	unsigned int par_lat = 0U;
189*b35ce0c4SPankaj Gupta 	const int tccdl = max(5U, picos_to_mclk(clk, pdimm->tccdl_ps));
190*b35ce0c4SPankaj Gupta 	int rwt_bg = cas_latency + 2 + 4 - wr_lat;
191*b35ce0c4SPankaj Gupta 	int wrt_bg = wr_lat + 4 + 1 - cas_latency;
192*b35ce0c4SPankaj Gupta 	const int rrt_bg = popts->burst_length == DDR_BL8 ?
193*b35ce0c4SPankaj Gupta 				tccdl - 4 : tccdl - 2;
194*b35ce0c4SPankaj Gupta 	const int wwt_bg = popts->burst_length == DDR_BL8 ?
195*b35ce0c4SPankaj Gupta 					tccdl - 4 : tccdl - 2;
196*b35ce0c4SPankaj Gupta 	const unsigned int acttoact_bg = picos_to_mclk(clk, pdimm->trrdl_ps);
197*b35ce0c4SPankaj Gupta 	const unsigned int wrtord_bg = max(4U, picos_to_mclk(clk, 7500)) +
198*b35ce0c4SPankaj Gupta 				       (popts->otf_burst_chop_en ? 2 : 0);
199*b35ce0c4SPankaj Gupta 	const unsigned int pre_all_rec = 0;
200*b35ce0c4SPankaj Gupta 	const unsigned int refrec_cid_mclk = pdimm->package_3ds ?
201*b35ce0c4SPankaj Gupta 				picos_to_mclk(clk, pdimm->trfc_slr_ps) : 0;
202*b35ce0c4SPankaj Gupta 	const unsigned int acttoact_cid_mclk = pdimm->package_3ds ? 4U : 0;
203*b35ce0c4SPankaj Gupta 
204*b35ce0c4SPankaj Gupta 
205*b35ce0c4SPankaj Gupta 	/* for two dual-rank DIMMs to avoid ODT overlap */
206*b35ce0c4SPankaj Gupta 	if (avoid_odt_overlap(conf, pdimm) == 2) {
207*b35ce0c4SPankaj Gupta 		twrt_mclk = 2;
208*b35ce0c4SPankaj Gupta 		twwt_mclk = 2;
209*b35ce0c4SPankaj Gupta 		trrt_mclk = 2;
210*b35ce0c4SPankaj Gupta 	} else {
211*b35ce0c4SPankaj Gupta 		twrt_mclk = 1;
212*b35ce0c4SPankaj Gupta 		twwt_mclk = 1;
213*b35ce0c4SPankaj Gupta 		trrt_mclk = 0;
214*b35ce0c4SPankaj Gupta 	}
215*b35ce0c4SPankaj Gupta 
216*b35ce0c4SPankaj Gupta 	if (popts->trwt_override != 0) {
217*b35ce0c4SPankaj Gupta 		trwt_mclk = popts->trwt;
218*b35ce0c4SPankaj Gupta 		if (popts->twrt != 0) {
219*b35ce0c4SPankaj Gupta 			twrt_mclk = popts->twrt;
220*b35ce0c4SPankaj Gupta 		}
221*b35ce0c4SPankaj Gupta 		if (popts->trrt != 0) {
222*b35ce0c4SPankaj Gupta 			trrt_mclk = popts->trrt;
223*b35ce0c4SPankaj Gupta 		}
224*b35ce0c4SPankaj Gupta 		if (popts->twwt != 0) {
225*b35ce0c4SPankaj Gupta 			twwt_mclk = popts->twwt;
226*b35ce0c4SPankaj Gupta 		}
227*b35ce0c4SPankaj Gupta 	}
228*b35ce0c4SPankaj Gupta 	regs->timing_cfg[0] = (((trwt_mclk & 0x3) << 30)		|
229*b35ce0c4SPankaj Gupta 			     ((twrt_mclk & 0x3) << 28)			|
230*b35ce0c4SPankaj Gupta 			     ((trrt_mclk & 0x3) << 26)			|
231*b35ce0c4SPankaj Gupta 			     ((twwt_mclk & 0x3) << 24)			|
232*b35ce0c4SPankaj Gupta 			     ((act_pd_exit_mclk & 0xf) << 20)		|
233*b35ce0c4SPankaj Gupta 			     ((pre_pd_exit_mclk & 0xF) << 16)		|
234*b35ce0c4SPankaj Gupta 			     ((taxpd_mclk & 0xf) << 8)			|
235*b35ce0c4SPankaj Gupta 			     ((tmrd_mclk & 0x1f) << 0));
236*b35ce0c4SPankaj Gupta 	debug("timing_cfg[0] = 0x%x\n", regs->timing_cfg[0]);
237*b35ce0c4SPankaj Gupta 
238*b35ce0c4SPankaj Gupta 	if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) {
239*b35ce0c4SPankaj Gupta 		ERROR("WRREC doesn't support clock %d\n", wrrec_mclk);
240*b35ce0c4SPankaj Gupta 	} else {
241*b35ce0c4SPankaj Gupta 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
242*b35ce0c4SPankaj Gupta 	}
243*b35ce0c4SPankaj Gupta 
244*b35ce0c4SPankaj Gupta 	if (popts->otf_burst_chop_en != 0) {
245*b35ce0c4SPankaj Gupta 		wrrec_mclk += 2;
246*b35ce0c4SPankaj Gupta 		wrtord_mclk += 2;
247*b35ce0c4SPankaj Gupta 	}
248*b35ce0c4SPankaj Gupta 
249*b35ce0c4SPankaj Gupta 	if (pdimm->trfc1_ps < trfc1_min) {
250*b35ce0c4SPankaj Gupta 		ERROR("trfc1_ps (%d) < %d\n", pdimm->trfc1_ps, trfc1_min);
251*b35ce0c4SPankaj Gupta 	}
252*b35ce0c4SPankaj Gupta 
253*b35ce0c4SPankaj Gupta 	regs->timing_cfg[1] = (((pretoact_mclk & 0x0F) << 28)		|
254*b35ce0c4SPankaj Gupta 			     ((acttopre_mclk & 0x0F) << 24)		|
255*b35ce0c4SPankaj Gupta 			     ((acttorw_mclk & 0xF) << 20)		|
256*b35ce0c4SPankaj Gupta 			     ((caslat_ctrl & 0xF) << 16)		|
257*b35ce0c4SPankaj Gupta 			     ((refrec_ctrl & 0xF) << 12)		|
258*b35ce0c4SPankaj Gupta 			     ((wrrec_mclk & 0x0F) << 8)			|
259*b35ce0c4SPankaj Gupta 			     ((acttoact_mclk & 0x0F) << 4)		|
260*b35ce0c4SPankaj Gupta 			     ((wrtord_mclk & 0x0F) << 0));
261*b35ce0c4SPankaj Gupta 	debug("timing_cfg[1] = 0x%x\n", regs->timing_cfg[1]);
262*b35ce0c4SPankaj Gupta 
263*b35ce0c4SPankaj Gupta 	if (rd_to_pre < 4) {
264*b35ce0c4SPankaj Gupta 		rd_to_pre = 4;
265*b35ce0c4SPankaj Gupta 	}
266*b35ce0c4SPankaj Gupta 	if (popts->otf_burst_chop_en) {
267*b35ce0c4SPankaj Gupta 		rd_to_pre += 2;
268*b35ce0c4SPankaj Gupta 	}
269*b35ce0c4SPankaj Gupta 
270*b35ce0c4SPankaj Gupta 	regs->timing_cfg[2] = (((additive_latency & 0xf) << 28)		|
271*b35ce0c4SPankaj Gupta 			     ((cpo & 0x1f) << 23)			|
272*b35ce0c4SPankaj Gupta 			     ((wr_lat & 0xf) << 19)			|
273*b35ce0c4SPankaj Gupta 			     (((wr_lat & 0x10) >> 4) << 18)		|
274*b35ce0c4SPankaj Gupta 			     ((rd_to_pre & 0xf) << 13)			|
275*b35ce0c4SPankaj Gupta 			     ((wr_data_delay & 0xf) << 9)		|
276*b35ce0c4SPankaj Gupta 			     ((cke_pls & 0x7) << 6)			|
277*b35ce0c4SPankaj Gupta 			     ((four_act & 0x3f) << 0));
278*b35ce0c4SPankaj Gupta 	debug("timing_cfg[2] = 0x%x\n", regs->timing_cfg[2]);
279*b35ce0c4SPankaj Gupta 
280*b35ce0c4SPankaj Gupta 	regs->timing_cfg[3] = (((ext_pretoact & 0x1) << 28)		|
281*b35ce0c4SPankaj Gupta 			     ((ext_acttopre & 0x3) << 24)		|
282*b35ce0c4SPankaj Gupta 			     ((ext_acttorw & 0x1) << 22)		|
283*b35ce0c4SPankaj Gupta 			     ((ext_refrec & 0x3F) << 16)		|
284*b35ce0c4SPankaj Gupta 			     ((ext_caslat & 0x3) << 12)			|
285*b35ce0c4SPankaj Gupta 			     ((ext_add_lat & 0x1) << 10)		|
286*b35ce0c4SPankaj Gupta 			     ((ext_wrrec & 0x1) << 8)			|
287*b35ce0c4SPankaj Gupta 			     ((cntl_adj & 0x7) << 0));
288*b35ce0c4SPankaj Gupta 	debug("timing_cfg[3] = 0x%x\n", regs->timing_cfg[3]);
289*b35ce0c4SPankaj Gupta 
290*b35ce0c4SPankaj Gupta 	regs->timing_cfg[4] = (((rwt_same_cs & 0xf) << 28)		|
291*b35ce0c4SPankaj Gupta 			     ((wrt_same_cs & 0xf) << 24)		|
292*b35ce0c4SPankaj Gupta 			     ((rrt_same_cs & 0xf) << 20)		|
293*b35ce0c4SPankaj Gupta 			     ((wwt_same_cs & 0xf) << 16)		|
294*b35ce0c4SPankaj Gupta 			     ((trwt_mclk & 0xc) << 12)			|
295*b35ce0c4SPankaj Gupta 			     ((twrt_mclk & 0x4) << 10)			|
296*b35ce0c4SPankaj Gupta 			     ((trrt_mclk & 0x4) << 8)			|
297*b35ce0c4SPankaj Gupta 			     ((twwt_mclk & 0x4) << 6)			|
298*b35ce0c4SPankaj Gupta 			     (dll_lock & 0x3));
299*b35ce0c4SPankaj Gupta 	debug("timing_cfg[4] = 0x%x\n", regs->timing_cfg[4]);
300*b35ce0c4SPankaj Gupta 
301*b35ce0c4SPankaj Gupta 	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
302*b35ce0c4SPankaj Gupta 	if (cas_latency >= wr_lat) {
303*b35ce0c4SPankaj Gupta 		rodt_on = cas_latency - wr_lat + 1;
304*b35ce0c4SPankaj Gupta 	}
305*b35ce0c4SPankaj Gupta 
306*b35ce0c4SPankaj Gupta 	regs->timing_cfg[5] = (((rodt_on & 0x1f) << 24)			|
307*b35ce0c4SPankaj Gupta 			     ((rodt_off & 0x7) << 20)			|
308*b35ce0c4SPankaj Gupta 			     ((wodt_on & 0x1f) << 12)			|
309*b35ce0c4SPankaj Gupta 			     (wodt_off & 0x7) << 8);
310*b35ce0c4SPankaj Gupta 	debug("timing_cfg[5] = 0x%x\n", regs->timing_cfg[5]);
311*b35ce0c4SPankaj Gupta 
312*b35ce0c4SPankaj Gupta 	regs->timing_cfg[6] = (((hs_caslat & 0x1f) << 24)		|
313*b35ce0c4SPankaj Gupta 			     ((hs_wrlat & 0x1f) << 19)			|
314*b35ce0c4SPankaj Gupta 			     ((hs_wrrec & 0x1f) << 12)			|
315*b35ce0c4SPankaj Gupta 			     ((hs_clkadj & 0x1f) << 6)			|
316*b35ce0c4SPankaj Gupta 			     ((hs_wrlvl_start & 0x1f) << 0));
317*b35ce0c4SPankaj Gupta 	debug("timing_cfg[6] = 0x%x\n", regs->timing_cfg[6]);
318*b35ce0c4SPankaj Gupta 
319*b35ce0c4SPankaj Gupta 	if (popts->ap_en != 0) {
320*b35ce0c4SPankaj Gupta 		par_lat = (regs->sdram_rcw[1] & 0xf) + 1;
321*b35ce0c4SPankaj Gupta 		debug("PAR_LAT = 0x%x\n", par_lat);
322*b35ce0c4SPankaj Gupta 	}
323*b35ce0c4SPankaj Gupta 
324*b35ce0c4SPankaj Gupta 	regs->timing_cfg[7] = (((cke_rst & 0x3) << 28)			|
325*b35ce0c4SPankaj Gupta 			     ((cksre & 0xf) << 24)			|
326*b35ce0c4SPankaj Gupta 			     ((cksrx & 0xf) << 20)			|
327*b35ce0c4SPankaj Gupta 			     ((par_lat & 0xf) << 16)			|
328*b35ce0c4SPankaj Gupta 			     ((cs_to_cmd & 0xf) << 4));
329*b35ce0c4SPankaj Gupta 	debug("timing_cfg[7] = 0x%x\n", regs->timing_cfg[7]);
330*b35ce0c4SPankaj Gupta 
331*b35ce0c4SPankaj Gupta 	if (rwt_bg < tccdl) {
332*b35ce0c4SPankaj Gupta 		rwt_bg = tccdl - rwt_bg;
333*b35ce0c4SPankaj Gupta 	} else {
334*b35ce0c4SPankaj Gupta 		rwt_bg = 0;
335*b35ce0c4SPankaj Gupta 	}
336*b35ce0c4SPankaj Gupta 	if (wrt_bg < tccdl) {
337*b35ce0c4SPankaj Gupta 		wrt_bg = tccdl - wrt_bg;
338*b35ce0c4SPankaj Gupta 	} else {
339*b35ce0c4SPankaj Gupta 		wrt_bg = 0;
340*b35ce0c4SPankaj Gupta 	}
341*b35ce0c4SPankaj Gupta 	regs->timing_cfg[8] = (((rwt_bg & 0xf) << 28)			|
342*b35ce0c4SPankaj Gupta 			     ((wrt_bg & 0xf) << 24)			|
343*b35ce0c4SPankaj Gupta 			     ((rrt_bg & 0xf) << 20)			|
344*b35ce0c4SPankaj Gupta 			     ((wwt_bg & 0xf) << 16)			|
345*b35ce0c4SPankaj Gupta 			     ((acttoact_bg & 0xf) << 12)		|
346*b35ce0c4SPankaj Gupta 			     ((wrtord_bg & 0xf) << 8)			|
347*b35ce0c4SPankaj Gupta 			     ((pre_all_rec & 0x1f) << 0));
348*b35ce0c4SPankaj Gupta 	debug("timing_cfg[8] = 0x%x\n", regs->timing_cfg[8]);
349*b35ce0c4SPankaj Gupta 
350*b35ce0c4SPankaj Gupta 	regs->timing_cfg[9] = (refrec_cid_mclk & 0x3ff) << 16		|
351*b35ce0c4SPankaj Gupta 			      (acttoact_cid_mclk & 0xf) << 8;
352*b35ce0c4SPankaj Gupta 	debug("timing_cfg[9] = 0x%x\n", regs->timing_cfg[9]);
353*b35ce0c4SPankaj Gupta }
354*b35ce0c4SPankaj Gupta 
355*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_rcw(const unsigned long clk,
356*b35ce0c4SPankaj Gupta 			      struct ddr_cfg_regs *regs,
357*b35ce0c4SPankaj Gupta 			      const struct memctl_opt *popts,
358*b35ce0c4SPankaj Gupta 			      const struct dimm_params *pdimm)
359*b35ce0c4SPankaj Gupta {
360*b35ce0c4SPankaj Gupta 	const unsigned int freq = clk / 1000000U;
361*b35ce0c4SPankaj Gupta 	unsigned int rc0a, rc0f;
362*b35ce0c4SPankaj Gupta 
363*b35ce0c4SPankaj Gupta 	if (pdimm->rdimm == 0) {
364*b35ce0c4SPankaj Gupta 		return;
365*b35ce0c4SPankaj Gupta 	}
366*b35ce0c4SPankaj Gupta 
367*b35ce0c4SPankaj Gupta 	rc0a = freq > 3200U ? 7U :
368*b35ce0c4SPankaj Gupta 	       (freq > 2933U ? 6U :
369*b35ce0c4SPankaj Gupta 		(freq > 2666U ? 5U :
370*b35ce0c4SPankaj Gupta 		 (freq > 2400U ? 4U :
371*b35ce0c4SPankaj Gupta 		  (freq > 2133U ? 3U :
372*b35ce0c4SPankaj Gupta 		   (freq > 1866U ? 2U :
373*b35ce0c4SPankaj Gupta 		    (freq > 1600U ? 1U : 0U))))));
374*b35ce0c4SPankaj Gupta 	rc0f = freq > 3200U ? 3U :
375*b35ce0c4SPankaj Gupta 		(freq > 2400U ? 2U :
376*b35ce0c4SPankaj Gupta 		 (freq > 2133U ? 1U : 0U));
377*b35ce0c4SPankaj Gupta 	rc0f = (regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) ? rc0f : 4;
378*b35ce0c4SPankaj Gupta 	regs->sdram_rcw[0] =
379*b35ce0c4SPankaj Gupta 		pdimm->rcw[0] << 28	|
380*b35ce0c4SPankaj Gupta 		pdimm->rcw[1] << 24	|
381*b35ce0c4SPankaj Gupta 		pdimm->rcw[2] << 20	|
382*b35ce0c4SPankaj Gupta 		pdimm->rcw[3] << 16	|
383*b35ce0c4SPankaj Gupta 		pdimm->rcw[4] << 12	|
384*b35ce0c4SPankaj Gupta 		pdimm->rcw[5] << 8	|
385*b35ce0c4SPankaj Gupta 		pdimm->rcw[6] << 4	|
386*b35ce0c4SPankaj Gupta 		pdimm->rcw[7];
387*b35ce0c4SPankaj Gupta 	regs->sdram_rcw[1] =
388*b35ce0c4SPankaj Gupta 		pdimm->rcw[8] << 28	|
389*b35ce0c4SPankaj Gupta 		pdimm->rcw[9] << 24	|
390*b35ce0c4SPankaj Gupta 		rc0a << 20		|
391*b35ce0c4SPankaj Gupta 		pdimm->rcw[11] << 16	|
392*b35ce0c4SPankaj Gupta 		pdimm->rcw[12] << 12	|
393*b35ce0c4SPankaj Gupta 		pdimm->rcw[13] << 8	|
394*b35ce0c4SPankaj Gupta 		pdimm->rcw[14] << 4	|
395*b35ce0c4SPankaj Gupta 		rc0f;
396*b35ce0c4SPankaj Gupta 	regs->sdram_rcw[2] =
397*b35ce0c4SPankaj Gupta 		((freq - 1260 + 19) / 20) << 8;
398*b35ce0c4SPankaj Gupta 
399*b35ce0c4SPankaj Gupta 	debug("sdram_rcw[0] = 0x%x\n", regs->sdram_rcw[0]);
400*b35ce0c4SPankaj Gupta 	debug("sdram_rcw[1] = 0x%x\n", regs->sdram_rcw[1]);
401*b35ce0c4SPankaj Gupta 	debug("sdram_rcw[2] = 0x%x\n", regs->sdram_rcw[2]);
402*b35ce0c4SPankaj Gupta }
403*b35ce0c4SPankaj Gupta 
404*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_cfg(const unsigned long clk,
405*b35ce0c4SPankaj Gupta 			      struct ddr_cfg_regs *regs,
406*b35ce0c4SPankaj Gupta 			      const struct memctl_opt *popts,
407*b35ce0c4SPankaj Gupta 			      const struct dimm_params *pdimm,
408*b35ce0c4SPankaj Gupta 			      const unsigned int ip_rev)
409*b35ce0c4SPankaj Gupta {
410*b35ce0c4SPankaj Gupta 	const unsigned int mem_en = 1U;
411*b35ce0c4SPankaj Gupta 	const unsigned int sren = popts->self_refresh_in_sleep;
412*b35ce0c4SPankaj Gupta 	const unsigned int ecc_en = popts->ecc_mode;
413*b35ce0c4SPankaj Gupta 	const unsigned int rd_en = (pdimm->rdimm != 0U) ? 1U : 0U;
414*b35ce0c4SPankaj Gupta 	const unsigned int dyn_pwr = popts->dynamic_power;
415*b35ce0c4SPankaj Gupta 	const unsigned int dbw = popts->data_bus_used;
416*b35ce0c4SPankaj Gupta 	const unsigned int eight_be = (dbw == 1U ||
417*b35ce0c4SPankaj Gupta 				       popts->burst_length == DDR_BL8) ? 1U : 0U;
418*b35ce0c4SPankaj Gupta 	const unsigned int ncap = 0U;
419*b35ce0c4SPankaj Gupta 	const unsigned int threet_en = popts->threet_en;
420*b35ce0c4SPankaj Gupta 	const unsigned int twot_en = pdimm->rdimm ?
421*b35ce0c4SPankaj Gupta 					0U : popts->twot_en;
422*b35ce0c4SPankaj Gupta 	const unsigned int ba_intlv = popts->ba_intlv;
423*b35ce0c4SPankaj Gupta 	const unsigned int x32_en = 0U;
424*b35ce0c4SPankaj Gupta 	const unsigned int pchb8 = 0U;
425*b35ce0c4SPankaj Gupta 	const unsigned int hse = popts->half_strength_drive_en;
426*b35ce0c4SPankaj Gupta 	const unsigned int acc_ecc_en = (dbw != 0U && ecc_en == 1U) ? 1U : 0U;
427*b35ce0c4SPankaj Gupta 	const unsigned int mem_halt = 0U;
428*b35ce0c4SPankaj Gupta #ifdef PHY_GEN2
429*b35ce0c4SPankaj Gupta 	const unsigned int bi = 1U;
430*b35ce0c4SPankaj Gupta #else
431*b35ce0c4SPankaj Gupta 	const unsigned int bi = 0U;
432*b35ce0c4SPankaj Gupta #endif
433*b35ce0c4SPankaj Gupta 	const unsigned int sdram_type = SDRAM_TYPE_DDR4;
434*b35ce0c4SPankaj Gupta 	unsigned int odt_cfg = 0U;
435*b35ce0c4SPankaj Gupta 	const unsigned int frc_sr = 0U;
436*b35ce0c4SPankaj Gupta 	const unsigned int sr_ie = popts->self_refresh_irq_en;
437*b35ce0c4SPankaj Gupta 	const unsigned int num_pr = pdimm->package_3ds + 1U;
438*b35ce0c4SPankaj Gupta 	const unsigned int slow = (clk < 1249000000U) ? 1U : 0U;
439*b35ce0c4SPankaj Gupta 	const unsigned int x4_en = popts->x4_en;
440*b35ce0c4SPankaj Gupta 	const unsigned int obc_cfg = popts->otf_burst_chop_en;
441*b35ce0c4SPankaj Gupta 	const unsigned int ap_en = ip_rev == 0x50500U ? 0U : popts->ap_en;
442*b35ce0c4SPankaj Gupta 	const unsigned int d_init = popts->ctlr_init_ecc;
443*b35ce0c4SPankaj Gupta 	const unsigned int rcw_en = popts->rdimm;
444*b35ce0c4SPankaj Gupta 	const unsigned int md_en = popts->mirrored_dimm;
445*b35ce0c4SPankaj Gupta 	const unsigned int qd_en = popts->quad_rank_present;
446*b35ce0c4SPankaj Gupta 	const unsigned int unq_mrs_en = ip_rev < 0x50500U ? 1U : 0U;
447*b35ce0c4SPankaj Gupta 	const unsigned int rd_pre = popts->quad_rank_present;
448*b35ce0c4SPankaj Gupta 	int i;
449*b35ce0c4SPankaj Gupta 
450*b35ce0c4SPankaj Gupta 	regs->sdram_cfg[0] = ((mem_en & 0x1) << 31)		|
451*b35ce0c4SPankaj Gupta 				((sren & 0x1) << 30)		|
452*b35ce0c4SPankaj Gupta 				((ecc_en & 0x1) << 29)		|
453*b35ce0c4SPankaj Gupta 				((rd_en & 0x1) << 28)		|
454*b35ce0c4SPankaj Gupta 				((sdram_type & 0x7) << 24)	|
455*b35ce0c4SPankaj Gupta 				((dyn_pwr & 0x1) << 21)		|
456*b35ce0c4SPankaj Gupta 				((dbw & 0x3) << 19)		|
457*b35ce0c4SPankaj Gupta 				((eight_be & 0x1) << 18)	|
458*b35ce0c4SPankaj Gupta 				((ncap & 0x1) << 17)		|
459*b35ce0c4SPankaj Gupta 				((threet_en & 0x1) << 16)	|
460*b35ce0c4SPankaj Gupta 				((twot_en & 0x1) << 15)		|
461*b35ce0c4SPankaj Gupta 				((ba_intlv & 0x7F) << 8)	|
462*b35ce0c4SPankaj Gupta 				((x32_en & 0x1) << 5)		|
463*b35ce0c4SPankaj Gupta 				((pchb8 & 0x1) << 4)		|
464*b35ce0c4SPankaj Gupta 				((hse & 0x1) << 3)		|
465*b35ce0c4SPankaj Gupta 				((acc_ecc_en & 0x1) << 2)	|
466*b35ce0c4SPankaj Gupta 				((mem_halt & 0x1) << 1)		|
467*b35ce0c4SPankaj Gupta 				((bi & 0x1) << 0);
468*b35ce0c4SPankaj Gupta 	debug("sdram_cfg[0] = 0x%x\n", regs->sdram_cfg[0]);
469*b35ce0c4SPankaj Gupta 
470*b35ce0c4SPankaj Gupta 	for (i = 0; i < DDRC_NUM_CS; i++) {
471*b35ce0c4SPankaj Gupta 		if (popts->cs_odt[i].odt_rd_cfg != 0 ||
472*b35ce0c4SPankaj Gupta 		    popts->cs_odt[i].odt_wr_cfg != 0) {
473*b35ce0c4SPankaj Gupta 			odt_cfg = SDRAM_CFG2_ODT_ONLY_READ;
474*b35ce0c4SPankaj Gupta 			break;
475*b35ce0c4SPankaj Gupta 		}
476*b35ce0c4SPankaj Gupta 	}
477*b35ce0c4SPankaj Gupta 
478*b35ce0c4SPankaj Gupta 	regs->sdram_cfg[1] = (0
479*b35ce0c4SPankaj Gupta 		| ((frc_sr & 0x1) << 31)
480*b35ce0c4SPankaj Gupta 		| ((sr_ie & 0x1) << 30)
481*b35ce0c4SPankaj Gupta 		| ((odt_cfg & 0x3) << 21)
482*b35ce0c4SPankaj Gupta 		| ((num_pr & 0xf) << 12)
483*b35ce0c4SPankaj Gupta 		| ((slow & 1) << 11)
484*b35ce0c4SPankaj Gupta 		| (x4_en << 10)
485*b35ce0c4SPankaj Gupta 		| (qd_en << 9)
486*b35ce0c4SPankaj Gupta 		| (unq_mrs_en << 8)
487*b35ce0c4SPankaj Gupta 		| ((obc_cfg & 0x1) << 6)
488*b35ce0c4SPankaj Gupta 		| ((ap_en & 0x1) << 5)
489*b35ce0c4SPankaj Gupta 		| ((d_init & 0x1) << 4)
490*b35ce0c4SPankaj Gupta 		| ((rcw_en & 0x1) << 2)
491*b35ce0c4SPankaj Gupta 		| ((md_en & 0x1) << 0)
492*b35ce0c4SPankaj Gupta 		);
493*b35ce0c4SPankaj Gupta 	debug("sdram_cfg[1] = 0x%x\n", regs->sdram_cfg[1]);
494*b35ce0c4SPankaj Gupta 
495*b35ce0c4SPankaj Gupta 	regs->sdram_cfg[2] = (rd_pre & 0x1) << 16	|
496*b35ce0c4SPankaj Gupta 				 (popts->rdimm ? 1 : 0);
497*b35ce0c4SPankaj Gupta 	if (pdimm->package_3ds != 0) {
498*b35ce0c4SPankaj Gupta 		if (((pdimm->package_3ds + 1) & 0x1) != 0) {
499*b35ce0c4SPankaj Gupta 			WARN("Unsupported 3DS DIMM\n");
500*b35ce0c4SPankaj Gupta 		} else {
501*b35ce0c4SPankaj Gupta 			regs->sdram_cfg[2] |= ((pdimm->package_3ds + 1) >> 1)
502*b35ce0c4SPankaj Gupta 						  << 4;
503*b35ce0c4SPankaj Gupta 		}
504*b35ce0c4SPankaj Gupta 	}
505*b35ce0c4SPankaj Gupta 	debug("sdram_cfg[2] = 0x%x\n", regs->sdram_cfg[2]);
506*b35ce0c4SPankaj Gupta }
507*b35ce0c4SPankaj Gupta 
508*b35ce0c4SPankaj Gupta 
509*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_interval(const unsigned long clk,
510*b35ce0c4SPankaj Gupta 				   struct ddr_cfg_regs *regs,
511*b35ce0c4SPankaj Gupta 				   const struct memctl_opt *popts,
512*b35ce0c4SPankaj Gupta 				   const struct dimm_params *pdimm)
513*b35ce0c4SPankaj Gupta {
514*b35ce0c4SPankaj Gupta 	const unsigned int refint = picos_to_mclk(clk, pdimm->refresh_rate_ps);
515*b35ce0c4SPankaj Gupta 	const unsigned int bstopre = popts->bstopre;
516*b35ce0c4SPankaj Gupta 
517*b35ce0c4SPankaj Gupta 	regs->interval = ((refint & 0xFFFF) << 16)	|
518*b35ce0c4SPankaj Gupta 				  ((bstopre & 0x3FFF) << 0);
519*b35ce0c4SPankaj Gupta 	debug("interval = 0x%x\n", regs->interval);
520*b35ce0c4SPankaj Gupta }
521*b35ce0c4SPankaj Gupta 
522*b35ce0c4SPankaj Gupta /* Require cs and cfg first */
523*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_mode(const unsigned long clk,
524*b35ce0c4SPankaj Gupta 			       struct ddr_cfg_regs *regs,
525*b35ce0c4SPankaj Gupta 			       const struct memctl_opt *popts,
526*b35ce0c4SPankaj Gupta 			       const struct ddr_conf *conf,
527*b35ce0c4SPankaj Gupta 			       const struct dimm_params *pdimm,
528*b35ce0c4SPankaj Gupta 			       unsigned int cas_latency,
529*b35ce0c4SPankaj Gupta 			       unsigned int additive_latency,
530*b35ce0c4SPankaj Gupta 			       const unsigned int ip_rev)
531*b35ce0c4SPankaj Gupta {
532*b35ce0c4SPankaj Gupta 	int i;
533*b35ce0c4SPankaj Gupta 	unsigned short esdmode;		/* Extended SDRAM mode */
534*b35ce0c4SPankaj Gupta 	unsigned short sdmode;		/* SDRAM mode */
535*b35ce0c4SPankaj Gupta 
536*b35ce0c4SPankaj Gupta 	/* Mode Register - MR1 */
537*b35ce0c4SPankaj Gupta 	const unsigned int qoff = 0;
538*b35ce0c4SPankaj Gupta 	const unsigned int tdqs_en = 0;
539*b35ce0c4SPankaj Gupta 	unsigned int rtt;
540*b35ce0c4SPankaj Gupta 	const unsigned int wrlvl_en = 0;
541*b35ce0c4SPankaj Gupta 	unsigned int al = 0;
542*b35ce0c4SPankaj Gupta 	unsigned int dic = 0;
543*b35ce0c4SPankaj Gupta 	const unsigned int dll_en = 1;
544*b35ce0c4SPankaj Gupta 
545*b35ce0c4SPankaj Gupta 	/* Mode Register - MR0 */
546*b35ce0c4SPankaj Gupta 	unsigned int wr = 0;
547*b35ce0c4SPankaj Gupta 	const unsigned int dll_rst = 0;
548*b35ce0c4SPankaj Gupta 	const unsigned int mode = 0;
549*b35ce0c4SPankaj Gupta 	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
550*b35ce0c4SPankaj Gupta 	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
551*b35ce0c4SPankaj Gupta 	const unsigned int bt = 0;
552*b35ce0c4SPankaj Gupta 	const unsigned int bl = popts->burst_length == DDR_BL8 ? 0 :
553*b35ce0c4SPankaj Gupta 				 (popts->burst_length == DDR_BC4 ? 2 : 1);
554*b35ce0c4SPankaj Gupta 
555*b35ce0c4SPankaj Gupta 	const unsigned int wr_mclk = picos_to_mclk(clk, pdimm->twr_ps);
556*b35ce0c4SPankaj Gupta 	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
557*b35ce0c4SPankaj Gupta 	static const int wr_table[] = {
558*b35ce0c4SPankaj Gupta 		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6
559*b35ce0c4SPankaj Gupta 	};
560*b35ce0c4SPankaj Gupta 	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
561*b35ce0c4SPankaj Gupta 	static const int cas_latency_table[] = {
562*b35ce0c4SPankaj Gupta 		0, 1, 2, 3, 4, 5, 6, 7, 13, 8,
563*b35ce0c4SPankaj Gupta 		14, 9, 15, 10, 12, 11, 16, 17,
564*b35ce0c4SPankaj Gupta 		18, 19, 20, 21, 22, 23
565*b35ce0c4SPankaj Gupta 	};
566*b35ce0c4SPankaj Gupta 	const unsigned int unq_mrs_en = ip_rev < U(0x50500) ? 1U : 0U;
567*b35ce0c4SPankaj Gupta 	unsigned short esdmode2 = 0U;
568*b35ce0c4SPankaj Gupta 	unsigned short esdmode3 = 0U;
569*b35ce0c4SPankaj Gupta 	const unsigned int wr_crc = 0U;
570*b35ce0c4SPankaj Gupta 	unsigned int rtt_wr = 0U;
571*b35ce0c4SPankaj Gupta 	const unsigned int srt = 0U;
572*b35ce0c4SPankaj Gupta 	unsigned int cwl = cal_cwl(clk);
573*b35ce0c4SPankaj Gupta 	const unsigned int mpr = 0U;
574*b35ce0c4SPankaj Gupta 	const unsigned int mclk_ps = get_memory_clk_ps(clk);
575*b35ce0c4SPankaj Gupta 	const unsigned int wc_lat = 0U;
576*b35ce0c4SPankaj Gupta 	unsigned short esdmode4 = 0U;
577*b35ce0c4SPankaj Gupta 	unsigned short esdmode5;
578*b35ce0c4SPankaj Gupta 	int rtt_park_all = 0;
579*b35ce0c4SPankaj Gupta 	unsigned int rtt_park;
580*b35ce0c4SPankaj Gupta 	const bool four_cs = conf->cs_in_use == 0xf ? true : false;
581*b35ce0c4SPankaj Gupta 	unsigned short esdmode6 = 0U;	/* Extended SDRAM mode 6 */
582*b35ce0c4SPankaj Gupta 	unsigned short esdmode7 = 0U;	/* Extended SDRAM mode 7 */
583*b35ce0c4SPankaj Gupta 	const unsigned int tccdl_min = max(5U,
584*b35ce0c4SPankaj Gupta 					   picos_to_mclk(clk, pdimm->tccdl_ps));
585*b35ce0c4SPankaj Gupta 
586*b35ce0c4SPankaj Gupta 	if (popts->rtt_override != 0U) {
587*b35ce0c4SPankaj Gupta 		rtt = popts->rtt_override_value;
588*b35ce0c4SPankaj Gupta 	} else {
589*b35ce0c4SPankaj Gupta 		rtt = popts->cs_odt[0].odt_rtt_norm;
590*b35ce0c4SPankaj Gupta 	}
591*b35ce0c4SPankaj Gupta 
592*b35ce0c4SPankaj Gupta 	if (additive_latency == (cas_latency - 1)) {
593*b35ce0c4SPankaj Gupta 		al = 1;
594*b35ce0c4SPankaj Gupta 	}
595*b35ce0c4SPankaj Gupta 	if (additive_latency == (cas_latency - 2)) {
596*b35ce0c4SPankaj Gupta 		al = 2;
597*b35ce0c4SPankaj Gupta 	}
598*b35ce0c4SPankaj Gupta 
599*b35ce0c4SPankaj Gupta 	if (popts->quad_rank_present != 0 || popts->output_driver_impedance != 0) {
600*b35ce0c4SPankaj Gupta 		dic = 1;	/* output driver impedance 240/7 ohm */
601*b35ce0c4SPankaj Gupta 	}
602*b35ce0c4SPankaj Gupta 
603*b35ce0c4SPankaj Gupta 	esdmode = (((qoff & 0x1) << 12)				|
604*b35ce0c4SPankaj Gupta 		   ((tdqs_en & 0x1) << 11)			|
605*b35ce0c4SPankaj Gupta 		   ((rtt & 0x7) << 8)				|
606*b35ce0c4SPankaj Gupta 		   ((wrlvl_en & 0x1) << 7)			|
607*b35ce0c4SPankaj Gupta 		   ((al & 0x3) << 3)				|
608*b35ce0c4SPankaj Gupta 		   ((dic & 0x3) << 1)				|
609*b35ce0c4SPankaj Gupta 		   ((dll_en & 0x1) << 0));
610*b35ce0c4SPankaj Gupta 
611*b35ce0c4SPankaj Gupta 	if (wr_mclk >= 10 && wr_mclk <= 24) {
612*b35ce0c4SPankaj Gupta 		wr = wr_table[wr_mclk - 10];
613*b35ce0c4SPankaj Gupta 	} else {
614*b35ce0c4SPankaj Gupta 		ERROR("unsupported wc_mclk = %d for mode register\n", wr_mclk);
615*b35ce0c4SPankaj Gupta 	}
616*b35ce0c4SPankaj Gupta 
617*b35ce0c4SPankaj Gupta 	/* look up table to get the cas latency bits */
618*b35ce0c4SPankaj Gupta 	if (cas_latency >= 9 && cas_latency <= 32) {
619*b35ce0c4SPankaj Gupta 		caslat = cas_latency_table[cas_latency - 9];
620*b35ce0c4SPankaj Gupta 	} else {
621*b35ce0c4SPankaj Gupta 		WARN("Error: unsupported cas latency for mode register\n");
622*b35ce0c4SPankaj Gupta 	}
623*b35ce0c4SPankaj Gupta 
624*b35ce0c4SPankaj Gupta 	sdmode = (((caslat & 0x10) << 8)			|
625*b35ce0c4SPankaj Gupta 		  ((wr & 0x7) << 9)				|
626*b35ce0c4SPankaj Gupta 		  ((dll_rst & 0x1) << 8)			|
627*b35ce0c4SPankaj Gupta 		  ((mode & 0x1) << 7)				|
628*b35ce0c4SPankaj Gupta 		  (((caslat >> 1) & 0x7) << 4)			|
629*b35ce0c4SPankaj Gupta 		  ((bt & 0x1) << 3)				|
630*b35ce0c4SPankaj Gupta 		  ((caslat & 1) << 2)				|
631*b35ce0c4SPankaj Gupta 		  ((bl & 0x3) << 0));
632*b35ce0c4SPankaj Gupta 
633*b35ce0c4SPankaj Gupta 	regs->sdram_mode[0] = (((esdmode & 0xFFFF) << 16)	|
634*b35ce0c4SPankaj Gupta 				 ((sdmode & 0xFFFF) << 0));
635*b35ce0c4SPankaj Gupta 	debug("sdram_mode[0] = 0x%x\n", regs->sdram_mode[0]);
636*b35ce0c4SPankaj Gupta 
637*b35ce0c4SPankaj Gupta 	switch (cwl) {
638*b35ce0c4SPankaj Gupta 	case 9:
639*b35ce0c4SPankaj Gupta 	case 10:
640*b35ce0c4SPankaj Gupta 	case 11:
641*b35ce0c4SPankaj Gupta 	case 12:
642*b35ce0c4SPankaj Gupta 		cwl -= 9;
643*b35ce0c4SPankaj Gupta 		break;
644*b35ce0c4SPankaj Gupta 	case 14:
645*b35ce0c4SPankaj Gupta 		cwl -= 10;
646*b35ce0c4SPankaj Gupta 		break;
647*b35ce0c4SPankaj Gupta 	case 16:
648*b35ce0c4SPankaj Gupta 		cwl -= 11;
649*b35ce0c4SPankaj Gupta 		break;
650*b35ce0c4SPankaj Gupta 	case 18:
651*b35ce0c4SPankaj Gupta 		cwl -= 12;
652*b35ce0c4SPankaj Gupta 		break;
653*b35ce0c4SPankaj Gupta 	case 20:
654*b35ce0c4SPankaj Gupta 		cwl -= 13;
655*b35ce0c4SPankaj Gupta 		break;
656*b35ce0c4SPankaj Gupta 	default:
657*b35ce0c4SPankaj Gupta 		printf("Error CWL\n");
658*b35ce0c4SPankaj Gupta 		break;
659*b35ce0c4SPankaj Gupta 	}
660*b35ce0c4SPankaj Gupta 
661*b35ce0c4SPankaj Gupta 	if (popts->rtt_override != 0) {
662*b35ce0c4SPankaj Gupta 		rtt_wr = popts->rtt_wr_override_value;
663*b35ce0c4SPankaj Gupta 	} else {
664*b35ce0c4SPankaj Gupta 		rtt_wr = popts->cs_odt[0].odt_rtt_wr;
665*b35ce0c4SPankaj Gupta 	}
666*b35ce0c4SPankaj Gupta 
667*b35ce0c4SPankaj Gupta 	esdmode2 = ((wr_crc & 0x1) << 12)			|
668*b35ce0c4SPankaj Gupta 		   ((rtt_wr & 0x7) << 9)			|
669*b35ce0c4SPankaj Gupta 		   ((srt & 0x3) << 6)				|
670*b35ce0c4SPankaj Gupta 		   ((cwl & 0x7) << 3);
671*b35ce0c4SPankaj Gupta 	esdmode3 = ((mpr & 0x3) << 11) | ((wc_lat & 0x3) << 9);
672*b35ce0c4SPankaj Gupta 
673*b35ce0c4SPankaj Gupta 	regs->sdram_mode[1] = ((esdmode2 & 0xFFFF) << 16)	|
674*b35ce0c4SPankaj Gupta 				((esdmode3 & 0xFFFF) << 0);
675*b35ce0c4SPankaj Gupta 	debug("sdram_mode[1] = 0x%x\n", regs->sdram_mode[1]);
676*b35ce0c4SPankaj Gupta 
677*b35ce0c4SPankaj Gupta 	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
678*b35ce0c4SPankaj Gupta 	if (popts->vref_dimm != 0) {
679*b35ce0c4SPankaj Gupta 		esdmode6 |= popts->vref_dimm & 0x7f;
680*b35ce0c4SPankaj Gupta 	} else if ((popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) != 0) {
681*b35ce0c4SPankaj Gupta 		esdmode6 |= 1 << 6;	/* Range 2 */
682*b35ce0c4SPankaj Gupta 	}
683*b35ce0c4SPankaj Gupta 
684*b35ce0c4SPankaj Gupta 	regs->sdram_mode[9] = ((esdmode6 & 0xffff) << 16)	|
685*b35ce0c4SPankaj Gupta 				 ((esdmode7 & 0xffff) << 0);
686*b35ce0c4SPankaj Gupta 	debug("sdram_mode[9] = 0x%x\n", regs->sdram_mode[9]);
687*b35ce0c4SPankaj Gupta 
688*b35ce0c4SPankaj Gupta 	rtt_park = (popts->rtt_park != 0) ? popts->rtt_park : 240;
689*b35ce0c4SPankaj Gupta 	switch (rtt_park) {
690*b35ce0c4SPankaj Gupta 	case 240:
691*b35ce0c4SPankaj Gupta 		rtt_park = 0x4;
692*b35ce0c4SPankaj Gupta 		break;
693*b35ce0c4SPankaj Gupta 	case 120:
694*b35ce0c4SPankaj Gupta 		rtt_park = 0x2;
695*b35ce0c4SPankaj Gupta 		break;
696*b35ce0c4SPankaj Gupta 	case 80:
697*b35ce0c4SPankaj Gupta 		rtt_park = 0x6;
698*b35ce0c4SPankaj Gupta 		break;
699*b35ce0c4SPankaj Gupta 	case 60:
700*b35ce0c4SPankaj Gupta 		rtt_park = 0x1;
701*b35ce0c4SPankaj Gupta 		break;
702*b35ce0c4SPankaj Gupta 	case 48:
703*b35ce0c4SPankaj Gupta 		rtt_park = 0x5;
704*b35ce0c4SPankaj Gupta 		break;
705*b35ce0c4SPankaj Gupta 	case 40:
706*b35ce0c4SPankaj Gupta 		rtt_park = 0x3;
707*b35ce0c4SPankaj Gupta 		break;
708*b35ce0c4SPankaj Gupta 	case 34:
709*b35ce0c4SPankaj Gupta 		rtt_park = 0x7;
710*b35ce0c4SPankaj Gupta 		break;
711*b35ce0c4SPankaj Gupta 	default:
712*b35ce0c4SPankaj Gupta 		rtt_park = 0;
713*b35ce0c4SPankaj Gupta 		break;
714*b35ce0c4SPankaj Gupta 	}
715*b35ce0c4SPankaj Gupta 
716*b35ce0c4SPankaj Gupta 	for (i = 0; i < DDRC_NUM_CS; i++) {
717*b35ce0c4SPankaj Gupta 		if (i != 0 && unq_mrs_en == 0) {
718*b35ce0c4SPankaj Gupta 			break;
719*b35ce0c4SPankaj Gupta 		}
720*b35ce0c4SPankaj Gupta 
721*b35ce0c4SPankaj Gupta 		if (popts->rtt_override != 0) {
722*b35ce0c4SPankaj Gupta 			rtt = popts->rtt_override_value;
723*b35ce0c4SPankaj Gupta 			rtt_wr = popts->rtt_wr_override_value;
724*b35ce0c4SPankaj Gupta 		} else {
725*b35ce0c4SPankaj Gupta 			rtt = popts->cs_odt[i].odt_rtt_norm;
726*b35ce0c4SPankaj Gupta 			rtt_wr = popts->cs_odt[i].odt_rtt_wr;
727*b35ce0c4SPankaj Gupta 		}
728*b35ce0c4SPankaj Gupta 
729*b35ce0c4SPankaj Gupta 		esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
730*b35ce0c4SPankaj Gupta 		esdmode |= (rtt & 0x7) << 8;
731*b35ce0c4SPankaj Gupta 		esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
732*b35ce0c4SPankaj Gupta 		esdmode2 |= (rtt_wr & 0x3) << 9;
733*b35ce0c4SPankaj Gupta 		esdmode5 = (popts->x4_en) ? 0 : 0x400; /* data mask */
734*b35ce0c4SPankaj Gupta 
735*b35ce0c4SPankaj Gupta 		if (rtt_park_all == 0 &&
736*b35ce0c4SPankaj Gupta 		    ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) != 0)) {
737*b35ce0c4SPankaj Gupta 			esdmode5 |= rtt_park << 6;
738*b35ce0c4SPankaj Gupta 			rtt_park_all = four_cs ? 0 : 1;
739*b35ce0c4SPankaj Gupta 		}
740*b35ce0c4SPankaj Gupta 
741*b35ce0c4SPankaj Gupta 		if (((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) &&
742*b35ce0c4SPankaj Gupta 		    (popts->rdimm == 0)) {
743*b35ce0c4SPankaj Gupta 			if (mclk_ps >= 935) {
744*b35ce0c4SPankaj Gupta 				esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK;
745*b35ce0c4SPankaj Gupta 			} else if (mclk_ps >= 833) {
746*b35ce0c4SPankaj Gupta 				esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
747*b35ce0c4SPankaj Gupta 			} else {
748*b35ce0c4SPankaj Gupta 				esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK;
749*b35ce0c4SPankaj Gupta 				WARN("mclk_ps not supported %d", mclk_ps);
750*b35ce0c4SPankaj Gupta 
751*b35ce0c4SPankaj Gupta 			}
752*b35ce0c4SPankaj Gupta 		}
753*b35ce0c4SPankaj Gupta 
754*b35ce0c4SPankaj Gupta 		switch (i) {
755*b35ce0c4SPankaj Gupta 		case 0:
756*b35ce0c4SPankaj Gupta 			regs->sdram_mode[8] = ((esdmode4 & 0xffff) << 16) |
757*b35ce0c4SPankaj Gupta 						((esdmode5 & 0xffff) << 0);
758*b35ce0c4SPankaj Gupta 			debug("sdram_mode[8] = 0x%x\n", regs->sdram_mode[8]);
759*b35ce0c4SPankaj Gupta 			break;
760*b35ce0c4SPankaj Gupta 		case 1:
761*b35ce0c4SPankaj Gupta 			regs->sdram_mode[2] = (((esdmode & 0xFFFF) << 16) |
762*b35ce0c4SPankaj Gupta 					      ((sdmode & 0xFFFF) << 0));
763*b35ce0c4SPankaj Gupta 			regs->sdram_mode[3] = ((esdmode2 & 0xFFFF) << 16) |
764*b35ce0c4SPankaj Gupta 					      ((esdmode3 & 0xFFFF) << 0);
765*b35ce0c4SPankaj Gupta 			regs->sdram_mode[10] = ((esdmode4 & 0xFFFF) << 16) |
766*b35ce0c4SPankaj Gupta 					       ((esdmode5 & 0xFFFF) << 0);
767*b35ce0c4SPankaj Gupta 			regs->sdram_mode[11] = ((esdmode6 & 0xFFFF) << 16) |
768*b35ce0c4SPankaj Gupta 					       ((esdmode7 & 0xFFFF) << 0);
769*b35ce0c4SPankaj Gupta 			debug("sdram_mode[2] = 0x%x\n", regs->sdram_mode[2]);
770*b35ce0c4SPankaj Gupta 			debug("sdram_mode[3] = 0x%x\n", regs->sdram_mode[3]);
771*b35ce0c4SPankaj Gupta 			debug("sdram_mode[10] = 0x%x\n", regs->sdram_mode[10]);
772*b35ce0c4SPankaj Gupta 			debug("sdram_mode[11] = 0x%x\n", regs->sdram_mode[11]);
773*b35ce0c4SPankaj Gupta 			break;
774*b35ce0c4SPankaj Gupta 		case 2:
775*b35ce0c4SPankaj Gupta 			regs->sdram_mode[4] = (((esdmode & 0xFFFF) << 16) |
776*b35ce0c4SPankaj Gupta 					      ((sdmode & 0xFFFF) << 0));
777*b35ce0c4SPankaj Gupta 			regs->sdram_mode[5] = ((esdmode2 & 0xFFFF) << 16) |
778*b35ce0c4SPankaj Gupta 					      ((esdmode3 & 0xFFFF) << 0);
779*b35ce0c4SPankaj Gupta 			regs->sdram_mode[12] = ((esdmode4 & 0xFFFF) << 16) |
780*b35ce0c4SPankaj Gupta 					       ((esdmode5 & 0xFFFF) << 0);
781*b35ce0c4SPankaj Gupta 			regs->sdram_mode[13] = ((esdmode6 & 0xFFFF) << 16) |
782*b35ce0c4SPankaj Gupta 					       ((esdmode7 & 0xFFFF) << 0);
783*b35ce0c4SPankaj Gupta 			debug("sdram_mode[4] = 0x%x\n", regs->sdram_mode[4]);
784*b35ce0c4SPankaj Gupta 			debug("sdram_mode[5] = 0x%x\n", regs->sdram_mode[5]);
785*b35ce0c4SPankaj Gupta 			debug("sdram_mode[12] = 0x%x\n", regs->sdram_mode[12]);
786*b35ce0c4SPankaj Gupta 			debug("sdram_mode[13] = 0x%x\n", regs->sdram_mode[13]);
787*b35ce0c4SPankaj Gupta 			break;
788*b35ce0c4SPankaj Gupta 		case 3:
789*b35ce0c4SPankaj Gupta 			regs->sdram_mode[6] = (((esdmode & 0xFFFF) << 16) |
790*b35ce0c4SPankaj Gupta 					      ((sdmode & 0xFFFF) << 0));
791*b35ce0c4SPankaj Gupta 			regs->sdram_mode[7] = ((esdmode2 & 0xFFFF) << 16) |
792*b35ce0c4SPankaj Gupta 					      ((esdmode3 & 0xFFFF) << 0);
793*b35ce0c4SPankaj Gupta 			regs->sdram_mode[14] = ((esdmode4 & 0xFFFF) << 16) |
794*b35ce0c4SPankaj Gupta 					       ((esdmode5 & 0xFFFF) << 0);
795*b35ce0c4SPankaj Gupta 			regs->sdram_mode[15] = ((esdmode6 & 0xFFFF) << 16) |
796*b35ce0c4SPankaj Gupta 					       ((esdmode7 & 0xFFFF) << 0);
797*b35ce0c4SPankaj Gupta 			debug("sdram_mode[6] = 0x%x\n", regs->sdram_mode[6]);
798*b35ce0c4SPankaj Gupta 			debug("sdram_mode[7] = 0x%x\n", regs->sdram_mode[7]);
799*b35ce0c4SPankaj Gupta 			debug("sdram_mode[14] = 0x%x\n", regs->sdram_mode[14]);
800*b35ce0c4SPankaj Gupta 			debug("sdram_mode[15] = 0x%x\n", regs->sdram_mode[15]);
801*b35ce0c4SPankaj Gupta 			break;
802*b35ce0c4SPankaj Gupta 		default:
803*b35ce0c4SPankaj Gupta 			break;
804*b35ce0c4SPankaj Gupta 		}
805*b35ce0c4SPankaj Gupta 	}
806*b35ce0c4SPankaj Gupta }
807*b35ce0c4SPankaj Gupta 
808*b35ce0c4SPankaj Gupta #ifndef CONFIG_MEM_INIT_VALUE
809*b35ce0c4SPankaj Gupta #define CONFIG_MEM_INIT_VALUE 0xDEADBEEF
810*b35ce0c4SPankaj Gupta #endif
811*b35ce0c4SPankaj Gupta static void cal_ddr_data_init(struct ddr_cfg_regs *regs)
812*b35ce0c4SPankaj Gupta {
813*b35ce0c4SPankaj Gupta 	regs->data_init = CONFIG_MEM_INIT_VALUE;
814*b35ce0c4SPankaj Gupta }
815*b35ce0c4SPankaj Gupta 
816*b35ce0c4SPankaj Gupta static void cal_ddr_dq_mapping(struct ddr_cfg_regs *regs,
817*b35ce0c4SPankaj Gupta 			       const struct dimm_params *pdimm)
818*b35ce0c4SPankaj Gupta {
819*b35ce0c4SPankaj Gupta 	const unsigned int acc_ecc_en = (regs->sdram_cfg[0] >> 2) & 0x1;
820*b35ce0c4SPankaj Gupta /* FIXME: revert the dq mapping from DIMM */
821*b35ce0c4SPankaj Gupta 	regs->dq_map[0] = ((pdimm->dq_mapping[0] & 0x3F) << 26)	|
822*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[1] & 0x3F) << 20)	|
823*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[2] & 0x3F) << 14)	|
824*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[3] & 0x3F) << 8)	|
825*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[4] & 0x3F) << 2);
826*b35ce0c4SPankaj Gupta 
827*b35ce0c4SPankaj Gupta 	regs->dq_map[1] = ((pdimm->dq_mapping[5] & 0x3F) << 26)	|
828*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[6] & 0x3F) << 20)	|
829*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[7] & 0x3F) << 14)	|
830*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[10] & 0x3F) << 8)	|
831*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[11] & 0x3F) << 2);
832*b35ce0c4SPankaj Gupta 
833*b35ce0c4SPankaj Gupta 	regs->dq_map[2] = ((pdimm->dq_mapping[12] & 0x3F) << 26)	|
834*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[13] & 0x3F) << 20)		|
835*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[14] & 0x3F) << 14)		|
836*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[15] & 0x3F) << 8)		|
837*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[16] & 0x3F) << 2);
838*b35ce0c4SPankaj Gupta 
839*b35ce0c4SPankaj Gupta 	/* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */
840*b35ce0c4SPankaj Gupta 	regs->dq_map[3] = ((pdimm->dq_mapping[17] & 0x3F) << 26)	|
841*b35ce0c4SPankaj Gupta 			 ((pdimm->dq_mapping[8] & 0x3F) << 20)		|
842*b35ce0c4SPankaj Gupta 			 ((acc_ecc_en != 0) ? 0 :
843*b35ce0c4SPankaj Gupta 			  (pdimm->dq_mapping[9] & 0x3F) << 14)		|
844*b35ce0c4SPankaj Gupta 			 pdimm->dq_mapping_ors;
845*b35ce0c4SPankaj Gupta 	debug("dq_map[0] = 0x%x\n", regs->dq_map[0]);
846*b35ce0c4SPankaj Gupta 	debug("dq_map[1] = 0x%x\n", regs->dq_map[1]);
847*b35ce0c4SPankaj Gupta 	debug("dq_map[2] = 0x%x\n", regs->dq_map[2]);
848*b35ce0c4SPankaj Gupta 	debug("dq_map[3] = 0x%x\n", regs->dq_map[3]);
849*b35ce0c4SPankaj Gupta }
850*b35ce0c4SPankaj Gupta static void cal_ddr_zq_cntl(struct ddr_cfg_regs *regs)
851*b35ce0c4SPankaj Gupta {
852*b35ce0c4SPankaj Gupta 	const unsigned int zqinit = 10U;	/* 1024 clocks */
853*b35ce0c4SPankaj Gupta 	const unsigned int zqoper = 9U;		/* 512 clocks */
854*b35ce0c4SPankaj Gupta 	const unsigned int zqcs = 7U;		/* 128 clocks */
855*b35ce0c4SPankaj Gupta 	const unsigned int zqcs_init = 5U;	/* 1024 refresh seqences */
856*b35ce0c4SPankaj Gupta 	const unsigned int zq_en = 1U;		/* enabled */
857*b35ce0c4SPankaj Gupta 
858*b35ce0c4SPankaj Gupta 	regs->zq_cntl = ((zq_en & 0x1) << 31)			|
859*b35ce0c4SPankaj Gupta 			   ((zqinit & 0xF) << 24)		|
860*b35ce0c4SPankaj Gupta 			   ((zqoper & 0xF) << 16)		|
861*b35ce0c4SPankaj Gupta 			   ((zqcs & 0xF) << 8)			|
862*b35ce0c4SPankaj Gupta 			   ((zqcs_init & 0xF) << 0);
863*b35ce0c4SPankaj Gupta 	debug("zq_cntl = 0x%x\n", regs->zq_cntl);
864*b35ce0c4SPankaj Gupta }
865*b35ce0c4SPankaj Gupta 
866*b35ce0c4SPankaj Gupta static void cal_ddr_sr_cntr(struct ddr_cfg_regs *regs,
867*b35ce0c4SPankaj Gupta 			    const struct memctl_opt *popts)
868*b35ce0c4SPankaj Gupta {
869*b35ce0c4SPankaj Gupta 	const unsigned int sr_it = (popts->auto_self_refresh_en) ?
870*b35ce0c4SPankaj Gupta 					popts->sr_it : 0;
871*b35ce0c4SPankaj Gupta 
872*b35ce0c4SPankaj Gupta 	regs->ddr_sr_cntr = (sr_it & 0xF) << 16;
873*b35ce0c4SPankaj Gupta 	debug("ddr_sr_cntr = 0x%x\n", regs->ddr_sr_cntr);
874*b35ce0c4SPankaj Gupta }
875*b35ce0c4SPankaj Gupta 
876*b35ce0c4SPankaj Gupta static void cal_ddr_eor(struct ddr_cfg_regs *regs,
877*b35ce0c4SPankaj Gupta 			const struct memctl_opt *popts)
878*b35ce0c4SPankaj Gupta {
879*b35ce0c4SPankaj Gupta 	if (popts->addr_hash != 0) {
880*b35ce0c4SPankaj Gupta 		regs->eor = 0x40000000;	/* address hash enable */
881*b35ce0c4SPankaj Gupta 		debug("eor = 0x%x\n", regs->eor);
882*b35ce0c4SPankaj Gupta 	}
883*b35ce0c4SPankaj Gupta }
884*b35ce0c4SPankaj Gupta 
885*b35ce0c4SPankaj Gupta static void cal_ddr_csn_bnds(struct ddr_cfg_regs *regs,
886*b35ce0c4SPankaj Gupta 			     const struct memctl_opt *popts,
887*b35ce0c4SPankaj Gupta 			     const struct ddr_conf *conf,
888*b35ce0c4SPankaj Gupta 			     const struct dimm_params *pdimm)
889*b35ce0c4SPankaj Gupta {
890*b35ce0c4SPankaj Gupta 	int i;
891*b35ce0c4SPankaj Gupta 	unsigned long long ea, sa;
892*b35ce0c4SPankaj Gupta 
893*b35ce0c4SPankaj Gupta 	/* Chip Select Memory Bounds (CSn_BNDS) */
894*b35ce0c4SPankaj Gupta 	for (i = 0;
895*b35ce0c4SPankaj Gupta 		i < DDRC_NUM_CS && conf->cs_size[i];
896*b35ce0c4SPankaj Gupta 		i++) {
897*b35ce0c4SPankaj Gupta 		debug("cs_in_use = 0x%x\n", conf->cs_in_use);
898*b35ce0c4SPankaj Gupta 		if (conf->cs_in_use != 0) {
899*b35ce0c4SPankaj Gupta 			sa = conf->cs_base_addr[i];
900*b35ce0c4SPankaj Gupta 			ea = sa + conf->cs_size[i] - 1;
901*b35ce0c4SPankaj Gupta 			sa >>= 24;
902*b35ce0c4SPankaj Gupta 			ea >>= 24;
903*b35ce0c4SPankaj Gupta 			regs->cs[i].bnds = ((sa & 0xffff) << 16) |
904*b35ce0c4SPankaj Gupta 					   ((ea & 0xffff) << 0);
905*b35ce0c4SPankaj Gupta 			cal_csn_config(i, regs, popts, pdimm);
906*b35ce0c4SPankaj Gupta 		} else {
907*b35ce0c4SPankaj Gupta 			/* setting bnds to 0xffffffff for inactive CS */
908*b35ce0c4SPankaj Gupta 			regs->cs[i].bnds = 0xffffffff;
909*b35ce0c4SPankaj Gupta 		}
910*b35ce0c4SPankaj Gupta 
911*b35ce0c4SPankaj Gupta 		debug("cs[%d].bnds = 0x%x\n", i, regs->cs[i].bnds);
912*b35ce0c4SPankaj Gupta 	}
913*b35ce0c4SPankaj Gupta }
914*b35ce0c4SPankaj Gupta 
915*b35ce0c4SPankaj Gupta static void cal_ddr_addr_dec(struct ddr_cfg_regs *regs)
916*b35ce0c4SPankaj Gupta {
917*b35ce0c4SPankaj Gupta #ifdef CONFIG_DDR_ADDR_DEC
918*b35ce0c4SPankaj Gupta 	unsigned int ba_bits __unused;
919*b35ce0c4SPankaj Gupta 	char p __unused;
920*b35ce0c4SPankaj Gupta 	const unsigned int cs0_config = regs->cs[0].config;
921*b35ce0c4SPankaj Gupta 	const int cacheline = PLATFORM_CACHE_LINE_SHIFT;
922*b35ce0c4SPankaj Gupta 	unsigned int bg_bits;
923*b35ce0c4SPankaj Gupta 	unsigned int row_bits;
924*b35ce0c4SPankaj Gupta 	unsigned int col_bits;
925*b35ce0c4SPankaj Gupta 	unsigned int cs;
926*b35ce0c4SPankaj Gupta 	unsigned int map_row[18];
927*b35ce0c4SPankaj Gupta 	unsigned int map_col[11];
928*b35ce0c4SPankaj Gupta 	unsigned int map_ba[2];
929*b35ce0c4SPankaj Gupta 	unsigned int map_cid[2] = {0x3F, 0x3F};
930*b35ce0c4SPankaj Gupta 	unsigned int map_bg[2] = {0x3F, 0x3F};
931*b35ce0c4SPankaj Gupta 	unsigned int map_cs[2] = {0x3F, 0x3F};
932*b35ce0c4SPankaj Gupta 	unsigned int dbw;
933*b35ce0c4SPankaj Gupta 	unsigned int ba_intlv;
934*b35ce0c4SPankaj Gupta 	int placement;
935*b35ce0c4SPankaj Gupta 	int intlv;
936*b35ce0c4SPankaj Gupta 	int abort = 0;
937*b35ce0c4SPankaj Gupta 	int i;
938*b35ce0c4SPankaj Gupta 	int j;
939*b35ce0c4SPankaj Gupta 
940*b35ce0c4SPankaj Gupta 	col_bits = (cs0_config >> 0) & 0x7;
941*b35ce0c4SPankaj Gupta 	if (col_bits < 4) {
942*b35ce0c4SPankaj Gupta 		col_bits += 8;
943*b35ce0c4SPankaj Gupta 	} else if (col_bits < 7 || col_bits > 10) {
944*b35ce0c4SPankaj Gupta 		ERROR("Error %s col_bits = %d\n", __func__, col_bits);
945*b35ce0c4SPankaj Gupta 	}
946*b35ce0c4SPankaj Gupta 	row_bits = ((cs0_config >> 8) & 0x7) + 12;
947*b35ce0c4SPankaj Gupta 	ba_bits = ((cs0_config >> 14) & 0x3) + 2;
948*b35ce0c4SPankaj Gupta 	bg_bits = ((cs0_config >> 4) & 0x3) + 0;
949*b35ce0c4SPankaj Gupta 	intlv = (cs0_config >> 24) & 0xf;
950*b35ce0c4SPankaj Gupta 	ba_intlv = (regs->sdram_cfg[0] >> 8) & 0x7f;
951*b35ce0c4SPankaj Gupta 	switch (ba_intlv) {
952*b35ce0c4SPankaj Gupta 	case DDR_BA_INTLV_CS01:
953*b35ce0c4SPankaj Gupta 		cs = 1;
954*b35ce0c4SPankaj Gupta 		break;
955*b35ce0c4SPankaj Gupta 	case DDR_BA_INTLV_CS0123:
956*b35ce0c4SPankaj Gupta 		cs = 2;
957*b35ce0c4SPankaj Gupta 		break;
958*b35ce0c4SPankaj Gupta 	case DDR_BA_NONE:
959*b35ce0c4SPankaj Gupta 		cs = 0;
960*b35ce0c4SPankaj Gupta 		break;
961*b35ce0c4SPankaj Gupta 	default:
962*b35ce0c4SPankaj Gupta 		ERROR("%s ba_intlv 0x%x\n", __func__, ba_intlv);
963*b35ce0c4SPankaj Gupta 		return;
964*b35ce0c4SPankaj Gupta 	}
965*b35ce0c4SPankaj Gupta 	debug("col %d, row %d, ba %d, bg %d, intlv %d\n",
966*b35ce0c4SPankaj Gupta 			col_bits, row_bits, ba_bits, bg_bits, intlv);
967*b35ce0c4SPankaj Gupta 	/*
968*b35ce0c4SPankaj Gupta 	 * Example mapping of 15x2x2x10
969*b35ce0c4SPankaj Gupta 	 * ---- --rr rrrr rrrr rrrr rCBB Gccc cccI cGcc cbbb
970*b35ce0c4SPankaj Gupta 	 */
971*b35ce0c4SPankaj Gupta 	dbw = (regs->sdram_cfg[0] >> 19) & 0x3;
972*b35ce0c4SPankaj Gupta 	switch (dbw) {
973*b35ce0c4SPankaj Gupta 	case 0:	/* 64-bit */
974*b35ce0c4SPankaj Gupta 		placement = 3;
975*b35ce0c4SPankaj Gupta 		break;
976*b35ce0c4SPankaj Gupta 	case 1:	/* 32-bit */
977*b35ce0c4SPankaj Gupta 		placement = 2;
978*b35ce0c4SPankaj Gupta 		break;
979*b35ce0c4SPankaj Gupta 	default:
980*b35ce0c4SPankaj Gupta 		ERROR("%s dbw = %d\n", __func__, dbw);
981*b35ce0c4SPankaj Gupta 		return;
982*b35ce0c4SPankaj Gupta 	}
983*b35ce0c4SPankaj Gupta 	debug("cacheline size %d\n", cacheline);
984*b35ce0c4SPankaj Gupta 	for (i = 0; placement < cacheline; i++) {
985*b35ce0c4SPankaj Gupta 		map_col[i] = placement++;
986*b35ce0c4SPankaj Gupta 	}
987*b35ce0c4SPankaj Gupta 	map_bg[0] = placement++;
988*b35ce0c4SPankaj Gupta 	for ( ; i < col_bits; i++) {
989*b35ce0c4SPankaj Gupta 		map_col[i] = placement++;
990*b35ce0c4SPankaj Gupta 		if (placement == intlv) {
991*b35ce0c4SPankaj Gupta 			placement++;
992*b35ce0c4SPankaj Gupta 		}
993*b35ce0c4SPankaj Gupta 	}
994*b35ce0c4SPankaj Gupta 	for ( ; i < 11; i++) {
995*b35ce0c4SPankaj Gupta 		map_col[i] = 0x3F;	/* unused col bits */
996*b35ce0c4SPankaj Gupta 	}
997*b35ce0c4SPankaj Gupta 
998*b35ce0c4SPankaj Gupta 	if (bg_bits >= 2) {
999*b35ce0c4SPankaj Gupta 		map_bg[1] = placement++;
1000*b35ce0c4SPankaj Gupta 	}
1001*b35ce0c4SPankaj Gupta 	map_ba[0] = placement++;
1002*b35ce0c4SPankaj Gupta 	map_ba[1] = placement++;
1003*b35ce0c4SPankaj Gupta 	if (cs != 0U) {
1004*b35ce0c4SPankaj Gupta 		map_cs[0] = placement++;
1005*b35ce0c4SPankaj Gupta 		if (cs == 2U) {
1006*b35ce0c4SPankaj Gupta 			map_cs[1] = placement++;
1007*b35ce0c4SPankaj Gupta 		}
1008*b35ce0c4SPankaj Gupta 	} else {
1009*b35ce0c4SPankaj Gupta 		map_cs[0] = U(0x3F);
1010*b35ce0c4SPankaj Gupta 	}
1011*b35ce0c4SPankaj Gupta 
1012*b35ce0c4SPankaj Gupta 	for (i = 0; i < row_bits; i++) {
1013*b35ce0c4SPankaj Gupta 		map_row[i] = placement++;
1014*b35ce0c4SPankaj Gupta 	}
1015*b35ce0c4SPankaj Gupta 
1016*b35ce0c4SPankaj Gupta 	for ( ; i < 18; i++) {
1017*b35ce0c4SPankaj Gupta 		map_row[i] = 0x3F;	/* unused row bits */
1018*b35ce0c4SPankaj Gupta 	}
1019*b35ce0c4SPankaj Gupta 
1020*b35ce0c4SPankaj Gupta 	for (i = 39; i >= 0 ; i--) {
1021*b35ce0c4SPankaj Gupta 		if (i == intlv) {
1022*b35ce0c4SPankaj Gupta 			placement = 8;
1023*b35ce0c4SPankaj Gupta 			p = 'I';
1024*b35ce0c4SPankaj Gupta 		} else if (i < 3) {
1025*b35ce0c4SPankaj Gupta 			p = 'b';
1026*b35ce0c4SPankaj Gupta 			placement = 0;
1027*b35ce0c4SPankaj Gupta 		} else {
1028*b35ce0c4SPankaj Gupta 			placement = 0;
1029*b35ce0c4SPankaj Gupta 			p = '-';
1030*b35ce0c4SPankaj Gupta 		}
1031*b35ce0c4SPankaj Gupta 		for (j = 0; j < 18; j++) {
1032*b35ce0c4SPankaj Gupta 			if (map_row[j] != i) {
1033*b35ce0c4SPankaj Gupta 				continue;
1034*b35ce0c4SPankaj Gupta 			}
1035*b35ce0c4SPankaj Gupta 			if (placement != 0) {
1036*b35ce0c4SPankaj Gupta 				abort = 1;
1037*b35ce0c4SPankaj Gupta 				ERROR("%s wrong address bit %d\n", __func__, i);
1038*b35ce0c4SPankaj Gupta 			}
1039*b35ce0c4SPankaj Gupta 			placement = i;
1040*b35ce0c4SPankaj Gupta 			p = 'r';
1041*b35ce0c4SPankaj Gupta 		}
1042*b35ce0c4SPankaj Gupta 		for (j = 0; j < 11; j++) {
1043*b35ce0c4SPankaj Gupta 			if (map_col[j] != i) {
1044*b35ce0c4SPankaj Gupta 				continue;
1045*b35ce0c4SPankaj Gupta 			}
1046*b35ce0c4SPankaj Gupta 			if (placement != 0) {
1047*b35ce0c4SPankaj Gupta 				abort = 1;
1048*b35ce0c4SPankaj Gupta 				ERROR("%s wrong address bit %d\n", __func__, i);
1049*b35ce0c4SPankaj Gupta 			}
1050*b35ce0c4SPankaj Gupta 			placement = i;
1051*b35ce0c4SPankaj Gupta 			p = 'c';
1052*b35ce0c4SPankaj Gupta 		}
1053*b35ce0c4SPankaj Gupta 		for (j = 0; j < 2; j++) {
1054*b35ce0c4SPankaj Gupta 			if (map_ba[j] != i) {
1055*b35ce0c4SPankaj Gupta 				continue;
1056*b35ce0c4SPankaj Gupta 			}
1057*b35ce0c4SPankaj Gupta 			if (placement != 0) {
1058*b35ce0c4SPankaj Gupta 				abort = 1;
1059*b35ce0c4SPankaj Gupta 				ERROR("%s wrong address bit %d\n", __func__, i);
1060*b35ce0c4SPankaj Gupta 			}
1061*b35ce0c4SPankaj Gupta 			placement = i;
1062*b35ce0c4SPankaj Gupta 			p = 'B';
1063*b35ce0c4SPankaj Gupta 		}
1064*b35ce0c4SPankaj Gupta 		for (j = 0; j < 2; j++) {
1065*b35ce0c4SPankaj Gupta 			if (map_bg[j] != i) {
1066*b35ce0c4SPankaj Gupta 				continue;
1067*b35ce0c4SPankaj Gupta 			}
1068*b35ce0c4SPankaj Gupta 			if (placement != 0) {
1069*b35ce0c4SPankaj Gupta 				abort = 1;
1070*b35ce0c4SPankaj Gupta 				ERROR("%s wrong address bit %d\n", __func__, i);
1071*b35ce0c4SPankaj Gupta 			}
1072*b35ce0c4SPankaj Gupta 			placement = i;
1073*b35ce0c4SPankaj Gupta 			p = 'G';
1074*b35ce0c4SPankaj Gupta 		}
1075*b35ce0c4SPankaj Gupta 		for (j = 0; j < 2; j++) {
1076*b35ce0c4SPankaj Gupta 			if (map_cs[j] != i) {
1077*b35ce0c4SPankaj Gupta 				continue;
1078*b35ce0c4SPankaj Gupta 			}
1079*b35ce0c4SPankaj Gupta 			if (placement != 0) {
1080*b35ce0c4SPankaj Gupta 				abort = 1;
1081*b35ce0c4SPankaj Gupta 				ERROR("%s wrong address bit %d\n", __func__, i);
1082*b35ce0c4SPankaj Gupta 			}
1083*b35ce0c4SPankaj Gupta 			placement = i;
1084*b35ce0c4SPankaj Gupta 			p = 'C';
1085*b35ce0c4SPankaj Gupta 		}
1086*b35ce0c4SPankaj Gupta #ifdef DDR_DEBUG
1087*b35ce0c4SPankaj Gupta 		printf("%c", p);
1088*b35ce0c4SPankaj Gupta 		if ((i % 4) == 0) {
1089*b35ce0c4SPankaj Gupta 			printf(" ");
1090*b35ce0c4SPankaj Gupta 		}
1091*b35ce0c4SPankaj Gupta #endif
1092*b35ce0c4SPankaj Gupta 	}
1093*b35ce0c4SPankaj Gupta #ifdef DDR_DEBUG
1094*b35ce0c4SPankaj Gupta 	puts("\n");
1095*b35ce0c4SPankaj Gupta #endif
1096*b35ce0c4SPankaj Gupta 
1097*b35ce0c4SPankaj Gupta 	if (abort != 0) {
1098*b35ce0c4SPankaj Gupta 		return;
1099*b35ce0c4SPankaj Gupta 	}
1100*b35ce0c4SPankaj Gupta 
1101*b35ce0c4SPankaj Gupta 	regs->dec[0] = map_row[17] << 26		|
1102*b35ce0c4SPankaj Gupta 		      map_row[16] << 18			|
1103*b35ce0c4SPankaj Gupta 		      map_row[15] << 10			|
1104*b35ce0c4SPankaj Gupta 		      map_row[14] << 2;
1105*b35ce0c4SPankaj Gupta 	regs->dec[1] = map_row[13] << 26		|
1106*b35ce0c4SPankaj Gupta 		      map_row[12] << 18			|
1107*b35ce0c4SPankaj Gupta 		      map_row[11] << 10			|
1108*b35ce0c4SPankaj Gupta 		      map_row[10] << 2;
1109*b35ce0c4SPankaj Gupta 	regs->dec[2] = map_row[9] << 26			|
1110*b35ce0c4SPankaj Gupta 		      map_row[8] << 18			|
1111*b35ce0c4SPankaj Gupta 		      map_row[7] << 10			|
1112*b35ce0c4SPankaj Gupta 		      map_row[6] << 2;
1113*b35ce0c4SPankaj Gupta 	regs->dec[3] = map_row[5] << 26			|
1114*b35ce0c4SPankaj Gupta 		      map_row[4] << 18			|
1115*b35ce0c4SPankaj Gupta 		      map_row[3] << 10			|
1116*b35ce0c4SPankaj Gupta 		      map_row[2] << 2;
1117*b35ce0c4SPankaj Gupta 	regs->dec[4] = map_row[1] << 26			|
1118*b35ce0c4SPankaj Gupta 		      map_row[0] << 18			|
1119*b35ce0c4SPankaj Gupta 		      map_col[10] << 10			|
1120*b35ce0c4SPankaj Gupta 		      map_col[9] << 2;
1121*b35ce0c4SPankaj Gupta 	regs->dec[5] = map_col[8] << 26			|
1122*b35ce0c4SPankaj Gupta 		      map_col[7] << 18			|
1123*b35ce0c4SPankaj Gupta 		      map_col[6] << 10			|
1124*b35ce0c4SPankaj Gupta 		      map_col[5] << 2;
1125*b35ce0c4SPankaj Gupta 	regs->dec[6] = map_col[4] << 26			|
1126*b35ce0c4SPankaj Gupta 		      map_col[3] << 18			|
1127*b35ce0c4SPankaj Gupta 		      map_col[2] << 10			|
1128*b35ce0c4SPankaj Gupta 		      map_col[1] << 2;
1129*b35ce0c4SPankaj Gupta 	regs->dec[7] = map_col[0] << 26			|
1130*b35ce0c4SPankaj Gupta 		      map_ba[1] << 18			|
1131*b35ce0c4SPankaj Gupta 		      map_ba[0] << 10			|
1132*b35ce0c4SPankaj Gupta 		      map_cid[1] << 2;
1133*b35ce0c4SPankaj Gupta 	regs->dec[8] = map_cid[1] << 26			|
1134*b35ce0c4SPankaj Gupta 		      map_cs[1] << 18			|
1135*b35ce0c4SPankaj Gupta 		      map_cs[0] << 10			|
1136*b35ce0c4SPankaj Gupta 		      map_bg[1] << 2;
1137*b35ce0c4SPankaj Gupta 	regs->dec[9] = map_bg[0] << 26			|
1138*b35ce0c4SPankaj Gupta 		      1;
1139*b35ce0c4SPankaj Gupta 	for (i = 0; i < 10; i++) {
1140*b35ce0c4SPankaj Gupta 		debug("dec[%d] = 0x%x\n", i, regs->dec[i]);
1141*b35ce0c4SPankaj Gupta 	}
1142*b35ce0c4SPankaj Gupta #endif
1143*b35ce0c4SPankaj Gupta }
1144*b35ce0c4SPankaj Gupta static unsigned int skip_caslat(unsigned int tckmin_ps,
1145*b35ce0c4SPankaj Gupta 				unsigned int taamin_ps,
1146*b35ce0c4SPankaj Gupta 				unsigned int mclk_ps,
1147*b35ce0c4SPankaj Gupta 				unsigned int package_3ds)
1148*b35ce0c4SPankaj Gupta {
1149*b35ce0c4SPankaj Gupta 	int i, j, k;
1150*b35ce0c4SPankaj Gupta 	struct cas {
1151*b35ce0c4SPankaj Gupta 		const unsigned int tckmin_ps;
1152*b35ce0c4SPankaj Gupta 		const unsigned int caslat[4];
1153*b35ce0c4SPankaj Gupta 	};
1154*b35ce0c4SPankaj Gupta 	struct speed {
1155*b35ce0c4SPankaj Gupta 		const struct cas *cl;
1156*b35ce0c4SPankaj Gupta 		const unsigned int taamin_ps[4];
1157*b35ce0c4SPankaj Gupta 	};
1158*b35ce0c4SPankaj Gupta 	const struct cas cl_3200[] = {
1159*b35ce0c4SPankaj Gupta 		{625,	{0xa00000, 0xb00000, 0xf000000,} },
1160*b35ce0c4SPankaj Gupta 		{750,	{ 0x20000,  0x60000,  0xe00000,} },
1161*b35ce0c4SPankaj Gupta 		{833,	{  0x8000,  0x18000,   0x38000,} },
1162*b35ce0c4SPankaj Gupta 		{937,	{  0x4000,   0x4000,    0xc000,} },
1163*b35ce0c4SPankaj Gupta 		{1071,	{  0x1000,   0x1000,    0x3000,} },
1164*b35ce0c4SPankaj Gupta 		{1250,	{   0x400,    0x400,     0xc00,} },
1165*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x600,     0x200,} },
1166*b35ce0c4SPankaj Gupta 	};
1167*b35ce0c4SPankaj Gupta 	const struct cas cl_2933[] = {
1168*b35ce0c4SPankaj Gupta 		{682,	{       0,  0x80000, 0x180000, 0x380000} },
1169*b35ce0c4SPankaj Gupta 		{750,	{ 0x20000,  0x60000,  0x60000,  0xe0000} },
1170*b35ce0c4SPankaj Gupta 		{833,	{  0x8000,  0x18000,  0x18000,  0x38000} },
1171*b35ce0c4SPankaj Gupta 		{937,	{  0x4000,   0x4000,   0x4000,   0xc000} },
1172*b35ce0c4SPankaj Gupta 		{1071,	{  0x1000,   0x1000,   0x1000,   0x3000} },
1173*b35ce0c4SPankaj Gupta 		{1250,	{   0x400,    0x400,    0x400,    0xc00} },
1174*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x200,    0x200,    0x200} },
1175*b35ce0c4SPankaj Gupta 	};
1176*b35ce0c4SPankaj Gupta 	const struct cas cl_2666[] = {
1177*b35ce0c4SPankaj Gupta 		{750,	{       0,  0x20000,  0x60000,  0xe0000} },
1178*b35ce0c4SPankaj Gupta 		{833,	{  0x8000,  0x18000,  0x18000,  0x38000} },
1179*b35ce0c4SPankaj Gupta 		{937,	{  0x4000,   0x4000,   0x4000,   0xc000} },
1180*b35ce0c4SPankaj Gupta 		{1071,	{  0x1000,   0x1000,   0x1000,   0x3000} },
1181*b35ce0c4SPankaj Gupta 		{1250,	{   0x400,    0x400,    0x400,    0xc00} },
1182*b35ce0c4SPankaj Gupta 		{1500,	{       0,        0,    0x200,    0x200} },
1183*b35ce0c4SPankaj Gupta 	};
1184*b35ce0c4SPankaj Gupta 	const struct cas cl_2400[] = {
1185*b35ce0c4SPankaj Gupta 		{833,	{       0,   0x8000,  0x18000,  0x38000} },
1186*b35ce0c4SPankaj Gupta 		{937,	{  0xc000,   0x4000,   0x4000,   0xc000} },
1187*b35ce0c4SPankaj Gupta 		{1071,	{  0x3000,   0x1000,   0x1000,   0x3000} },
1188*b35ce0c4SPankaj Gupta 		{1250,	{   0xc00,    0x400,    0x400,    0xc00} },
1189*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x400,    0x200,    0x200} },
1190*b35ce0c4SPankaj Gupta 	};
1191*b35ce0c4SPankaj Gupta 	const struct cas cl_2133[] = {
1192*b35ce0c4SPankaj Gupta 		{937,	{       0,   0x4000,   0xc000,} },
1193*b35ce0c4SPankaj Gupta 		{1071,	{  0x2000,        0,   0x2000,} },
1194*b35ce0c4SPankaj Gupta 		{1250,	{   0x800,        0,    0x800,} },
1195*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x400,    0x200,} },
1196*b35ce0c4SPankaj Gupta 	};
1197*b35ce0c4SPankaj Gupta 	const struct cas cl_1866[] = {
1198*b35ce0c4SPankaj Gupta 		{1071,	{       0,   0x1000,   0x3000,} },
1199*b35ce0c4SPankaj Gupta 		{1250,	{   0xc00,    0x400,    0xc00,} },
1200*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x400,    0x200,} },
1201*b35ce0c4SPankaj Gupta 	};
1202*b35ce0c4SPankaj Gupta 	const struct cas cl_1600[] = {
1203*b35ce0c4SPankaj Gupta 		{1250,	{       0,    0x400,    0xc00,} },
1204*b35ce0c4SPankaj Gupta 		{1500,	{       0,    0x400,    0x200,} },
1205*b35ce0c4SPankaj Gupta 	};
1206*b35ce0c4SPankaj Gupta 	const struct speed bin_0[] = {
1207*b35ce0c4SPankaj Gupta 		{cl_3200, {12500, 13750, 15000,} },
1208*b35ce0c4SPankaj Gupta 		{cl_2933, {12960, 13640, 13750, 15000,} },
1209*b35ce0c4SPankaj Gupta 		{cl_2666, {12750, 13500, 13750, 15000,} },
1210*b35ce0c4SPankaj Gupta 		{cl_2400, {12500, 13320, 13750, 15000,} },
1211*b35ce0c4SPankaj Gupta 		{cl_2133, {13130, 13500, 15000,} },
1212*b35ce0c4SPankaj Gupta 		{cl_1866, {12850, 13500, 15000,} },
1213*b35ce0c4SPankaj Gupta 		{cl_1600, {12500, 13500, 15000,} }
1214*b35ce0c4SPankaj Gupta 	};
1215*b35ce0c4SPankaj Gupta 	const struct cas cl_3200_3ds[] = {
1216*b35ce0c4SPankaj Gupta 		{625,	{ 0xa000000, 0xb000000, 0xf000000,} },
1217*b35ce0c4SPankaj Gupta 		{750,	{ 0xaa00000, 0xab00000, 0xef00000,} },
1218*b35ce0c4SPankaj Gupta 		{833,	{ 0xaac0000, 0xaac0000, 0xebc0000,} },
1219*b35ce0c4SPankaj Gupta 		{937,	{ 0xaab0000, 0xaab0000, 0xeaf0000,} },
1220*b35ce0c4SPankaj Gupta 		{1071,	{ 0xaaa4000, 0xaaac000, 0xeaec000,} },
1221*b35ce0c4SPankaj Gupta 		{1250,	{ 0xaaa0000, 0xaaa2000, 0xeaeb000,} },
1222*b35ce0c4SPankaj Gupta 	};
1223*b35ce0c4SPankaj Gupta 	const struct cas cl_2666_3ds[] = {
1224*b35ce0c4SPankaj Gupta 		{750,	{ 0xa00000, 0xb00000, 0xf00000,} },
1225*b35ce0c4SPankaj Gupta 		{833,	{ 0xac0000, 0xac0000, 0xbc0000,} },
1226*b35ce0c4SPankaj Gupta 		{937,	{ 0xab0000, 0xab0000, 0xaf0000,} },
1227*b35ce0c4SPankaj Gupta 		{1071,	{ 0xaa4000, 0xaac000, 0xaac000,} },
1228*b35ce0c4SPankaj Gupta 		{1250,	{ 0xaa0000, 0xaaa000, 0xaaa000,} },
1229*b35ce0c4SPankaj Gupta 	};
1230*b35ce0c4SPankaj Gupta 	const struct cas cl_2400_3ds[] = {
1231*b35ce0c4SPankaj Gupta 		{833,	{ 0xe00000, 0xe40000, 0xec0000, 0xb00000} },
1232*b35ce0c4SPankaj Gupta 		{937,	{ 0xe00000, 0xe00000, 0xea0000, 0xae0000} },
1233*b35ce0c4SPankaj Gupta 		{1071,	{ 0xe00000, 0xe04000, 0xeac000, 0xaec000} },
1234*b35ce0c4SPankaj Gupta 		{1250,	{ 0xe00000, 0xe00000, 0xeaa000, 0xae2000} },
1235*b35ce0c4SPankaj Gupta 	};
1236*b35ce0c4SPankaj Gupta 	const struct cas cl_2133_3ds[] = {
1237*b35ce0c4SPankaj Gupta 		{937,	{  0x90000,  0xb0000,  0xf0000,} },
1238*b35ce0c4SPankaj Gupta 		{1071,	{  0x84000,  0xac000,  0xec000,} },
1239*b35ce0c4SPankaj Gupta 		{1250,	{  0x80000,  0xa2000,  0xe2000,} },
1240*b35ce0c4SPankaj Gupta 	};
1241*b35ce0c4SPankaj Gupta 	const struct cas cl_1866_3ds[] = {
1242*b35ce0c4SPankaj Gupta 		{1071,	{        0,   0x4000,   0xc000,} },
1243*b35ce0c4SPankaj Gupta 		{1250,	{        0,   0x1000,   0x3000,} },
1244*b35ce0c4SPankaj Gupta 	};
1245*b35ce0c4SPankaj Gupta 	const struct cas cl_1600_3ds[] = {
1246*b35ce0c4SPankaj Gupta 		{1250,	{        0,   0x1000,   0x3000,} },
1247*b35ce0c4SPankaj Gupta 	};
1248*b35ce0c4SPankaj Gupta 	const struct speed bin_3ds[] = {
1249*b35ce0c4SPankaj Gupta 		{cl_3200_3ds, {15000, 16250, 17140,} },
1250*b35ce0c4SPankaj Gupta 		{cl_2666_3ds, {15000, 16500, 17140,} },
1251*b35ce0c4SPankaj Gupta 		{cl_2400_3ds, {15000, 15830, 16670, 17140} },
1252*b35ce0c4SPankaj Gupta 		{cl_2133_3ds, {15950, 16880, 17140,} },
1253*b35ce0c4SPankaj Gupta 		{cl_1866_3ds, {15000, 16070, 17140,} },
1254*b35ce0c4SPankaj Gupta 		{cl_1600_3ds, {15000, 16250, 17500,} },
1255*b35ce0c4SPankaj Gupta 	};
1256*b35ce0c4SPankaj Gupta 	const struct speed *bin;
1257*b35ce0c4SPankaj Gupta 	int size;
1258*b35ce0c4SPankaj Gupta 	unsigned int taamin_max, tck_max;
1259*b35ce0c4SPankaj Gupta 
1260*b35ce0c4SPankaj Gupta 	if (taamin_ps > ((package_3ds != 0) ? 21500 : 18000)) {
1261*b35ce0c4SPankaj Gupta 		ERROR("taamin_ps %u invalid\n", taamin_ps);
1262*b35ce0c4SPankaj Gupta 		return 0;
1263*b35ce0c4SPankaj Gupta 	}
1264*b35ce0c4SPankaj Gupta 	if (package_3ds != 0) {
1265*b35ce0c4SPankaj Gupta 		bin = bin_3ds;
1266*b35ce0c4SPankaj Gupta 		size = ARRAY_SIZE(bin_3ds);
1267*b35ce0c4SPankaj Gupta 		taamin_max = 1250;
1268*b35ce0c4SPankaj Gupta 		tck_max = 1500;
1269*b35ce0c4SPankaj Gupta 	} else {
1270*b35ce0c4SPankaj Gupta 		bin = bin_0;
1271*b35ce0c4SPankaj Gupta 		size = ARRAY_SIZE(bin_0);
1272*b35ce0c4SPankaj Gupta 		taamin_max = 1500;
1273*b35ce0c4SPankaj Gupta 		tck_max = 1600;
1274*b35ce0c4SPankaj Gupta 	}
1275*b35ce0c4SPankaj Gupta 	if (mclk_ps < 625 || mclk_ps > tck_max) {
1276*b35ce0c4SPankaj Gupta 		ERROR("mclk %u invalid\n", mclk_ps);
1277*b35ce0c4SPankaj Gupta 		return 0;
1278*b35ce0c4SPankaj Gupta 	}
1279*b35ce0c4SPankaj Gupta 
1280*b35ce0c4SPankaj Gupta 	for (i = 0; i < size; i++) {
1281*b35ce0c4SPankaj Gupta 		if (bin[i].cl[0].tckmin_ps >= tckmin_ps) {
1282*b35ce0c4SPankaj Gupta 			break;
1283*b35ce0c4SPankaj Gupta 		}
1284*b35ce0c4SPankaj Gupta 	}
1285*b35ce0c4SPankaj Gupta 	if (i >= size) {
1286*b35ce0c4SPankaj Gupta 		ERROR("speed bin not found\n");
1287*b35ce0c4SPankaj Gupta 		return 0;
1288*b35ce0c4SPankaj Gupta 	}
1289*b35ce0c4SPankaj Gupta 	if (bin[i].cl[0].tckmin_ps > tckmin_ps && i > 0) {
1290*b35ce0c4SPankaj Gupta 		i--;
1291*b35ce0c4SPankaj Gupta 	}
1292*b35ce0c4SPankaj Gupta 
1293*b35ce0c4SPankaj Gupta 	for (j = 0; j < 4; j++) {
1294*b35ce0c4SPankaj Gupta 		if ((bin[i].taamin_ps[j] == 0) ||
1295*b35ce0c4SPankaj Gupta 		    bin[i].taamin_ps[j] >= taamin_ps) {
1296*b35ce0c4SPankaj Gupta 			break;
1297*b35ce0c4SPankaj Gupta 		}
1298*b35ce0c4SPankaj Gupta 	}
1299*b35ce0c4SPankaj Gupta 
1300*b35ce0c4SPankaj Gupta 	if (j >= 4) {
1301*b35ce0c4SPankaj Gupta 		ERROR("taamin_ps out of range.\n");
1302*b35ce0c4SPankaj Gupta 		return 0;
1303*b35ce0c4SPankaj Gupta 	}
1304*b35ce0c4SPankaj Gupta 
1305*b35ce0c4SPankaj Gupta 	if ((bin[i].taamin_ps[j] == 0) ||
1306*b35ce0c4SPankaj Gupta 	    (bin[i].taamin_ps[j] > taamin_ps && j > 0)) {
1307*b35ce0c4SPankaj Gupta 		j--;
1308*b35ce0c4SPankaj Gupta 	}
1309*b35ce0c4SPankaj Gupta 
1310*b35ce0c4SPankaj Gupta 	for (k = 0; bin[i].cl[k].tckmin_ps < mclk_ps &&
1311*b35ce0c4SPankaj Gupta 		    bin[i].cl[k].tckmin_ps < taamin_max; k++)
1312*b35ce0c4SPankaj Gupta 		;
1313*b35ce0c4SPankaj Gupta 	if (bin[i].cl[k].tckmin_ps > mclk_ps && k > 0) {
1314*b35ce0c4SPankaj Gupta 		k--;
1315*b35ce0c4SPankaj Gupta 	}
1316*b35ce0c4SPankaj Gupta 
1317*b35ce0c4SPankaj Gupta 	debug("Skip CL mask for this speed 0x%x\n", bin[i].cl[k].caslat[j]);
1318*b35ce0c4SPankaj Gupta 
1319*b35ce0c4SPankaj Gupta 	return bin[i].cl[k].caslat[j];
1320*b35ce0c4SPankaj Gupta }
1321*b35ce0c4SPankaj Gupta 
1322*b35ce0c4SPankaj Gupta int compute_ddrc(const unsigned long clk,
1323*b35ce0c4SPankaj Gupta 		 const struct memctl_opt *popts,
1324*b35ce0c4SPankaj Gupta 		 const struct ddr_conf *conf,
1325*b35ce0c4SPankaj Gupta 		 struct ddr_cfg_regs *regs,
1326*b35ce0c4SPankaj Gupta 		 const struct dimm_params *pdimm,
1327*b35ce0c4SPankaj Gupta 		 unsigned int ip_rev)
1328*b35ce0c4SPankaj Gupta {
1329*b35ce0c4SPankaj Gupta 	unsigned int cas_latency;
1330*b35ce0c4SPankaj Gupta 	unsigned int caslat_skip;
1331*b35ce0c4SPankaj Gupta 	unsigned int additive_latency;
1332*b35ce0c4SPankaj Gupta 	const unsigned int mclk_ps = get_memory_clk_ps(clk);
1333*b35ce0c4SPankaj Gupta 	int i;
1334*b35ce0c4SPankaj Gupta 
1335*b35ce0c4SPankaj Gupta 	zeromem(regs, sizeof(struct ddr_cfg_regs));
1336*b35ce0c4SPankaj Gupta 
1337*b35ce0c4SPankaj Gupta 	if (mclk_ps < pdimm->tckmin_x_ps) {
1338*b35ce0c4SPankaj Gupta 		ERROR("DDR Clk: MCLK cycle is %u ps.\n", mclk_ps);
1339*b35ce0c4SPankaj Gupta 		ERROR("DDR Clk is faster than DIMM can support.\n");
1340*b35ce0c4SPankaj Gupta 	}
1341*b35ce0c4SPankaj Gupta 
1342*b35ce0c4SPankaj Gupta 	/* calculate cas latency, override first */
1343*b35ce0c4SPankaj Gupta 	cas_latency = (popts->caslat_override != 0) ?
1344*b35ce0c4SPankaj Gupta 			popts->caslat_override_value :
1345*b35ce0c4SPankaj Gupta 			(pdimm->taa_ps + mclk_ps - 1) / mclk_ps;
1346*b35ce0c4SPankaj Gupta 
1347*b35ce0c4SPankaj Gupta 	/* skip unsupported caslat based on speed bin */
1348*b35ce0c4SPankaj Gupta 	caslat_skip = skip_caslat(pdimm->tckmin_x_ps,
1349*b35ce0c4SPankaj Gupta 				  pdimm->taa_ps,
1350*b35ce0c4SPankaj Gupta 				  mclk_ps,
1351*b35ce0c4SPankaj Gupta 				  pdimm->package_3ds);
1352*b35ce0c4SPankaj Gupta 	debug("Skip caslat 0x%x\n", caslat_skip);
1353*b35ce0c4SPankaj Gupta 
1354*b35ce0c4SPankaj Gupta 	/* Check if DIMM supports the cas latency */
1355*b35ce0c4SPankaj Gupta 	i = 24;
1356*b35ce0c4SPankaj Gupta 	while (((pdimm->caslat_x & ~caslat_skip & (1 << cas_latency)) == 0) &&
1357*b35ce0c4SPankaj Gupta 	       (i-- > 0)) {
1358*b35ce0c4SPankaj Gupta 		cas_latency++;
1359*b35ce0c4SPankaj Gupta 	}
1360*b35ce0c4SPankaj Gupta 
1361*b35ce0c4SPankaj Gupta 	if (i <= 0) {
1362*b35ce0c4SPankaj Gupta 		ERROR("Failed to find a proper cas latency\n");
1363*b35ce0c4SPankaj Gupta 		return -EINVAL;
1364*b35ce0c4SPankaj Gupta 	}
1365*b35ce0c4SPankaj Gupta 	/* Verify cas latency does not exceed 18ns for DDR4 */
1366*b35ce0c4SPankaj Gupta 	if (cas_latency * mclk_ps > 18000) {
1367*b35ce0c4SPankaj Gupta 		ERROR("cas latency is too large %d\n", cas_latency);
1368*b35ce0c4SPankaj Gupta 		return -EINVAL;
1369*b35ce0c4SPankaj Gupta 	}
1370*b35ce0c4SPankaj Gupta 
1371*b35ce0c4SPankaj Gupta 	additive_latency = (popts->addt_lat_override != 0) ?
1372*b35ce0c4SPankaj Gupta 				popts->addt_lat_override_value : 0;
1373*b35ce0c4SPankaj Gupta 
1374*b35ce0c4SPankaj Gupta 	cal_ddr_csn_bnds(regs, popts, conf, pdimm);
1375*b35ce0c4SPankaj Gupta 	cal_ddr_sdram_cfg(clk, regs, popts, pdimm, ip_rev);
1376*b35ce0c4SPankaj Gupta 	cal_ddr_sdram_rcw(clk, regs, popts, pdimm);
1377*b35ce0c4SPankaj Gupta 	cal_timing_cfg(clk, regs, popts, pdimm, conf, cas_latency,
1378*b35ce0c4SPankaj Gupta 		       additive_latency);
1379*b35ce0c4SPankaj Gupta 	cal_ddr_dq_mapping(regs, pdimm);
1380*b35ce0c4SPankaj Gupta 
1381*b35ce0c4SPankaj Gupta 	if (ip_rev >= 0x50500) {
1382*b35ce0c4SPankaj Gupta 		cal_ddr_addr_dec(regs);
1383*b35ce0c4SPankaj Gupta 	}
1384*b35ce0c4SPankaj Gupta 
1385*b35ce0c4SPankaj Gupta 	cal_ddr_sdram_mode(clk, regs, popts, conf, pdimm, cas_latency,
1386*b35ce0c4SPankaj Gupta 			   additive_latency, ip_rev);
1387*b35ce0c4SPankaj Gupta 	cal_ddr_eor(regs, popts);
1388*b35ce0c4SPankaj Gupta 	cal_ddr_data_init(regs);
1389*b35ce0c4SPankaj Gupta 	cal_ddr_sdram_interval(clk, regs, popts, pdimm);
1390*b35ce0c4SPankaj Gupta 	cal_ddr_zq_cntl(regs);
1391*b35ce0c4SPankaj Gupta 	cal_ddr_sr_cntr(regs, popts);
1392*b35ce0c4SPankaj Gupta 
1393*b35ce0c4SPankaj Gupta 	return 0;
1394*b35ce0c4SPankaj Gupta }
1395