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