xref: /openbmc/u-boot/board/freescale/mpc8572ds/ddr.c (revision 939e5bf9)
1129ba616SKumar Gala /*
2129ba616SKumar Gala  * Copyright 2008 Freescale Semiconductor, Inc.
3129ba616SKumar Gala  *
4129ba616SKumar Gala  * This program is free software; you can redistribute it and/or
5129ba616SKumar Gala  * modify it under the terms of the GNU General Public License
6129ba616SKumar Gala  * Version 2 as published by the Free Software Foundation.
7129ba616SKumar Gala  */
8129ba616SKumar Gala 
9129ba616SKumar Gala #include <common.h>
10129ba616SKumar Gala 
11129ba616SKumar Gala #include <asm/fsl_ddr_sdram.h>
12dfb49108SHaiying Wang #include <asm/fsl_ddr_dimm_params.h>
13129ba616SKumar Gala 
144ca06607SHaiying Wang typedef struct {
154ca06607SHaiying Wang 	u32 datarate_mhz_low;
164ca06607SHaiying Wang 	u32 datarate_mhz_high;
174ca06607SHaiying Wang 	u32 n_ranks;
184ca06607SHaiying Wang 	u32 clk_adjust;
194ca06607SHaiying Wang 	u32 cpo;
204ca06607SHaiying Wang 	u32 write_data_delay;
214ca06607SHaiying Wang 	u32 force_2T;
224ca06607SHaiying Wang } board_specific_parameters_t;
234ca06607SHaiying Wang 
24634bc554SYork Sun /*
25634bc554SYork Sun  * CPO value doesn't matter if workaround for errata 111 and 134 enabled.
26634bc554SYork Sun  *
27634bc554SYork Sun  * For DDR2 DIMM, all combinations of clk_adjust and write_data_delay have been
28634bc554SYork Sun  * tested. For RDIMM, clk_adjust = 4 and write_data_delay = 3 is optimized for
29634bc554SYork Sun  * all clocks from 400MT/s to 800MT/s, verified with Kingston KVR800D2D8P6/2G.
30634bc554SYork Sun  * For UDIMM, clk_adjust = 8 and write_delay = 5 is optimized for all clocks
31634bc554SYork Sun  * from 400MT/s to 800MT/s, verified with Micron MT18HTF25672AY-800E1.
324ca06607SHaiying Wang  */
33634bc554SYork Sun const board_specific_parameters_t board_specific_parameters_udimm[][20] = {
344ca06607SHaiying Wang 	{
35634bc554SYork Sun 	/*
36634bc554SYork Sun 	 *	memory controller 0
37634bc554SYork Sun 	 *	  lo|  hi|  num|  clk| cpo|wrdata|2T
38634bc554SYork Sun 	 *	 mhz| mhz|ranks|adjst|    | delay|
39634bc554SYork Sun 	 */
40634bc554SYork Sun 		{  0, 333,    2,    8,   7,    5,  0},
41634bc554SYork Sun 		{334, 400,    2,    8,   9,    5,  0},
42634bc554SYork Sun 		{401, 549,    2,    8,  11,    5,  0},
43634bc554SYork Sun 		{550, 680,    2,    8,  10,    5,  0},
44634bc554SYork Sun 		{681, 850,    2,    8,  12,    5,  1},
454ca06607SHaiying Wang 		{  0, 333,    1,    6,   7,    3,  0},
464ca06607SHaiying Wang 		{334, 400,    1,    6,   9,    3,  0},
474ca06607SHaiying Wang 		{401, 549,    1,    6,  11,    3,  0},
484ca06607SHaiying Wang 		{550, 680,    1,    1,  10,    5,  0},
494ca06607SHaiying Wang 		{681, 850,    1,    1,  12,    5,  0}
504ca06607SHaiying Wang 	},
514ca06607SHaiying Wang 
524ca06607SHaiying Wang 	{
53634bc554SYork Sun 	/*
54634bc554SYork Sun 	 *	memory controller 1
55634bc554SYork Sun 	 *	  lo|  hi|  num|  clk| cpo|wrdata|2T
56634bc554SYork Sun 	 *	 mhz| mhz|ranks|adjst|    | delay|
57634bc554SYork Sun 	 */
58634bc554SYork Sun 		{  0, 333,    2,     8,  7,    5,  0},
59634bc554SYork Sun 		{334, 400,    2,     8,  9,    5,  0},
60634bc554SYork Sun 		{401, 549,    2,     8, 11,    5,  0},
61634bc554SYork Sun 		{550, 680,    2,     8, 11,    5,  0},
62634bc554SYork Sun 		{681, 850,    2,     8, 13,    5,  1},
634ca06607SHaiying Wang 		{  0, 333,    1,     6,  7,    3,  0},
644ca06607SHaiying Wang 		{334, 400,    1,     6,  9,    3,  0},
654ca06607SHaiying Wang 		{401, 549,    1,     6, 11,    3,  0},
664ca06607SHaiying Wang 		{550, 680,    1,     1, 11,    6,  0},
674ca06607SHaiying Wang 		{681, 850,    1,     1, 13,    6,  0}
684ca06607SHaiying Wang 	}
694ca06607SHaiying Wang };
704ca06607SHaiying Wang 
71634bc554SYork Sun const board_specific_parameters_t board_specific_parameters_rdimm[][20] = {
72634bc554SYork Sun 	{
73634bc554SYork Sun 	/*
74634bc554SYork Sun 	 *	memory controller 0
75634bc554SYork Sun 	 *	  lo|  hi|  num|  clk| cpo|wrdata|2T
76634bc554SYork Sun 	 *	 mhz| mhz|ranks|adjst|    | delay|
77634bc554SYork Sun 	 */
78634bc554SYork Sun 		{  0, 333,    2,    4,   7,    3,  0},
79634bc554SYork Sun 		{334, 400,    2,    4,   9,    3,  0},
80634bc554SYork Sun 		{401, 549,    2,    4,  11,    3,  0},
81634bc554SYork Sun 		{550, 680,    2,    4,  10,    3,  0},
82634bc554SYork Sun 		{681, 850,    2,    4,  12,    3,  1},
83634bc554SYork Sun 	},
84634bc554SYork Sun 
85634bc554SYork Sun 	{
86634bc554SYork Sun 	/*
87634bc554SYork Sun 	 *	memory controller 1
88634bc554SYork Sun 	 *	  lo|  hi|  num|  clk| cpo|wrdata|2T
89634bc554SYork Sun 	 *	 mhz| mhz|ranks|adjst|    | delay|
90634bc554SYork Sun 	 */
91634bc554SYork Sun 		{  0, 333,    2,     4,  7,    3,  0},
92634bc554SYork Sun 		{334, 400,    2,     4,  9,    3,  0},
93634bc554SYork Sun 		{401, 549,    2,     4, 11,    3,  0},
94634bc554SYork Sun 		{550, 680,    2,     4, 11,    3,  0},
95634bc554SYork Sun 		{681, 850,    2,     4, 13,    3,  1},
96634bc554SYork Sun 	}
97634bc554SYork Sun };
98634bc554SYork Sun 
99dfb49108SHaiying Wang void fsl_ddr_board_options(memctl_options_t *popts,
100dfb49108SHaiying Wang 				dimm_params_t *pdimm,
101dfb49108SHaiying Wang 				unsigned int ctrl_num)
102129ba616SKumar Gala {
103634bc554SYork Sun 	const board_specific_parameters_t *pbsp;
104634bc554SYork Sun 	u32 num_params;
1054ca06607SHaiying Wang 	u32 i;
1064ca06607SHaiying Wang 	ulong ddr_freq;
107634bc554SYork Sun 
108634bc554SYork Sun 	if (!pdimm->n_ranks)
109634bc554SYork Sun 		return;
110634bc554SYork Sun 
111634bc554SYork Sun 	if (popts->registered_dimm_en) {
112634bc554SYork Sun 		pbsp = &(board_specific_parameters_rdimm[ctrl_num][0]);
113634bc554SYork Sun 		num_params = sizeof(board_specific_parameters_rdimm[ctrl_num]) /
114634bc554SYork Sun 				sizeof(board_specific_parameters_rdimm[0][0]);
115634bc554SYork Sun 	} else {
116634bc554SYork Sun 		pbsp = &(board_specific_parameters_udimm[ctrl_num][0]);
117634bc554SYork Sun 		num_params = sizeof(board_specific_parameters_udimm[ctrl_num]) /
118634bc554SYork Sun 				sizeof(board_specific_parameters_udimm[0][0]);
119634bc554SYork Sun 	}
120129ba616SKumar Gala 
1214ca06607SHaiying Wang 	/* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in
1224ca06607SHaiying Wang 	 * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If
1234ca06607SHaiying Wang 	 * there are two dimms in the controller, set odt_rd_cfg to 3 and
1244ca06607SHaiying Wang 	 * odt_wr_cfg to 3 for the even CS, 0 for the odd CS.
125129ba616SKumar Gala 	 */
1264ca06607SHaiying Wang 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
1274ca06607SHaiying Wang 		if (i&1) {	/* odd CS */
1284ca06607SHaiying Wang 			popts->cs_local_opts[i].odt_rd_cfg = 0;
1294ca06607SHaiying Wang 			popts->cs_local_opts[i].odt_wr_cfg = 0;
1304ca06607SHaiying Wang 		} else {	/* even CS */
1314ca06607SHaiying Wang 			if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
1324ca06607SHaiying Wang 				popts->cs_local_opts[i].odt_rd_cfg = 0;
1334ca06607SHaiying Wang 				popts->cs_local_opts[i].odt_wr_cfg = 4;
1344ca06607SHaiying Wang 			} else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
1354ca06607SHaiying Wang 			popts->cs_local_opts[i].odt_rd_cfg = 3;
1364ca06607SHaiying Wang 			popts->cs_local_opts[i].odt_wr_cfg = 3;
1374ca06607SHaiying Wang 			}
1384ca06607SHaiying Wang 		}
1394ca06607SHaiying Wang 	}
140129ba616SKumar Gala 
1414ca06607SHaiying Wang 	/* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
1424ca06607SHaiying Wang 	 * freqency and n_banks specified in board_specific_parameters table.
143129ba616SKumar Gala 	 */
1444ca06607SHaiying Wang 	ddr_freq = get_ddr_freq(0) / 1000000;
1454ca06607SHaiying Wang 	for (i = 0; i < num_params; i++) {
1464ca06607SHaiying Wang 		if (ddr_freq >= pbsp->datarate_mhz_low &&
1474ca06607SHaiying Wang 		    ddr_freq <= pbsp->datarate_mhz_high &&
1484ca06607SHaiying Wang 		    pdimm->n_ranks == pbsp->n_ranks) {
1494ca06607SHaiying Wang 			popts->clk_adjust = pbsp->clk_adjust;
1504ca06607SHaiying Wang 			popts->cpo_override = pbsp->cpo;
1514ca06607SHaiying Wang 			popts->write_data_delay = pbsp->write_data_delay;
1524ca06607SHaiying Wang 			popts->twoT_en = pbsp->force_2T;
153634bc554SYork Sun 			break;
1544ca06607SHaiying Wang 		}
1554ca06607SHaiying Wang 		pbsp++;
1564ca06607SHaiying Wang 	}
157129ba616SKumar Gala 
158*939e5bf9SYork Sun 	if (i == num_params) {
159*939e5bf9SYork Sun 		printf("Warning: board specific timing not found "
160*939e5bf9SYork Sun 			"for data rate %lu MT/s!\n", ddr_freq);
161*939e5bf9SYork Sun 	}
162634bc554SYork Sun 
163129ba616SKumar Gala 	/*
164129ba616SKumar Gala 	 * Factors to consider for half-strength driver enable:
165129ba616SKumar Gala 	 *	- number of DIMMs installed
166129ba616SKumar Gala 	 */
167129ba616SKumar Gala 	popts->half_strength_driver_enable = 0;
168129ba616SKumar Gala }
169