/src/barebox/common/ddr2_dimm_params.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-only |
2 | | /* |
3 | | * Copyright 2008 Freescale Semiconductor, Inc. |
4 | | */ |
5 | | |
6 | | #include <common.h> |
7 | | #include <linux/log2.h> |
8 | | #include <ddr_dimms.h> |
9 | | |
10 | | /* |
11 | | * Calculate the Density of each Physical Rank. |
12 | | * Returned size is in bytes. |
13 | | * |
14 | | * Study these table from Byte 31 of JEDEC SPD Spec. |
15 | | * |
16 | | * DDR I DDR II |
17 | | * Bit Size Size |
18 | | * --- ----- ------ |
19 | | * 7 high 512MB 512MB |
20 | | * 6 256MB 256MB |
21 | | * 5 128MB 128MB |
22 | | * 4 64MB 16GB |
23 | | * 3 32MB 8GB |
24 | | * 2 16MB 4GB |
25 | | * 1 2GB 2GB |
26 | | * 0 low 1GB 1GB |
27 | | * |
28 | | * Reorder Table to be linear by stripping the bottom |
29 | | * 2 or 5 bits off and shifting them up to the top. |
30 | | * |
31 | | */ |
32 | | static unsigned long long |
33 | | compute_ranksize(unsigned int mem_type, unsigned char row_dens) |
34 | 0 | { |
35 | 0 | unsigned long long bsize; |
36 | | |
37 | | /* Bottom 5 bits up to the top. */ |
38 | 0 | bsize = ((row_dens >> 5) | ((row_dens & 31) << 3)); |
39 | 0 | bsize <<= 27ULL; |
40 | 0 | debug("DDR: DDR II rank density = 0x%16llx\n", bsize); |
41 | |
|
42 | 0 | return bsize; |
43 | 0 | } |
44 | | |
45 | | /* |
46 | | * Convert a two-nibble BCD value into a cycle time. |
47 | | * While the spec calls for nano-seconds, picos are returned. |
48 | | * |
49 | | * This implements the tables for bytes 9, 23 and 25 for both |
50 | | * DDR I and II. No allowance for distinguishing the invalid |
51 | | * fields absent for DDR I yet present in DDR II is made. |
52 | | * (That is, cycle times of .25, .33, .66 and .75 ns are |
53 | | * allowed for both DDR II and I.) |
54 | | */ |
55 | | static unsigned int |
56 | | convert_bcd_tenths_to_cycle_time_ps(unsigned int spd_val) |
57 | 0 | { |
58 | | /* Table look up the lower nibble, allow DDR I & II. */ |
59 | 0 | unsigned int tenths_ps[16] = { |
60 | 0 | 0, |
61 | 0 | 100, |
62 | 0 | 200, |
63 | 0 | 300, |
64 | 0 | 400, |
65 | 0 | 500, |
66 | 0 | 600, |
67 | 0 | 700, |
68 | 0 | 800, |
69 | 0 | 900, |
70 | 0 | 250, /* This and the next 3 entries valid ... */ |
71 | 0 | 330, /* ... only for tCK calculations. */ |
72 | 0 | 660, |
73 | 0 | 750, |
74 | 0 | 0, /* undefined */ |
75 | 0 | 0 /* undefined */ |
76 | 0 | }; |
77 | |
|
78 | 0 | unsigned int whole_ns = (spd_val & 0xF0) >> 4; |
79 | 0 | unsigned int tenth_ns = spd_val & 0x0F; |
80 | 0 | unsigned int ps = whole_ns * 1000 + tenths_ps[tenth_ns]; |
81 | |
|
82 | 0 | return ps; |
83 | 0 | } |
84 | | |
85 | | static unsigned int |
86 | | convert_bcd_hundredths_to_cycle_time_ps(unsigned int spd_val) |
87 | 0 | { |
88 | 0 | unsigned int tenth_ns = (spd_val & 0xF0) >> 4; |
89 | 0 | unsigned int hundredth_ns = spd_val & 0x0F; |
90 | 0 | unsigned int ps = tenth_ns * 100 + hundredth_ns * 10; |
91 | |
|
92 | 0 | return ps; |
93 | 0 | } |
94 | | |
95 | | static unsigned int byte40_table_ps[8] = { |
96 | | 0, |
97 | | 250, |
98 | | 330, |
99 | | 500, |
100 | | 660, |
101 | | 750, |
102 | | 0, /* supposed to be RFC, but not sure what that means */ |
103 | | 0 /* Undefined */ |
104 | | }; |
105 | | |
106 | | static unsigned int |
107 | | compute_trfc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trfc) |
108 | 0 | { |
109 | 0 | return (((trctrfc_ext & 0x1) * 256) + trfc) * 1000 |
110 | 0 | + byte40_table_ps[(trctrfc_ext >> 1) & 0x7]; |
111 | 0 | } |
112 | | |
113 | | static unsigned int |
114 | | compute_trc_ps_from_spd(unsigned char trctrfc_ext, unsigned char trc) |
115 | 0 | { |
116 | 0 | return trc * 1000 + byte40_table_ps[(trctrfc_ext >> 4) & 0x7]; |
117 | 0 | } |
118 | | |
119 | | /* |
120 | | * Determine Refresh Rate. Ignore self refresh bit on DDR I. |
121 | | * Table from SPD Spec, Byte 12, converted to picoseconds and |
122 | | * filled in with "default" normal values. |
123 | | */ |
124 | | static unsigned int |
125 | | determine_refresh_rate_ps(const unsigned int spd_refresh) |
126 | 0 | { |
127 | 0 | unsigned int refresh_time_ps[8] = { |
128 | 0 | 15625000, /* 0 Normal 1.00x */ |
129 | 0 | 3900000, /* 1 Reduced .25x */ |
130 | 0 | 7800000, /* 2 Extended .50x */ |
131 | 0 | 31300000, /* 3 Extended 2.00x */ |
132 | 0 | 62500000, /* 4 Extended 4.00x */ |
133 | 0 | 125000000, /* 5 Extended 8.00x */ |
134 | 0 | 15625000, /* 6 Normal 1.00x filler */ |
135 | 0 | 15625000, /* 7 Normal 1.00x filler */ |
136 | 0 | }; |
137 | |
|
138 | 0 | return refresh_time_ps[spd_refresh & 0x7]; |
139 | 0 | } |
140 | | |
141 | | /* |
142 | | * The purpose of this function is to compute a suitable |
143 | | * CAS latency given the DRAM clock period. The SPD only |
144 | | * defines at most 3 CAS latencies. Typically the slower in |
145 | | * frequency the DIMM runs at, the shorter its CAS latency can. |
146 | | * be. If the DIMM is operating at a sufficiently low frequency, |
147 | | * it may be able to run at a CAS latency shorter than the |
148 | | * shortest SPD-defined CAS latency. |
149 | | * |
150 | | * If a CAS latency is not found, 0 is returned. |
151 | | * |
152 | | * Do this by finding in the standard speed bin table the longest |
153 | | * tCKmin that doesn't exceed the value of mclk_ps (tCK). |
154 | | * |
155 | | * An assumption made is that the SDRAM device allows the |
156 | | * CL to be programmed for a value that is lower than those |
157 | | * advertised by the SPD. This is not always the case, |
158 | | * as those modes not defined in the SPD are optional. |
159 | | * |
160 | | * CAS latency de-rating based upon values JEDEC Standard No. 79-2C |
161 | | * Table 40, "DDR2 SDRAM stanadard speed bins and tCK, tRCD, tRP, tRAS, |
162 | | * and tRC for corresponding bin" |
163 | | * |
164 | | * ordinal 2, ddr2_speed_bins[1] contains tCK for CL=3 |
165 | | * Not certain if any good value exists for CL=2 |
166 | | */ |
167 | | /* CL2 CL3 CL4 CL5 CL6 CL7*/ |
168 | | static unsigned short ddr2_speed_bins[] = { 0, 5000, 3750, 3000, 2500, 1875 }; |
169 | | |
170 | | static unsigned int |
171 | | compute_derated_DDR2_CAS_latency(unsigned int mclk_ps) |
172 | 0 | { |
173 | 0 | const unsigned int num_speed_bins = ARRAY_SIZE(ddr2_speed_bins); |
174 | 0 | unsigned int lowest_tCKmin_found = 0; |
175 | 0 | unsigned int lowest_tCKmin_CL = 0; |
176 | 0 | unsigned int i; |
177 | |
|
178 | 0 | debug("mclk_ps = %u\n", mclk_ps); |
179 | |
|
180 | 0 | for (i = 0; i < num_speed_bins; i++) { |
181 | 0 | unsigned int x = ddr2_speed_bins[i]; |
182 | 0 | debug("i=%u, x = %u, lowest_tCKmin_found = %u\n", |
183 | 0 | i, x, lowest_tCKmin_found); |
184 | 0 | if (x && x <= mclk_ps && x >= lowest_tCKmin_found ) { |
185 | 0 | lowest_tCKmin_found = x; |
186 | 0 | lowest_tCKmin_CL = i + 2; |
187 | 0 | } |
188 | 0 | } |
189 | |
|
190 | 0 | debug("lowest_tCKmin_CL = %u\n", lowest_tCKmin_CL); |
191 | |
|
192 | 0 | return lowest_tCKmin_CL; |
193 | 0 | } |
194 | | |
195 | | /* |
196 | | * ddr2_compute_dimm_parameters for DDR2 SPD |
197 | | * |
198 | | * Compute DIMM parameters based upon the SPD information in spd. |
199 | | * Writes the results to the struct dimm_params structure pointed by pdimm. |
200 | | * |
201 | | * FIXME: use #define for the retvals |
202 | | */ |
203 | | unsigned int ddr2_compute_dimm_parameters(unsigned int mclk_ps, |
204 | | const struct ddr2_spd_eeprom *spd, |
205 | | struct dimm_params *pdimm) |
206 | 0 | { |
207 | 0 | int ret; |
208 | |
|
209 | 0 | if (spd->mem_type != SPD_MEMTYPE_DDR2 && |
210 | 0 | spd->mem_type != SPD_MEMTYPE_DDR2_FBDIMM && |
211 | 0 | spd->mem_type != SPD_MEMTYPE_DDR2_FBDIMM_PROBE) { |
212 | 0 | printf("DIMM: SPD data is not DDR2\n"); |
213 | 0 | return 3; |
214 | 0 | } |
215 | | |
216 | 0 | ret = ddr2_spd_check(spd); |
217 | 0 | if (ret) { |
218 | 0 | printf("DIMM: failed checksum\n"); |
219 | 0 | return 2; |
220 | 0 | } |
221 | | |
222 | | /* |
223 | | * The part name in ASCII in the SPD EEPROM is not null terminated. |
224 | | * Guarantee null termination here by presetting all bytes to 0 |
225 | | * and copying the part name in ASCII from the SPD onto it |
226 | | */ |
227 | 0 | memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); |
228 | 0 | memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); |
229 | | |
230 | | /* DIMM organization parameters */ |
231 | 0 | pdimm->n_ranks = (spd->mod_ranks & 0x7) + 1; |
232 | 0 | pdimm->rank_density = compute_ranksize(spd->mem_type, spd->rank_dens); |
233 | 0 | pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; |
234 | 0 | pdimm->data_width = spd->dataw; |
235 | 0 | pdimm->primary_sdram_width = spd->primw; |
236 | 0 | pdimm->ec_sdram_width = spd->ecw; |
237 | | |
238 | | /* These are all the types defined by the JEDEC DDR2 SPD 1.3 spec */ |
239 | 0 | switch (spd->dimm_type) { |
240 | 0 | case DDR2_SPD_DIMMTYPE_RDIMM: |
241 | 0 | case DDR2_SPD_DIMMTYPE_72B_SO_RDIMM: |
242 | 0 | case DDR2_SPD_DIMMTYPE_MINI_RDIMM: |
243 | | /* Registered/buffered DIMMs */ |
244 | 0 | pdimm->registered_dimm = 1; |
245 | 0 | break; |
246 | | |
247 | 0 | case DDR2_SPD_DIMMTYPE_UDIMM: |
248 | 0 | case DDR2_SPD_DIMMTYPE_SO_DIMM: |
249 | 0 | case DDR2_SPD_DIMMTYPE_MICRO_DIMM: |
250 | 0 | case DDR2_SPD_DIMMTYPE_MINI_UDIMM: |
251 | | /* Unbuffered DIMMs */ |
252 | 0 | pdimm->registered_dimm = 0; |
253 | 0 | break; |
254 | | |
255 | 0 | case DDR2_SPD_DIMMTYPE_72B_SO_CDIMM: |
256 | 0 | default: |
257 | 0 | printf("unknown dimm_type 0x%02X\n", spd->dimm_type); |
258 | 0 | return 1; |
259 | 0 | } |
260 | | |
261 | | /* SDRAM device parameters */ |
262 | 0 | pdimm->n_row_addr = spd->nrow_addr; |
263 | 0 | pdimm->n_col_addr = spd->ncol_addr; |
264 | 0 | pdimm->n_banks_per_sdram_device = spd->nbanks; |
265 | 0 | pdimm->edc_config = spd->config; |
266 | 0 | pdimm->burst_lengths_bitmask = spd->burstl; |
267 | | |
268 | | /* |
269 | | * Calculate the Maximum Data Rate based on the Minimum Cycle time. |
270 | | * The SPD clk_cycle field (tCKmin) is measured in tenths of |
271 | | * nanoseconds and represented as BCD. |
272 | | */ |
273 | 0 | pdimm->tckmin_x_ps |
274 | 0 | = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle); |
275 | 0 | pdimm->tckmin_x_minus_1_ps |
276 | 0 | = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle2); |
277 | 0 | pdimm->tckmin_x_minus_2_ps |
278 | 0 | = convert_bcd_tenths_to_cycle_time_ps(spd->clk_cycle3); |
279 | |
|
280 | 0 | pdimm->tckmax_ps = convert_bcd_tenths_to_cycle_time_ps(spd->tckmax); |
281 | | |
282 | | /* |
283 | | * Compute CAS latencies defined by SPD |
284 | | * The SPD caslat_x should have at least 1 and at most 3 bits set. |
285 | | * |
286 | | * If cas_lat after masking is 0, the __ilog2 function returns |
287 | | * 255 into the variable. This behavior is abused once. |
288 | | */ |
289 | 0 | pdimm->caslat_x = ilog2(spd->cas_lat); |
290 | 0 | pdimm->caslat_x_minus_1 = ilog2(spd->cas_lat |
291 | 0 | & ~(1 << pdimm->caslat_x)); |
292 | 0 | pdimm->caslat_x_minus_2 = ilog2(spd->cas_lat |
293 | 0 | & ~(1 << pdimm->caslat_x) |
294 | 0 | & ~(1 << pdimm->caslat_x_minus_1)); |
295 | | |
296 | | /* Compute CAS latencies below that defined by SPD */ |
297 | 0 | pdimm->caslat_lowest_derated = compute_derated_DDR2_CAS_latency( |
298 | 0 | mclk_ps); |
299 | | |
300 | | /* Compute timing parameters */ |
301 | 0 | pdimm->trcd_ps = spd->trcd * 250; |
302 | 0 | pdimm->trp_ps = spd->trp * 250; |
303 | 0 | pdimm->tras_ps = spd->tras * 1000; |
304 | |
|
305 | 0 | pdimm->twr_ps = spd->twr * 250; |
306 | 0 | pdimm->twtr_ps = spd->twtr * 250; |
307 | 0 | pdimm->trfc_ps = compute_trfc_ps_from_spd(spd->trctrfc_ext, spd->trfc); |
308 | |
|
309 | 0 | pdimm->trrd_ps = spd->trrd * 250; |
310 | 0 | pdimm->trc_ps = compute_trc_ps_from_spd(spd->trctrfc_ext, spd->trc); |
311 | |
|
312 | 0 | pdimm->refresh_rate_ps = determine_refresh_rate_ps(spd->refresh); |
313 | |
|
314 | 0 | pdimm->tis_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_setup); |
315 | 0 | pdimm->tih_ps = convert_bcd_hundredths_to_cycle_time_ps(spd->ca_hold); |
316 | 0 | pdimm->tds_ps |
317 | 0 | = convert_bcd_hundredths_to_cycle_time_ps(spd->data_setup); |
318 | 0 | pdimm->tdh_ps |
319 | 0 | = convert_bcd_hundredths_to_cycle_time_ps(spd->data_hold); |
320 | |
|
321 | 0 | pdimm->trtp_ps = spd->trtp * 250; |
322 | 0 | pdimm->tdqsq_max_ps = spd->tdqsq * 10; |
323 | 0 | pdimm->tqhs_ps = spd->tqhs * 10; |
324 | |
|
325 | 0 | return 0; |
326 | 0 | } |