xref: /rk3399_rockchip-uboot/drivers/ddr/fsl/interactive.c (revision 5614e71b4956c579cd4419b958b33fa6316eaa92)
1*5614e71bSYork Sun /*
2*5614e71bSYork Sun  * Copyright 2010-2012 Freescale Semiconductor, Inc.
3*5614e71bSYork Sun  *
4*5614e71bSYork Sun  * SPDX-License-Identifier:	GPL-2.0+
5*5614e71bSYork Sun  */
6*5614e71bSYork Sun 
7*5614e71bSYork Sun /*
8*5614e71bSYork Sun  * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
9*5614e71bSYork Sun  * Based on code from spd_sdram.c
10*5614e71bSYork Sun  * Author: James Yang [at freescale.com]
11*5614e71bSYork Sun  *         York Sun [at freescale.com]
12*5614e71bSYork Sun  */
13*5614e71bSYork Sun 
14*5614e71bSYork Sun #include <common.h>
15*5614e71bSYork Sun #include <linux/ctype.h>
16*5614e71bSYork Sun #include <asm/types.h>
17*5614e71bSYork Sun #include <asm/io.h>
18*5614e71bSYork Sun 
19*5614e71bSYork Sun #include <fsl_ddr_sdram.h>
20*5614e71bSYork Sun #include <fsl_ddr.h>
21*5614e71bSYork Sun 
22*5614e71bSYork Sun /* Option parameter Structures */
23*5614e71bSYork Sun struct options_string {
24*5614e71bSYork Sun 	const char *option_name;
25*5614e71bSYork Sun 	size_t offset;
26*5614e71bSYork Sun 	unsigned int size;
27*5614e71bSYork Sun 	const char printhex;
28*5614e71bSYork Sun };
29*5614e71bSYork Sun 
30*5614e71bSYork Sun static unsigned int picos_to_mhz(unsigned int picos)
31*5614e71bSYork Sun {
32*5614e71bSYork Sun 	return 1000000 / picos;
33*5614e71bSYork Sun }
34*5614e71bSYork Sun 
35*5614e71bSYork Sun static void print_option_table(const struct options_string *table,
36*5614e71bSYork Sun 			 int table_size,
37*5614e71bSYork Sun 			 const void *base)
38*5614e71bSYork Sun {
39*5614e71bSYork Sun 	unsigned int i;
40*5614e71bSYork Sun 	unsigned int *ptr;
41*5614e71bSYork Sun 	unsigned long long *ptr_l;
42*5614e71bSYork Sun 
43*5614e71bSYork Sun 	for (i = 0; i < table_size; i++) {
44*5614e71bSYork Sun 		switch (table[i].size) {
45*5614e71bSYork Sun 		case 4:
46*5614e71bSYork Sun 			ptr = (unsigned int *) (base + table[i].offset);
47*5614e71bSYork Sun 			if (table[i].printhex) {
48*5614e71bSYork Sun 				printf("%s = 0x%08X\n",
49*5614e71bSYork Sun 					table[i].option_name, *ptr);
50*5614e71bSYork Sun 			} else {
51*5614e71bSYork Sun 				printf("%s = %u\n",
52*5614e71bSYork Sun 					table[i].option_name, *ptr);
53*5614e71bSYork Sun 			}
54*5614e71bSYork Sun 			break;
55*5614e71bSYork Sun 		case 8:
56*5614e71bSYork Sun 			ptr_l = (unsigned long long *) (base + table[i].offset);
57*5614e71bSYork Sun 			printf("%s = %llu\n",
58*5614e71bSYork Sun 				table[i].option_name, *ptr_l);
59*5614e71bSYork Sun 			break;
60*5614e71bSYork Sun 		default:
61*5614e71bSYork Sun 			printf("Unrecognized size!\n");
62*5614e71bSYork Sun 			break;
63*5614e71bSYork Sun 		}
64*5614e71bSYork Sun 	}
65*5614e71bSYork Sun }
66*5614e71bSYork Sun 
67*5614e71bSYork Sun static int handle_option_table(const struct options_string *table,
68*5614e71bSYork Sun 			 int table_size,
69*5614e71bSYork Sun 			 void *base,
70*5614e71bSYork Sun 			 const char *opt,
71*5614e71bSYork Sun 			 const char *val)
72*5614e71bSYork Sun {
73*5614e71bSYork Sun 	unsigned int i;
74*5614e71bSYork Sun 	unsigned int value, *ptr;
75*5614e71bSYork Sun 	unsigned long long value_l, *ptr_l;
76*5614e71bSYork Sun 
77*5614e71bSYork Sun 	for (i = 0; i < table_size; i++) {
78*5614e71bSYork Sun 		if (strcmp(table[i].option_name, opt) != 0)
79*5614e71bSYork Sun 			continue;
80*5614e71bSYork Sun 		switch (table[i].size) {
81*5614e71bSYork Sun 		case 4:
82*5614e71bSYork Sun 			value = simple_strtoul(val, NULL, 0);
83*5614e71bSYork Sun 			ptr = base + table[i].offset;
84*5614e71bSYork Sun 			*ptr = value;
85*5614e71bSYork Sun 			break;
86*5614e71bSYork Sun 		case 8:
87*5614e71bSYork Sun 			value_l = simple_strtoull(val, NULL, 0);
88*5614e71bSYork Sun 			ptr_l = base + table[i].offset;
89*5614e71bSYork Sun 			*ptr_l = value_l;
90*5614e71bSYork Sun 			break;
91*5614e71bSYork Sun 		default:
92*5614e71bSYork Sun 			printf("Unrecognized size!\n");
93*5614e71bSYork Sun 			break;
94*5614e71bSYork Sun 		}
95*5614e71bSYork Sun 		return 1;
96*5614e71bSYork Sun 	}
97*5614e71bSYork Sun 
98*5614e71bSYork Sun 	return 0;
99*5614e71bSYork Sun }
100*5614e71bSYork Sun 
101*5614e71bSYork Sun static void fsl_ddr_generic_edit(void *pdata,
102*5614e71bSYork Sun 			   void *pend,
103*5614e71bSYork Sun 			   unsigned int element_size,
104*5614e71bSYork Sun 			   unsigned int element_num,
105*5614e71bSYork Sun 			   unsigned int value)
106*5614e71bSYork Sun {
107*5614e71bSYork Sun 	char *pcdata = (char *)pdata;		/* BIG ENDIAN ONLY */
108*5614e71bSYork Sun 
109*5614e71bSYork Sun 	pcdata += element_num * element_size;
110*5614e71bSYork Sun 	if ((pcdata + element_size) > (char *) pend) {
111*5614e71bSYork Sun 		printf("trying to write past end of data\n");
112*5614e71bSYork Sun 		return;
113*5614e71bSYork Sun 	}
114*5614e71bSYork Sun 
115*5614e71bSYork Sun 	switch (element_size) {
116*5614e71bSYork Sun 	case 1:
117*5614e71bSYork Sun 		__raw_writeb(value, pcdata);
118*5614e71bSYork Sun 		break;
119*5614e71bSYork Sun 	case 2:
120*5614e71bSYork Sun 		__raw_writew(value, pcdata);
121*5614e71bSYork Sun 		break;
122*5614e71bSYork Sun 	case 4:
123*5614e71bSYork Sun 		__raw_writel(value, pcdata);
124*5614e71bSYork Sun 		break;
125*5614e71bSYork Sun 	default:
126*5614e71bSYork Sun 		printf("unexpected element size %u\n", element_size);
127*5614e71bSYork Sun 		break;
128*5614e71bSYork Sun 	}
129*5614e71bSYork Sun }
130*5614e71bSYork Sun 
131*5614e71bSYork Sun static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
132*5614e71bSYork Sun 		       unsigned int ctrl_num,
133*5614e71bSYork Sun 		       unsigned int dimm_num,
134*5614e71bSYork Sun 		       unsigned int element_num,
135*5614e71bSYork Sun 		       unsigned int value)
136*5614e71bSYork Sun {
137*5614e71bSYork Sun 	generic_spd_eeprom_t *pspd;
138*5614e71bSYork Sun 
139*5614e71bSYork Sun 	pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
140*5614e71bSYork Sun 	fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value);
141*5614e71bSYork Sun }
142*5614e71bSYork Sun 
143*5614e71bSYork Sun #define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \
144*5614e71bSYork Sun 	sizeof((common_timing_params_t *)0)->x, 0}
145*5614e71bSYork Sun 
146*5614e71bSYork Sun static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
147*5614e71bSYork Sun 					unsigned int ctrl_num,
148*5614e71bSYork Sun 					const char *optname_str,
149*5614e71bSYork Sun 					const char *value_str)
150*5614e71bSYork Sun {
151*5614e71bSYork Sun 	common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];
152*5614e71bSYork Sun 
153*5614e71bSYork Sun 	static const struct options_string options[] = {
154*5614e71bSYork Sun 		COMMON_TIMING(tckmin_x_ps),
155*5614e71bSYork Sun 		COMMON_TIMING(tckmax_ps),
156*5614e71bSYork Sun 		COMMON_TIMING(tckmax_max_ps),
157*5614e71bSYork Sun 		COMMON_TIMING(trcd_ps),
158*5614e71bSYork Sun 		COMMON_TIMING(trp_ps),
159*5614e71bSYork Sun 		COMMON_TIMING(tras_ps),
160*5614e71bSYork Sun 		COMMON_TIMING(twr_ps),
161*5614e71bSYork Sun 		COMMON_TIMING(twtr_ps),
162*5614e71bSYork Sun 		COMMON_TIMING(trfc_ps),
163*5614e71bSYork Sun 		COMMON_TIMING(trrd_ps),
164*5614e71bSYork Sun 		COMMON_TIMING(trc_ps),
165*5614e71bSYork Sun 		COMMON_TIMING(refresh_rate_ps),
166*5614e71bSYork Sun 		COMMON_TIMING(tis_ps),
167*5614e71bSYork Sun 		COMMON_TIMING(tih_ps),
168*5614e71bSYork Sun 		COMMON_TIMING(tds_ps),
169*5614e71bSYork Sun 		COMMON_TIMING(tdh_ps),
170*5614e71bSYork Sun 		COMMON_TIMING(trtp_ps),
171*5614e71bSYork Sun 		COMMON_TIMING(tdqsq_max_ps),
172*5614e71bSYork Sun 		COMMON_TIMING(tqhs_ps),
173*5614e71bSYork Sun 		COMMON_TIMING(ndimms_present),
174*5614e71bSYork Sun 		COMMON_TIMING(lowest_common_SPD_caslat),
175*5614e71bSYork Sun 		COMMON_TIMING(highest_common_derated_caslat),
176*5614e71bSYork Sun 		COMMON_TIMING(additive_latency),
177*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_burst_lengths_bitmask),
178*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_registered),
179*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_unbuffered),
180*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_ecc_capable),
181*5614e71bSYork Sun 		COMMON_TIMING(total_mem),
182*5614e71bSYork Sun 		COMMON_TIMING(base_address),
183*5614e71bSYork Sun 	};
184*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
185*5614e71bSYork Sun 
186*5614e71bSYork Sun 	if (handle_option_table(options, n_opts, p, optname_str, value_str))
187*5614e71bSYork Sun 		return;
188*5614e71bSYork Sun 
189*5614e71bSYork Sun 	printf("Error: couldn't find option string %s\n", optname_str);
190*5614e71bSYork Sun }
191*5614e71bSYork Sun 
192*5614e71bSYork Sun #define DIMM_PARM(x) {#x, offsetof(dimm_params_t, x), \
193*5614e71bSYork Sun 	sizeof((dimm_params_t *)0)->x, 0}
194*5614e71bSYork Sun 
195*5614e71bSYork Sun static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
196*5614e71bSYork Sun 				   unsigned int ctrl_num,
197*5614e71bSYork Sun 				   unsigned int dimm_num,
198*5614e71bSYork Sun 				   const char *optname_str,
199*5614e71bSYork Sun 				   const char *value_str)
200*5614e71bSYork Sun {
201*5614e71bSYork Sun 	dimm_params_t *p = &(pinfo->dimm_params[ctrl_num][dimm_num]);
202*5614e71bSYork Sun 
203*5614e71bSYork Sun 	static const struct options_string options[] = {
204*5614e71bSYork Sun 		DIMM_PARM(n_ranks),
205*5614e71bSYork Sun 		DIMM_PARM(data_width),
206*5614e71bSYork Sun 		DIMM_PARM(primary_sdram_width),
207*5614e71bSYork Sun 		DIMM_PARM(ec_sdram_width),
208*5614e71bSYork Sun 		DIMM_PARM(registered_dimm),
209*5614e71bSYork Sun 		DIMM_PARM(device_width),
210*5614e71bSYork Sun 
211*5614e71bSYork Sun 		DIMM_PARM(n_row_addr),
212*5614e71bSYork Sun 		DIMM_PARM(n_col_addr),
213*5614e71bSYork Sun 		DIMM_PARM(edc_config),
214*5614e71bSYork Sun 		DIMM_PARM(n_banks_per_sdram_device),
215*5614e71bSYork Sun 		DIMM_PARM(burst_lengths_bitmask),
216*5614e71bSYork Sun 		DIMM_PARM(row_density),
217*5614e71bSYork Sun 
218*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_ps),
219*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_minus_1_ps),
220*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_minus_2_ps),
221*5614e71bSYork Sun 		DIMM_PARM(tckmax_ps),
222*5614e71bSYork Sun 
223*5614e71bSYork Sun 		DIMM_PARM(caslat_x),
224*5614e71bSYork Sun 		DIMM_PARM(caslat_x_minus_1),
225*5614e71bSYork Sun 		DIMM_PARM(caslat_x_minus_2),
226*5614e71bSYork Sun 
227*5614e71bSYork Sun 		DIMM_PARM(caslat_lowest_derated),
228*5614e71bSYork Sun 
229*5614e71bSYork Sun 		DIMM_PARM(trcd_ps),
230*5614e71bSYork Sun 		DIMM_PARM(trp_ps),
231*5614e71bSYork Sun 		DIMM_PARM(tras_ps),
232*5614e71bSYork Sun 		DIMM_PARM(twr_ps),
233*5614e71bSYork Sun 		DIMM_PARM(twtr_ps),
234*5614e71bSYork Sun 		DIMM_PARM(trfc_ps),
235*5614e71bSYork Sun 		DIMM_PARM(trrd_ps),
236*5614e71bSYork Sun 		DIMM_PARM(trc_ps),
237*5614e71bSYork Sun 		DIMM_PARM(refresh_rate_ps),
238*5614e71bSYork Sun 
239*5614e71bSYork Sun 		DIMM_PARM(tis_ps),
240*5614e71bSYork Sun 		DIMM_PARM(tih_ps),
241*5614e71bSYork Sun 		DIMM_PARM(tds_ps),
242*5614e71bSYork Sun 		DIMM_PARM(tdh_ps),
243*5614e71bSYork Sun 		DIMM_PARM(trtp_ps),
244*5614e71bSYork Sun 		DIMM_PARM(tdqsq_max_ps),
245*5614e71bSYork Sun 		DIMM_PARM(tqhs_ps),
246*5614e71bSYork Sun 
247*5614e71bSYork Sun 		DIMM_PARM(rank_density),
248*5614e71bSYork Sun 		DIMM_PARM(capacity),
249*5614e71bSYork Sun 		DIMM_PARM(base_address),
250*5614e71bSYork Sun 	};
251*5614e71bSYork Sun 
252*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
253*5614e71bSYork Sun 
254*5614e71bSYork Sun 	if (handle_option_table(options, n_opts, p, optname_str, value_str))
255*5614e71bSYork Sun 		return;
256*5614e71bSYork Sun 
257*5614e71bSYork Sun 	printf("couldn't find option string %s\n", optname_str);
258*5614e71bSYork Sun }
259*5614e71bSYork Sun 
260*5614e71bSYork Sun static void print_dimm_parameters(const dimm_params_t *pdimm)
261*5614e71bSYork Sun {
262*5614e71bSYork Sun 	static const struct options_string options[] = {
263*5614e71bSYork Sun 		DIMM_PARM(n_ranks),
264*5614e71bSYork Sun 		DIMM_PARM(data_width),
265*5614e71bSYork Sun 		DIMM_PARM(primary_sdram_width),
266*5614e71bSYork Sun 		DIMM_PARM(ec_sdram_width),
267*5614e71bSYork Sun 		DIMM_PARM(registered_dimm),
268*5614e71bSYork Sun 		DIMM_PARM(device_width),
269*5614e71bSYork Sun 
270*5614e71bSYork Sun 		DIMM_PARM(n_row_addr),
271*5614e71bSYork Sun 		DIMM_PARM(n_col_addr),
272*5614e71bSYork Sun 		DIMM_PARM(edc_config),
273*5614e71bSYork Sun 		DIMM_PARM(n_banks_per_sdram_device),
274*5614e71bSYork Sun 
275*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_ps),
276*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_minus_1_ps),
277*5614e71bSYork Sun 		DIMM_PARM(tckmin_x_minus_2_ps),
278*5614e71bSYork Sun 		DIMM_PARM(tckmax_ps),
279*5614e71bSYork Sun 
280*5614e71bSYork Sun 		DIMM_PARM(caslat_x),
281*5614e71bSYork Sun 		DIMM_PARM(taa_ps),
282*5614e71bSYork Sun 		DIMM_PARM(caslat_x_minus_1),
283*5614e71bSYork Sun 		DIMM_PARM(caslat_x_minus_2),
284*5614e71bSYork Sun 		DIMM_PARM(caslat_lowest_derated),
285*5614e71bSYork Sun 
286*5614e71bSYork Sun 		DIMM_PARM(trcd_ps),
287*5614e71bSYork Sun 		DIMM_PARM(trp_ps),
288*5614e71bSYork Sun 		DIMM_PARM(tras_ps),
289*5614e71bSYork Sun 		DIMM_PARM(twr_ps),
290*5614e71bSYork Sun 		DIMM_PARM(twtr_ps),
291*5614e71bSYork Sun 		DIMM_PARM(trfc_ps),
292*5614e71bSYork Sun 		DIMM_PARM(trrd_ps),
293*5614e71bSYork Sun 		DIMM_PARM(trc_ps),
294*5614e71bSYork Sun 		DIMM_PARM(refresh_rate_ps),
295*5614e71bSYork Sun 
296*5614e71bSYork Sun 		DIMM_PARM(tis_ps),
297*5614e71bSYork Sun 		DIMM_PARM(tih_ps),
298*5614e71bSYork Sun 		DIMM_PARM(tds_ps),
299*5614e71bSYork Sun 		DIMM_PARM(tdh_ps),
300*5614e71bSYork Sun 		DIMM_PARM(trtp_ps),
301*5614e71bSYork Sun 		DIMM_PARM(tdqsq_max_ps),
302*5614e71bSYork Sun 		DIMM_PARM(tqhs_ps),
303*5614e71bSYork Sun 	};
304*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
305*5614e71bSYork Sun 
306*5614e71bSYork Sun 	if (pdimm->n_ranks == 0) {
307*5614e71bSYork Sun 		printf("DIMM not present\n");
308*5614e71bSYork Sun 		return;
309*5614e71bSYork Sun 	}
310*5614e71bSYork Sun 	printf("DIMM organization parameters:\n");
311*5614e71bSYork Sun 	printf("module part name = %s\n", pdimm->mpart);
312*5614e71bSYork Sun 	printf("rank_density = %llu bytes (%llu megabytes)\n",
313*5614e71bSYork Sun 	       pdimm->rank_density, pdimm->rank_density / 0x100000);
314*5614e71bSYork Sun 	printf("capacity = %llu bytes (%llu megabytes)\n",
315*5614e71bSYork Sun 	       pdimm->capacity, pdimm->capacity / 0x100000);
316*5614e71bSYork Sun 	printf("burst_lengths_bitmask = %02X\n",
317*5614e71bSYork Sun 	       pdimm->burst_lengths_bitmask);
318*5614e71bSYork Sun 	printf("base_addresss = %llu (%08llX %08llX)\n",
319*5614e71bSYork Sun 	       pdimm->base_address,
320*5614e71bSYork Sun 	       (pdimm->base_address >> 32),
321*5614e71bSYork Sun 	       pdimm->base_address & 0xFFFFFFFF);
322*5614e71bSYork Sun 	print_option_table(options, n_opts, pdimm);
323*5614e71bSYork Sun }
324*5614e71bSYork Sun 
325*5614e71bSYork Sun static void print_lowest_common_dimm_parameters(
326*5614e71bSYork Sun 		const common_timing_params_t *plcd_dimm_params)
327*5614e71bSYork Sun {
328*5614e71bSYork Sun 	static const struct options_string options[] = {
329*5614e71bSYork Sun 		COMMON_TIMING(tckmax_max_ps),
330*5614e71bSYork Sun 		COMMON_TIMING(trcd_ps),
331*5614e71bSYork Sun 		COMMON_TIMING(trp_ps),
332*5614e71bSYork Sun 		COMMON_TIMING(tras_ps),
333*5614e71bSYork Sun 		COMMON_TIMING(twr_ps),
334*5614e71bSYork Sun 		COMMON_TIMING(twtr_ps),
335*5614e71bSYork Sun 		COMMON_TIMING(trfc_ps),
336*5614e71bSYork Sun 		COMMON_TIMING(trrd_ps),
337*5614e71bSYork Sun 		COMMON_TIMING(trc_ps),
338*5614e71bSYork Sun 		COMMON_TIMING(refresh_rate_ps),
339*5614e71bSYork Sun 		COMMON_TIMING(tis_ps),
340*5614e71bSYork Sun 		COMMON_TIMING(tds_ps),
341*5614e71bSYork Sun 		COMMON_TIMING(tdh_ps),
342*5614e71bSYork Sun 		COMMON_TIMING(trtp_ps),
343*5614e71bSYork Sun 		COMMON_TIMING(tdqsq_max_ps),
344*5614e71bSYork Sun 		COMMON_TIMING(tqhs_ps),
345*5614e71bSYork Sun 		COMMON_TIMING(lowest_common_SPD_caslat),
346*5614e71bSYork Sun 		COMMON_TIMING(highest_common_derated_caslat),
347*5614e71bSYork Sun 		COMMON_TIMING(additive_latency),
348*5614e71bSYork Sun 		COMMON_TIMING(ndimms_present),
349*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_registered),
350*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_unbuffered),
351*5614e71bSYork Sun 		COMMON_TIMING(all_dimms_ecc_capable),
352*5614e71bSYork Sun 	};
353*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
354*5614e71bSYork Sun 
355*5614e71bSYork Sun 	/* Clock frequencies */
356*5614e71bSYork Sun 	printf("tckmin_x_ps = %u (%u MHz)\n",
357*5614e71bSYork Sun 	       plcd_dimm_params->tckmin_x_ps,
358*5614e71bSYork Sun 	       picos_to_mhz(plcd_dimm_params->tckmin_x_ps));
359*5614e71bSYork Sun 	printf("tckmax_ps = %u (%u MHz)\n",
360*5614e71bSYork Sun 	       plcd_dimm_params->tckmax_ps,
361*5614e71bSYork Sun 	       picos_to_mhz(plcd_dimm_params->tckmax_ps));
362*5614e71bSYork Sun 	printf("all_dimms_burst_lengths_bitmask = %02X\n",
363*5614e71bSYork Sun 	       plcd_dimm_params->all_dimms_burst_lengths_bitmask);
364*5614e71bSYork Sun 
365*5614e71bSYork Sun 	print_option_table(options, n_opts, plcd_dimm_params);
366*5614e71bSYork Sun 
367*5614e71bSYork Sun 	printf("total_mem = %llu (%llu megabytes)\n",
368*5614e71bSYork Sun 	       plcd_dimm_params->total_mem,
369*5614e71bSYork Sun 	       plcd_dimm_params->total_mem / 0x100000);
370*5614e71bSYork Sun 	printf("base_address = %llu (%llu megabytes)\n",
371*5614e71bSYork Sun 	       plcd_dimm_params->base_address,
372*5614e71bSYork Sun 	       plcd_dimm_params->base_address / 0x100000);
373*5614e71bSYork Sun }
374*5614e71bSYork Sun 
375*5614e71bSYork Sun #define CTRL_OPTIONS(x) {#x, offsetof(memctl_options_t, x), \
376*5614e71bSYork Sun 	sizeof((memctl_options_t *)0)->x, 0}
377*5614e71bSYork Sun #define CTRL_OPTIONS_CS(x, y) {"cs" #x "_" #y, \
378*5614e71bSYork Sun 	offsetof(memctl_options_t, cs_local_opts[x].y), \
379*5614e71bSYork Sun 	sizeof((memctl_options_t *)0)->cs_local_opts[x].y, 0}
380*5614e71bSYork Sun 
381*5614e71bSYork Sun static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
382*5614e71bSYork Sun 			   unsigned int ctl_num,
383*5614e71bSYork Sun 			   const char *optname_str,
384*5614e71bSYork Sun 			   const char *value_str)
385*5614e71bSYork Sun {
386*5614e71bSYork Sun 	memctl_options_t *p = &(pinfo->memctl_opts[ctl_num]);
387*5614e71bSYork Sun 	/*
388*5614e71bSYork Sun 	 * This array all on the stack and *computed* each time this
389*5614e71bSYork Sun 	 * function is rung.
390*5614e71bSYork Sun 	 */
391*5614e71bSYork Sun 	static const struct options_string options[] = {
392*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rd_cfg),
393*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_wr_cfg),
394*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
395*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rd_cfg),
396*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_wr_cfg),
397*5614e71bSYork Sun #endif
398*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
399*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rd_cfg),
400*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_wr_cfg),
401*5614e71bSYork Sun #endif
402*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
403*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rd_cfg),
404*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_wr_cfg),
405*5614e71bSYork Sun #endif
406*5614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR3)
407*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rtt_norm),
408*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rtt_wr),
409*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
410*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rtt_norm),
411*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rtt_wr),
412*5614e71bSYork Sun #endif
413*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
414*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rtt_norm),
415*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rtt_wr),
416*5614e71bSYork Sun #endif
417*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
418*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rtt_norm),
419*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rtt_wr),
420*5614e71bSYork Sun #endif
421*5614e71bSYork Sun #endif
422*5614e71bSYork Sun 		CTRL_OPTIONS(memctl_interleaving),
423*5614e71bSYork Sun 		CTRL_OPTIONS(memctl_interleaving_mode),
424*5614e71bSYork Sun 		CTRL_OPTIONS(ba_intlv_ctl),
425*5614e71bSYork Sun 		CTRL_OPTIONS(ecc_mode),
426*5614e71bSYork Sun 		CTRL_OPTIONS(ecc_init_using_memctl),
427*5614e71bSYork Sun 		CTRL_OPTIONS(dqs_config),
428*5614e71bSYork Sun 		CTRL_OPTIONS(self_refresh_in_sleep),
429*5614e71bSYork Sun 		CTRL_OPTIONS(dynamic_power),
430*5614e71bSYork Sun 		CTRL_OPTIONS(data_bus_width),
431*5614e71bSYork Sun 		CTRL_OPTIONS(burst_length),
432*5614e71bSYork Sun 		CTRL_OPTIONS(cas_latency_override),
433*5614e71bSYork Sun 		CTRL_OPTIONS(cas_latency_override_value),
434*5614e71bSYork Sun 		CTRL_OPTIONS(use_derated_caslat),
435*5614e71bSYork Sun 		CTRL_OPTIONS(additive_latency_override),
436*5614e71bSYork Sun 		CTRL_OPTIONS(additive_latency_override_value),
437*5614e71bSYork Sun 		CTRL_OPTIONS(clk_adjust),
438*5614e71bSYork Sun 		CTRL_OPTIONS(cpo_override),
439*5614e71bSYork Sun 		CTRL_OPTIONS(write_data_delay),
440*5614e71bSYork Sun 		CTRL_OPTIONS(half_strength_driver_enable),
441*5614e71bSYork Sun 
442*5614e71bSYork Sun 		/*
443*5614e71bSYork Sun 		 * These can probably be changed to 2T_EN and 3T_EN
444*5614e71bSYork Sun 		 * (using a leading numerical character) without problem
445*5614e71bSYork Sun 		 */
446*5614e71bSYork Sun 		CTRL_OPTIONS(twot_en),
447*5614e71bSYork Sun 		CTRL_OPTIONS(threet_en),
448*5614e71bSYork Sun 		CTRL_OPTIONS(ap_en),
449*5614e71bSYork Sun 		CTRL_OPTIONS(x4_en),
450*5614e71bSYork Sun 		CTRL_OPTIONS(bstopre),
451*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_override),
452*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_sample),
453*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_start),
454*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_override),
455*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_1),
456*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_2),
457*5614e71bSYork Sun 		CTRL_OPTIONS(ddr_cdr1),
458*5614e71bSYork Sun 		CTRL_OPTIONS(ddr_cdr2),
459*5614e71bSYork Sun 		CTRL_OPTIONS(tcke_clock_pulse_width_ps),
460*5614e71bSYork Sun 		CTRL_OPTIONS(tfaw_window_four_activates_ps),
461*5614e71bSYork Sun 		CTRL_OPTIONS(trwt_override),
462*5614e71bSYork Sun 		CTRL_OPTIONS(trwt),
463*5614e71bSYork Sun 	};
464*5614e71bSYork Sun 
465*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
466*5614e71bSYork Sun 
467*5614e71bSYork Sun 	if (handle_option_table(options, n_opts, p,
468*5614e71bSYork Sun 					optname_str, value_str))
469*5614e71bSYork Sun 		return;
470*5614e71bSYork Sun 
471*5614e71bSYork Sun 	printf("couldn't find option string %s\n", optname_str);
472*5614e71bSYork Sun }
473*5614e71bSYork Sun 
474*5614e71bSYork Sun #define CFG_REGS(x) {#x, offsetof(fsl_ddr_cfg_regs_t, x), \
475*5614e71bSYork Sun 	sizeof((fsl_ddr_cfg_regs_t *)0)->x, 1}
476*5614e71bSYork Sun #define CFG_REGS_CS(x, y) {"cs" #x "_" #y, \
477*5614e71bSYork Sun 	offsetof(fsl_ddr_cfg_regs_t, cs[x].y), \
478*5614e71bSYork Sun 	sizeof((fsl_ddr_cfg_regs_t *)0)->cs[x].y, 1}
479*5614e71bSYork Sun 
480*5614e71bSYork Sun static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
481*5614e71bSYork Sun {
482*5614e71bSYork Sun 	unsigned int i;
483*5614e71bSYork Sun 	static const struct options_string options[] = {
484*5614e71bSYork Sun 		CFG_REGS_CS(0, bnds),
485*5614e71bSYork Sun 		CFG_REGS_CS(0, config),
486*5614e71bSYork Sun 		CFG_REGS_CS(0, config_2),
487*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
488*5614e71bSYork Sun 		CFG_REGS_CS(1, bnds),
489*5614e71bSYork Sun 		CFG_REGS_CS(1, config),
490*5614e71bSYork Sun 		CFG_REGS_CS(1, config_2),
491*5614e71bSYork Sun #endif
492*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
493*5614e71bSYork Sun 		CFG_REGS_CS(2, bnds),
494*5614e71bSYork Sun 		CFG_REGS_CS(2, config),
495*5614e71bSYork Sun 		CFG_REGS_CS(2, config_2),
496*5614e71bSYork Sun #endif
497*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
498*5614e71bSYork Sun 		CFG_REGS_CS(3, bnds),
499*5614e71bSYork Sun 		CFG_REGS_CS(3, config),
500*5614e71bSYork Sun 		CFG_REGS_CS(3, config_2),
501*5614e71bSYork Sun #endif
502*5614e71bSYork Sun 		CFG_REGS(timing_cfg_3),
503*5614e71bSYork Sun 		CFG_REGS(timing_cfg_0),
504*5614e71bSYork Sun 		CFG_REGS(timing_cfg_1),
505*5614e71bSYork Sun 		CFG_REGS(timing_cfg_2),
506*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_cfg),
507*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_cfg_2),
508*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode),
509*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_2),
510*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_3),
511*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_4),
512*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_5),
513*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_6),
514*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_7),
515*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_8),
516*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_interval),
517*5614e71bSYork Sun 		CFG_REGS(ddr_data_init),
518*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_clk_cntl),
519*5614e71bSYork Sun 		CFG_REGS(ddr_init_addr),
520*5614e71bSYork Sun 		CFG_REGS(ddr_init_ext_addr),
521*5614e71bSYork Sun 		CFG_REGS(timing_cfg_4),
522*5614e71bSYork Sun 		CFG_REGS(timing_cfg_5),
523*5614e71bSYork Sun 		CFG_REGS(ddr_zq_cntl),
524*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl),
525*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl_2),
526*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl_3),
527*5614e71bSYork Sun 		CFG_REGS(ddr_sr_cntr),
528*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_1),
529*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_2),
530*5614e71bSYork Sun 		CFG_REGS(ddr_cdr1),
531*5614e71bSYork Sun 		CFG_REGS(ddr_cdr2),
532*5614e71bSYork Sun 		CFG_REGS(err_disable),
533*5614e71bSYork Sun 		CFG_REGS(err_int_en),
534*5614e71bSYork Sun 		CFG_REGS(ddr_eor),
535*5614e71bSYork Sun 	};
536*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
537*5614e71bSYork Sun 
538*5614e71bSYork Sun 	print_option_table(options, n_opts, ddr);
539*5614e71bSYork Sun 
540*5614e71bSYork Sun 	for (i = 0; i < 32; i++)
541*5614e71bSYork Sun 		printf("debug_%02d = 0x%08X\n", i+1, ddr->debug[i]);
542*5614e71bSYork Sun }
543*5614e71bSYork Sun 
544*5614e71bSYork Sun static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
545*5614e71bSYork Sun 			unsigned int ctrl_num,
546*5614e71bSYork Sun 			const char *regname,
547*5614e71bSYork Sun 			const char *value_str)
548*5614e71bSYork Sun {
549*5614e71bSYork Sun 	unsigned int i;
550*5614e71bSYork Sun 	fsl_ddr_cfg_regs_t *ddr;
551*5614e71bSYork Sun 	char buf[20];
552*5614e71bSYork Sun 	static const struct options_string options[] = {
553*5614e71bSYork Sun 		CFG_REGS_CS(0, bnds),
554*5614e71bSYork Sun 		CFG_REGS_CS(0, config),
555*5614e71bSYork Sun 		CFG_REGS_CS(0, config_2),
556*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
557*5614e71bSYork Sun 		CFG_REGS_CS(1, bnds),
558*5614e71bSYork Sun 		CFG_REGS_CS(1, config),
559*5614e71bSYork Sun 		CFG_REGS_CS(1, config_2),
560*5614e71bSYork Sun #endif
561*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
562*5614e71bSYork Sun 		CFG_REGS_CS(2, bnds),
563*5614e71bSYork Sun 		CFG_REGS_CS(2, config),
564*5614e71bSYork Sun 		CFG_REGS_CS(2, config_2),
565*5614e71bSYork Sun #endif
566*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
567*5614e71bSYork Sun 		CFG_REGS_CS(3, bnds),
568*5614e71bSYork Sun 		CFG_REGS_CS(3, config),
569*5614e71bSYork Sun 		CFG_REGS_CS(3, config_2),
570*5614e71bSYork Sun #endif
571*5614e71bSYork Sun 		CFG_REGS(timing_cfg_3),
572*5614e71bSYork Sun 		CFG_REGS(timing_cfg_0),
573*5614e71bSYork Sun 		CFG_REGS(timing_cfg_1),
574*5614e71bSYork Sun 		CFG_REGS(timing_cfg_2),
575*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_cfg),
576*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_cfg_2),
577*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode),
578*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_2),
579*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_3),
580*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_4),
581*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_5),
582*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_6),
583*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_7),
584*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_mode_8),
585*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_interval),
586*5614e71bSYork Sun 		CFG_REGS(ddr_data_init),
587*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_clk_cntl),
588*5614e71bSYork Sun 		CFG_REGS(ddr_init_addr),
589*5614e71bSYork Sun 		CFG_REGS(ddr_init_ext_addr),
590*5614e71bSYork Sun 		CFG_REGS(timing_cfg_4),
591*5614e71bSYork Sun 		CFG_REGS(timing_cfg_5),
592*5614e71bSYork Sun 		CFG_REGS(ddr_zq_cntl),
593*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl),
594*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl_2),
595*5614e71bSYork Sun 		CFG_REGS(ddr_wrlvl_cntl_3),
596*5614e71bSYork Sun 		CFG_REGS(ddr_sr_cntr),
597*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_1),
598*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_2),
599*5614e71bSYork Sun 		CFG_REGS(ddr_cdr1),
600*5614e71bSYork Sun 		CFG_REGS(ddr_cdr2),
601*5614e71bSYork Sun 		CFG_REGS(err_disable),
602*5614e71bSYork Sun 		CFG_REGS(err_int_en),
603*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_2),
604*5614e71bSYork Sun 		CFG_REGS(ddr_sdram_rcw_2),
605*5614e71bSYork Sun 		CFG_REGS(ddr_eor),
606*5614e71bSYork Sun 	};
607*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
608*5614e71bSYork Sun 
609*5614e71bSYork Sun 	debug("fsl_ddr_regs_edit: ctrl_num = %u, "
610*5614e71bSYork Sun 		"regname = %s, value = %s\n",
611*5614e71bSYork Sun 		ctrl_num, regname, value_str);
612*5614e71bSYork Sun 	if (ctrl_num > CONFIG_NUM_DDR_CONTROLLERS)
613*5614e71bSYork Sun 		return;
614*5614e71bSYork Sun 
615*5614e71bSYork Sun 	ddr = &(pinfo->fsl_ddr_config_reg[ctrl_num]);
616*5614e71bSYork Sun 
617*5614e71bSYork Sun 	if (handle_option_table(options, n_opts, ddr, regname, value_str))
618*5614e71bSYork Sun 		return;
619*5614e71bSYork Sun 
620*5614e71bSYork Sun 	for (i = 0; i < 32; i++) {
621*5614e71bSYork Sun 		unsigned int value = simple_strtoul(value_str, NULL, 0);
622*5614e71bSYork Sun 		sprintf(buf, "debug_%u", i + 1);
623*5614e71bSYork Sun 		if (strcmp(buf, regname) == 0) {
624*5614e71bSYork Sun 			ddr->debug[i] = value;
625*5614e71bSYork Sun 			return;
626*5614e71bSYork Sun 		}
627*5614e71bSYork Sun 	}
628*5614e71bSYork Sun 	printf("Error: couldn't find register string %s\n", regname);
629*5614e71bSYork Sun }
630*5614e71bSYork Sun 
631*5614e71bSYork Sun #define CTRL_OPTIONS_HEX(x) {#x, offsetof(memctl_options_t, x), \
632*5614e71bSYork Sun 	sizeof((memctl_options_t *)0)->x, 1}
633*5614e71bSYork Sun 
634*5614e71bSYork Sun static void print_memctl_options(const memctl_options_t *popts)
635*5614e71bSYork Sun {
636*5614e71bSYork Sun 	static const struct options_string options[] = {
637*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rd_cfg),
638*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_wr_cfg),
639*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
640*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rd_cfg),
641*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_wr_cfg),
642*5614e71bSYork Sun #endif
643*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
644*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rd_cfg),
645*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_wr_cfg),
646*5614e71bSYork Sun #endif
647*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
648*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rd_cfg),
649*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_wr_cfg),
650*5614e71bSYork Sun #endif
651*5614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR3)
652*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rtt_norm),
653*5614e71bSYork Sun 		CTRL_OPTIONS_CS(0, odt_rtt_wr),
654*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 1)
655*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rtt_norm),
656*5614e71bSYork Sun 		CTRL_OPTIONS_CS(1, odt_rtt_wr),
657*5614e71bSYork Sun #endif
658*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 2)
659*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rtt_norm),
660*5614e71bSYork Sun 		CTRL_OPTIONS_CS(2, odt_rtt_wr),
661*5614e71bSYork Sun #endif
662*5614e71bSYork Sun #if (CONFIG_CHIP_SELECTS_PER_CTRL > 3)
663*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rtt_norm),
664*5614e71bSYork Sun 		CTRL_OPTIONS_CS(3, odt_rtt_wr),
665*5614e71bSYork Sun #endif
666*5614e71bSYork Sun #endif
667*5614e71bSYork Sun 		CTRL_OPTIONS(memctl_interleaving),
668*5614e71bSYork Sun 		CTRL_OPTIONS(memctl_interleaving_mode),
669*5614e71bSYork Sun 		CTRL_OPTIONS_HEX(ba_intlv_ctl),
670*5614e71bSYork Sun 		CTRL_OPTIONS(ecc_mode),
671*5614e71bSYork Sun 		CTRL_OPTIONS(ecc_init_using_memctl),
672*5614e71bSYork Sun 		CTRL_OPTIONS(dqs_config),
673*5614e71bSYork Sun 		CTRL_OPTIONS(self_refresh_in_sleep),
674*5614e71bSYork Sun 		CTRL_OPTIONS(dynamic_power),
675*5614e71bSYork Sun 		CTRL_OPTIONS(data_bus_width),
676*5614e71bSYork Sun 		CTRL_OPTIONS(burst_length),
677*5614e71bSYork Sun 		CTRL_OPTIONS(cas_latency_override),
678*5614e71bSYork Sun 		CTRL_OPTIONS(cas_latency_override_value),
679*5614e71bSYork Sun 		CTRL_OPTIONS(use_derated_caslat),
680*5614e71bSYork Sun 		CTRL_OPTIONS(additive_latency_override),
681*5614e71bSYork Sun 		CTRL_OPTIONS(additive_latency_override_value),
682*5614e71bSYork Sun 		CTRL_OPTIONS(clk_adjust),
683*5614e71bSYork Sun 		CTRL_OPTIONS(cpo_override),
684*5614e71bSYork Sun 		CTRL_OPTIONS(write_data_delay),
685*5614e71bSYork Sun 		CTRL_OPTIONS(half_strength_driver_enable),
686*5614e71bSYork Sun 		/*
687*5614e71bSYork Sun 		 * These can probably be changed to 2T_EN and 3T_EN
688*5614e71bSYork Sun 		 * (using a leading numerical character) without problem
689*5614e71bSYork Sun 		 */
690*5614e71bSYork Sun 		CTRL_OPTIONS(twot_en),
691*5614e71bSYork Sun 		CTRL_OPTIONS(threet_en),
692*5614e71bSYork Sun 		CTRL_OPTIONS(registered_dimm_en),
693*5614e71bSYork Sun 		CTRL_OPTIONS(ap_en),
694*5614e71bSYork Sun 		CTRL_OPTIONS(x4_en),
695*5614e71bSYork Sun 		CTRL_OPTIONS(bstopre),
696*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_override),
697*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_sample),
698*5614e71bSYork Sun 		CTRL_OPTIONS(wrlvl_start),
699*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_override),
700*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_1),
701*5614e71bSYork Sun 		CTRL_OPTIONS(rcw_2),
702*5614e71bSYork Sun 		CTRL_OPTIONS_HEX(ddr_cdr1),
703*5614e71bSYork Sun 		CTRL_OPTIONS_HEX(ddr_cdr2),
704*5614e71bSYork Sun 		CTRL_OPTIONS(tcke_clock_pulse_width_ps),
705*5614e71bSYork Sun 		CTRL_OPTIONS(tfaw_window_four_activates_ps),
706*5614e71bSYork Sun 		CTRL_OPTIONS(trwt_override),
707*5614e71bSYork Sun 		CTRL_OPTIONS(trwt),
708*5614e71bSYork Sun 	};
709*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
710*5614e71bSYork Sun 
711*5614e71bSYork Sun 	print_option_table(options, n_opts, popts);
712*5614e71bSYork Sun }
713*5614e71bSYork Sun 
714*5614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR1
715*5614e71bSYork Sun void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd)
716*5614e71bSYork Sun {
717*5614e71bSYork Sun 	unsigned int i;
718*5614e71bSYork Sun 
719*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 0, spd->info_size,
720*5614e71bSYork Sun 	       " spd->info_size,   *  0 # bytes written into serial memory *");
721*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 1, spd->chip_size,
722*5614e71bSYork Sun 	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
723*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 2, spd->mem_type,
724*5614e71bSYork Sun 	       " spd->mem_type,    *  2 Fundamental memory type *");
725*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 3, spd->nrow_addr,
726*5614e71bSYork Sun 	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
727*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 4, spd->ncol_addr,
728*5614e71bSYork Sun 	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
729*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 5, spd->nrows,
730*5614e71bSYork Sun 	       " spd->nrows        *  5 # of DIMM Banks *");
731*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 6, spd->dataw_lsb,
732*5614e71bSYork Sun 	       " spd->dataw_lsb,   *  6 Data Width lsb of this assembly *");
733*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 7, spd->dataw_msb,
734*5614e71bSYork Sun 	       " spd->dataw_msb,   *  7 Data Width msb of this assembly *");
735*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 8, spd->voltage,
736*5614e71bSYork Sun 	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
737*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 9, spd->clk_cycle,
738*5614e71bSYork Sun 	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
739*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 10, spd->clk_access,
740*5614e71bSYork Sun 	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
741*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 11, spd->config,
742*5614e71bSYork Sun 	       " spd->config,      * 11 DIMM Configuration type *");
743*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 12, spd->refresh,
744*5614e71bSYork Sun 	       " spd->refresh,     * 12 Refresh Rate/Type *");
745*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 13, spd->primw,
746*5614e71bSYork Sun 	       " spd->primw,       * 13 Primary SDRAM Width *");
747*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 14, spd->ecw,
748*5614e71bSYork Sun 	       " spd->ecw,         * 14 Error Checking SDRAM width *");
749*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 15, spd->min_delay,
750*5614e71bSYork Sun 	       " spd->min_delay,   * 15 Back to Back Random Access *");
751*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 16, spd->burstl,
752*5614e71bSYork Sun 	       " spd->burstl,      * 16 Burst Lengths Supported *");
753*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 17, spd->nbanks,
754*5614e71bSYork Sun 	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
755*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 18, spd->cas_lat,
756*5614e71bSYork Sun 	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
757*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 19, spd->cs_lat,
758*5614e71bSYork Sun 	       " spd->cs_lat,      * 19 Chip Select Latency *");
759*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 20, spd->write_lat,
760*5614e71bSYork Sun 	       " spd->write_lat,   * 20 Write Latency/Recovery *");
761*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 21, spd->mod_attr,
762*5614e71bSYork Sun 	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
763*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 22, spd->dev_attr,
764*5614e71bSYork Sun 	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
765*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 23, spd->clk_cycle2,
766*5614e71bSYork Sun 	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
767*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 24, spd->clk_access2,
768*5614e71bSYork Sun 	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
769*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 25, spd->clk_cycle3,
770*5614e71bSYork Sun 	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
771*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 26, spd->clk_access3,
772*5614e71bSYork Sun 	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
773*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 27, spd->trp,
774*5614e71bSYork Sun 	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
775*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 28, spd->trrd,
776*5614e71bSYork Sun 	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
777*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 29, spd->trcd,
778*5614e71bSYork Sun 	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
779*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 30, spd->tras,
780*5614e71bSYork Sun 	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
781*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 31, spd->bank_dens,
782*5614e71bSYork Sun 	       " spd->bank_dens,   * 31 Density of each bank on module *");
783*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 32, spd->ca_setup,
784*5614e71bSYork Sun 	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
785*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 33, spd->ca_hold,
786*5614e71bSYork Sun 	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
787*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 34, spd->data_setup,
788*5614e71bSYork Sun 	       " spd->data_setup,  * 34 Data signal input setup time *");
789*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 35, spd->data_hold,
790*5614e71bSYork Sun 	       " spd->data_hold,   * 35 Data signal input hold time *");
791*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 36, spd->res_36_40[0],
792*5614e71bSYork Sun 	       " spd->res_36_40[0], * 36 Reserved / tWR *");
793*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 37, spd->res_36_40[1],
794*5614e71bSYork Sun 	       " spd->res_36_40[1], * 37 Reserved / tWTR *");
795*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 38, spd->res_36_40[2],
796*5614e71bSYork Sun 	       " spd->res_36_40[2], * 38 Reserved / tRTP *");
797*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 39, spd->res_36_40[3],
798*5614e71bSYork Sun 	       " spd->res_36_40[3], * 39 Reserved / mem_probe *");
799*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 40, spd->res_36_40[4],
800*5614e71bSYork Sun 	       " spd->res_36_40[4], * 40 Reserved / trc,trfc extensions *");
801*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 41, spd->trc,
802*5614e71bSYork Sun 	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
803*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 42, spd->trfc,
804*5614e71bSYork Sun 	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
805*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 43, spd->tckmax,
806*5614e71bSYork Sun 	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
807*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 44, spd->tdqsq,
808*5614e71bSYork Sun 	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
809*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 45, spd->tqhs,
810*5614e71bSYork Sun 	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
811*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 46, spd->res_46,
812*5614e71bSYork Sun 	       " spd->res_46,  * 46 Reserved/ PLL Relock time *");
813*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 47, spd->dimm_height,
814*5614e71bSYork Sun 	       " spd->dimm_height  * 47 SDRAM DIMM Height *");
815*5614e71bSYork Sun 
816*5614e71bSYork Sun 	printf("%-3d-%3d: ",  48, 61);
817*5614e71bSYork Sun 
818*5614e71bSYork Sun 	for (i = 0; i < 14; i++)
819*5614e71bSYork Sun 		printf("%02x", spd->res_48_61[i]);
820*5614e71bSYork Sun 
821*5614e71bSYork Sun 	printf(" * 48-61 IDD in SPD and Reserved space *\n");
822*5614e71bSYork Sun 
823*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 62, spd->spd_rev,
824*5614e71bSYork Sun 	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
825*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 63, spd->cksum,
826*5614e71bSYork Sun 	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
827*5614e71bSYork Sun 	printf("%-3d-%3d: ",  64, 71);
828*5614e71bSYork Sun 
829*5614e71bSYork Sun 	for (i = 0; i < 8; i++)
830*5614e71bSYork Sun 		printf("%02x", spd->mid[i]);
831*5614e71bSYork Sun 
832*5614e71bSYork Sun 	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
833*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 72, spd->mloc,
834*5614e71bSYork Sun 	       " spd->mloc,        * 72 Manufacturing Location *");
835*5614e71bSYork Sun 
836*5614e71bSYork Sun 	printf("%-3d-%3d: >>",  73, 90);
837*5614e71bSYork Sun 
838*5614e71bSYork Sun 	for (i = 0; i < 18; i++)
839*5614e71bSYork Sun 		printf("%c", spd->mpart[i]);
840*5614e71bSYork Sun 
841*5614e71bSYork Sun 	printf("<<* 73 Manufacturer's Part Number *\n");
842*5614e71bSYork Sun 
843*5614e71bSYork Sun 	printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1],
844*5614e71bSYork Sun 	       "* 91 Revision Code *");
845*5614e71bSYork Sun 	printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1],
846*5614e71bSYork Sun 	       "* 93 Manufacturing Date *");
847*5614e71bSYork Sun 	printf("%-3d-%3d: ", 95, 98);
848*5614e71bSYork Sun 
849*5614e71bSYork Sun 	for (i = 0; i < 4; i++)
850*5614e71bSYork Sun 		printf("%02x", spd->sernum[i]);
851*5614e71bSYork Sun 
852*5614e71bSYork Sun 	printf("* 95 Assembly Serial Number *\n");
853*5614e71bSYork Sun 
854*5614e71bSYork Sun 	printf("%-3d-%3d: ", 99, 127);
855*5614e71bSYork Sun 
856*5614e71bSYork Sun 	for (i = 0; i < 27; i++)
857*5614e71bSYork Sun 		printf("%02x", spd->mspec[i]);
858*5614e71bSYork Sun 
859*5614e71bSYork Sun 	printf("* 99 Manufacturer Specific Data *\n");
860*5614e71bSYork Sun }
861*5614e71bSYork Sun #endif
862*5614e71bSYork Sun 
863*5614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR2
864*5614e71bSYork Sun void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd)
865*5614e71bSYork Sun {
866*5614e71bSYork Sun 	unsigned int i;
867*5614e71bSYork Sun 
868*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 0, spd->info_size,
869*5614e71bSYork Sun 	       " spd->info_size,   *  0 # bytes written into serial memory *");
870*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 1, spd->chip_size,
871*5614e71bSYork Sun 	       " spd->chip_size,   *  1 Total # bytes of SPD memory device *");
872*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 2, spd->mem_type,
873*5614e71bSYork Sun 	       " spd->mem_type,    *  2 Fundamental memory type *");
874*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 3, spd->nrow_addr,
875*5614e71bSYork Sun 	       " spd->nrow_addr,   *  3 # of Row Addresses on this assembly *");
876*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 4, spd->ncol_addr,
877*5614e71bSYork Sun 	       " spd->ncol_addr,   *  4 # of Column Addrs on this assembly *");
878*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 5, spd->mod_ranks,
879*5614e71bSYork Sun 	       " spd->mod_ranks    *  5 # of Module Rows on this assembly *");
880*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 6, spd->dataw,
881*5614e71bSYork Sun 	       " spd->dataw,       *  6 Data Width of this assembly *");
882*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 7, spd->res_7,
883*5614e71bSYork Sun 	       " spd->res_7,       *  7 Reserved *");
884*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 8, spd->voltage,
885*5614e71bSYork Sun 	       " spd->voltage,     *  8 Voltage intf std of this assembly *");
886*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 9, spd->clk_cycle,
887*5614e71bSYork Sun 	       " spd->clk_cycle,   *  9 SDRAM Cycle time at CL=X *");
888*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 10, spd->clk_access,
889*5614e71bSYork Sun 	       " spd->clk_access,  * 10 SDRAM Access from Clock at CL=X *");
890*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 11, spd->config,
891*5614e71bSYork Sun 	       " spd->config,      * 11 DIMM Configuration type *");
892*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 12, spd->refresh,
893*5614e71bSYork Sun 	       " spd->refresh,     * 12 Refresh Rate/Type *");
894*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 13, spd->primw,
895*5614e71bSYork Sun 	       " spd->primw,       * 13 Primary SDRAM Width *");
896*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 14, spd->ecw,
897*5614e71bSYork Sun 	       " spd->ecw,         * 14 Error Checking SDRAM width *");
898*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 15, spd->res_15,
899*5614e71bSYork Sun 	       " spd->res_15,      * 15 Reserved *");
900*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 16, spd->burstl,
901*5614e71bSYork Sun 	       " spd->burstl,      * 16 Burst Lengths Supported *");
902*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 17, spd->nbanks,
903*5614e71bSYork Sun 	       " spd->nbanks,      * 17 # of Banks on Each SDRAM Device *");
904*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 18, spd->cas_lat,
905*5614e71bSYork Sun 	       " spd->cas_lat,     * 18 CAS# Latencies Supported *");
906*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 19, spd->mech_char,
907*5614e71bSYork Sun 	       " spd->mech_char,   * 19 Mechanical Characteristics *");
908*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 20, spd->dimm_type,
909*5614e71bSYork Sun 	       " spd->dimm_type,   * 20 DIMM type *");
910*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 21, spd->mod_attr,
911*5614e71bSYork Sun 	       " spd->mod_attr,    * 21 SDRAM Module Attributes *");
912*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 22, spd->dev_attr,
913*5614e71bSYork Sun 	       " spd->dev_attr,    * 22 SDRAM Device Attributes *");
914*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 23, spd->clk_cycle2,
915*5614e71bSYork Sun 	       " spd->clk_cycle2,  * 23 Min SDRAM Cycle time at CL=X-1 *");
916*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 24, spd->clk_access2,
917*5614e71bSYork Sun 	       " spd->clk_access2, * 24 SDRAM Access from Clock at CL=X-1 *");
918*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 25, spd->clk_cycle3,
919*5614e71bSYork Sun 	       " spd->clk_cycle3,  * 25 Min SDRAM Cycle time at CL=X-2 *");
920*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 26, spd->clk_access3,
921*5614e71bSYork Sun 	       " spd->clk_access3, * 26 Max Access from Clock at CL=X-2 *");
922*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 27, spd->trp,
923*5614e71bSYork Sun 	       " spd->trp,         * 27 Min Row Precharge Time (tRP)*");
924*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 28, spd->trrd,
925*5614e71bSYork Sun 	       " spd->trrd,        * 28 Min Row Active to Row Active (tRRD) *");
926*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 29, spd->trcd,
927*5614e71bSYork Sun 	       " spd->trcd,        * 29 Min RAS to CAS Delay (tRCD) *");
928*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 30, spd->tras,
929*5614e71bSYork Sun 	       " spd->tras,        * 30 Minimum RAS Pulse Width (tRAS) *");
930*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 31, spd->rank_dens,
931*5614e71bSYork Sun 	       " spd->rank_dens,   * 31 Density of each rank on module *");
932*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 32, spd->ca_setup,
933*5614e71bSYork Sun 	       " spd->ca_setup,    * 32 Cmd + Addr signal input setup time *");
934*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 33, spd->ca_hold,
935*5614e71bSYork Sun 	       " spd->ca_hold,     * 33 Cmd and Addr signal input hold time *");
936*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 34, spd->data_setup,
937*5614e71bSYork Sun 	       " spd->data_setup,  * 34 Data signal input setup time *");
938*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 35, spd->data_hold,
939*5614e71bSYork Sun 	       " spd->data_hold,   * 35 Data signal input hold time *");
940*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 36, spd->twr,
941*5614e71bSYork Sun 	       " spd->twr,         * 36 Write Recovery time tWR *");
942*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 37, spd->twtr,
943*5614e71bSYork Sun 	       " spd->twtr,        * 37 Int write to read delay tWTR *");
944*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 38, spd->trtp,
945*5614e71bSYork Sun 	       " spd->trtp,        * 38 Int read to precharge delay tRTP *");
946*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 39, spd->mem_probe,
947*5614e71bSYork Sun 	       " spd->mem_probe,   * 39 Mem analysis probe characteristics *");
948*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 40, spd->trctrfc_ext,
949*5614e71bSYork Sun 	       " spd->trctrfc_ext, * 40 Extensions to trc and trfc *");
950*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 41, spd->trc,
951*5614e71bSYork Sun 	       " spd->trc,         * 41 Min Active to Auto refresh time tRC *");
952*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 42, spd->trfc,
953*5614e71bSYork Sun 	       " spd->trfc,        * 42 Min Auto to Active period tRFC *");
954*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 43, spd->tckmax,
955*5614e71bSYork Sun 	       " spd->tckmax,      * 43 Max device cycle time tCKmax *");
956*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 44, spd->tdqsq,
957*5614e71bSYork Sun 	       " spd->tdqsq,       * 44 Max DQS to DQ skew *");
958*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 45, spd->tqhs,
959*5614e71bSYork Sun 	       " spd->tqhs,        * 45 Max Read DataHold skew tQHS *");
960*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 46, spd->pll_relock,
961*5614e71bSYork Sun 	       " spd->pll_relock,  * 46 PLL Relock time *");
962*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 47, spd->t_casemax,
963*5614e71bSYork Sun 	       " spd->t_casemax,    * 47 t_casemax *");
964*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 48, spd->psi_ta_dram,
965*5614e71bSYork Sun 	       " spd->psi_ta_dram,   * 48 Thermal Resistance of DRAM Package "
966*5614e71bSYork Sun 	       "from Top (Case) to Ambient (Psi T-A DRAM) *");
967*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 49, spd->dt0_mode,
968*5614e71bSYork Sun 	       " spd->dt0_mode,    * 49 DRAM Case Temperature Rise from "
969*5614e71bSYork Sun 	       "Ambient due to Activate-Precharge/Mode Bits "
970*5614e71bSYork Sun 	       "(DT0/Mode Bits) *)");
971*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 50, spd->dt2n_dt2q,
972*5614e71bSYork Sun 	       " spd->dt2n_dt2q,   * 50 DRAM Case Temperature Rise from "
973*5614e71bSYork Sun 	       "Ambient due to Precharge/Quiet Standby "
974*5614e71bSYork Sun 	       "(DT2N/DT2Q) *");
975*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 51, spd->dt2p,
976*5614e71bSYork Sun 	       " spd->dt2p,        * 51 DRAM Case Temperature Rise from "
977*5614e71bSYork Sun 	       "Ambient due to Precharge Power-Down (DT2P) *");
978*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 52, spd->dt3n,
979*5614e71bSYork Sun 	       " spd->dt3n,        * 52 DRAM Case Temperature Rise from "
980*5614e71bSYork Sun 	       "Ambient due to Active Standby (DT3N) *");
981*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 53, spd->dt3pfast,
982*5614e71bSYork Sun 	       " spd->dt3pfast,    * 53 DRAM Case Temperature Rise from "
983*5614e71bSYork Sun 	       "Ambient due to Active Power-Down with Fast PDN Exit "
984*5614e71bSYork Sun 	       "(DT3Pfast) *");
985*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 54, spd->dt3pslow,
986*5614e71bSYork Sun 	       " spd->dt3pslow,    * 54 DRAM Case Temperature Rise from "
987*5614e71bSYork Sun 	       "Ambient due to Active Power-Down with Slow PDN Exit "
988*5614e71bSYork Sun 	       "(DT3Pslow) *");
989*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 55, spd->dt4r_dt4r4w,
990*5614e71bSYork Sun 	       " spd->dt4r_dt4r4w, * 55 DRAM Case Temperature Rise from "
991*5614e71bSYork Sun 	       "Ambient due to Page Open Burst Read/DT4R4W Mode Bit "
992*5614e71bSYork Sun 	       "(DT4R/DT4R4W Mode Bit) *");
993*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 56, spd->dt5b,
994*5614e71bSYork Sun 	       " spd->dt5b,        * 56 DRAM Case Temperature Rise from "
995*5614e71bSYork Sun 	       "Ambient due to Burst Refresh (DT5B) *");
996*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 57, spd->dt7,
997*5614e71bSYork Sun 	       " spd->dt7,         * 57 DRAM Case Temperature Rise from "
998*5614e71bSYork Sun 	       "Ambient due to Bank Interleave Reads with "
999*5614e71bSYork Sun 	       "Auto-Precharge (DT7) *");
1000*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 58, spd->psi_ta_pll,
1001*5614e71bSYork Sun 	       " spd->psi_ta_pll,    * 58 Thermal Resistance of PLL Package form"
1002*5614e71bSYork Sun 	       " Top (Case) to Ambient (Psi T-A PLL) *");
1003*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 59, spd->psi_ta_reg,
1004*5614e71bSYork Sun 	       " spd->psi_ta_reg,    * 59 Thermal Reisitance of Register Package"
1005*5614e71bSYork Sun 	       " from Top (Case) to Ambient (Psi T-A Register) *");
1006*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 60, spd->dtpllactive,
1007*5614e71bSYork Sun 	       " spd->dtpllactive, * 60 PLL Case Temperature Rise from "
1008*5614e71bSYork Sun 	       "Ambient due to PLL Active (DT PLL Active) *");
1009*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 61, spd->dtregact,
1010*5614e71bSYork Sun 	       " spd->dtregact,    "
1011*5614e71bSYork Sun 	       "* 61 Register Case Temperature Rise from Ambient due to "
1012*5614e71bSYork Sun 	       "Register Active/Mode Bit (DT Register Active/Mode Bit) *");
1013*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 62, spd->spd_rev,
1014*5614e71bSYork Sun 	       " spd->spd_rev,     * 62 SPD Data Revision Code *");
1015*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 63, spd->cksum,
1016*5614e71bSYork Sun 	       " spd->cksum,       * 63 Checksum for bytes 0-62 *");
1017*5614e71bSYork Sun 
1018*5614e71bSYork Sun 	printf("%-3d-%3d: ",  64, 71);
1019*5614e71bSYork Sun 
1020*5614e71bSYork Sun 	for (i = 0; i < 8; i++)
1021*5614e71bSYork Sun 		printf("%02x", spd->mid[i]);
1022*5614e71bSYork Sun 
1023*5614e71bSYork Sun 	printf("* 64 Mfr's JEDEC ID code per JEP-108E *\n");
1024*5614e71bSYork Sun 
1025*5614e71bSYork Sun 	printf("%-3d    : %02x %s\n", 72, spd->mloc,
1026*5614e71bSYork Sun 	       " spd->mloc,        * 72 Manufacturing Location *");
1027*5614e71bSYork Sun 
1028*5614e71bSYork Sun 	printf("%-3d-%3d: >>",  73, 90);
1029*5614e71bSYork Sun 	for (i = 0; i < 18; i++)
1030*5614e71bSYork Sun 		printf("%c", spd->mpart[i]);
1031*5614e71bSYork Sun 
1032*5614e71bSYork Sun 
1033*5614e71bSYork Sun 	printf("<<* 73 Manufacturer's Part Number *\n");
1034*5614e71bSYork Sun 
1035*5614e71bSYork Sun 	printf("%-3d-%3d: %02x %02x %s\n", 91, 92, spd->rev[0], spd->rev[1],
1036*5614e71bSYork Sun 	       "* 91 Revision Code *");
1037*5614e71bSYork Sun 	printf("%-3d-%3d: %02x %02x %s\n", 93, 94, spd->mdate[0], spd->mdate[1],
1038*5614e71bSYork Sun 	       "* 93 Manufacturing Date *");
1039*5614e71bSYork Sun 	printf("%-3d-%3d: ", 95, 98);
1040*5614e71bSYork Sun 
1041*5614e71bSYork Sun 	for (i = 0; i < 4; i++)
1042*5614e71bSYork Sun 		printf("%02x", spd->sernum[i]);
1043*5614e71bSYork Sun 
1044*5614e71bSYork Sun 	printf("* 95 Assembly Serial Number *\n");
1045*5614e71bSYork Sun 
1046*5614e71bSYork Sun 	printf("%-3d-%3d: ", 99, 127);
1047*5614e71bSYork Sun 	for (i = 0; i < 27; i++)
1048*5614e71bSYork Sun 		printf("%02x", spd->mspec[i]);
1049*5614e71bSYork Sun 
1050*5614e71bSYork Sun 
1051*5614e71bSYork Sun 	printf("* 99 Manufacturer Specific Data *\n");
1052*5614e71bSYork Sun }
1053*5614e71bSYork Sun #endif
1054*5614e71bSYork Sun 
1055*5614e71bSYork Sun #ifdef CONFIG_SYS_FSL_DDR3
1056*5614e71bSYork Sun void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
1057*5614e71bSYork Sun {
1058*5614e71bSYork Sun 	unsigned int i;
1059*5614e71bSYork Sun 
1060*5614e71bSYork Sun 	/* General Section: Bytes 0-59 */
1061*5614e71bSYork Sun 
1062*5614e71bSYork Sun #define PRINT_NXS(x, y, z...) printf("%-3d    : %02x " z "\n", x, (u8)y);
1063*5614e71bSYork Sun #define PRINT_NNXXS(n0, n1, x0, x1, s) \
1064*5614e71bSYork Sun 	printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
1065*5614e71bSYork Sun 
1066*5614e71bSYork Sun 	PRINT_NXS(0, spd->info_size_crc,
1067*5614e71bSYork Sun 		"info_size_crc  bytes written into serial memory, "
1068*5614e71bSYork Sun 		"CRC coverage");
1069*5614e71bSYork Sun 	PRINT_NXS(1, spd->spd_rev,
1070*5614e71bSYork Sun 		"spd_rev        SPD Revision");
1071*5614e71bSYork Sun 	PRINT_NXS(2, spd->mem_type,
1072*5614e71bSYork Sun 		"mem_type       Key Byte / DRAM Device Type");
1073*5614e71bSYork Sun 	PRINT_NXS(3, spd->module_type,
1074*5614e71bSYork Sun 		"module_type    Key Byte / Module Type");
1075*5614e71bSYork Sun 	PRINT_NXS(4, spd->density_banks,
1076*5614e71bSYork Sun 		"density_banks  SDRAM Density and Banks");
1077*5614e71bSYork Sun 	PRINT_NXS(5, spd->addressing,
1078*5614e71bSYork Sun 		"addressing     SDRAM Addressing");
1079*5614e71bSYork Sun 	PRINT_NXS(6, spd->module_vdd,
1080*5614e71bSYork Sun 		"module_vdd     Module Nominal Voltage, VDD");
1081*5614e71bSYork Sun 	PRINT_NXS(7, spd->organization,
1082*5614e71bSYork Sun 		"organization   Module Organization");
1083*5614e71bSYork Sun 	PRINT_NXS(8, spd->bus_width,
1084*5614e71bSYork Sun 		"bus_width      Module Memory Bus Width");
1085*5614e71bSYork Sun 	PRINT_NXS(9, spd->ftb_div,
1086*5614e71bSYork Sun 		"ftb_div        Fine Timebase (FTB) Dividend / Divisor");
1087*5614e71bSYork Sun 	PRINT_NXS(10, spd->mtb_dividend,
1088*5614e71bSYork Sun 		"mtb_dividend   Medium Timebase (MTB) Dividend");
1089*5614e71bSYork Sun 	PRINT_NXS(11, spd->mtb_divisor,
1090*5614e71bSYork Sun 		"mtb_divisor    Medium Timebase (MTB) Divisor");
1091*5614e71bSYork Sun 	PRINT_NXS(12, spd->tck_min,
1092*5614e71bSYork Sun 		  "tck_min        SDRAM Minimum Cycle Time");
1093*5614e71bSYork Sun 	PRINT_NXS(13, spd->res_13,
1094*5614e71bSYork Sun 		"res_13         Reserved");
1095*5614e71bSYork Sun 	PRINT_NXS(14, spd->caslat_lsb,
1096*5614e71bSYork Sun 		"caslat_lsb     CAS Latencies Supported, LSB");
1097*5614e71bSYork Sun 	PRINT_NXS(15, spd->caslat_msb,
1098*5614e71bSYork Sun 		"caslat_msb     CAS Latencies Supported, MSB");
1099*5614e71bSYork Sun 	PRINT_NXS(16, spd->taa_min,
1100*5614e71bSYork Sun 		  "taa_min        Min CAS Latency Time");
1101*5614e71bSYork Sun 	PRINT_NXS(17, spd->twr_min,
1102*5614e71bSYork Sun 		  "twr_min        Min Write REcovery Time");
1103*5614e71bSYork Sun 	PRINT_NXS(18, spd->trcd_min,
1104*5614e71bSYork Sun 		  "trcd_min       Min RAS# to CAS# Delay Time");
1105*5614e71bSYork Sun 	PRINT_NXS(19, spd->trrd_min,
1106*5614e71bSYork Sun 		  "trrd_min       Min Row Active to Row Active Delay Time");
1107*5614e71bSYork Sun 	PRINT_NXS(20, spd->trp_min,
1108*5614e71bSYork Sun 		  "trp_min        Min Row Precharge Delay Time");
1109*5614e71bSYork Sun 	PRINT_NXS(21, spd->tras_trc_ext,
1110*5614e71bSYork Sun 		  "tras_trc_ext   Upper Nibbles for tRAS and tRC");
1111*5614e71bSYork Sun 	PRINT_NXS(22, spd->tras_min_lsb,
1112*5614e71bSYork Sun 		  "tras_min_lsb   Min Active to Precharge Delay Time, LSB");
1113*5614e71bSYork Sun 	PRINT_NXS(23, spd->trc_min_lsb,
1114*5614e71bSYork Sun 		  "trc_min_lsb Min Active to Active/Refresh Delay Time, LSB");
1115*5614e71bSYork Sun 	PRINT_NXS(24, spd->trfc_min_lsb,
1116*5614e71bSYork Sun 		  "trfc_min_lsb   Min Refresh Recovery Delay Time LSB");
1117*5614e71bSYork Sun 	PRINT_NXS(25, spd->trfc_min_msb,
1118*5614e71bSYork Sun 		  "trfc_min_msb   Min Refresh Recovery Delay Time MSB");
1119*5614e71bSYork Sun 	PRINT_NXS(26, spd->twtr_min,
1120*5614e71bSYork Sun 		  "twtr_min Min Internal Write to Read Command Delay Time");
1121*5614e71bSYork Sun 	PRINT_NXS(27, spd->trtp_min,
1122*5614e71bSYork Sun 		  "trtp_min "
1123*5614e71bSYork Sun 		  "Min Internal Read to Precharge Command Delay Time");
1124*5614e71bSYork Sun 	PRINT_NXS(28, spd->tfaw_msb,
1125*5614e71bSYork Sun 		  "tfaw_msb       Upper Nibble for tFAW");
1126*5614e71bSYork Sun 	PRINT_NXS(29, spd->tfaw_min,
1127*5614e71bSYork Sun 		  "tfaw_min       Min Four Activate Window Delay Time");
1128*5614e71bSYork Sun 	PRINT_NXS(30, spd->opt_features,
1129*5614e71bSYork Sun 		"opt_features   SDRAM Optional Features");
1130*5614e71bSYork Sun 	PRINT_NXS(31, spd->therm_ref_opt,
1131*5614e71bSYork Sun 		"therm_ref_opt  SDRAM Thermal and Refresh Opts");
1132*5614e71bSYork Sun 	PRINT_NXS(32, spd->therm_sensor,
1133*5614e71bSYork Sun 		"therm_sensor  SDRAM Thermal Sensor");
1134*5614e71bSYork Sun 	PRINT_NXS(33, spd->device_type,
1135*5614e71bSYork Sun 		"device_type  SDRAM Device Type");
1136*5614e71bSYork Sun 	PRINT_NXS(34, spd->fine_tck_min,
1137*5614e71bSYork Sun 		  "fine_tck_min  Fine offset for tCKmin");
1138*5614e71bSYork Sun 	PRINT_NXS(35, spd->fine_taa_min,
1139*5614e71bSYork Sun 		  "fine_taa_min  Fine offset for tAAmin");
1140*5614e71bSYork Sun 	PRINT_NXS(36, spd->fine_trcd_min,
1141*5614e71bSYork Sun 		  "fine_trcd_min Fine offset for tRCDmin");
1142*5614e71bSYork Sun 	PRINT_NXS(37, spd->fine_trp_min,
1143*5614e71bSYork Sun 		  "fine_trp_min  Fine offset for tRPmin");
1144*5614e71bSYork Sun 	PRINT_NXS(38, spd->fine_trc_min,
1145*5614e71bSYork Sun 		  "fine_trc_min  Fine offset for tRCmin");
1146*5614e71bSYork Sun 
1147*5614e71bSYork Sun 	printf("%-3d-%3d: ",  39, 59);  /* Reserved, General Section */
1148*5614e71bSYork Sun 
1149*5614e71bSYork Sun 	for (i = 39; i <= 59; i++)
1150*5614e71bSYork Sun 		printf("%02x ", spd->res_39_59[i - 39]);
1151*5614e71bSYork Sun 
1152*5614e71bSYork Sun 	puts("\n");
1153*5614e71bSYork Sun 
1154*5614e71bSYork Sun 	switch (spd->module_type) {
1155*5614e71bSYork Sun 	case 0x02:  /* UDIMM */
1156*5614e71bSYork Sun 	case 0x03:  /* SO-DIMM */
1157*5614e71bSYork Sun 	case 0x04:  /* Micro-DIMM */
1158*5614e71bSYork Sun 	case 0x06:  /* Mini-UDIMM */
1159*5614e71bSYork Sun 		PRINT_NXS(60, spd->mod_section.unbuffered.mod_height,
1160*5614e71bSYork Sun 			"mod_height    (Unbuffered) Module Nominal Height");
1161*5614e71bSYork Sun 		PRINT_NXS(61, spd->mod_section.unbuffered.mod_thickness,
1162*5614e71bSYork Sun 			"mod_thickness (Unbuffered) Module Maximum Thickness");
1163*5614e71bSYork Sun 		PRINT_NXS(62, spd->mod_section.unbuffered.ref_raw_card,
1164*5614e71bSYork Sun 			"ref_raw_card  (Unbuffered) Reference Raw Card Used");
1165*5614e71bSYork Sun 		PRINT_NXS(63, spd->mod_section.unbuffered.addr_mapping,
1166*5614e71bSYork Sun 			"addr_mapping  (Unbuffered) Address mapping from "
1167*5614e71bSYork Sun 			"Edge Connector to DRAM");
1168*5614e71bSYork Sun 		break;
1169*5614e71bSYork Sun 	case 0x01:  /* RDIMM */
1170*5614e71bSYork Sun 	case 0x05:  /* Mini-RDIMM */
1171*5614e71bSYork Sun 		PRINT_NXS(60, spd->mod_section.registered.mod_height,
1172*5614e71bSYork Sun 			"mod_height    (Registered) Module Nominal Height");
1173*5614e71bSYork Sun 		PRINT_NXS(61, spd->mod_section.registered.mod_thickness,
1174*5614e71bSYork Sun 			"mod_thickness (Registered) Module Maximum Thickness");
1175*5614e71bSYork Sun 		PRINT_NXS(62, spd->mod_section.registered.ref_raw_card,
1176*5614e71bSYork Sun 			"ref_raw_card  (Registered) Reference Raw Card Used");
1177*5614e71bSYork Sun 		PRINT_NXS(63, spd->mod_section.registered.modu_attr,
1178*5614e71bSYork Sun 			"modu_attr     (Registered) DIMM Module Attributes");
1179*5614e71bSYork Sun 		PRINT_NXS(64, spd->mod_section.registered.thermal,
1180*5614e71bSYork Sun 			"thermal       (Registered) Thermal Heat "
1181*5614e71bSYork Sun 			"Spreader Solution");
1182*5614e71bSYork Sun 		PRINT_NXS(65, spd->mod_section.registered.reg_id_lo,
1183*5614e71bSYork Sun 			"reg_id_lo     (Registered) Register Manufacturer ID "
1184*5614e71bSYork Sun 			"Code, LSB");
1185*5614e71bSYork Sun 		PRINT_NXS(66, spd->mod_section.registered.reg_id_hi,
1186*5614e71bSYork Sun 			"reg_id_hi     (Registered) Register Manufacturer ID "
1187*5614e71bSYork Sun 			"Code, MSB");
1188*5614e71bSYork Sun 		PRINT_NXS(67, spd->mod_section.registered.reg_rev,
1189*5614e71bSYork Sun 			"reg_rev       (Registered) Register "
1190*5614e71bSYork Sun 			"Revision Number");
1191*5614e71bSYork Sun 		PRINT_NXS(68, spd->mod_section.registered.reg_type,
1192*5614e71bSYork Sun 			"reg_type      (Registered) Register Type");
1193*5614e71bSYork Sun 		for (i = 69; i <= 76; i++) {
1194*5614e71bSYork Sun 			printf("%-3d    : %02x rcw[%d]\n", i,
1195*5614e71bSYork Sun 				spd->mod_section.registered.rcw[i-69], i-69);
1196*5614e71bSYork Sun 		}
1197*5614e71bSYork Sun 		break;
1198*5614e71bSYork Sun 	default:
1199*5614e71bSYork Sun 		/* Module-specific Section, Unsupported Module Type */
1200*5614e71bSYork Sun 		printf("%-3d-%3d: ", 60, 116);
1201*5614e71bSYork Sun 
1202*5614e71bSYork Sun 		for (i = 60; i <= 116; i++)
1203*5614e71bSYork Sun 			printf("%02x", spd->mod_section.uc[i - 60]);
1204*5614e71bSYork Sun 
1205*5614e71bSYork Sun 		break;
1206*5614e71bSYork Sun 	}
1207*5614e71bSYork Sun 
1208*5614e71bSYork Sun 	/* Unique Module ID: Bytes 117-125 */
1209*5614e71bSYork Sun 	PRINT_NXS(117, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
1210*5614e71bSYork Sun 	PRINT_NXS(118, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
1211*5614e71bSYork Sun 	PRINT_NXS(119, spd->mloc,     "Mfg Location");
1212*5614e71bSYork Sun 	PRINT_NNXXS(120, 121, spd->mdate[0], spd->mdate[1], "Mfg Date");
1213*5614e71bSYork Sun 
1214*5614e71bSYork Sun 	printf("%-3d-%3d: ", 122, 125);
1215*5614e71bSYork Sun 
1216*5614e71bSYork Sun 	for (i = 122; i <= 125; i++)
1217*5614e71bSYork Sun 		printf("%02x ", spd->sernum[i - 122]);
1218*5614e71bSYork Sun 	printf("   Module Serial Number\n");
1219*5614e71bSYork Sun 
1220*5614e71bSYork Sun 	/* CRC: Bytes 126-127 */
1221*5614e71bSYork Sun 	PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], "  SPD CRC");
1222*5614e71bSYork Sun 
1223*5614e71bSYork Sun 	/* Other Manufacturer Fields and User Space: Bytes 128-255 */
1224*5614e71bSYork Sun 	printf("%-3d-%3d: ", 128, 145);
1225*5614e71bSYork Sun 	for (i = 128; i <= 145; i++)
1226*5614e71bSYork Sun 		printf("%02x ", spd->mpart[i - 128]);
1227*5614e71bSYork Sun 	printf("   Mfg's Module Part Number\n");
1228*5614e71bSYork Sun 
1229*5614e71bSYork Sun 	PRINT_NNXXS(146, 147, spd->mrev[0], spd->mrev[1],
1230*5614e71bSYork Sun 		"Module Revision code");
1231*5614e71bSYork Sun 
1232*5614e71bSYork Sun 	PRINT_NXS(148, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
1233*5614e71bSYork Sun 	PRINT_NXS(149, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
1234*5614e71bSYork Sun 
1235*5614e71bSYork Sun 	printf("%-3d-%3d: ", 150, 175);
1236*5614e71bSYork Sun 	for (i = 150; i <= 175; i++)
1237*5614e71bSYork Sun 		printf("%02x ", spd->msd[i - 150]);
1238*5614e71bSYork Sun 	printf("   Mfg's Specific Data\n");
1239*5614e71bSYork Sun 
1240*5614e71bSYork Sun 	printf("%-3d-%3d: ", 176, 255);
1241*5614e71bSYork Sun 	for (i = 176; i <= 255; i++)
1242*5614e71bSYork Sun 		printf("%02x", spd->cust[i - 176]);
1243*5614e71bSYork Sun 	printf("   Mfg's Specific Data\n");
1244*5614e71bSYork Sun 
1245*5614e71bSYork Sun }
1246*5614e71bSYork Sun #endif
1247*5614e71bSYork Sun 
1248*5614e71bSYork Sun static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
1249*5614e71bSYork Sun {
1250*5614e71bSYork Sun #if defined(CONFIG_SYS_FSL_DDR1)
1251*5614e71bSYork Sun 	ddr1_spd_dump(spd);
1252*5614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR2)
1253*5614e71bSYork Sun 	ddr2_spd_dump(spd);
1254*5614e71bSYork Sun #elif defined(CONFIG_SYS_FSL_DDR3)
1255*5614e71bSYork Sun 	ddr3_spd_dump(spd);
1256*5614e71bSYork Sun #endif
1257*5614e71bSYork Sun }
1258*5614e71bSYork Sun 
1259*5614e71bSYork Sun static void fsl_ddr_printinfo(const fsl_ddr_info_t *pinfo,
1260*5614e71bSYork Sun 			unsigned int ctrl_mask,
1261*5614e71bSYork Sun 			unsigned int dimm_mask,
1262*5614e71bSYork Sun 			unsigned int do_mask)
1263*5614e71bSYork Sun {
1264*5614e71bSYork Sun 	unsigned int i, j, retval;
1265*5614e71bSYork Sun 
1266*5614e71bSYork Sun 	/* STEP 1:  DIMM SPD data */
1267*5614e71bSYork Sun 	if (do_mask & STEP_GET_SPD) {
1268*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1269*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1270*5614e71bSYork Sun 				continue;
1271*5614e71bSYork Sun 
1272*5614e71bSYork Sun 			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
1273*5614e71bSYork Sun 				if (!(dimm_mask & (1 << j)))
1274*5614e71bSYork Sun 					continue;
1275*5614e71bSYork Sun 
1276*5614e71bSYork Sun 				printf("SPD info:  Controller=%u "
1277*5614e71bSYork Sun 						"DIMM=%u\n", i, j);
1278*5614e71bSYork Sun 				generic_spd_dump(
1279*5614e71bSYork Sun 					&(pinfo->spd_installed_dimms[i][j]));
1280*5614e71bSYork Sun 				printf("\n");
1281*5614e71bSYork Sun 			}
1282*5614e71bSYork Sun 			printf("\n");
1283*5614e71bSYork Sun 		}
1284*5614e71bSYork Sun 		printf("\n");
1285*5614e71bSYork Sun 	}
1286*5614e71bSYork Sun 
1287*5614e71bSYork Sun 	/* STEP 2:  DIMM Parameters */
1288*5614e71bSYork Sun 	if (do_mask & STEP_COMPUTE_DIMM_PARMS) {
1289*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1290*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1291*5614e71bSYork Sun 				continue;
1292*5614e71bSYork Sun 			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
1293*5614e71bSYork Sun 				if (!(dimm_mask & (1 << j)))
1294*5614e71bSYork Sun 					continue;
1295*5614e71bSYork Sun 				printf("DIMM parameters:  Controller=%u "
1296*5614e71bSYork Sun 						"DIMM=%u\n", i, j);
1297*5614e71bSYork Sun 				print_dimm_parameters(
1298*5614e71bSYork Sun 					&(pinfo->dimm_params[i][j]));
1299*5614e71bSYork Sun 				printf("\n");
1300*5614e71bSYork Sun 			}
1301*5614e71bSYork Sun 			printf("\n");
1302*5614e71bSYork Sun 		}
1303*5614e71bSYork Sun 		printf("\n");
1304*5614e71bSYork Sun 	}
1305*5614e71bSYork Sun 
1306*5614e71bSYork Sun 	/* STEP 3:  Common Parameters */
1307*5614e71bSYork Sun 	if (do_mask & STEP_COMPUTE_COMMON_PARMS) {
1308*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1309*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1310*5614e71bSYork Sun 				continue;
1311*5614e71bSYork Sun 			printf("\"lowest common\" DIMM parameters:  "
1312*5614e71bSYork Sun 					"Controller=%u\n", i);
1313*5614e71bSYork Sun 			print_lowest_common_dimm_parameters(
1314*5614e71bSYork Sun 				&pinfo->common_timing_params[i]);
1315*5614e71bSYork Sun 			printf("\n");
1316*5614e71bSYork Sun 		}
1317*5614e71bSYork Sun 		printf("\n");
1318*5614e71bSYork Sun 	}
1319*5614e71bSYork Sun 
1320*5614e71bSYork Sun 	/* STEP 4:  User Configuration Options */
1321*5614e71bSYork Sun 	if (do_mask & STEP_GATHER_OPTS) {
1322*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1323*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1324*5614e71bSYork Sun 				continue;
1325*5614e71bSYork Sun 			printf("User Config Options: Controller=%u\n", i);
1326*5614e71bSYork Sun 			print_memctl_options(&pinfo->memctl_opts[i]);
1327*5614e71bSYork Sun 			printf("\n");
1328*5614e71bSYork Sun 		}
1329*5614e71bSYork Sun 		printf("\n");
1330*5614e71bSYork Sun 	}
1331*5614e71bSYork Sun 
1332*5614e71bSYork Sun 	/* STEP 5:  Address assignment */
1333*5614e71bSYork Sun 	if (do_mask & STEP_ASSIGN_ADDRESSES) {
1334*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1335*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1336*5614e71bSYork Sun 				continue;
1337*5614e71bSYork Sun 			for (j = 0; j < CONFIG_DIMM_SLOTS_PER_CTLR; j++) {
1338*5614e71bSYork Sun 				printf("Address Assignment: Controller=%u "
1339*5614e71bSYork Sun 						"DIMM=%u\n", i, j);
1340*5614e71bSYork Sun 				printf("Don't have this functionality yet\n");
1341*5614e71bSYork Sun 			}
1342*5614e71bSYork Sun 			printf("\n");
1343*5614e71bSYork Sun 		}
1344*5614e71bSYork Sun 		printf("\n");
1345*5614e71bSYork Sun 	}
1346*5614e71bSYork Sun 
1347*5614e71bSYork Sun 	/* STEP 6:  computed controller register values */
1348*5614e71bSYork Sun 	if (do_mask & STEP_COMPUTE_REGS) {
1349*5614e71bSYork Sun 		for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
1350*5614e71bSYork Sun 			if (!(ctrl_mask & (1 << i)))
1351*5614e71bSYork Sun 				continue;
1352*5614e71bSYork Sun 			printf("Computed Register Values: Controller=%u\n", i);
1353*5614e71bSYork Sun 			print_fsl_memctl_config_regs(
1354*5614e71bSYork Sun 				&pinfo->fsl_ddr_config_reg[i]);
1355*5614e71bSYork Sun 			retval = check_fsl_memctl_config_regs(
1356*5614e71bSYork Sun 				&pinfo->fsl_ddr_config_reg[i]);
1357*5614e71bSYork Sun 			if (retval) {
1358*5614e71bSYork Sun 				printf("check_fsl_memctl_config_regs "
1359*5614e71bSYork Sun 					"result = %u\n", retval);
1360*5614e71bSYork Sun 			}
1361*5614e71bSYork Sun 			printf("\n");
1362*5614e71bSYork Sun 		}
1363*5614e71bSYork Sun 		printf("\n");
1364*5614e71bSYork Sun 	}
1365*5614e71bSYork Sun }
1366*5614e71bSYork Sun 
1367*5614e71bSYork Sun struct data_strings {
1368*5614e71bSYork Sun 	const char *data_name;
1369*5614e71bSYork Sun 	unsigned int step_mask;
1370*5614e71bSYork Sun 	unsigned int dimm_number_required;
1371*5614e71bSYork Sun };
1372*5614e71bSYork Sun 
1373*5614e71bSYork Sun #define DATA_OPTIONS(name, step, dimm) {#name, step, dimm}
1374*5614e71bSYork Sun 
1375*5614e71bSYork Sun static unsigned int fsl_ddr_parse_interactive_cmd(
1376*5614e71bSYork Sun 	char **argv,
1377*5614e71bSYork Sun 	int argc,
1378*5614e71bSYork Sun 	unsigned int *pstep_mask,
1379*5614e71bSYork Sun 	unsigned int *pctlr_mask,
1380*5614e71bSYork Sun 	unsigned int *pdimm_mask,
1381*5614e71bSYork Sun 	unsigned int *pdimm_number_required
1382*5614e71bSYork Sun 	 ) {
1383*5614e71bSYork Sun 
1384*5614e71bSYork Sun 	static const struct data_strings options[] = {
1385*5614e71bSYork Sun 		DATA_OPTIONS(spd, STEP_GET_SPD, 1),
1386*5614e71bSYork Sun 		DATA_OPTIONS(dimmparms, STEP_COMPUTE_DIMM_PARMS, 1),
1387*5614e71bSYork Sun 		DATA_OPTIONS(commonparms, STEP_COMPUTE_COMMON_PARMS, 0),
1388*5614e71bSYork Sun 		DATA_OPTIONS(opts, STEP_GATHER_OPTS, 0),
1389*5614e71bSYork Sun 		DATA_OPTIONS(addresses, STEP_ASSIGN_ADDRESSES, 0),
1390*5614e71bSYork Sun 		DATA_OPTIONS(regs, STEP_COMPUTE_REGS, 0),
1391*5614e71bSYork Sun 	};
1392*5614e71bSYork Sun 	static const unsigned int n_opts = ARRAY_SIZE(options);
1393*5614e71bSYork Sun 
1394*5614e71bSYork Sun 	unsigned int i, j;
1395*5614e71bSYork Sun 	unsigned int error = 0;
1396*5614e71bSYork Sun 
1397*5614e71bSYork Sun 	for (i = 1; i < argc; i++) {
1398*5614e71bSYork Sun 		unsigned int matched = 0;
1399*5614e71bSYork Sun 
1400*5614e71bSYork Sun 		for (j = 0; j < n_opts; j++) {
1401*5614e71bSYork Sun 			if (strcmp(options[j].data_name, argv[i]) != 0)
1402*5614e71bSYork Sun 				continue;
1403*5614e71bSYork Sun 			*pstep_mask |= options[j].step_mask;
1404*5614e71bSYork Sun 			*pdimm_number_required =
1405*5614e71bSYork Sun 				options[j].dimm_number_required;
1406*5614e71bSYork Sun 			matched = 1;
1407*5614e71bSYork Sun 			break;
1408*5614e71bSYork Sun 		}
1409*5614e71bSYork Sun 
1410*5614e71bSYork Sun 		if (matched)
1411*5614e71bSYork Sun 			continue;
1412*5614e71bSYork Sun 
1413*5614e71bSYork Sun 		if (argv[i][0] == 'c') {
1414*5614e71bSYork Sun 			char c = argv[i][1];
1415*5614e71bSYork Sun 			if (isdigit(c))
1416*5614e71bSYork Sun 				*pctlr_mask |= 1 << (c - '0');
1417*5614e71bSYork Sun 			continue;
1418*5614e71bSYork Sun 		}
1419*5614e71bSYork Sun 
1420*5614e71bSYork Sun 		if (argv[i][0] == 'd') {
1421*5614e71bSYork Sun 			char c = argv[i][1];
1422*5614e71bSYork Sun 			if (isdigit(c))
1423*5614e71bSYork Sun 				*pdimm_mask |= 1 << (c - '0');
1424*5614e71bSYork Sun 			continue;
1425*5614e71bSYork Sun 		}
1426*5614e71bSYork Sun 
1427*5614e71bSYork Sun 		printf("unknown arg %s\n", argv[i]);
1428*5614e71bSYork Sun 		*pstep_mask = 0;
1429*5614e71bSYork Sun 		error = 1;
1430*5614e71bSYork Sun 		break;
1431*5614e71bSYork Sun 	}
1432*5614e71bSYork Sun 
1433*5614e71bSYork Sun 	return error;
1434*5614e71bSYork Sun }
1435*5614e71bSYork Sun 
1436*5614e71bSYork Sun int fsl_ddr_interactive_env_var_exists(void)
1437*5614e71bSYork Sun {
1438*5614e71bSYork Sun 	char buffer[CONFIG_SYS_CBSIZE];
1439*5614e71bSYork Sun 
1440*5614e71bSYork Sun 	if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0)
1441*5614e71bSYork Sun 		return 1;
1442*5614e71bSYork Sun 
1443*5614e71bSYork Sun 	return 0;
1444*5614e71bSYork Sun }
1445*5614e71bSYork Sun 
1446*5614e71bSYork Sun unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set)
1447*5614e71bSYork Sun {
1448*5614e71bSYork Sun 	unsigned long long ddrsize;
1449*5614e71bSYork Sun 	const char *prompt = "FSL DDR>";
1450*5614e71bSYork Sun 	char buffer[CONFIG_SYS_CBSIZE];
1451*5614e71bSYork Sun 	char buffer2[CONFIG_SYS_CBSIZE];
1452*5614e71bSYork Sun 	char *p = NULL;
1453*5614e71bSYork Sun 	char *argv[CONFIG_SYS_MAXARGS + 1];	/* NULL terminated */
1454*5614e71bSYork Sun 	int argc;
1455*5614e71bSYork Sun 	unsigned int next_step = STEP_GET_SPD;
1456*5614e71bSYork Sun 	const char *usage = {
1457*5614e71bSYork Sun 		"commands:\n"
1458*5614e71bSYork Sun 		"print      print SPD and intermediate computed data\n"
1459*5614e71bSYork Sun 		"reset      reboot machine\n"
1460*5614e71bSYork Sun 		"recompute  reload SPD and options to default and recompute regs\n"
1461*5614e71bSYork Sun 		"edit       modify spd, parameter, or option\n"
1462*5614e71bSYork Sun 		"compute    recompute registers from current next_step to end\n"
1463*5614e71bSYork Sun 		"copy       copy parameters\n"
1464*5614e71bSYork Sun 		"next_step  shows current next_step\n"
1465*5614e71bSYork Sun 		"help       this message\n"
1466*5614e71bSYork Sun 		"go         program the memory controller and continue with u-boot\n"
1467*5614e71bSYork Sun 	};
1468*5614e71bSYork Sun 
1469*5614e71bSYork Sun 	if (var_is_set) {
1470*5614e71bSYork Sun 		if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) {
1471*5614e71bSYork Sun 			p = buffer2;
1472*5614e71bSYork Sun 		} else {
1473*5614e71bSYork Sun 			var_is_set = 0;
1474*5614e71bSYork Sun 		}
1475*5614e71bSYork Sun 	}
1476*5614e71bSYork Sun 
1477*5614e71bSYork Sun 	/*
1478*5614e71bSYork Sun 	 * The strategy for next_step is that it points to the next
1479*5614e71bSYork Sun 	 * step in the computation process that needs to be done.
1480*5614e71bSYork Sun 	 */
1481*5614e71bSYork Sun 	while (1) {
1482*5614e71bSYork Sun 		if (var_is_set) {
1483*5614e71bSYork Sun 			char *pend = strchr(p, ';');
1484*5614e71bSYork Sun 			if (pend) {
1485*5614e71bSYork Sun 				/* found command separator, copy sub-command */
1486*5614e71bSYork Sun 				*pend = '\0';
1487*5614e71bSYork Sun 				strcpy(buffer, p);
1488*5614e71bSYork Sun 				p = pend + 1;
1489*5614e71bSYork Sun 			} else {
1490*5614e71bSYork Sun 				/* separator not found, copy whole string */
1491*5614e71bSYork Sun 				strcpy(buffer, p);
1492*5614e71bSYork Sun 				p = NULL;
1493*5614e71bSYork Sun 				var_is_set = 0;
1494*5614e71bSYork Sun 			}
1495*5614e71bSYork Sun 		} else {
1496*5614e71bSYork Sun 			/*
1497*5614e71bSYork Sun 			 * No need to worry for buffer overflow here in
1498*5614e71bSYork Sun 			 * this function;  readline() maxes out at CFG_CBSIZE
1499*5614e71bSYork Sun 			 */
1500*5614e71bSYork Sun 			readline_into_buffer(prompt, buffer, 0);
1501*5614e71bSYork Sun 		}
1502*5614e71bSYork Sun 		argc = parse_line(buffer, argv);
1503*5614e71bSYork Sun 		if (argc == 0)
1504*5614e71bSYork Sun 			continue;
1505*5614e71bSYork Sun 
1506*5614e71bSYork Sun 
1507*5614e71bSYork Sun 		if (strcmp(argv[0], "help") == 0) {
1508*5614e71bSYork Sun 			puts(usage);
1509*5614e71bSYork Sun 			continue;
1510*5614e71bSYork Sun 		}
1511*5614e71bSYork Sun 
1512*5614e71bSYork Sun 		if (strcmp(argv[0], "next_step") == 0) {
1513*5614e71bSYork Sun 			printf("next_step = 0x%02X (%s)\n",
1514*5614e71bSYork Sun 			       next_step,
1515*5614e71bSYork Sun 			       step_to_string(next_step));
1516*5614e71bSYork Sun 			continue;
1517*5614e71bSYork Sun 		}
1518*5614e71bSYork Sun 
1519*5614e71bSYork Sun 		if (strcmp(argv[0], "copy") == 0) {
1520*5614e71bSYork Sun 			unsigned int error = 0;
1521*5614e71bSYork Sun 			unsigned int step_mask = 0;
1522*5614e71bSYork Sun 			unsigned int src_ctlr_mask = 0;
1523*5614e71bSYork Sun 			unsigned int src_dimm_mask = 0;
1524*5614e71bSYork Sun 			unsigned int dimm_number_required = 0;
1525*5614e71bSYork Sun 			unsigned int src_ctlr_num = 0;
1526*5614e71bSYork Sun 			unsigned int src_dimm_num = 0;
1527*5614e71bSYork Sun 			unsigned int dst_ctlr_num = -1;
1528*5614e71bSYork Sun 			unsigned int dst_dimm_num = -1;
1529*5614e71bSYork Sun 			unsigned int i, num_dest_parms;
1530*5614e71bSYork Sun 
1531*5614e71bSYork Sun 			if (argc == 1) {
1532*5614e71bSYork Sun 				printf("copy <src c#> <src d#> <spd|dimmparms|commonparms|opts|addresses|regs> <dst c#> <dst d#>\n");
1533*5614e71bSYork Sun 				continue;
1534*5614e71bSYork Sun 			}
1535*5614e71bSYork Sun 
1536*5614e71bSYork Sun 			error = fsl_ddr_parse_interactive_cmd(
1537*5614e71bSYork Sun 				argv, argc,
1538*5614e71bSYork Sun 				&step_mask,
1539*5614e71bSYork Sun 				&src_ctlr_mask,
1540*5614e71bSYork Sun 				&src_dimm_mask,
1541*5614e71bSYork Sun 				&dimm_number_required
1542*5614e71bSYork Sun 			);
1543*5614e71bSYork Sun 
1544*5614e71bSYork Sun 			/* XXX: only dimm_number_required and step_mask will
1545*5614e71bSYork Sun 			   be used by this function.  Parse the controller and
1546*5614e71bSYork Sun 			   DIMM number separately because it is easier.  */
1547*5614e71bSYork Sun 
1548*5614e71bSYork Sun 			if (error)
1549*5614e71bSYork Sun 				continue;
1550*5614e71bSYork Sun 
1551*5614e71bSYork Sun 			/* parse source destination controller / DIMM */
1552*5614e71bSYork Sun 
1553*5614e71bSYork Sun 			num_dest_parms = dimm_number_required ? 2 : 1;
1554*5614e71bSYork Sun 
1555*5614e71bSYork Sun 			for (i = 0; i < argc; i++) {
1556*5614e71bSYork Sun 				if (argv[i][0] == 'c') {
1557*5614e71bSYork Sun 					char c = argv[i][1];
1558*5614e71bSYork Sun 					if (isdigit(c)) {
1559*5614e71bSYork Sun 						src_ctlr_num = (c - '0');
1560*5614e71bSYork Sun 						break;
1561*5614e71bSYork Sun 					}
1562*5614e71bSYork Sun 				}
1563*5614e71bSYork Sun 			}
1564*5614e71bSYork Sun 
1565*5614e71bSYork Sun 			for (i = 0; i < argc; i++) {
1566*5614e71bSYork Sun 				if (argv[i][0] == 'd') {
1567*5614e71bSYork Sun 					char c = argv[i][1];
1568*5614e71bSYork Sun 					if (isdigit(c)) {
1569*5614e71bSYork Sun 						src_dimm_num = (c - '0');
1570*5614e71bSYork Sun 						break;
1571*5614e71bSYork Sun 					}
1572*5614e71bSYork Sun 				}
1573*5614e71bSYork Sun 			}
1574*5614e71bSYork Sun 
1575*5614e71bSYork Sun 			/* parse destination controller / DIMM */
1576*5614e71bSYork Sun 
1577*5614e71bSYork Sun 			for (i = argc - 1; i >= argc - num_dest_parms; i--) {
1578*5614e71bSYork Sun 				if (argv[i][0] == 'c') {
1579*5614e71bSYork Sun 					char c = argv[i][1];
1580*5614e71bSYork Sun 					if (isdigit(c)) {
1581*5614e71bSYork Sun 						dst_ctlr_num = (c - '0');
1582*5614e71bSYork Sun 						break;
1583*5614e71bSYork Sun 					}
1584*5614e71bSYork Sun 				}
1585*5614e71bSYork Sun 			}
1586*5614e71bSYork Sun 
1587*5614e71bSYork Sun 			for (i = argc - 1; i >= argc - num_dest_parms; i--) {
1588*5614e71bSYork Sun 				if (argv[i][0] == 'd') {
1589*5614e71bSYork Sun 					char c = argv[i][1];
1590*5614e71bSYork Sun 					if (isdigit(c)) {
1591*5614e71bSYork Sun 						dst_dimm_num = (c - '0');
1592*5614e71bSYork Sun 						break;
1593*5614e71bSYork Sun 					}
1594*5614e71bSYork Sun 				}
1595*5614e71bSYork Sun 			}
1596*5614e71bSYork Sun 
1597*5614e71bSYork Sun 			/* TODO: validate inputs */
1598*5614e71bSYork Sun 
1599*5614e71bSYork Sun 			debug("src_ctlr_num = %u, src_dimm_num = %u, dst_ctlr_num = %u, dst_dimm_num = %u, step_mask = %x\n",
1600*5614e71bSYork Sun 				src_ctlr_num, src_dimm_num, dst_ctlr_num, dst_dimm_num, step_mask);
1601*5614e71bSYork Sun 
1602*5614e71bSYork Sun 
1603*5614e71bSYork Sun 			switch (step_mask) {
1604*5614e71bSYork Sun 
1605*5614e71bSYork Sun 			case STEP_GET_SPD:
1606*5614e71bSYork Sun 				memcpy(&(pinfo->spd_installed_dimms[dst_ctlr_num][dst_dimm_num]),
1607*5614e71bSYork Sun 					&(pinfo->spd_installed_dimms[src_ctlr_num][src_dimm_num]),
1608*5614e71bSYork Sun 					sizeof(pinfo->spd_installed_dimms[0][0]));
1609*5614e71bSYork Sun 				break;
1610*5614e71bSYork Sun 
1611*5614e71bSYork Sun 			case STEP_COMPUTE_DIMM_PARMS:
1612*5614e71bSYork Sun 				memcpy(&(pinfo->dimm_params[dst_ctlr_num][dst_dimm_num]),
1613*5614e71bSYork Sun 					&(pinfo->dimm_params[src_ctlr_num][src_dimm_num]),
1614*5614e71bSYork Sun 					sizeof(pinfo->dimm_params[0][0]));
1615*5614e71bSYork Sun 				break;
1616*5614e71bSYork Sun 
1617*5614e71bSYork Sun 			case STEP_COMPUTE_COMMON_PARMS:
1618*5614e71bSYork Sun 				memcpy(&(pinfo->common_timing_params[dst_ctlr_num]),
1619*5614e71bSYork Sun 					&(pinfo->common_timing_params[src_ctlr_num]),
1620*5614e71bSYork Sun 					sizeof(pinfo->common_timing_params[0]));
1621*5614e71bSYork Sun 				break;
1622*5614e71bSYork Sun 
1623*5614e71bSYork Sun 			case STEP_GATHER_OPTS:
1624*5614e71bSYork Sun 				memcpy(&(pinfo->memctl_opts[dst_ctlr_num]),
1625*5614e71bSYork Sun 					&(pinfo->memctl_opts[src_ctlr_num]),
1626*5614e71bSYork Sun 					sizeof(pinfo->memctl_opts[0]));
1627*5614e71bSYork Sun 				break;
1628*5614e71bSYork Sun 
1629*5614e71bSYork Sun 			/* someday be able to have addresses to copy addresses... */
1630*5614e71bSYork Sun 
1631*5614e71bSYork Sun 			case STEP_COMPUTE_REGS:
1632*5614e71bSYork Sun 				memcpy(&(pinfo->fsl_ddr_config_reg[dst_ctlr_num]),
1633*5614e71bSYork Sun 					&(pinfo->fsl_ddr_config_reg[src_ctlr_num]),
1634*5614e71bSYork Sun 					sizeof(pinfo->memctl_opts[0]));
1635*5614e71bSYork Sun 				break;
1636*5614e71bSYork Sun 
1637*5614e71bSYork Sun 			default:
1638*5614e71bSYork Sun 				printf("unexpected step_mask value\n");
1639*5614e71bSYork Sun 			}
1640*5614e71bSYork Sun 
1641*5614e71bSYork Sun 			continue;
1642*5614e71bSYork Sun 
1643*5614e71bSYork Sun 		}
1644*5614e71bSYork Sun 
1645*5614e71bSYork Sun 		if (strcmp(argv[0], "edit") == 0) {
1646*5614e71bSYork Sun 			unsigned int error = 0;
1647*5614e71bSYork Sun 			unsigned int step_mask = 0;
1648*5614e71bSYork Sun 			unsigned int ctlr_mask = 0;
1649*5614e71bSYork Sun 			unsigned int dimm_mask = 0;
1650*5614e71bSYork Sun 			char *p_element = NULL;
1651*5614e71bSYork Sun 			char *p_value = NULL;
1652*5614e71bSYork Sun 			unsigned int dimm_number_required = 0;
1653*5614e71bSYork Sun 			unsigned int ctrl_num;
1654*5614e71bSYork Sun 			unsigned int dimm_num;
1655*5614e71bSYork Sun 
1656*5614e71bSYork Sun 			if (argc == 1) {
1657*5614e71bSYork Sun 				/* Only the element and value must be last */
1658*5614e71bSYork Sun 				printf("edit <c#> <d#> "
1659*5614e71bSYork Sun 					"<spd|dimmparms|commonparms|opts|"
1660*5614e71bSYork Sun 					"addresses|regs> <element> <value>\n");
1661*5614e71bSYork Sun 				printf("for spd, specify byte number for "
1662*5614e71bSYork Sun 					"element\n");
1663*5614e71bSYork Sun 				continue;
1664*5614e71bSYork Sun 			}
1665*5614e71bSYork Sun 
1666*5614e71bSYork Sun 			error = fsl_ddr_parse_interactive_cmd(
1667*5614e71bSYork Sun 				argv, argc - 2,
1668*5614e71bSYork Sun 				&step_mask,
1669*5614e71bSYork Sun 				&ctlr_mask,
1670*5614e71bSYork Sun 				&dimm_mask,
1671*5614e71bSYork Sun 				&dimm_number_required
1672*5614e71bSYork Sun 			);
1673*5614e71bSYork Sun 
1674*5614e71bSYork Sun 			if (error)
1675*5614e71bSYork Sun 				continue;
1676*5614e71bSYork Sun 
1677*5614e71bSYork Sun 
1678*5614e71bSYork Sun 			/* Check arguments */
1679*5614e71bSYork Sun 
1680*5614e71bSYork Sun 			/* ERROR: If no steps were found */
1681*5614e71bSYork Sun 			if (step_mask == 0) {
1682*5614e71bSYork Sun 				printf("Error: No valid steps were specified "
1683*5614e71bSYork Sun 						"in argument.\n");
1684*5614e71bSYork Sun 				continue;
1685*5614e71bSYork Sun 			}
1686*5614e71bSYork Sun 
1687*5614e71bSYork Sun 			/* ERROR: If multiple steps were found */
1688*5614e71bSYork Sun 			if (step_mask & (step_mask - 1)) {
1689*5614e71bSYork Sun 				printf("Error: Multiple steps specified in "
1690*5614e71bSYork Sun 						"argument.\n");
1691*5614e71bSYork Sun 				continue;
1692*5614e71bSYork Sun 			}
1693*5614e71bSYork Sun 
1694*5614e71bSYork Sun 			/* ERROR: Controller not specified */
1695*5614e71bSYork Sun 			if (ctlr_mask == 0) {
1696*5614e71bSYork Sun 				printf("Error: controller number not "
1697*5614e71bSYork Sun 					"specified or no element and "
1698*5614e71bSYork Sun 					"value specified\n");
1699*5614e71bSYork Sun 				continue;
1700*5614e71bSYork Sun 			}
1701*5614e71bSYork Sun 
1702*5614e71bSYork Sun 			if (ctlr_mask & (ctlr_mask - 1)) {
1703*5614e71bSYork Sun 				printf("Error: multiple controllers "
1704*5614e71bSYork Sun 						"specified, %X\n", ctlr_mask);
1705*5614e71bSYork Sun 				continue;
1706*5614e71bSYork Sun 			}
1707*5614e71bSYork Sun 
1708*5614e71bSYork Sun 			/* ERROR: DIMM number not specified */
1709*5614e71bSYork Sun 			if (dimm_number_required && dimm_mask == 0) {
1710*5614e71bSYork Sun 				printf("Error: DIMM number number not "
1711*5614e71bSYork Sun 					"specified or no element and "
1712*5614e71bSYork Sun 					"value specified\n");
1713*5614e71bSYork Sun 				continue;
1714*5614e71bSYork Sun 			}
1715*5614e71bSYork Sun 
1716*5614e71bSYork Sun 			if (dimm_mask & (dimm_mask - 1)) {
1717*5614e71bSYork Sun 				printf("Error: multipled DIMMs specified\n");
1718*5614e71bSYork Sun 				continue;
1719*5614e71bSYork Sun 			}
1720*5614e71bSYork Sun 
1721*5614e71bSYork Sun 			p_element = argv[argc - 2];
1722*5614e71bSYork Sun 			p_value = argv[argc - 1];
1723*5614e71bSYork Sun 
1724*5614e71bSYork Sun 			ctrl_num = __ilog2(ctlr_mask);
1725*5614e71bSYork Sun 			dimm_num = __ilog2(dimm_mask);
1726*5614e71bSYork Sun 
1727*5614e71bSYork Sun 			switch (step_mask) {
1728*5614e71bSYork Sun 			case STEP_GET_SPD:
1729*5614e71bSYork Sun 				{
1730*5614e71bSYork Sun 					unsigned int element_num;
1731*5614e71bSYork Sun 					unsigned int value;
1732*5614e71bSYork Sun 
1733*5614e71bSYork Sun 					element_num = simple_strtoul(p_element,
1734*5614e71bSYork Sun 								     NULL, 0);
1735*5614e71bSYork Sun 					value = simple_strtoul(p_value,
1736*5614e71bSYork Sun 							       NULL, 0);
1737*5614e71bSYork Sun 					fsl_ddr_spd_edit(pinfo,
1738*5614e71bSYork Sun 							       ctrl_num,
1739*5614e71bSYork Sun 							       dimm_num,
1740*5614e71bSYork Sun 							       element_num,
1741*5614e71bSYork Sun 							       value);
1742*5614e71bSYork Sun 					next_step = STEP_COMPUTE_DIMM_PARMS;
1743*5614e71bSYork Sun 				}
1744*5614e71bSYork Sun 				break;
1745*5614e71bSYork Sun 
1746*5614e71bSYork Sun 			case STEP_COMPUTE_DIMM_PARMS:
1747*5614e71bSYork Sun 				fsl_ddr_dimm_parameters_edit(
1748*5614e71bSYork Sun 						 pinfo, ctrl_num, dimm_num,
1749*5614e71bSYork Sun 						 p_element, p_value);
1750*5614e71bSYork Sun 				next_step = STEP_COMPUTE_COMMON_PARMS;
1751*5614e71bSYork Sun 				break;
1752*5614e71bSYork Sun 
1753*5614e71bSYork Sun 			case STEP_COMPUTE_COMMON_PARMS:
1754*5614e71bSYork Sun 				lowest_common_dimm_parameters_edit(pinfo,
1755*5614e71bSYork Sun 						ctrl_num, p_element, p_value);
1756*5614e71bSYork Sun 				next_step = STEP_GATHER_OPTS;
1757*5614e71bSYork Sun 				break;
1758*5614e71bSYork Sun 
1759*5614e71bSYork Sun 			case STEP_GATHER_OPTS:
1760*5614e71bSYork Sun 				fsl_ddr_options_edit(pinfo, ctrl_num,
1761*5614e71bSYork Sun 							   p_element, p_value);
1762*5614e71bSYork Sun 				next_step = STEP_ASSIGN_ADDRESSES;
1763*5614e71bSYork Sun 				break;
1764*5614e71bSYork Sun 
1765*5614e71bSYork Sun 			case STEP_ASSIGN_ADDRESSES:
1766*5614e71bSYork Sun 				printf("editing of address assignment "
1767*5614e71bSYork Sun 						"not yet implemented\n");
1768*5614e71bSYork Sun 				break;
1769*5614e71bSYork Sun 
1770*5614e71bSYork Sun 			case STEP_COMPUTE_REGS:
1771*5614e71bSYork Sun 				{
1772*5614e71bSYork Sun 					fsl_ddr_regs_edit(pinfo,
1773*5614e71bSYork Sun 								ctrl_num,
1774*5614e71bSYork Sun 								p_element,
1775*5614e71bSYork Sun 								p_value);
1776*5614e71bSYork Sun 					next_step = STEP_PROGRAM_REGS;
1777*5614e71bSYork Sun 				}
1778*5614e71bSYork Sun 				break;
1779*5614e71bSYork Sun 
1780*5614e71bSYork Sun 			default:
1781*5614e71bSYork Sun 				printf("programming error\n");
1782*5614e71bSYork Sun 				while (1)
1783*5614e71bSYork Sun 					;
1784*5614e71bSYork Sun 				break;
1785*5614e71bSYork Sun 			}
1786*5614e71bSYork Sun 			continue;
1787*5614e71bSYork Sun 		}
1788*5614e71bSYork Sun 
1789*5614e71bSYork Sun 		if (strcmp(argv[0], "reset") == 0) {
1790*5614e71bSYork Sun 			/*
1791*5614e71bSYork Sun 			 * Reboot machine.
1792*5614e71bSYork Sun 			 * Args don't seem to matter because this
1793*5614e71bSYork Sun 			 * doesn't return
1794*5614e71bSYork Sun 			 */
1795*5614e71bSYork Sun 			do_reset(NULL, 0, 0, NULL);
1796*5614e71bSYork Sun 			printf("Reset didn't work\n");
1797*5614e71bSYork Sun 		}
1798*5614e71bSYork Sun 
1799*5614e71bSYork Sun 		if (strcmp(argv[0], "recompute") == 0) {
1800*5614e71bSYork Sun 			/*
1801*5614e71bSYork Sun 			 * Recalculate everything, starting with
1802*5614e71bSYork Sun 			 * loading SPD EEPROM from DIMMs
1803*5614e71bSYork Sun 			 */
1804*5614e71bSYork Sun 			next_step = STEP_GET_SPD;
1805*5614e71bSYork Sun 			ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
1806*5614e71bSYork Sun 			continue;
1807*5614e71bSYork Sun 		}
1808*5614e71bSYork Sun 
1809*5614e71bSYork Sun 		if (strcmp(argv[0], "compute") == 0) {
1810*5614e71bSYork Sun 			/*
1811*5614e71bSYork Sun 			 * Compute rest of steps starting at
1812*5614e71bSYork Sun 			 * the current next_step/
1813*5614e71bSYork Sun 			 */
1814*5614e71bSYork Sun 			ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
1815*5614e71bSYork Sun 			continue;
1816*5614e71bSYork Sun 		}
1817*5614e71bSYork Sun 
1818*5614e71bSYork Sun 		if (strcmp(argv[0], "print") == 0) {
1819*5614e71bSYork Sun 			unsigned int error = 0;
1820*5614e71bSYork Sun 			unsigned int step_mask = 0;
1821*5614e71bSYork Sun 			unsigned int ctlr_mask = 0;
1822*5614e71bSYork Sun 			unsigned int dimm_mask = 0;
1823*5614e71bSYork Sun 			unsigned int dimm_number_required = 0;
1824*5614e71bSYork Sun 
1825*5614e71bSYork Sun 			if (argc == 1) {
1826*5614e71bSYork Sun 				printf("print [c<n>] [d<n>] [spd] [dimmparms] "
1827*5614e71bSYork Sun 				  "[commonparms] [opts] [addresses] [regs]\n");
1828*5614e71bSYork Sun 				continue;
1829*5614e71bSYork Sun 			}
1830*5614e71bSYork Sun 
1831*5614e71bSYork Sun 			error = fsl_ddr_parse_interactive_cmd(
1832*5614e71bSYork Sun 				argv, argc,
1833*5614e71bSYork Sun 				&step_mask,
1834*5614e71bSYork Sun 				&ctlr_mask,
1835*5614e71bSYork Sun 				&dimm_mask,
1836*5614e71bSYork Sun 				&dimm_number_required
1837*5614e71bSYork Sun 			);
1838*5614e71bSYork Sun 
1839*5614e71bSYork Sun 			if (error)
1840*5614e71bSYork Sun 				continue;
1841*5614e71bSYork Sun 
1842*5614e71bSYork Sun 			/* If no particular controller was found, print all */
1843*5614e71bSYork Sun 			if (ctlr_mask == 0)
1844*5614e71bSYork Sun 				ctlr_mask = 0xFF;
1845*5614e71bSYork Sun 
1846*5614e71bSYork Sun 			/* If no particular dimm was found, print all dimms. */
1847*5614e71bSYork Sun 			if (dimm_mask == 0)
1848*5614e71bSYork Sun 				dimm_mask = 0xFF;
1849*5614e71bSYork Sun 
1850*5614e71bSYork Sun 			/* If no steps were found, print all steps. */
1851*5614e71bSYork Sun 			if (step_mask == 0)
1852*5614e71bSYork Sun 				step_mask = STEP_ALL;
1853*5614e71bSYork Sun 
1854*5614e71bSYork Sun 			fsl_ddr_printinfo(pinfo, ctlr_mask,
1855*5614e71bSYork Sun 						dimm_mask, step_mask);
1856*5614e71bSYork Sun 			continue;
1857*5614e71bSYork Sun 		}
1858*5614e71bSYork Sun 
1859*5614e71bSYork Sun 		if (strcmp(argv[0], "go") == 0) {
1860*5614e71bSYork Sun 			if (next_step)
1861*5614e71bSYork Sun 				ddrsize = fsl_ddr_compute(pinfo, next_step, 0);
1862*5614e71bSYork Sun 			break;
1863*5614e71bSYork Sun 		}
1864*5614e71bSYork Sun 
1865*5614e71bSYork Sun 		printf("unknown command %s\n", argv[0]);
1866*5614e71bSYork Sun 	}
1867*5614e71bSYork Sun 
1868*5614e71bSYork Sun 	debug("end of memory = %llu\n", (u64)ddrsize);
1869*5614e71bSYork Sun 
1870*5614e71bSYork Sun 	return ddrsize;
1871*5614e71bSYork Sun }
1872