1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 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 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_attach(device_t dev); 146 147 static int jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type, 148 uint32_t *capacity_mb); 149 150 static int jedec_dimm_detach(device_t dev); 151 152 static int jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type); 153 154 static int jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, 155 size_t dstsz, uint16_t offset, uint16_t len, bool ascii); 156 157 static int jedec_dimm_probe(device_t dev); 158 159 static int jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, 160 uint16_t *val); 161 162 static int jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS); 163 164 static const char *jedec_dimm_tsod_match(uint16_t vid, uint16_t did); 165 166 167 /** 168 * device_attach() method. Read the DRAM type, use that to determine the offsets 169 * and lengths of the asset string fields. Calculate the capacity. If a TSOD is 170 * present, figure out exactly what it is, and update the device description. 171 * If all of that was successful, create the sysctls for the DIMM. If an 172 * optional slotid has been hinted, create a sysctl for that too. 173 * 174 * @author rpokala 175 * 176 * @param[in,out] dev 177 * Device being attached. 178 */ 179 static int 180 jedec_dimm_attach(device_t dev) 181 { 182 uint8_t byte; 183 uint16_t devid; 184 uint16_t partnum_len; 185 uint16_t partnum_offset; 186 uint16_t serial_len; 187 uint16_t serial_offset; 188 uint16_t tsod_present_offset; 189 uint16_t vendorid; 190 bool tsod_present; 191 int rc; 192 int new_desc_len; 193 enum dram_type type; 194 struct jedec_dimm_softc *sc; 195 struct sysctl_ctx_list *ctx; 196 struct sysctl_oid *oid; 197 struct sysctl_oid_list *children; 198 const char *tsod_match; 199 const char *slotid_str; 200 char *new_desc; 201 202 sc = device_get_softc(dev); 203 ctx = device_get_sysctl_ctx(dev); 204 oid = device_get_sysctl_tree(dev); 205 children = SYSCTL_CHILDREN(oid); 206 207 bzero(sc, sizeof(*sc)); 208 sc->dev = dev; 209 sc->smbus = device_get_parent(dev); 210 sc->spd_addr = smbus_get_addr(dev); 211 212 /* The TSOD address has a different DTI from the SPD address, but shares 213 * the LSA bits. 214 */ 215 sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f); 216 217 /* Read the DRAM type, and set the various offsets and lengths. */ 218 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte); 219 if (rc != 0) { 220 device_printf(dev, "failed to read dram_type: %d\n", rc); 221 goto out; 222 } 223 type = (enum dram_type) byte; 224 switch (type) { 225 case DRAM_TYPE_DDR3_SDRAM: 226 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3"); 227 partnum_len = SPD_LEN_DDR3_PARTNUM; 228 partnum_offset = SPD_OFFSET_DDR3_PARTNUM; 229 serial_len = SPD_LEN_DDR3_SERIAL; 230 serial_offset = SPD_OFFSET_DDR3_SERIAL; 231 tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT; 232 break; 233 case DRAM_TYPE_DDR4_SDRAM: 234 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4"); 235 partnum_len = SPD_LEN_DDR4_PARTNUM; 236 partnum_offset = SPD_OFFSET_DDR4_PARTNUM; 237 serial_len = SPD_LEN_DDR4_SERIAL; 238 serial_offset = SPD_OFFSET_DDR4_SERIAL; 239 tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT; 240 break; 241 default: 242 device_printf(dev, "unsupported dram_type 0x%02x\n", type); 243 rc = EINVAL; 244 goto out; 245 } 246 247 if (bootverbose) { 248 /* bootverbose debuggery is best-effort, so ignore the rc. */ 249 (void) jedec_dimm_dump(sc, type); 250 } 251 252 /* Read all the required info from the SPD. If any of it fails, error 253 * out without creating the sysctls. 254 */ 255 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb); 256 if (rc != 0) { 257 goto out; 258 } 259 260 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str), 261 partnum_offset, partnum_len, true); 262 if (rc != 0) { 263 goto out; 264 } 265 266 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str), 267 serial_offset, serial_len, false); 268 if (rc != 0) { 269 goto out; 270 } 271 272 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD 273 * is in fact present. (While DDR3 and DDR4 don't explicitly require a 274 * TSOD, essentially all DDR3 and DDR4 DIMMs include one.) But, as 275 * discussed in [PR 235944], it turns out that some DIMMs claim to have 276 * a TSOD when they actually don't. (Or maybe the firmware blocks it?) 277 * <sigh> 278 * If the SPD data says the TSOD is present, try to read manufacturer 279 * and device info from it to confirm that it's a valid TSOD device. 280 * If the data is unreadable, just continue as if the TSOD isn't there. 281 * If the data was read successfully, see if it is a known TSOD device; 282 * it's okay if it isn't (tsod_match == NULL). 283 */ 284 rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte); 285 if (rc != 0) { 286 device_printf(dev, "failed to read TSOD-present byte: %d\n", 287 rc); 288 goto out; 289 } 290 if (byte & 0x80) { 291 tsod_present = true; 292 rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid); 293 if (rc != 0) { 294 device_printf(dev, 295 "failed to read TSOD Manufacturer ID\n"); 296 rc = 0; 297 goto no_tsod; 298 } 299 rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid); 300 if (rc != 0) { 301 device_printf(dev, "failed to read TSOD Device ID\n"); 302 rc = 0; 303 goto no_tsod; 304 } 305 306 tsod_match = jedec_dimm_tsod_match(vendorid, devid); 307 if (bootverbose) { 308 if (tsod_match == NULL) { 309 device_printf(dev, 310 "Unknown TSOD Manufacturer and Device IDs," 311 " 0x%x and 0x%x\n", vendorid, devid); 312 } else { 313 device_printf(dev, 314 "TSOD: %s\n", tsod_match); 315 } 316 } 317 } else { 318 no_tsod: 319 tsod_match = NULL; 320 tsod_present = false; 321 } 322 323 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type", 324 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0, 325 "DIMM type"); 326 327 SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity", 328 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb, 329 "DIMM capacity (MB)"); 330 331 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part", 332 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0, 333 "DIMM Part Number"); 334 335 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial", 336 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0, 337 "DIMM Serial Number"); 338 339 /* Create the temperature sysctl IFF the TSOD is present and valid */ 340 if (tsod_present && (tsod_match != NULL)) { 341 SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp", 342 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, 343 jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)"); 344 } 345 346 /* If a "slotid" was hinted, add the sysctl for it. */ 347 if (resource_string_value(device_get_name(dev), device_get_unit(dev), 348 "slotid", &slotid_str) == 0) { 349 if (slotid_str != NULL) { 350 sc->slotid_str = strdup(slotid_str, M_DEVBUF); 351 SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid", 352 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0, 353 "DIMM Slot Identifier"); 354 } 355 } 356 357 /* If a TSOD type string or a slotid are present, add them to the 358 * device description. 359 */ 360 if ((tsod_match != NULL) || (sc->slotid_str != NULL)) { 361 new_desc_len = strlen(device_get_desc(dev)); 362 if (tsod_match != NULL) { 363 new_desc_len += strlen(tsod_match); 364 new_desc_len += 4; /* " w/ " */ 365 } 366 if (sc->slotid_str != NULL) { 367 new_desc_len += strlen(sc->slotid_str); 368 new_desc_len += 3; /* space + parens */ 369 } 370 new_desc_len++; /* terminator */ 371 new_desc = malloc(new_desc_len, M_TEMP, (M_WAITOK | M_ZERO)); 372 (void) snprintf(new_desc, new_desc_len, "%s%s%s%s%s%s", 373 device_get_desc(dev), 374 (tsod_match ? " w/ " : ""), 375 (tsod_match ? tsod_match : ""), 376 (sc->slotid_str ? " (" : ""), 377 (sc->slotid_str ? sc->slotid_str : ""), 378 (sc->slotid_str ? ")" : "")); 379 device_set_desc_copy(dev, new_desc); 380 free(new_desc, M_TEMP); 381 } 382 383 out: 384 return (rc); 385 } 386 387 /** 388 * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry" 389 * information in various SPD bytes. The standards documents codify everything 390 * in look-up tables, but it's trivial to reverse-engineer the the formulas for 391 * most of them. Unless otherwise noted, the same formulas apply for both DDR3 392 * and DDR4. The SPD offsets of where the data comes from are different between 393 * the two types, because having them be the same would be too easy. 394 * 395 * @author rpokala 396 * 397 * @param[in] sc 398 * Instance-specific context data 399 * 400 * @param[in] dram_type 401 * The locations of the data used to calculate the capacity depends on the 402 * type of the DIMM. 403 * 404 * @param[out] capacity_mb 405 * The calculated capacity, in MB 406 */ 407 static int 408 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type, 409 uint32_t *capacity_mb) 410 { 411 uint8_t bus_width_byte; 412 uint8_t bus_width_offset; 413 uint8_t dimm_ranks_byte; 414 uint8_t dimm_ranks_offset; 415 uint8_t sdram_capacity_byte; 416 uint8_t sdram_capacity_offset; 417 uint8_t sdram_pkg_type_byte; 418 uint8_t sdram_pkg_type_offset; 419 uint8_t sdram_width_byte; 420 uint8_t sdram_width_offset; 421 uint32_t bus_width; 422 uint32_t dimm_ranks; 423 uint32_t sdram_capacity; 424 uint32_t sdram_pkg_type; 425 uint32_t sdram_width; 426 int rc; 427 428 switch (type) { 429 case DRAM_TYPE_DDR3_SDRAM: 430 bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH; 431 dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS; 432 sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY; 433 sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH; 434 break; 435 case DRAM_TYPE_DDR4_SDRAM: 436 bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH; 437 dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS; 438 sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY; 439 sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE; 440 sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH; 441 break; 442 default: 443 device_printf(sc->dev, "unsupported dram_type 0x%02x\n", type); 444 rc = EINVAL; 445 goto out; 446 } 447 448 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset, 449 &bus_width_byte); 450 if (rc != 0) { 451 device_printf(sc->dev, "failed to read bus_width: %d\n", rc); 452 goto out; 453 } 454 455 rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset, 456 &dimm_ranks_byte); 457 if (rc != 0) { 458 device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc); 459 goto out; 460 } 461 462 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset, 463 &sdram_capacity_byte); 464 if (rc != 0) { 465 device_printf(sc->dev, "failed to read sdram_capacity: %d\n", 466 rc); 467 goto out; 468 } 469 470 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset, 471 &sdram_width_byte); 472 if (rc != 0) { 473 device_printf(sc->dev, "failed to read sdram_width: %d\n", rc); 474 goto out; 475 } 476 477 /* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */ 478 if (type == DRAM_TYPE_DDR4_SDRAM) { 479 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset, 480 &sdram_pkg_type_byte); 481 if (rc != 0) { 482 device_printf(sc->dev, 483 "failed to read sdram_pkg_type: %d\n", rc); 484 goto out; 485 } 486 } 487 488 /* "Primary bus width, in bits" is in bits [2:0]. */ 489 bus_width_byte &= 0x07; 490 if (bus_width_byte <= 3) { 491 bus_width = 1 << bus_width_byte; 492 bus_width *= 8; 493 } else { 494 device_printf(sc->dev, "invalid bus width info\n"); 495 rc = EINVAL; 496 goto out; 497 } 498 499 /* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only 500 * valid for DDR4. 501 */ 502 dimm_ranks_byte >>= 3; 503 dimm_ranks_byte &= 0x07; 504 if (dimm_ranks_byte <= 7) { 505 dimm_ranks = dimm_ranks_byte + 1; 506 } else { 507 device_printf(sc->dev, "invalid DIMM Rank info\n"); 508 rc = EINVAL; 509 goto out; 510 } 511 if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) { 512 device_printf(sc->dev, "invalid DIMM Rank info\n"); 513 rc = EINVAL; 514 goto out; 515 } 516 517 /* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two 518 * different formulas, for values 0-7 and for values 8-9. Also, values 519 * 7-9 are only valid for DDR4. 520 */ 521 sdram_capacity_byte &= 0x0f; 522 if (sdram_capacity_byte <= 7) { 523 sdram_capacity = 1 << sdram_capacity_byte; 524 sdram_capacity *= 256; 525 } else if (sdram_capacity_byte <= 9) { 526 sdram_capacity = 12 << (sdram_capacity_byte - 8); 527 sdram_capacity *= 1024; 528 } else { 529 device_printf(sc->dev, "invalid SDRAM capacity info\n"); 530 rc = EINVAL; 531 goto out; 532 } 533 if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) { 534 device_printf(sc->dev, "invalid SDRAM capacity info\n"); 535 rc = EINVAL; 536 goto out; 537 } 538 539 /* "SDRAM device width" is in bits [2:0]. */ 540 sdram_width_byte &= 0x7; 541 if (sdram_width_byte <= 3) { 542 sdram_width = 1 << sdram_width_byte; 543 sdram_width *= 4; 544 } else { 545 device_printf(sc->dev, "invalid SDRAM width info\n"); 546 rc = EINVAL; 547 goto out; 548 } 549 550 /* DDR4 has something called "3DS", which is indicated by [1:0] = 2; 551 * when that is the case, the die count is encoded in [6:4], and 552 * dimm_ranks is multiplied by it. 553 */ 554 if ((type == DRAM_TYPE_DDR4_SDRAM) && 555 ((sdram_pkg_type_byte & 0x3) == 2)) { 556 sdram_pkg_type_byte >>= 4; 557 sdram_pkg_type_byte &= 0x07; 558 sdram_pkg_type = sdram_pkg_type_byte + 1; 559 dimm_ranks *= sdram_pkg_type; 560 } 561 562 /* Finally, assemble the actual capacity. The formula is the same for 563 * both DDR3 and DDR4. 564 */ 565 *capacity_mb = sdram_capacity / 8 * bus_width / sdram_width * 566 dimm_ranks; 567 568 out: 569 return (rc); 570 } 571 572 /** 573 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we 574 * didn't allocate, free it anyway; free(NULL) is safe. 575 * 576 * @author rpokala 577 * 578 * @param[in,out] dev 579 * Device being detached. 580 */ 581 static int 582 jedec_dimm_detach(device_t dev) 583 { 584 struct jedec_dimm_softc *sc; 585 586 sc = device_get_softc(dev); 587 free(sc->slotid_str, M_DEVBUF); 588 589 return (0); 590 } 591 592 /** 593 * Read and dump the entire SPD contents. 594 * 595 * @author rpokala 596 * 597 * @param[in] sc 598 * Instance-specific context data 599 * 600 * @param[in] dram_type 601 * The length of data which needs to be read and dumped differs based on 602 * the type of the DIMM. 603 */ 604 static int 605 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type) 606 { 607 int i; 608 int rc; 609 bool page_changed; 610 uint8_t bytes[512]; 611 612 page_changed = false; 613 614 for (i = 0; i < 256; i++) { 615 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]); 616 if (rc != 0) { 617 device_printf(sc->dev, 618 "unable to read page0:0x%02x: %d\n", i, rc); 619 goto out; 620 } 621 } 622 623 /* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets. 624 * JEDEC gets around this by defining the "PAGE" DTI and LSAs. 625 */ 626 if (type == DRAM_TYPE_DDR4_SDRAM) { 627 page_changed = true; 628 rc = smbus_writeb(sc->smbus, 629 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0); 630 if (rc != 0) { 631 /* Some SPD devices (or SMBus controllers?) claim the 632 * page-change command failed when it actually 633 * succeeded. Log a message but soldier on. 634 */ 635 device_printf(sc->dev, "unable to change page: %d\n", 636 rc); 637 } 638 /* Add 256 to the store location, because we're in the second 639 * page. 640 */ 641 for (i = 0; i < 256; i++) { 642 rc = smbus_readb(sc->smbus, sc->spd_addr, i, 643 &bytes[256 + i]); 644 if (rc != 0) { 645 device_printf(sc->dev, 646 "unable to read page1:0x%02x: %d\n", i, rc); 647 goto out; 648 } 649 } 650 } 651 652 /* Display the data in a nice hexdump format, with byte offsets. */ 653 hexdump(bytes, (page_changed ? 512 : 256), NULL, 0); 654 655 out: 656 if (page_changed) { 657 int rc2; 658 /* Switch back to page0 before returning. */ 659 rc2 = smbus_writeb(sc->smbus, 660 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0); 661 if (rc2 != 0) { 662 device_printf(sc->dev, "unable to restore page: %d\n", 663 rc2); 664 } 665 } 666 return (rc); 667 } 668 669 /** 670 * Read a specified range of bytes from the SPD, convert them to a string, and 671 * store them in the provided buffer. Some SPD fields are space-padded ASCII, 672 * and some are just a string of bits that we want to convert to a hex string. 673 * 674 * @author rpokala 675 * 676 * @param[in] sc 677 * Instance-specific context data 678 * 679 * @param[out] dst 680 * The output buffer to populate 681 * 682 * @param[in] dstsz 683 * The size of the output buffer 684 * 685 * @param[in] offset 686 * The starting offset of the field within the SPD 687 * 688 * @param[in] len 689 * The length in bytes of the field within the SPD 690 * 691 * @param[in] ascii 692 * Is the field a sequence of ASCII characters? If not, it is binary data 693 * which should be converted to characters. 694 */ 695 static int 696 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz, 697 uint16_t offset, uint16_t len, bool ascii) 698 { 699 uint8_t byte; 700 int i; 701 int rc; 702 bool page_changed; 703 704 /* Change to the proper page. Offsets [0, 255] are in page0; offsets 705 * [256, 512] are in page1. 706 * 707 * *The page must be reset to page0 before returning.* 708 * 709 * For the page-change operation, only the DTI and LSA matter; the 710 * offset and write-value are ignored, so use just 0. 711 * 712 * Mercifully, JEDEC defined the fields such that none of them cross 713 * pages, so we don't need to worry about that complication. 714 */ 715 if (offset < JEDEC_SPD_PAGE_SIZE) { 716 page_changed = false; 717 } else if (offset < (2 * JEDEC_SPD_PAGE_SIZE)) { 718 page_changed = true; 719 rc = smbus_writeb(sc->smbus, 720 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0); 721 if (rc != 0) { 722 device_printf(sc->dev, 723 "unable to change page for offset 0x%04x: %d\n", 724 offset, rc); 725 } 726 /* Adjust the offset to account for the page change. */ 727 offset -= JEDEC_SPD_PAGE_SIZE; 728 } else { 729 page_changed = false; 730 rc = EINVAL; 731 device_printf(sc->dev, "invalid offset 0x%04x\n", offset); 732 goto out; 733 } 734 735 /* Sanity-check (adjusted) offset and length; everything must be within 736 * the same page. 737 */ 738 if (offset >= JEDEC_SPD_PAGE_SIZE) { 739 rc = EINVAL; 740 device_printf(sc->dev, "invalid offset 0x%04x\n", offset); 741 goto out; 742 } 743 if ((offset + len) >= JEDEC_SPD_PAGE_SIZE) { 744 rc = EINVAL; 745 device_printf(sc->dev, 746 "(offset + len) would cross page (0x%04x + 0x%04x)\n", 747 offset, len); 748 goto out; 749 } 750 751 /* Sanity-check the destination string length. If we're dealing with 752 * ASCII chars, then the destination must be at least the same length; 753 * otherwise, it must be *twice* the length, because each byte must 754 * be converted into two nybble characters. 755 * 756 * And, of course, there needs to be an extra byte for the terminator. 757 */ 758 if (ascii) { 759 if (dstsz < (len + 1)) { 760 rc = EINVAL; 761 device_printf(sc->dev, 762 "destination too short (%u < %u)\n", 763 (uint16_t) dstsz, (len + 1)); 764 goto out; 765 } 766 } else { 767 if (dstsz < ((2 * len) + 1)) { 768 rc = EINVAL; 769 device_printf(sc->dev, 770 "destination too short (%u < %u)\n", 771 (uint16_t) dstsz, ((2 * len) + 1)); 772 goto out; 773 } 774 } 775 776 /* Read a byte at a time. */ 777 for (i = 0; i < len; i++) { 778 rc = smbus_readb(sc->smbus, sc->spd_addr, (offset + i), &byte); 779 if (rc != 0) { 780 device_printf(sc->dev, 781 "failed to read byte at 0x%02x: %d\n", 782 (offset + i), rc); 783 goto out; 784 } 785 if (ascii) { 786 /* chars can be copied directly. */ 787 dst[i] = byte; 788 } else { 789 /* Raw bytes need to be converted to a two-byte hex 790 * string, plus the terminator. 791 */ 792 (void) snprintf(&dst[(2 * i)], 3, "%02x", byte); 793 } 794 } 795 796 /* If we're dealing with ASCII, convert trailing spaces to NULs. */ 797 if (ascii) { 798 for (i = dstsz; i > 0; i--) { 799 if (dst[i] == ' ') { 800 dst[i] = 0; 801 } else if (dst[i] == 0) { 802 continue; 803 } else { 804 break; 805 } 806 } 807 } 808 809 out: 810 if (page_changed) { 811 int rc2; 812 /* Switch back to page0 before returning. */ 813 rc2 = smbus_writeb(sc->smbus, 814 (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0); 815 if (rc2 != 0) { 816 device_printf(sc->dev, 817 "unable to restore page for offset 0x%04x: %d\n", 818 offset, rc2); 819 } 820 } 821 822 return (rc); 823 } 824 825 /** 826 * device_probe() method. Validate the address that was given as a hint, and 827 * display an error if it's bogus. Make sure that we're dealing with one of the 828 * SPD versions that we can handle. 829 * 830 * @author rpokala 831 * 832 * @param[in] dev 833 * Device being probed. 834 */ 835 static int 836 jedec_dimm_probe(device_t dev) 837 { 838 uint8_t addr; 839 uint8_t byte; 840 int rc; 841 enum dram_type type; 842 device_t smbus; 843 844 smbus = device_get_parent(dev); 845 addr = smbus_get_addr(dev); 846 847 /* Don't bother if this isn't an SPD address, or if the LSBit is set. */ 848 if (((addr & 0xf0) != JEDEC_DTI_SPD) || 849 ((addr & 0x01) != 0)) { 850 device_printf(dev, 851 "invalid \"addr\" hint; address must start with \"0x%x\"," 852 " and the least-significant bit must be 0\n", 853 JEDEC_DTI_SPD); 854 rc = ENXIO; 855 goto out; 856 } 857 858 /* Try to read the DRAM_TYPE from the SPD. */ 859 rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte); 860 if (rc != 0) { 861 device_printf(dev, "failed to read dram_type\n"); 862 goto out; 863 } 864 865 /* This driver currently only supports DDR3 and DDR4 SPDs. */ 866 type = (enum dram_type) byte; 867 switch (type) { 868 case DRAM_TYPE_DDR3_SDRAM: 869 rc = BUS_PROBE_DEFAULT; 870 device_set_desc(dev, "DDR3 DIMM"); 871 break; 872 case DRAM_TYPE_DDR4_SDRAM: 873 rc = BUS_PROBE_DEFAULT; 874 device_set_desc(dev, "DDR4 DIMM"); 875 break; 876 default: 877 rc = ENXIO; 878 break; 879 } 880 881 out: 882 return (rc); 883 } 884 885 /** 886 * SMBus specifies little-endian byte order, but it looks like the TSODs use 887 * big-endian. Read and convert. 888 * 889 * @author avg 890 * 891 * @param[in] sc 892 * Instance-specific context data 893 * 894 * @param[in] reg 895 * The register number to read. 896 * 897 * @param[out] val 898 * Pointer to populate with the value read. 899 */ 900 static int 901 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val) 902 { 903 int rc; 904 905 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val); 906 if (rc != 0) { 907 goto out; 908 } 909 *val = be16toh(*val); 910 911 out: 912 return (rc); 913 } 914 915 /** 916 * Read the temperature data from the TSOD and convert it to the deciKelvin 917 * value that the sysctl expects. 918 * 919 * @author avg 920 */ 921 static int 922 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS) 923 { 924 uint16_t val; 925 int rc; 926 int temp; 927 device_t dev = arg1; 928 struct jedec_dimm_softc *sc; 929 930 sc = device_get_softc(dev); 931 932 rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val); 933 if (rc != 0) { 934 goto out; 935 } 936 937 /* The three MSBits are flags, and the next bit is a sign bit. */ 938 temp = val & 0xfff; 939 if ((val & 0x1000) != 0) 940 temp = -temp; 941 /* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */ 942 temp *= 625; 943 /* ... and then convert to 1000ths of a Kelvin */ 944 temp += 2731500; 945 /* As a practical matter, few (if any) TSODs are more accurate than 946 * about a tenth of a degree, so round accordingly. This correlates with 947 * the "IK" formatting used for this sysctl. 948 */ 949 temp = (temp + 500) / 1000; 950 951 rc = sysctl_handle_int(oidp, &temp, 0, req); 952 953 out: 954 return (rc); 955 } 956 957 /** 958 * Check the TSOD's Vendor ID and Device ID against the list of known TSOD 959 * devices. Return the description, or NULL if this doesn't look like a valid 960 * TSOD. 961 * 962 * @author avg 963 * 964 * @param[in] vid 965 * The Vendor ID of the TSOD device 966 * 967 * @param[in] did 968 * The Device ID of the TSOD device 969 * 970 * @return 971 * The description string, or NULL for a failure to match. 972 */ 973 static const char * 974 jedec_dimm_tsod_match(uint16_t vid, uint16_t did) 975 { 976 const struct jedec_dimm_tsod_dev *d; 977 int i; 978 979 for (i = 0; i < nitems(known_tsod_devices); i++) { 980 d = &known_tsod_devices[i]; 981 if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) { 982 return (d->description); 983 } 984 } 985 986 /* If no matches for a specific device, then check for a generic 987 * TSE2004av-compliant device. 988 */ 989 if ((did >> 8) == 0x22) { 990 return ("TSE2004av compliant TSOD"); 991 } 992 993 return (NULL); 994 } 995 996 static device_method_t jedec_dimm_methods[] = { 997 /* Methods from the device interface */ 998 DEVMETHOD(device_probe, jedec_dimm_probe), 999 DEVMETHOD(device_attach, jedec_dimm_attach), 1000 DEVMETHOD(device_detach, jedec_dimm_detach), 1001 DEVMETHOD_END 1002 }; 1003 1004 static driver_t jedec_dimm_driver = { 1005 .name = "jedec_dimm", 1006 .methods = jedec_dimm_methods, 1007 .size = sizeof(struct jedec_dimm_softc), 1008 }; 1009 1010 static devclass_t jedec_dimm_devclass; 1011 1012 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, jedec_dimm_devclass, 0, 0); 1013 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); 1014 MODULE_VERSION(jedec_dimm, 1); 1015 1016 /* vi: set ts=8 sw=4 sts=8 noet: */ 1017