diff options
Diffstat (limited to 'src/northbridge/intel/haswell/raminit.c')
-rw-r--r-- | src/northbridge/intel/haswell/raminit.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index 5d67954125..0b5969249a 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -10,6 +10,7 @@ #include <memory_info.h> #include <mrc_cache.h> #include <device/pci_def.h> +#include <device/pci_ops.h> #include <device/dram/ddr3.h> #include <smbios.h> #include <spd.h> @@ -170,6 +171,45 @@ void sdram_initialize(struct pei_data *pei_data) report_memory_config(); } +static bool nb_supports_ecc(const uint32_t capid0_a) +{ + return !(capid0_a & CAPID_ECCDIS); +} + +static uint16_t nb_slots_per_channel(const uint32_t capid0_a) +{ + return !(capid0_a & CAPID_DDPCD) + 1; +} + +static uint16_t nb_number_of_channels(const uint32_t capid0_a) +{ + return !(capid0_a & CAPID_PDCD) + 1; +} + +static uint32_t nb_max_chan_capacity_mib(const uint32_t capid0_a) +{ + uint32_t ddrsz; + + /* Values from documentation, which assume two DIMMs per channel */ + switch (CAPID_DDRSZ(capid0_a)) { + case 1: + ddrsz = 8192; + break; + case 2: + ddrsz = 2048; + break; + case 3: + ddrsz = 512; + break; + default: + ddrsz = 16384; + break; + } + + /* Account for the maximum number of DIMMs per channel */ + return (ddrsz / 2) * nb_slots_per_channel(capid0_a); +} + void setup_sdram_meminfo(struct pei_data *pei_data) { u32 addr_decode_ch[2]; @@ -221,4 +261,12 @@ void setup_sdram_meminfo(struct pei_data *pei_data) } } mem_info->dimm_cnt = dimm_cnt; + + const uint32_t capid0_a = pci_read_config32(HOST_BRIDGE, CAPID0_A); + + const uint16_t channels = nb_number_of_channels(capid0_a); + + mem_info->ecc_capable = nb_supports_ecc(capid0_a); + mem_info->max_capacity_mib = channels * nb_max_chan_capacity_mib(capid0_a); + mem_info->number_of_devices = channels * nb_slots_per_channel(capid0_a); } |