spdmem.c revision 1.5.2.2 1 1.5.2.2 yamt /* $NetBSD: spdmem.c,v 1.5.2.2 2014/05/22 11:40:22 yamt Exp $ */
2 1.1 pgoyette
3 1.1 pgoyette /*
4 1.1 pgoyette * Copyright (c) 2007 Nicolas Joly
5 1.1 pgoyette * Copyright (c) 2007 Paul Goyette
6 1.1 pgoyette * Copyright (c) 2007 Tobias Nygren
7 1.1 pgoyette * All rights reserved.
8 1.1 pgoyette *
9 1.1 pgoyette * Redistribution and use in source and binary forms, with or without
10 1.1 pgoyette * modification, are permitted provided that the following conditions
11 1.1 pgoyette * are met:
12 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright
13 1.1 pgoyette * notice, this list of conditions and the following disclaimer.
14 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the
16 1.1 pgoyette * documentation and/or other materials provided with the distribution.
17 1.1 pgoyette * 3. The name of the author may not be used to endorse or promote products
18 1.1 pgoyette * derived from this software without specific prior written permission.
19 1.1 pgoyette *
20 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
21 1.1 pgoyette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.1 pgoyette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.1 pgoyette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.1 pgoyette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.1 pgoyette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.1 pgoyette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.1 pgoyette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.1 pgoyette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.1 pgoyette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.1 pgoyette * POSSIBILITY OF SUCH DAMAGE.
31 1.1 pgoyette */
32 1.1 pgoyette
33 1.1 pgoyette /*
34 1.1 pgoyette * Serial Presence Detect (SPD) memory identification
35 1.1 pgoyette */
36 1.1 pgoyette
37 1.1 pgoyette #include <sys/cdefs.h>
38 1.5.2.2 yamt __KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.5.2.2 2014/05/22 11:40:22 yamt Exp $");
39 1.1 pgoyette
40 1.1 pgoyette #include <sys/param.h>
41 1.1 pgoyette #include <sys/device.h>
42 1.1 pgoyette #include <sys/endian.h>
43 1.1 pgoyette #include <sys/sysctl.h>
44 1.1 pgoyette #include <machine/bswap.h>
45 1.1 pgoyette
46 1.1 pgoyette #include <dev/i2c/i2cvar.h>
47 1.1 pgoyette #include <dev/ic/spdmemreg.h>
48 1.1 pgoyette #include <dev/ic/spdmemvar.h>
49 1.1 pgoyette
50 1.1 pgoyette /* Routines for decoding spd data */
51 1.1 pgoyette static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *);
52 1.1 pgoyette static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *);
53 1.1 pgoyette static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *,
54 1.1 pgoyette int);
55 1.1 pgoyette static void decode_ddr(const struct sysctlnode *, device_t, struct spdmem *);
56 1.1 pgoyette static void decode_ddr2(const struct sysctlnode *, device_t, struct spdmem *);
57 1.1 pgoyette static void decode_ddr3(const struct sysctlnode *, device_t, struct spdmem *);
58 1.1 pgoyette static void decode_fbdimm(const struct sysctlnode *, device_t, struct spdmem *);
59 1.1 pgoyette
60 1.3 pgoyette static void decode_size_speed(device_t, const struct sysctlnode *,
61 1.3 pgoyette int, int, int, int, bool, const char *, int);
62 1.1 pgoyette static void decode_voltage_refresh(device_t, struct spdmem *);
63 1.1 pgoyette
64 1.1 pgoyette #define IS_RAMBUS_TYPE (s->sm_len < 4)
65 1.1 pgoyette
66 1.1 pgoyette static const char* spdmem_basic_types[] = {
67 1.1 pgoyette "unknown",
68 1.1 pgoyette "FPM",
69 1.1 pgoyette "EDO",
70 1.1 pgoyette "Pipelined Nibble",
71 1.1 pgoyette "SDRAM",
72 1.1 pgoyette "ROM",
73 1.1 pgoyette "DDR SGRAM",
74 1.1 pgoyette "DDR SDRAM",
75 1.1 pgoyette "DDR2 SDRAM",
76 1.1 pgoyette "DDR2 SDRAM FB",
77 1.1 pgoyette "DDR2 SDRAM FB Probe",
78 1.1 pgoyette "DDR3 SDRAM"
79 1.1 pgoyette };
80 1.1 pgoyette
81 1.1 pgoyette static const char* spdmem_superset_types[] = {
82 1.1 pgoyette "unknown",
83 1.1 pgoyette "ESDRAM",
84 1.1 pgoyette "DDR ESDRAM",
85 1.1 pgoyette "PEM EDO",
86 1.1 pgoyette "PEM SDRAM"
87 1.1 pgoyette };
88 1.1 pgoyette
89 1.1 pgoyette static const char* spdmem_voltage_types[] = {
90 1.1 pgoyette "TTL (5V tolerant)",
91 1.1 pgoyette "LvTTL (not 5V tolerant)",
92 1.1 pgoyette "HSTL 1.5V",
93 1.1 pgoyette "SSTL 3.3V",
94 1.1 pgoyette "SSTL 2.5V",
95 1.1 pgoyette "SSTL 1.8V"
96 1.1 pgoyette };
97 1.1 pgoyette
98 1.1 pgoyette static const char* spdmem_refresh_types[] = {
99 1.1 pgoyette "15.625us",
100 1.1 pgoyette "3.9us",
101 1.1 pgoyette "7.8us",
102 1.1 pgoyette "31.3us",
103 1.1 pgoyette "62.5us",
104 1.1 pgoyette "125us"
105 1.1 pgoyette };
106 1.1 pgoyette
107 1.1 pgoyette static const char* spdmem_parity_types[] = {
108 1.1 pgoyette "no parity or ECC",
109 1.1 pgoyette "data parity",
110 1.1 pgoyette "data ECC",
111 1.1 pgoyette "data parity and ECC",
112 1.1 pgoyette "cmd/addr parity",
113 1.1 pgoyette "cmd/addr/data parity",
114 1.1 pgoyette "cmd/addr parity, data ECC",
115 1.1 pgoyette "cmd/addr/data parity, data ECC"
116 1.1 pgoyette };
117 1.1 pgoyette
118 1.1 pgoyette /* Cycle time fractional values (units of .001 ns) for DDR2 SDRAM */
119 1.1 pgoyette static const uint16_t spdmem_cycle_frac[] = {
120 1.1 pgoyette 0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
121 1.1 pgoyette 250, 333, 667, 750, 999, 999
122 1.1 pgoyette };
123 1.1 pgoyette
124 1.1 pgoyette /* Format string for timing info */
125 1.5 wiz #define LATENCY "tAA-tRCD-tRP-tRAS: %d-%d-%d-%d\n"
126 1.1 pgoyette
127 1.1 pgoyette /* CRC functions used for certain memory types */
128 1.1 pgoyette
129 1.1 pgoyette static uint16_t spdcrc16 (struct spdmem_softc *sc, int count)
130 1.1 pgoyette {
131 1.1 pgoyette uint16_t crc;
132 1.1 pgoyette int i, j;
133 1.1 pgoyette uint8_t val;
134 1.1 pgoyette crc = 0;
135 1.1 pgoyette for (j = 0; j <= count; j++) {
136 1.1 pgoyette val = (sc->sc_read)(sc, j);
137 1.1 pgoyette crc = crc ^ val << 8;
138 1.1 pgoyette for (i = 0; i < 8; ++i)
139 1.1 pgoyette if (crc & 0x8000)
140 1.1 pgoyette crc = crc << 1 ^ 0x1021;
141 1.1 pgoyette else
142 1.1 pgoyette crc = crc << 1;
143 1.1 pgoyette }
144 1.1 pgoyette return (crc & 0xFFFF);
145 1.1 pgoyette }
146 1.1 pgoyette
147 1.1 pgoyette int
148 1.1 pgoyette spdmem_common_probe(struct spdmem_softc *sc)
149 1.1 pgoyette {
150 1.1 pgoyette int cksum = 0;
151 1.1 pgoyette uint8_t i, val, spd_type;
152 1.1 pgoyette int spd_len, spd_crc_cover;
153 1.1 pgoyette uint16_t crc_calc, crc_spd;
154 1.1 pgoyette
155 1.1 pgoyette spd_type = (sc->sc_read)(sc, 2);
156 1.1 pgoyette
157 1.1 pgoyette /* For older memory types, validate the checksum over 1st 63 bytes */
158 1.1 pgoyette if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) {
159 1.1 pgoyette for (i = 0; i < 63; i++)
160 1.1 pgoyette cksum += (sc->sc_read)(sc, i);
161 1.1 pgoyette
162 1.1 pgoyette val = (sc->sc_read)(sc, 63);
163 1.1 pgoyette
164 1.1 pgoyette if (cksum == 0 || (cksum & 0xff) != val) {
165 1.1 pgoyette aprint_debug("spd checksum failed, calc = 0x%02x, "
166 1.1 pgoyette "spd = 0x%02x\n", cksum, val);
167 1.1 pgoyette return 0;
168 1.1 pgoyette } else
169 1.1 pgoyette return 1;
170 1.1 pgoyette }
171 1.1 pgoyette
172 1.1 pgoyette /* For DDR3 and FBDIMM, verify the CRC */
173 1.1 pgoyette else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) {
174 1.1 pgoyette spd_len = (sc->sc_read)(sc, 0);
175 1.2 pgoyette if (spd_len & SPDMEM_SPDCRC_116)
176 1.1 pgoyette spd_crc_cover = 116;
177 1.1 pgoyette else
178 1.1 pgoyette spd_crc_cover = 125;
179 1.1 pgoyette switch (spd_len & SPDMEM_SPDLEN_MASK) {
180 1.1 pgoyette case SPDMEM_SPDLEN_128:
181 1.1 pgoyette spd_len = 128;
182 1.1 pgoyette break;
183 1.1 pgoyette case SPDMEM_SPDLEN_176:
184 1.1 pgoyette spd_len = 176;
185 1.1 pgoyette break;
186 1.1 pgoyette case SPDMEM_SPDLEN_256:
187 1.1 pgoyette spd_len = 256;
188 1.1 pgoyette break;
189 1.1 pgoyette default:
190 1.1 pgoyette return 0;
191 1.1 pgoyette }
192 1.1 pgoyette if (spd_crc_cover > spd_len)
193 1.1 pgoyette return 0;
194 1.1 pgoyette crc_calc = spdcrc16(sc, spd_crc_cover);
195 1.1 pgoyette crc_spd = (sc->sc_read)(sc, 127) << 8;
196 1.1 pgoyette crc_spd |= (sc->sc_read)(sc, 126);
197 1.1 pgoyette if (crc_calc != crc_spd) {
198 1.1 pgoyette aprint_debug("crc16 failed, covers %d bytes, "
199 1.1 pgoyette "calc = 0x%04x, spd = 0x%04x\n",
200 1.1 pgoyette spd_crc_cover, crc_calc, crc_spd);
201 1.1 pgoyette return 0;
202 1.1 pgoyette }
203 1.1 pgoyette return 1;
204 1.1 pgoyette }
205 1.1 pgoyette
206 1.1 pgoyette /* For unrecognized memory types, don't match at all */
207 1.1 pgoyette return 0;
208 1.1 pgoyette }
209 1.1 pgoyette
210 1.1 pgoyette void
211 1.1 pgoyette spdmem_common_attach(struct spdmem_softc *sc, device_t self)
212 1.1 pgoyette {
213 1.1 pgoyette struct spdmem *s = &(sc->sc_spd_data);
214 1.1 pgoyette const char *type;
215 1.1 pgoyette const char *rambus_rev = "Reserved";
216 1.1 pgoyette int dimm_size;
217 1.3 pgoyette unsigned int i, spd_len, spd_size;
218 1.1 pgoyette const struct sysctlnode *node = NULL;
219 1.1 pgoyette
220 1.1 pgoyette /*
221 1.1 pgoyette * FBDIMM and DDR3 (and probably all newer) have a different
222 1.1 pgoyette * encoding of the SPD EEPROM used/total sizes
223 1.1 pgoyette */
224 1.1 pgoyette s->sm_len = (sc->sc_read)(sc, 0);
225 1.1 pgoyette s->sm_size = (sc->sc_read)(sc, 1);
226 1.1 pgoyette s->sm_type = (sc->sc_read)(sc, 2);
227 1.1 pgoyette
228 1.1 pgoyette if (s->sm_type >= SPDMEM_MEMTYPE_FBDIMM) {
229 1.1 pgoyette spd_size = 64 << (s->sm_len & SPDMEM_SPDSIZE_MASK);
230 1.1 pgoyette switch (s->sm_len & SPDMEM_SPDLEN_MASK) {
231 1.1 pgoyette case SPDMEM_SPDLEN_128:
232 1.1 pgoyette spd_len = 128;
233 1.1 pgoyette break;
234 1.1 pgoyette case SPDMEM_SPDLEN_176:
235 1.1 pgoyette spd_len = 176;
236 1.1 pgoyette break;
237 1.1 pgoyette case SPDMEM_SPDLEN_256:
238 1.1 pgoyette spd_len = 256;
239 1.1 pgoyette break;
240 1.1 pgoyette default:
241 1.1 pgoyette spd_len = 64;
242 1.1 pgoyette break;
243 1.1 pgoyette }
244 1.1 pgoyette } else {
245 1.1 pgoyette spd_size = 1 << s->sm_size;
246 1.1 pgoyette spd_len = s->sm_len;
247 1.1 pgoyette if (spd_len < 64)
248 1.1 pgoyette spd_len = 64;
249 1.1 pgoyette }
250 1.1 pgoyette if (spd_len > spd_size)
251 1.1 pgoyette spd_len = spd_size;
252 1.1 pgoyette if (spd_len > sizeof(struct spdmem))
253 1.1 pgoyette spd_len = sizeof(struct spdmem);
254 1.1 pgoyette for (i = 3; i < spd_len; i++)
255 1.1 pgoyette ((uint8_t *)s)[i] = (sc->sc_read)(sc, i);
256 1.1 pgoyette
257 1.1 pgoyette /*
258 1.1 pgoyette * Setup our sysctl subtree, hw.spdmemN
259 1.1 pgoyette */
260 1.3 pgoyette sc->sc_sysctl_log = NULL;
261 1.5.2.2 yamt sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &node,
262 1.5.2.2 yamt 0, CTLTYPE_NODE,
263 1.5.2.2 yamt device_xname(self), NULL, NULL, 0, NULL, 0,
264 1.5.2.2 yamt CTL_HW, CTL_CREATE, CTL_EOL);
265 1.1 pgoyette if (node != NULL && spd_len != 0)
266 1.3 pgoyette sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
267 1.1 pgoyette 0,
268 1.1 pgoyette CTLTYPE_STRUCT, "spd_data",
269 1.1 pgoyette SYSCTL_DESCR("raw spd data"), NULL,
270 1.1 pgoyette 0, s, spd_len,
271 1.1 pgoyette CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
272 1.1 pgoyette
273 1.1 pgoyette /*
274 1.1 pgoyette * Decode and print key SPD contents
275 1.1 pgoyette */
276 1.1 pgoyette if (IS_RAMBUS_TYPE) {
277 1.1 pgoyette if (s->sm_type == SPDMEM_MEMTYPE_RAMBUS)
278 1.1 pgoyette type = "Rambus";
279 1.1 pgoyette else if (s->sm_type == SPDMEM_MEMTYPE_DIRECTRAMBUS)
280 1.1 pgoyette type = "Direct Rambus";
281 1.1 pgoyette else
282 1.1 pgoyette type = "Rambus (unknown)";
283 1.1 pgoyette
284 1.1 pgoyette switch (s->sm_len) {
285 1.1 pgoyette case 0:
286 1.1 pgoyette rambus_rev = "Invalid";
287 1.1 pgoyette break;
288 1.1 pgoyette case 1:
289 1.1 pgoyette rambus_rev = "0.7";
290 1.1 pgoyette break;
291 1.1 pgoyette case 2:
292 1.1 pgoyette rambus_rev = "1.0";
293 1.1 pgoyette break;
294 1.1 pgoyette default:
295 1.1 pgoyette rambus_rev = "Reserved";
296 1.1 pgoyette break;
297 1.1 pgoyette }
298 1.1 pgoyette } else {
299 1.1 pgoyette if (s->sm_type < __arraycount(spdmem_basic_types))
300 1.1 pgoyette type = spdmem_basic_types[s->sm_type];
301 1.1 pgoyette else
302 1.1 pgoyette type = "unknown memory type";
303 1.1 pgoyette
304 1.1 pgoyette if (s->sm_type == SPDMEM_MEMTYPE_EDO &&
305 1.1 pgoyette s->sm_fpm.fpm_superset == SPDMEM_SUPERSET_EDO_PEM)
306 1.1 pgoyette type = spdmem_superset_types[SPDMEM_SUPERSET_EDO_PEM];
307 1.1 pgoyette if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
308 1.1 pgoyette s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_SDRAM_PEM)
309 1.1 pgoyette type = spdmem_superset_types[SPDMEM_SUPERSET_SDRAM_PEM];
310 1.1 pgoyette if (s->sm_type == SPDMEM_MEMTYPE_DDRSDRAM &&
311 1.1 pgoyette s->sm_ddr.ddr_superset == SPDMEM_SUPERSET_DDR_ESDRAM)
312 1.1 pgoyette type =
313 1.1 pgoyette spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM];
314 1.1 pgoyette if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
315 1.1 pgoyette s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_ESDRAM) {
316 1.1 pgoyette type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM];
317 1.1 pgoyette }
318 1.1 pgoyette }
319 1.1 pgoyette
320 1.1 pgoyette strlcpy(sc->sc_type, type, SPDMEM_TYPE_MAXLEN);
321 1.1 pgoyette if (node != NULL)
322 1.3 pgoyette sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
323 1.1 pgoyette 0,
324 1.1 pgoyette CTLTYPE_STRING, "mem_type",
325 1.1 pgoyette SYSCTL_DESCR("memory module type"), NULL,
326 1.1 pgoyette 0, sc->sc_type, 0,
327 1.1 pgoyette CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
328 1.1 pgoyette
329 1.1 pgoyette if (IS_RAMBUS_TYPE) {
330 1.5.2.2 yamt aprint_naive("\n");
331 1.5.2.2 yamt aprint_normal("\n");
332 1.5.2.2 yamt aprint_normal_dev(self, "%s, SPD Revision %s", type, rambus_rev);
333 1.1 pgoyette dimm_size = 1 << (s->sm_rdr.rdr_rows + s->sm_rdr.rdr_cols - 13);
334 1.1 pgoyette if (dimm_size >= 1024)
335 1.1 pgoyette aprint_normal(", %dGB\n", dimm_size / 1024);
336 1.1 pgoyette else
337 1.1 pgoyette aprint_normal(", %dMB\n", dimm_size);
338 1.1 pgoyette
339 1.1 pgoyette /* No further decode for RAMBUS memory */
340 1.1 pgoyette return;
341 1.1 pgoyette }
342 1.1 pgoyette switch (s->sm_type) {
343 1.1 pgoyette case SPDMEM_MEMTYPE_EDO:
344 1.1 pgoyette case SPDMEM_MEMTYPE_FPM:
345 1.1 pgoyette decode_edofpm(node, self, s);
346 1.1 pgoyette break;
347 1.1 pgoyette case SPDMEM_MEMTYPE_ROM:
348 1.1 pgoyette decode_rom(node, self, s);
349 1.1 pgoyette break;
350 1.1 pgoyette case SPDMEM_MEMTYPE_SDRAM:
351 1.1 pgoyette decode_sdram(node, self, s, spd_len);
352 1.1 pgoyette break;
353 1.1 pgoyette case SPDMEM_MEMTYPE_DDRSDRAM:
354 1.1 pgoyette decode_ddr(node, self, s);
355 1.1 pgoyette break;
356 1.1 pgoyette case SPDMEM_MEMTYPE_DDR2SDRAM:
357 1.1 pgoyette decode_ddr2(node, self, s);
358 1.1 pgoyette break;
359 1.1 pgoyette case SPDMEM_MEMTYPE_DDR3SDRAM:
360 1.1 pgoyette decode_ddr3(node, self, s);
361 1.1 pgoyette break;
362 1.1 pgoyette case SPDMEM_MEMTYPE_FBDIMM:
363 1.1 pgoyette case SPDMEM_MEMTYPE_FBDIMM_PROBE:
364 1.1 pgoyette decode_fbdimm(node, self, s);
365 1.1 pgoyette break;
366 1.1 pgoyette }
367 1.5.2.2 yamt
368 1.5.2.2 yamt /* Dump SPD */
369 1.5.2.2 yamt for (i = 0; i < spd_len; i += 16) {
370 1.5.2.2 yamt unsigned int j, k;
371 1.5.2.2 yamt aprint_debug_dev(self, "0x%02x:", i);
372 1.5.2.2 yamt k = (spd_len > (i + 16)) ? i + 16 : spd_len;
373 1.5.2.2 yamt for (j = i; j < k; j++)
374 1.5.2.2 yamt aprint_debug(" %02x", ((uint8_t *)s)[j]);
375 1.5.2.2 yamt aprint_debug("\n");
376 1.5.2.2 yamt }
377 1.1 pgoyette }
378 1.1 pgoyette
379 1.3 pgoyette int
380 1.3 pgoyette spdmem_common_detach(struct spdmem_softc *sc, device_t self)
381 1.3 pgoyette {
382 1.3 pgoyette sysctl_teardown(&sc->sc_sysctl_log);
383 1.3 pgoyette
384 1.3 pgoyette return 0;
385 1.3 pgoyette }
386 1.3 pgoyette
387 1.1 pgoyette static void
388 1.3 pgoyette decode_size_speed(device_t self, const struct sysctlnode *node,
389 1.3 pgoyette int dimm_size, int cycle_time, int d_clk, int bits,
390 1.3 pgoyette bool round, const char *ddr_type_string, int speed)
391 1.1 pgoyette {
392 1.1 pgoyette int p_clk;
393 1.5.2.1 yamt struct spdmem_softc *sc = device_private(self);
394 1.1 pgoyette
395 1.1 pgoyette if (dimm_size < 1024)
396 1.1 pgoyette aprint_normal("%dMB", dimm_size);
397 1.1 pgoyette else
398 1.1 pgoyette aprint_normal("%dGB", dimm_size / 1024);
399 1.1 pgoyette if (node != NULL)
400 1.3 pgoyette sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
401 1.1 pgoyette CTLFLAG_IMMEDIATE,
402 1.1 pgoyette CTLTYPE_INT, "size",
403 1.1 pgoyette SYSCTL_DESCR("module size in MB"), NULL,
404 1.1 pgoyette dimm_size, NULL, 0,
405 1.1 pgoyette CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
406 1.1 pgoyette
407 1.1 pgoyette if (cycle_time == 0) {
408 1.1 pgoyette aprint_normal("\n");
409 1.1 pgoyette return;
410 1.1 pgoyette }
411 1.1 pgoyette
412 1.1 pgoyette /*
413 1.1 pgoyette * Calculate p_clk first, since for DDR3 we need maximum significance.
414 1.1 pgoyette * DDR3 rating is not rounded to a multiple of 100. This results in
415 1.1 pgoyette * cycle_time of 1.5ns displayed as PC3-10666.
416 1.1 pgoyette *
417 1.1 pgoyette * For SDRAM, the speed is provided by the caller so we use it.
418 1.1 pgoyette */
419 1.1 pgoyette d_clk *= 1000 * 1000;
420 1.1 pgoyette if (speed)
421 1.1 pgoyette p_clk = speed;
422 1.1 pgoyette else
423 1.1 pgoyette p_clk = (d_clk * bits) / 8 / cycle_time;
424 1.1 pgoyette d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
425 1.1 pgoyette if (round) {
426 1.1 pgoyette if ((p_clk % 100) >= 50)
427 1.1 pgoyette p_clk += 50;
428 1.1 pgoyette p_clk -= p_clk % 100;
429 1.1 pgoyette }
430 1.1 pgoyette aprint_normal(", %dMHz (%s-%d)\n",
431 1.1 pgoyette d_clk, ddr_type_string, p_clk);
432 1.1 pgoyette if (node != NULL)
433 1.3 pgoyette sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
434 1.1 pgoyette CTLFLAG_IMMEDIATE,
435 1.1 pgoyette CTLTYPE_INT, "speed",
436 1.1 pgoyette SYSCTL_DESCR("memory speed in MHz"),
437 1.1 pgoyette NULL, d_clk, NULL, 0,
438 1.1 pgoyette CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
439 1.1 pgoyette }
440 1.1 pgoyette
441 1.1 pgoyette static void
442 1.1 pgoyette decode_voltage_refresh(device_t self, struct spdmem *s)
443 1.1 pgoyette {
444 1.1 pgoyette const char *voltage, *refresh;
445 1.1 pgoyette
446 1.1 pgoyette if (s->sm_voltage < __arraycount(spdmem_voltage_types))
447 1.1 pgoyette voltage = spdmem_voltage_types[s->sm_voltage];
448 1.1 pgoyette else
449 1.1 pgoyette voltage = "unknown";
450 1.1 pgoyette
451 1.1 pgoyette if (s->sm_refresh < __arraycount(spdmem_refresh_types))
452 1.1 pgoyette refresh = spdmem_refresh_types[s->sm_refresh];
453 1.1 pgoyette else
454 1.1 pgoyette refresh = "unknown";
455 1.1 pgoyette
456 1.1 pgoyette aprint_verbose_dev(self, "voltage %s, refresh time %s%s\n",
457 1.1 pgoyette voltage, refresh,
458 1.1 pgoyette s->sm_selfrefresh?" (self-refreshing)":"");
459 1.1 pgoyette }
460 1.1 pgoyette
461 1.1 pgoyette static void
462 1.1 pgoyette decode_edofpm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
463 1.5.2.2 yamt aprint_naive("\n");
464 1.5.2.2 yamt aprint_normal("\n");
465 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
466 1.5.2.2 yamt
467 1.1 pgoyette aprint_normal("\n");
468 1.1 pgoyette aprint_verbose_dev(self,
469 1.1 pgoyette "%d rows, %d cols, %d banks, %dns tRAC, %dns tCAC\n",
470 1.1 pgoyette s->sm_fpm.fpm_rows, s->sm_fpm.fpm_cols, s->sm_fpm.fpm_banks,
471 1.1 pgoyette s->sm_fpm.fpm_tRAC, s->sm_fpm.fpm_tCAC);
472 1.1 pgoyette }
473 1.1 pgoyette
474 1.1 pgoyette static void
475 1.1 pgoyette decode_rom(const struct sysctlnode *node, device_t self, struct spdmem *s) {
476 1.5.2.2 yamt aprint_naive("\n");
477 1.5.2.2 yamt aprint_normal("\n");
478 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
479 1.5.2.2 yamt
480 1.1 pgoyette aprint_normal("\n");
481 1.1 pgoyette aprint_verbose_dev(self, "%d rows, %d cols, %d banks\n",
482 1.1 pgoyette s->sm_rom.rom_rows, s->sm_rom.rom_cols, s->sm_rom.rom_banks);
483 1.1 pgoyette }
484 1.1 pgoyette
485 1.1 pgoyette static void
486 1.1 pgoyette decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s,
487 1.1 pgoyette int spd_len) {
488 1.1 pgoyette int dimm_size, cycle_time, bits, tAA, i, speed, freq;
489 1.1 pgoyette
490 1.5.2.2 yamt aprint_naive("\n");
491 1.5.2.2 yamt aprint_normal("\n");
492 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
493 1.5.2.2 yamt
494 1.1 pgoyette aprint_normal("%s, %s, ",
495 1.1 pgoyette (s->sm_sdr.sdr_mod_attrs & SPDMEM_SDR_MASK_REG)?
496 1.1 pgoyette " (registered)":"",
497 1.1 pgoyette (s->sm_config < __arraycount(spdmem_parity_types))?
498 1.1 pgoyette spdmem_parity_types[s->sm_config]:"invalid parity");
499 1.1 pgoyette
500 1.1 pgoyette dimm_size = 1 << (s->sm_sdr.sdr_rows + s->sm_sdr.sdr_cols - 17);
501 1.1 pgoyette dimm_size *= s->sm_sdr.sdr_banks * s->sm_sdr.sdr_banks_per_chip;
502 1.1 pgoyette
503 1.1 pgoyette cycle_time = s->sm_sdr.sdr_cycle_whole * 1000 +
504 1.1 pgoyette s->sm_sdr.sdr_cycle_tenths * 100;
505 1.1 pgoyette bits = le16toh(s->sm_sdr.sdr_datawidth);
506 1.1 pgoyette if (s->sm_config == 1 || s->sm_config == 2)
507 1.1 pgoyette bits -= 8;
508 1.1 pgoyette
509 1.1 pgoyette /* Calculate speed here - from OpenBSD */
510 1.1 pgoyette if (spd_len >= 128)
511 1.1 pgoyette freq = ((uint8_t *)s)[126];
512 1.1 pgoyette else
513 1.1 pgoyette freq = 0;
514 1.1 pgoyette switch (freq) {
515 1.1 pgoyette /*
516 1.1 pgoyette * Must check cycle time since some PC-133 DIMMs
517 1.1 pgoyette * actually report PC-100
518 1.1 pgoyette */
519 1.1 pgoyette case 100:
520 1.1 pgoyette case 133:
521 1.1 pgoyette if (cycle_time < 8000)
522 1.1 pgoyette speed = 133;
523 1.1 pgoyette else
524 1.1 pgoyette speed = 100;
525 1.1 pgoyette break;
526 1.1 pgoyette case 0x66: /* Legacy DIMMs use _hex_ 66! */
527 1.1 pgoyette default:
528 1.1 pgoyette speed = 66;
529 1.1 pgoyette }
530 1.3 pgoyette decode_size_speed(self, node, dimm_size, cycle_time, 1, bits, FALSE,
531 1.3 pgoyette "PC", speed);
532 1.1 pgoyette
533 1.1 pgoyette aprint_verbose_dev(self,
534 1.1 pgoyette "%d rows, %d cols, %d banks, %d banks/chip, %d.%dns cycle time\n",
535 1.1 pgoyette s->sm_sdr.sdr_rows, s->sm_sdr.sdr_cols, s->sm_sdr.sdr_banks,
536 1.1 pgoyette s->sm_sdr.sdr_banks_per_chip, cycle_time/1000,
537 1.1 pgoyette (cycle_time % 1000) / 100);
538 1.1 pgoyette
539 1.1 pgoyette tAA = 0;
540 1.1 pgoyette for (i = 0; i < 8; i++)
541 1.1 pgoyette if (s->sm_sdr.sdr_tCAS & (1 << i))
542 1.1 pgoyette tAA = i;
543 1.1 pgoyette tAA++;
544 1.4 christos aprint_verbose_dev(self, LATENCY, tAA, s->sm_sdr.sdr_tRCD,
545 1.1 pgoyette s->sm_sdr.sdr_tRP, s->sm_sdr.sdr_tRAS);
546 1.1 pgoyette
547 1.1 pgoyette decode_voltage_refresh(self, s);
548 1.1 pgoyette }
549 1.1 pgoyette
550 1.1 pgoyette static void
551 1.1 pgoyette decode_ddr(const struct sysctlnode *node, device_t self, struct spdmem *s) {
552 1.1 pgoyette int dimm_size, cycle_time, bits, tAA, i;
553 1.1 pgoyette
554 1.5.2.2 yamt aprint_naive("\n");
555 1.5.2.2 yamt aprint_normal("\n");
556 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
557 1.5.2.2 yamt
558 1.1 pgoyette aprint_normal("%s, %s, ",
559 1.1 pgoyette (s->sm_ddr.ddr_mod_attrs & SPDMEM_DDR_MASK_REG)?
560 1.1 pgoyette " (registered)":"",
561 1.1 pgoyette (s->sm_config < __arraycount(spdmem_parity_types))?
562 1.1 pgoyette spdmem_parity_types[s->sm_config]:"invalid parity");
563 1.1 pgoyette
564 1.1 pgoyette dimm_size = 1 << (s->sm_ddr.ddr_rows + s->sm_ddr.ddr_cols - 17);
565 1.1 pgoyette dimm_size *= s->sm_ddr.ddr_ranks * s->sm_ddr.ddr_banks_per_chip;
566 1.1 pgoyette
567 1.1 pgoyette cycle_time = s->sm_ddr.ddr_cycle_whole * 1000 +
568 1.1 pgoyette spdmem_cycle_frac[s->sm_ddr.ddr_cycle_tenths];
569 1.1 pgoyette bits = le16toh(s->sm_ddr.ddr_datawidth);
570 1.1 pgoyette if (s->sm_config == 1 || s->sm_config == 2)
571 1.1 pgoyette bits -= 8;
572 1.3 pgoyette decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
573 1.3 pgoyette "PC", 0);
574 1.1 pgoyette
575 1.1 pgoyette aprint_verbose_dev(self,
576 1.1 pgoyette "%d rows, %d cols, %d ranks, %d banks/chip, %d.%dns cycle time\n",
577 1.1 pgoyette s->sm_ddr.ddr_rows, s->sm_ddr.ddr_cols, s->sm_ddr.ddr_ranks,
578 1.1 pgoyette s->sm_ddr.ddr_banks_per_chip, cycle_time/1000,
579 1.1 pgoyette (cycle_time % 1000 + 50) / 100);
580 1.1 pgoyette
581 1.1 pgoyette tAA = 0;
582 1.1 pgoyette for (i = 2; i < 8; i++)
583 1.1 pgoyette if (s->sm_ddr.ddr_tCAS & (1 << i))
584 1.1 pgoyette tAA = i;
585 1.1 pgoyette tAA /= 2;
586 1.1 pgoyette
587 1.1 pgoyette #define __DDR_ROUND(scale, field) \
588 1.1 pgoyette ((scale * s->sm_ddr.field + cycle_time - 1) / cycle_time)
589 1.1 pgoyette
590 1.4 christos aprint_verbose_dev(self, LATENCY, tAA, __DDR_ROUND(250, ddr_tRCD),
591 1.1 pgoyette __DDR_ROUND(250, ddr_tRP), __DDR_ROUND(1000, ddr_tRAS));
592 1.1 pgoyette
593 1.1 pgoyette #undef __DDR_ROUND
594 1.1 pgoyette
595 1.1 pgoyette decode_voltage_refresh(self, s);
596 1.1 pgoyette }
597 1.1 pgoyette
598 1.1 pgoyette static void
599 1.1 pgoyette decode_ddr2(const struct sysctlnode *node, device_t self, struct spdmem *s) {
600 1.1 pgoyette int dimm_size, cycle_time, bits, tAA, i;
601 1.1 pgoyette
602 1.5.2.2 yamt aprint_naive("\n");
603 1.5.2.2 yamt aprint_normal("\n");
604 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
605 1.5.2.2 yamt
606 1.1 pgoyette aprint_normal("%s, %s, ",
607 1.1 pgoyette (s->sm_ddr2.ddr2_mod_attrs & SPDMEM_DDR2_MASK_REG)?
608 1.1 pgoyette " (registered)":"",
609 1.1 pgoyette (s->sm_config < __arraycount(spdmem_parity_types))?
610 1.1 pgoyette spdmem_parity_types[s->sm_config]:"invalid parity");
611 1.1 pgoyette
612 1.1 pgoyette dimm_size = 1 << (s->sm_ddr2.ddr2_rows + s->sm_ddr2.ddr2_cols - 17);
613 1.1 pgoyette dimm_size *= (s->sm_ddr2.ddr2_ranks + 1) *
614 1.1 pgoyette s->sm_ddr2.ddr2_banks_per_chip;
615 1.1 pgoyette
616 1.1 pgoyette cycle_time = s->sm_ddr2.ddr2_cycle_whole * 1000 +
617 1.1 pgoyette spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac];
618 1.1 pgoyette bits = s->sm_ddr2.ddr2_datawidth;
619 1.1 pgoyette if ((s->sm_config & 0x03) != 0)
620 1.1 pgoyette bits -= 8;
621 1.3 pgoyette decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
622 1.3 pgoyette "PC2", 0);
623 1.1 pgoyette
624 1.1 pgoyette aprint_verbose_dev(self,
625 1.1 pgoyette "%d rows, %d cols, %d ranks, %d banks/chip, %d.%02dns cycle time\n",
626 1.1 pgoyette s->sm_ddr2.ddr2_rows, s->sm_ddr2.ddr2_cols,
627 1.1 pgoyette s->sm_ddr2.ddr2_ranks + 1, s->sm_ddr2.ddr2_banks_per_chip,
628 1.1 pgoyette cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
629 1.1 pgoyette
630 1.1 pgoyette tAA = 0;
631 1.1 pgoyette for (i = 2; i < 8; i++)
632 1.1 pgoyette if (s->sm_ddr2.ddr2_tCAS & (1 << i))
633 1.1 pgoyette tAA = i;
634 1.1 pgoyette
635 1.1 pgoyette #define __DDR2_ROUND(scale, field) \
636 1.1 pgoyette ((scale * s->sm_ddr2.field + cycle_time - 1) / cycle_time)
637 1.1 pgoyette
638 1.4 christos aprint_verbose_dev(self, LATENCY, tAA, __DDR2_ROUND(250, ddr2_tRCD),
639 1.1 pgoyette __DDR2_ROUND(250, ddr2_tRP), __DDR2_ROUND(1000, ddr2_tRAS));
640 1.1 pgoyette
641 1.1 pgoyette #undef __DDR_ROUND
642 1.1 pgoyette
643 1.1 pgoyette decode_voltage_refresh(self, s);
644 1.1 pgoyette }
645 1.1 pgoyette
646 1.1 pgoyette static void
647 1.1 pgoyette decode_ddr3(const struct sysctlnode *node, device_t self, struct spdmem *s) {
648 1.1 pgoyette int dimm_size, cycle_time, bits;
649 1.1 pgoyette
650 1.5.2.2 yamt aprint_naive("\n");
651 1.5.2.2 yamt aprint_normal(": %18s\n", s->sm_ddr3.ddr3_part);
652 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
653 1.5.2.2 yamt
654 1.1 pgoyette if (s->sm_ddr3.ddr3_mod_type ==
655 1.1 pgoyette SPDMEM_DDR3_TYPE_MINI_RDIMM ||
656 1.1 pgoyette s->sm_ddr3.ddr3_mod_type == SPDMEM_DDR3_TYPE_RDIMM)
657 1.1 pgoyette aprint_normal(" (registered)");
658 1.1 pgoyette aprint_normal(", %sECC, %stemp-sensor, ",
659 1.1 pgoyette (s->sm_ddr3.ddr3_hasECC)?"":"no ",
660 1.1 pgoyette (s->sm_ddr3.ddr3_has_therm_sensor)?"":"no ");
661 1.1 pgoyette
662 1.1 pgoyette /*
663 1.1 pgoyette * DDR3 size specification is quite different from others
664 1.1 pgoyette *
665 1.1 pgoyette * Module capacity is defined as
666 1.1 pgoyette * Chip_Capacity_in_bits / 8bits-per-byte *
667 1.1 pgoyette * external_bus_width / internal_bus_width
668 1.1 pgoyette * We further divide by 2**20 to get our answer in MB
669 1.1 pgoyette */
670 1.1 pgoyette dimm_size = (s->sm_ddr3.ddr3_chipsize + 28 - 20) - 3 +
671 1.1 pgoyette (s->sm_ddr3.ddr3_datawidth + 3) -
672 1.1 pgoyette (s->sm_ddr3.ddr3_chipwidth + 2);
673 1.1 pgoyette dimm_size = (1 << dimm_size) * (s->sm_ddr3.ddr3_physbanks + 1);
674 1.1 pgoyette
675 1.1 pgoyette cycle_time = (1000 * s->sm_ddr3.ddr3_mtb_dividend +
676 1.1 pgoyette (s->sm_ddr3.ddr3_mtb_divisor / 2)) /
677 1.1 pgoyette s->sm_ddr3.ddr3_mtb_divisor;
678 1.1 pgoyette cycle_time *= s->sm_ddr3.ddr3_tCKmin;
679 1.1 pgoyette bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3);
680 1.3 pgoyette decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, FALSE,
681 1.3 pgoyette "PC3", 0);
682 1.1 pgoyette
683 1.1 pgoyette aprint_verbose_dev(self,
684 1.1 pgoyette "%d rows, %d cols, %d log. banks, %d phys. banks, "
685 1.1 pgoyette "%d.%03dns cycle time\n",
686 1.1 pgoyette s->sm_ddr3.ddr3_rows + 9, s->sm_ddr3.ddr3_cols + 12,
687 1.1 pgoyette 1 << (s->sm_ddr3.ddr3_logbanks + 3),
688 1.1 pgoyette s->sm_ddr3.ddr3_physbanks + 1,
689 1.1 pgoyette cycle_time/1000, cycle_time % 1000);
690 1.1 pgoyette
691 1.1 pgoyette #define __DDR3_CYCLES(field) (s->sm_ddr3.field / s->sm_ddr3.ddr3_tCKmin)
692 1.1 pgoyette
693 1.4 christos aprint_verbose_dev(self, LATENCY, __DDR3_CYCLES(ddr3_tAAmin),
694 1.1 pgoyette __DDR3_CYCLES(ddr3_tRCDmin), __DDR3_CYCLES(ddr3_tRPmin),
695 1.1 pgoyette (s->sm_ddr3.ddr3_tRAS_msb * 256 + s->sm_ddr3.ddr3_tRAS_lsb) /
696 1.1 pgoyette s->sm_ddr3.ddr3_tCKmin);
697 1.1 pgoyette
698 1.1 pgoyette #undef __DDR3_CYCLES
699 1.1 pgoyette }
700 1.1 pgoyette
701 1.1 pgoyette static void
702 1.1 pgoyette decode_fbdimm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
703 1.1 pgoyette int dimm_size, cycle_time, bits;
704 1.1 pgoyette
705 1.5.2.2 yamt aprint_naive("\n");
706 1.5.2.2 yamt aprint_normal("\n");
707 1.5.2.2 yamt aprint_normal_dev(self, "%s", spdmem_basic_types[s->sm_type]);
708 1.5.2.2 yamt
709 1.1 pgoyette /*
710 1.1 pgoyette * FB-DIMM module size calculation is very much like DDR3
711 1.1 pgoyette */
712 1.1 pgoyette dimm_size = s->sm_fbd.fbdimm_rows + 12 +
713 1.1 pgoyette s->sm_fbd.fbdimm_cols + 9 - 20 - 3;
714 1.1 pgoyette dimm_size = (1 << dimm_size) * (1 << (s->sm_fbd.fbdimm_banks + 2));
715 1.1 pgoyette
716 1.1 pgoyette cycle_time = (1000 * s->sm_fbd.fbdimm_mtb_dividend +
717 1.1 pgoyette (s->sm_fbd.fbdimm_mtb_divisor / 2)) /
718 1.1 pgoyette s->sm_fbd.fbdimm_mtb_divisor;
719 1.1 pgoyette bits = 1 << (s->sm_fbd.fbdimm_dev_width + 2);
720 1.3 pgoyette decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
721 1.3 pgoyette "PC2", 0);
722 1.1 pgoyette
723 1.1 pgoyette aprint_verbose_dev(self,
724 1.1 pgoyette "%d rows, %d cols, %d banks, %d.%02dns cycle time\n",
725 1.1 pgoyette s->sm_fbd.fbdimm_rows, s->sm_fbd.fbdimm_cols,
726 1.1 pgoyette 1 << (s->sm_fbd.fbdimm_banks + 2),
727 1.1 pgoyette cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
728 1.1 pgoyette
729 1.1 pgoyette #define __FBDIMM_CYCLES(field) (s->sm_fbd.field / s->sm_fbd.fbdimm_tCKmin)
730 1.1 pgoyette
731 1.4 christos aprint_verbose_dev(self, LATENCY, __FBDIMM_CYCLES(fbdimm_tAAmin),
732 1.1 pgoyette __FBDIMM_CYCLES(fbdimm_tRCDmin), __FBDIMM_CYCLES(fbdimm_tRPmin),
733 1.1 pgoyette (s->sm_fbd.fbdimm_tRAS_msb * 256 +
734 1.1 pgoyette s->sm_fbd.fbdimm_tRAS_lsb) /
735 1.1 pgoyette s->sm_fbd.fbdimm_tCKmin);
736 1.1 pgoyette
737 1.1 pgoyette #undef __FBDIMM_CYCLES
738 1.1 pgoyette
739 1.1 pgoyette decode_voltage_refresh(self, s);
740 1.1 pgoyette }
741