haswell: add CBMEM_MEMINFO table when initing RAM
Populate a memory_info struct with PEI and SPD data, in order to inject the CBMEM_INFO table necessary to populate a type17 SMBIOS table. On Broadwell, this is done by the MRC binary, but the older Haswell MRC binary doesn't populate the pei_data struct with all the info needed, so we have to pull it from the SPD. Some values are hardcoded based on platform specifications. Change-Id: Iea837d23f2c9c1c943e0db28cf81b265f054e9d1 Signed-off-by: Matt DeVillier <matt.devillier@gmail.com> Reviewed-on: https://review.coreboot.org/19958 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
parent
f739e7f56a
commit
5aaa8ce21c
|
@ -245,6 +245,8 @@ void romstage_common(const struct romstage_params *params)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setup_sdram_meminfo(params->pei_data);
|
||||||
|
|
||||||
romstage_handoff_init(wake_from_s3);
|
romstage_handoff_init(wake_from_s3);
|
||||||
|
|
||||||
post_code(0x3f);
|
post_code(0x3f);
|
||||||
|
|
|
@ -32,6 +32,19 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <spd.h>
|
#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
|
* \brief Convenience definitions for TCK values
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,9 +21,13 @@
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
#include <halt.h>
|
#include <halt.h>
|
||||||
#include <ip_checksum.h>
|
#include <ip_checksum.h>
|
||||||
|
#include <memory_info.h>
|
||||||
#include <northbridge/intel/common/mrc_cache.h>
|
#include <northbridge/intel/common/mrc_cache.h>
|
||||||
#include <pc80/mc146818rtc.h>
|
#include <pc80/mc146818rtc.h>
|
||||||
#include <device/pci_def.h>
|
#include <device/pci_def.h>
|
||||||
|
#include <device/dram/ddr3.h>
|
||||||
|
#include <smbios.h>
|
||||||
|
#include <spd.h>
|
||||||
#include <vboot/vboot_common.h>
|
#include <vboot/vboot_common.h>
|
||||||
#include "raminit.h"
|
#include "raminit.h"
|
||||||
#include "pei_data.h"
|
#include "pei_data.h"
|
||||||
|
@ -171,3 +175,54 @@ void sdram_initialize(struct pei_data *pei_data)
|
||||||
|
|
||||||
report_memory_config();
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "pei_data.h"
|
#include "pei_data.h"
|
||||||
|
|
||||||
void sdram_initialize(struct pei_data *pei_data);
|
void sdram_initialize(struct pei_data *pei_data);
|
||||||
|
void setup_sdram_meminfo(struct pei_data *pei_data);
|
||||||
int fixup_haswell_errata(void);
|
int fixup_haswell_errata(void);
|
||||||
/* save_mrc_data() must be called after cbmem has been initialized. */
|
/* save_mrc_data() must be called after cbmem has been initialized. */
|
||||||
void save_mrc_data(struct pei_data *pei_data);
|
void save_mrc_data(struct pei_data *pei_data);
|
||||||
|
|
Loading…
Reference in New Issue