Line data Source code
1 : /* $OpenBSD: spdmem.c,v 1.5 2015/01/25 11:38:49 jsg Exp $ */
2 : /* $NetBSD: spdmem.c,v 1.3 2007/09/20 23:09:59 xtraeme Exp $ */
3 :
4 : /*
5 : * Copyright (c) 2007 Jonathan Gray <jsg@openbsd.org>
6 : *
7 : * Permission to use, copy, modify, and distribute this software for any
8 : * purpose with or without fee is hereby granted, provided that the above
9 : * copyright notice and this permission notice appear in all copies.
10 : *
11 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 : */
19 :
20 : /*
21 : * Copyright (c) 2007 Nicolas Joly
22 : * Copyright (c) 2007 Paul Goyette
23 : * Copyright (c) 2007 Tobias Nygren
24 : * All rights reserved.
25 : *
26 : * Redistribution and use in source and binary forms, with or without
27 : * modification, are permitted provided that the following conditions
28 : * are met:
29 : * 1. Redistributions of source code must retain the above copyright
30 : * notice, this list of conditions and the following disclaimer.
31 : * 2. Redistributions in binary form must reproduce the above copyright
32 : * notice, this list of conditions and the following disclaimer in the
33 : * documentation and/or other materials provided with the distribution.
34 : * 3. The name of the author may not be used to endorse or promote products
35 : * derived from this software without specific prior written permission.
36 : *
37 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
38 : * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
39 : * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
41 : * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 : * POSSIBILITY OF SUCH DAMAGE.
48 : */
49 :
50 : /*
51 : * Serial Presence Detect (SPD) memory identification
52 : */
53 :
54 : #include <sys/param.h>
55 : #include <sys/systm.h>
56 : #include <sys/device.h>
57 :
58 : #include <dev/spdmemvar.h>
59 :
60 : /* Encodings of the size used/total byte for certain memory types */
61 : #define SPDMEM_SPDSIZE_MASK 0x0F /* SPD EEPROM Size */
62 :
63 : #define SPDMEM_SPDLEN_128 0x00 /* SPD EEPROM Sizes */
64 : #define SPDMEM_SPDLEN_176 0x10
65 : #define SPDMEM_SPDLEN_256 0x20
66 : #define SPDMEM_SPDLEN_MASK 0x70 /* Bits 4 - 6 */
67 :
68 : #define SPDMEM_SPDCRC_116 0x80 /* CRC Bytes covered */
69 : #define SPDMEM_SPDCRC_125 0x00
70 : #define SPDMEM_SPDCRC_MASK 0x80 /* Bit 7 */
71 :
72 :
73 : /* possible values for the memory type */
74 : #define SPDMEM_MEMTYPE_FPM 0x01
75 : #define SPDMEM_MEMTYPE_EDO 0x02
76 : #define SPDMEM_MEMTYPE_PIPE_NIBBLE 0x03
77 : #define SPDMEM_MEMTYPE_SDRAM 0x04
78 : #define SPDMEM_MEMTYPE_ROM 0x05
79 : #define SPDMEM_MEMTYPE_DDRSGRAM 0x06
80 : #define SPDMEM_MEMTYPE_DDRSDRAM 0x07
81 : #define SPDMEM_MEMTYPE_DDR2SDRAM 0x08
82 : #define SPDMEM_MEMTYPE_FBDIMM 0x09
83 : #define SPDMEM_MEMTYPE_FBDIMM_PROBE 0x0a
84 : #define SPDMEM_MEMTYPE_DDR3SDRAM 0x0b
85 : #define SPDMEM_MEMTYPE_NONE 0xff
86 :
87 : #define SPDMEM_MEMTYPE_DIRECT_RAMBUS 0x01
88 : #define SPDMEM_MEMTYPE_RAMBUS 0x11
89 :
90 : /* possible values for the supply voltage */
91 : #define SPDMEM_VOLTAGE_TTL_5V 0x00
92 : #define SPDMEM_VOLTAGE_TTL_LV 0x01
93 : #define SPDMEM_VOLTAGE_HSTTL_1_5V 0x02
94 : #define SPDMEM_VOLTAGE_SSTL_3_3V 0x03
95 : #define SPDMEM_VOLTAGE_SSTL_2_5V 0x04
96 : #define SPDMEM_VOLTAGE_SSTL_1_8V 0x05
97 :
98 : /* possible values for module configuration */
99 : #define SPDMEM_MODCONFIG_PARITY 0x01
100 : #define SPDMEM_MODCONFIG_ECC 0x02
101 :
102 : /* for DDR2, module configuration is a bit-mask field */
103 : #define SPDMEM_MODCONFIG_HAS_DATA_PARITY 0x01
104 : #define SPDMEM_MODCONFIG_HAS_DATA_ECC 0x02
105 : #define SPDMEM_MODCONFIG_HAS_ADDR_CMD_PARITY 0x04
106 :
107 : /* possible values for the refresh field */
108 : #define SPDMEM_REFRESH_STD 0x00
109 : #define SPDMEM_REFRESH_QUARTER 0x01
110 : #define SPDMEM_REFRESH_HALF 0x02
111 : #define SPDMEM_REFRESH_TWOX 0x03
112 : #define SPDMEM_REFRESH_FOURX 0x04
113 : #define SPDMEM_REFRESH_EIGHTX 0x05
114 : #define SPDMEM_REFRESH_SELFREFRESH 0x80
115 :
116 : /* superset types */
117 : #define SPDMEM_SUPERSET_ESDRAM 0x01
118 : #define SPDMEM_SUPERSET_DDR_ESDRAM 0x02
119 : #define SPDMEM_SUPERSET_EDO_PEM 0x03
120 : #define SPDMEM_SUPERSET_SDR_PEM 0x04
121 :
122 : /* FPM and EDO DIMMS */
123 : #define SPDMEM_FPM_ROWS 0x00
124 : #define SPDMEM_FPM_COLS 0x01
125 : #define SPDMEM_FPM_BANKS 0x02
126 : #define SPDMEM_FPM_CONFIG 0x08
127 : #define SPDMEM_FPM_REFRESH 0x09
128 : #define SPDMEM_FPM_SUPERSET 0x0c
129 :
130 : /* PC66/PC100/PC133 SDRAM */
131 : #define SPDMEM_SDR_ROWS 0x00
132 : #define SPDMEM_SDR_COLS 0x01
133 : #define SPDMEM_SDR_BANKS 0x02
134 : #define SPDMEM_SDR_CYCLE 0x06
135 : #define SPDMEM_SDR_BANKS_PER_CHIP 0x0e
136 : #define SPDMEM_SDR_MOD_ATTRIB 0x12
137 : #define SPDMEM_SDR_SUPERSET 0x1d
138 :
139 : #define SPDMEM_SDR_FREQUENCY 126
140 : #define SPDMEM_SDR_CAS 127
141 : #define SPDMEM_SDR_FREQ_66 0x66
142 : #define SPDMEM_SDR_FREQ_100 0x64
143 : #define SPDMEM_SDR_FREQ_133 0x85
144 : #define SPDMEM_SDR_CAS2 (1 << 1)
145 : #define SPDMEM_SDR_CAS3 (1 << 2)
146 :
147 : /* Rambus Direct DRAM */
148 : #define SPDMEM_RDR_MODULE_TYPE 0x00
149 : #define SPDMEM_RDR_ROWS_COLS 0x01
150 : #define SPDMEM_RDR_BANK 0x02
151 :
152 : #define SPDMEM_RDR_TYPE_RIMM 1
153 : #define SPDMEM_RDR_TYPE_SORIMM 2
154 : #define SPDMEM_RDR_TYPE_EMBED 3
155 : #define SPDMEM_RDR_TYPE_RIMM32 4
156 :
157 : /* Dual Data Rate SDRAM */
158 : #define SPDMEM_DDR_ROWS 0x00
159 : #define SPDMEM_DDR_COLS 0x01
160 : #define SPDMEM_DDR_RANKS 0x02
161 : #define SPDMEM_DDR_DATAWIDTH 0x03
162 : #define SPDMEM_DDR_VOLTAGE 0x05
163 : #define SPDMEM_DDR_CYCLE 0x06
164 : #define SPDMEM_DDR_REFRESH 0x09
165 : #define SPDMEM_DDR_BANKS_PER_CHIP 0x0e
166 : #define SPDMEM_DDR_CAS 0x0f
167 : #define SPDMEM_DDR_MOD_ATTRIB 0x12
168 : #define SPDMEM_DDR_SUPERSET 0x1d
169 :
170 : #define SPDMEM_DDR_ATTRIB_REG (1 << 1)
171 :
172 : /* Dual Data Rate 2 SDRAM */
173 : #define SPDMEM_DDR2_ROWS 0x00
174 : #define SPDMEM_DDR2_COLS 0x01
175 : #define SPDMEM_DDR2_RANKS 0x02
176 : #define SPDMEM_DDR2_DATAWIDTH 0x03
177 : #define SPDMEM_DDR2_VOLTAGE 0x05
178 : #define SPDMEM_DDR2_CYCLE 0x06
179 : #define SPDMEM_DDR2_DIMMTYPE 0x11
180 : #define SPDMEM_DDR2_RANK_DENSITY 0x1c
181 :
182 : #define SPDMEM_DDR2_TYPE_REGMASK ((1 << 4) | (1 << 0))
183 : #define SPDMEM_DDR2_SODIMM (1 << 2)
184 : #define SPDMEM_DDR2_MICRO_DIMM (1 << 3)
185 : #define SPDMEM_DDR2_MINI_RDIMM (1 << 4)
186 : #define SPDMEM_DDR2_MINI_UDIMM (1 << 5)
187 :
188 : /* DDR2 FB-DIMM SDRAM */
189 : #define SPDMEM_FBDIMM_ADDR 0x01
190 : #define SPDMEM_FBDIMM_RANKS 0x04
191 : #define SPDMEM_FBDIMM_MTB_DIVIDEND 0x06
192 : #define SPDMEM_FBDIMM_MTB_DIVISOR 0x07
193 : #define SPDMEM_FBDIMM_PROTO 0x4e
194 :
195 : #define SPDMEM_FBDIMM_RANKS_WIDTH 0x07
196 : #define SPDMEM_FBDIMM_ADDR_BANKS 0x02
197 : #define SPDMEM_FBDIMM_ADDR_COL 0x0c
198 : #define SPDMEM_FBDIMM_ADDR_COL_SHIFT 2
199 : #define SPDMEM_FBDIMM_ADDR_ROW 0xe0
200 : #define SPDMEM_FBDIMM_ADDR_ROW_SHIFT 5
201 : #define SPDMEM_FBDIMM_PROTO_ECC (1 << 1)
202 :
203 :
204 : /* Dual Data Rate 3 SDRAM */
205 : #define SPDMEM_DDR3_MODTYPE 0x00
206 : #define SPDMEM_DDR3_DENSITY 0x01
207 : #define SPDMEM_DDR3_MOD_ORG 0x04
208 : #define SPDMEM_DDR3_DATAWIDTH 0x05
209 : #define SPDMEM_DDR3_MTB_DIVIDEND 0x07
210 : #define SPDMEM_DDR3_MTB_DIVISOR 0x08
211 : #define SPDMEM_DDR3_TCKMIN 0x09
212 : #define SPDMEM_DDR3_THERMAL 0x1d
213 :
214 : #define SPDMEM_DDR3_DENSITY_CAPMASK 0x0f
215 : #define SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK 0x07
216 : #define SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT 3
217 : #define SPDMEM_DDR3_MOD_ORG_BANKS_MASK 0x07
218 : #define SPDMEM_DDR3_DATAWIDTH_ECCMASK (1 << 3)
219 : #define SPDMEM_DDR3_DATAWIDTH_PRIMASK 0x07
220 : #define SPDMEM_DDR3_THERMAL_PRESENT (1 << 7)
221 :
222 : #define SPDMEM_DDR3_RDIMM 0x01
223 : #define SPDMEM_DDR3_UDIMM 0x02
224 : #define SPDMEM_DDR3_SODIMM 0x03
225 : #define SPDMEM_DDR3_MICRO_DIMM 0x04
226 : #define SPDMEM_DDR3_MINI_RDIMM 0x05
227 : #define SPDMEM_DDR3_MINI_UDIMM 0x06
228 :
229 : static const uint8_t ddr2_cycle_tenths[] = {
230 : 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 25, 33, 66, 75, 0, 0
231 : };
232 :
233 : #define SPDMEM_TYPE_MAXLEN 16
234 :
235 : uint16_t spdmem_crc16(struct spdmem_softc *, int);
236 : static inline
237 : uint8_t spdmem_read(struct spdmem_softc *, uint8_t);
238 : void spdmem_sdram_decode(struct spdmem_softc *, struct spdmem *);
239 : void spdmem_rdr_decode(struct spdmem_softc *, struct spdmem *);
240 : void spdmem_ddr_decode(struct spdmem_softc *, struct spdmem *);
241 : void spdmem_ddr2_decode(struct spdmem_softc *, struct spdmem *);
242 : void spdmem_fbdimm_decode(struct spdmem_softc *, struct spdmem *);
243 : void spdmem_ddr3_decode(struct spdmem_softc *, struct spdmem *);
244 :
245 : struct cfdriver spdmem_cd = {
246 : NULL, "spdmem", DV_DULL
247 : };
248 :
249 : #define IS_RAMBUS_TYPE (s->sm_len < 4)
250 :
251 : static const char *spdmem_basic_types[] = {
252 : "unknown",
253 : "FPM",
254 : "EDO",
255 : "Pipelined Nibble",
256 : "SDRAM",
257 : "ROM",
258 : "DDR SGRAM",
259 : "DDR SDRAM",
260 : "DDR2 SDRAM",
261 : "DDR2 SDRAM FB-DIMM",
262 : "DDR2 SDRAM FB-DIMM Probe",
263 : "DDR3 SDRAM"
264 : };
265 :
266 : static const char *spdmem_superset_types[] = {
267 : "unknown",
268 : "ESDRAM",
269 : "DDR ESDRAM",
270 : "PEM EDO",
271 : "PEM SDRAM"
272 : };
273 :
274 : static const char *spdmem_parity_types[] = {
275 : "non-parity",
276 : "data parity",
277 : "ECC",
278 : "data parity and ECC",
279 : "cmd/addr parity",
280 : "cmd/addr/data parity",
281 : "cmd/addr parity, data ECC",
282 : "cmd/addr/data parity, data ECC"
283 : };
284 :
285 : static inline uint8_t
286 0 : spdmem_read(struct spdmem_softc *sc, uint8_t reg)
287 : {
288 0 : return (*sc->sc_read)(sc, reg);
289 : }
290 :
291 : /* CRC functions used for certain memory types */
292 : uint16_t
293 0 : spdmem_crc16(struct spdmem_softc *sc, int count)
294 : {
295 : uint16_t crc;
296 : int i, j;
297 : uint8_t val;
298 : crc = 0;
299 0 : for (j = 0; j <= count; j++) {
300 0 : val = spdmem_read(sc, j);
301 0 : crc = crc ^ val << 8;
302 0 : for (i = 0; i < 8; ++i)
303 0 : if (crc & 0x8000)
304 0 : crc = crc << 1 ^ 0x1021;
305 : else
306 0 : crc = crc << 1;
307 : }
308 0 : return (crc & 0xFFFF);
309 : }
310 :
311 : void
312 0 : spdmem_sdram_decode(struct spdmem_softc *sc, struct spdmem *s)
313 : {
314 : const char *type;
315 : int dimm_size, p_clk;
316 : int num_banks, per_chip;
317 : uint8_t rows, cols;
318 :
319 0 : type = spdmem_basic_types[s->sm_type];
320 :
321 0 : if (s->sm_data[SPDMEM_SDR_SUPERSET] == SPDMEM_SUPERSET_SDR_PEM)
322 0 : type = spdmem_superset_types[SPDMEM_SUPERSET_SDR_PEM];
323 0 : if (s->sm_data[SPDMEM_SDR_SUPERSET] == SPDMEM_SUPERSET_ESDRAM)
324 0 : type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM];
325 :
326 0 : num_banks = s->sm_data[SPDMEM_SDR_BANKS];
327 0 : per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP];
328 0 : rows = s->sm_data[SPDMEM_SDR_ROWS] & 0x0f;
329 0 : cols = s->sm_data[SPDMEM_SDR_COLS] & 0x0f;
330 0 : dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
331 :
332 0 : if (dimm_size > 0) {
333 0 : if (dimm_size < 1024)
334 0 : printf(" %dMB", dimm_size);
335 : else
336 0 : printf(" %dGB", dimm_size / 1024);
337 : }
338 :
339 0 : printf(" %s", type);
340 :
341 0 : if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB] & SPDMEM_DDR_ATTRIB_REG)
342 0 : printf(" registered");
343 :
344 0 : if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
345 0 : printf(" %s",
346 0 : spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
347 :
348 : p_clk = 66;
349 0 : if (s->sm_len >= 128) {
350 0 : switch (spdmem_read(sc, SPDMEM_SDR_FREQUENCY)) {
351 : case SPDMEM_SDR_FREQ_100:
352 : case SPDMEM_SDR_FREQ_133:
353 : /* We need to check ns to decide here */
354 0 : if (s->sm_data[SPDMEM_SDR_CYCLE] < 0x80)
355 0 : p_clk = 133;
356 : else
357 : p_clk = 100;
358 : break;
359 : case SPDMEM_SDR_FREQ_66:
360 : default:
361 : p_clk = 66;
362 0 : break;
363 : }
364 : }
365 0 : printf(" PC%d", p_clk);
366 :
367 : /* Print CAS latency */
368 0 : if (s->sm_len < 128)
369 0 : return;
370 0 : if (spdmem_read(sc, SPDMEM_SDR_CAS) & SPDMEM_SDR_CAS2)
371 0 : printf("CL2");
372 0 : else if (spdmem_read(sc, SPDMEM_SDR_CAS) & SPDMEM_SDR_CAS3)
373 0 : printf("CL3");
374 0 : }
375 :
376 : void
377 0 : spdmem_rdr_decode(struct spdmem_softc *sc, struct spdmem *s)
378 : {
379 : int rimm_size;
380 : uint8_t row_bits, col_bits, bank_bits;
381 :
382 0 : row_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS] >> 4;
383 0 : col_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS] & 0x0f;
384 0 : bank_bits = s->sm_data[SPDMEM_RDR_BANK] & 0x07;
385 :
386 : /* subtracting 13 here is a cheaper way of dividing by 8k later */
387 0 : rimm_size = 1 << (row_bits + col_bits + bank_bits - 13);
388 :
389 0 : if (rimm_size < 1024)
390 0 : printf(" %dMB ", rimm_size);
391 : else
392 0 : printf(" %dGB ", rimm_size / 1024);
393 :
394 0 : switch(s->sm_data[SPDMEM_RDR_MODULE_TYPE]) {
395 : case SPDMEM_RDR_TYPE_RIMM:
396 0 : printf("RIMM");
397 0 : break;
398 : case SPDMEM_RDR_TYPE_SORIMM:
399 0 : printf("SO-RIMM");
400 0 : break;
401 : case SPDMEM_RDR_TYPE_EMBED:
402 0 : printf("Embedded Rambus");
403 0 : break;
404 : case SPDMEM_RDR_TYPE_RIMM32:
405 0 : printf("RIMM32");
406 0 : break;
407 : }
408 0 : }
409 :
410 : void
411 0 : spdmem_ddr_decode(struct spdmem_softc *sc, struct spdmem *s)
412 : {
413 : const char *type;
414 : int dimm_size, cycle_time, d_clk, p_clk, bits;
415 : int i, num_banks, per_chip;
416 : uint8_t config, rows, cols, cl;
417 :
418 0 : type = spdmem_basic_types[s->sm_type];
419 :
420 0 : if (s->sm_data[SPDMEM_DDR_SUPERSET] == SPDMEM_SUPERSET_DDR_ESDRAM)
421 0 : type = spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM];
422 :
423 0 : num_banks = s->sm_data[SPDMEM_SDR_BANKS];
424 0 : per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP];
425 0 : rows = s->sm_data[SPDMEM_SDR_ROWS] & 0x0f;
426 0 : cols = s->sm_data[SPDMEM_SDR_COLS] & 0x0f;
427 0 : dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
428 :
429 0 : if (dimm_size > 0) {
430 0 : if (dimm_size < 1024)
431 0 : printf(" %dMB", dimm_size);
432 : else
433 0 : printf(" %dGB", dimm_size / 1024);
434 : }
435 :
436 0 : printf(" %s", type);
437 :
438 0 : if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB] & SPDMEM_DDR_ATTRIB_REG)
439 0 : printf(" registered");
440 :
441 0 : if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
442 0 : printf(" %s",
443 0 : spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
444 :
445 : /* cycle_time is expressed in units of 0.01 ns */
446 0 : cycle_time = (s->sm_data[SPDMEM_DDR_CYCLE] >> 4) * 100 +
447 0 : (s->sm_data[SPDMEM_DDR_CYCLE] & 0x0f) * 10;
448 :
449 0 : if (cycle_time != 0) {
450 : /*
451 : * cycle time is scaled by a factor of 100 to avoid using
452 : * floating point. Calculate memory speed as the number
453 : * of cycles per microsecond.
454 : * DDR uses dual-pumped clock
455 : */
456 : d_clk = 100 * 1000 * 2;
457 0 : config = s->sm_data[SPDMEM_FPM_CONFIG];
458 0 : bits = s->sm_data[SPDMEM_DDR_DATAWIDTH] |
459 0 : (s->sm_data[SPDMEM_DDR_DATAWIDTH + 1] << 8);
460 0 : if (config == 1 || config == 2)
461 0 : bits -= 8;
462 :
463 0 : d_clk /= cycle_time;
464 0 : p_clk = d_clk * bits / 8;
465 0 : if ((p_clk % 100) >= 50)
466 0 : p_clk += 50;
467 0 : p_clk -= p_clk % 100;
468 0 : printf(" PC%d", p_clk);
469 0 : }
470 :
471 : /* Print CAS latency */
472 0 : for (i = 6; i >= 0; i--) {
473 0 : if (s->sm_data[SPDMEM_DDR_CAS] & (1 << i)) {
474 0 : cl = ((i * 10) / 2) + 10;
475 0 : printf("CL%d.%d", cl / 10, cl % 10);
476 0 : break;
477 : }
478 : }
479 0 : }
480 :
481 : void
482 0 : spdmem_ddr2_decode(struct spdmem_softc *sc, struct spdmem *s)
483 : {
484 : const char *type;
485 : int dimm_size, cycle_time, d_clk, p_clk, bits;
486 : int i, num_ranks, density;
487 : uint8_t config;
488 :
489 0 : type = spdmem_basic_types[s->sm_type];
490 :
491 0 : num_ranks = (s->sm_data[SPDMEM_DDR2_RANKS] & 0x7) + 1;
492 0 : density = (s->sm_data[SPDMEM_DDR2_RANK_DENSITY] & 0xf0) |
493 0 : ((s->sm_data[SPDMEM_DDR2_RANK_DENSITY] & 0x0f) << 8);
494 0 : dimm_size = num_ranks * density * 4;
495 :
496 0 : if (dimm_size > 0) {
497 0 : if (dimm_size < 1024)
498 0 : printf(" %dMB", dimm_size);
499 : else
500 0 : printf(" %dGB", dimm_size / 1024);
501 : }
502 :
503 0 : printf(" %s", type);
504 :
505 0 : if (s->sm_data[SPDMEM_DDR2_DIMMTYPE] & SPDMEM_DDR2_TYPE_REGMASK)
506 0 : printf(" registered");
507 :
508 0 : if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
509 0 : printf(" %s",
510 0 : spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
511 :
512 : /* cycle_time is expressed in units of 0.01 ns */
513 0 : cycle_time = (s->sm_data[SPDMEM_DDR2_CYCLE] >> 4) * 100 +
514 0 : ddr2_cycle_tenths[(s->sm_data[SPDMEM_DDR2_CYCLE] & 0x0f)];
515 :
516 0 : if (cycle_time != 0) {
517 : /*
518 : * cycle time is scaled by a factor of 100 to avoid using
519 : * floating point. Calculate memory speed as the number
520 : * of cycles per microsecond.
521 : * DDR2 uses quad-pumped clock
522 : */
523 : d_clk = 100 * 1000 * 4;
524 0 : config = s->sm_data[SPDMEM_FPM_CONFIG];
525 0 : bits = s->sm_data[SPDMEM_DDR2_DATAWIDTH];
526 0 : if ((config & 0x03) != 0)
527 0 : bits -= 8;
528 0 : d_clk /= cycle_time;
529 0 : d_clk = (d_clk + 1) / 2;
530 0 : p_clk = d_clk * bits / 8;
531 0 : p_clk -= p_clk % 100;
532 0 : printf(" PC2-%d", p_clk);
533 0 : }
534 :
535 : /* Print CAS latency */
536 0 : for (i = 7; i >= 2; i--) {
537 0 : if (s->sm_data[SPDMEM_DDR_CAS] & (1 << i)) {
538 0 : printf("CL%d", i);
539 0 : break;
540 : }
541 : }
542 :
543 0 : switch (s->sm_data[SPDMEM_DDR2_DIMMTYPE]) {
544 : case SPDMEM_DDR2_SODIMM:
545 0 : printf(" SO-DIMM");
546 0 : break;
547 : case SPDMEM_DDR2_MICRO_DIMM:
548 0 : printf(" Micro-DIMM");
549 0 : break;
550 : case SPDMEM_DDR2_MINI_RDIMM:
551 : case SPDMEM_DDR2_MINI_UDIMM:
552 0 : printf(" Mini-DIMM");
553 0 : break;
554 : }
555 0 : }
556 :
557 : void
558 0 : spdmem_fbdimm_decode(struct spdmem_softc *sc, struct spdmem *s)
559 : {
560 : int dimm_size, cycle_time, d_clk, p_clk, bits;
561 : uint8_t rows, cols, dividend, divisor;
562 : /*
563 : * FB-DIMM is very much like DDR3
564 : */
565 :
566 0 : cols = (s->sm_data[SPDMEM_FBDIMM_ADDR] & SPDMEM_FBDIMM_ADDR_COL) >>
567 : SPDMEM_FBDIMM_ADDR_COL_SHIFT;
568 0 : rows = (s->sm_data[SPDMEM_FBDIMM_ADDR] & SPDMEM_FBDIMM_ADDR_ROW) >>
569 : SPDMEM_FBDIMM_ADDR_ROW_SHIFT;
570 0 : dimm_size = rows + 12 + cols + 9 - 20 - 3;
571 :
572 0 : if (dimm_size < 1024)
573 0 : printf(" %dMB", dimm_size);
574 : else
575 0 : printf(" %dGB", dimm_size / 1024);
576 :
577 0 : dividend = s->sm_data[SPDMEM_FBDIMM_MTB_DIVIDEND];
578 0 : divisor = s->sm_data[SPDMEM_FBDIMM_MTB_DIVISOR];
579 :
580 0 : cycle_time = (1000 * dividend + (divisor / 2)) / divisor;
581 :
582 0 : if (cycle_time != 0) {
583 : /*
584 : * cycle time is scaled by a factor of 1000 to avoid using
585 : * floating point. Calculate memory speed as the number
586 : * of cycles per microsecond.
587 : */
588 : d_clk = 1000 * 1000;
589 :
590 : /* DDR2 FB-DIMM uses a dual-pumped clock */
591 : d_clk *= 2;
592 0 : bits = 1 << ((s->sm_data[SPDMEM_FBDIMM_RANKS] &
593 0 : SPDMEM_FBDIMM_RANKS_WIDTH) + 2);
594 :
595 0 : p_clk = (d_clk * bits) / 8 / cycle_time;
596 0 : p_clk -= p_clk % 100;
597 0 : printf(" PC2-%d", p_clk);
598 0 : }
599 0 : }
600 :
601 : void
602 0 : spdmem_ddr3_decode(struct spdmem_softc *sc, struct spdmem *s)
603 : {
604 : const char *type;
605 : int dimm_size, cycle_time, d_clk, p_clk, bits;
606 : uint8_t mtype, chipsize, dividend, divisor;
607 : uint8_t datawidth, chipwidth, physbanks;
608 :
609 0 : type = spdmem_basic_types[s->sm_type];
610 :
611 0 : chipsize = s->sm_data[SPDMEM_DDR3_DENSITY] &
612 : SPDMEM_DDR3_DENSITY_CAPMASK;
613 0 : datawidth = s->sm_data[SPDMEM_DDR3_DATAWIDTH] &
614 : SPDMEM_DDR3_DATAWIDTH_PRIMASK;
615 0 : chipwidth = s->sm_data[SPDMEM_DDR3_MOD_ORG] &
616 : SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK;
617 0 : physbanks = (s->sm_data[SPDMEM_DDR3_MOD_ORG] >>
618 0 : SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT) & SPDMEM_DDR3_MOD_ORG_BANKS_MASK;
619 :
620 0 : dimm_size = (chipsize + 28 - 20) - 3 + (datawidth + 3) -
621 0 : (chipwidth + 2);
622 0 : dimm_size = (1 << dimm_size) * (physbanks + 1);
623 :
624 0 : if (dimm_size < 1024)
625 0 : printf(" %dMB", dimm_size);
626 : else
627 0 : printf(" %dGB", dimm_size / 1024);
628 :
629 0 : printf(" %s", type);
630 :
631 0 : mtype = s->sm_data[SPDMEM_DDR3_MODTYPE];
632 0 : if (mtype == SPDMEM_DDR3_RDIMM || mtype == SPDMEM_DDR3_MINI_RDIMM)
633 0 : printf(" registered");
634 :
635 0 : if (s->sm_data[SPDMEM_DDR3_DATAWIDTH] & SPDMEM_DDR3_DATAWIDTH_ECCMASK)
636 0 : printf(" ECC");
637 :
638 0 : dividend = s->sm_data[SPDMEM_DDR3_MTB_DIVIDEND];
639 0 : divisor = s->sm_data[SPDMEM_DDR3_MTB_DIVISOR];
640 0 : cycle_time = (1000 * dividend + (divisor / 2)) / divisor;
641 0 : cycle_time *= s->sm_data[SPDMEM_DDR3_TCKMIN];
642 :
643 0 : if (cycle_time != 0) {
644 : /*
645 : * cycle time is scaled by a factor of 1000 to avoid using
646 : * floating point. Calculate memory speed as the number
647 : * of cycles per microsecond.
648 : * DDR3 uses a dual-pumped clock
649 : */
650 : d_clk = 1000 * 1000;
651 : d_clk *= 2;
652 0 : bits = 1 << ((s->sm_data[SPDMEM_DDR3_DATAWIDTH] &
653 0 : SPDMEM_DDR3_DATAWIDTH_PRIMASK) + 3);
654 : /*
655 : * Calculate p_clk first, since for DDR3 we need maximum
656 : * significance. DDR3 rating is not rounded to a multiple
657 : * of 100. This results in cycle_time of 1.5ns displayed
658 : * as p_clk PC3-10666 (d_clk DDR3-1333)
659 : */
660 0 : p_clk = (d_clk * bits) / 8 / cycle_time;
661 0 : p_clk -= (p_clk % 100);
662 0 : d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
663 0 : printf(" PC3-%d", p_clk);
664 0 : }
665 :
666 0 : switch (s->sm_data[SPDMEM_DDR3_MODTYPE]) {
667 : case SPDMEM_DDR3_SODIMM:
668 0 : printf(" SO-DIMM");
669 0 : break;
670 : case SPDMEM_DDR3_MICRO_DIMM:
671 0 : printf(" Micro-DIMM");
672 0 : break;
673 : case SPDMEM_DDR3_MINI_RDIMM:
674 : case SPDMEM_DDR3_MINI_UDIMM:
675 0 : printf(" Mini-DIMM");
676 0 : break;
677 : }
678 :
679 0 : if (s->sm_data[SPDMEM_DDR3_THERMAL] & SPDMEM_DDR3_THERMAL_PRESENT)
680 0 : printf(" with thermal sensor");
681 0 : }
682 :
683 : int
684 0 : spdmem_probe(struct spdmem_softc *sc)
685 : {
686 : uint8_t i, val, type;
687 : int cksum = 0;
688 : int spd_len, spd_crc_cover;
689 : uint16_t crc_calc, crc_spd;
690 :
691 0 : type = spdmem_read(sc, 2);
692 : /* For older memory types, validate the checksum over 1st 63 bytes */
693 0 : if (type <= SPDMEM_MEMTYPE_DDR2SDRAM) {
694 0 : for (i = 0; i < 63; i++)
695 0 : cksum += spdmem_read(sc, i);
696 :
697 0 : val = spdmem_read(sc, 63);
698 :
699 0 : if (cksum == 0 || (cksum & 0xff) != val) {
700 0 : return 0;
701 : } else
702 0 : return 1;
703 : }
704 :
705 : /* For DDR3 and FBDIMM, verify the CRC */
706 0 : else if (type <= SPDMEM_MEMTYPE_DDR3SDRAM) {
707 0 : spd_len = spdmem_read(sc, 0);
708 0 : if (spd_len & SPDMEM_SPDCRC_116)
709 0 : spd_crc_cover = 116;
710 : else
711 : spd_crc_cover = 125;
712 0 : switch (spd_len & SPDMEM_SPDLEN_MASK) {
713 : case SPDMEM_SPDLEN_128:
714 : spd_len = 128;
715 0 : break;
716 : case SPDMEM_SPDLEN_176:
717 : spd_len = 176;
718 0 : break;
719 : case SPDMEM_SPDLEN_256:
720 : spd_len = 256;
721 0 : break;
722 : default:
723 0 : return 0;
724 : }
725 0 : if (spd_crc_cover > spd_len)
726 0 : return 0;
727 0 : crc_calc = spdmem_crc16(sc, spd_crc_cover);
728 0 : crc_spd = spdmem_read(sc, 127) << 8;
729 0 : crc_spd |= spdmem_read(sc, 126);
730 0 : if (crc_calc != crc_spd) {
731 0 : return 0;
732 : }
733 0 : return 1;
734 : }
735 :
736 0 : return 0;
737 0 : }
738 :
739 : void
740 0 : spdmem_attach_common(struct spdmem_softc *sc)
741 : {
742 0 : struct spdmem *s = &(sc->sc_spd_data);
743 : int i;
744 :
745 : /* All SPD have at least 64 bytes of data including checksum */
746 0 : for (i = 0; i < 64; i++) {
747 0 : ((uint8_t *)s)[i] = spdmem_read(sc, i);
748 : }
749 :
750 : /*
751 : * Decode and print SPD contents
752 : */
753 0 : if (s->sm_len < 4) {
754 0 : if (s->sm_type == SPDMEM_MEMTYPE_DIRECT_RAMBUS)
755 0 : spdmem_rdr_decode(sc, s);
756 : else
757 0 : printf(" no decode method for Rambus memory");
758 : } else {
759 0 : switch(s->sm_type) {
760 : case SPDMEM_MEMTYPE_EDO:
761 : case SPDMEM_MEMTYPE_SDRAM:
762 0 : spdmem_sdram_decode(sc, s);
763 0 : break;
764 : case SPDMEM_MEMTYPE_DDRSDRAM:
765 0 : spdmem_ddr_decode(sc, s);
766 0 : break;
767 : case SPDMEM_MEMTYPE_DDR2SDRAM:
768 0 : spdmem_ddr2_decode(sc, s);
769 0 : break;
770 : case SPDMEM_MEMTYPE_FBDIMM:
771 : case SPDMEM_MEMTYPE_FBDIMM_PROBE:
772 0 : spdmem_fbdimm_decode(sc, s);
773 0 : break;
774 : case SPDMEM_MEMTYPE_DDR3SDRAM:
775 0 : spdmem_ddr3_decode(sc, s);
776 0 : break;
777 : case SPDMEM_MEMTYPE_NONE:
778 0 : printf(" no EEPROM found");
779 0 : break;
780 : default:
781 0 : if (s->sm_type <= 10)
782 0 : printf(" no decode method for %s memory",
783 0 : spdmem_basic_types[s->sm_type]);
784 : else
785 0 : printf(" unknown memory type %d", s->sm_type);
786 : break;
787 : }
788 : }
789 :
790 0 : printf("\n");
791 0 : }
|