/ src / lib / dimm_info_util.c
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  }