powerpc/8xxx: Replace fsl_ddr_get_mem_data_rate with get_ddr_freq()
[platform/kernel/u-boot.git] / board / freescale / mpc8572ds / ddr.c
1 /*
2  * Copyright 2008 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * Version 2 as published by the Free Software Foundation.
7  */
8
9 #include <common.h>
10 #include <i2c.h>
11
12 #include <asm/fsl_ddr_sdram.h>
13 #include <asm/fsl_ddr_dimm_params.h>
14
15 static void get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address)
16 {
17         i2c_read(i2c_address, 0, 1, (uchar *)spd, sizeof(ddr2_spd_eeprom_t));
18 }
19
20 void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd,
21                       unsigned int ctrl_num)
22 {
23         unsigned int i;
24         unsigned int i2c_address = 0;
25
26         for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) {
27                 if (ctrl_num == 0 && i == 0) {
28                         i2c_address = SPD_EEPROM_ADDRESS1;
29                 }
30                 if (ctrl_num == 1 && i == 0) {
31                         i2c_address = SPD_EEPROM_ADDRESS2;
32                 }
33                 get_spd(&(ctrl_dimms_spd[i]), i2c_address);
34         }
35 }
36
37 typedef struct {
38         u32 datarate_mhz_low;
39         u32 datarate_mhz_high;
40         u32 n_ranks;
41         u32 clk_adjust;
42         u32 cpo;
43         u32 write_data_delay;
44         u32 force_2T;
45 } board_specific_parameters_t;
46
47 /*
48  * CPO value doesn't matter if workaround for errata 111 and 134 enabled.
49  *
50  * For DDR2 DIMM, all combinations of clk_adjust and write_data_delay have been
51  * tested. For RDIMM, clk_adjust = 4 and write_data_delay = 3 is optimized for
52  * all clocks from 400MT/s to 800MT/s, verified with Kingston KVR800D2D8P6/2G.
53  * For UDIMM, clk_adjust = 8 and write_delay = 5 is optimized for all clocks
54  * from 400MT/s to 800MT/s, verified with Micron MT18HTF25672AY-800E1.
55  */
56 const board_specific_parameters_t board_specific_parameters_udimm[][20] = {
57         {
58         /*
59          *      memory controller 0
60          *        lo|  hi|  num|  clk| cpo|wrdata|2T
61          *       mhz| mhz|ranks|adjst|    | delay|
62          */
63                 {  0, 333,    2,    8,   7,    5,  0},
64                 {334, 400,    2,    8,   9,    5,  0},
65                 {401, 549,    2,    8,  11,    5,  0},
66                 {550, 680,    2,    8,  10,    5,  0},
67                 {681, 850,    2,    8,  12,    5,  1},
68                 {  0, 333,    1,    6,   7,    3,  0},
69                 {334, 400,    1,    6,   9,    3,  0},
70                 {401, 549,    1,    6,  11,    3,  0},
71                 {550, 680,    1,    1,  10,    5,  0},
72                 {681, 850,    1,    1,  12,    5,  0}
73         },
74
75         {
76         /*
77          *      memory controller 1
78          *        lo|  hi|  num|  clk| cpo|wrdata|2T
79          *       mhz| mhz|ranks|adjst|    | delay|
80          */
81                 {  0, 333,    2,     8,  7,    5,  0},
82                 {334, 400,    2,     8,  9,    5,  0},
83                 {401, 549,    2,     8, 11,    5,  0},
84                 {550, 680,    2,     8, 11,    5,  0},
85                 {681, 850,    2,     8, 13,    5,  1},
86                 {  0, 333,    1,     6,  7,    3,  0},
87                 {334, 400,    1,     6,  9,    3,  0},
88                 {401, 549,    1,     6, 11,    3,  0},
89                 {550, 680,    1,     1, 11,    6,  0},
90                 {681, 850,    1,     1, 13,    6,  0}
91         }
92 };
93
94 const board_specific_parameters_t board_specific_parameters_rdimm[][20] = {
95         {
96         /*
97          *      memory controller 0
98          *        lo|  hi|  num|  clk| cpo|wrdata|2T
99          *       mhz| mhz|ranks|adjst|    | delay|
100          */
101                 {  0, 333,    2,    4,   7,    3,  0},
102                 {334, 400,    2,    4,   9,    3,  0},
103                 {401, 549,    2,    4,  11,    3,  0},
104                 {550, 680,    2,    4,  10,    3,  0},
105                 {681, 850,    2,    4,  12,    3,  1},
106         },
107
108         {
109         /*
110          *      memory controller 1
111          *        lo|  hi|  num|  clk| cpo|wrdata|2T
112          *       mhz| mhz|ranks|adjst|    | delay|
113          */
114                 {  0, 333,    2,     4,  7,    3,  0},
115                 {334, 400,    2,     4,  9,    3,  0},
116                 {401, 549,    2,     4, 11,    3,  0},
117                 {550, 680,    2,     4, 11,    3,  0},
118                 {681, 850,    2,     4, 13,    3,  1},
119         }
120 };
121
122 void fsl_ddr_board_options(memctl_options_t *popts,
123                                 dimm_params_t *pdimm,
124                                 unsigned int ctrl_num)
125 {
126         const board_specific_parameters_t *pbsp;
127         u32 num_params;
128         u32 i;
129         ulong ddr_freq;
130         int matched = 0;
131
132         if (!pdimm->n_ranks)
133                 return;
134
135         if (popts->registered_dimm_en) {
136                 pbsp = &(board_specific_parameters_rdimm[ctrl_num][0]);
137                 num_params = sizeof(board_specific_parameters_rdimm[ctrl_num]) /
138                                 sizeof(board_specific_parameters_rdimm[0][0]);
139         } else {
140                 pbsp = &(board_specific_parameters_udimm[ctrl_num][0]);
141                 num_params = sizeof(board_specific_parameters_udimm[ctrl_num]) /
142                                 sizeof(board_specific_parameters_udimm[0][0]);
143         }
144
145         /* set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in
146          * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If
147          * there are two dimms in the controller, set odt_rd_cfg to 3 and
148          * odt_wr_cfg to 3 for the even CS, 0 for the odd CS.
149          */
150         for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
151                 if (i&1) {      /* odd CS */
152                         popts->cs_local_opts[i].odt_rd_cfg = 0;
153                         popts->cs_local_opts[i].odt_wr_cfg = 0;
154                 } else {        /* even CS */
155                         if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
156                                 popts->cs_local_opts[i].odt_rd_cfg = 0;
157                                 popts->cs_local_opts[i].odt_wr_cfg = 4;
158                         } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) {
159                         popts->cs_local_opts[i].odt_rd_cfg = 3;
160                         popts->cs_local_opts[i].odt_wr_cfg = 3;
161                         }
162                 }
163         }
164
165         /* Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr
166          * freqency and n_banks specified in board_specific_parameters table.
167          */
168         ddr_freq = get_ddr_freq(0) / 1000000;
169         for (i = 0; i < num_params; i++) {
170                 if (ddr_freq >= pbsp->datarate_mhz_low &&
171                     ddr_freq <= pbsp->datarate_mhz_high &&
172                     pdimm->n_ranks == pbsp->n_ranks) {
173                         popts->clk_adjust = pbsp->clk_adjust;
174                         popts->cpo_override = pbsp->cpo;
175                         popts->write_data_delay = pbsp->write_data_delay;
176                         popts->twoT_en = pbsp->force_2T;
177                         matched = 1;
178                         break;
179                 }
180                 pbsp++;
181         }
182
183         if (!matched)
184                 printf("Warning: board specific timing not found!\n");
185
186         /*
187          * Factors to consider for half-strength driver enable:
188          *      - number of DIMMs installed
189          */
190         popts->half_strength_driver_enable = 0;
191 }