/src/barebox/common/ddr4_dimm_params.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * Copyright 2014-2016 Freescale Semiconductor, Inc. |
4 | | * Copyright 2017-2018 NXP Semiconductor |
5 | | * |
6 | | * calculate the organization and timing parameter |
7 | | * from ddr3 spd, please refer to the spec |
8 | | * JEDEC standard No.21-C 4_01_02_12R23A.pdf |
9 | | * |
10 | | * |
11 | | */ |
12 | | |
13 | | #include <common.h> |
14 | | #include <ddr_dimms.h> |
15 | | |
16 | | /* |
17 | | * Calculate the Density of each Physical Rank. |
18 | | * Returned size is in bytes. |
19 | | * |
20 | | * Total DIMM size = |
21 | | * sdram capacity(bit) / 8 * primary bus width / sdram width |
22 | | * * Logical Ranks per DIMM |
23 | | * |
24 | | * where: sdram capacity = spd byte4[3:0] |
25 | | * primary bus width = spd byte13[2:0] |
26 | | * sdram width = spd byte12[2:0] |
27 | | * Logical Ranks per DIMM = spd byte12[5:3] for SDP, DDP, QDP |
28 | | * spd byte12{5:3] * spd byte6[6:4] for 3DS |
29 | | * |
30 | | * To simplify each rank size = total DIMM size / Number of Package Ranks |
31 | | * where Number of Package Ranks = spd byte12[5:3] |
32 | | * |
33 | | * SPD byte4 - sdram density and banks |
34 | | * bit[3:0] size(bit) size(byte) |
35 | | * 0000 256Mb 32MB |
36 | | * 0001 512Mb 64MB |
37 | | * 0010 1Gb 128MB |
38 | | * 0011 2Gb 256MB |
39 | | * 0100 4Gb 512MB |
40 | | * 0101 8Gb 1GB |
41 | | * 0110 16Gb 2GB |
42 | | * 0111 32Gb 4GB |
43 | | * |
44 | | * SPD byte13 - module memory bus width |
45 | | * bit[2:0] primary bus width |
46 | | * 000 8bits |
47 | | * 001 16bits |
48 | | * 010 32bits |
49 | | * 011 64bits |
50 | | * |
51 | | * SPD byte12 - module organization |
52 | | * bit[2:0] sdram device width |
53 | | * 000 4bits |
54 | | * 001 8bits |
55 | | * 010 16bits |
56 | | * 011 32bits |
57 | | * |
58 | | * SPD byte12 - module organization |
59 | | * bit[5:3] number of package ranks per DIMM |
60 | | * 000 1 |
61 | | * 001 2 |
62 | | * 010 3 |
63 | | * 011 4 |
64 | | * |
65 | | * SPD byte6 - SDRAM package type |
66 | | * bit[6:4] Die count |
67 | | * 000 1 |
68 | | * 001 2 |
69 | | * 010 3 |
70 | | * 011 4 |
71 | | * 100 5 |
72 | | * 101 6 |
73 | | * 110 7 |
74 | | * 111 8 |
75 | | * |
76 | | * SPD byte6 - SRAM package type |
77 | | * bit[1:0] Signal loading |
78 | | * 00 Not specified |
79 | | * 01 Multi load stack |
80 | | * 10 Sigle load stack (3DS) |
81 | | * 11 Reserved |
82 | | */ |
83 | | static unsigned long long |
84 | | compute_ranksize(const struct ddr4_spd_eeprom *spd) |
85 | 0 | { |
86 | 0 | unsigned long long bsize; |
87 | |
|
88 | 0 | int nbit_sdram_cap_bsize = 0; |
89 | 0 | int nbit_primary_bus_width = 0; |
90 | 0 | int nbit_sdram_width = 0; |
91 | 0 | int die_count = 0; |
92 | 0 | bool package_3ds; |
93 | |
|
94 | 0 | if ((spd->density_banks & 0xf) <= 7) |
95 | 0 | nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28; |
96 | 0 | if ((spd->bus_width & 0x7) < 4) |
97 | 0 | nbit_primary_bus_width = (spd->bus_width & 0x7) + 3; |
98 | 0 | if ((spd->organization & 0x7) < 4) |
99 | 0 | nbit_sdram_width = (spd->organization & 0x7) + 2; |
100 | 0 | package_3ds = (spd->package_type & 0x3) == 0x2; |
101 | 0 | if ((spd->package_type & 0x80) && !package_3ds) { /* other than 3DS */ |
102 | 0 | printf("Warning: not supported SDRAM package type\n"); |
103 | 0 | return 0; |
104 | 0 | } |
105 | 0 | if (package_3ds) |
106 | 0 | die_count = (spd->package_type >> 4) & 0x7; |
107 | |
|
108 | 0 | bsize = 1ULL << (nbit_sdram_cap_bsize - 3 + |
109 | 0 | nbit_primary_bus_width - nbit_sdram_width + |
110 | 0 | die_count); |
111 | |
|
112 | 0 | debug("DDR: DDR rank density = 0x%16llx\n", bsize); |
113 | |
|
114 | 0 | return bsize; |
115 | 0 | } |
116 | | |
117 | | #define spd_to_ps(mtb, ftb) \ |
118 | 0 | (mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10) |
119 | | /* |
120 | | * ddr4_compute_dimm_parameters for DDR4 SPD |
121 | | * |
122 | | * Compute DIMM parameters based upon the SPD information in spd. |
123 | | * Writes the results to the struct dimm_params structure pointed by pdimm. |
124 | | * |
125 | | */ |
126 | | unsigned int ddr4_compute_dimm_parameters(const struct ddr4_spd_eeprom *spd, |
127 | | struct dimm_params *pdimm) |
128 | 0 | { |
129 | 0 | int ret; |
130 | 0 | int i; |
131 | 0 | const u8 udimm_rc_e_dq[18] = { |
132 | 0 | 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15, |
133 | 0 | 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36 |
134 | 0 | }; |
135 | 0 | int spd_error = 0; |
136 | 0 | u8 *ptr; |
137 | 0 | u8 val; |
138 | |
|
139 | 0 | if (spd->mem_type != SPD_MEMTYPE_DDR4) { |
140 | 0 | printf("DIMM: SPD data is not DDR4\n"); |
141 | 0 | return 3; |
142 | 0 | } |
143 | | |
144 | 0 | ret = ddr4_spd_check(spd); |
145 | 0 | if (ret) { |
146 | 0 | printf("DIMM: failed checksum\n"); |
147 | 0 | return 2; |
148 | 0 | } |
149 | | |
150 | | /* |
151 | | * The part name in ASCII in the SPD EEPROM is not null terminated. |
152 | | * Guarantee null termination here by presetting all bytes to 0 |
153 | | * and copying the part name in ASCII from the SPD onto it |
154 | | */ |
155 | 0 | memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); |
156 | 0 | if ((spd->info_size_crc & 0xF) > 2) |
157 | 0 | memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); |
158 | | |
159 | | /* DIMM organization parameters */ |
160 | 0 | pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; |
161 | 0 | pdimm->rank_density = compute_ranksize(spd); |
162 | 0 | pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; |
163 | 0 | pdimm->die_density = spd->density_banks & 0xf; |
164 | 0 | pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); |
165 | 0 | if ((spd->bus_width >> 3) & 0x3) |
166 | 0 | pdimm->ec_sdram_width = 8; |
167 | 0 | else |
168 | 0 | pdimm->ec_sdram_width = 0; |
169 | 0 | pdimm->data_width = pdimm->primary_sdram_width |
170 | 0 | + pdimm->ec_sdram_width; |
171 | 0 | pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); |
172 | 0 | pdimm->package_3ds = (spd->package_type & 0x3) == 0x2 ? |
173 | 0 | (spd->package_type >> 4) & 0x7 : 0; |
174 | | |
175 | | /* These are the types defined by the JEDEC SPD spec */ |
176 | 0 | pdimm->mirrored_dimm = 0; |
177 | 0 | pdimm->registered_dimm = 0; |
178 | 0 | switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) { |
179 | 0 | case DDR4_SPD_MODULETYPE_RDIMM: |
180 | | /* Registered/buffered DIMMs */ |
181 | 0 | pdimm->registered_dimm = 1; |
182 | 0 | if (spd->mod_section.registered.reg_map & 0x1) |
183 | 0 | pdimm->mirrored_dimm = 1; |
184 | 0 | val = spd->mod_section.registered.ca_stren; |
185 | 0 | pdimm->rcw[3] = val >> 4; |
186 | 0 | pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); |
187 | 0 | val = spd->mod_section.registered.clk_stren; |
188 | 0 | pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); |
189 | | /* Not all in SPD. For convience only. Boards may overwrite. */ |
190 | 0 | pdimm->rcw[6] = 0xf; |
191 | | /* |
192 | | * A17 only used for 16Gb and above devices. |
193 | | * C[2:0] only used for 3DS. |
194 | | */ |
195 | 0 | pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 | |
196 | 0 | (pdimm->package_3ds > 0x3 ? 0x0 : |
197 | 0 | (pdimm->package_3ds > 0x1 ? 0x1 : |
198 | 0 | (pdimm->package_3ds > 0 ? 0x2 : 0x3))); |
199 | 0 | if (pdimm->package_3ds || pdimm->n_ranks != 4) |
200 | 0 | pdimm->rcw[13] = 0xc; |
201 | 0 | else |
202 | 0 | pdimm->rcw[13] = 0xd; /* Fix encoded by board */ |
203 | |
|
204 | 0 | break; |
205 | | |
206 | 0 | case DDR4_SPD_MODULETYPE_UDIMM: |
207 | 0 | case DDR4_SPD_MODULETYPE_SO_DIMM: |
208 | | /* Unbuffered DIMMs */ |
209 | 0 | if (spd->mod_section.unbuffered.addr_mapping & 0x1) |
210 | 0 | pdimm->mirrored_dimm = 1; |
211 | 0 | if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 && |
212 | 0 | (spd->mod_section.unbuffered.ref_raw_card == 0x04)) { |
213 | | /* Fix SPD error found on DIMMs with raw card E0 */ |
214 | 0 | for (i = 0; i < 18; i++) { |
215 | 0 | if (spd->mapping[i] == udimm_rc_e_dq[i]) |
216 | 0 | continue; |
217 | 0 | spd_error = 1; |
218 | 0 | debug("SPD byte %d: 0x%x, should be 0x%x\n", |
219 | 0 | 60 + i, spd->mapping[i], |
220 | 0 | udimm_rc_e_dq[i]); |
221 | 0 | ptr = (u8 *)&spd->mapping[i]; |
222 | 0 | *ptr = udimm_rc_e_dq[i]; |
223 | 0 | } |
224 | 0 | if (spd_error) |
225 | 0 | printf("SPD DQ mapping error fixed\n"); |
226 | 0 | } |
227 | 0 | break; |
228 | | |
229 | 0 | default: |
230 | 0 | printf("unknown module_type 0x%02X\n", spd->module_type); |
231 | 0 | return 1; |
232 | 0 | } |
233 | | |
234 | | /* SDRAM device parameters */ |
235 | 0 | pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; |
236 | 0 | pdimm->n_col_addr = (spd->addressing & 0x7) + 9; |
237 | 0 | pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3; |
238 | 0 | pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3; |
239 | | |
240 | | /* |
241 | | * The SPD spec has not the ECC bit, |
242 | | * We consider the DIMM as ECC capability |
243 | | * when the extension bus exist |
244 | | */ |
245 | 0 | if (pdimm->ec_sdram_width) |
246 | 0 | pdimm->edc_config = 0x02; |
247 | 0 | else |
248 | 0 | pdimm->edc_config = 0x00; |
249 | | |
250 | | /* |
251 | | * The SPD spec has not the burst length byte |
252 | | * but DDR4 spec has nature BL8 and BC4, |
253 | | * BL8 -bit3, BC4 -bit2 |
254 | | */ |
255 | 0 | pdimm->burst_lengths_bitmask = 0x0c; |
256 | | |
257 | | /* MTB - medium timebase |
258 | | * The MTB in the SPD spec is 125ps, |
259 | | * |
260 | | * FTB - fine timebase |
261 | | * use 1/10th of ps as our unit to avoid floating point |
262 | | * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps |
263 | | */ |
264 | 0 | if ((spd->timebases & 0xf) == 0x0) { |
265 | 0 | pdimm->mtb_ps = 125; |
266 | 0 | pdimm->ftb_10th_ps = 10; |
267 | |
|
268 | 0 | } else { |
269 | 0 | printf("Unknown Timebases\n"); |
270 | 0 | } |
271 | | |
272 | | /* sdram minimum cycle time */ |
273 | 0 | pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min); |
274 | | |
275 | | /* sdram max cycle time */ |
276 | 0 | pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max); |
277 | | |
278 | | /* |
279 | | * CAS latency supported |
280 | | * bit0 - CL7 |
281 | | * bit4 - CL11 |
282 | | * bit8 - CL15 |
283 | | * bit12- CL19 |
284 | | * bit16- CL23 |
285 | | */ |
286 | 0 | pdimm->caslat_x = (spd->caslat_b1 << 7) | |
287 | 0 | (spd->caslat_b2 << 15) | |
288 | 0 | (spd->caslat_b3 << 23); |
289 | |
|
290 | 0 | BUG_ON(spd->caslat_b4 != 0); |
291 | | |
292 | | /* |
293 | | * min CAS latency time |
294 | | */ |
295 | 0 | pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min); |
296 | | |
297 | | /* |
298 | | * min RAS to CAS delay time |
299 | | */ |
300 | 0 | pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min); |
301 | | |
302 | | /* |
303 | | * Min Row Precharge Delay Time |
304 | | */ |
305 | 0 | pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min); |
306 | | |
307 | | /* min active to precharge delay time */ |
308 | 0 | pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) + |
309 | 0 | spd->tras_min_lsb) * pdimm->mtb_ps; |
310 | | |
311 | | /* min active to actice/refresh delay time */ |
312 | 0 | pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) + |
313 | 0 | spd->trc_min_lsb), spd->fine_trc_min); |
314 | | /* Min Refresh Recovery Delay Time */ |
315 | 0 | pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) * |
316 | 0 | pdimm->mtb_ps; |
317 | 0 | pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) * |
318 | 0 | pdimm->mtb_ps; |
319 | 0 | pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) * |
320 | 0 | pdimm->mtb_ps; |
321 | | /* min four active window delay time */ |
322 | 0 | pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) * |
323 | 0 | pdimm->mtb_ps; |
324 | | |
325 | | /* min row active to row active delay time, different bank group */ |
326 | 0 | pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min); |
327 | | /* min row active to row active delay time, same bank group */ |
328 | 0 | pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min); |
329 | | /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */ |
330 | 0 | pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min); |
331 | |
|
332 | 0 | if (pdimm->package_3ds) { |
333 | 0 | if (pdimm->die_density <= 0x4) { |
334 | 0 | pdimm->trfc_slr_ps = 260000; |
335 | 0 | } else if (pdimm->die_density <= 0x5) { |
336 | 0 | pdimm->trfc_slr_ps = 350000; |
337 | 0 | } else { |
338 | 0 | printf("WARN: Unsupported logical rank density 0x%x\n", |
339 | 0 | pdimm->die_density); |
340 | 0 | } |
341 | 0 | } |
342 | | |
343 | | /* |
344 | | * Average periodic refresh interval |
345 | | * tREFI = 7.8 us at normal temperature range |
346 | | */ |
347 | 0 | pdimm->refresh_rate_ps = 7800000; |
348 | |
|
349 | 0 | for (i = 0; i < 18; i++) |
350 | 0 | pdimm->dq_mapping[i] = spd->mapping[i]; |
351 | |
|
352 | 0 | pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0; |
353 | |
|
354 | 0 | return 0; |
355 | 0 | } |