summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/intel/haswell/romstage.c2
-rw-r--r--src/include/device/dram/ddr3.h13
-rw-r--r--src/northbridge/intel/haswell/raminit.c55
-rw-r--r--src/northbridge/intel/haswell/raminit.h1
4 files changed, 71 insertions, 0 deletions
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index c6765c757c..ac45ee62ad 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -245,6 +245,8 @@ void romstage_common(const struct romstage_params *params)
#endif
}
+ setup_sdram_meminfo(params->pei_data);
+
romstage_handoff_init(wake_from_s3);
post_code(0x3f);
diff --git a/src/include/device/dram/ddr3.h b/src/include/device/dram/ddr3.h
index 9597a3140b..5961f4106b 100644
--- a/src/include/device/dram/ddr3.h
+++ b/src/include/device/dram/ddr3.h
@@ -33,6 +33,19 @@
#include <spd.h>
/**
+ * Convenience definitions for SPD offsets
+ *
+ * @{
+ */
+#define SPD_DIMM_MOD_ID1 117
+#define SPD_DIMM_MOD_ID2 118
+#define SPD_DIMM_SERIAL_NUM 122
+#define SPD_DIMM_SERIAL_LEN 4
+#define SPD_DIMM_PART_NUM 128
+#define SPD_DIMM_PART_LEN 18
+/** @} */
+
+/**
* \brief Convenience definitions for TCK values
*
* Different values for tCK, representing standard DDR3 frequencies.
diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c
index 469c4f2fa0..50443aa94c 100644
--- a/src/northbridge/intel/haswell/raminit.c
+++ b/src/northbridge/intel/haswell/raminit.c
@@ -21,9 +21,13 @@
#include <cbfs.h>
#include <halt.h>
#include <ip_checksum.h>
+#include <memory_info.h>
#include <northbridge/intel/common/mrc_cache.h>
#include <pc80/mc146818rtc.h>
#include <device/pci_def.h>
+#include <device/dram/ddr3.h>
+#include <smbios.h>
+#include <spd.h>
#include <vboot/vboot_common.h>
#include "raminit.h"
#include "pei_data.h"
@@ -171,3 +175,54 @@ void sdram_initialize(struct pei_data *pei_data)
report_memory_config();
}
+
+void setup_sdram_meminfo(struct pei_data *pei_data)
+{
+ u32 addr_decoder_common, addr_decode_ch[2];
+ struct memory_info* mem_info;
+ struct dimm_info *dimm;
+ int ddr_frequency;
+ int dimm_size;
+ int ch, d_num;
+ int dimm_cnt = 0;
+
+ mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info));
+ memset(mem_info, 0, sizeof(struct memory_info));
+
+ addr_decoder_common = MCHBAR32(0x5000);
+ addr_decode_ch[0] = MCHBAR32(0x5004);
+ addr_decode_ch[1] = MCHBAR32(0x5008);
+
+ ddr_frequency = (MCHBAR32(0x5e04) * 13333 * 2 + 50) / 100;
+
+ for (ch = 0; ch < ARRAY_SIZE(addr_decode_ch); ch++) {
+ u32 ch_conf = addr_decode_ch[ch];
+ /* DIMMs A/B */
+ for (d_num = 0; d_num < 2; d_num++) {
+ dimm_size = ((ch_conf >> (d_num * 8)) & 0xff) * 256;
+ if (dimm_size) {
+ dimm = &mem_info->dimm[dimm_cnt];
+ dimm->dimm_size = dimm_size;
+ dimm->ddr_type = MEMORY_TYPE_DDR3;
+ dimm->ddr_frequency = ddr_frequency;
+ dimm->rank_per_dimm = 1 + ((ch_conf >> (17 + d_num)) & 1);
+ dimm->channel_num = ch;
+ dimm->dimm_num = d_num;
+ dimm->bank_locator = ch * 2;
+ memcpy(dimm->serial,
+ &pei_data->spd_data[dimm_cnt][SPD_DIMM_SERIAL_NUM],
+ SPD_DIMM_SERIAL_LEN);
+ memcpy(dimm->module_part_number,
+ &pei_data->spd_data[dimm_cnt][SPD_DIMM_PART_NUM],
+ SPD_DIMM_PART_LEN);
+ dimm->mod_id =
+ (pei_data->spd_data[dimm_cnt][SPD_DIMM_MOD_ID2] << 8) |
+ (pei_data->spd_data[dimm_cnt][SPD_DIMM_MOD_ID1] & 0xFF);
+ dimm->mod_type = SPD_SODIMM;
+ dimm->bus_width = 0x3; /* 64-bit */
+ dimm_cnt++;
+ }
+ }
+ }
+ mem_info->dimm_cnt = dimm_cnt;
+}
diff --git a/src/northbridge/intel/haswell/raminit.h b/src/northbridge/intel/haswell/raminit.h
index d02b72dac2..b42fcf87d6 100644
--- a/src/northbridge/intel/haswell/raminit.h
+++ b/src/northbridge/intel/haswell/raminit.h
@@ -19,6 +19,7 @@
#include "pei_data.h"
void sdram_initialize(struct pei_data *pei_data);
+void setup_sdram_meminfo(struct pei_data *pei_data);
int fixup_haswell_errata(void);
/* save_mrc_data() must be called after cbmem has been initialized. */
void save_mrc_data(struct pei_data *pei_data);