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