50 .max_clock_mhz = 1067,
54 .min_clock_mhz = 1068,
55 .max_clock_mhz = 1200,
59 .min_clock_mhz = 1201,
60 .max_clock_mhz = 1333,
64 .min_clock_mhz = 1334,
65 .max_clock_mhz = 1466,
69 .min_clock_mhz = 1467,
70 .max_clock_mhz = 1600,
98 {.type =
BLOCK_3, 384, 128, 0} };
108 return spd_crc == crc;
125 is_hybrid = (dimm_type >> 4) & ((1 << 3) - 1);
146 printk(
BIOS_ERR,
"DDR4 speed of %d MHz is out of range\n", speed_mhz);
169 u8 bus_width, sdram_width;
170 u16 cap_per_die_mbit;
171 u16 spd_bytes_total, spd_bytes_used;
172 const uint16_t spd_bytes_used_table[] = {0, 128, 256, 384, 512};
181 spd_bytes_total = (spd[0] >> 4) & 0x7;
182 spd_bytes_used = spd[0] & 0xf;
184 if (!spd_bytes_total || !spd_bytes_used) {
189 if (spd_bytes_total >= 3)
192 spd_bytes_total = 256 << (spd_bytes_total - 1);
194 if (spd_bytes_used > 4) {
199 spd_bytes_used = spd_bytes_used_table[spd_bytes_used];
201 if (spd_bytes_used > spd_bytes_total) {
202 printk(
BIOS_ERR,
"SPD Bytes Used is greater than SPD Bytes Total\n");
224 dimm->
dimm_type = spd[3] & ((1 << 4) - 1);
226 reg8 = spd[13] & ((1 << 4) - 1);
228 bus_width = 8 << (reg8 & ((1 << 3) - 1));
230 reg8 = spd[12] & ((1 << 3) - 1);
232 sdram_width = 4 << reg8;
234 reg8 = spd[4] & ((1 << 4) - 1);
236 cap_per_die_mbit = (1 << reg8) * 256;
238 reg8 = (spd[12] >> 3) & ((1 << 3) - 1);
239 dimm->
ranks = reg8 + 1;
241 if (!bus_width || !sdram_width) {
251 dimm->
size_mb = cap_per_die_mbit / 8 * bus_width / sdram_width * dimm->
ranks;
254 if (spd_bytes_used > 320) {
281 memset(mem_info, 0,
sizeof(*mem_info));
300 switch (
info->dimm_type) {
void * memcpy(void *dest, const void *src, size_t n)
void * memset(void *dstpp, int c, size_t len)
cb_err
coreboot error codes
@ CB_ERR
Generic error code.
@ CB_SUCCESS
Call completed successfully.
void * cbmem_add(u32 id, u64 size)
void * cbmem_find(u32 id)
#define printk(level,...)
int spd_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_raw_data spd)
Decode the raw SPD data.
static bool verify_block(const spd_block *block, spd_raw_data spd)
uint16_t ddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz)
Converts DDR4 clock speed in MHz to the standard reported speed in MT/s.
static const struct ddr4_speed_attr ddr4_speeds[]
DDR4 speed attributes derived from JEDEC 79-4C tables 169 & 170.
const spd_block spd_blocks[]
enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 selected_freq, const struct dimm_attr_ddr4_st *info)
static bool block_exists(spd_block_type type, u8 dimm_type)
Utilities for decoding DDR4 SPDs.
@ SPD_DDR4_DIMM_TYPE_SO_DIMM
@ SPD_DDR4_DIMM_TYPE_UDIMM
@ SPD_DDR4_DIMM_TYPE_RDIMM
@ SPD_DDR4_DIMM_TYPE_72B_SO_RDIMM
#define SPD_DDR4_PART_LEN
u16 ddr_crc16(const u8 *ptr, int n_crc)
Calculate the CRC of a DDR SPD data.
static struct smmstore_params_info info
@ SPD_MEMORY_TYPE_DDR4_SDRAM
@ SPD_MEMORY_TYPE_UNDEFINED
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
char part_number[SPD_DDR4_PART_LEN+1]
enum spd_memory_type dram_type
enum spd_dimm_type_ddr4 dimm_type
If this table is filled and put in CBMEM, then these info in CBMEM will be used to generate smbios ty...
uint8_t module_part_number[DIMM_INFO_PART_NUMBER_SIZE]
uint8_t serial[DIMM_INFO_SERIAL_SIZE]
struct dimm_info dimm[DIMM_INFO_TOTAL]