123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- From 54cfbe4cf53d16f747bfcfadd20445a0f5f1e5db Mon Sep 17 00:00:00 2001
- From: Angel Pons <th3fanbus@gmail.com>
- Date: Sun, 8 May 2022 01:11:03 +0200
- Subject: [PATCH 20/26] haswell NRI: Add library to change margins
- Implement a library to change Rx/Tx margins. It will be expanded later.
- Change-Id: I0b55aba428d8b4d4e16d2fbdec57235ce3ce8adf
- Signed-off-by: Angel Pons <th3fanbus@gmail.com>
- ---
- .../intel/haswell/native_raminit/Makefile.inc | 1 +
- .../haswell/native_raminit/change_margin.c | 154 ++++++++++++++++++
- .../haswell/native_raminit/raminit_native.h | 50 ++++++
- .../intel/haswell/registers/mchbar.h | 9 +
- 4 files changed, 214 insertions(+)
- create mode 100644 src/northbridge/intel/haswell/native_raminit/change_margin.c
- diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- index 2da950771d..ebe9e9b762 100644
- --- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- +++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- @@ -1,5 +1,6 @@
- ## SPDX-License-Identifier: GPL-2.0-or-later
-
- +romstage-y += change_margin.c
- romstage-y += configure_mc.c
- romstage-y += ddr3.c
- romstage-y += jedec_reset.c
- diff --git a/src/northbridge/intel/haswell/native_raminit/change_margin.c b/src/northbridge/intel/haswell/native_raminit/change_margin.c
- new file mode 100644
- index 0000000000..12da59580f
- --- /dev/null
- +++ b/src/northbridge/intel/haswell/native_raminit/change_margin.c
- @@ -0,0 +1,154 @@
- +/* SPDX-License-Identifier: GPL-2.0-or-later */
- +
- +#include <commonlib/clamp.h>
- +#include <console/console.h>
- +#include <delay.h>
- +#include <northbridge/intel/haswell/haswell.h>
- +#include <timer.h>
- +
- +#include "raminit_native.h"
- +
- +void update_rxt(
- + struct sysinfo *ctrl,
- + const uint8_t channel,
- + const uint8_t rank,
- + const uint8_t byte,
- + const enum rxt_subfield subfield,
- + const int32_t value)
- +{
- + union ddr_data_rx_train_rank_reg rxt = {
- + .rcven = ctrl->rcven[channel][rank][byte],
- + .dqs_p = ctrl->rxdqsp[channel][rank][byte],
- + .rx_eq = ctrl->rx_eq[channel][rank][byte],
- + .dqs_n = ctrl->rxdqsn[channel][rank][byte],
- + .vref = ctrl->rxvref[channel][rank][byte],
- + };
- + int32_t new_value;
- + switch (subfield) {
- + case RXT_RCVEN:
- + new_value = clamp_s32(0, value, 511);
- + rxt.rcven = new_value;
- + break;
- + case RXT_RXDQS_P:
- + new_value = clamp_s32(0, value, 63);
- + rxt.dqs_p = new_value;
- + break;
- + case RXT_RX_EQ:
- + new_value = clamp_s32(0, value, 31);
- + rxt.rx_eq = new_value;
- + break;
- + case RXT_RXDQS_N:
- + new_value = clamp_s32(0, value, 63);
- + rxt.dqs_n = new_value;
- + break;
- + case RXT_RX_VREF:
- + new_value = clamp_s32(-32, value, 31);
- + rxt.vref = new_value;
- + break;
- + case RXT_RXDQS_BOTH:
- + new_value = clamp_s32(0, value, 63);
- + rxt.dqs_p = new_value;
- + rxt.dqs_n = new_value;
- + break;
- + case RXT_RESTORE:
- + new_value = value;
- + break;
- + default:
- + die("%s: Unhandled subfield index %u\n", __func__, subfield);
- + }
- +
- + if (new_value != value) {
- + printk(BIOS_ERR, "%s: Overflow for subfield %u: %d ---> %d\n",
- + __func__, subfield, value, new_value);
- + }
- + mchbar_write32(RX_TRAIN_ch_r_b(channel, rank, byte), rxt.raw);
- + download_regfile(ctrl, channel, false, rank, REG_FILE_USE_RANK, byte, true, false);
- +}
- +
- +void update_txt(
- + struct sysinfo *ctrl,
- + const uint8_t channel,
- + const uint8_t rank,
- + const uint8_t byte,
- + const enum txt_subfield subfield,
- + const int32_t value)
- +{
- + union ddr_data_tx_train_rank_reg txt = {
- + .dq_delay = ctrl->tx_dq[channel][rank][byte],
- + .dqs_delay = ctrl->txdqs[channel][rank][byte],
- + .tx_eq = ctrl->tx_eq[channel][rank][byte],
- + };
- + int32_t new_value;
- + switch (subfield) {
- + case TXT_TX_DQ:
- + new_value = clamp_s32(0, value, 511);
- + txt.dq_delay = new_value;
- + break;
- + case TXT_TXDQS:
- + new_value = clamp_s32(0, value, 511);
- + txt.dqs_delay = new_value;
- + break;
- + case TXT_TX_EQ:
- + new_value = clamp_s32(0, value, 63);
- + txt.tx_eq = new_value;
- + break;
- + case TXT_DQDQS_OFF:
- + new_value = value;
- + txt.dqs_delay += new_value;
- + txt.dq_delay += new_value;
- + break;
- + case TXT_RESTORE:
- + new_value = value;
- + break;
- + default:
- + die("%s: Unhandled subfield index %u\n", __func__, subfield);
- + }
- + if (new_value != value) {
- + printk(BIOS_ERR, "%s: Overflow for subfield %u: %d ---> %d\n",
- + __func__, subfield, value, new_value);
- + }
- + mchbar_write32(TX_TRAIN_ch_r_b(channel, rank, byte), txt.raw);
- + download_regfile(ctrl, channel, false, rank, REG_FILE_USE_RANK, byte, false, true);
- +}
- +
- +void download_regfile(
- + struct sysinfo *ctrl,
- + const uint8_t channel,
- + const bool multicast,
- + const uint8_t rank,
- + const enum regfile_mode regfile,
- + const uint8_t byte,
- + const bool read_rf_rd,
- + const bool read_rf_wr)
- +{
- + union reut_seq_base_addr_reg reut_seq_base_addr;
- + switch (regfile) {
- + case REG_FILE_USE_START:
- + reut_seq_base_addr.raw = mchbar_read64(REUT_ch_SEQ_ADDR_START(channel));
- + break;
- + case REG_FILE_USE_CURRENT:
- + reut_seq_base_addr.raw = mchbar_read64(REUT_ch_SEQ_ADDR_CURRENT(channel));
- + break;
- + case REG_FILE_USE_RANK:
- + reut_seq_base_addr.raw = 0;
- + if (rank >= NUM_SLOTRANKS)
- + die("%s: bad rank %u\n", __func__, rank);
- + break;
- + default:
- + die("%s: Invalid regfile param %u\n", __func__, regfile);
- + }
- + uint8_t phys_rank = rank;
- + if (reut_seq_base_addr.raw != 0) {
- + /* Map REUT logical rank to physical rank */
- + const uint32_t log_to_phys = mchbar_read32(REUT_ch_RANK_LOG_TO_PHYS(channel));
- + phys_rank = log_to_phys >> (reut_seq_base_addr.rank_addr * 4) & 0x3;
- + }
- + uint32_t reg = multicast ? DDR_DATA_ch_CONTROL_0(channel) : DQ_CONTROL_0(channel, byte);
- + union ddr_data_control_0_reg ddr_data_control_0 = {
- + .raw = mchbar_read32(reg),
- + };
- + ddr_data_control_0.read_rf_rd = read_rf_rd;
- + ddr_data_control_0.read_rf_wr = read_rf_wr;
- + ddr_data_control_0.read_rf_rank = phys_rank;
- + mchbar_write32(reg, ddr_data_control_0.raw);
- +}
- diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- index 56df36ca8d..7c1a786780 100644
- --- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- +++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- @@ -117,6 +117,30 @@ enum test_stop {
- ALSOE = 3, /* Stop on all lanes error */
- };
-
- +enum rxt_subfield {
- + RXT_RCVEN = 0,
- + RXT_RXDQS_P = 1,
- + RXT_RX_EQ = 2,
- + RXT_RXDQS_N = 3,
- + RXT_RX_VREF = 4,
- + RXT_RXDQS_BOTH = 5,
- + RXT_RESTORE = 255,
- +};
- +
- +enum txt_subfield {
- + TXT_TX_DQ = 0,
- + TXT_TXDQS = 1,
- + TXT_TX_EQ = 2,
- + TXT_DQDQS_OFF = 3,
- + TXT_RESTORE = 255,
- +};
- +
- +enum regfile_mode {
- + REG_FILE_USE_RANK, /* Used when changing parameters for each rank */
- + REG_FILE_USE_START, /* Used when changing parameters before the test */
- + REG_FILE_USE_CURRENT, /* Used when changing parameters after the test */
- +};
- +
- struct wdb_pat {
- uint32_t start_ptr; /* Starting pointer in WDB */
- uint32_t stop_ptr; /* Stopping pointer in WDB */
- @@ -452,6 +476,32 @@ uint8_t select_reut_ranks(struct sysinfo *ctrl, uint8_t channel, uint8_t rankmas
- void run_mpr_io_test(bool clear_errors);
- uint8_t run_io_test(struct sysinfo *ctrl, uint8_t chanmask, uint8_t dq_pat, bool clear_errors);
-
- +void update_rxt(
- + struct sysinfo *ctrl,
- + uint8_t channel,
- + uint8_t rank,
- + uint8_t byte,
- + enum rxt_subfield subfield,
- + int32_t value);
- +
- +void update_txt(
- + struct sysinfo *ctrl,
- + uint8_t channel,
- + uint8_t rank,
- + uint8_t byte,
- + enum txt_subfield subfield,
- + int32_t value);
- +
- +void download_regfile(
- + struct sysinfo *ctrl,
- + uint8_t channel,
- + bool multicast,
- + uint8_t rank,
- + enum regfile_mode regfile,
- + uint8_t byte,
- + bool read_rf_rd,
- + bool read_rf_wr);
- +
- 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/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
- index 817a9f8bf8..a81559bb1e 100644
- --- a/src/northbridge/intel/haswell/registers/mchbar.h
- +++ b/src/northbridge/intel/haswell/registers/mchbar.h
- @@ -15,7 +15,11 @@
- /* Register definitions */
-
- /* DDR DATA per-channel per-bytelane */
- +#define RX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0000, ch, rank, byte)
- +#define TX_TRAIN_ch_r_b(ch, rank, byte) _DDRIO_C_R_B(0x0020, ch, rank, byte)
- +
- #define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte)
- +#define DQ_CONTROL_0(ch, byte) _DDRIO_C_R_B(0x0074, ch, 0, byte)
-
- /* DDR CKE per-channel */
- #define DDR_CKE_ch_CMD_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1204, ch, 0, 0)
- @@ -38,6 +42,9 @@
- #define DDR_SCRAMBLE_ch(ch) (0x2000 + 4 * (ch))
- #define DDR_SCRAM_MISC_CONTROL 0x2008
-
- +/* DDR DATA per-channel multicast */
- +#define DDR_DATA_ch_CONTROL_0(ch) _DDRIO_C_R_B(0x3074, ch, 0, 0)
- +
- /* DDR CMDN/CMDS per-channel (writes go to both CMDN and CMDS fubs) */
- #define DDR_CMD_ch_COMP_OFFSET(ch) _DDRIO_C_R_B(0x3204, ch, 0, 0)
- #define DDR_CMD_ch_PI_CODING(ch) _DDRIO_C_R_B(0x3208, ch, 0, 0)
- @@ -147,6 +154,8 @@
-
- #define REUT_ch_SEQ_ADDR_WRAP(ch) (0x48e8 + 8 * (ch))
-
- +#define REUT_ch_SEQ_ADDR_CURRENT(ch) (0x48f8 + 8 * (ch))
- +
- #define REUT_ch_SEQ_MISC_CTL(ch) (0x4908 + 4 * (ch))
-
- #define REUT_ch_SEQ_ADDR_INC_CTL(ch) (0x4910 + 8 * (ch))
- --
- 2.39.2
|