root/usr/src/lib/libjedec/common/spd_ddr4.h
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2024 Oxide Computer Company
 */

#ifndef _SPD_DDR4_H
#define _SPD_DDR4_H

/*
 * Definitions for use in DDR4 Serial Presence Detect decoding based on JEDEC
 * Standard 21-C Annex L: Serial Presence Detect (SPD) for DDR4 SDRAM Modules
 * Release 6.
 *
 * DDR4 modules are organized into a few main regions:
 *
 *   o Base Configuration and DRAM parameters (bytes 0x00-0x7f)
 *   o Standard Module Parameters (bytes 0x80-0xbf) these vary on whether
 *     something is considered an RDIMM, UDIMM, LRDIMM, etc.
 *   o Hybrid Module Parameters (bytes 0xc0-0xff)
 *   o Hybrid Module Extended Parameters (bytes 0x100-0x13f).
 *   o Manufacturing Information (bytes 0x140-0x17f)
 *   o End User Programmable data (0x180-0x1ff).
 *
 * This does not currently provide definitions for DDR4 NVDIMMs.
 */

#include <sys/bitext.h>
#include "spd_common.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * S8.1.1 Number of Bytes Used / Number of Bytes in SPD Device.
 */
#define SPD_DDR4_NBYTES 0x000
#define SPD_DDR4_NBYTES_TOTAL(r)        bitx8(r, 6, 4)
#define SPD_DDR4_NBYTES_TOTAL_UNDEF     0
#define SPD_DDR4_NBYTES_TOTAL_256       1
#define SPD_DDR4_NBYTES_TOTAL_512       2
#define SPD_DDR4_NBYTES_USED(r)         bitx8(r, 3, 0)
#define SPD_DDR4_NBYTES_USED_UNDEF      0
#define SPD_DDR4_NBYTES_USED_128        1
#define SPD_DDR4_NBYTES_USED_256        2
#define SPD_DDR4_NBYTES_USED_384        3
#define SPD_DDR4_NBYTES_USED_512        4

/*
 * S8.1.2: SPD Revision. The SPD revision is split into two 4-bit fields. There
 * is an encoding level and an additions level. This can be somewhat thought of
 * like a major and minor version. The upper 4-bit encoding level tells us
 * whether or not we can parse it. The additions level just says what's been
 * added, but it doesn't reset across major versions.
 *
 * Currently all DDR4 devices are at encoding revision 1. The additions level
 * varies based on the type of DDR4 device (RDIMM, UDIMM, etc.).
 */
#define SPD_DDR4_SPD_REV        0x001
#define SPD_DDR4_SPD_REV_ENC(r) bitx8(r, 7, 4)
#define SPD_DDR4_SPD_REV_ADD(r) bitx8(r, 3, 0)
#define SPD_DDR4_SPD_REV_V1     1

/*
 * S8.1.3: Key Byte / DRAM Device Type. This field identifies the type of DDR
 * device and is actually consistent across all SPD versions. Known values are
 * in the spd_dram_type_t enumeration.
 */
#define SPD_DDR4_DRAM_TYPE      0x002

/*
 * S8.1.4: Key Byte / Module type. This is used to describe what kind of DDR
 * module it is, which tell us what the module-specific section contents are.
 * These bits, unlike the one above are device specific.
 */
#define SPD_DDR4_MOD_TYPE       0x003
#define SPD_DDR4_MOD_TYPE_ISHYBRID(r)   bitx8(r, 7, 7)
#define SPD_DDR4_MOD_TYPE_HYBRID(r)     bitx8(r, 6, 4)
#define SPD_DDR4_MOD_TYPE_HYBRID_NONE           0
#define SPD_DDR4_MOD_TYPE_HYBRID_NVDIMM_NF      1
#define SPD_DDR4_MOD_TYPE_HYBRID_NVDIMM_P       2
#define SPD_DDR4_MOD_TYPE_HYBRID_NVDIMM_H       3
#define SPD_DDR4_MOD_TYPE_TYPE(r)       bitx8(r, 3, 0)
#define SPD_DDR4_MOD_TYPE_TYPE_EXT              0
#define SPD_DDR4_MOD_TYPE_TYPE_RDIMM            1
#define SPD_DDR4_MOD_TYPE_TYPE_UDIMM            2
#define SPD_DDR4_MOD_TYPE_TYPE_SODIMM           3
#define SPD_DDR4_MOD_TYPE_TYPE_LRDIMM           4
#define SPD_DDR4_MOD_TYPE_TYPE_MINI_RDIMM       5
#define SPD_DDR4_MOD_TYPE_TYPE_MINI_UDIMM       6
#define SPD_DDR4_MOD_TYPE_TYPE_72b_SORDIMM      8
#define SPD_DDR4_MOD_TYPE_TYPE_72b_SOUDIMM      9
#define SPD_DDR4_MOD_TYPE_TYPE_16b_SODIMM       12
#define SPD_DDR4_MOD_TYPE_TYPE_32b_SODIMM       13

/*
 * S8.1.5 SDRAM Density and Banks.
 */
#define SPD_DDR4_DENSITY        0x004
#define SPD_DDR4_DENSITY_NBG_BITS(r)    bitx8(r, 7, 6)
#define SPD_DDR4_DENSITY_NBG_BITS_MAX   2
#define SPD_DDR4_DENSITY_NBA_BITS(r)    bitx8(r, 5, 4)
#define SPD_DDR4_DENSITY_NBA_BITS_BASE  2
#define SPD_DDR4_DENSITY_NBA_BITS_MAX   3
#define SPD_DDR4_DENSITY_DENSITY(r)     bitx8(r, 3, 0)
#define SPD_DDR4_DENSITY_DENSITY_256Mb  0
#define SPD_DDR4_DENSITY_DENSITY_512Mb  1
#define SPD_DDR4_DENSITY_DENSITY_1Gb    2
#define SPD_DDR4_DENSITY_DENSITY_2Gb    3
#define SPD_DDR4_DENSITY_DENSITY_4Gb    4
#define SPD_DDR4_DENSITY_DENSITY_8Gb    5
#define SPD_DDR4_DENSITY_DENSITY_16Gb   6
#define SPD_DDR4_DENSITY_DENSITY_32Gb   7
#define SPD_DDR4_DENSITY_DENSITY_12Gb   8
#define SPD_DDR4_DENSITY_DENSITY_24Gb   9

/*
 * S8.1.6 SDRAM Addressing.
 */
#define SPD_DDR4_ADDR   0x005
#define SPD_DDR4_ADDR_NROWS(r)  bitx8(r, 5, 3)
#define SPD_DDR4_ADDR_NROWS_BASE        12
#define SPD_DDR4_ADDR_NROWS_MAX         18
#define SPD_DDR4_ADDR_NCOLS(r)  bitx8(r, 2, 0)
#define SPD_DDR4_ADDR_NCOLS_BASE        9
#define SPD_DDR4_ADDR_NCOLS_MAX         12

/*
 * S8.1.7 Primary SDRAM Package Type
 * S8.1.11 Secondary SDRAM Package Type
 *
 * This contains information about the package types that are present. The
 * secondary is only used when asymmetrical SDRAM types are present. These are
 * generally the same bits and meanings, with the one exception that the bits
 * 3:2 must be 0 in the primary. As such, we try to reuse definitions. In the
 * ratio macros, the 1S and 2S refer to the fact that they are 1 and 2 module
 * densities smaller.
 */
#define SPD_DDR4_PRI_PKG        0x006
#define SPD_DDR4_SEC_PKG        0x00a
#define SPD_DDR4_PKG_TYPE(r)    bitx8(r, 7, 7)
#define SPD_DDR4_PKG_TYPE_MONO  0
#define SPD_DDR4_PKG_TYPE_NOT   1
#define SPD_DDR4_PKG_DIE_CNT(r) bitx8(r, 6, 4)
#define SPD_DDR4_PKG_DIE_CNT_BASE       1
#define SPD_DDR4_SEC_PKG_RATIO(r)       bitx8(r, 3, 2)
#define SPD_DDR4_SEC_PKG_RATIO_EQ       0
#define SPD_DDR4_SEC_PKG_RATIO_1S       1
#define SPD_DDR4_SEC_PKG_RATIO_2S       2
#define SPD_DDR4_PKG_SIG_LOAD(r)        bitx8(r, 1, 0)
#define SPD_DDR4_PKG_SIG_LOAD_UNSPEC    0
#define SPD_DDR4_PKG_SIG_LOAD_MULTI     1
#define SPD_DDR4_PKG_SIG_LOAD_SINGLE    2

/*
 * S8.1.8 SDRAM Optional Features.
 */
#define SPD_DDR4_OPT_FEAT       0x007
#define SPD_DDR4_OPT_FEAT_MAW(r)        bitx8(r, 5, 4)
#define SPD_DDR4_OPT_FEAT_MAW_8192X     0
#define SPD_DDR4_OPT_FEAT_MAW_4096X     1
#define SPD_DDR4_OPT_FEAT_MAW_2048X     2
#define SPD_DDR4_OPT_FEAT_MAC(r)        bitx8(r, 3, 0)
#define SPD_DDR4_OPT_FEAT_MAC_UNTESTED  0
#define SPD_DDR4_OPT_FEAT_MAC_700K      1
#define SPD_DDR4_OPT_FEAT_MAC_600K      2
#define SPD_DDR4_OPT_FEAT_MAC_500K      3
#define SPD_DDR4_OPT_FEAT_MAC_400K      4
#define SPD_DDR4_OPT_FEAT_MAC_300K      5
#define SPD_DDR4_OPT_FEAT_MAC_200K      6
#define SPD_DDR4_OPT_FEAT_MAC_UNLIMITED 8

/*
 * S8.1.9 SDRAM Thermal and Refresh Options. This in theory is supposed to have
 * additional information from a data sheet; however, this field is noted as
 * reserved as zero. Therefore we entirely ignore this byte.
 */

/*
 * S8.1.10 Other SDRAM Optional Features. These are even more that aren't in the
 * first set of optional features.
 */
#define SPD_DDR4_OPT_FEAT2      0x009
#define SPD_DDR4_OPT_FEAT2_PPR(r)       bitx8(r, 7, 6)
#define SPD_DDR4_OPT_FEAT2_PPR_NOTSUP   0
#define SPD_DDR4_OPT_FEAT2_PPR_1RPBG    1
#define SPD_DDR4_OPT_FEAT2_SOFT_PPR(r)  bitx8(r, 5, 5)
#define SPD_DDR4_OPT_FEAT2_MBIST_PPR(r) bitx8(r, 4, 4)

/*
 * S8.1.12 Module Nominal Voltage, VDD.
 */
#define SPD_DDR4_VOLT   0x00b
#define SPD_DDR4_VOLT_V1P2_ENDUR(r)     bitx8(r, 1, 1)
#define SPD_DDR4_VOLT_V1P2_OPER(r)      bitx8(r, 0, 0)

/*
 * S8.1.13 Module Organization
 */
#define SPD_DDR4_MOD_ORG        0x00c
#define SPD_DDR4_MOD_ORG_RANK_MIX(r)    bitx8(r, 6, 6)
#define SPD_DDR4_MOD_ORG_RANK_MIX_SYM   0
#define SPD_DDR4_MOD_ORG_RANK_MIX_ASYM  1
#define SPD_DDR4_MOD_ORG_NPKG_RANK(r)   bitx8(r, 5, 3)
#define SPD_DDR4_MOD_ORG_NPKG_RANK_BASE 1
#define SPD_DDR4_MOD_ORG_WIDTH(r)       bitx8(r, 2, 0)
#define SPD_DDR4_MOD_ORG_WIDTH_4b       0
#define SPD_DDR4_MOD_ORG_WIDTH_8b       1
#define SPD_DDR4_MOD_ORG_WIDTH_16b      2
#define SPD_DDR4_MOD_ORG_WIDTH_32b      3

/*
 * S8.1.14 Module Memory Bus Width. The extensions here are generally used for
 * ECC.
 */
#define SPD_DDR4_MOD_BUS_WIDTH  0x00d
#define SPD_DDR4_MOD_BUS_WIDTH_EXT(r)   bitx8(r, 4, 3)
#define SPD_DDR4_MOD_BUS_WIDTH_EXT_NONE 0
#define SPD_DDR4_MOD_BUS_WIDTH_EXT_8b   1
#define SPD_DDR4_MOD_BUS_WIDTH_PRI(r)   bitx8(r, 2, 0)
#define SPD_DDR4_MOD_BUS_WIDTH_PRI_8b   0
#define SPD_DDR4_MOD_BUS_WIDTH_PRI_16b  1
#define SPD_DDR4_MOD_BUS_WIDTH_PRI_32b  2
#define SPD_DDR4_MOD_BUS_WIDTH_PRI_64b  3

/*
 * S8.1.15 Module Thermal Sensor.
 */
#define SPD_DDR4_MOD_THERM      0x00e
#define SPD_DDR4_MOD_THERM_PRES(r)      bitx8(r, 7, 7)

/*
 * S8.1.16 Extended Module Type. This contains a 4-bit extended module type;
 * however, none are defined for DDR4. We do not bother with a definition for
 * it. S8.1.17 Byte 16 is just reserved as must be zero.
 */

/*
 * S8.1.18 Timebases. These values are used throughout all other calculations to
 * describe various values that are present throughout many of the subsequent
 * bytes. There are two defined entities: the Median Time Base (MTB) and the
 * Fine Time Base (FTB). There is only one MTB and FTB defined for DDR4. These
 * are 125ps and 1ps respectively.
 *
 * Many of the timing values are split into two registers. One which contains a
 * value in MTB and one which has an adjustment in FTB. This is used when there
 * would otherwise be a fractional value that could not be rounded up to an even
 * number of MTB. We represent the FTB values by appending '_FINE' to them.
 */
#define SPD_DDR4_TIMEBASE       0x011
#define SPD_DDR4_TIMEBASE_MTB(r)        bitx8(r, 3, 2)
#define SPD_DDR4_TIMEBASE_MTB_125ps     0
#define SPD_DDR4_TIMEBASE_FTB(r)        bitx8(r, 1, 0)
#define SPD_DDR4_TIMEBASE_FTB_1ps       0
#define SPD_DDR4_MTB_PS         125
#define SPD_DDR4_FTB_PS         1

/*
 * S8.1.19 SDRAM Minimum Cycle Time t~ckavg~min.
 * S8.1.52 Fine Offset for ^
 * S8.1.20 SDRAM Maximum Cycle Time t~ckavg~max.
 * S8.1.51 Fine Offset for ^
 */
#define SPD_DDR4_TCKAVG_MIN             0x012
#define SPD_DDR4_TCKAVG_MIN_FINE        0x07d
#define SPD_DDR4_TCKAVG_MAX             0x013
#define SPD_DDR4_TCKAVG_MAX_FINE        0x07c

/*
 * S8.1.21 CAS Latencies. There are four bytes that are used to get at this and
 * show what is supported. These either start at CL7 or CL23 depending on the
 * top bit of the last CAS byte.
 */
#define SPD_DDR4_CAS_SUP0       0x014
#define SPD_DDR4_CAS_SUP1       0x015
#define SPD_DDR4_CAS_SUP2       0x016
#define SPD_DDR4_CAS_SUP3       0x017
#define SPD_DDR4_CAS_SUP3_RANGE(r)      bitx8(r, 7, 7)
#define SPD_DDR4_CAS_SUP3_RANGE_7       0
#define SPD_DDR4_CAS_SUP3_RANGE_23      1

/*
 * S8.1.22 Minimum CAS Latency Time t~AA~min. This uses the MTB.
 * S8.1.50 Fine Offset for ^
 */
#define SPD_DDR4_TAA_MIN        0x018
#define SPD_DDR4_TAA_MIN_FINE   0x07b

/*
 * S8.1.23 Minimum RAS to CAS Delay Time t~RCD~min.
 * S8.1.49 Fine Offset for ^
 */
#define SPD_DDR4_TRCD_MIN       0x019
#define SPD_DDR4_TRCD_MIN_FINE  0x07a

/*
 * S8.1.24 Minimum Row Precharge Delay Time t~RP~min.
 * S8.1.48 Fine Offset for ^
 */
#define SPD_DDR4_TRP_MIN        0x01a
#define SPD_DDR4_TRP_MIN_FINE   0x079

/*
 * S8.1.25 Upper Nibbles for t~RAS~min and t~RC~min. These are bits 11:9 of
 * these values. The lower byte is in subsequent values.
 * S8.1.26 Minimum Active to Precharge Delay Time t~RAS~min.
 * S8.1.27 Minimum Active to Active/Refresh Delay Time t~RC~min.
 * S8.1.47 Fine Offset for ^
 */
#define SPD_DDR4_RAS_RC_UPPER   0x01b
#define SPD_DDR4_RAS_RC_UPPER_RC(r)     bitx8(r, 7, 4)
#define SPD_DDR4_RAS_RC_UPPER_RAS(r)    bitx8(r, 3, 0)
#define SPD_DDR4_TRAS_MIN       0x01c
#define SPD_DDR4_TRC_MIN        0x01d
#define SPD_DDR4_TRC_MIN_FINE   0x078

/*
 * S8.1.28: Minimum Refresh Recovery Delay Time t~RFC1~min.
 * S8.1.29: Minimum Refresh Recovery Delay Time t~RFC2~min.
 * S8.1.30: Minimum Refresh Recovery Delay Time t~RFC4~min.
 *
 * These are all different minimum refresh times. They are all two byte values
 * in units of MTB.
 */
#define SPD_DDR4_TRFC1_MIN_LSB  0x01e
#define SPD_DDR4_TRFC1_MIN_MSB  0x01f
#define SPD_DDR4_TRFC2_MIN_LSB  0x020
#define SPD_DDR4_TRFC2_MIN_MSB  0x021
#define SPD_DDR4_TRFC4_MIN_LSB  0x022
#define SPD_DDR4_TRFC4_MIN_MSB  0x023

/*
 * S8.1.31 Upper nibble for t~FAW~
 * S8.1.32 Minimum Four Activate Window Delay t~FAW~min.
 *
 * This is another 12-bit MTB-unit field.
 */
#define SPD_DDR4_TFAW_UPPER     0x024
#define SPD_DDR4_TFAW_UPPER_FAW(r)      bitx8(r, 3, 0)
#define SPD_DDR4_TFAW           0x025

/*
 * S8.1.33 Minimum Activate to Activate Delay Time t~RRD_S~min, different bank
 * group.
 * S8.1.46 Fine Offset for ^
 *
 * S8.1.34 Minimum Activate to Activate Delay Time t~RRD_L~min, same bank group.
 * S8.1.45 Fine Offset for ^
 *
 * S8.1.35 Minimum CAS to CAS Delay Time t~CCD_L~min, same bank group.
 * S8.1.44 Fine Offset for ^
 * group.
 */
#define SPD_DDR4_TRRDS_MIN      0x026
#define SPD_DDR4_TRRDS_MIN_FINE 0x077
#define SPD_DDR4_TRRDL_MIN      0x027
#define SPD_DDR4_TRRDL_MIN_FINE 0x076
#define SPD_DDR4_TCCDL_MIN      0x028
#define SPD_DDR4_TCCDL_MIN_FINE 0x075

/*
 * S8.1.36 Upper Nibble for t~WR~min.
 * S8.1.37 Minimum Write Recovery Time t~WR~min.
 */
#define SPD_DDR4_TWR_MIN_UPPER  0x029
#define SPD_DDR4_TWR_MIN_UPPER_TWR(r)   bitx8(r, 3, 0)
#define SPD_DDR4_TWR_MIN        0x02a

/*
 * S 8.1.38 Upper Nibbles for t~WTR~min
 * S8.1.39 Minimum Write to Read Time t~WTR_S~min, different bank group.
 * S8.1.40 Minimum Write to Read Time t~WTR_L~min, same bank group.
 *
 * Note, the referenced version of the spec has a typo here and refers to this
 * as byte 0x29, but that already exists with a different meaning.
 */
#define SPD_DDR4_TWRT_UPPER     0x02b
#define SPD_DDR4_TWRT_UPPER_TWRL(r)     bitx8(r, 7, 4)
#define SPD_DDR4_TWRT_UPPER_TWRS(r)     bitx8(r, 3, 0)
#define SPD_DDR4_TWTRS_MIN      0x02c
#define SPD_DDR4_TWTRL_MIN      0x02d

/*
 * Bytes 0x2e to 0x3b are all reserved.
 */

/*
 * S8.1.42 Connector to SDRAM bit mapping. Each of the bytes defines a different
 * set of pins here. These all have a fairly standard set of transformations
 * that can be applied. These include a package rank map which only has a single
 * identity transformation applied and a separate nibble map encoding.
 */
#define SPD_DDR4_MAP_DQ0        0x03c
#define SPD_DDR4_MAP_DQ4        0x03d
#define SPD_DDR4_MAP_DQ8        0x03e
#define SPD_DDR4_MAP_DQ12       0x03f
#define SPD_DDR4_MAP_DQ16       0x040
#define SPD_DDR4_MAP_DQ20       0x041
#define SPD_DDR4_MAP_DQ24       0x042
#define SPD_DDR4_MAP_DQ28       0x043
#define SPD_DDR4_MAP_CB0        0x044
#define SPD_DDR4_MAP_CB4        0x045
#define SPD_DDR4_MAP_DQ32       0x046
#define SPD_DDR4_MAP_DQ36       0x047
#define SPD_DDR4_MAP_DQ40       0x048
#define SPD_DDR4_MAP_DQ44       0x049
#define SPD_DDR4_MAP_DQ48       0x04a
#define SPD_DDR4_MAP_DQ52       0x04b
#define SPD_DDR4_MAP_DQ56       0x04c
#define SPD_DDR4_MAP_DQ60       0x04d
#define SPD_DDR4_MAP_PKG(r)     bitx8(r, 7, 6)
#define SPD_DDR4_MAP_PKG_FLIP   0
#define SPD_DDR4_MAP_NIBBLE(r)  bitx8(r, 5, 5)
#define SPD_DDR4_MAP_IDX(r)     bitx8(r, 4, 0)
#define SPD_DDR4_MAP_IDX_UNSPEC 0

/*
 * Bytes 0x4e-0x74 are reserved. Bytes 75-7D are fine offsets that are laid out
 * with their base counterparts.
 */

/*
 * S8.1.53 CRC For Base Configuration Section. This is a CRC that covers bytes
 * 0x00 to 0x7D using a specific CRC16.
 */
#define SPD_DDR4_CRC_LSB        0x07e
#define SPD_DDR4_CRC_MSB        0x07f

/*
 * We jump ahead to another common region which contains the common
 * manufacturing information which is shared across all module types.
 */

/*
 * S8.5.1 Module Manufacturer ID Code. This is a two byte JEP-108 style MFG ID.
 * S8.5.7 DRAM Manufacturer ID code.
 */
#define SPD_DDR4_MOD_MFG_ID0    0x140
#define SPD_DDR4_MOD_MFG_ID1    0x141
#define SPD_DDR4_DRAM_MFG_ID0   0x15e
#define SPD_DDR4_DRAM_MFG_ID1   0x15f

/*
 * S8.5.2 Module Manufacturing Location. This byte is manufacturer specific.
 */
#define SPD_DDR4_MOD_MFG_LOC    0x142

/*
 * S8.5.3 Module Manufacturing Date. Encoded as two BCD bytes for the year and
 * week.
 */
#define SPD_DDR4_MOD_MFG_YEAR   0x143
#define SPD_DDR4_MOD_MFG_WEEK   0x144

/*
 * S8.5.4 Module Serial Number.
 * S8.5.5 Module Part Number
 * S8.5.6 Module Revision Code
 */
#define SPD_DDR4_MOD_SN         0x145
#define SPD_DDR4_MOD_SN_LEN     4
#define SPD_DDR4_MOD_PN         0x149
#define SPD_DDR4_MOD_PN_LEN     20
#define SPD_DDR4_MOD_REV        0x15d

/*
 * S8.5.8 DRAM Stepping
 */
#define SPD_DDR4_DRAM_STEP      0x160

/*
 * Bytes 0x161-0x17d are left for Manufacturer specific data while bytes
 * 0x17e-0x17f are reserved.
 */

/*
 * The next region of bytes in the range 0x80-0xbf. We have specific definitions
 * for RDIMMs, LRDIMMs, and UDIMMs. While these often are very similar, they are
 * subtlety different.
 */

/*
 * S9.2.1 RDIMM: Raw Card Extension, Module Nominal Height. Bits 7-5 here have a
 * raw card revision. The revision extension, bits 7:5, are only valid when the
 * value of the normal reference card used in byte 0x82 is set to 0b11 (3).
 */
#define SPD_DDR4_RDIMM_HEIGHT   0x080
#define SPD_DDR4_RDIMM_HEIGHT_REV(r)    bitx8(r, 7, 5)
#define SPD_DDR4_RDIMM_HEIGHT_MM(r)     bitx8(r, 4, 0)
#define SPD_DDR4_RDIMM_HEIGHT_LT15MM    0
#define SPD_DDR4_RDIMM_HEIGHT_BASE      15

/*
 * S9.2.2 RDIMM: Module Maximum Thickness. These measure thicknesses in mm, with
 * zero value meaning less than or equal to 1mm.
 */
#define SPD_DDR4_RDIMM_THICK    0x081
#define SPD_DDR4_RDIMM_THICK_BACK(r)    bitx8(r, 7, 4)
#define SPD_DDR4_RDIMM_THICK_FRONT(r)   bitx8(r, 3, 0)
#define SPD_DDR4_RDIMM_THICK_BASE       1

/*
 * S9.2.3 RDIMM: Reference Raw Card Used. Bit 7 is used as basically another bit
 * for bits 4-0. We do not define each meaning of these bit combinations in this
 * header, that is left for tables in the library. When bits 6:5 are 0b11 (3)
 * then we must add in the reference card value in byte 0x80 to bits 6:5.
 */
#define SPD_DDR4_RDIMM_REF      0x082
#define SPD_DDR4_RDIMM_REF_EXT(r)       bitx8(r, 7, 7)
#define SPD_DDR4_RDIMM_REF_REV(r)       bitx8(r, 6, 5)
#define SPD_DDR4_RDIMM_REV_USE_HEIGHT   3
#define SPD_DDR4_RDIMM_REF_CARD(r)      bitx8(r, 4, 0)

/*
 * S9.2.4 RDIMM: DIMM Attributes.
 */
#define SPD_DDR4_RDIMM_ATTR     0x083
#define SPD_DDR4_RDIMM_ATTR_TYPE(r)     bitx8(r, 7, 4)
#define SPD_DDR4_RDIMM_ATTR_TYPE_RCD01  0
#define SPD_DDR4_RDIMM_ATTR_TYPE_RCD02  1
#define SPD_DDR4_RDIMM_ATTR_NROWS(r)    bitx8(r, 3, 2)
#define SPD_DDR4_RDIMM_ATTR_NREGS(r)    bitx8(r, 1, 0)

/*
 * S9.2.5 RDIMM: Thermal Heat Spreader Solution
 */
#define SPD_DDR4_RDIMM_THERM    0x084
#define SPD_DDR4_RDIMM_THERM_IMPL(r)    bitx8(r, 7, 7)

/*
 * S9.2.6 RDIMM: Register Manufacturer JEDEC ID. This contains the JEDEC ID for
 * the manufacturer encoded as the number of continuation bytes and then the
 * actual code. This works with libjedec_vendor_string.
 */
#define SPD_DDR4_RDIMM_REG_MFG_ID0      0x085
#define SPD_DDR4_RDIMM_REG_MFG_ID1      0x086

/*
 * S9.2.7 RDIMM: Register Revision Number. This value is just a straight up hex
 * encoded value. It's a bit arbitrary. For example, they say 0x31 can be rev
 * 3.1, while 0x01 is just revision 1, and 0xB1 is revision B1.
 */
#define SPD_DDR4_RDIMM_REV      0x087
#define SPD_DDR4_RDIMM_REV_UNDEF        0xff

/*
 * S9.2.8 RDIMM: Address Mapping from Register to DRAM. This covers how the
 * register maps ranks 1 and 3 between the register and the actual modules.
 * Ranks 0/2 are always standard.
 */
#define SPD_DDR4_RDIMM_MAP      0x88
#define SPD_DDR4_RDIMM_MAP_R1(r)        bitx8(r, 0, 0)
#define SPD_DDR4_RDIMM_MAP_R1_STD       0
#define SPD_DDR4_RDIMM_MAP_R1_MIRROR    1

/*
 * S9.2.9 RDIMM: Register Output Drive Strength for Control and Command/Address
 * S9.2.10 RDIMM: Register Output Drive Strength for Clock
 */
#define SPD_DDR4_RDIMM_ODS0     0x89
#define SPD_DDR4_RDIMM_ODS0_CS(r)       bitx8(r, 7, 6)
#define SPD_DDR4_RDIMM_ODS0_CA(r)       bitx8(r, 5, 4)
#define SPD_DDR4_RDIMM_ODS0_ODT(r)      bitx8(r, 3, 2)
#define SPD_DDR4_RDIMM_ODS0_CKE(r)      bitx8(r, 1, 0)
#define SPD_DDR4_RDIMM_ODS0_LIGHT       0
#define SPD_DDR4_RDIMM_ODS0_MODERATE    1
#define SPD_DDR4_RDIMM_ODS0_STRONG      2
#define SPD_DDR4_RDIMM_ODS0_VERY_STRONG 3
#define SPD_DDR4_RDIMM_ODS1     0x8a
#define SPD_DDR4_RDIMM_ODS1_SLEW_SUP(r) bitx8(r, 6, 6)
#define SPD_DDR4_RDIMM_ODS1_Y1(r)       bitx8(r, 3, 2)
#define SPD_DDR4_RDIMM_ODS1_Y0(r)       bitx8(r, 1, 0)

/*
 * S9.2.12 CRC for SPD Block 1.
 */
#define SPD_DDR4_BLK1_CRC_START 0x80
#define SPD_DDR4_BLK1_CRC_LSB   0xfe
#define SPD_DDR4_BLK1_CRC_MSB   0xff

/*
 * S9.1.1 UDIMM: Raw Card Extension, Module Nominal Height.
 * S9.1.2 UDIMM: Module Maximum Thickness.
 * S9.1.3 UDIMM: Reference Raw Card Used.
 *
 * These definitions are the same as for RDIMMs.
 */
#define SPD_DDR4_UDIMM_HEIGHT   0x080
#define SPD_DDR4_UDIMM_THICK    0x081
#define SPD_DDR4_UDIMM_REF      0x082

/*
 * S9.1.4 UDIMM: Address Mapping from Edge Connector to DRAM. This is similar to
 * SPD_DDR4_RDIMM_MAP; however it doesn't take into account the register.
 */
#define SPD_DDR4_UDIMM_MAP      0x83

/*
 * Everything else in UDIMMs is reserved, aside from the CRC, which is the same
 * as RDIMMs.
 */

/*
 * S9.3.1 LRDIMM: Raw Card Extension, Module Nominal Height
 * S9.3.2 LRDIMM: Module Maximum Thickness
 * S9.3.3 LRDIMM: Reference Raw Card Used
 *
 * These are the same as the corresponding UDIMM / RDIMM values.
 */
#define SPD_DDR4_LRDIMM_HEIGHT  0x080
#define SPD_DDR4_LRDIMM_THICK   0x081
#define SPD_DDR4_LRDIMM_REF     0x082

/*
 * S9.3.4 LRDIMM: DIMM Attributes.
 */
#define SPD_DDR4_LRDIMM_ATTR    0x083
#define SPD_DDR4_LRDIMM_ATTR_TYPE(r)    bitx8(r, 7, 4)
#define SPD_DDR4_LRDIMM_ATTR_TYPE_RCD01_DB01    0
#define SPD_DDR4_LRDIMM_ATTR_TYPE_RCD02_DB02    1
#define SPD_DDR4_LRDIMM_ATTR_NROWS(r)   bitx8(r, 3, 2)
#define SPD_DDR4_LRDIMM_ATTR_NREGS(r)   bitx8(r, 1, 0)

/*
 * S9.3.5 LRDIMM: Thermal Heat Spreader. See RDIMM version.
 */
#define SPD_DDR4_LRDIMM_THERM   0x084

/*
 * S9.3.6 LRDIMM: Register and Data Buffer Manufacturer. See RDIMM version.
 */
#define SPD_DDR4_LRDIMM_REG_MFG_ID0     0x085
#define SPD_DDR4_LRDIMM_REG_MFG_ID1     0x086

/*
 * S9.3.7 LRDIMM: Register Revision Number. See RDIMM for more info.
 */
#define SPD_DDR4_LRDIMM_REV     0x087

/*
 * S9.3.8 LRDIMM: Address Mapping from Register to DRAM. See RDIMM.
 */
#define SPD_DDR4_LRDIMM_MAP     0x88

/*
 * S9.3.9 LRDIMM: Register Output Drive Strength for Control and
 * Command/Address.
 * S9.3.10: LRDIMM: Register Output Drive Strength for Clock and Data Buffer
 * Control.
 * See RDIMM for valid drive strength values and ODS0.
 */
#define SPD_DDR4_LRDIMM_ODS0    0x89
#define SPD_DDR4_LRDIMM_ODS1    0x8a
#define SPD_DDR4_LRDIMM_ODS1_OSRC_SUP(r)        bitx8(r, 6, 6)
#define SPD_DDR4_LRDIMM_ODS1_BCK(r)     bitx8(r, 5, 5)
#define SPD_DDR4_LRDIMM_ODS1_BCOM(r)    bitx8(r, 4, 4)
#define SPD_DDR4_LRDIMM_ODS1_MODERATE   0
#define SPD_DDR4_LRDIMM_ODS1_STRONG     1
/*
 * The above two bit ranges use a single bit drive strength while the following
 * two use the same two-bit version as RDIMMs.
 */
#define SPD_DDR4_RDIMM_ODS1_Y1(r)       bitx8(r, 3, 2)
#define SPD_DDR4_RDIMM_ODS1_Y0(r)       bitx8(r, 1, 0)

/*
 * S9.3.7 LRDIMM: Data Buffer Revision Number.
 */
#define SPD_DDR4_LRDIMM_DB_REV  0x08b

/*
 * S9.3.12 LRDIMM: DRAM VrefDQ for Package Rank 0
 * S9.3.13 LRDIMM: DRAM VrefDQ for Package Rank 1
 * S9.3.14 LRDIMM: DRAM VrefDQ for Package Rank 2
 * S9.3.15 LRDIMM: DRAM VrefDQ for Package Rank 3
 *
 * These are all encoded with a value from MR6 in JESD79-4 apparently.
 */
#define SPD_DDR4_LRDIMM_VREFDQ0 0x08c
#define SPD_DDR4_LRDIMM_VREFDQ1 0x08d
#define SPD_DDR4_LRDIMM_VREFDQ2 0x08e
#define SPD_DDR4_LRDIMM_VREFDQ3 0x08f
#define SPD_DDR4_LRDIMM_VREFDQ_V(r)     bitx8(r, 5, 0)

/*
 * S9.3.16 LRDIMM: Data Buffer VrefDQ for DRAM Interface. The entire byte is
 * used to match the encoding from the DDR4DB01 spec.
 */
#define SPD_DDR4_LRDIMM_VREFDQ_DB       0x090

/*
 * S9.3.17 LRDIMM: Data Buffer MDQ Drive Strength and RTT for data rate <= 1866
 * S9.3.18 LRDIMM: Data Buffer MDQ Drive Strength and RTT for 1866 < data rate
 * <= 2400
 * S9.3.19 LRDIMM: Data Buffer MDQ Drive Strength and RTT for 2400 < data rate
 * <= 3200
 *
 * These three registers all share the same bit values and register extraction.
 */
#define SPD_DDR4_LRDIMM_MDQ_1866        0x091
#define SPD_DDR4_LRDIMM_MDQ_2400        0x092
#define SPD_DDR4_LRDIMM_MDQ_3200        0x093
#define SPD_DDR4_LRDIMM_MDQ_DS(r)       bitx8(r, 6, 4)
#define SPD_DDR4_LRDIMM_MDQ_DS_40R      0
#define SPD_DDR4_LRDIMM_MDQ_DS_34R      1
#define SPD_DDR4_LRDIMM_MDQ_DS_48R      2
#define SPD_DDR4_LRDIMM_MDQ_DS_60R      5
#define SPD_DDR4_LRDIMM_MDQ_RTT(r)      bitx8(r, 2, 0)
#define SPD_DDR4_LRDIMM_MDQ_RTT_DIS     0
#define SPD_DDR4_LRDIMM_MDQ_RTT_60R     1
#define SPD_DDR4_LRDIMM_MDQ_RTT_120R    2
#define SPD_DDR4_LRDIMM_MDQ_RTT_40R     3
#define SPD_DDR4_LRDIMM_MDQ_RTT_240R    4
#define SPD_DDR4_LRDIMM_MDQ_RTT_48R     5
#define SPD_DDR4_LRDIMM_MDQ_RTT_80R     6
#define SPD_DDR4_LRDIMM_MDQ_RTT_34R     7

/*
 * S9.3.20: LRDIMM: DRAM Drive Strength. One byte covers all data rates, which
 * share the same resistance values.
 */
#define SPD_DDR4_LRDIMM_DRAM_DS 0x094
#define SPD_DDR4_LRDIMM_DRAM_DS_3200(r) bitx8(r, 5, 4)
#define SPD_DDR4_LRDIMM_DRAM_DS_2400(r) bitx8(r, 3, 2)
#define SPD_DDR4_LRDIMM_DRAM_DS_1866(r) bitx8(r, 1, 0)
#define SPD_DDR4_LRDIMM_DRAM_DS_34R     0
#define SPD_DDR4_LRDIMM_DRAM_DS_48R     1

/*
 * S9.3.21 LRDIMM: DRAM ODT (RTT_WR and RTT_NOM) for data rate <= 1866
 * S9.3.22 LRDIMM: DRAM ODT (RTT_WR and RTT_NOM) for 1866 < data rate <= 2400
 * S9.3.23 LRDIMM: DRAM ODT (RTT_WR and RTT_NOM) for 2400 < data rate <= 3200
 */
#define SPD_DDR4_LRDIMM_ODT_1866        0x095
#define SPD_DDR4_LRDIMM_ODT_2400        0x096
#define SPD_DDR4_LRDIMM_ODT_3200        0x097
#define SPD_DDR4_LRDIMM_ODT_WR(r)       bitx8(r, 5, 3)
#define SPD_DDR4_LRDIMM_ODT_WR_DYN_OFF  0
#define SPD_DDR4_LRDIMM_ODT_WR_120R     1
#define SPD_DDR4_LRDIMM_ODT_WR_240R     2
#define SPD_DDR4_LRDIMM_ODT_WR_HIZ      3
#define SPD_DDR4_LRDIMM_ODT_WR_80R      4
#define SPD_DDR4_LRDIMM_ODT_NOM(r)      bitx8(r, 2, 0)
#define SPD_DDR4_LRDIMM_ODT_NOM_DIS     0
#define SPD_DDR4_LRDIMM_ODT_NOM_60R     1
#define SPD_DDR4_LRDIMM_ODT_NOM_120R    2
#define SPD_DDR4_LRDIMM_ODT_NOM_40R     3
#define SPD_DDR4_LRDIMM_ODT_NOM_240R    4
#define SPD_DDR4_LRDIMM_ODT_NOM_48R     5
#define SPD_DDR4_LRDIMM_ODT_NOM_80R     6
#define SPD_DDR4_LRDIMM_ODT_NOM_34R     7

/*
 * S9.3.24 LRDIMM: DRAM ODT (RTT_PARK) for data rate <= 1866
 * S9.3.25 LRDIMM: DRAM ODT (RTT_PARK) for 1866 < data rate <= 2400
 * S9.3.26 LRDIMM: DRAM ODT (RTT_PARK) for 2400 < data rate <= 3200
 */
#define SPD_DDR4_LRDIMM_PARK_1866       0x098
#define SPD_DDR4_LRDIMM_PARK_2400       0x099
#define SPD_DDR4_LRDIMM_PARK_3200       0x09a
#define SPD_DDR4_LRDIMM_PARK_R23(r)     bitx8(r, 5, 3)
#define SPD_DDR4_LRDIMM_PARK_R01(r)     bitx8(r, 2, 0)
#define SPD_DDR4_LRDIMM_PARK_DIS        0
#define SPD_DDR4_LRDIMM_PARK_60R        1
#define SPD_DDR4_LRDIMM_PARK_120R       2
#define SPD_DDR4_LRDIMM_PARK_40R        3
#define SPD_DDR4_LRDIMM_PARK_240R       4
#define SPD_DDR4_LRDIMM_PARK_48R        5
#define SPD_DDR4_LRDIMM_PARK_80R        6
#define SPD_DDR4_LRDIMM_PARK_34R        7

/*
 * S9.3.27: Data Buffer VrefDQ for DRAM Interface Range.
 */
#define SPD_DDR4_LRDIMM_VREFDQ_RNG      0x09b
#define SPD_DDR4_LRDIMM_VREFDQ_RNG_DB(r)        bitx8(r, 4, 4)
#define SPD_DDR4_LRDIMM_VREFDQ_RNG_R3(r)        bitx8(r, 3, 3)
#define SPD_DDR4_LRDIMM_VREFDQ_RNG_R2(r)        bitx8(r, 2, 2)
#define SPD_DDR4_LRDIMM_VREFDQ_RNG_R1(r)        bitx8(r, 1, 1)
#define SPD_DDR4_LRDIMM_VREFDQ_RNG_R0(r)        bitx8(r, 0, 0)
#define SPD_DDR4_LRDIMM_VERFDQ_RNG_1    0
#define SPD_DDR4_LRDIMM_VERFDQ_RNG_2    1

/*
 * S9.3.28: Data Buffer DQ Decision Feedback Equalization
 */
#define SPD_DDR4_LRDIMM_EQ      0x09c
#define SPD_DDR4_LRDIMM_EQ_DFE_SUP(r)   bitx8(r, 1, 1)
#define SPD_DDR4_LRDIMM_EQ_GA_SUP(r)    bitx8(r, 0, 0)

#ifdef __cplusplus
}
#endif

#endif /* _SPD_DDR4_H */