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 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 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 int new_desc_len; 269 enum dram_type type; 270 struct jedec_dimm_softc *sc; 271 struct sysctl_ctx_list *ctx; 272 struct sysctl_oid *oid; 273 struct sysctl_oid_list *children; 274 const char *tsod_match; 275 const char *slotid_str; 276 char *new_desc; 277 278 sc = device_get_softc(dev); 279 ctx = device_get_sysctl_ctx(dev); 280 oid = device_get_sysctl_tree(dev); 281 children = SYSCTL_CHILDREN(oid); 282 283 bzero(sc, sizeof(*sc)); 284 sc->dev = dev; 285 sc->smbus = device_get_parent(dev); 286 sc->spd_addr = smbus_get_addr(dev); 287 288 /* The TSOD address has a different DTI from the SPD address, but shares 289 * the LSA bits. 290 */ 291 sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f); 292 293 /* Read the DRAM type, and set the various offsets and lengths. */ 294 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte); 295 if (rc != 0) { 296 device_printf(dev, "failed to read dram_type: %d\n", rc); 297 goto out; 298 } 299 type = (enum dram_type) byte; 300 switch (type) { 301 case DRAM_TYPE_DDR3_SDRAM: 302 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3"); 303 partnum_len = SPD_LEN_DDR3_PARTNUM; 304 partnum_offset = SPD_OFFSET_DDR3_PARTNUM; 305 serial_len = SPD_LEN_DDR3_SERIAL; 306 serial_offset = SPD_OFFSET_DDR3_SERIAL; 307 tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT; 308 break; 309 case DRAM_TYPE_DDR4_SDRAM: 310 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4"); 311 partnum_len = SPD_LEN_DDR4_PARTNUM; 312 partnum_offset = SPD_OFFSET_DDR4_PARTNUM; 313 serial_len = SPD_LEN_DDR4_SERIAL; 314 serial_offset = SPD_OFFSET_DDR4_SERIAL; 315 tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT; 316 break; 317 default: 318 device_printf(dev, "unsupported dram_type 0x%02x\n", type); 319 rc = EINVAL; 320 goto out; 321 } 322 323 if (bootverbose) { 324 /* bootverbose debuggery is best-effort, so ignore the rc. */ 325 (void) jedec_dimm_dump(sc, type); 326 } 327 328 /* Read all the required info from the SPD. If any of it fails, error 329 * out without creating the sysctls. 330 */ 331 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb); 332 if (rc != 0) { 333 goto out; 334 } 335 336 rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week); 337 if (rc != 0) { 338 goto out; 339 } 340 341 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str), 342 partnum_offset, partnum_len, true); 343 if (rc != 0) { 344 goto out; 345 } 346 347 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str), 348 serial_offset, serial_len, false); 349 if (rc != 0) { 350 goto out; 351 } 352 353 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD 354 * is in fact present. (While DDR3 and DDR4 don't explicitly require a 355 * TSOD, essentially all DDR3 and DDR4 DIMMs include one.) But, as 356 * discussed in [PR 235944], it turns out that some DIMMs claim to have 357 * a TSOD when they actually don't. (Or maybe the firmware blocks it?) 358 * <sigh> 359 * If the SPD data says the TSOD is present, try to read manufacturer 360 * and device info from it to confirm that it's a valid TSOD device. 361 * If the data is unreadable, just continue as if the TSOD isn't there. 362 * If the data was read successfully, see if it is a known TSOD device; 363 * it's okay if it isn't (tsod_match == NULL). 364 */ 365 rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte); 366 if (rc != 0) { 367 device_printf(dev, "failed to read TSOD-present byte: %d\n", 368 rc); 369 goto out; 370 } 371 if (byte & 0x80) { 372 tsod_present = true; 373 rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid); 374 if (rc != 0) { 375 device_printf(dev, 376 "failed to read TSOD Manufacturer ID\n"); 377 rc = 0; 378 goto no_tsod; 379 } 380 rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid); 381 if (rc != 0) { 382 device_printf(dev, "failed to read TSOD Device ID\n"); 383 rc = 0; 384 goto no_tsod; 385 } 386 387 tsod_match = jedec_dimm_tsod_match(vendorid, devid); 388 if (bootverbose) { 389 if (tsod_match == NULL) { 390 device_printf(dev, 391 "Unknown TSOD Manufacturer and Device IDs," 392 " 0x%x and 0x%x\n", vendorid, devid); 393 } else { 394 device_printf(dev, 395 "TSOD: %s\n", tsod_match); 396 } 397 } 398 } else { 399 no_tsod: 400 tsod_match = NULL; 401 tsod_present = false; 402 } 403 404 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type", 405 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0, 406 "DIMM type"); 407 408 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity", 409 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb, 410 "DIMM capacity (MB)"); 411 412 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part", 413 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0, 414 "DIMM Part Number"); 415 416 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial", 417 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0, 418 "DIMM Serial Number"); 419 420 SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_year", 421 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_year, 422 "DIMM manufacturing year (20xx)"); 423 424 SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_week", 425 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_week, 426 "DIMM manufacturing week"); 427 428 /* Create the temperature sysctl IFF the TSOD is present and valid */ 429 if (tsod_present && (tsod_match != NULL)) { 430 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp", 431 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, 432 jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)"); 433 } 434 435 /* If a "slotid" was hinted, add the sysctl for it. */ 436 if (resource_string_value(device_get_name(dev), device_get_unit(dev), 437 "slotid", &slotid_str) == 0) { 438 if (slotid_str != NULL) { 439 sc->slotid_str = strdup(slotid_str, M_DEVBUF); 440 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid", 441 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0, 442 "DIMM Slot Identifier"); 443 } 444 } 445 446 /* If a TSOD type string or a slotid are present, add them to the 447 * device description. 448 */ 449 if ((tsod_match != NULL) || (sc->slotid_str != NULL)) { 450 new_desc_len = strlen(device_get_desc(dev)); 451 if (tsod_match != NULL) { 452 new_desc_len += strlen(tsod_match); 453 new_desc_len += 4; /* " w/ " */ 454 } 455 if (sc->slotid_str != NULL) { 456 new_desc_len += strlen(sc->slotid_str); 457 new_desc_len += 3; /* space + parens */ 458 } 459 new_desc_len++; /* terminator */ 460 new_desc = malloc(new_desc_len, M_TEMP, (M_WAITOK | M_ZERO)); 461 (void) snprintf(new_desc, new_desc_len, "%s%s%s%s%s%s", 462 device_get_desc(dev), 463 (tsod_match ? " w/ " : ""), 464 (tsod_match ? tsod_match : ""), 465 (sc->slotid_str ? " (" : ""), 466 (sc->slotid_str ? sc->slotid_str : ""), 467 (sc->slotid_str ? ")" : "")); 468 device_set_desc_copy(dev, new_desc); 469 free(new_desc, M_TEMP); 470 } 471 472 out: 473 return (rc); 474 } 475 476 /** 477 * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry" 478 * information in various SPD bytes. The standards documents codify everything 479 * in look-up tables, but it's trivial to reverse-engineer the the formulas for 480 * most of them. Unless otherwise noted, the same formulas apply for both DDR3 481 * and DDR4. The SPD offsets of where the data comes from are different between 482 * the two types, because having them be the same would be too easy. 483 * 484 * @author rpokala 485 * 486 * @param[in] sc 487 * Instance-specific context data 488 * 489 * @param[in] dram_type 490 * The locations of the data used to calculate the capacity depends on the 491 * type of the DIMM. 492 * 493 * @param[out] capacity_mb 494 * The calculated capacity, in MB 495 */ 496 static int 497 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type, 498 uint32_t *capacity_mb) 499 { 500 uint8_t bus_width_byte; 501 uint8_t bus_width_offset; 502 uint8_t dimm_ranks_byte; 503 uint8_t dimm_ranks_offset; 504 uint8_t sdram_capacity_byte; 505 uint8_t sdram_capacity_offset; 506 uint8_t sdram_pkg_type_byte; 507 uint8_t sdram_pkg_type_offset; 508 uint8_t sdram_width_byte; 509 uint8_t sdram_width_offset; 510 uint32_t bus_width; 511 uint32_t dimm_ranks; 512 uint32_t sdram_capacity; 513 uint32_t sdram_pkg_type; 514 uint32_t sdram_width; 515 int rc; 516 517 switch (type) { 518 case DRAM_TYPE_DDR3_SDRAM: 519 bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH; 520 dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS; 521 sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY; 522 sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH; 523 break; 524 case DRAM_TYPE_DDR4_SDRAM: 525 bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH; 526 dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS; 527 sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY; 528 sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE; 529 sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH; 530 break; 531 default: 532 __assert_unreachable(); 533 } 534 535 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset, 536 &bus_width_byte); 537 if (rc != 0) { 538 device_printf(sc->dev, "failed to read bus_width: %d\n", rc); 539 goto out; 540 } 541 542 rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset, 543 &dimm_ranks_byte); 544 if (rc != 0) { 545 device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc); 546 goto out; 547 } 548 549 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset, 550 &sdram_capacity_byte); 551 if (rc != 0) { 552 device_printf(sc->dev, "failed to read sdram_capacity: %d\n", 553 rc); 554 goto out; 555 } 556 557 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset, 558 &sdram_width_byte); 559 if (rc != 0) { 560 device_printf(sc->dev, "failed to read sdram_width: %d\n", rc); 561 goto out; 562 } 563 564 /* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */ 565 if (type == DRAM_TYPE_DDR4_SDRAM) { 566 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset, 567 &sdram_pkg_type_byte); 568 if (rc != 0) { 569 device_printf(sc->dev, 570 "failed to read sdram_pkg_type: %d\n", rc); 571 goto out; 572 } 573 } 574 575 /* "Primary bus width, in bits" is in bits [2:0]. */ 576 bus_width_byte &= 0x07; 577 if (bus_width_byte <= 3) { 578 bus_width = 1 << bus_width_byte; 579 bus_width *= 8; 580 } else { 581 device_printf(sc->dev, "invalid bus width info\n"); 582 rc = EINVAL; 583 goto out; 584 } 585 586 /* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only 587 * valid for DDR4. 588 */ 589 dimm_ranks_byte >>= 3; 590 dimm_ranks_byte &= 0x07; 591 if (dimm_ranks_byte <= 7) { 592 dimm_ranks = dimm_ranks_byte + 1; 593 } else { 594 device_printf(sc->dev, "invalid DIMM Rank info\n"); 595 rc = EINVAL; 596 goto out; 597 } 598 if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) { 599 device_printf(sc->dev, "invalid DIMM Rank info\n"); 600 rc = EINVAL; 601 goto out; 602 } 603 604 /* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two 605 * different formulas, for values 0-7 and for values 8-9. Also, values 606 * 7-9 are only valid for DDR4. 607 */ 608 sdram_capacity_byte &= 0x0f; 609 if (sdram_capacity_byte <= 7) { 610 sdram_capacity = 1 << sdram_capacity_byte; 611 sdram_capacity *= 256; 612 } else if (sdram_capacity_byte <= 9) { 613 sdram_capacity = 12 << (sdram_capacity_byte - 8); 614 sdram_capacity *= 1024; 615 } else { 616 device_printf(sc->dev, "invalid SDRAM capacity info\n"); 617 rc = EINVAL; 618 goto out; 619 } 620 if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) { 621 device_printf(sc->dev, "invalid SDRAM capacity info\n"); 622 rc = EINVAL; 623 goto out; 624 } 625 626 /* "SDRAM device width" is in bits [2:0]. */ 627 sdram_width_byte &= 0x7; 628 if (sdram_width_byte <= 3) { 629 sdram_width = 1 << sdram_width_byte; 630 sdram_width *= 4; 631 } else { 632 device_printf(sc->dev, "invalid SDRAM width info\n"); 633 rc = EINVAL; 634 goto out; 635 } 636 637 /* DDR4 has something called "3DS", which is indicated by [1:0] = 2; 638 * when that is the case, the die count is encoded in [6:4], and 639 * dimm_ranks is multiplied by it. 640 */ 641 if ((type == DRAM_TYPE_DDR4_SDRAM) && 642 ((sdram_pkg_type_byte & 0x3) == 2)) { 643 sdram_pkg_type_byte >>= 4; 644 sdram_pkg_type_byte &= 0x07; 645 sdram_pkg_type = sdram_pkg_type_byte + 1; 646 dimm_ranks *= sdram_pkg_type; 647 } 648 649 /* Finally, assemble the actual capacity. The formula is the same for 650 * both DDR3 and DDR4. 651 */ 652 *capacity_mb = sdram_capacity / 8 * bus_width / sdram_width * 653 dimm_ranks; 654 655 out: 656 return (rc); 657 } 658 659 /** 660 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we 661 * didn't allocate, free it anyway; free(NULL) is safe. 662 * 663 * @author rpokala 664 * 665 * @param[in,out] dev 666 * Device being detached. 667 */ 668 static int 669 jedec_dimm_detach(device_t dev) 670 { 671 struct jedec_dimm_softc *sc; 672 673 sc = device_get_softc(dev); 674 free(sc->slotid_str, M_DEVBUF); 675 676 return (0); 677 } 678 679 /** 680 * Read and dump the entire SPD contents. 681 * 682 * @author rpokala 683 * 684 * @param[in] sc 685 * Instance-specific context data 686 * 687 * @param[in] dram_type 688 * The length of data which needs to be read and dumped differs based on 689 * the type of the DIMM. 690 */ 691 static int 692 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type) 693 { 694 int i; 695 int rc; 696 bool page_changed; 697 uint8_t bytes[512]; 698 699 page_changed = false; 700 701 for (i = 0; i < 256; i++) { 702 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]); 703 if (rc != 0) { 704 device_printf(sc->dev, 705 "unable to read page0:0x%02x: %d\n", i, rc); 706 goto out; 707 } 708 } 709 710 /* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets. 711 * JEDEC gets around this by defining the "PAGE" DTI and LSAs. 712 */ 713 if (type == DRAM_TYPE_DDR4_SDRAM) { 714 page_changed = true; 715 rc = smbus_writeb(sc->smbus, 716 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0); 717 if (rc != 0) { 718 /* Some SPD devices (or SMBus controllers?) claim the 719 * page-change command failed when it actually 720 * succeeded. Log a message but soldier on. 721 */ 722 device_printf(sc->dev, "unable to change page: %d\n", 723 rc); 724 } 725 /* Add 256 to the store location, because we're in the second 726 * page. 727 */ 728 for (i = 0; i < 256; i++) { 729 rc = smbus_readb(sc->smbus, sc->spd_addr, i, 730 &bytes[256 + i]); 731 if (rc != 0) { 732 device_printf(sc->dev, 733 "unable to read page1:0x%02x: %d\n", i, rc); 734 goto out; 735 } 736 } 737 } 738 739 /* Display the data in a nice hexdump format, with byte offsets. */ 740 hexdump(bytes, (page_changed ? 512 : 256), NULL, 0); 741 742 out: 743 if (page_changed) { 744 int rc2; 745 746 rc2 = jedec_dimm_reset_page0(sc); 747 if ((rc2 != 0) && (rc == 0)) { 748 rc = rc2; 749 } 750 } 751 752 return (rc); 753 } 754 755 /** 756 * Read a specified range of bytes from the SPD, convert them to a string, and 757 * store them in the provided buffer. Some SPD fields are space-padded ASCII, 758 * and some are just a string of bits that we want to convert to a hex string. 759 * 760 * @author rpokala 761 * 762 * @param[in] sc 763 * Instance-specific context data 764 * 765 * @param[out] dst 766 * The output buffer to populate 767 * 768 * @param[in] dstsz 769 * The size of the output buffer 770 * 771 * @param[in] offset 772 * The starting offset of the field within the SPD 773 * 774 * @param[in] len 775 * The length in bytes of the field within the SPD 776 * 777 * @param[in] ascii 778 * Is the field a sequence of ASCII characters? If not, it is binary data 779 * which should be converted to characters. 780 */ 781 static int 782 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz, 783 uint16_t offset, uint16_t len, bool ascii) 784 { 785 uint8_t byte; 786 uint16_t new_offset; 787 int i; 788 int rc; 789 bool page_changed; 790 791 rc = jedec_dimm_adjust_offset(sc, offset, &new_offset, &page_changed); 792 if (rc != 0) { 793 goto out; 794 } 795 796 /* Sanity-check (adjusted) offset and length; everything must be within 797 * the same page. 798 */ 799 if (new_offset >= JEDEC_SPD_PAGE_SIZE) { 800 rc = EINVAL; 801 device_printf(sc->dev, "invalid offset 0x%04x\n", new_offset); 802 goto out; 803 } 804 if ((new_offset + len) >= JEDEC_SPD_PAGE_SIZE) { 805 rc = EINVAL; 806 device_printf(sc->dev, 807 "(new_offset + len) would cross page (0x%04x + 0x%04x)\n", 808 new_offset, len); 809 goto out; 810 } 811 812 /* Sanity-check the destination string length. If we're dealing with 813 * ASCII chars, then the destination must be at least the same length; 814 * otherwise, it must be *twice* the length, because each byte must 815 * be converted into two nybble characters. 816 * 817 * And, of course, there needs to be an extra byte for the terminator. 818 */ 819 if (ascii) { 820 if (dstsz < (len + 1)) { 821 rc = EINVAL; 822 device_printf(sc->dev, 823 "destination too short (%u < %u)\n", 824 (uint16_t) dstsz, (len + 1)); 825 goto out; 826 } 827 } else { 828 if (dstsz < ((2 * len) + 1)) { 829 rc = EINVAL; 830 device_printf(sc->dev, 831 "destination too short (%u < %u)\n", 832 (uint16_t) dstsz, ((2 * len) + 1)); 833 goto out; 834 } 835 } 836 837 /* Read a byte at a time. */ 838 for (i = 0; i < len; i++) { 839 rc = smbus_readb(sc->smbus, sc->spd_addr, (new_offset + i), 840 &byte); 841 if (rc != 0) { 842 device_printf(sc->dev, 843 "failed to read byte at 0x%02x: %d\n", 844 (new_offset + i), rc); 845 goto out; 846 } 847 if (ascii) { 848 /* chars can be copied directly. */ 849 dst[i] = byte; 850 } else { 851 /* Raw bytes need to be converted to a two-byte hex 852 * string, plus the terminator. 853 */ 854 (void) snprintf(&dst[(2 * i)], 3, "%02x", byte); 855 } 856 } 857 858 /* If we're dealing with ASCII, convert trailing spaces to NULs. */ 859 if (ascii) { 860 for (i = dstsz - 1; i > 0; i--) { 861 if (dst[i] == ' ') { 862 dst[i] = 0; 863 } else if (dst[i] == 0) { 864 continue; 865 } else { 866 break; 867 } 868 } 869 } 870 871 out: 872 if (page_changed) { 873 int rc2; 874 875 rc2 = jedec_dimm_reset_page0(sc); 876 if ((rc2 != 0) && (rc == 0)) { 877 rc = rc2; 878 } 879 } 880 881 return (rc); 882 } 883 884 /** 885 * Both DDR3 and DDR4 encode manufacturing date as a one-byte BCD-encoded 886 * year (offset from 2000) and a one-byte BCD-encoded week within that year. 887 * The SPD offsets are different between the two types. 888 * 889 * @author rpokala 890 * 891 * @param[in] sc 892 * Instance-specific context data 893 * 894 * @param[in] dram_type 895 * The locations of the manufacturing date depends on the type of the DIMM. 896 * 897 * @param[out] year 898 * The manufacturing year, offset from 2000 899 * 900 * @param[out] week 901 * The manufacturing week within the year 902 */ 903 static int 904 jedec_dimm_mfg_date(struct jedec_dimm_softc *sc, enum dram_type type, 905 uint8_t *year, uint8_t *week) 906 { 907 uint8_t year_bcd; 908 uint8_t week_bcd; 909 uint16_t year_offset; 910 uint16_t week_offset; 911 bool page_changed; 912 int rc; 913 914 switch (type) { 915 case DRAM_TYPE_DDR3_SDRAM: 916 year_offset = SPD_OFFSET_DDR3_MOD_MFG_YEAR; 917 week_offset = SPD_OFFSET_DDR3_MOD_MFG_WEEK; 918 break; 919 case DRAM_TYPE_DDR4_SDRAM: 920 year_offset = SPD_OFFSET_DDR4_MOD_MFG_YEAR; 921 week_offset = SPD_OFFSET_DDR4_MOD_MFG_WEEK; 922 break; 923 default: 924 __assert_unreachable(); 925 } 926 927 /* Change to the proper page. Offsets [0, 255] are in page0; offsets 928 * [256, 512] are in page1. 929 * 930 * *The page must be reset to page0 before returning.* 931 * 932 * For the page-change operation, only the DTI and LSA matter; the 933 * offset and write-value are ignored, so use just 0. 934 * 935 * Mercifully, JEDEC defined the fields such that all of the 936 * manufacturing-related ones are on the same page, so we don't need to 937 * worry about that complication. 938 */ 939 if (year_offset < JEDEC_SPD_PAGE_SIZE) { 940 page_changed = false; 941 } else if (year_offset < (2 * JEDEC_SPD_PAGE_SIZE)) { 942 page_changed = true; 943 rc = smbus_writeb(sc->smbus, 944 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0); 945 if (rc != 0) { 946 device_printf(sc->dev, 947 "unable to change page for offset 0x%04x: %d\n", 948 year_offset, rc); 949 } 950 /* Adjust the offset to account for the page change. */ 951 year_offset -= JEDEC_SPD_PAGE_SIZE; 952 week_offset -= JEDEC_SPD_PAGE_SIZE; 953 } else { 954 device_printf(sc->dev, "invalid offset 0x%04x\n", year_offset); 955 rc = EINVAL; 956 page_changed = false; 957 goto out; 958 } 959 960 rc = smbus_readb(sc->smbus, sc->spd_addr, year_offset, &year_bcd); 961 if (rc != 0) { 962 device_printf(sc->dev, "failed to read mfg year: %d\n", rc); 963 goto out; 964 } 965 966 rc = smbus_readb(sc->smbus, sc->spd_addr, week_offset, &week_bcd); 967 if (rc != 0) { 968 device_printf(sc->dev, "failed to read mfg week: %d\n", rc); 969 goto out; 970 } 971 972 /* Convert from one-byte BCD to one-byte integer. */ 973 *year = (((year_bcd & 0xf0) >> 4) * 10) + (year_bcd & 0x0f); 974 *week = (((week_bcd & 0xf0) >> 4) * 10) + (week_bcd & 0x0f); 975 976 out: 977 if (page_changed) { 978 int rc2; 979 /* Switch back to page0 before returning. */ 980 rc2 = smbus_writeb(sc->smbus, 981 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0); 982 if (rc2 != 0) { 983 device_printf(sc->dev, 984 "unable to restore page for offset 0x%04x: %d\n", 985 year_offset, rc2); 986 } 987 } 988 989 return (rc); 990 } 991 992 /** 993 * device_probe() method. Validate the address that was given as a hint, and 994 * display an error if it's bogus. Make sure that we're dealing with one of the 995 * SPD versions that we can handle. 996 * 997 * @author rpokala 998 * 999 * @param[in] dev 1000 * Device being probed. 1001 */ 1002 static int 1003 jedec_dimm_probe(device_t dev) 1004 { 1005 uint8_t addr; 1006 uint8_t byte; 1007 int rc; 1008 enum dram_type type; 1009 device_t smbus; 1010 1011 smbus = device_get_parent(dev); 1012 addr = smbus_get_addr(dev); 1013 1014 /* Don't bother if this isn't an SPD address, or if the LSBit is set. */ 1015 if (((addr & 0xf0) != JEDEC_DTI_SPD) || 1016 ((addr & 0x01) != 0)) { 1017 device_printf(dev, 1018 "invalid \"addr\" hint; address must start with \"0x%x\"," 1019 " and the least-significant bit must be 0\n", 1020 JEDEC_DTI_SPD); 1021 rc = ENXIO; 1022 goto out; 1023 } 1024 1025 /* Try to read the DRAM_TYPE from the SPD. */ 1026 rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte); 1027 if (rc != 0) { 1028 device_printf(dev, "failed to read dram_type\n"); 1029 goto out; 1030 } 1031 1032 /* This driver currently only supports DDR3 and DDR4 SPDs. */ 1033 type = (enum dram_type) byte; 1034 switch (type) { 1035 case DRAM_TYPE_DDR3_SDRAM: 1036 rc = BUS_PROBE_DEFAULT; 1037 device_set_desc(dev, "DDR3 DIMM"); 1038 break; 1039 case DRAM_TYPE_DDR4_SDRAM: 1040 rc = BUS_PROBE_DEFAULT; 1041 device_set_desc(dev, "DDR4 DIMM"); 1042 break; 1043 default: 1044 rc = ENXIO; 1045 break; 1046 } 1047 1048 out: 1049 return (rc); 1050 } 1051 1052 /** 1053 * SMBus specifies little-endian byte order, but it looks like the TSODs use 1054 * big-endian. Read and convert. 1055 * 1056 * @author avg 1057 * 1058 * @param[in] sc 1059 * Instance-specific context data 1060 * 1061 * @param[in] reg 1062 * The register number to read. 1063 * 1064 * @param[out] val 1065 * Pointer to populate with the value read. 1066 */ 1067 static int 1068 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val) 1069 { 1070 int rc; 1071 1072 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val); 1073 if (rc != 0) { 1074 goto out; 1075 } 1076 *val = be16toh(*val); 1077 1078 out: 1079 return (rc); 1080 } 1081 1082 /** 1083 * Reset to the default condition of operating on page0. This must be called 1084 * after a previous operation changed to page1. 1085 * 1086 * @author rpokala 1087 * 1088 * @param[in] sc 1089 * Instance-specific context data 1090 */ 1091 static int 1092 jedec_dimm_reset_page0(struct jedec_dimm_softc *sc) 1093 { 1094 int rc; 1095 1096 /* For the page-change operation, only the DTI and LSA matter; the 1097 * offset and write-value are ignored, so just use 0. 1098 */ 1099 rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 1100 0, 0); 1101 if (rc != 0) { 1102 device_printf(sc->dev, "unable to restore page: %d\n", rc); 1103 } 1104 1105 return (rc); 1106 } 1107 1108 /** 1109 * Read the temperature data from the TSOD and convert it to the deciKelvin 1110 * value that the sysctl expects. 1111 * 1112 * @author avg 1113 */ 1114 static int 1115 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS) 1116 { 1117 uint16_t val; 1118 int rc; 1119 int temp; 1120 device_t dev = arg1; 1121 struct jedec_dimm_softc *sc; 1122 1123 sc = device_get_softc(dev); 1124 1125 rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val); 1126 if (rc != 0) { 1127 goto out; 1128 } 1129 1130 /* The three MSBits are flags, and the next bit is a sign bit. */ 1131 temp = val & 0xfff; 1132 if ((val & 0x1000) != 0) 1133 temp = -temp; 1134 /* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */ 1135 temp *= 625; 1136 /* ... and then convert to 1000ths of a Kelvin */ 1137 temp += 2731500; 1138 /* As a practical matter, few (if any) TSODs are more accurate than 1139 * about a tenth of a degree, so round accordingly. This correlates with 1140 * the "IK" formatting used for this sysctl. 1141 */ 1142 temp = (temp + 500) / 1000; 1143 1144 rc = sysctl_handle_int(oidp, &temp, 0, req); 1145 1146 out: 1147 return (rc); 1148 } 1149 1150 /** 1151 * Check the TSOD's Vendor ID and Device ID against the list of known TSOD 1152 * devices. Return the description, or NULL if this doesn't look like a valid 1153 * TSOD. 1154 * 1155 * @author avg 1156 * 1157 * @param[in] vid 1158 * The Vendor ID of the TSOD device 1159 * 1160 * @param[in] did 1161 * The Device ID of the TSOD device 1162 * 1163 * @return 1164 * The description string, or NULL for a failure to match. 1165 */ 1166 static const char * 1167 jedec_dimm_tsod_match(uint16_t vid, uint16_t did) 1168 { 1169 const struct jedec_dimm_tsod_dev *d; 1170 int i; 1171 1172 for (i = 0; i < nitems(known_tsod_devices); i++) { 1173 d = &known_tsod_devices[i]; 1174 if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) { 1175 return (d->description); 1176 } 1177 } 1178 1179 /* If no matches for a specific device, then check for a generic 1180 * TSE2004av-compliant device. 1181 */ 1182 if ((did >> 8) == 0x22) { 1183 return ("TSE2004av compliant TSOD"); 1184 } 1185 1186 return (NULL); 1187 } 1188 1189 static device_method_t jedec_dimm_methods[] = { 1190 /* Methods from the device interface */ 1191 DEVMETHOD(device_probe, jedec_dimm_probe), 1192 DEVMETHOD(device_attach, jedec_dimm_attach), 1193 DEVMETHOD(device_detach, jedec_dimm_detach), 1194 DEVMETHOD_END 1195 }; 1196 1197 static driver_t jedec_dimm_driver = { 1198 .name = "jedec_dimm", 1199 .methods = jedec_dimm_methods, 1200 .size = sizeof(struct jedec_dimm_softc), 1201 }; 1202 1203 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, 0, 0); 1204 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 1205 MODULE_VERSION(jedec_dimm, 1); 1206 1207 /* vi: set ts=8 sw=4 sts=8 noet: */ 1208