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