1
2
3
4
5
6
7
8
9#include <common.h>
10#include <asm/fsl_ddr_sdram.h>
11
12#include "ddr.h"
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35static unsigned long long
36compute_ranksize(unsigned int mem_type, unsigned char row_dens)
37{
38 unsigned long long bsize;
39
40
41 bsize = ((row_dens >> 5) | ((row_dens & 31) << 3));
42 bsize <<= 27ULL;
43 debug("DDR: DDR II rank density = 0x%08x\n", bsize);
44
45 return bsize;
46}
47
48
49
50
51
52
53
54
55
56
57
58static unsigned int
59convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val)
60{
61
62 unsigned int tenths_ps[16] = {
63 0,
64 100,
65 200,
66 300,
67 400,
68 500,
69 600,
70 700,
71 800,
72 900,
73 250,
74 330,
75 660,
76 750,
77 0,
78 0
79 };
80
81 unsigned int whole_ns = (spd_val & 0xF0) >> 4;
82 unsigned int tenth_ns = spd_val & 0x0F;
83 unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns];
84
85 return ps;
86}
87
88static unsigned int
89convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val)
90{
91 unsigned int tenth_ns = (spd_val & 0xF0) >> 4;
92 unsigned int hundredth_ns = spd_val & 0x0F;
93 unsigned int ps = tenth_ns * 100 + hundredth_ns * 10;
94
95 return ps;
96}
97
98static unsigned int byte40_table_ps[8] = {
99 0,
100 250,
101 330,
102 500,
103 660,
104 750,
105 0,
106 0
107};
108
109static unsigned int
110compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc)
111{
112 unsigned int trfc_ps;
113
114 trfc_ps = (((trctrfc_ext & 0x1) * 256) + trfc) * 1000
115 + byte40_table_ps[(trctrfc_ext >> 1) & 0x7];
116
117 return trfc_ps;
118}
119
120static unsigned int
121compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc)
122{
123 unsigned int trc_ps;
124
125 trc_ps = trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7];
126
127 return trc_ps;
128}
129
130
131
132
133
134
135static unsigned int
136determine_refresh_rate_ps(const unsigned int spd_refresh)
137{
138 unsigned int refresh_time_ps[8] = {
139 15625000,
140 3900000,
141 7800000,
142 31300000,
143 62500000,
144 125000000,
145 15625000,
146 15625000,
147 };
148
149 return refresh_time_ps[spd_refresh & 0x7];
150}
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179unsigned short ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500 };
180
181unsigned int
182compute_derated_DDR2_CAS_latency(unsigned int mclk_ps)
183{
184 const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins);
185 unsigned int lowest_tCKmin_found = 0;
186 unsigned int lowest_tCKmin_CL = 0;
187 unsigned int i;
188
189 debug("mclk_ps = %u\n", mclk_ps);
190
191 for (i = 0; i < num_speed_bins; i++) {
192 unsigned int x = ddr2_speed_bins[i];
193 debug("i=%u, x = %u, lowest_tCKmin_found = %u\n",
194 i, x, lowest_tCKmin_found);
195 if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) {
196 lowest_tCKmin_found = x;
197 lowest_tCKmin_CL = i + 2;
198 }
199 }
200
201 debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL);
202
203 return lowest_tCKmin_CL;
204}
205
206
207
208
209
210
211
212
213
214unsigned int
215ddr_compute_dimm_parameters(const ddr2_spd_eeprom_t *spd,
216 dimm_params_t *pdimm,
217 unsigned int dimm_number)
218{
219 unsigned int retval;
220
221 if (spd->mem_type) {
222 if (spd->mem_type != SPD_MEMTYPE_DDR2) {
223 printf("DIMM %u: is not a DDR2 SPD.\n", dimm_number);
224 return 1;
225 }
226 } else {
227 memset(pdimm, 0, sizeof(dimm_params_t));
228 return 1;
229 }
230
231 retval = ddr2_spd_check(spd);
232 if (retval) {
233 printf("DIMM %u: failed checksum\n", dimm_number);
234 return 2;
235 }
236
237
238
239
240
241
242 memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
243 memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
244
245
246 pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1;
247 pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens);
248 pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
249 pdimm->data_width = spd->dataw;
250 pdimm->primary_sdram_width = spd->primw;
251 pdimm->ec_sdram_width = spd->ecw;
252
253
254 switch (spd->dimm_type) {
255 case 0x01:
256 case 0x10:
257 pdimm->registered_dimm = 1;
258 break;
259
260 case 0x02:
261 case 0x04:
262 case 0x08:
263 case 0x20:
264 pdimm->registered_dimm = 0;
265 break;
266
267 default:
268 printf("unknown dimm_type 0x%02X\n", spd->dimm_type);
269 return 1;
270 break;
271 }
272
273
274 pdimm->n_row_addr = spd->nrow_addr;
275 pdimm->n_col_addr = spd->ncol_addr;
276 pdimm->n_banks_per_sdram_device = spd->nbanks;
277 pdimm->edc_config = spd->config;
278 pdimm->burst_lengths_bitmask = spd->burstl;
279 pdimm->row_density = spd->rank_dens;
280
281
282
283
284
285
286 pdimm->tCKmin_X_ps
287 = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle);
288 pdimm->tCKmin_X_minus_1_ps
289 = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2);
290 pdimm->tCKmin_X_minus_2_ps
291 = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3);
292
293 pdimm->tCKmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax);
294
295
296
297
298
299
300
301
302 pdimm->caslat_X = __ilog2(spd->cas_lat);
303 pdimm->caslat_X_minus_1 = __ilog2(spd->cas_lat
304 & ~(1 << pdimm->caslat_X));
305 pdimm->caslat_X_minus_2 = __ilog2(spd->cas_lat
306 & ~(1 << pdimm->caslat_X)
307 & ~(1 << pdimm->caslat_X_minus_1));
308
309
310 pdimm->caslat_lowest_derated
311 = compute_derated_DDR2_CAS_latency(get_memory_clk_period_ps());
312
313
314 pdimm->tRCD_ps = spd->trcd * 250;
315 pdimm->tRP_ps = spd->trp * 250;
316 pdimm->tRAS_ps = spd->tras * 1000;
317
318 pdimm->tWR_ps = spd->twr * 250;
319 pdimm->tWTR_ps = spd->twtr * 250;
320 pdimm->tRFC_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc);
321
322 pdimm->tRRD_ps = spd->trrd * 250;
323 pdimm->tRC_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc);
324
325 pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh);
326
327 pdimm->tIS_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup);
328 pdimm->tIH_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold);
329 pdimm->tDS_ps
330 = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup);
331 pdimm->tDH_ps
332 = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold);
333
334 pdimm->tRTP_ps = spd->trtp * 250;
335 pdimm->tDQSQ_max_ps = spd->tdqsq * 10;
336 pdimm->tQHS_ps = spd->tqhs * 10;
337
338 return 0;
339}
340