2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Authors: Ravi Pokala (rpokala@freebsd.org), Andriy Gapon (avg@FreeBSD.org)
6 * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
7 * Copyright (c) 2018 Panasas
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * This driver is a super-set of jedec_ts(4), and most of the code for reading
36 * and reporting the temperature is either based on that driver, or copied
40 #include <sys/param.h>
41 #include <sys/kernel.h>
43 #include <sys/endian.h>
44 #include <sys/malloc.h>
45 #include <sys/module.h>
46 #include <sys/sysctl.h>
47 #include <sys/systm.h>
49 #include <dev/jedec_dimm/jedec_dimm.h>
50 #include <dev/smbus/smbconf.h>
51 #include <dev/smbus/smbus.h>
55 struct jedec_dimm_softc {
58 uint8_t spd_addr; /* SMBus address of the SPD EEPROM. */
59 uint8_t tsod_addr; /* Address of the Thermal Sensor On DIMM */
62 char part_str[21]; /* 18 (DDR3) or 20 (DDR4) chars, plus terminator */
63 char serial_str[9]; /* 4 bytes = 8 nybble characters, plus terminator */
64 char *slotid_str; /* Optional DIMM slot identifier (silkscreen) */
67 /* General Thermal Sensor on DIMM (TSOD) identification notes.
69 * The JEDEC TSE2004av specification defines the device ID that all compliant
70 * devices should use, but very few do in practice. Maybe that's because the
71 * earlier TSE2002av specification was rather vague about that.
72 * Rare examples are IDT TSE2004GB2B0 and Atmel AT30TSE004A, not sure if
73 * they are TSE2004av compliant by design or by accident.
74 * Also, the specification mandates that PCI SIG manufacturer IDs are to be
75 * used, but in practice the JEDEC manufacturer IDs are often used.
77 const struct jedec_dimm_tsod_dev {
80 const char *description;
81 } known_tsod_devices[] = {
82 /* Analog Devices ADT7408.
83 * http://www.analog.com/media/en/technical-documentation/data-sheets/ADT7408.pdf
85 { 0x11d4, 0x08, "Analog Devices TSOD" },
87 /* Atmel AT30TSE002B, AT30TSE004A.
88 * http://www.atmel.com/images/doc8711.pdf
89 * http://www.atmel.com/images/atmel-8868-dts-at30tse004a-datasheet.pdf
90 * Note how one chip uses the JEDEC Manufacturer ID while the other
91 * uses the PCI SIG one.
93 { 0x001f, 0x82, "Atmel TSOD" },
94 { 0x1114, 0x22, "Atmel TSOD" },
96 /* Integrated Device Technology (IDT) TS3000B3A, TSE2002B3C,
97 * TSE2004GB2B0 chips and their variants.
98 * http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
99 * http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
100 * https://www.idt.com/document/dst/tse2004gb2b0-datasheet
102 { 0x00b3, 0x29, "IDT TSOD" },
103 { 0x00b3, 0x22, "IDT TSOD" },
105 /* Maxim Integrated MAX6604.
106 * Different document revisions specify different Device IDs.
107 * Document 19-3837; Rev 0; 10/05 has 0x3e00 while
108 * 19-3837; Rev 3; 10/11 has 0x5400.
109 * http://datasheets.maximintegrated.com/en/ds/MAX6604.pdf
111 { 0x004d, 0x3e, "Maxim Integrated TSOD" },
112 { 0x004d, 0x54, "Maxim Integrated TSOD" },
114 /* Microchip Technology MCP9805, MCP9843, MCP98242, MCP98243
115 * and their variants.
116 * http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
117 * Microchip Technology EMC1501.
118 * http://ww1.microchip.com/downloads/en/DeviceDoc/00001605A.pdf
120 { 0x0054, 0x00, "Microchip TSOD" },
121 { 0x0054, 0x20, "Microchip TSOD" },
122 { 0x0054, 0x21, "Microchip TSOD" },
123 { 0x1055, 0x08, "Microchip TSOD" },
125 /* NXP Semiconductors SE97 and SE98.
126 * http://www.nxp.com/docs/en/data-sheet/SE97B.pdf
128 { 0x1131, 0xa1, "NXP TSOD" },
129 { 0x1131, 0xa2, "NXP TSOD" },
131 /* ON Semiconductor CAT34TS02 revisions B and C, CAT6095 and compatible.
132 * https://www.onsemi.com/pub/Collateral/CAT34TS02-D.PDF
133 * http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
135 { 0x1b09, 0x08, "ON Semiconductor TSOD" },
136 { 0x1b09, 0x0a, "ON Semiconductor TSOD" },
138 /* ST[Microelectronics] STTS424E02, STTS2002 and others.
139 * http://www.st.com/resource/en/datasheet/cd00157558.pdf
140 * http://www.st.com/resource/en/datasheet/stts2002.pdf
142 { 0x104a, 0x00, "ST Microelectronics TSOD" },
143 { 0x104a, 0x03, "ST Microelectronics TSOD" },
146 static int jedec_dimm_attach(device_t dev);
148 static int jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
149 uint32_t *capacity_mb);
151 static int jedec_dimm_detach(device_t dev);
153 static int jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type);
155 static int jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst,
156 size_t dstsz, uint16_t offset, uint16_t len, bool ascii);
158 static int jedec_dimm_probe(device_t dev);
160 static int jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg,
163 static int jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS);
165 static const char *jedec_dimm_tsod_match(uint16_t vid, uint16_t did);
169 * device_attach() method. Read the DRAM type, use that to determine the offsets
170 * and lengths of the asset string fields. Calculate the capacity. If a TSOD is
171 * present, figure out exactly what it is, and update the device description.
172 * If all of that was successful, create the sysctls for the DIMM. If an
173 * optional slotid has been hinted, create a sysctl for that too.
178 * Device being attached.
181 jedec_dimm_attach(device_t dev)
185 uint16_t partnum_len;
186 uint16_t partnum_offset;
188 uint16_t serial_offset;
189 uint16_t tsod_present_offset;
195 struct jedec_dimm_softc *sc;
196 struct sysctl_ctx_list *ctx;
197 struct sysctl_oid *oid;
198 struct sysctl_oid_list *children;
199 const char *tsod_match;
200 const char *slotid_str;
203 sc = device_get_softc(dev);
204 ctx = device_get_sysctl_ctx(dev);
205 oid = device_get_sysctl_tree(dev);
206 children = SYSCTL_CHILDREN(oid);
208 bzero(sc, sizeof(*sc));
210 sc->smbus = device_get_parent(dev);
211 sc->spd_addr = smbus_get_addr(dev);
213 /* The TSOD address has a different DTI from the SPD address, but shares
216 sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f);
218 /* Read the DRAM type, and set the various offsets and lengths. */
219 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte);
221 device_printf(dev, "failed to read dram_type: %d\n", rc);
224 type = (enum dram_type) byte;
226 case DRAM_TYPE_DDR3_SDRAM:
227 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3");
228 partnum_len = SPD_LEN_DDR3_PARTNUM;
229 partnum_offset = SPD_OFFSET_DDR3_PARTNUM;
230 serial_len = SPD_LEN_DDR3_SERIAL;
231 serial_offset = SPD_OFFSET_DDR3_SERIAL;
232 tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT;
234 case DRAM_TYPE_DDR4_SDRAM:
235 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4");
236 partnum_len = SPD_LEN_DDR4_PARTNUM;
237 partnum_offset = SPD_OFFSET_DDR4_PARTNUM;
238 serial_len = SPD_LEN_DDR4_SERIAL;
239 serial_offset = SPD_OFFSET_DDR4_SERIAL;
240 tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT;
243 device_printf(dev, "unsupported dram_type 0x%02x\n", type);
249 /* bootverbose debuggery is best-effort, so ignore the rc. */
250 (void) jedec_dimm_dump(sc, type);
253 /* Read all the required info from the SPD. If any of it fails, error
254 * out without creating the sysctls.
256 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb);
261 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str),
262 partnum_offset, partnum_len, true);
267 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str),
268 serial_offset, serial_len, false);
273 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD
274 * is in fact present. If it is, read manufacturer and device info from
275 * it to confirm that it's a valid TSOD device. It's an error if any of
276 * those bytes are unreadable; it's not an error if the device is simply
277 * not known to us (tsod_match == NULL).
278 * While DDR3 and DDR4 don't explicitly require a TSOD, essentially all
279 * DDR3 and DDR4 DIMMs include one.
281 rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte);
283 device_printf(dev, "failed to read TSOD-present byte: %d\n",
289 rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid);
292 "failed to read TSOD Manufacturer ID\n");
295 rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid);
297 device_printf(dev, "failed to read TSOD Device ID\n");
301 tsod_match = jedec_dimm_tsod_match(vendorid, devid);
303 if (tsod_match == NULL) {
305 "Unknown TSOD Manufacturer and Device IDs,"
306 " 0x%x and 0x%x\n", vendorid, devid);
309 "TSOD: %s\n", tsod_match);
314 tsod_present = false;
317 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type",
318 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0,
321 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity",
322 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb,
323 "DIMM capacity (MB)");
325 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part",
326 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0,
329 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial",
330 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0,
331 "DIMM Serial Number");
333 /* Create the temperature sysctl IFF the TSOD is present and valid */
334 if (tsod_present && (tsod_match != NULL)) {
335 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp",
336 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
337 jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)");
340 /* If a "slotid" was hinted, add the sysctl for it. */
341 if (resource_string_value(device_get_name(dev), device_get_unit(dev),
342 "slotid", &slotid_str) == 0) {
343 if (slotid_str != NULL) {
344 sc->slotid_str = malloc(strlen(slotid_str) + 1,
345 M_DEVBUF, (M_WAITOK | M_ZERO));
346 strlcpy(sc->slotid_str, slotid_str,
347 sizeof(sc->slotid_str));
348 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid",
349 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0,
350 "DIMM Slot Identifier");
354 /* If a TSOD type string or a slotid are present, add them to the
355 * device description.
357 if ((tsod_match != NULL) || (sc->slotid_str != NULL)) {
358 new_desc_len = strlen(device_get_desc(dev));
359 if (tsod_match != NULL) {
360 new_desc_len += strlen(tsod_match);
361 new_desc_len += 4; /* " w/ " */
363 if (sc->slotid_str != NULL) {
364 new_desc_len += strlen(sc->slotid_str);
365 new_desc_len += 3; /* space + parens */
367 new_desc_len++; /* terminator */
368 new_desc = malloc(new_desc_len, M_TEMP, (M_WAITOK | M_ZERO));
369 (void) snprintf(new_desc, new_desc_len, "%s%s%s%s%s%s",
370 device_get_desc(dev),
371 (tsod_match ? " w/ " : ""),
372 (tsod_match ? tsod_match : ""),
373 (sc->slotid_str ? " (" : ""),
374 (sc->slotid_str ? sc->slotid_str : ""),
375 (sc->slotid_str ? ")" : ""));
376 device_set_desc_copy(dev, new_desc);
377 free(new_desc, M_TEMP);
385 * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry"
386 * information in various SPD bytes. The standards documents codify everything
387 * in look-up tables, but it's trivial to reverse-engineer the the formulas for
388 * most of them. Unless otherwise noted, the same formulas apply for both DDR3
389 * and DDR4. The SPD offsets of where the data comes from are different between
390 * the two types, because having them be the same would be too easy.
395 * Instance-specific context data
397 * @param[in] dram_type
398 * The locations of the data used to calculate the capacity depends on the
401 * @param[out] capacity_mb
402 * The calculated capacity, in MB
405 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
406 uint32_t *capacity_mb)
408 uint8_t bus_width_byte;
409 uint8_t bus_width_offset;
410 uint8_t dimm_ranks_byte;
411 uint8_t dimm_ranks_offset;
412 uint8_t sdram_capacity_byte;
413 uint8_t sdram_capacity_offset;
414 uint8_t sdram_pkg_type_byte;
415 uint8_t sdram_pkg_type_offset;
416 uint8_t sdram_width_byte;
417 uint8_t sdram_width_offset;
420 uint32_t sdram_capacity;
421 uint32_t sdram_pkg_type;
422 uint32_t sdram_width;
426 case DRAM_TYPE_DDR3_SDRAM:
427 bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH;
428 dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS;
429 sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY;
430 sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH;
432 case DRAM_TYPE_DDR4_SDRAM:
433 bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH;
434 dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS;
435 sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY;
436 sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE;
437 sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH;
440 device_printf(sc->dev, "unsupported dram_type 0x%02x\n", type);
445 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset,
448 device_printf(sc->dev, "failed to read bus_width: %d\n", rc);
452 rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset,
455 device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc);
459 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset,
460 &sdram_capacity_byte);
462 device_printf(sc->dev, "failed to read sdram_capacity: %d\n",
467 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset,
470 device_printf(sc->dev, "failed to read sdram_width: %d\n", rc);
474 /* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */
475 if (type == DRAM_TYPE_DDR4_SDRAM) {
476 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset,
477 &sdram_pkg_type_byte);
479 device_printf(sc->dev,
480 "failed to read sdram_pkg_type: %d\n", rc);
485 /* "Primary bus width, in bits" is in bits [2:0]. */
486 bus_width_byte &= 0x07;
487 if (bus_width_byte <= 3) {
488 bus_width = 1 << bus_width_byte;
491 device_printf(sc->dev, "invalid bus width info\n");
496 /* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only
499 dimm_ranks_byte >>= 3;
500 dimm_ranks_byte &= 0x07;
501 if (dimm_ranks_byte <= 7) {
502 dimm_ranks = dimm_ranks_byte + 1;
504 device_printf(sc->dev, "invalid DIMM Rank info\n");
508 if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) {
509 device_printf(sc->dev, "invalid DIMM Rank info\n");
514 /* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two
515 * different formulas, for values 0-7 and for values 8-9. Also, values
516 * 7-9 are only valid for DDR4.
518 sdram_capacity_byte &= 0x0f;
519 if (sdram_capacity_byte <= 7) {
520 sdram_capacity = 1 << sdram_capacity_byte;
521 sdram_capacity *= 256;
522 } else if (sdram_capacity_byte <= 9) {
523 sdram_capacity = 12 << (sdram_capacity_byte - 8);
524 sdram_capacity *= 1024;
526 device_printf(sc->dev, "invalid SDRAM capacity info\n");
530 if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) {
531 device_printf(sc->dev, "invalid SDRAM capacity info\n");
536 /* "SDRAM device width" is in bits [2:0]. */
537 sdram_width_byte &= 0x7;
538 if (sdram_width_byte <= 3) {
539 sdram_width = 1 << sdram_width_byte;
542 device_printf(sc->dev, "invalid SDRAM width info\n");
547 /* DDR4 has something called "3DS", which is indicated by [1:0] = 2;
548 * when that is the case, the die count is encoded in [6:4], and
549 * dimm_ranks is multiplied by it.
551 if ((type == DRAM_TYPE_DDR4_SDRAM) &&
552 ((sdram_pkg_type_byte & 0x3) == 2)) {
553 sdram_pkg_type_byte >>= 4;
554 sdram_pkg_type_byte &= 0x07;
555 sdram_pkg_type = sdram_pkg_type_byte + 1;
556 dimm_ranks *= sdram_pkg_type;
559 /* Finally, assemble the actual capacity. The formula is the same for
560 * both DDR3 and DDR4.
562 *capacity_mb = sdram_capacity / 8 * bus_width / sdram_width *
570 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
571 * didn't allocate, free it anyway; free(NULL) is safe.
576 * Device being detached.
579 jedec_dimm_detach(device_t dev)
581 struct jedec_dimm_softc *sc;
583 sc = device_get_softc(dev);
584 free(sc->slotid_str, M_DEVBUF);
590 * Read and dump the entire SPD contents.
595 * Instance-specific context data
597 * @param[in] dram_type
598 * The length of data which needs to be read and dumped differs based on
599 * the type of the DIMM.
602 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type)
609 page_changed = false;
611 for (i = 0; i < 256; i++) {
612 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]);
614 device_printf(sc->dev,
615 "unable to read page0:0x%02x: %d\n", i, rc);
620 /* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets.
621 * JEDEC gets around this by defining the "PAGE" DTI and LSAs.
623 if (type == DRAM_TYPE_DDR4_SDRAM) {
625 rc = smbus_writeb(sc->smbus,
626 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
628 device_printf(sc->dev, "unable to change page: %d\n",
632 /* Add 256 to the store location, because we're in the second
635 for (i = 0; i < 256; i++) {
636 rc = smbus_readb(sc->smbus, sc->spd_addr, i,
639 device_printf(sc->dev,
640 "unable to read page1:0x%02x: %d\n", i, rc);
646 /* Display the data in a nice hexdump format, with byte offsets. */
647 hexdump(bytes, (page_changed ? 512 : 256), NULL, 0);
652 /* Switch back to page0 before returning. */
653 rc2 = smbus_writeb(sc->smbus,
654 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
656 device_printf(sc->dev, "unable to restore page: %d\n",
664 * Read a specified range of bytes from the SPD, convert them to a string, and
665 * store them in the provided buffer. Some SPD fields are space-padded ASCII,
666 * and some are just a string of bits that we want to convert to a hex string.
671 * Instance-specific context data
674 * The output buffer to populate
677 * The size of the output buffer
680 * The starting offset of the field within the SPD
683 * The length in bytes of the field within the SPD
686 * Is the field a sequence of ASCII characters? If not, it is binary data
687 * which should be converted to characters.
690 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz,
691 uint16_t offset, uint16_t len, bool ascii)
698 /* Change to the proper page. Offsets [0, 255] are in page0; offsets
699 * [256, 512] are in page1.
701 * *The page must be reset to page0 before returning.*
703 * For the page-change operation, only the DTI and LSA matter; the
704 * offset and write-value are ignored, so use just 0.
706 * Mercifully, JEDEC defined the fields such that none of them cross
707 * pages, so we don't need to worry about that complication.
709 if (offset < JEDEC_SPD_PAGE_SIZE) {
710 page_changed = false;
711 } else if (offset < (2 * JEDEC_SPD_PAGE_SIZE)) {
713 rc = smbus_writeb(sc->smbus,
714 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
716 device_printf(sc->dev,
717 "unable to change page for offset 0x%04x: %d\n",
720 /* Adjust the offset to account for the page change. */
721 offset -= JEDEC_SPD_PAGE_SIZE;
723 page_changed = false;
725 device_printf(sc->dev, "invalid offset 0x%04x\n", offset);
729 /* Sanity-check (adjusted) offset and length; everything must be within
732 if (offset >= JEDEC_SPD_PAGE_SIZE) {
734 device_printf(sc->dev, "invalid offset 0x%04x\n", offset);
737 if ((offset + len) >= JEDEC_SPD_PAGE_SIZE) {
739 device_printf(sc->dev,
740 "(offset + len) would cross page (0x%04x + 0x%04x)\n",
745 /* Sanity-check the destination string length. If we're dealing with
746 * ASCII chars, then the destination must be at least the same length;
747 * otherwise, it must be *twice* the length, because each byte must
748 * be converted into two nybble characters.
750 * And, of course, there needs to be an extra byte for the terminator.
753 if (dstsz < (len + 1)) {
755 device_printf(sc->dev,
756 "destination too short (%u < %u)\n",
757 (uint16_t) dstsz, (len + 1));
761 if (dstsz < ((2 * len) + 1)) {
763 device_printf(sc->dev,
764 "destination too short (%u < %u)\n",
765 (uint16_t) dstsz, ((2 * len) + 1));
770 /* Read a byte at a time. */
771 for (i = 0; i < len; i++) {
772 rc = smbus_readb(sc->smbus, sc->spd_addr, (offset + i), &byte);
774 device_printf(sc->dev,
775 "failed to read byte at 0x%02x: %d\n",
780 /* chars can be copied directly. */
783 /* Raw bytes need to be converted to a two-byte hex
784 * string, plus the terminator.
786 (void) snprintf(&dst[(2 * i)], 3, "%02x", byte);
790 /* If we're dealing with ASCII, convert trailing spaces to NULs. */
792 for (i = dstsz; i > 0; i--) {
795 } else if (dst[i] == 0) {
806 /* Switch back to page0 before returning. */
807 rc2 = smbus_writeb(sc->smbus,
808 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
810 device_printf(sc->dev,
811 "unable to restore page for offset 0x%04x: %d\n",
820 * device_probe() method. Validate the address that was given as a hint, and
821 * display an error if it's bogus. Make sure that we're dealing with one of the
822 * SPD versions that we can handle.
827 * Device being probed.
830 jedec_dimm_probe(device_t dev)
838 smbus = device_get_parent(dev);
839 addr = smbus_get_addr(dev);
841 /* Don't bother if this isn't an SPD address, or if the LSBit is set. */
842 if (((addr & 0xf0) != JEDEC_DTI_SPD) ||
843 ((addr & 0x01) != 0)) {
845 "invalid \"addr\" hint; address must start with \"0x%x\","
846 " and the least-significant bit must be 0\n",
852 /* Try to read the DRAM_TYPE from the SPD. */
853 rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte);
855 device_printf(dev, "failed to read dram_type\n");
859 /* This driver currently only supports DDR3 and DDR4 SPDs. */
860 type = (enum dram_type) byte;
862 case DRAM_TYPE_DDR3_SDRAM:
863 rc = BUS_PROBE_DEFAULT;
864 device_set_desc(dev, "DDR3 DIMM");
866 case DRAM_TYPE_DDR4_SDRAM:
867 rc = BUS_PROBE_DEFAULT;
868 device_set_desc(dev, "DDR4 DIMM");
880 * SMBus specifies little-endian byte order, but it looks like the TSODs use
881 * big-endian. Read and convert.
886 * Instance-specific context data
889 * The register number to read.
892 * Pointer to populate with the value read.
895 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val)
899 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val);
903 *val = be16toh(*val);
910 * Read the temperature data from the TSOD and convert it to the deciKelvin
911 * value that the sysctl expects.
916 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)
922 struct jedec_dimm_softc *sc;
924 sc = device_get_softc(dev);
926 rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val);
931 /* The three MSBits are flags, and the next bit is a sign bit. */
933 if ((val & 0x1000) != 0)
935 /* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */
937 /* ... and then convert to 1000ths of a Kelvin */
939 /* As a practical matter, few (if any) TSODs are more accurate than
940 * about a tenth of a degree, so round accordingly. This correlates with
941 * the "IK" formatting used for this sysctl.
943 temp = (temp + 500) / 1000;
945 rc = sysctl_handle_int(oidp, &temp, 0, req);
952 * Check the TSOD's Vendor ID and Device ID against the list of known TSOD
953 * devices. Return the description, or NULL if this doesn't look like a valid
959 * The Vendor ID of the TSOD device
962 * The Device ID of the TSOD device
965 * The description string, or NULL for a failure to match.
968 jedec_dimm_tsod_match(uint16_t vid, uint16_t did)
970 const struct jedec_dimm_tsod_dev *d;
973 for (i = 0; i < nitems(known_tsod_devices); i++) {
974 d = &known_tsod_devices[i];
975 if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) {
976 return (d->description);
980 /* If no matches for a specific device, then check for a generic
981 * TSE2004av-compliant device.
983 if ((did >> 8) == 0x22) {
984 return ("TSE2004av compliant TSOD");
990 static device_method_t jedec_dimm_methods[] = {
991 /* Methods from the device interface */
992 DEVMETHOD(device_probe, jedec_dimm_probe),
993 DEVMETHOD(device_attach, jedec_dimm_attach),
994 DEVMETHOD(device_detach, jedec_dimm_detach),
998 static driver_t jedec_dimm_driver = {
999 .name = "jedec_dimm",
1000 .methods = jedec_dimm_methods,
1001 .size = sizeof(struct jedec_dimm_softc),
1004 static devclass_t jedec_dimm_devclass;
1006 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, jedec_dimm_devclass, 0, 0);
1007 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1008 MODULE_VERSION(jedec_dimm, 1);
1010 /* vi: set ts=8 sw=4 sts=8 noet: */