Lines Matching +full:com +full:- +full:offset

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
87 * http://www.atmel.com/images/doc8711.pdf
88 * http://www.atmel.com/images/atmel-8868-dts-at30tse004a-datasheet.pdf
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
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
115 * http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
117 * http://ww1.microchip.com/downloads/en/DeviceDoc/00001605A.pdf
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
138 * http://www.st.com/resource/en/datasheet/cd00157558.pdf
139 * http://www.st.com/resource/en/datasheet/stts2002.pdf
158 size_t dstsz, uint16_t offset, uint16_t len, bool ascii);
176 * The DDR4 SPD information is spread across two 256-byte pages, but the
177 * offsets in the spec are absolute, not per-page. If a given offset is on the
178 * second page, we need to change to that page and adjust the offset to be
184 * Instance-specific context data
187 * The original value of the offset, before any adjustment is made.
190 * The offset to actually read from, adjusted if needed.
193 * Whether or not the page was actually changed, and the offset adjusted.
202 /* Don't change the offset, or indicate that the page has been changed, in jedec_dimm_adjust_offset()
212 /* Within page0; no adjustment or page-change required. */ 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()
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()
237 *new_offset = orig_offset - JEDEC_SPD_PAGE_SIZE; in jedec_dimm_adjust_offset()
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()
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()
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()
334 rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week); in jedec_dimm_attach()
339 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str), in jedec_dimm_attach()
345 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str), 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()
365 device_printf(dev, "failed to read TSOD-present byte: %d\n", 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()
464 * in look-up tables, but it's trivial to reverse-engineer the the formulas for
472 * Instance-specific context data
520 rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset, 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()
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()
537 device_printf(sc->dev, "failed to read sdram_capacity: %d\n", in jedec_dimm_capacity()
542 rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset, 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()
554 device_printf(sc->dev, in jedec_dimm_capacity()
566 device_printf(sc->dev, "invalid bus width info\n"); 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()
584 device_printf(sc->dev, "invalid DIMM Rank info\n"); 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()
606 device_printf(sc->dev, "invalid SDRAM capacity info\n"); in jedec_dimm_capacity()
617 device_printf(sc->dev, "invalid SDRAM width info\n"); 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
687 rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]); in jedec_dimm_dump()
689 device_printf(sc->dev, 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()
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()
714 rc = smbus_readb(sc->smbus, sc->spd_addr, i, in jedec_dimm_dump()
717 device_printf(sc->dev, in jedec_dimm_dump()
742 * store them in the provided buffer. Some SPD fields are space-padded ASCII,
748 * Instance-specific context data
756 * @param[in] offset
757 * The starting offset of the field within the SPD
768 uint16_t offset, uint16_t len, bool ascii) in jedec_dimm_field_to_str() argument
776 rc = jedec_dimm_adjust_offset(sc, offset, &new_offset, &page_changed); in jedec_dimm_field_to_str()
781 /* Sanity-check (adjusted) offset and length; everything must be within in jedec_dimm_field_to_str()
786 device_printf(sc->dev, "invalid offset 0x%04x\n", new_offset); in jedec_dimm_field_to_str()
791 device_printf(sc->dev, in jedec_dimm_field_to_str()
797 /* Sanity-check the destination string length. If we're dealing with in jedec_dimm_field_to_str()
807 device_printf(sc->dev, 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()
827 device_printf(sc->dev, in jedec_dimm_field_to_str()
836 /* Raw bytes need to be converted to a two-byte hex in jedec_dimm_field_to_str()
845 for (i = dstsz - 1; i > 0; i--) { 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
883 * The manufacturing year, offset from 2000
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()
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()
935 /* Adjust the offset to account for the page change. */ 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()
945 rc = smbus_readb(sc->smbus, sc->spd_addr, year_offset, &year_bcd); 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()
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()
1004 " and the least-significant bit must be 0\n", 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
1057 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val); in jedec_dimm_readw_be()
1074 * Instance-specific context data
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()
1087 device_printf(sc->dev, "unable to restore page: %d\n", rc); in jedec_dimm_reset_page0()
1118 temp = -temp; 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()