summaryrefslogtreecommitdiff
path: root/config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch
diff options
context:
space:
mode:
Diffstat (limited to 'config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch')
-rw-r--r--config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch344
1 files changed, 0 insertions, 344 deletions
diff --git a/config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch b/config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch
deleted file mode 100644
index 4c2a2670..00000000
--- a/config/coreboot/haswell/patches/0010-haswell-NRI-Collect-SPD-info.patch
+++ /dev/null
@@ -1,344 +0,0 @@
-From 354969af4361bcc7dc240ef5871d169728f7f0cc Mon Sep 17 00:00:00 2001
-From: Angel Pons <th3fanbus@gmail.com>
-Date: Sat, 7 May 2022 13:48:53 +0200
-Subject: [PATCH 10/26] haswell NRI: Collect SPD info
-
-Collect SPD data from DIMMs and memory-down, and find the common
-supported settings.
-
-Change-Id: I4e6a1408a638a463ecae37a447cfed1d6556e44a
-Signed-off-by: Angel Pons <th3fanbus@gmail.com>
----
- .../intel/haswell/native_raminit/Makefile.inc | 1 +
- .../haswell/native_raminit/raminit_main.c | 1 +
- .../haswell/native_raminit/raminit_native.h | 57 +++++
- .../haswell/native_raminit/spd_bitmunching.c | 206 ++++++++++++++++++
- 4 files changed, 265 insertions(+)
- create mode 100644 src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c
-
-diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
-index 90af951c5a..ebf7abc6ec 100644
---- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc
-+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
-@@ -2,3 +2,4 @@
-
- romstage-y += raminit_main.c
- romstage-y += raminit_native.c
-+romstage-y += spd_bitmunching.c
-diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
-index 9b42c25b40..2d2cfa48bb 100644
---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c
-+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
-@@ -20,6 +20,7 @@ struct task_entry {
- };
-
- static const struct task_entry cold_boot[] = {
-+ { collect_spd_info, true, "PROCSPD", },
- };
-
- /* Return a generic stepping value to make stepping checks simpler */
-diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
-index 885f0184f4..1a0793947e 100644
---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
-+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
-@@ -3,6 +3,15 @@
- #ifndef HASWELL_RAMINIT_NATIVE_H
- #define HASWELL_RAMINIT_NATIVE_H
-
-+#include <device/dram/ddr3.h>
-+#include <northbridge/intel/haswell/haswell.h>
-+
-+#define SPD_LEN 256
-+
-+/* 8 data lanes + 1 ECC lane */
-+#define NUM_LANES 9
-+#define NUM_LANES_NO_ECC 8
-+
- enum raminit_boot_mode {
- BOOTMODE_COLD,
- BOOTMODE_WARM,
-@@ -12,6 +21,8 @@ enum raminit_boot_mode {
-
- enum raminit_status {
- RAMINIT_STATUS_SUCCESS = 0,
-+ RAMINIT_STATUS_NO_MEMORY_INSTALLED,
-+ RAMINIT_STATUS_UNSUPPORTED_MEMORY,
- RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/
- };
-
-@@ -21,14 +32,60 @@ enum generic_stepping {
- STEPPING_C0 = 3,
- };
-
-+struct raminit_dimm_info {
-+ spd_raw_data raw_spd;
-+ struct dimm_attr_ddr3_st data;
-+ uint8_t spd_addr;
-+ bool valid;
-+};
-+
- struct sysinfo {
- enum raminit_boot_mode bootmode;
- enum generic_stepping stepping;
- uint32_t cpu; /* CPUID value */
-
- bool dq_pins_interleaved;
-+
-+ /** TODO: ECC support untested **/
-+ bool is_ecc;
-+
-+ /**
-+ * FIXME: LPDDR support is incomplete. The largest chunks are missing,
-+ * but some LPDDR-specific variations in algorithms have been handled.
-+ * LPDDR-specific functions have stubs which will halt upon execution.
-+ */
-+ bool lpddr;
-+
-+ struct raminit_dimm_info dimms[NUM_CHANNELS][NUM_SLOTS];
-+ union dimm_flags_ddr3_st flags;
-+ uint16_t cas_supported;
-+
-+ /* Except for tCK, everything is eventually stored in DCLKs */
-+ uint32_t tCK;
-+ uint32_t tAA; /* Also known as tCL */
-+ uint32_t tWR;
-+ uint32_t tRCD;
-+ uint32_t tRRD;
-+ uint32_t tRP;
-+ uint32_t tRAS;
-+ uint32_t tRC;
-+ uint32_t tRFC;
-+ uint32_t tWTR;
-+ uint32_t tRTP;
-+ uint32_t tFAW;
-+ uint32_t tCWL;
-+ uint32_t tCMD;
-+
-+ uint8_t lanes; /* 8 or 9 */
-+ uint8_t chanmap;
-+ uint8_t dpc[NUM_CHANNELS]; /* DIMMs per channel */
-+ uint8_t rankmap[NUM_CHANNELS];
-+ uint8_t rank_mirrored[NUM_CHANNELS];
-+ uint32_t channel_size_mb[NUM_CHANNELS];
- };
-
- void raminit_main(enum raminit_boot_mode bootmode);
-
-+enum raminit_status collect_spd_info(struct sysinfo *ctrl);
-+
- #endif
-diff --git a/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c b/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c
-new file mode 100644
-index 0000000000..dbe02c72d0
---- /dev/null
-+++ b/src/northbridge/intel/haswell/native_raminit/spd_bitmunching.c
-@@ -0,0 +1,206 @@
-+/* SPDX-License-Identifier: GPL-2.0-or-later */
-+
-+#include <cbfs.h>
-+#include <commonlib/clamp.h>
-+#include <console/console.h>
-+#include <device/dram/ddr3.h>
-+#include <device/smbus_host.h>
-+#include <northbridge/intel/haswell/haswell.h>
-+#include <northbridge/intel/haswell/raminit.h>
-+#include <string.h>
-+#include <types.h>
-+
-+#include "raminit_native.h"
-+
-+static const uint8_t *get_spd_data_from_cbfs(struct spd_info *spdi)
-+{
-+ if (!CONFIG(HAVE_SPD_IN_CBFS))
-+ return NULL;
-+
-+ printk(RAM_DEBUG, "SPD index %u\n", spdi->spd_index);
-+
-+ size_t spd_file_len;
-+ uint8_t *spd_file = cbfs_map("spd.bin", &spd_file_len);
-+
-+ if (!spd_file) {
-+ printk(BIOS_ERR, "SPD data not found in CBFS\n");
-+ return NULL;
-+ }
-+
-+ if (spd_file_len < ((spdi->spd_index + 1) * SPD_LEN)) {
-+ printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n");
-+ spdi->spd_index = 0;
-+ }
-+
-+ if (spd_file_len < SPD_LEN) {
-+ printk(BIOS_ERR, "Invalid SPD data in CBFS\n");
-+ return NULL;
-+ }
-+
-+ return spd_file + (spdi->spd_index * SPD_LEN);
-+}
-+
-+static void get_spd_for_dimm(struct raminit_dimm_info *const dimm, const uint8_t *cbfs_spd)
-+{
-+ if (dimm->spd_addr == SPD_MEMORY_DOWN) {
-+ if (cbfs_spd) {
-+ memcpy(dimm->raw_spd, cbfs_spd, SPD_LEN);
-+ dimm->valid = true;
-+ printk(RAM_DEBUG, "memory-down\n");
-+ return;
-+ } else {
-+ printk(RAM_DEBUG, "memory-down but no CBFS SPD data, ignoring\n");
-+ return;
-+ }
-+ }
-+ printk(RAM_DEBUG, "slotted ");
-+ const uint8_t spd_mem_type = smbus_read_byte(dimm->spd_addr, SPD_MEMORY_TYPE);
-+ if (spd_mem_type != SPD_MEMORY_TYPE_SDRAM_DDR3) {
-+ printk(RAM_DEBUG, "and not DDR3, ignoring\n");
-+ return;
-+ }
-+ printk(RAM_DEBUG, "and DDR3\n");
-+ if (i2c_eeprom_read(dimm->spd_addr, 0, SPD_LEN, dimm->raw_spd) != SPD_LEN) {
-+ printk(BIOS_WARNING, "I2C block read failed, trying SMBus byte reads\n");
-+ for (uint32_t i = 0; i < SPD_LEN; i++)
-+ dimm->raw_spd[i] = smbus_read_byte(dimm->spd_addr, i);
-+ }
-+ dimm->valid = true;
-+}
-+
-+static void get_spd_data(struct sysinfo *ctrl)
-+{
-+ struct spd_info spdi = {0};
-+ mb_get_spd_map(&spdi);
-+ const uint8_t *cbfs_spd = get_spd_data_from_cbfs(&spdi);
-+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
-+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
-+ struct raminit_dimm_info *const dimm = &ctrl->dimms[channel][slot];
-+ dimm->spd_addr = spdi.addresses[channel + channel + slot];
-+ if (!dimm->spd_addr)
-+ continue;
-+
-+ printk(RAM_DEBUG, "CH%uS%u is ", channel, slot);
-+ get_spd_for_dimm(dimm, cbfs_spd);
-+ }
-+ }
-+}
-+
-+static void decode_spd(struct raminit_dimm_info *const dimm)
-+{
-+ /** TODO: Hook up somewhere, and handle lack of XMP data **/
-+ const bool enable_xmp = false;
-+ memset(&dimm->data, 0, sizeof(dimm->data));
-+ if (enable_xmp)
-+ spd_xmp_decode_ddr3(&dimm->data, dimm->raw_spd, DDR3_XMP_PROFILE_1);
-+ else
-+ spd_decode_ddr3(&dimm->data, dimm->raw_spd);
-+
-+ if (CONFIG(DEBUG_RAM_SETUP))
-+ dram_print_spd_ddr3(&dimm->data);
-+}
-+
-+static enum raminit_status find_common_spd_parameters(struct sysinfo *ctrl)
-+{
-+ ctrl->cas_supported = 0xffff;
-+ ctrl->flags.raw = 0xffffffff;
-+
-+ ctrl->tCK = 0;
-+ ctrl->tAA = 0;
-+ ctrl->tWR = 0;
-+ ctrl->tRCD = 0;
-+ ctrl->tRRD = 0;
-+ ctrl->tRP = 0;
-+ ctrl->tRAS = 0;
-+ ctrl->tRC = 0;
-+ ctrl->tRFC = 0;
-+ ctrl->tWTR = 0;
-+ ctrl->tRTP = 0;
-+ ctrl->tFAW = 0;
-+ ctrl->tCWL = 0;
-+ ctrl->tCMD = 0;
-+ ctrl->chanmap = 0;
-+
-+ bool yes_ecc = false;
-+ bool not_ecc = false;
-+
-+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
-+ ctrl->dpc[channel] = 0;
-+ ctrl->rankmap[channel] = 0;
-+ ctrl->rank_mirrored[channel] = 0;
-+ ctrl->channel_size_mb[channel] = 0;
-+ for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
-+ struct raminit_dimm_info *const dimm = &ctrl->dimms[channel][slot];
-+ if (!dimm->valid)
-+ continue;
-+
-+ printk(RAM_DEBUG, "\nCH%uS%u SPD:\n", channel, slot);
-+ decode_spd(dimm);
-+
-+ ctrl->chanmap |= BIT(channel);
-+ ctrl->dpc[channel]++;
-+ ctrl->channel_size_mb[channel] += dimm->data.size_mb;
-+
-+ /* The first rank of a populated slot is always present */
-+ const uint8_t rank = slot + slot;
-+ assert(dimm->data.ranks);
-+ ctrl->rankmap[channel] |= (BIT(dimm->data.ranks) - 1) << rank;
-+
-+ if (dimm->data.flags.pins_mirrored)
-+ ctrl->rank_mirrored[channel] |= BIT(rank + 1);
-+
-+ /* Find common settings */
-+ ctrl->cas_supported &= dimm->data.cas_supported;
-+ ctrl->flags.raw &= dimm->data.flags.raw;
-+ ctrl->tCK = MAX(ctrl->tCK, dimm->data.tCK);
-+ ctrl->tAA = MAX(ctrl->tAA, dimm->data.tAA);
-+ ctrl->tWR = MAX(ctrl->tWR, dimm->data.tWR);
-+ ctrl->tRCD = MAX(ctrl->tRCD, dimm->data.tRCD);
-+ ctrl->tRRD = MAX(ctrl->tRRD, dimm->data.tRRD);
-+ ctrl->tRP = MAX(ctrl->tRP, dimm->data.tRP);
-+ ctrl->tRAS = MAX(ctrl->tRAS, dimm->data.tRAS);
-+ ctrl->tRC = MAX(ctrl->tRC, dimm->data.tRC);
-+ ctrl->tRFC = MAX(ctrl->tRFC, dimm->data.tRFC);
-+ ctrl->tWTR = MAX(ctrl->tWTR, dimm->data.tWTR);
-+ ctrl->tRTP = MAX(ctrl->tRTP, dimm->data.tRTP);
-+ ctrl->tFAW = MAX(ctrl->tFAW, dimm->data.tFAW);
-+ ctrl->tCWL = MAX(ctrl->tCWL, dimm->data.tCWL);
-+ ctrl->tCMD = MAX(ctrl->tCMD, dimm->data.tCMD);
-+
-+ yes_ecc |= dimm->data.flags.is_ecc;
-+ not_ecc |= !dimm->data.flags.is_ecc;
-+ }
-+ }
-+
-+ if (!ctrl->chanmap) {
-+ printk(BIOS_ERR, "No DIMMs were found\n");
-+ return RAMINIT_STATUS_NO_MEMORY_INSTALLED;
-+ }
-+ if (!ctrl->cas_supported) {
-+ printk(BIOS_ERR, "Could not resolve common CAS latency\n");
-+ return RAMINIT_STATUS_UNSUPPORTED_MEMORY;
-+ }
-+ /** TODO: Properly handle ECC support and ECC forced **/
-+ if (yes_ecc && not_ecc) {
-+ /** TODO: Test if the ECC DIMMs can be operated as non-ECC DIMMs **/
-+ printk(BIOS_ERR, "Both ECC and non-ECC DIMMs present, this is unsupported\n");
-+ return RAMINIT_STATUS_UNSUPPORTED_MEMORY;
-+ }
-+ if (yes_ecc)
-+ ctrl->lanes = NUM_LANES;
-+ else
-+ ctrl->lanes = NUM_LANES_NO_ECC;
-+
-+ ctrl->is_ecc = yes_ecc;
-+
-+ /** TODO: Complete LPDDR support **/
-+ ctrl->lpddr = false;
-+
-+ return RAMINIT_STATUS_SUCCESS;
-+}
-+
-+enum raminit_status collect_spd_info(struct sysinfo *ctrl)
-+{
-+ get_spd_data(ctrl);
-+ return find_common_spd_parameters(ctrl);
-+}
---
-2.39.2
-