diff options
Diffstat (limited to 'src/northbridge/intel/haswell')
-rw-r--r-- | src/northbridge/intel/haswell/hostbridge_regs.h | 4 | ||||
-rw-r--r-- | src/northbridge/intel/haswell/raminit.c | 48 |
2 files changed, 52 insertions, 0 deletions
diff --git a/src/northbridge/intel/haswell/hostbridge_regs.h b/src/northbridge/intel/haswell/hostbridge_regs.h index f5fa54aef7..70e15b74e2 100644 --- a/src/northbridge/intel/haswell/hostbridge_regs.h +++ b/src/northbridge/intel/haswell/hostbridge_regs.h @@ -60,7 +60,11 @@ #define SKPAD 0xdc /* Scratchpad Data */ #define CAPID0_A 0xe4 +#define CAPID_ECCDIS (1 << 25) #define VTD_DISABLE (1 << 23) +#define CAPID_DDPCD (1 << 14) +#define CAPID_PDCD (1 << 12) +#define CAPID_DDRSZ(x) (((x) >> 19) & 0x3) #define CAPID0_B 0xe8 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); } |