diff options
author | Angel Pons <th3fanbus@gmail.com> | 2024-04-12 17:02:24 +0200 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2024-04-18 11:02:46 +0000 |
commit | 7d3e161d70d1265c26baf59546dfcaac4ac2fb4c (patch) | |
tree | f9b70b10b7d54854b3fda35fb7cf75205d068745 /src | |
parent | 57946ad8174a70269f59d2df20a451acdbb1dc38 (diff) |
nb/intel/gm45: Fill in memory info
Fill in memory info so that coreboot can generate SMBIOS Type 17 tables.
The S/N, P/N and module ID fields are only populated for DDR3.
Change-Id: I92060ce05bdf0ca617a3383a2db1fdbd43df6fe4
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/81861
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Jean Lucas
Diffstat (limited to 'src')
-rw-r--r-- | src/northbridge/intel/gm45/Makefile.mk | 1 | ||||
-rw-r--r-- | src/northbridge/intel/gm45/gm45.h | 1 | ||||
-rw-r--r-- | src/northbridge/intel/gm45/raminit_meminfo.c | 85 | ||||
-rw-r--r-- | src/northbridge/intel/gm45/romstage.c | 2 |
4 files changed, 89 insertions, 0 deletions
diff --git a/src/northbridge/intel/gm45/Makefile.mk b/src/northbridge/intel/gm45/Makefile.mk index db9dc3f9ac..a26565ff2f 100644 --- a/src/northbridge/intel/gm45/Makefile.mk +++ b/src/northbridge/intel/gm45/Makefile.mk @@ -10,6 +10,7 @@ romstage-y += raminit.c romstage-y += raminit_rcomp_calibration.c romstage-y += raminit_receive_enable_calibration.c romstage-y += raminit_read_write_training.c +romstage-y += raminit_meminfo.c romstage-y += pcie.c romstage-y += thermal.c romstage-y += igd.c diff --git a/src/northbridge/intel/gm45/gm45.h b/src/northbridge/intel/gm45/gm45.h index d929533d92..5d9ac56606 100644 --- a/src/northbridge/intel/gm45/gm45.h +++ b/src/northbridge/intel/gm45/gm45.h @@ -412,6 +412,7 @@ void enter_raminit_or_reset(void); void get_gmch_info(sysinfo_t *); void raminit(sysinfo_t *, int s3resume); void raminit_thermal(const sysinfo_t *); +void setup_sdram_meminfo(const sysinfo_t *); void init_igd(const sysinfo_t *const); void init_pm(const sysinfo_t *, int do_freq_scaling_cfg); void igd_compute_ggc(sysinfo_t *const sysinfo); diff --git a/src/northbridge/intel/gm45/raminit_meminfo.c b/src/northbridge/intel/gm45/raminit_meminfo.c new file mode 100644 index 0000000000..c2c7f510d8 --- /dev/null +++ b/src/northbridge/intel/gm45/raminit_meminfo.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <cbmem.h> +#include <console/console.h> +#include <device/dram/ddr2.h> +#include <device/dram/ddr3.h> +#include <device/smbus_host.h> +#include <lib.h> +#include <memory_info.h> +#include <spd.h> + +#include "gm45.h" +#include "chip.h" + +static u8 get_dimm_mod_type(const sysinfo_t *sysinfo, const int idx) +{ + if (sysinfo->spd_type == DDR2) { + return smbus_read_byte(sysinfo->spd_map[idx], 20) & SPD_DDR2_DIMM_TYPE_MASK; + } else { + return smbus_read_byte(sysinfo->spd_map[idx], 3) & 0xf; + } +} + +static void ddr3_read_ids(const sysinfo_t *sysinfo, struct dimm_info *dimm, const int idx) +{ + const u8 addr = sysinfo->spd_map[idx]; + for (int k = 0; k < SPD_DIMM_SERIAL_LEN; k++) { + dimm->serial[k] = smbus_read_byte(addr, SPD_DIMM_SERIAL_NUM + k); + } + for (int k = 0; k < SPD_DIMM_PART_LEN; k++) { + dimm->module_part_number[k] = smbus_read_byte(addr, SPD_DIMM_PART_NUM + k); + } + dimm->mod_id = (smbus_read_byte(addr, SPD_DIMM_MOD_ID2) << 8) | + (smbus_read_byte(addr, SPD_DIMM_MOD_ID1) << 0); +} + +static u32 get_mem_clock_mt(const int clock_index) +{ + switch (clock_index) { + case MEM_CLOCK_1067MT: return 1067; + case MEM_CLOCK_800MT: return 800; + case MEM_CLOCK_667MT: return 667; + default: return 0; + } +} + +void setup_sdram_meminfo(const sysinfo_t *sysinfo) +{ + struct memory_info *mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(struct memory_info)); + if (!mem_info) + die("Failed to add memory info to CBMEM.\n"); + + memset(mem_info, 0, sizeof(struct memory_info)); + + const u16 ddr_type = (sysinfo->spd_type == DDR2) ? MEMORY_TYPE_DDR2 : MEMORY_TYPE_DDR3; + const u32 ddr_freq_mt = get_mem_clock_mt(sysinfo->selected_timings.mem_clock); + + int dimm_cnt = 0; + + int ch; + FOR_EACH_POPULATED_CHANNEL(sysinfo->dimms, ch) { + struct dimm_info *dimm = &mem_info->dimm[dimm_cnt]; + const int idx = ch * 2; + const int ranks = sysinfo->dimms[ch].ranks; + dimm->dimm_size = (256 << sysinfo->dimms[ch].chip_capacity) * ranks; + dimm->ddr_type = ddr_type; + dimm->ddr_frequency = ddr_freq_mt; + dimm->rank_per_dimm = ranks; + dimm->channel_num = ch; + dimm->dimm_num = 0; + dimm->bank_locator = ch; + /* TODO: Handle DDR2 SPDs */ + if (sysinfo->spd_type == DDR3) { + ddr3_read_ids(sysinfo, dimm, idx); + } + dimm->mod_type = get_dimm_mod_type(sysinfo, idx); + dimm->bus_width = MEMORY_BUS_WIDTH_64; + dimm_cnt++; + } + mem_info->dimm_cnt = dimm_cnt; + + mem_info->ecc_type = MEMORY_ARRAY_ECC_NONE; + mem_info->max_capacity_mib = 8192; + mem_info->number_of_devices = 2; +} diff --git a/src/northbridge/intel/gm45/romstage.c b/src/northbridge/intel/gm45/romstage.c index 01df965c86..9ed3c00154 100644 --- a/src/northbridge/intel/gm45/romstage.c +++ b/src/northbridge/intel/gm45/romstage.c @@ -91,6 +91,8 @@ void mainboard_romstage_entry(void) cbmem_initted = !cbmem_recovery(s3resume); + setup_sdram_meminfo(&sysinfo); + romstage_handoff_init(cbmem_initted && s3resume); printk(BIOS_SPEW, "exit main()\n"); |