1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Authors: Ravi Pokala (rpokala@freebsd.org), Andriy Gapon (avg@FreeBSD.org)
5 *
6 * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
7 * Copyright (c) 2018-2023 Panasas
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 /*
32 * This driver is a super-set of the now-deleted jedec_ts(4), and most of the
33 * code for reading and reporting the temperature is either based on that driver,
34 * or copied from it verbatim.
35 */
36
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/bus.h>
40 #include <sys/endian.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/sysctl.h>
44 #include <sys/systm.h>
45
46 #include <dev/jedec_dimm/jedec_dimm.h>
47 #include <dev/smbus/smbconf.h>
48 #include <dev/smbus/smbus.h>
49
50 #include "smbus_if.h"
51
52 struct jedec_dimm_softc {
53 device_t dev;
54 device_t smbus;
55 uint8_t spd_addr; /* SMBus address of the SPD EEPROM. */
56 uint8_t tsod_addr; /* Address of the Thermal Sensor On DIMM */
57 uint8_t mfg_year;
58 uint8_t mfg_week;
59 uint32_t capacity_mb;
60 char type_str[5];
61 char part_str[21]; /* 18 (DDR3) or 20 (DDR4) chars, plus terminator */
62 char serial_str[9]; /* 4 bytes = 8 nybble characters, plus terminator */
63 char *slotid_str; /* Optional DIMM slot identifier (silkscreen) */
64 };
65
66 /* General Thermal Sensor on DIMM (TSOD) identification notes.
67 *
68 * The JEDEC TSE2004av specification defines the device ID that all compliant
69 * devices should use, but very few do in practice. Maybe that's because the
70 * earlier TSE2002av specification was rather vague about that.
71 * Rare examples are IDT TSE2004GB2B0 and Atmel AT30TSE004A, not sure if
72 * they are TSE2004av compliant by design or by accident.
73 * Also, the specification mandates that PCI SIG manufacturer IDs are to be
74 * used, but in practice the JEDEC manufacturer IDs are often used.
75 */
76 const struct jedec_dimm_tsod_dev {
77 uint16_t vendor_id;
78 uint8_t device_id;
79 const char *description;
80 } known_tsod_devices[] = {
81 /* Analog Devices ADT7408.
82 * http://www.analog.com/media/en/technical-documentation/data-sheets/ADT7408.pdf
83 */
84 { 0x11d4, 0x08, "Analog Devices TSOD" },
85
86 /* Atmel AT30TSE002B, AT30TSE004A.
87 * http://www.atmel.com/images/doc8711.pdf
88 * http://www.atmel.com/images/atmel-8868-dts-at30tse004a-datasheet.pdf
89 * Note how one chip uses the JEDEC Manufacturer ID while the other
90 * uses the PCI SIG one.
91 */
92 { 0x001f, 0x82, "Atmel TSOD" },
93 { 0x1114, 0x22, "Atmel TSOD" },
94
95 /* Integrated Device Technology (IDT) TS3000B3A, TSE2002B3C,
96 * TSE2004GB2B0 chips and their variants.
97 * http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
98 * http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
99 * https://www.idt.com/document/dst/tse2004gb2b0-datasheet
100 */
101 { 0x00b3, 0x29, "IDT TSOD" },
102 { 0x00b3, 0x22, "IDT TSOD" },
103
104 /* Maxim Integrated MAX6604.
105 * Different document revisions specify different Device IDs.
106 * Document 19-3837; Rev 0; 10/05 has 0x3e00 while
107 * 19-3837; Rev 3; 10/11 has 0x5400.
108 * http://datasheets.maximintegrated.com/en/ds/MAX6604.pdf
109 */
110 { 0x004d, 0x3e, "Maxim Integrated TSOD" },
111 { 0x004d, 0x54, "Maxim Integrated TSOD" },
112
113 /* Microchip Technology MCP9805, MCP9843, MCP98242, MCP98243
114 * and their variants.
115 * http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
116 * Microchip Technology EMC1501.
117 * http://ww1.microchip.com/downloads/en/DeviceDoc/00001605A.pdf
118 */
119 { 0x0054, 0x00, "Microchip TSOD" },
120 { 0x0054, 0x20, "Microchip TSOD" },
121 { 0x0054, 0x21, "Microchip TSOD" },
122 { 0x1055, 0x08, "Microchip TSOD" },
123
124 /* NXP Semiconductors SE97 and SE98.
125 * http://www.nxp.com/docs/en/data-sheet/SE97B.pdf
126 */
127 { 0x1131, 0xa1, "NXP TSOD" },
128 { 0x1131, 0xa2, "NXP TSOD" },
129
130 /* ON Semiconductor CAT34TS02 revisions B and C, CAT6095 and compatible.
131 * https://www.onsemi.com/pub/Collateral/CAT34TS02-D.PDF
132 * http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
133 */
134 { 0x1b09, 0x08, "ON Semiconductor TSOD" },
135 { 0x1b09, 0x0a, "ON Semiconductor TSOD" },
136
137 /* ST[Microelectronics] STTS424E02, STTS2002 and others.
138 * http://www.st.com/resource/en/datasheet/cd00157558.pdf
139 * http://www.st.com/resource/en/datasheet/stts2002.pdf
140 */
141 { 0x104a, 0x00, "ST Microelectronics TSOD" },
142 { 0x104a, 0x03, "ST Microelectronics TSOD" },
143 };
144
145 static int jedec_dimm_adjust_offset(struct jedec_dimm_softc *sc,
146 uint16_t orig_offset, uint16_t *new_offset, bool *page_changed);
147
148 static int jedec_dimm_attach(device_t dev);
149
150 static int jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
151 uint32_t *capacity_mb);
152
153 static int jedec_dimm_detach(device_t dev);
154
155 static int jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type);
156
157 static int jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst,
158 size_t dstsz, uint16_t offset, uint16_t len, bool ascii);
159
160 static int jedec_dimm_mfg_date(struct jedec_dimm_softc *sc, enum dram_type type,
161 uint8_t *year, uint8_t *week);
162
163 static int jedec_dimm_probe(device_t dev);
164
165 static int jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg,
166 uint16_t *val);
167
168 static int jedec_dimm_reset_page0(struct jedec_dimm_softc *sc);
169
170 static int jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS);
171
172 static const char *jedec_dimm_tsod_match(uint16_t vid, uint16_t did);
173
174
175 /**
176 * The DDR4 SPD information is spread across two 256-byte pages, but the
177 * offsets in the spec are absolute, not per-page. If a given offset is on the
178 * second page, we need to change to that page and adjust the offset to be
179 * relative to that page.
180 *
181 * @author rpokala
182 *
183 * @param[in] sc
184 * Instance-specific context data
185 *
186 * @param[in] orig_offset
187 * The original value of the offset, before any adjustment is made.
188 *
189 * @param[out] new_offset
190 * The offset to actually read from, adjusted if needed.
191 *
192 * @param[out] page_changed
193 * Whether or not the page was actually changed, and the offset adjusted.
194 * *If 'true', caller must call reset_page0() before itself returning.*
195 */
196 static int
jedec_dimm_adjust_offset(struct jedec_dimm_softc * sc,uint16_t orig_offset,uint16_t * new_offset,bool * page_changed)197 jedec_dimm_adjust_offset(struct jedec_dimm_softc *sc, uint16_t orig_offset,
198 uint16_t *new_offset, bool *page_changed)
199 {
200 int rc;
201
202 /* Don't change the offset, or indicate that the page has been changed,
203 * until the page has actually been changed.
204 */
205 *new_offset = orig_offset;
206 *page_changed = false;
207
208 /* Change to the proper page. Offsets [0, 255] are in page0; offsets
209 * [256, 511] are in page1.
210 */
211 if (orig_offset < JEDEC_SPD_PAGE_SIZE) {
212 /* Within page0; no adjustment or page-change required. */
213 rc = 0;
214 goto out;
215 } else if (orig_offset >= (2 * JEDEC_SPD_PAGE_SIZE)) {
216 /* Outside of expected range. */
217 rc = EINVAL;
218 device_printf(sc->dev, "invalid offset 0x%04x\n", orig_offset);
219 goto out;
220 }
221
222 /* 'orig_offset' is in page1. Switch to that page, and adjust
223 * 'new_offset' accordingly if successful.
224 *
225 * For the page-change operation, only the DTI and LSA matter; the
226 * offset and write-value are ignored, so just use 0.
227 */
228 rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1),
229 0, 0);
230 if (rc != 0) {
231 device_printf(sc->dev,
232 "unable to change page for offset 0x%04x: %d\n",
233 orig_offset, rc);
234 goto out;
235 }
236 *page_changed = true;
237 *new_offset = orig_offset - JEDEC_SPD_PAGE_SIZE;
238
239 out:
240 return (rc);
241 }
242
243 /**
244 * device_attach() method. Read the DRAM type, use that to determine the offsets
245 * and lengths of the asset string fields. Calculate the capacity. If a TSOD is
246 * present, figure out exactly what it is, and update the device description.
247 * If all of that was successful, create the sysctls for the DIMM. If an
248 * optional slotid has been hinted, create a sysctl for that too.
249 *
250 * @author rpokala
251 *
252 * @param[in,out] dev
253 * Device being attached.
254 */
255 static int
jedec_dimm_attach(device_t dev)256 jedec_dimm_attach(device_t dev)
257 {
258 uint8_t byte;
259 uint16_t devid;
260 uint16_t partnum_len;
261 uint16_t partnum_offset;
262 uint16_t serial_len;
263 uint16_t serial_offset;
264 uint16_t tsod_present_offset;
265 uint16_t vendorid;
266 bool tsod_present;
267 int rc;
268 enum dram_type type;
269 struct jedec_dimm_softc *sc;
270 struct sysctl_ctx_list *ctx;
271 struct sysctl_oid *oid;
272 struct sysctl_oid_list *children;
273 const char *tsod_match;
274 const char *slotid_str;
275
276 sc = device_get_softc(dev);
277 ctx = device_get_sysctl_ctx(dev);
278 oid = device_get_sysctl_tree(dev);
279 children = SYSCTL_CHILDREN(oid);
280
281 bzero(sc, sizeof(*sc));
282 sc->dev = dev;
283 sc->smbus = device_get_parent(dev);
284 sc->spd_addr = smbus_get_addr(dev);
285
286 /* The TSOD address has a different DTI from the SPD address, but shares
287 * the LSA bits.
288 */
289 sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f);
290
291 /* Read the DRAM type, and set the various offsets and lengths. */
292 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte);
293 if (rc != 0) {
294 device_printf(dev, "failed to read dram_type: %d\n", rc);
295 goto out;
296 }
297 type = (enum dram_type) byte;
298 switch (type) {
299 case DRAM_TYPE_DDR3_SDRAM:
300 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3");
301 partnum_len = SPD_LEN_DDR3_PARTNUM;
302 partnum_offset = SPD_OFFSET_DDR3_PARTNUM;
303 serial_len = SPD_LEN_DDR3_SERIAL;
304 serial_offset = SPD_OFFSET_DDR3_SERIAL;
305 tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT;
306 break;
307 case DRAM_TYPE_DDR4_SDRAM:
308 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4");
309 partnum_len = SPD_LEN_DDR4_PARTNUM;
310 partnum_offset = SPD_OFFSET_DDR4_PARTNUM;
311 serial_len = SPD_LEN_DDR4_SERIAL;
312 serial_offset = SPD_OFFSET_DDR4_SERIAL;
313 tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT;
314 break;
315 default:
316 device_printf(dev, "unsupported dram_type 0x%02x\n", type);
317 rc = EINVAL;
318 goto out;
319 }
320
321 if (bootverbose) {
322 /* bootverbose debuggery is best-effort, so ignore the rc. */
323 (void) jedec_dimm_dump(sc, type);
324 }
325
326 /* Read all the required info from the SPD. If any of it fails, error
327 * out without creating the sysctls.
328 */
329 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb);
330 if (rc != 0) {
331 goto out;
332 }
333
334 rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week);
335 if (rc != 0) {
336 goto out;
337 }
338
339 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str),
340 partnum_offset, partnum_len, true);
341 if (rc != 0) {
342 goto out;
343 }
344
345 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str),
346 serial_offset, serial_len, false);
347 if (rc != 0) {
348 goto out;
349 }
350
351 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD
352 * is in fact present. (While DDR3 and DDR4 don't explicitly require a
353 * TSOD, essentially all DDR3 and DDR4 DIMMs include one.) But, as
354 * discussed in [PR 235944], it turns out that some DIMMs claim to have
355 * a TSOD when they actually don't. (Or maybe the firmware blocks it?)
356 * <sigh>
357 * If the SPD data says the TSOD is present, try to read manufacturer
358 * and device info from it to confirm that it's a valid TSOD device.
359 * If the data is unreadable, just continue as if the TSOD isn't there.
360 * If the data was read successfully, see if it is a known TSOD device;
361 * it's okay if it isn't (tsod_match == NULL).
362 */
363 rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte);
364 if (rc != 0) {
365 device_printf(dev, "failed to read TSOD-present byte: %d\n",
366 rc);
367 goto out;
368 }
369 if (byte & 0x80) {
370 tsod_present = true;
371 rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid);
372 if (rc != 0) {
373 device_printf(dev,
374 "failed to read TSOD Manufacturer ID\n");
375 rc = 0;
376 goto no_tsod;
377 }
378 rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid);
379 if (rc != 0) {
380 device_printf(dev, "failed to read TSOD Device ID\n");
381 rc = 0;
382 goto no_tsod;
383 }
384
385 tsod_match = jedec_dimm_tsod_match(vendorid, devid);
386 if (bootverbose) {
387 if (tsod_match == NULL) {
388 device_printf(dev,
389 "Unknown TSOD Manufacturer and Device IDs,"
390 " 0x%x and 0x%x\n", vendorid, devid);
391 } else {
392 device_printf(dev,
393 "TSOD: %s\n", tsod_match);
394 }
395 }
396 } else {
397 no_tsod:
398 tsod_match = NULL;
399 tsod_present = false;
400 }
401
402 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type",
403 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0,
404 "DIMM type");
405
406 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity",
407 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb,
408 "DIMM capacity (MB)");
409
410 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part",
411 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0,
412 "DIMM Part Number");
413
414 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial",
415 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0,
416 "DIMM Serial Number");
417
418 SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_year",
419 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_year,
420 "DIMM manufacturing year (20xx)");
421
422 SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_week",
423 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_week,
424 "DIMM manufacturing week");
425
426 /* Create the temperature sysctl IFF the TSOD is present and valid */
427 if (tsod_present && (tsod_match != NULL)) {
428 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp",
429 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
430 jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)");
431 }
432
433 /* If a "slotid" was hinted, add the sysctl for it. */
434 if (resource_string_value(device_get_name(dev), device_get_unit(dev),
435 "slotid", &slotid_str) == 0) {
436 if (slotid_str != NULL) {
437 sc->slotid_str = strdup(slotid_str, M_DEVBUF);
438 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid",
439 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0,
440 "DIMM Slot Identifier");
441 }
442 }
443
444 /* If a TSOD type string or a slotid are present, add them to the
445 * device description.
446 */
447 if ((tsod_match != NULL) || (sc->slotid_str != NULL)) {
448 device_set_descf(dev, "%s%s%s%s%s%s",
449 device_get_desc(dev),
450 (tsod_match ? " w/ " : ""),
451 (tsod_match ? tsod_match : ""),
452 (sc->slotid_str ? " (" : ""),
453 (sc->slotid_str ? sc->slotid_str : ""),
454 (sc->slotid_str ? ")" : ""));
455 }
456
457 out:
458 return (rc);
459 }
460
461 /**
462 * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry"
463 * information in various SPD bytes. The standards documents codify everything
464 * in look-up tables, but it's trivial to reverse-engineer the the formulas for
465 * most of them. Unless otherwise noted, the same formulas apply for both DDR3
466 * and DDR4. The SPD offsets of where the data comes from are different between
467 * the two types, because having them be the same would be too easy.
468 *
469 * @author rpokala
470 *
471 * @param[in] sc
472 * Instance-specific context data
473 *
474 * @param[in] dram_type
475 * The locations of the data used to calculate the capacity depends on the
476 * type of the DIMM.
477 *
478 * @param[out] capacity_mb
479 * The calculated capacity, in MB
480 */
481 static int
jedec_dimm_capacity(struct jedec_dimm_softc * sc,enum dram_type type,uint32_t * capacity_mb)482 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
483 uint32_t *capacity_mb)
484 {
485 uint8_t bus_width_byte;
486 uint8_t bus_width_offset;
487 uint8_t dimm_ranks_byte;
488 uint8_t dimm_ranks_offset;
489 uint8_t sdram_capacity_byte;
490 uint8_t sdram_capacity_offset;
491 uint8_t sdram_pkg_type_byte;
492 uint8_t sdram_pkg_type_offset;
493 uint8_t sdram_width_byte;
494 uint8_t sdram_width_offset;
495 uint32_t bus_width;
496 uint32_t dimm_ranks;
497 uint32_t sdram_capacity;
498 uint32_t sdram_pkg_type;
499 uint32_t sdram_width;
500 int rc;
501
502 switch (type) {
503 case DRAM_TYPE_DDR3_SDRAM:
504 bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH;
505 dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS;
506 sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY;
507 sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH;
508 break;
509 case DRAM_TYPE_DDR4_SDRAM:
510 bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH;
511 dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS;
512 sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY;
513 sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE;
514 sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH;
515 break;
516 default:
517 __assert_unreachable();
518 }
519
520 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset,
521 &bus_width_byte);
522 if (rc != 0) {
523 device_printf(sc->dev, "failed to read bus_width: %d\n", rc);
524 goto out;
525 }
526
527 rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset,
528 &dimm_ranks_byte);
529 if (rc != 0) {
530 device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc);
531 goto out;
532 }
533
534 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset,
535 &sdram_capacity_byte);
536 if (rc != 0) {
537 device_printf(sc->dev, "failed to read sdram_capacity: %d\n",
538 rc);
539 goto out;
540 }
541
542 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset,
543 &sdram_width_byte);
544 if (rc != 0) {
545 device_printf(sc->dev, "failed to read sdram_width: %d\n", rc);
546 goto out;
547 }
548
549 /* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */
550 if (type == DRAM_TYPE_DDR4_SDRAM) {
551 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset,
552 &sdram_pkg_type_byte);
553 if (rc != 0) {
554 device_printf(sc->dev,
555 "failed to read sdram_pkg_type: %d\n", rc);
556 goto out;
557 }
558 }
559
560 /* "Primary bus width, in bits" is in bits [2:0]. */
561 bus_width_byte &= 0x07;
562 if (bus_width_byte <= 3) {
563 bus_width = 1 << bus_width_byte;
564 bus_width *= 8;
565 } else {
566 device_printf(sc->dev, "invalid bus width info\n");
567 rc = EINVAL;
568 goto out;
569 }
570
571 /* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only
572 * valid for DDR4.
573 */
574 dimm_ranks_byte >>= 3;
575 dimm_ranks_byte &= 0x07;
576 if (dimm_ranks_byte <= 7) {
577 dimm_ranks = dimm_ranks_byte + 1;
578 } else {
579 device_printf(sc->dev, "invalid DIMM Rank info\n");
580 rc = EINVAL;
581 goto out;
582 }
583 if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) {
584 device_printf(sc->dev, "invalid DIMM Rank info\n");
585 rc = EINVAL;
586 goto out;
587 }
588
589 /* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two
590 * different formulas, for values 0-7 and for values 8-9. Also, values
591 * 7-9 are only valid for DDR4.
592 */
593 sdram_capacity_byte &= 0x0f;
594 if (sdram_capacity_byte <= 7) {
595 sdram_capacity = 1 << sdram_capacity_byte;
596 sdram_capacity *= 256;
597 } else if (sdram_capacity_byte <= 9) {
598 sdram_capacity = 12 << (sdram_capacity_byte - 8);
599 sdram_capacity *= 1024;
600 } else {
601 device_printf(sc->dev, "invalid SDRAM capacity info\n");
602 rc = EINVAL;
603 goto out;
604 }
605 if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) {
606 device_printf(sc->dev, "invalid SDRAM capacity info\n");
607 rc = EINVAL;
608 goto out;
609 }
610
611 /* "SDRAM device width" is in bits [2:0]. */
612 sdram_width_byte &= 0x7;
613 if (sdram_width_byte <= 3) {
614 sdram_width = 1 << sdram_width_byte;
615 sdram_width *= 4;
616 } else {
617 device_printf(sc->dev, "invalid SDRAM width info\n");
618 rc = EINVAL;
619 goto out;
620 }
621
622 /* DDR4 has something called "3DS", which is indicated by [1:0] = 2;
623 * when that is the case, the die count is encoded in [6:4], and
624 * dimm_ranks is multiplied by it.
625 */
626 if ((type == DRAM_TYPE_DDR4_SDRAM) &&
627 ((sdram_pkg_type_byte & 0x3) == 2)) {
628 sdram_pkg_type_byte >>= 4;
629 sdram_pkg_type_byte &= 0x07;
630 sdram_pkg_type = sdram_pkg_type_byte + 1;
631 dimm_ranks *= sdram_pkg_type;
632 }
633
634 /* Finally, assemble the actual capacity. The formula is the same for
635 * both DDR3 and DDR4.
636 */
637 *capacity_mb = sdram_capacity / 8 * bus_width / sdram_width *
638 dimm_ranks;
639
640 out:
641 return (rc);
642 }
643
644 /**
645 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
646 * didn't allocate, free it anyway; free(NULL) is safe.
647 *
648 * @author rpokala
649 *
650 * @param[in,out] dev
651 * Device being detached.
652 */
653 static int
jedec_dimm_detach(device_t dev)654 jedec_dimm_detach(device_t dev)
655 {
656 struct jedec_dimm_softc *sc;
657
658 sc = device_get_softc(dev);
659 free(sc->slotid_str, M_DEVBUF);
660
661 return (0);
662 }
663
664 /**
665 * Read and dump the entire SPD contents.
666 *
667 * @author rpokala
668 *
669 * @param[in] sc
670 * Instance-specific context data
671 *
672 * @param[in] dram_type
673 * The length of data which needs to be read and dumped differs based on
674 * the type of the DIMM.
675 */
676 static int
jedec_dimm_dump(struct jedec_dimm_softc * sc,enum dram_type type)677 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type)
678 {
679 int i;
680 int rc;
681 bool page_changed;
682 uint8_t bytes[512];
683
684 page_changed = false;
685
686 for (i = 0; i < 256; i++) {
687 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]);
688 if (rc != 0) {
689 device_printf(sc->dev,
690 "unable to read page0:0x%02x: %d\n", i, rc);
691 goto out;
692 }
693 }
694
695 /* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets.
696 * JEDEC gets around this by defining the "PAGE" DTI and LSAs.
697 */
698 if (type == DRAM_TYPE_DDR4_SDRAM) {
699 page_changed = true;
700 rc = smbus_writeb(sc->smbus,
701 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
702 if (rc != 0) {
703 /* Some SPD devices (or SMBus controllers?) claim the
704 * page-change command failed when it actually
705 * succeeded. Log a message but soldier on.
706 */
707 device_printf(sc->dev, "unable to change page: %d\n",
708 rc);
709 }
710 /* Add 256 to the store location, because we're in the second
711 * page.
712 */
713 for (i = 0; i < 256; i++) {
714 rc = smbus_readb(sc->smbus, sc->spd_addr, i,
715 &bytes[256 + i]);
716 if (rc != 0) {
717 device_printf(sc->dev,
718 "unable to read page1:0x%02x: %d\n", i, rc);
719 goto out;
720 }
721 }
722 }
723
724 /* Display the data in a nice hexdump format, with byte offsets. */
725 hexdump(bytes, (page_changed ? 512 : 256), NULL, 0);
726
727 out:
728 if (page_changed) {
729 int rc2;
730
731 rc2 = jedec_dimm_reset_page0(sc);
732 if ((rc2 != 0) && (rc == 0)) {
733 rc = rc2;
734 }
735 }
736
737 return (rc);
738 }
739
740 /**
741 * Read a specified range of bytes from the SPD, convert them to a string, and
742 * store them in the provided buffer. Some SPD fields are space-padded ASCII,
743 * and some are just a string of bits that we want to convert to a hex string.
744 *
745 * @author rpokala
746 *
747 * @param[in] sc
748 * Instance-specific context data
749 *
750 * @param[out] dst
751 * The output buffer to populate
752 *
753 * @param[in] dstsz
754 * The size of the output buffer
755 *
756 * @param[in] offset
757 * The starting offset of the field within the SPD
758 *
759 * @param[in] len
760 * The length in bytes of the field within the SPD
761 *
762 * @param[in] ascii
763 * Is the field a sequence of ASCII characters? If not, it is binary data
764 * which should be converted to characters.
765 */
766 static int
jedec_dimm_field_to_str(struct jedec_dimm_softc * sc,char * dst,size_t dstsz,uint16_t offset,uint16_t len,bool ascii)767 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz,
768 uint16_t offset, uint16_t len, bool ascii)
769 {
770 uint8_t byte;
771 uint16_t new_offset;
772 int i;
773 int rc;
774 bool page_changed;
775
776 rc = jedec_dimm_adjust_offset(sc, offset, &new_offset, &page_changed);
777 if (rc != 0) {
778 goto out;
779 }
780
781 /* Sanity-check (adjusted) offset and length; everything must be within
782 * the same page.
783 */
784 if (new_offset >= JEDEC_SPD_PAGE_SIZE) {
785 rc = EINVAL;
786 device_printf(sc->dev, "invalid offset 0x%04x\n", new_offset);
787 goto out;
788 }
789 if ((new_offset + len) >= JEDEC_SPD_PAGE_SIZE) {
790 rc = EINVAL;
791 device_printf(sc->dev,
792 "(new_offset + len) would cross page (0x%04x + 0x%04x)\n",
793 new_offset, len);
794 goto out;
795 }
796
797 /* Sanity-check the destination string length. If we're dealing with
798 * ASCII chars, then the destination must be at least the same length;
799 * otherwise, it must be *twice* the length, because each byte must
800 * be converted into two nybble characters.
801 *
802 * And, of course, there needs to be an extra byte for the terminator.
803 */
804 if (ascii) {
805 if (dstsz < (len + 1)) {
806 rc = EINVAL;
807 device_printf(sc->dev,
808 "destination too short (%u < %u)\n",
809 (uint16_t) dstsz, (len + 1));
810 goto out;
811 }
812 } else {
813 if (dstsz < ((2 * len) + 1)) {
814 rc = EINVAL;
815 device_printf(sc->dev,
816 "destination too short (%u < %u)\n",
817 (uint16_t) dstsz, ((2 * len) + 1));
818 goto out;
819 }
820 }
821
822 /* Read a byte at a time. */
823 for (i = 0; i < len; i++) {
824 rc = smbus_readb(sc->smbus, sc->spd_addr, (new_offset + i),
825 &byte);
826 if (rc != 0) {
827 device_printf(sc->dev,
828 "failed to read byte at 0x%02x: %d\n",
829 (new_offset + i), rc);
830 goto out;
831 }
832 if (ascii) {
833 /* chars can be copied directly. */
834 dst[i] = byte;
835 } else {
836 /* Raw bytes need to be converted to a two-byte hex
837 * string, plus the terminator.
838 */
839 (void) snprintf(&dst[(2 * i)], 3, "%02x", byte);
840 }
841 }
842
843 /* If we're dealing with ASCII, convert trailing spaces to NULs. */
844 if (ascii) {
845 for (i = dstsz - 1; i > 0; i--) {
846 if (dst[i] == ' ') {
847 dst[i] = 0;
848 } else if (dst[i] == 0) {
849 continue;
850 } else {
851 break;
852 }
853 }
854 }
855
856 out:
857 if (page_changed) {
858 int rc2;
859
860 rc2 = jedec_dimm_reset_page0(sc);
861 if ((rc2 != 0) && (rc == 0)) {
862 rc = rc2;
863 }
864 }
865
866 return (rc);
867 }
868
869 /**
870 * Both DDR3 and DDR4 encode manufacturing date as a one-byte BCD-encoded
871 * year (offset from 2000) and a one-byte BCD-encoded week within that year.
872 * The SPD offsets are different between the two types.
873 *
874 * @author rpokala
875 *
876 * @param[in] sc
877 * Instance-specific context data
878 *
879 * @param[in] dram_type
880 * The locations of the manufacturing date depends on the type of the DIMM.
881 *
882 * @param[out] year
883 * The manufacturing year, offset from 2000
884 *
885 * @param[out] week
886 * The manufacturing week within the year
887 */
888 static int
jedec_dimm_mfg_date(struct jedec_dimm_softc * sc,enum dram_type type,uint8_t * year,uint8_t * week)889 jedec_dimm_mfg_date(struct jedec_dimm_softc *sc, enum dram_type type,
890 uint8_t *year, uint8_t *week)
891 {
892 uint8_t year_bcd;
893 uint8_t week_bcd;
894 uint16_t year_offset;
895 uint16_t week_offset;
896 bool page_changed;
897 int rc;
898
899 switch (type) {
900 case DRAM_TYPE_DDR3_SDRAM:
901 year_offset = SPD_OFFSET_DDR3_MOD_MFG_YEAR;
902 week_offset = SPD_OFFSET_DDR3_MOD_MFG_WEEK;
903 break;
904 case DRAM_TYPE_DDR4_SDRAM:
905 year_offset = SPD_OFFSET_DDR4_MOD_MFG_YEAR;
906 week_offset = SPD_OFFSET_DDR4_MOD_MFG_WEEK;
907 break;
908 default:
909 __assert_unreachable();
910 }
911
912 /* Change to the proper page. Offsets [0, 255] are in page0; offsets
913 * [256, 512] are in page1.
914 *
915 * *The page must be reset to page0 before returning.*
916 *
917 * For the page-change operation, only the DTI and LSA matter; the
918 * offset and write-value are ignored, so use just 0.
919 *
920 * Mercifully, JEDEC defined the fields such that all of the
921 * manufacturing-related ones are on the same page, so we don't need to
922 * worry about that complication.
923 */
924 if (year_offset < JEDEC_SPD_PAGE_SIZE) {
925 page_changed = false;
926 } else if (year_offset < (2 * JEDEC_SPD_PAGE_SIZE)) {
927 page_changed = true;
928 rc = smbus_writeb(sc->smbus,
929 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
930 if (rc != 0) {
931 device_printf(sc->dev,
932 "unable to change page for offset 0x%04x: %d\n",
933 year_offset, rc);
934 }
935 /* Adjust the offset to account for the page change. */
936 year_offset -= JEDEC_SPD_PAGE_SIZE;
937 week_offset -= JEDEC_SPD_PAGE_SIZE;
938 } else {
939 device_printf(sc->dev, "invalid offset 0x%04x\n", year_offset);
940 rc = EINVAL;
941 page_changed = false;
942 goto out;
943 }
944
945 rc = smbus_readb(sc->smbus, sc->spd_addr, year_offset, &year_bcd);
946 if (rc != 0) {
947 device_printf(sc->dev, "failed to read mfg year: %d\n", rc);
948 goto out;
949 }
950
951 rc = smbus_readb(sc->smbus, sc->spd_addr, week_offset, &week_bcd);
952 if (rc != 0) {
953 device_printf(sc->dev, "failed to read mfg week: %d\n", rc);
954 goto out;
955 }
956
957 /* Convert from one-byte BCD to one-byte integer. */
958 *year = (((year_bcd & 0xf0) >> 4) * 10) + (year_bcd & 0x0f);
959 *week = (((week_bcd & 0xf0) >> 4) * 10) + (week_bcd & 0x0f);
960
961 out:
962 if (page_changed) {
963 int rc2;
964 /* Switch back to page0 before returning. */
965 rc2 = smbus_writeb(sc->smbus,
966 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
967 if (rc2 != 0) {
968 device_printf(sc->dev,
969 "unable to restore page for offset 0x%04x: %d\n",
970 year_offset, rc2);
971 }
972 }
973
974 return (rc);
975 }
976
977 /**
978 * device_probe() method. Validate the address that was given as a hint, and
979 * display an error if it's bogus. Make sure that we're dealing with one of the
980 * SPD versions that we can handle.
981 *
982 * @author rpokala
983 *
984 * @param[in] dev
985 * Device being probed.
986 */
987 static int
jedec_dimm_probe(device_t dev)988 jedec_dimm_probe(device_t dev)
989 {
990 uint8_t addr;
991 uint8_t byte;
992 int rc;
993 enum dram_type type;
994 device_t smbus;
995
996 smbus = device_get_parent(dev);
997 addr = smbus_get_addr(dev);
998
999 /* Don't bother if this isn't an SPD address, or if the LSBit is set. */
1000 if (((addr & 0xf0) != JEDEC_DTI_SPD) ||
1001 ((addr & 0x01) != 0)) {
1002 device_printf(dev,
1003 "invalid \"addr\" hint; address must start with \"0x%x\","
1004 " and the least-significant bit must be 0\n",
1005 JEDEC_DTI_SPD);
1006 rc = ENXIO;
1007 goto out;
1008 }
1009
1010 /* Try to read the DRAM_TYPE from the SPD. */
1011 rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte);
1012 if (rc != 0) {
1013 device_printf(dev, "failed to read dram_type\n");
1014 goto out;
1015 }
1016
1017 /* This driver currently only supports DDR3 and DDR4 SPDs. */
1018 type = (enum dram_type) byte;
1019 switch (type) {
1020 case DRAM_TYPE_DDR3_SDRAM:
1021 rc = BUS_PROBE_DEFAULT;
1022 device_set_desc(dev, "DDR3 DIMM");
1023 break;
1024 case DRAM_TYPE_DDR4_SDRAM:
1025 rc = BUS_PROBE_DEFAULT;
1026 device_set_desc(dev, "DDR4 DIMM");
1027 break;
1028 default:
1029 rc = ENXIO;
1030 break;
1031 }
1032
1033 out:
1034 return (rc);
1035 }
1036
1037 /**
1038 * SMBus specifies little-endian byte order, but it looks like the TSODs use
1039 * big-endian. Read and convert.
1040 *
1041 * @author avg
1042 *
1043 * @param[in] sc
1044 * Instance-specific context data
1045 *
1046 * @param[in] reg
1047 * The register number to read.
1048 *
1049 * @param[out] val
1050 * Pointer to populate with the value read.
1051 */
1052 static int
jedec_dimm_readw_be(struct jedec_dimm_softc * sc,uint8_t reg,uint16_t * val)1053 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val)
1054 {
1055 int rc;
1056
1057 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val);
1058 if (rc != 0) {
1059 goto out;
1060 }
1061 *val = be16toh(*val);
1062
1063 out:
1064 return (rc);
1065 }
1066
1067 /**
1068 * Reset to the default condition of operating on page0. This must be called
1069 * after a previous operation changed to page1.
1070 *
1071 * @author rpokala
1072 *
1073 * @param[in] sc
1074 * Instance-specific context data
1075 */
1076 static int
jedec_dimm_reset_page0(struct jedec_dimm_softc * sc)1077 jedec_dimm_reset_page0(struct jedec_dimm_softc *sc)
1078 {
1079 int rc;
1080
1081 /* For the page-change operation, only the DTI and LSA matter; the
1082 * offset and write-value are ignored, so just use 0.
1083 */
1084 rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0),
1085 0, 0);
1086 if (rc != 0) {
1087 device_printf(sc->dev, "unable to restore page: %d\n", rc);
1088 }
1089
1090 return (rc);
1091 }
1092
1093 /**
1094 * Read the temperature data from the TSOD and convert it to the deciKelvin
1095 * value that the sysctl expects.
1096 *
1097 * @author avg
1098 */
1099 static int
jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)1100 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)
1101 {
1102 uint16_t val;
1103 int rc;
1104 int temp;
1105 device_t dev = arg1;
1106 struct jedec_dimm_softc *sc;
1107
1108 sc = device_get_softc(dev);
1109
1110 rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val);
1111 if (rc != 0) {
1112 goto out;
1113 }
1114
1115 /* The three MSBits are flags, and the next bit is a sign bit. */
1116 temp = val & 0xfff;
1117 if ((val & 0x1000) != 0)
1118 temp = -temp;
1119 /* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */
1120 temp *= 625;
1121 /* ... and then convert to 1000ths of a Kelvin */
1122 temp += 2731500;
1123 /* As a practical matter, few (if any) TSODs are more accurate than
1124 * about a tenth of a degree, so round accordingly. This correlates with
1125 * the "IK" formatting used for this sysctl.
1126 */
1127 temp = (temp + 500) / 1000;
1128
1129 rc = sysctl_handle_int(oidp, &temp, 0, req);
1130
1131 out:
1132 return (rc);
1133 }
1134
1135 /**
1136 * Check the TSOD's Vendor ID and Device ID against the list of known TSOD
1137 * devices. Return the description, or NULL if this doesn't look like a valid
1138 * TSOD.
1139 *
1140 * @author avg
1141 *
1142 * @param[in] vid
1143 * The Vendor ID of the TSOD device
1144 *
1145 * @param[in] did
1146 * The Device ID of the TSOD device
1147 *
1148 * @return
1149 * The description string, or NULL for a failure to match.
1150 */
1151 static const char *
jedec_dimm_tsod_match(uint16_t vid,uint16_t did)1152 jedec_dimm_tsod_match(uint16_t vid, uint16_t did)
1153 {
1154 const struct jedec_dimm_tsod_dev *d;
1155 int i;
1156
1157 for (i = 0; i < nitems(known_tsod_devices); i++) {
1158 d = &known_tsod_devices[i];
1159 if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) {
1160 return (d->description);
1161 }
1162 }
1163
1164 /* If no matches for a specific device, then check for a generic
1165 * TSE2004av-compliant device.
1166 */
1167 if ((did >> 8) == 0x22) {
1168 return ("TSE2004av compliant TSOD");
1169 }
1170
1171 return (NULL);
1172 }
1173
1174 static device_method_t jedec_dimm_methods[] = {
1175 /* Methods from the device interface */
1176 DEVMETHOD(device_probe, jedec_dimm_probe),
1177 DEVMETHOD(device_attach, jedec_dimm_attach),
1178 DEVMETHOD(device_detach, jedec_dimm_detach),
1179 DEVMETHOD_END
1180 };
1181
1182 static driver_t jedec_dimm_driver = {
1183 .name = "jedec_dimm",
1184 .methods = jedec_dimm_methods,
1185 .size = sizeof(struct jedec_dimm_softc),
1186 };
1187
1188 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, 0, 0);
1189 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1190 MODULE_VERSION(jedec_dimm, 1);
1191
1192 /* vi: set ts=8 sw=4 sts=8 noet: */
1193