Angel Pons | 118a9c7 | 2020-04-02 23:48:34 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 2 | |
Subrata Banik | 6de8b42 | 2021-10-26 20:46:21 +0530 | [diff] [blame] | 3 | #include <device/dram/spd.h> |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 4 | #include <dimm_info_util.h> |
| 5 | #include <smbios.h> |
| 6 | #include <spd.h> |
| 7 | #include <console/console.h> |
| 8 | |
Subrata Banik | 3306f37 | 2021-10-26 13:19:20 +0530 | [diff] [blame] | 9 | uint8_t smbios_bus_width_to_spd_width(uint8_t ddr_type, uint16_t total_width, |
| 10 | uint16_t data_width) |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 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", 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: |
Subrata Banik | 3306f37 | 2021-10-26 13:19:20 +0530 | [diff] [blame] | 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; |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 47 | break; |
| 48 | case 0: |
| 49 | /* No extension bits */ |
| 50 | break; |
| 51 | default: |
| 52 | printk(BIOS_NOTICE, "Unknown number of extension bits %hu", |
| 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 | |
Subrata Banik | 6de8b42 | 2021-10-26 20:46:21 +0530 | [diff] [blame] | 76 | uint8_t smbios_form_factor_to_spd_mod_type(smbios_memory_type memory_type, |
| 77 | smbios_memory_form_factor form_factor) |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 78 | { |
Subrata Banik | 6de8b42 | 2021-10-26 20:46:21 +0530 | [diff] [blame] | 79 | return convert_form_factor_to_module_type(memory_type, form_factor); |
Raul E Rangel | 21db6cc | 2018-03-29 10:18:14 -0600 | [diff] [blame] | 80 | } |