xref: /arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright 2021 NXP
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <errno.h>
8*91f16700Schasinglulu #include <inttypes.h>
9*91f16700Schasinglulu #include <stdint.h>
10*91f16700Schasinglulu #include <stdio.h>
11*91f16700Schasinglulu #include <stdlib.h>
12*91f16700Schasinglulu #include <string.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #include <common/debug.h>
15*91f16700Schasinglulu #include <ddr.h>
16*91f16700Schasinglulu #ifndef CONFIG_DDR_NODIMM
17*91f16700Schasinglulu #include <i2c.h>
18*91f16700Schasinglulu #endif
19*91f16700Schasinglulu #include <nxp_timer.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu struct dynamic_odt {
22*91f16700Schasinglulu 	unsigned int odt_rd_cfg;
23*91f16700Schasinglulu 	unsigned int odt_wr_cfg;
24*91f16700Schasinglulu 	unsigned int odt_rtt_norm;
25*91f16700Schasinglulu 	unsigned int odt_rtt_wr;
26*91f16700Schasinglulu };
27*91f16700Schasinglulu 
28*91f16700Schasinglulu #ifndef CONFIG_STATIC_DDR
29*91f16700Schasinglulu #if defined(PHY_GEN2_FW_IMAGE_BUFFER) && !defined(NXP_DDR_PHY_GEN2)
30*91f16700Schasinglulu #error Missing NXP_DDR_PHY_GEN2
31*91f16700Schasinglulu #endif
32*91f16700Schasinglulu #ifdef NXP_DDR_PHY_GEN2
33*91f16700Schasinglulu static const struct dynamic_odt single_D[4] = {
34*91f16700Schasinglulu 	{	/* cs0 */
35*91f16700Schasinglulu 		DDR_ODT_NEVER,
36*91f16700Schasinglulu 		DDR_ODT_ALL,
37*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
38*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
39*91f16700Schasinglulu 	},
40*91f16700Schasinglulu 	{	/* cs1 */
41*91f16700Schasinglulu 		DDR_ODT_NEVER,
42*91f16700Schasinglulu 		DDR_ODT_NEVER,
43*91f16700Schasinglulu 		DDR4_RTT_OFF,
44*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
45*91f16700Schasinglulu 	},
46*91f16700Schasinglulu 	{},
47*91f16700Schasinglulu 	{}
48*91f16700Schasinglulu };
49*91f16700Schasinglulu 
50*91f16700Schasinglulu static const struct dynamic_odt single_S[4] = {
51*91f16700Schasinglulu 	{	/* cs0 */
52*91f16700Schasinglulu 		DDR_ODT_NEVER,
53*91f16700Schasinglulu 		DDR_ODT_ALL,
54*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
55*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
56*91f16700Schasinglulu 	},
57*91f16700Schasinglulu 	{},
58*91f16700Schasinglulu 	{},
59*91f16700Schasinglulu 	{},
60*91f16700Schasinglulu };
61*91f16700Schasinglulu 
62*91f16700Schasinglulu static const struct dynamic_odt dual_DD[4] = {
63*91f16700Schasinglulu 	{	/* cs0 */
64*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
65*91f16700Schasinglulu 		DDR_ODT_ALL,
66*91f16700Schasinglulu 		DDR4_RTT_60_OHM,
67*91f16700Schasinglulu 		DDR4_RTT_WR_240_OHM
68*91f16700Schasinglulu 	},
69*91f16700Schasinglulu 	{	/* cs1 */
70*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
71*91f16700Schasinglulu 		DDR_ODT_ALL,
72*91f16700Schasinglulu 		DDR4_RTT_60_OHM,
73*91f16700Schasinglulu 		DDR4_RTT_WR_240_OHM
74*91f16700Schasinglulu 	},
75*91f16700Schasinglulu 	{	/* cs2 */
76*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
77*91f16700Schasinglulu 		DDR_ODT_ALL,
78*91f16700Schasinglulu 		DDR4_RTT_60_OHM,
79*91f16700Schasinglulu 		DDR4_RTT_WR_240_OHM
80*91f16700Schasinglulu 	},
81*91f16700Schasinglulu 	{	/* cs3 */
82*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
83*91f16700Schasinglulu 		DDR_ODT_ALL,
84*91f16700Schasinglulu 		DDR4_RTT_60_OHM,
85*91f16700Schasinglulu 		DDR4_RTT_WR_240_OHM
86*91f16700Schasinglulu 	}
87*91f16700Schasinglulu };
88*91f16700Schasinglulu 
89*91f16700Schasinglulu static const struct dynamic_odt dual_SS[4] = {
90*91f16700Schasinglulu 	{	/* cs0 */
91*91f16700Schasinglulu 		DDR_ODT_NEVER,
92*91f16700Schasinglulu 		DDR_ODT_ALL,
93*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
94*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
95*91f16700Schasinglulu 	},
96*91f16700Schasinglulu 	{},
97*91f16700Schasinglulu 	{	/* cs2 */
98*91f16700Schasinglulu 		DDR_ODT_NEVER,
99*91f16700Schasinglulu 		DDR_ODT_ALL,
100*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
101*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
102*91f16700Schasinglulu 	},
103*91f16700Schasinglulu 	{}
104*91f16700Schasinglulu };
105*91f16700Schasinglulu 
106*91f16700Schasinglulu static const struct dynamic_odt dual_D0[4] = {
107*91f16700Schasinglulu 	{	/* cs0 */
108*91f16700Schasinglulu 		DDR_ODT_NEVER,
109*91f16700Schasinglulu 		DDR_ODT_SAME_DIMM,
110*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
111*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
112*91f16700Schasinglulu 	},
113*91f16700Schasinglulu 	{	/* cs1 */
114*91f16700Schasinglulu 		DDR_ODT_NEVER,
115*91f16700Schasinglulu 		DDR_ODT_NEVER,
116*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
117*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
118*91f16700Schasinglulu 	},
119*91f16700Schasinglulu 	{},
120*91f16700Schasinglulu 	{}
121*91f16700Schasinglulu };
122*91f16700Schasinglulu 
123*91f16700Schasinglulu static const struct dynamic_odt dual_S0[4] = {
124*91f16700Schasinglulu 	{	/* cs0 */
125*91f16700Schasinglulu 		DDR_ODT_NEVER,
126*91f16700Schasinglulu 		DDR_ODT_CS,
127*91f16700Schasinglulu 		DDR4_RTT_80_OHM,
128*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
129*91f16700Schasinglulu 	},
130*91f16700Schasinglulu 	{},
131*91f16700Schasinglulu 	{},
132*91f16700Schasinglulu 	{}
133*91f16700Schasinglulu };
134*91f16700Schasinglulu #else
135*91f16700Schasinglulu static const struct dynamic_odt single_D[4] = {
136*91f16700Schasinglulu 	{	/* cs0 */
137*91f16700Schasinglulu 		DDR_ODT_NEVER,
138*91f16700Schasinglulu 		DDR_ODT_ALL,
139*91f16700Schasinglulu 		DDR4_RTT_40_OHM,
140*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
141*91f16700Schasinglulu 	},
142*91f16700Schasinglulu 	{	/* cs1 */
143*91f16700Schasinglulu 		DDR_ODT_NEVER,
144*91f16700Schasinglulu 		DDR_ODT_NEVER,
145*91f16700Schasinglulu 		DDR4_RTT_OFF,
146*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
147*91f16700Schasinglulu 	},
148*91f16700Schasinglulu 	{},
149*91f16700Schasinglulu 	{}
150*91f16700Schasinglulu };
151*91f16700Schasinglulu 
152*91f16700Schasinglulu static const struct dynamic_odt single_S[4] = {
153*91f16700Schasinglulu 	{	/* cs0 */
154*91f16700Schasinglulu 		DDR_ODT_NEVER,
155*91f16700Schasinglulu 		DDR_ODT_ALL,
156*91f16700Schasinglulu 		DDR4_RTT_40_OHM,
157*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
158*91f16700Schasinglulu 	},
159*91f16700Schasinglulu 	{},
160*91f16700Schasinglulu 	{},
161*91f16700Schasinglulu 	{},
162*91f16700Schasinglulu };
163*91f16700Schasinglulu 
164*91f16700Schasinglulu static const struct dynamic_odt dual_DD[4] = {
165*91f16700Schasinglulu 	{	/* cs0 */
166*91f16700Schasinglulu 		DDR_ODT_NEVER,
167*91f16700Schasinglulu 		DDR_ODT_SAME_DIMM,
168*91f16700Schasinglulu 		DDR4_RTT_120_OHM,
169*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
170*91f16700Schasinglulu 	},
171*91f16700Schasinglulu 	{	/* cs1 */
172*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
173*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
174*91f16700Schasinglulu 		DDR4_RTT_34_OHM,
175*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
176*91f16700Schasinglulu 	},
177*91f16700Schasinglulu 	{	/* cs2 */
178*91f16700Schasinglulu 		DDR_ODT_NEVER,
179*91f16700Schasinglulu 		DDR_ODT_SAME_DIMM,
180*91f16700Schasinglulu 		DDR4_RTT_120_OHM,
181*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
182*91f16700Schasinglulu 	},
183*91f16700Schasinglulu 	{	/* cs3 */
184*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
185*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
186*91f16700Schasinglulu 		DDR4_RTT_34_OHM,
187*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
188*91f16700Schasinglulu 	}
189*91f16700Schasinglulu };
190*91f16700Schasinglulu 
191*91f16700Schasinglulu static const struct dynamic_odt dual_SS[4] = {
192*91f16700Schasinglulu 	{	/* cs0 */
193*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
194*91f16700Schasinglulu 		DDR_ODT_ALL,
195*91f16700Schasinglulu 		DDR4_RTT_34_OHM,
196*91f16700Schasinglulu 		DDR4_RTT_WR_120_OHM
197*91f16700Schasinglulu 	},
198*91f16700Schasinglulu 	{},
199*91f16700Schasinglulu 	{	/* cs2 */
200*91f16700Schasinglulu 		DDR_ODT_OTHER_DIMM,
201*91f16700Schasinglulu 		DDR_ODT_ALL,
202*91f16700Schasinglulu 		DDR4_RTT_34_OHM,
203*91f16700Schasinglulu 		DDR4_RTT_WR_120_OHM
204*91f16700Schasinglulu 	},
205*91f16700Schasinglulu 	{}
206*91f16700Schasinglulu };
207*91f16700Schasinglulu 
208*91f16700Schasinglulu static const struct dynamic_odt dual_D0[4] = {
209*91f16700Schasinglulu 	{	/* cs0 */
210*91f16700Schasinglulu 		DDR_ODT_NEVER,
211*91f16700Schasinglulu 		DDR_ODT_SAME_DIMM,
212*91f16700Schasinglulu 		DDR4_RTT_40_OHM,
213*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
214*91f16700Schasinglulu 	},
215*91f16700Schasinglulu 	{	/* cs1 */
216*91f16700Schasinglulu 		DDR_ODT_NEVER,
217*91f16700Schasinglulu 		DDR_ODT_NEVER,
218*91f16700Schasinglulu 		DDR4_RTT_OFF,
219*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
220*91f16700Schasinglulu 	},
221*91f16700Schasinglulu 	{},
222*91f16700Schasinglulu 	{}
223*91f16700Schasinglulu };
224*91f16700Schasinglulu 
225*91f16700Schasinglulu static const struct dynamic_odt dual_S0[4] = {
226*91f16700Schasinglulu 	{	/* cs0 */
227*91f16700Schasinglulu 		DDR_ODT_NEVER,
228*91f16700Schasinglulu 		DDR_ODT_CS,
229*91f16700Schasinglulu 		DDR4_RTT_40_OHM,
230*91f16700Schasinglulu 		DDR4_RTT_WR_OFF
231*91f16700Schasinglulu 	},
232*91f16700Schasinglulu 	{},
233*91f16700Schasinglulu 	{},
234*91f16700Schasinglulu 	{}
235*91f16700Schasinglulu };
236*91f16700Schasinglulu #endif /* NXP_DDR_PHY_GEN2 */
237*91f16700Schasinglulu 
238*91f16700Schasinglulu /*
239*91f16700Schasinglulu  * Automatically select bank interleaving mode based on DIMMs
240*91f16700Schasinglulu  * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null.
241*91f16700Schasinglulu  * This function only deal with one or two slots per controller.
242*91f16700Schasinglulu  */
243*91f16700Schasinglulu static inline unsigned int auto_bank_intlv(const int cs_in_use,
244*91f16700Schasinglulu 					   const struct dimm_params *pdimm)
245*91f16700Schasinglulu {
246*91f16700Schasinglulu 	switch (cs_in_use) {
247*91f16700Schasinglulu 	case 0xf:
248*91f16700Schasinglulu 		return DDR_BA_INTLV_CS0123;
249*91f16700Schasinglulu 	case 0x3:
250*91f16700Schasinglulu 		return DDR_BA_INTLV_CS01;
251*91f16700Schasinglulu 	case 0x1:
252*91f16700Schasinglulu 		return DDR_BA_NONE;
253*91f16700Schasinglulu 	case 0x5:
254*91f16700Schasinglulu 		return DDR_BA_NONE;
255*91f16700Schasinglulu 	default:
256*91f16700Schasinglulu 		break;
257*91f16700Schasinglulu 	}
258*91f16700Schasinglulu 
259*91f16700Schasinglulu 	return 0U;
260*91f16700Schasinglulu }
261*91f16700Schasinglulu 
262*91f16700Schasinglulu static int cal_odt(const unsigned int clk,
263*91f16700Schasinglulu 		   struct memctl_opt *popts,
264*91f16700Schasinglulu 		   struct ddr_conf *conf,
265*91f16700Schasinglulu 		   struct dimm_params *pdimm,
266*91f16700Schasinglulu 		   const int dimm_slot_per_ctrl)
267*91f16700Schasinglulu 
268*91f16700Schasinglulu {
269*91f16700Schasinglulu 	unsigned int i;
270*91f16700Schasinglulu 	const struct dynamic_odt *pdodt = NULL;
271*91f16700Schasinglulu 
272*91f16700Schasinglulu 	static const struct dynamic_odt *table[2][5] = {
273*91f16700Schasinglulu 		{single_S, single_D, NULL, NULL},
274*91f16700Schasinglulu 		{dual_SS, dual_DD, NULL, NULL},
275*91f16700Schasinglulu 	};
276*91f16700Schasinglulu 
277*91f16700Schasinglulu 	if (dimm_slot_per_ctrl != 1 && dimm_slot_per_ctrl != 2) {
278*91f16700Schasinglulu 		ERROR("Unsupported number of DIMMs\n");
279*91f16700Schasinglulu 		return -EINVAL;
280*91f16700Schasinglulu 	}
281*91f16700Schasinglulu 
282*91f16700Schasinglulu 	pdodt = table[dimm_slot_per_ctrl - 1][pdimm->n_ranks - 1];
283*91f16700Schasinglulu 	if (pdodt == dual_SS) {
284*91f16700Schasinglulu 		pdodt = (conf->cs_in_use == 0x5) ? dual_SS :
285*91f16700Schasinglulu 			((conf->cs_in_use == 0x1) ? dual_S0 : NULL);
286*91f16700Schasinglulu 	} else if (pdodt == dual_DD) {
287*91f16700Schasinglulu 		pdodt = (conf->cs_in_use == 0xf) ? dual_DD :
288*91f16700Schasinglulu 			((conf->cs_in_use == 0x3) ? dual_D0 : NULL);
289*91f16700Schasinglulu 	}
290*91f16700Schasinglulu 	if (pdodt == dual_DD && pdimm->package_3ds) {
291*91f16700Schasinglulu 		ERROR("Too many 3DS DIMMs.\n");
292*91f16700Schasinglulu 		return -EINVAL;
293*91f16700Schasinglulu 	}
294*91f16700Schasinglulu 
295*91f16700Schasinglulu 	if (pdodt == NULL) {
296*91f16700Schasinglulu 		ERROR("Error determining ODT.\n");
297*91f16700Schasinglulu 		return -EINVAL;
298*91f16700Schasinglulu 	}
299*91f16700Schasinglulu 
300*91f16700Schasinglulu 	/* Pick chip-select local options. */
301*91f16700Schasinglulu 	for (i = 0U; i < DDRC_NUM_CS; i++) {
302*91f16700Schasinglulu 		debug("cs %d\n", i);
303*91f16700Schasinglulu 		popts->cs_odt[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
304*91f16700Schasinglulu 		debug("     odt_rd_cfg 0x%x\n",
305*91f16700Schasinglulu 			  popts->cs_odt[i].odt_rd_cfg);
306*91f16700Schasinglulu 		popts->cs_odt[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
307*91f16700Schasinglulu 		debug("     odt_wr_cfg 0x%x\n",
308*91f16700Schasinglulu 			  popts->cs_odt[i].odt_wr_cfg);
309*91f16700Schasinglulu 		popts->cs_odt[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
310*91f16700Schasinglulu 		debug("     odt_rtt_norm 0x%x\n",
311*91f16700Schasinglulu 			  popts->cs_odt[i].odt_rtt_norm);
312*91f16700Schasinglulu 		popts->cs_odt[i].odt_rtt_wr = pdodt[i].odt_rtt_wr;
313*91f16700Schasinglulu 		debug("     odt_rtt_wr 0x%x\n",
314*91f16700Schasinglulu 			  popts->cs_odt[i].odt_rtt_wr);
315*91f16700Schasinglulu 		popts->cs_odt[i].auto_precharge = 0;
316*91f16700Schasinglulu 		debug("     auto_precharge %d\n",
317*91f16700Schasinglulu 			  popts->cs_odt[i].auto_precharge);
318*91f16700Schasinglulu 	}
319*91f16700Schasinglulu 
320*91f16700Schasinglulu 	return 0;
321*91f16700Schasinglulu }
322*91f16700Schasinglulu 
323*91f16700Schasinglulu static int cal_opts(const unsigned int clk,
324*91f16700Schasinglulu 		    struct memctl_opt *popts,
325*91f16700Schasinglulu 		    struct ddr_conf *conf,
326*91f16700Schasinglulu 		    struct dimm_params *pdimm,
327*91f16700Schasinglulu 		    const int dimm_slot_per_ctrl,
328*91f16700Schasinglulu 		    const unsigned int ip_rev)
329*91f16700Schasinglulu {
330*91f16700Schasinglulu 	popts->rdimm = pdimm->rdimm;
331*91f16700Schasinglulu 	popts->mirrored_dimm = pdimm->mirrored_dimm;
332*91f16700Schasinglulu #ifdef CONFIG_DDR_ECC_EN
333*91f16700Schasinglulu 	popts->ecc_mode = pdimm->edc_config == 0x02 ? 1 : 0;
334*91f16700Schasinglulu #endif
335*91f16700Schasinglulu 	popts->ctlr_init_ecc = popts->ecc_mode;
336*91f16700Schasinglulu 	debug("ctlr_init_ecc %d\n", popts->ctlr_init_ecc);
337*91f16700Schasinglulu 	popts->self_refresh_in_sleep = 1;
338*91f16700Schasinglulu 	popts->dynamic_power = 0;
339*91f16700Schasinglulu 
340*91f16700Schasinglulu 	/*
341*91f16700Schasinglulu 	 * check sdram width, allow platform override
342*91f16700Schasinglulu 	 * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
343*91f16700Schasinglulu 	 */
344*91f16700Schasinglulu 	if (pdimm->primary_sdram_width == 64) {
345*91f16700Schasinglulu 		popts->data_bus_dimm = DDR_DBUS_64;
346*91f16700Schasinglulu 		popts->otf_burst_chop_en = 1;
347*91f16700Schasinglulu 	} else if (pdimm->primary_sdram_width == 32) {
348*91f16700Schasinglulu 		popts->data_bus_dimm = DDR_DBUS_32;
349*91f16700Schasinglulu 		popts->otf_burst_chop_en = 0;
350*91f16700Schasinglulu 	} else if (pdimm->primary_sdram_width == 16) {
351*91f16700Schasinglulu 		popts->data_bus_dimm = DDR_DBUS_16;
352*91f16700Schasinglulu 		popts->otf_burst_chop_en = 0;
353*91f16700Schasinglulu 	} else {
354*91f16700Schasinglulu 		ERROR("primary sdram width invalid!\n");
355*91f16700Schasinglulu 		return -EINVAL;
356*91f16700Schasinglulu 	}
357*91f16700Schasinglulu 	popts->data_bus_used = popts->data_bus_dimm;
358*91f16700Schasinglulu 	popts->x4_en = (pdimm->device_width == 4) ? 1 : 0;
359*91f16700Schasinglulu 	debug("x4_en %d\n", popts->x4_en);
360*91f16700Schasinglulu 
361*91f16700Schasinglulu 	/* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */
362*91f16700Schasinglulu 	if (popts->rdimm != 0) {
363*91f16700Schasinglulu 		popts->ap_en = 1; /* 0 = disable,  1 = enable */
364*91f16700Schasinglulu 	} else {
365*91f16700Schasinglulu 		popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */
366*91f16700Schasinglulu 	}
367*91f16700Schasinglulu 
368*91f16700Schasinglulu 	if (ip_rev == 0x50500) {
369*91f16700Schasinglulu 		popts->ap_en = 0;
370*91f16700Schasinglulu 	}
371*91f16700Schasinglulu 
372*91f16700Schasinglulu 	debug("ap_en %d\n", popts->ap_en);
373*91f16700Schasinglulu 
374*91f16700Schasinglulu 	/* BSTTOPRE precharge interval uses 1/4 of refint value. */
375*91f16700Schasinglulu 	popts->bstopre = picos_to_mclk(clk, pdimm->refresh_rate_ps) >> 2;
376*91f16700Schasinglulu 	popts->tfaw_ps = pdimm->tfaw_ps;
377*91f16700Schasinglulu 
378*91f16700Schasinglulu 	return 0;
379*91f16700Schasinglulu }
380*91f16700Schasinglulu 
381*91f16700Schasinglulu static void cal_intlv(const int num_ctlrs,
382*91f16700Schasinglulu 		      struct memctl_opt *popts,
383*91f16700Schasinglulu 		      struct ddr_conf *conf,
384*91f16700Schasinglulu 		      struct dimm_params *pdimm)
385*91f16700Schasinglulu {
386*91f16700Schasinglulu #ifdef NXP_DDR_INTLV_256B
387*91f16700Schasinglulu 	if (num_ctlrs == 2) {
388*91f16700Schasinglulu 		popts->ctlr_intlv = 1;
389*91f16700Schasinglulu 		popts->ctlr_intlv_mode = DDR_256B_INTLV;
390*91f16700Schasinglulu 	}
391*91f16700Schasinglulu #endif
392*91f16700Schasinglulu 	debug("ctlr_intlv %d\n", popts->ctlr_intlv);
393*91f16700Schasinglulu 	debug("ctlr_intlv_mode %d\n", popts->ctlr_intlv_mode);
394*91f16700Schasinglulu 
395*91f16700Schasinglulu 	popts->ba_intlv = auto_bank_intlv(conf->cs_in_use, pdimm);
396*91f16700Schasinglulu 	debug("ba_intlv 0x%x\n", popts->ba_intlv);
397*91f16700Schasinglulu }
398*91f16700Schasinglulu 
399*91f16700Schasinglulu static int update_burst_length(struct memctl_opt *popts)
400*91f16700Schasinglulu {
401*91f16700Schasinglulu 	/* Choose burst length. */
402*91f16700Schasinglulu 	if ((popts->data_bus_used == DDR_DBUS_32) ||
403*91f16700Schasinglulu 	    (popts->data_bus_used == DDR_DBUS_16)) {
404*91f16700Schasinglulu 		/* 32-bit or 16-bit bus */
405*91f16700Schasinglulu 		popts->otf_burst_chop_en = 0;
406*91f16700Schasinglulu 		popts->burst_length = DDR_BL8;
407*91f16700Schasinglulu 	} else if (popts->otf_burst_chop_en != 0) { /* on-the-fly burst chop */
408*91f16700Schasinglulu 		popts->burst_length = DDR_OTF;	/* on-the-fly BC4 and BL8 */
409*91f16700Schasinglulu 	} else {
410*91f16700Schasinglulu 		popts->burst_length = DDR_BL8;
411*91f16700Schasinglulu 	}
412*91f16700Schasinglulu 	debug("data_bus_used %d\n", popts->data_bus_used);
413*91f16700Schasinglulu 	debug("otf_burst_chop_en %d\n", popts->otf_burst_chop_en);
414*91f16700Schasinglulu 	debug("burst_length 0x%x\n", popts->burst_length);
415*91f16700Schasinglulu 	/*
416*91f16700Schasinglulu 	 * If a reduced data width is requested, but the SPD
417*91f16700Schasinglulu 	 * specifies a physically wider device, adjust the
418*91f16700Schasinglulu 	 * computed dimm capacities accordingly before
419*91f16700Schasinglulu 	 * assigning addresses.
420*91f16700Schasinglulu 	 * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit
421*91f16700Schasinglulu 	 */
422*91f16700Schasinglulu 	if (popts->data_bus_dimm > popts->data_bus_used) {
423*91f16700Schasinglulu 		ERROR("Data bus configuration error\n");
424*91f16700Schasinglulu 		return -EINVAL;
425*91f16700Schasinglulu 	}
426*91f16700Schasinglulu 	popts->dbw_cap_shift = popts->data_bus_used - popts->data_bus_dimm;
427*91f16700Schasinglulu 	debug("dbw_cap_shift %d\n", popts->dbw_cap_shift);
428*91f16700Schasinglulu 
429*91f16700Schasinglulu 	return 0;
430*91f16700Schasinglulu }
431*91f16700Schasinglulu 
432*91f16700Schasinglulu int cal_board_params(struct ddr_info *priv,
433*91f16700Schasinglulu 		     const struct board_timing *dimm,
434*91f16700Schasinglulu 		     int len)
435*91f16700Schasinglulu {
436*91f16700Schasinglulu 	const unsigned long speed = priv->clk / 1000000;
437*91f16700Schasinglulu 	const struct dimm_params *pdimm = &priv->dimm;
438*91f16700Schasinglulu 	struct memctl_opt *popts = &priv->opt;
439*91f16700Schasinglulu 	struct rc_timing const *prt = NULL;
440*91f16700Schasinglulu 	struct rc_timing const *chosen = NULL;
441*91f16700Schasinglulu 	int i;
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	for (i = 0; i < len; i++) {
444*91f16700Schasinglulu 		if (pdimm->rc == dimm[i].rc) {
445*91f16700Schasinglulu 			prt = dimm[i].p;
446*91f16700Schasinglulu 			break;
447*91f16700Schasinglulu 		}
448*91f16700Schasinglulu 	}
449*91f16700Schasinglulu 	if (prt == NULL) {
450*91f16700Schasinglulu 		ERROR("Board parameters no match.\n");
451*91f16700Schasinglulu 		return -EINVAL;
452*91f16700Schasinglulu 	}
453*91f16700Schasinglulu 	while (prt->speed_bin != 0) {
454*91f16700Schasinglulu 		if (speed <= prt->speed_bin) {
455*91f16700Schasinglulu 			chosen = prt;
456*91f16700Schasinglulu 			break;
457*91f16700Schasinglulu 		}
458*91f16700Schasinglulu 		prt++;
459*91f16700Schasinglulu 	}
460*91f16700Schasinglulu 	if (chosen == NULL) {
461*91f16700Schasinglulu 		ERROR("timing no match for speed %lu\n", speed);
462*91f16700Schasinglulu 		return -EINVAL;
463*91f16700Schasinglulu 	}
464*91f16700Schasinglulu 	popts->clk_adj = prt->clk_adj;
465*91f16700Schasinglulu 	popts->wrlvl_start = prt->wrlvl;
466*91f16700Schasinglulu 	popts->wrlvl_ctl_2 = (prt->wrlvl * 0x01010101 + dimm[i].add1) &
467*91f16700Schasinglulu 			     0xFFFFFFFF;
468*91f16700Schasinglulu 	popts->wrlvl_ctl_3 = (prt->wrlvl * 0x01010101 + dimm[i].add2) &
469*91f16700Schasinglulu 			     0xFFFFFFFF;
470*91f16700Schasinglulu 
471*91f16700Schasinglulu 	return 0;
472*91f16700Schasinglulu }
473*91f16700Schasinglulu 
474*91f16700Schasinglulu static int synthesize_ctlr(struct ddr_info *priv)
475*91f16700Schasinglulu {
476*91f16700Schasinglulu 	int ret;
477*91f16700Schasinglulu 
478*91f16700Schasinglulu 	ret = cal_odt(priv->clk,
479*91f16700Schasinglulu 		      &priv->opt,
480*91f16700Schasinglulu 		      &priv->conf,
481*91f16700Schasinglulu 		      &priv->dimm,
482*91f16700Schasinglulu 		      priv->dimm_on_ctlr);
483*91f16700Schasinglulu 	if (ret != 0) {
484*91f16700Schasinglulu 		return ret;
485*91f16700Schasinglulu 	}
486*91f16700Schasinglulu 
487*91f16700Schasinglulu 	ret = cal_opts(priv->clk,
488*91f16700Schasinglulu 		       &priv->opt,
489*91f16700Schasinglulu 		       &priv->conf,
490*91f16700Schasinglulu 		       &priv->dimm,
491*91f16700Schasinglulu 		       priv->dimm_on_ctlr,
492*91f16700Schasinglulu 		       priv->ip_rev);
493*91f16700Schasinglulu 
494*91f16700Schasinglulu 	if (ret != 0) {
495*91f16700Schasinglulu 		return ret;
496*91f16700Schasinglulu 	}
497*91f16700Schasinglulu 
498*91f16700Schasinglulu 	cal_intlv(priv->num_ctlrs, &priv->opt, &priv->conf, &priv->dimm);
499*91f16700Schasinglulu 	ret = ddr_board_options(priv);
500*91f16700Schasinglulu 	if (ret != 0) {
501*91f16700Schasinglulu 		ERROR("Failed matching board timing.\n");
502*91f16700Schasinglulu 	}
503*91f16700Schasinglulu 
504*91f16700Schasinglulu 	ret = update_burst_length(&priv->opt);
505*91f16700Schasinglulu 
506*91f16700Schasinglulu 	return ret;
507*91f16700Schasinglulu }
508*91f16700Schasinglulu 
509*91f16700Schasinglulu /* Return the bit mask of valid DIMMs found */
510*91f16700Schasinglulu static int parse_spd(struct ddr_info *priv)
511*91f16700Schasinglulu {
512*91f16700Schasinglulu 	struct ddr_conf *conf = &priv->conf;
513*91f16700Schasinglulu 	struct dimm_params *dimm = &priv->dimm;
514*91f16700Schasinglulu 	int j, valid_mask = 0;
515*91f16700Schasinglulu 
516*91f16700Schasinglulu #ifdef CONFIG_DDR_NODIMM
517*91f16700Schasinglulu 	valid_mask = ddr_get_ddr_params(dimm, conf);
518*91f16700Schasinglulu 	if (valid_mask < 0) {
519*91f16700Schasinglulu 		ERROR("DDR params error\n");
520*91f16700Schasinglulu 		return valid_mask;
521*91f16700Schasinglulu 	}
522*91f16700Schasinglulu #else
523*91f16700Schasinglulu 	const int *spd_addr = priv->spd_addr;
524*91f16700Schasinglulu 	const int num_ctlrs = priv->num_ctlrs;
525*91f16700Schasinglulu 	const int num_dimm = priv->dimm_on_ctlr;
526*91f16700Schasinglulu 	struct ddr4_spd spd[2];
527*91f16700Schasinglulu 	unsigned int spd_checksum[2];
528*91f16700Schasinglulu 	int addr_idx = 0;
529*91f16700Schasinglulu 	int spd_idx = 0;
530*91f16700Schasinglulu 	int ret, addr, i;
531*91f16700Schasinglulu 
532*91f16700Schasinglulu 	/* Scan all DIMMs */
533*91f16700Schasinglulu 	for (i = 0; i < num_ctlrs; i++) {
534*91f16700Schasinglulu 		debug("Controller %d\n", i);
535*91f16700Schasinglulu 		for (j = 0; j < num_dimm; j++, addr_idx++) {
536*91f16700Schasinglulu 			debug("DIMM %d\n", j);
537*91f16700Schasinglulu 			addr = spd_addr[addr_idx];
538*91f16700Schasinglulu 			if (addr == 0) {
539*91f16700Schasinglulu 				if (j == 0) {
540*91f16700Schasinglulu 					ERROR("First SPD addr wrong.\n");
541*91f16700Schasinglulu 					return -EINVAL;
542*91f16700Schasinglulu 				}
543*91f16700Schasinglulu 				continue;
544*91f16700Schasinglulu 			}
545*91f16700Schasinglulu 			debug("addr 0x%x\n", addr);
546*91f16700Schasinglulu 			ret = read_spd(addr, &spd[spd_idx],
547*91f16700Schasinglulu 				       sizeof(struct ddr4_spd));
548*91f16700Schasinglulu 			if (ret != 0) {	/* invalid */
549*91f16700Schasinglulu 				debug("Invalid SPD at address 0x%x\n", addr);
550*91f16700Schasinglulu 				continue;
551*91f16700Schasinglulu 			}
552*91f16700Schasinglulu 
553*91f16700Schasinglulu 			spd_checksum[spd_idx] =
554*91f16700Schasinglulu 				(spd[spd_idx].crc[1] << 24) |
555*91f16700Schasinglulu 				(spd[spd_idx].crc[0] << 16) |
556*91f16700Schasinglulu 				(spd[spd_idx].mod_section.uc[127] << 8) |
557*91f16700Schasinglulu 				(spd[spd_idx].mod_section.uc[126] << 0);
558*91f16700Schasinglulu 			debug("checksum 0x%x\n", spd_checksum[spd_idx]);
559*91f16700Schasinglulu 			if (spd_checksum[spd_idx] == 0) {
560*91f16700Schasinglulu 				debug("Bad checksum, ignored.\n");
561*91f16700Schasinglulu 				continue;
562*91f16700Schasinglulu 			}
563*91f16700Schasinglulu 			if (spd_idx == 0) {
564*91f16700Schasinglulu 				/* first valid SPD */
565*91f16700Schasinglulu 				ret = cal_dimm_params(&spd[0], dimm);
566*91f16700Schasinglulu 				if (ret != 0) {
567*91f16700Schasinglulu 					ERROR("SPD calculation error\n");
568*91f16700Schasinglulu 					return -EINVAL;
569*91f16700Schasinglulu 				}
570*91f16700Schasinglulu 			}
571*91f16700Schasinglulu 
572*91f16700Schasinglulu 			if (spd_idx != 0 && spd_checksum[0] !=
573*91f16700Schasinglulu 			    spd_checksum[spd_idx]) {
574*91f16700Schasinglulu 				ERROR("Not identical DIMMs.\n");
575*91f16700Schasinglulu 				return -EINVAL;
576*91f16700Schasinglulu 			}
577*91f16700Schasinglulu 			conf->dimm_in_use[j] = 1;
578*91f16700Schasinglulu 			valid_mask |= 1 << addr_idx;
579*91f16700Schasinglulu 			spd_idx = 1;
580*91f16700Schasinglulu 		}
581*91f16700Schasinglulu 		debug("done with controller %d\n", i);
582*91f16700Schasinglulu 	}
583*91f16700Schasinglulu 	switch (num_ctlrs) {
584*91f16700Schasinglulu 	case 1:
585*91f16700Schasinglulu 		if ((valid_mask & 0x1) == 0) {
586*91f16700Schasinglulu 			ERROR("First slot cannot be empty.\n");
587*91f16700Schasinglulu 			return -EINVAL;
588*91f16700Schasinglulu 		}
589*91f16700Schasinglulu 		break;
590*91f16700Schasinglulu 	case 2:
591*91f16700Schasinglulu 		switch (num_dimm) {
592*91f16700Schasinglulu 		case 1:
593*91f16700Schasinglulu 			if (valid_mask == 0) {
594*91f16700Schasinglulu 				ERROR("Both slot empty\n");
595*91f16700Schasinglulu 				return -EINVAL;
596*91f16700Schasinglulu 			}
597*91f16700Schasinglulu 			break;
598*91f16700Schasinglulu 		case 2:
599*91f16700Schasinglulu 			if (valid_mask != 0x5 &&
600*91f16700Schasinglulu 			    valid_mask != 0xf &&
601*91f16700Schasinglulu 			    (valid_mask & 0x7) != 0x4 &&
602*91f16700Schasinglulu 			    (valid_mask & 0xd) != 0x1) {
603*91f16700Schasinglulu 				ERROR("Invalid DIMM combination.\n");
604*91f16700Schasinglulu 				return -EINVAL;
605*91f16700Schasinglulu 			}
606*91f16700Schasinglulu 			break;
607*91f16700Schasinglulu 		default:
608*91f16700Schasinglulu 			ERROR("Invalid number of DIMMs.\n");
609*91f16700Schasinglulu 			return -EINVAL;
610*91f16700Schasinglulu 		}
611*91f16700Schasinglulu 		break;
612*91f16700Schasinglulu 	default:
613*91f16700Schasinglulu 		ERROR("Invalid number of controllers.\n");
614*91f16700Schasinglulu 		return -EINVAL;
615*91f16700Schasinglulu 	}
616*91f16700Schasinglulu 	/* now we have valid and identical DIMMs on controllers */
617*91f16700Schasinglulu #endif	/* CONFIG_DDR_NODIMM */
618*91f16700Schasinglulu 
619*91f16700Schasinglulu 	debug("cal cs\n");
620*91f16700Schasinglulu 	conf->cs_in_use = 0;
621*91f16700Schasinglulu 	for (j = 0; j < DDRC_NUM_DIMM; j++) {
622*91f16700Schasinglulu 		if (conf->dimm_in_use[j] == 0) {
623*91f16700Schasinglulu 			continue;
624*91f16700Schasinglulu 		}
625*91f16700Schasinglulu 		switch (dimm->n_ranks) {
626*91f16700Schasinglulu 		case 4:
627*91f16700Schasinglulu 			ERROR("Quad-rank DIMM not supported\n");
628*91f16700Schasinglulu 			return -EINVAL;
629*91f16700Schasinglulu 		case 2:
630*91f16700Schasinglulu 			conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT);
631*91f16700Schasinglulu 			conf->cs_in_use |= conf->cs_on_dimm[j];
632*91f16700Schasinglulu 			break;
633*91f16700Schasinglulu 		case 1:
634*91f16700Schasinglulu 			conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT);
635*91f16700Schasinglulu 			conf->cs_in_use |= conf->cs_on_dimm[j];
636*91f16700Schasinglulu 			break;
637*91f16700Schasinglulu 		default:
638*91f16700Schasinglulu 			ERROR("SPD error with n_ranks\n");
639*91f16700Schasinglulu 			return -EINVAL;
640*91f16700Schasinglulu 		}
641*91f16700Schasinglulu 		debug("cs_in_use = %x\n", conf->cs_in_use);
642*91f16700Schasinglulu 		debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]);
643*91f16700Schasinglulu 	}
644*91f16700Schasinglulu #ifndef CONFIG_DDR_NODIMM
645*91f16700Schasinglulu 	if (priv->dimm.rdimm != 0) {
646*91f16700Schasinglulu 		NOTICE("RDIMM %s\n", priv->dimm.mpart);
647*91f16700Schasinglulu 	} else {
648*91f16700Schasinglulu 		NOTICE("UDIMM %s\n", priv->dimm.mpart);
649*91f16700Schasinglulu 	}
650*91f16700Schasinglulu #else
651*91f16700Schasinglulu 	NOTICE("%s\n", priv->dimm.mpart);
652*91f16700Schasinglulu #endif
653*91f16700Schasinglulu 
654*91f16700Schasinglulu 	return valid_mask;
655*91f16700Schasinglulu }
656*91f16700Schasinglulu 
657*91f16700Schasinglulu static unsigned long long assign_intlv_addr(
658*91f16700Schasinglulu 	const struct dimm_params *pdimm,
659*91f16700Schasinglulu 	const struct memctl_opt *opt,
660*91f16700Schasinglulu 	struct ddr_conf *conf,
661*91f16700Schasinglulu 	const unsigned long long current_mem_base)
662*91f16700Schasinglulu {
663*91f16700Schasinglulu 	int i;
664*91f16700Schasinglulu 	int ctlr_density_mul = 0;
665*91f16700Schasinglulu 	const unsigned long long rank_density = pdimm->rank_density >>
666*91f16700Schasinglulu 						opt->dbw_cap_shift;
667*91f16700Schasinglulu 	unsigned long long total_ctlr_mem;
668*91f16700Schasinglulu 
669*91f16700Schasinglulu 	debug("rank density 0x%llx\n", rank_density);
670*91f16700Schasinglulu 	switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) {
671*91f16700Schasinglulu 	case DDR_BA_INTLV_CS0123:
672*91f16700Schasinglulu 		ctlr_density_mul = 4;
673*91f16700Schasinglulu 		break;
674*91f16700Schasinglulu 	case DDR_BA_INTLV_CS01:
675*91f16700Schasinglulu 		ctlr_density_mul = 2;
676*91f16700Schasinglulu 		break;
677*91f16700Schasinglulu 	default:
678*91f16700Schasinglulu 		ctlr_density_mul = 1;
679*91f16700Schasinglulu 		break;
680*91f16700Schasinglulu 	}
681*91f16700Schasinglulu 	debug("ctlr density mul %d\n", ctlr_density_mul);
682*91f16700Schasinglulu 	switch (opt->ctlr_intlv_mode) {
683*91f16700Schasinglulu 	case DDR_256B_INTLV:
684*91f16700Schasinglulu 		total_ctlr_mem = 2 * ctlr_density_mul * rank_density;
685*91f16700Schasinglulu 		break;
686*91f16700Schasinglulu 	default:
687*91f16700Schasinglulu 		ERROR("Unknown interleaving mode");
688*91f16700Schasinglulu 		return 0;
689*91f16700Schasinglulu 	}
690*91f16700Schasinglulu 	conf->base_addr = current_mem_base;
691*91f16700Schasinglulu 	conf->total_mem = total_ctlr_mem;
692*91f16700Schasinglulu 
693*91f16700Schasinglulu 	/* overwrite cs_in_use bitmask with controller interleaving */
694*91f16700Schasinglulu 	conf->cs_in_use = (1 << ctlr_density_mul) - 1;
695*91f16700Schasinglulu 	debug("Overwrite cs_in_use as %x\n", conf->cs_in_use);
696*91f16700Schasinglulu 
697*91f16700Schasinglulu 	/* Fill addr with each cs in use */
698*91f16700Schasinglulu 	for (i = 0; i < ctlr_density_mul; i++) {
699*91f16700Schasinglulu 		conf->cs_base_addr[i] = current_mem_base;
700*91f16700Schasinglulu 		conf->cs_size[i] = total_ctlr_mem;
701*91f16700Schasinglulu 		debug("CS %d\n", i);
702*91f16700Schasinglulu 		debug("    base_addr 0x%llx\n", conf->cs_base_addr[i]);
703*91f16700Schasinglulu 		debug("    size 0x%llx\n", conf->cs_size[i]);
704*91f16700Schasinglulu 	}
705*91f16700Schasinglulu 
706*91f16700Schasinglulu 	return total_ctlr_mem;
707*91f16700Schasinglulu }
708*91f16700Schasinglulu 
709*91f16700Schasinglulu static unsigned long long assign_non_intlv_addr(
710*91f16700Schasinglulu 	const struct dimm_params *pdimm,
711*91f16700Schasinglulu 	const struct memctl_opt *opt,
712*91f16700Schasinglulu 	struct ddr_conf *conf,
713*91f16700Schasinglulu 	unsigned long long current_mem_base)
714*91f16700Schasinglulu {
715*91f16700Schasinglulu 	int i;
716*91f16700Schasinglulu 	const unsigned long long rank_density = pdimm->rank_density >>
717*91f16700Schasinglulu 						opt->dbw_cap_shift;
718*91f16700Schasinglulu 	unsigned long long total_ctlr_mem = 0ULL;
719*91f16700Schasinglulu 
720*91f16700Schasinglulu 	debug("rank density 0x%llx\n", rank_density);
721*91f16700Schasinglulu 	conf->base_addr = current_mem_base;
722*91f16700Schasinglulu 
723*91f16700Schasinglulu 	/* assign each cs */
724*91f16700Schasinglulu 	switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) {
725*91f16700Schasinglulu 	case DDR_BA_INTLV_CS0123:
726*91f16700Schasinglulu 		for (i = 0; i < DDRC_NUM_CS; i++) {
727*91f16700Schasinglulu 			conf->cs_base_addr[i] = current_mem_base;
728*91f16700Schasinglulu 			conf->cs_size[i] = rank_density << 2;
729*91f16700Schasinglulu 			total_ctlr_mem += rank_density;
730*91f16700Schasinglulu 		}
731*91f16700Schasinglulu 		break;
732*91f16700Schasinglulu 	case DDR_BA_INTLV_CS01:
733*91f16700Schasinglulu 		for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && i < 2; i++) {
734*91f16700Schasinglulu 			conf->cs_base_addr[i] = current_mem_base;
735*91f16700Schasinglulu 			conf->cs_size[i] = rank_density << 1;
736*91f16700Schasinglulu 			total_ctlr_mem += rank_density;
737*91f16700Schasinglulu 		}
738*91f16700Schasinglulu 		current_mem_base += total_ctlr_mem;
739*91f16700Schasinglulu 		for (; ((conf->cs_in_use & (1 << i)) != 0) && i < DDRC_NUM_CS;
740*91f16700Schasinglulu 		     i++) {
741*91f16700Schasinglulu 			conf->cs_base_addr[i] = current_mem_base;
742*91f16700Schasinglulu 			conf->cs_size[i] = rank_density;
743*91f16700Schasinglulu 			total_ctlr_mem += rank_density;
744*91f16700Schasinglulu 			current_mem_base += rank_density;
745*91f16700Schasinglulu 		}
746*91f16700Schasinglulu 		break;
747*91f16700Schasinglulu 	case DDR_BA_NONE:
748*91f16700Schasinglulu 		for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) &&
749*91f16700Schasinglulu 			     (i < DDRC_NUM_CS); i++) {
750*91f16700Schasinglulu 			conf->cs_base_addr[i] = current_mem_base;
751*91f16700Schasinglulu 			conf->cs_size[i] = rank_density;
752*91f16700Schasinglulu 			current_mem_base += rank_density;
753*91f16700Schasinglulu 			total_ctlr_mem += rank_density;
754*91f16700Schasinglulu 		}
755*91f16700Schasinglulu 		break;
756*91f16700Schasinglulu 	default:
757*91f16700Schasinglulu 		ERROR("Unsupported bank interleaving\n");
758*91f16700Schasinglulu 		return 0;
759*91f16700Schasinglulu 	}
760*91f16700Schasinglulu 	for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) &&
761*91f16700Schasinglulu 		     (i < DDRC_NUM_CS); i++) {
762*91f16700Schasinglulu 		debug("CS %d\n", i);
763*91f16700Schasinglulu 		debug("    base_addr 0x%llx\n", conf->cs_base_addr[i]);
764*91f16700Schasinglulu 		debug("    size 0x%llx\n", conf->cs_size[i]);
765*91f16700Schasinglulu 	}
766*91f16700Schasinglulu 
767*91f16700Schasinglulu 	return total_ctlr_mem;
768*91f16700Schasinglulu }
769*91f16700Schasinglulu 
770*91f16700Schasinglulu unsigned long long assign_addresses(struct ddr_info *priv)
771*91f16700Schasinglulu 		   __attribute__ ((weak));
772*91f16700Schasinglulu 
773*91f16700Schasinglulu unsigned long long assign_addresses(struct ddr_info *priv)
774*91f16700Schasinglulu {
775*91f16700Schasinglulu 	struct memctl_opt *opt = &priv->opt;
776*91f16700Schasinglulu 	const struct dimm_params *dimm = &priv->dimm;
777*91f16700Schasinglulu 	struct ddr_conf *conf = &priv->conf;
778*91f16700Schasinglulu 	unsigned long long current_mem_base = priv->mem_base;
779*91f16700Schasinglulu 	unsigned long long total_mem;
780*91f16700Schasinglulu 
781*91f16700Schasinglulu 	total_mem = 0ULL;
782*91f16700Schasinglulu 	debug("ctlr_intlv %d\n", opt->ctlr_intlv);
783*91f16700Schasinglulu 	if (opt->ctlr_intlv != 0) {
784*91f16700Schasinglulu 		total_mem = assign_intlv_addr(dimm, opt, conf,
785*91f16700Schasinglulu 					      current_mem_base);
786*91f16700Schasinglulu 	} else {
787*91f16700Schasinglulu 		/*
788*91f16700Schasinglulu 		 * Simple linear assignment if memory controllers are not
789*91f16700Schasinglulu 		 * interleaved. This is only valid for SoCs with single DDRC.
790*91f16700Schasinglulu 		 */
791*91f16700Schasinglulu 		total_mem = assign_non_intlv_addr(dimm, opt, conf,
792*91f16700Schasinglulu 						  current_mem_base);
793*91f16700Schasinglulu 	}
794*91f16700Schasinglulu 	conf->total_mem = total_mem;
795*91f16700Schasinglulu 	debug("base 0x%llx\n", current_mem_base);
796*91f16700Schasinglulu 	debug("Total mem by assignment is 0x%llx\n", total_mem);
797*91f16700Schasinglulu 
798*91f16700Schasinglulu 	return total_mem;
799*91f16700Schasinglulu }
800*91f16700Schasinglulu 
801*91f16700Schasinglulu static int cal_ddrc_regs(struct ddr_info *priv)
802*91f16700Schasinglulu {
803*91f16700Schasinglulu 	int ret;
804*91f16700Schasinglulu 
805*91f16700Schasinglulu 	ret = compute_ddrc(priv->clk,
806*91f16700Schasinglulu 			   &priv->opt,
807*91f16700Schasinglulu 			   &priv->conf,
808*91f16700Schasinglulu 			   &priv->ddr_reg,
809*91f16700Schasinglulu 			   &priv->dimm,
810*91f16700Schasinglulu 			   priv->ip_rev);
811*91f16700Schasinglulu 	if (ret != 0) {
812*91f16700Schasinglulu 		ERROR("Calculating DDR registers failed\n");
813*91f16700Schasinglulu 	}
814*91f16700Schasinglulu 
815*91f16700Schasinglulu 	return ret;
816*91f16700Schasinglulu }
817*91f16700Schasinglulu 
818*91f16700Schasinglulu #endif /* CONFIG_STATIC_DDR */
819*91f16700Schasinglulu 
820*91f16700Schasinglulu static int write_ddrc_regs(struct ddr_info *priv)
821*91f16700Schasinglulu {
822*91f16700Schasinglulu 	int i;
823*91f16700Schasinglulu 	int ret;
824*91f16700Schasinglulu 
825*91f16700Schasinglulu 	for (i = 0; i < priv->num_ctlrs; i++) {
826*91f16700Schasinglulu 		ret = ddrc_set_regs(priv->clk, &priv->ddr_reg, priv->ddr[i], 0);
827*91f16700Schasinglulu 		if (ret != 0) {
828*91f16700Schasinglulu 			ERROR("Writing DDR register(s) failed\n");
829*91f16700Schasinglulu 			return ret;
830*91f16700Schasinglulu 		}
831*91f16700Schasinglulu 	}
832*91f16700Schasinglulu 
833*91f16700Schasinglulu 	return 0;
834*91f16700Schasinglulu }
835*91f16700Schasinglulu 
836*91f16700Schasinglulu long long dram_init(struct ddr_info *priv
837*91f16700Schasinglulu #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
838*91f16700Schasinglulu 		    , uintptr_t nxp_ccn_hn_f0_addr
839*91f16700Schasinglulu #endif
840*91f16700Schasinglulu 		)
841*91f16700Schasinglulu {
842*91f16700Schasinglulu 	uint64_t time __unused;
843*91f16700Schasinglulu 	long long dram_size;
844*91f16700Schasinglulu 	int ret;
845*91f16700Schasinglulu 	const uint64_t time_base = get_timer_val(0);
846*91f16700Schasinglulu 	unsigned int ip_rev = get_ddrc_version(priv->ddr[0]);
847*91f16700Schasinglulu 
848*91f16700Schasinglulu 	int valid_spd_mask __unused;
849*91f16700Schasinglulu 	int scratch = 0x0;
850*91f16700Schasinglulu 
851*91f16700Schasinglulu 	priv->ip_rev = ip_rev;
852*91f16700Schasinglulu 
853*91f16700Schasinglulu #ifndef CONFIG_STATIC_DDR
854*91f16700Schasinglulu 	INFO("time base %" PRIu64 " ms\n", time_base);
855*91f16700Schasinglulu 	debug("Parse DIMM SPD(s)\n");
856*91f16700Schasinglulu 	valid_spd_mask = parse_spd(priv);
857*91f16700Schasinglulu 
858*91f16700Schasinglulu 	if (valid_spd_mask < 0) {
859*91f16700Schasinglulu 		ERROR("Parsing DIMM Error\n");
860*91f16700Schasinglulu 		return valid_spd_mask;
861*91f16700Schasinglulu 	}
862*91f16700Schasinglulu 
863*91f16700Schasinglulu #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
864*91f16700Schasinglulu 	if (priv->num_ctlrs == 2 || priv->num_ctlrs == 1) {
865*91f16700Schasinglulu 		ret = disable_unused_ddrc(priv, valid_spd_mask,
866*91f16700Schasinglulu 					  nxp_ccn_hn_f0_addr);
867*91f16700Schasinglulu 		if (ret != 0) {
868*91f16700Schasinglulu 			return ret;
869*91f16700Schasinglulu 		}
870*91f16700Schasinglulu 	}
871*91f16700Schasinglulu #endif
872*91f16700Schasinglulu 
873*91f16700Schasinglulu 	time = get_timer_val(time_base);
874*91f16700Schasinglulu 	INFO("Time after parsing SPD %" PRIu64 " ms\n", time);
875*91f16700Schasinglulu 	debug("Synthesize configurations\n");
876*91f16700Schasinglulu 	ret = synthesize_ctlr(priv);
877*91f16700Schasinglulu 	if (ret != 0) {
878*91f16700Schasinglulu 		ERROR("Synthesize config error\n");
879*91f16700Schasinglulu 		return ret;
880*91f16700Schasinglulu 	}
881*91f16700Schasinglulu 
882*91f16700Schasinglulu 	debug("Assign binding addresses\n");
883*91f16700Schasinglulu 	dram_size = assign_addresses(priv);
884*91f16700Schasinglulu 	if (dram_size == 0) {
885*91f16700Schasinglulu 		ERROR("Assigning address error\n");
886*91f16700Schasinglulu 		return -EINVAL;
887*91f16700Schasinglulu 	}
888*91f16700Schasinglulu 
889*91f16700Schasinglulu 	debug("Calculate controller registers\n");
890*91f16700Schasinglulu 	ret = cal_ddrc_regs(priv);
891*91f16700Schasinglulu 	if (ret != 0) {
892*91f16700Schasinglulu 		ERROR("Calculate register error\n");
893*91f16700Schasinglulu 		return ret;
894*91f16700Schasinglulu 	}
895*91f16700Schasinglulu 
896*91f16700Schasinglulu 	ret = compute_ddr_phy(priv);
897*91f16700Schasinglulu 	if (ret != 0)
898*91f16700Schasinglulu 		ERROR("Calculating DDR PHY registers failed.\n");
899*91f16700Schasinglulu 
900*91f16700Schasinglulu #else
901*91f16700Schasinglulu 	dram_size = board_static_ddr(priv);
902*91f16700Schasinglulu 	if (dram_size == 0) {
903*91f16700Schasinglulu 		ERROR("Error getting static DDR settings.\n");
904*91f16700Schasinglulu 		return -EINVAL;
905*91f16700Schasinglulu 	}
906*91f16700Schasinglulu #endif
907*91f16700Schasinglulu 
908*91f16700Schasinglulu 	if (priv->warm_boot_flag == DDR_WARM_BOOT) {
909*91f16700Schasinglulu 		scratch = (priv->ddr_reg).sdram_cfg[1];
910*91f16700Schasinglulu 		scratch = scratch & ~(SDRAM_CFG2_D_INIT);
911*91f16700Schasinglulu 		priv->ddr_reg.sdram_cfg[1] = scratch;
912*91f16700Schasinglulu 	}
913*91f16700Schasinglulu 
914*91f16700Schasinglulu 	time = get_timer_val(time_base);
915*91f16700Schasinglulu 	INFO("Time before programming controller %" PRIu64 " ms\n", time);
916*91f16700Schasinglulu 	debug("Program controller registers\n");
917*91f16700Schasinglulu 	ret = write_ddrc_regs(priv);
918*91f16700Schasinglulu 	if (ret != 0) {
919*91f16700Schasinglulu 		ERROR("Programming DDRC error\n");
920*91f16700Schasinglulu 		return ret;
921*91f16700Schasinglulu 	}
922*91f16700Schasinglulu 
923*91f16700Schasinglulu 	puts("");
924*91f16700Schasinglulu 	NOTICE("%lld GB ", dram_size >> 30);
925*91f16700Schasinglulu 	print_ddr_info(priv->ddr[0]);
926*91f16700Schasinglulu 
927*91f16700Schasinglulu 	time = get_timer_val(time_base);
928*91f16700Schasinglulu 	INFO("Time used by DDR driver %" PRIu64 " ms\n", time);
929*91f16700Schasinglulu 
930*91f16700Schasinglulu 	return dram_size;
931*91f16700Schasinglulu }
932