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