Lines Matching +full:read +full:- +full:out
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
7 * Copyright (c) 2018-2023 Panasas
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
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
189 * @param[out] new_offset
190 * The offset to actually read from, adjusted if needed.
192 * @param[out] page_changed
212 /* Within page0; no adjustment or page-change required. */ in jedec_dimm_adjust_offset()
214 goto out; in jedec_dimm_adjust_offset()
218 device_printf(sc->dev, "invalid offset 0x%04x\n", orig_offset); in jedec_dimm_adjust_offset()
219 goto out; 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()
234 goto out; in jedec_dimm_adjust_offset()
237 *new_offset = orig_offset - JEDEC_SPD_PAGE_SIZE; in jedec_dimm_adjust_offset()
239 out: in jedec_dimm_adjust_offset()
244 * device_attach() method. Read the DRAM type, use that to determine the offsets
246 * present, figure out exactly what it is, and update the device description.
252 * @param[in,out] dev
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()
291 /* Read the DRAM type, and set the various offsets and lengths. */ in jedec_dimm_attach()
292 rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte); in jedec_dimm_attach()
294 device_printf(dev, "failed to read dram_type: %d\n", rc); in jedec_dimm_attach()
295 goto out; 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()
318 goto out; in jedec_dimm_attach()
322 /* bootverbose debuggery is best-effort, so ignore the rc. */ in jedec_dimm_attach()
326 /* Read all the required info from the SPD. If any of it fails, error in jedec_dimm_attach()
327 * out without creating the sysctls. in jedec_dimm_attach()
329 rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb); in jedec_dimm_attach()
331 goto out; in jedec_dimm_attach()
334 rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week); in jedec_dimm_attach()
336 goto out; in jedec_dimm_attach()
339 rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str), in jedec_dimm_attach()
342 goto out; in jedec_dimm_attach()
345 rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str), in jedec_dimm_attach()
348 goto out; in jedec_dimm_attach()
351 /* The MSBit of the TSOD-presence byte reports whether or not the TSOD in jedec_dimm_attach()
354 * discussed in [PR 235944], it turns out that some DIMMs claim to have in jedec_dimm_attach()
357 * If the SPD data says the TSOD is present, try to read manufacturer in jedec_dimm_attach()
360 * If the data was read successfully, see if it is a known TSOD device; 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()
367 goto out; in jedec_dimm_attach()
374 "failed to read TSOD Manufacturer ID\n"); in jedec_dimm_attach()
380 device_printf(dev, "failed to read TSOD Device ID\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()
457 out: 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
478 * @param[out] capacity_mb
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()
524 goto out; 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()
531 goto out; 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()
539 goto out; 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()
546 goto out; 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()
555 "failed to read sdram_pkg_type: %d\n", rc); in jedec_dimm_capacity()
556 goto out; in jedec_dimm_capacity()
566 device_printf(sc->dev, "invalid bus width info\n"); in jedec_dimm_capacity()
568 goto out; 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()
581 goto out; in jedec_dimm_capacity()
584 device_printf(sc->dev, "invalid DIMM Rank info\n"); in jedec_dimm_capacity()
586 goto out; 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()
603 goto out; in jedec_dimm_capacity()
606 device_printf(sc->dev, "invalid SDRAM capacity info\n"); in jedec_dimm_capacity()
608 goto out; in jedec_dimm_capacity()
617 device_printf(sc->dev, "invalid SDRAM width info\n"); in jedec_dimm_capacity()
619 goto out; in jedec_dimm_capacity()
640 out: in jedec_dimm_capacity()
645 * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
650 * @param[in,out] dev
659 free(sc->slotid_str, M_DEVBUF); in jedec_dimm_detach()
665 * Read and dump the entire SPD contents.
670 * Instance-specific context data
673 * The length of data which needs to be read and dumped differs based on
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()
690 "unable to read page0:0x%02x: %d\n", i, rc); in jedec_dimm_dump()
691 goto out; 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()
718 "unable to read page1:0x%02x: %d\n", i, rc); in jedec_dimm_dump()
719 goto out; in jedec_dimm_dump()
727 out: in jedec_dimm_dump()
741 * Read a specified range of bytes from the SPD, convert them to a string, and
742 * store them in the provided buffer. Some SPD fields are space-padded ASCII,
748 * Instance-specific context data
750 * @param[out] dst
778 goto out; 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()
787 goto out; in jedec_dimm_field_to_str()
791 device_printf(sc->dev, in jedec_dimm_field_to_str()
794 goto out; 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()
810 goto out; in jedec_dimm_field_to_str()
815 device_printf(sc->dev, in jedec_dimm_field_to_str()
818 goto out; in jedec_dimm_field_to_str()
822 /* Read a byte at a time. */ 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()
828 "failed to read byte at 0x%02x: %d\n", in jedec_dimm_field_to_str()
830 goto out; 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()
856 out: 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
882 * @param[out] year
885 * @param[out] week
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()
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()
942 goto out; 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()
948 goto out; 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()
954 goto out; in jedec_dimm_mfg_date()
957 /* Convert from one-byte BCD to one-byte integer. */ in jedec_dimm_mfg_date()
961 out: 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()
1004 " and the least-significant bit must be 0\n", in jedec_dimm_probe()
1007 goto out; in jedec_dimm_probe()
1010 /* Try to read the DRAM_TYPE from the SPD. */ in jedec_dimm_probe()
1013 device_printf(dev, "failed to read dram_type\n"); in jedec_dimm_probe()
1014 goto out; in jedec_dimm_probe()
1033 out: 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
1047 * The register number to read.
1049 * @param[out] val
1050 * Pointer to populate with the value read.
1057 rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val); in jedec_dimm_readw_be()
1059 goto out; in jedec_dimm_readw_be()
1063 out: 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()
1094 * Read the temperature data from the TSOD and convert it to the deciKelvin
1112 goto out; in jedec_dimm_temp_sysctl()
1118 temp = -temp; in jedec_dimm_temp_sysctl()
1131 out: 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()