dimm_info_util.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <device/dram/spd.h> 4 #include <dimm_info_util.h> 5 #include <smbios.h> 6 #include <spd.h> 7 #include <console/console.h> 8 9 uint8_t smbios_bus_width_to_spd_width(uint8_t ddr_type, uint16_t total_width, 10 uint16_t data_width) 11 { 12 uint8_t out; 13 14 /* Lookup table as defined in the JEDEC Standard. */ 15 switch (data_width) { 16 case 64: 17 out = MEMORY_BUS_WIDTH_64; 18 break; 19 case 32: 20 out = MEMORY_BUS_WIDTH_32; 21 break; 22 case 16: 23 out = MEMORY_BUS_WIDTH_16; 24 break; 25 case 8: 26 out = MEMORY_BUS_WIDTH_8; 27 break; 28 default: 29 printk(BIOS_NOTICE, "Unknown memory size %hu\n", data_width); 30 /* 31 * The SMBIOS spec says we should set 0xFFFF on an unknown 32 * value, but we don't have a way of passing that signal via SPD 33 * encoded values. 34 */ 35 out = MEMORY_BUS_WIDTH_8; 36 break; 37 } 38 39 uint16_t extension_bits = total_width - data_width; 40 41 switch (extension_bits) { 42 case 8: 43 if (ddr_type == MEMORY_TYPE_DDR5 || ddr_type == MEMORY_TYPE_LPDDR5) 44 out |= SPD_ECC_8BIT_LP5_DDR5; 45 else 46 out |= SPD_ECC_8BIT; 47 break; 48 case 0: 49 /* No extension bits */ 50 break; 51 default: 52 printk(BIOS_NOTICE, "Unknown number of extension bits %hu\n", 53 extension_bits); 54 break; 55 } 56 57 return out; 58 } 59 60 uint32_t smbios_memory_size_to_mib(uint16_t memory_size, uint32_t extended_size) 61 { 62 /* Memory size is unknown */ 63 if (memory_size == 0xFFFF) 64 return 0; 65 /* (32 GiB - 1 MiB) or greater is expressed in the extended size. */ 66 else if (memory_size == 0x7FFF) 67 return extended_size; 68 /* When the MSB is flipped, the value is specified in kilobytes */ 69 else if (memory_size & 0x8000) 70 return (memory_size ^ 0x8000) / KiB; 71 /* Value contains MiB */ 72 else 73 return memory_size; 74 } 75 76 uint8_t smbios_form_factor_to_spd_mod_type(smbios_memory_type memory_type, 77 smbios_memory_form_factor form_factor) 78 { 79 return convert_form_factor_to_module_type(memory_type, form_factor); 80 }