Lines Matching +full:x +full:- +full:rc
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
7 * Copyright (c) 2018-2023 Panasas
32 * This driver is a super-set of the now-deleted jedec_ts(4), and most of the
82 * http://www.analog.com/media/en/technical-documentation/data-sheets/ADT7408.pdf
88 * http://www.atmel.com/images/atmel-8868-dts-at30tse004a-datasheet.pdf
99 * https://www.idt.com/document/dst/tse2004gb2b0-datasheet
106 * Document 19-3837; Rev 0; 10/05 has 0x3e00 while
107 * 19-3837; Rev 3; 10/11 has 0x5400.
125 * http://www.nxp.com/docs/en/data-sheet/SE97B.pdf
131 * https://www.onsemi.com/pub/Collateral/CAT34TS02-D.PDF
132 * http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
176 * The DDR4 SPD information is spread across two 256-byte pages, but the
177 * offsets in the spec are absolute, not per-page. If a given offset is on the
184 * Instance-specific context data
200 int rc; in jedec_dimm_adjust_offset() local
212 /* Within page0; no adjustment or page-change required. */ in jedec_dimm_adjust_offset()
213 rc = 0; in jedec_dimm_adjust_offset()
217 rc = EINVAL; in jedec_dimm_adjust_offset()
218 device_printf(sc->dev, "invalid offset 0x%04x\n", orig_offset); in jedec_dimm_adjust_offset()
225 * For the page-change operation, only the DTI and LSA matter; the in jedec_dimm_adjust_offset()
226 * offset and write-value are ignored, so just use 0. in jedec_dimm_adjust_offset()
228 rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), in jedec_dimm_adjust_offset()
230 if (rc != 0) { in jedec_dimm_adjust_offset()
231 device_printf(sc->dev, in jedec_dimm_adjust_offset()
232 "unable to change page for offset 0x%04x: %d\n", in jedec_dimm_adjust_offset()
233 orig_offset, rc); in jedec_dimm_adjust_offset()
237 *new_offset = orig_offset - JEDEC_SPD_PAGE_SIZE; in jedec_dimm_adjust_offset()
240 return (rc); in jedec_dimm_adjust_offset()
267 int rc; in jedec_dimm_attach() local
282 sc->dev = dev; in jedec_dimm_attach()
283 sc->smbus = device_get_parent(dev); in jedec_dimm_attach()
284 sc->spd_addr = smbus_get_addr(dev); in jedec_dimm_attach()
289 sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f); in jedec_dimm_attach()
292 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte); in jedec_dimm_attach()
293 if (rc != 0) { in jedec_dimm_attach()
294 device_printf(dev, "failed to read dram_type: %d\n", rc); in jedec_dimm_attach()
300 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3"); in jedec_dimm_attach()
308 (void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4"); in jedec_dimm_attach()
316 device_printf(dev, "unsupported dram_type 0x%02x\n", type); in jedec_dimm_attach()
317 rc = EINVAL; in jedec_dimm_attach()
322 /* bootverbose debuggery is best-effort, so ignore the rc. */ in jedec_dimm_attach()
329 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb); in jedec_dimm_attach()
330 if (rc != 0) { in jedec_dimm_attach()
334 rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week); in jedec_dimm_attach()
335 if (rc != 0) { in jedec_dimm_attach()
339 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str), in jedec_dimm_attach()
341 if (rc != 0) { in jedec_dimm_attach()
345 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str), in jedec_dimm_attach()
347 if (rc != 0) { in jedec_dimm_attach()
351 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD in jedec_dimm_attach()
363 rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte); in jedec_dimm_attach()
364 if (rc != 0) { in jedec_dimm_attach()
365 device_printf(dev, "failed to read TSOD-present byte: %d\n", in jedec_dimm_attach()
366 rc); in jedec_dimm_attach()
371 rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid); in jedec_dimm_attach()
372 if (rc != 0) { in jedec_dimm_attach()
375 rc = 0; in jedec_dimm_attach()
378 rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid); in jedec_dimm_attach()
379 if (rc != 0) { in jedec_dimm_attach()
381 rc = 0; in jedec_dimm_attach()
390 " 0x%x and 0x%x\n", vendorid, devid); in jedec_dimm_attach()
403 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0, in jedec_dimm_attach()
407 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb, in jedec_dimm_attach()
411 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0, in jedec_dimm_attach()
415 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0, in jedec_dimm_attach()
419 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_year, in jedec_dimm_attach()
423 CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_week, in jedec_dimm_attach()
437 sc->slotid_str = strdup(slotid_str, M_DEVBUF); in jedec_dimm_attach()
439 CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0, in jedec_dimm_attach()
447 if ((tsod_match != NULL) || (sc->slotid_str != NULL)) { in jedec_dimm_attach()
452 (sc->slotid_str ? " (" : ""), in jedec_dimm_attach()
453 (sc->slotid_str ? sc->slotid_str : ""), in jedec_dimm_attach()
454 (sc->slotid_str ? ")" : "")); in jedec_dimm_attach()
458 return (rc); in jedec_dimm_attach()
464 * in look-up tables, but it's trivial to reverse-engineer the the formulas for
472 * Instance-specific context data
500 int rc; in jedec_dimm_capacity() local
520 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset, in jedec_dimm_capacity()
522 if (rc != 0) { in jedec_dimm_capacity()
523 device_printf(sc->dev, "failed to read bus_width: %d\n", rc); in jedec_dimm_capacity()
527 rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset, in jedec_dimm_capacity()
529 if (rc != 0) { in jedec_dimm_capacity()
530 device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc); in jedec_dimm_capacity()
534 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset, in jedec_dimm_capacity()
536 if (rc != 0) { in jedec_dimm_capacity()
537 device_printf(sc->dev, "failed to read sdram_capacity: %d\n", in jedec_dimm_capacity()
538 rc); in jedec_dimm_capacity()
542 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset, in jedec_dimm_capacity()
544 if (rc != 0) { in jedec_dimm_capacity()
545 device_printf(sc->dev, "failed to read sdram_width: %d\n", rc); in jedec_dimm_capacity()
551 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset, in jedec_dimm_capacity()
553 if (rc != 0) { in jedec_dimm_capacity()
554 device_printf(sc->dev, in jedec_dimm_capacity()
555 "failed to read sdram_pkg_type: %d\n", rc); in jedec_dimm_capacity()
566 device_printf(sc->dev, "invalid bus width info\n"); in jedec_dimm_capacity()
567 rc = EINVAL; in jedec_dimm_capacity()
571 /* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only in jedec_dimm_capacity()
579 device_printf(sc->dev, "invalid DIMM Rank info\n"); in jedec_dimm_capacity()
580 rc = EINVAL; in jedec_dimm_capacity()
584 device_printf(sc->dev, "invalid DIMM Rank info\n"); in jedec_dimm_capacity()
585 rc = EINVAL; in jedec_dimm_capacity()
590 * different formulas, for values 0-7 and for values 8-9. Also, values in jedec_dimm_capacity()
591 * 7-9 are only valid for DDR4. in jedec_dimm_capacity()
598 sdram_capacity = 12 << (sdram_capacity_byte - 8); in jedec_dimm_capacity()
601 device_printf(sc->dev, "invalid SDRAM capacity info\n"); in jedec_dimm_capacity()
602 rc = EINVAL; in jedec_dimm_capacity()
606 device_printf(sc->dev, "invalid SDRAM capacity info\n"); in jedec_dimm_capacity()
607 rc = EINVAL; in jedec_dimm_capacity()
617 device_printf(sc->dev, "invalid SDRAM width info\n"); in jedec_dimm_capacity()
618 rc = EINVAL; in jedec_dimm_capacity()
641 return (rc); in jedec_dimm_capacity()
645 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
659 free(sc->slotid_str, M_DEVBUF); in jedec_dimm_detach()
670 * Instance-specific context data
680 int rc; in jedec_dimm_dump() local
687 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]); in jedec_dimm_dump()
688 if (rc != 0) { in jedec_dimm_dump()
689 device_printf(sc->dev, in jedec_dimm_dump()
690 "unable to read page0:0x%02x: %d\n", i, rc); in jedec_dimm_dump()
695 /* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets. in jedec_dimm_dump()
700 rc = smbus_writeb(sc->smbus, in jedec_dimm_dump()
702 if (rc != 0) { in jedec_dimm_dump()
704 * page-change command failed when it actually in jedec_dimm_dump()
707 device_printf(sc->dev, "unable to change page: %d\n", in jedec_dimm_dump()
708 rc); in jedec_dimm_dump()
714 rc = smbus_readb(sc->smbus, sc->spd_addr, i, in jedec_dimm_dump()
716 if (rc != 0) { in jedec_dimm_dump()
717 device_printf(sc->dev, in jedec_dimm_dump()
718 "unable to read page1:0x%02x: %d\n", i, rc); in jedec_dimm_dump()
732 if ((rc2 != 0) && (rc == 0)) { in jedec_dimm_dump()
733 rc = rc2; in jedec_dimm_dump()
737 return (rc); in jedec_dimm_dump()
742 * store them in the provided buffer. Some SPD fields are space-padded ASCII,
748 * Instance-specific context data
773 int rc; in jedec_dimm_field_to_str() local
776 rc = jedec_dimm_adjust_offset(sc, offset, &new_offset, &page_changed); in jedec_dimm_field_to_str()
777 if (rc != 0) { in jedec_dimm_field_to_str()
781 /* Sanity-check (adjusted) offset and length; everything must be within in jedec_dimm_field_to_str()
785 rc = EINVAL; in jedec_dimm_field_to_str()
786 device_printf(sc->dev, "invalid offset 0x%04x\n", new_offset); in jedec_dimm_field_to_str()
790 rc = EINVAL; in jedec_dimm_field_to_str()
791 device_printf(sc->dev, in jedec_dimm_field_to_str()
792 "(new_offset + len) would cross page (0x%04x + 0x%04x)\n", in jedec_dimm_field_to_str()
797 /* Sanity-check the destination string length. If we're dealing with in jedec_dimm_field_to_str()
806 rc = EINVAL; in jedec_dimm_field_to_str()
807 device_printf(sc->dev, in jedec_dimm_field_to_str()
814 rc = EINVAL; in jedec_dimm_field_to_str()
815 device_printf(sc->dev, in jedec_dimm_field_to_str()
824 rc = smbus_readb(sc->smbus, sc->spd_addr, (new_offset + i), in jedec_dimm_field_to_str()
826 if (rc != 0) { in jedec_dimm_field_to_str()
827 device_printf(sc->dev, in jedec_dimm_field_to_str()
828 "failed to read byte at 0x%02x: %d\n", in jedec_dimm_field_to_str()
829 (new_offset + i), rc); in jedec_dimm_field_to_str()
836 /* Raw bytes need to be converted to a two-byte hex in jedec_dimm_field_to_str()
839 (void) snprintf(&dst[(2 * i)], 3, "%02x", byte); in jedec_dimm_field_to_str()
845 for (i = dstsz - 1; i > 0; i--) { in jedec_dimm_field_to_str()
861 if ((rc2 != 0) && (rc == 0)) { in jedec_dimm_field_to_str()
862 rc = rc2; in jedec_dimm_field_to_str()
866 return (rc); in jedec_dimm_field_to_str()
870 * Both DDR3 and DDR4 encode manufacturing date as a one-byte BCD-encoded
871 * year (offset from 2000) and a one-byte BCD-encoded week within that year.
877 * Instance-specific context data
897 int rc; in jedec_dimm_mfg_date() local
917 * For the page-change operation, only the DTI and LSA matter; the in jedec_dimm_mfg_date()
918 * offset and write-value are ignored, so use just 0. in jedec_dimm_mfg_date()
921 * manufacturing-related ones are on the same page, so we don't need to in jedec_dimm_mfg_date()
928 rc = smbus_writeb(sc->smbus, in jedec_dimm_mfg_date()
930 if (rc != 0) { in jedec_dimm_mfg_date()
931 device_printf(sc->dev, in jedec_dimm_mfg_date()
932 "unable to change page for offset 0x%04x: %d\n", in jedec_dimm_mfg_date()
933 year_offset, rc); in jedec_dimm_mfg_date()
936 year_offset -= JEDEC_SPD_PAGE_SIZE; in jedec_dimm_mfg_date()
937 week_offset -= JEDEC_SPD_PAGE_SIZE; in jedec_dimm_mfg_date()
939 device_printf(sc->dev, "invalid offset 0x%04x\n", year_offset); in jedec_dimm_mfg_date()
940 rc = EINVAL; in jedec_dimm_mfg_date()
945 rc = smbus_readb(sc->smbus, sc->spd_addr, year_offset, &year_bcd); in jedec_dimm_mfg_date()
946 if (rc != 0) { in jedec_dimm_mfg_date()
947 device_printf(sc->dev, "failed to read mfg year: %d\n", rc); in jedec_dimm_mfg_date()
951 rc = smbus_readb(sc->smbus, sc->spd_addr, week_offset, &week_bcd); in jedec_dimm_mfg_date()
952 if (rc != 0) { in jedec_dimm_mfg_date()
953 device_printf(sc->dev, "failed to read mfg week: %d\n", rc); in jedec_dimm_mfg_date()
957 /* Convert from one-byte BCD to one-byte integer. */ in jedec_dimm_mfg_date()
965 rc2 = smbus_writeb(sc->smbus, in jedec_dimm_mfg_date()
968 device_printf(sc->dev, in jedec_dimm_mfg_date()
969 "unable to restore page for offset 0x%04x: %d\n", in jedec_dimm_mfg_date()
974 return (rc); in jedec_dimm_mfg_date()
992 int rc; in jedec_dimm_probe() local
1003 "invalid \"addr\" hint; address must start with \"0x%x\"," in jedec_dimm_probe()
1004 " and the least-significant bit must be 0\n", in jedec_dimm_probe()
1006 rc = ENXIO; in jedec_dimm_probe()
1011 rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte); in jedec_dimm_probe()
1012 if (rc != 0) { in jedec_dimm_probe()
1021 rc = BUS_PROBE_DEFAULT; in jedec_dimm_probe()
1025 rc = BUS_PROBE_DEFAULT; in jedec_dimm_probe()
1029 rc = ENXIO; in jedec_dimm_probe()
1034 return (rc); in jedec_dimm_probe()
1038 * SMBus specifies little-endian byte order, but it looks like the TSODs use
1039 * big-endian. Read and convert.
1044 * Instance-specific context data
1055 int rc; in jedec_dimm_readw_be() local
1057 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val); in jedec_dimm_readw_be()
1058 if (rc != 0) { in jedec_dimm_readw_be()
1064 return (rc); in jedec_dimm_readw_be()
1074 * Instance-specific context data
1079 int rc; in jedec_dimm_reset_page0() local
1081 /* For the page-change operation, only the DTI and LSA matter; the in jedec_dimm_reset_page0()
1082 * offset and write-value are ignored, so just use 0. in jedec_dimm_reset_page0()
1084 rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), in jedec_dimm_reset_page0()
1086 if (rc != 0) { in jedec_dimm_reset_page0()
1087 device_printf(sc->dev, "unable to restore page: %d\n", rc); in jedec_dimm_reset_page0()
1090 return (rc); in jedec_dimm_reset_page0()
1103 int rc; in jedec_dimm_temp_sysctl() local
1110 rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val); in jedec_dimm_temp_sysctl()
1111 if (rc != 0) { in jedec_dimm_temp_sysctl()
1118 temp = -temp; in jedec_dimm_temp_sysctl()
1129 rc = sysctl_handle_int(oidp, &temp, 0, req); in jedec_dimm_temp_sysctl()
1132 return (rc); in jedec_dimm_temp_sysctl()
1159 if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) { in jedec_dimm_tsod_match()
1160 return (d->description); in jedec_dimm_tsod_match()
1165 * TSE2004av-compliant device. in jedec_dimm_tsod_match()