summaryrefslogtreecommitdiff
path: root/resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2023-03-18 00:36:27 +0000
committerLeah Rowe <leah@libreboot.org>2023-03-18 00:55:10 +0000
commit548872ce8e84fe10d52417acab9b3cf886821386 (patch)
treeb549ad51c9c693a323f0f8edc9a11eab92220013 /resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch
parenta942bd6590dd450140fc0af8549ca470a065adf5 (diff)
haswell boards: use libre mrc.bin replacement
courtesy of Angel Pons from the coreboot project this uses the following patch set from gerrit, as yet unmerged (in coreboot master) on this date: https://review.coreboot.org/c/coreboot/+/64198/5 logic for downloading mrc blobs has been deleted from lbmk, as this is now completely obsolete (for haswell boards) if other platforms are added later that need mrc.bin, then logic will be re-added again for that
Diffstat (limited to 'resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch')
-rw-r--r--resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch272
1 files changed, 272 insertions, 0 deletions
diff --git a/resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch b/resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch
new file mode 100644
index 00000000..2e6de17c
--- /dev/null
+++ b/resources/coreboot/haswell/patches/0022-haswell-NRI-Add-function-to-change-margins.patch
@@ -0,0 +1,272 @@
+From 8c3874195c0fc1af9d0b84611496689da1c19d8c Mon Sep 17 00:00:00 2001
+From: Angel Pons <th3fanbus@gmail.com>
+Date: Sun, 8 May 2022 11:58:59 +0200
+Subject: [PATCH 22/26] haswell NRI: Add function to change margins
+
+Implement a function to change margin parameters. Haswell provides a
+register to apply an offset to margin parameters during training, so
+make use of it. There are other margin parameters that have not been
+implemented yet, as they are not needed for now and special handling
+is needed to provide offset training functionality.
+
+Change-Id: I5392380e13de3c44e77b7bc9f3b819e2661d1e2d
+Signed-off-by: Angel Pons <th3fanbus@gmail.com>
+---
+ .../haswell/native_raminit/change_margin.c | 136 ++++++++++++++++++
+ .../haswell/native_raminit/raminit_native.h | 39 +++++
+ .../haswell/native_raminit/reg_structs.h | 12 ++
+ .../intel/haswell/registers/mchbar.h | 1 +
+ 4 files changed, 188 insertions(+)
+
+diff --git a/src/northbridge/intel/haswell/native_raminit/change_margin.c b/src/northbridge/intel/haswell/native_raminit/change_margin.c
+index 12da59580f..4ba9cfa5c6 100644
+--- a/src/northbridge/intel/haswell/native_raminit/change_margin.c
++++ b/src/northbridge/intel/haswell/native_raminit/change_margin.c
+@@ -1,5 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0-or-later */
+
++#include <assert.h>
+ #include <commonlib/clamp.h>
+ #include <console/console.h>
+ #include <delay.h>
+@@ -152,3 +153,138 @@ void download_regfile(
+ ddr_data_control_0.read_rf_rank = phys_rank;
+ mchbar_write32(reg, ddr_data_control_0.raw);
+ }
++
++static void update_data_offset_train(
++ struct sysinfo *ctrl,
++ const uint8_t param,
++ const uint8_t en_multicast,
++ const uint8_t channel_in,
++ const uint8_t rank,
++ const uint8_t byte_in,
++ const bool update_ctrl,
++ const enum regfile_mode regfile,
++ const uint32_t value)
++{
++ bool is_rd = false;
++ bool is_wr = false;
++ switch (param) {
++ case RdT:
++ case RdV:
++ case RcvEna:
++ is_rd = true;
++ break;
++ case WrT:
++ case WrDqsT:
++ is_wr = true;
++ break;
++ default:
++ die("%s: Invalid margin parameter %u\n", __func__, param);
++ }
++ if (en_multicast) {
++ mchbar_write32(DDR_DATA_OFFSET_TRAIN, value);
++ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
++ if (!does_ch_exist(ctrl, channel))
++ continue;
++
++ download_regfile(ctrl, channel, true, rank, regfile, 0, is_rd, is_wr);
++ if (update_ctrl) {
++ for (uint8_t byte = 0; byte < ctrl->lanes; byte++)
++ ctrl->data_offset_train[channel][byte] = value;
++ }
++ }
++ } else {
++ mchbar_write32(DDR_DATA_OFFSET_TRAIN_ch_b(channel_in, byte_in), value);
++ download_regfile(ctrl, channel_in, false, rank, regfile, byte_in, is_rd, is_wr);
++ if (update_ctrl)
++ ctrl->data_offset_train[channel_in][byte_in] = value;
++ }
++}
++
++static uint32_t get_max_margin(const enum margin_parameter param)
++{
++ switch (param) {
++ case RcvEna:
++ case RdT:
++ case WrT:
++ case WrDqsT:
++ return MAX_POSSIBLE_TIME;
++ case RdV:
++ return MAX_POSSIBLE_VREF;
++ default:
++ die("%s: Invalid margin parameter %u\n", __func__, param);
++ }
++}
++
++void change_margin(
++ struct sysinfo *ctrl,
++ const enum margin_parameter param,
++ const int32_t value0,
++ const bool en_multicast,
++ const uint8_t channel,
++ const uint8_t rank,
++ const uint8_t byte,
++ const bool update_ctrl,
++ const enum regfile_mode regfile)
++{
++ /** FIXME: Remove this **/
++ if (rank == 0xff)
++ die("%s: rank is 0xff\n", __func__);
++
++ if (!en_multicast && !does_ch_exist(ctrl, channel))
++ die("%s: Tried to change margin of empty channel %u\n", __func__, channel);
++
++ const uint32_t max_value = get_max_margin(param);
++ const int32_t v0 = clamp_s32(-max_value, value0, max_value);
++
++ union ddr_data_offset_train_reg ddr_data_offset_train = {
++ .raw = en_multicast ? 0 : ctrl->data_offset_train[channel][byte],
++ };
++ bool update_offset_train = false;
++ switch (param) {
++ case RcvEna:
++ ddr_data_offset_train.rcven = v0;
++ update_offset_train = true;
++ break;
++ case RdT:
++ ddr_data_offset_train.rx_dqs = v0;
++ update_offset_train = true;
++ break;
++ case WrT:
++ ddr_data_offset_train.tx_dq = v0;
++ update_offset_train = true;
++ break;
++ case WrDqsT:
++ ddr_data_offset_train.tx_dqs = v0;
++ update_offset_train = true;
++ break;
++ case RdV:
++ ddr_data_offset_train.vref = v0;
++ update_offset_train = true;
++ break;
++ default:
++ die("%s: Invalid margin parameter %u\n", __func__, param);
++ }
++ if (update_offset_train) {
++ update_data_offset_train(
++ ctrl,
++ param,
++ en_multicast,
++ channel,
++ rank,
++ byte,
++ update_ctrl,
++ regfile,
++ ddr_data_offset_train.raw);
++ }
++}
++
++void change_1d_margin_multicast(
++ struct sysinfo *ctrl,
++ const enum margin_parameter param,
++ const int32_t value0,
++ const uint8_t rank,
++ const bool update_ctrl,
++ const enum regfile_mode regfile)
++{
++ change_margin(ctrl, param, value0, true, 0, rank, 0, update_ctrl, regfile);
++}
+diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
+index a36ebfacd1..500fc28909 100644
+--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
++++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
+@@ -35,6 +35,18 @@
+
+ #define RTTNOM_MASK (BIT(9) | BIT(6) | BIT(2))
+
++/* Margin parameter limits */
++#define MAX_POSSIBLE_TIME 31
++#define MAX_POSSIBLE_VREF 54
++
++#define MAX_POSSIBLE_BOTH MAX_POSSIBLE_VREF
++
++#define MIN_TIME (-MAX_POSSIBLE_TIME)
++#define MAX_TIME (MAX_POSSIBLE_TIME)
++
++#define MIN_VREF (-MAX_POSSIBLE_VREF)
++#define MAX_VREF (MAX_POSSIBLE_VREF)
++
+ #define BASIC_VA_PAT_SPREAD_8 0x01010101
+
+ #define WDB_CACHE_LINE_SIZE 8
+@@ -45,6 +57,14 @@
+ /* Specified in PI ticks. 64 PI ticks == 1 qclk */
+ #define tDQSCK_DRIFT 64
+
++enum margin_parameter {
++ RcvEna,
++ RdT,
++ WrT,
++ WrDqsT,
++ RdV,
++};
++
+ /* ZQ calibration types */
+ enum {
+ ZQ_INIT, /* DDR3: ZQCL with tZQinit, LPDDR3: ZQ Init with tZQinit */
+@@ -516,6 +536,25 @@ void download_regfile(
+ bool read_rf_rd,
+ bool read_rf_wr);
+
++void change_margin(
++ struct sysinfo *ctrl,
++ const enum margin_parameter param,
++ const int32_t value0,
++ const bool en_multicast,
++ const uint8_t channel,
++ const uint8_t rank,
++ const uint8_t byte,
++ const bool update_ctrl,
++ const enum regfile_mode regfile);
++
++void change_1d_margin_multicast(
++ struct sysinfo *ctrl,
++ const enum margin_parameter param,
++ const int32_t value0,
++ const uint8_t rank,
++ const bool update_ctrl,
++ const enum regfile_mode regfile);
++
+ uint8_t get_rx_bias(const struct sysinfo *ctrl);
+
+ uint8_t get_tCWL(uint32_t mem_clock_mhz);
+diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
+index b099f4bb82..a0e36ed082 100644
+--- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h
++++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
+@@ -25,6 +25,18 @@ union ddr_data_tx_train_rank_reg {
+ uint32_t raw;
+ };
+
++union ddr_data_offset_train_reg {
++ struct __packed {
++ int32_t rcven : 6; // Bits 5:0
++ int32_t rx_dqs : 6; // Bits 11:6
++ int32_t tx_dq : 6; // Bits 17:12
++ int32_t tx_dqs : 6; // Bits 23:18
++ int32_t vref : 7; // Bits 30:24
++ int32_t : 1; // Bits 31:31
++ };
++ uint32_t raw;
++};
++
+ union ddr_data_control_0_reg {
+ struct __packed {
+ uint32_t rx_training_mode : 1; // Bits 0:0
+diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
+index 9172d4f2b0..0acafbc826 100644
+--- a/src/northbridge/intel/haswell/registers/mchbar.h
++++ b/src/northbridge/intel/haswell/registers/mchbar.h
+@@ -21,6 +21,7 @@
+ #define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte)
+
+ #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte)
++#define DDR_DATA_OFFSET_TRAIN_ch_b(ch, byte) _DDRIO_C_R_B(0x0070, ch, 0, byte)
+ #define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte)
+
+ /* DDR CKE per-channel */
+--
+2.39.2
+