xref: /aosp_15_r20/external/coreboot/src/lib/dimm_info_util.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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 
smbios_bus_width_to_spd_width(uint8_t ddr_type,uint16_t total_width,uint16_t data_width)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 
smbios_memory_size_to_mib(uint16_t memory_size,uint32_t extended_size)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 
smbios_form_factor_to_spd_mod_type(smbios_memory_type memory_type,smbios_memory_form_factor form_factor)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 }
81