lbmk/config/coreboot/haswell/patches/0015-haswell-NRI-Add-final-...

571 lines
20 KiB
Diff

From eba8680d618db95028e3f984f25881df0e67abf7 Mon Sep 17 00:00:00 2001
From: Angel Pons <th3fanbus@gmail.com>
Date: Sun, 8 May 2022 14:29:05 +0200
Subject: [PATCH 15/20] haswell NRI: Add final raminit steps
Implement the remaining raminit steps. Although many training steps are
missing, this is enough to boot on the Asrock B85M Pro4.
Change-Id: I94f3b65f0218d4da4fda4d84592dfd91f77f8f21
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
---
src/northbridge/intel/haswell/Kconfig | 4 +-
.../intel/haswell/native_raminit/Makefile.mk | 1 +
.../haswell/native_raminit/activate_mc.c | 388 ++++++++++++++++++
.../haswell/native_raminit/raminit_main.c | 5 +-
.../haswell/native_raminit/raminit_native.c | 5 +-
.../haswell/native_raminit/raminit_native.h | 2 +
.../haswell/native_raminit/reg_structs.h | 12 +
.../intel/haswell/registers/mchbar.h | 7 +
8 files changed, 416 insertions(+), 8 deletions(-)
create mode 100644 src/northbridge/intel/haswell/native_raminit/activate_mc.c
diff --git a/src/northbridge/intel/haswell/Kconfig b/src/northbridge/intel/haswell/Kconfig
index 4b83a25bc1..c6ab27184e 100644
--- a/src/northbridge/intel/haswell/Kconfig
+++ b/src/northbridge/intel/haswell/Kconfig
@@ -11,12 +11,12 @@ config NORTHBRIDGE_INTEL_HASWELL
if NORTHBRIDGE_INTEL_HASWELL
config USE_NATIVE_RAMINIT
- bool "[NOT WORKING] Use native raminit"
+ bool "[NOT COMPLETE] Use native raminit"
default n
select HAVE_DEBUG_RAM_SETUP
help
Select if you want to use coreboot implementation of raminit rather than
- MRC.bin. Currently incomplete and does not boot.
+ MRC.bin. Currently incomplete and does not support S3 resume.
config HASWELL_VBOOT_IN_BOOTBLOCK
depends on VBOOT
diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk
index 40c2f5e014..d97da72890 100644
--- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk
+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk
@@ -1,5 +1,6 @@
## SPDX-License-Identifier: GPL-2.0-or-later
+romstage-y += activate_mc.c
romstage-y += change_margin.c
romstage-y += configure_mc.c
romstage-y += ddr3.c
diff --git a/src/northbridge/intel/haswell/native_raminit/activate_mc.c b/src/northbridge/intel/haswell/native_raminit/activate_mc.c
new file mode 100644
index 0000000000..78a7ad27ef
--- /dev/null
+++ b/src/northbridge/intel/haswell/native_raminit/activate_mc.c
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/pci_ops.h>
+#include <northbridge/intel/haswell/haswell.h>
+#include <timer.h>
+#include <types.h>
+
+#include "raminit_native.h"
+
+static void update_internal_clocks_on(struct sysinfo *ctrl)
+{
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ bool clocks_on = false;
+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
+ const union ddr_data_control_1_reg data_control_1 = {
+ .raw = ctrl->dq_control_1[channel][byte],
+ };
+ const int8_t o_on = data_control_1.odt_delay;
+ const int8_t s_on = data_control_1.sense_amp_delay;
+ const int8_t o_off = data_control_1.odt_duration;
+ const int8_t s_off = data_control_1.sense_amp_duration;
+ if (o_on + o_off >= 7 || s_on + s_off >= 7) {
+ clocks_on = true;
+ break;
+ }
+ }
+ union ddr_data_control_0_reg data_control_0 = {
+ .raw = ctrl->dq_control_0[channel],
+ };
+ data_control_0.internal_clocks_on = clocks_on;
+ ctrl->dq_control_0[channel] = data_control_0.raw;
+ mchbar_write32(DDR_DATA_ch_CONTROL_0(channel), data_control_0.raw);
+ }
+}
+
+/* Switch off unused segments of the SDLL to save power */
+static void update_sdll_length(struct sysinfo *ctrl)
+{
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
+ uint8_t max_pi = 0;
+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) {
+ if (!rank_in_ch(ctrl, rank, channel))
+ continue;
+
+ const uint8_t rx_dqs_p = ctrl->rxdqsp[channel][rank][byte];
+ const uint8_t rx_dqs_n = ctrl->rxdqsn[channel][rank][byte];
+ max_pi = MAX(max_pi, MAX(rx_dqs_p, rx_dqs_n));
+ }
+ /* Update SDLL length for power savings */
+ union ddr_data_control_1_reg data_control_1 = {
+ .raw = ctrl->dq_control_1[channel][byte],
+ };
+ /* Calculate which segments to turn off */
+ data_control_1.sdll_segment_disable = (7 - (max_pi >> 3)) & ~1;
+ ctrl->dq_control_1[channel][byte] = data_control_1.raw;
+ mchbar_write32(DQ_CONTROL_1(channel, byte), data_control_1.raw);
+ }
+ }
+}
+
+static void set_rx_clk_stg_num(struct sysinfo *ctrl, const uint8_t channel)
+{
+ const uint8_t rcven_drift = ctrl->lpddr ? DIV_ROUND_UP(tDQSCK_DRIFT, ctrl->qclkps) : 1;
+ uint8_t max_rcven = 0;
+ for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) {
+ if (!rank_in_ch(ctrl, rank, channel))
+ continue;
+
+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++)
+ max_rcven = MAX(max_rcven, ctrl->rcven[channel][rank][byte] / 64);
+ }
+ const union ddr_data_control_1_reg ddr_data_control_1 = {
+ .raw = ctrl->dq_control_1[channel][0],
+ };
+ const bool lpddr_long_odt = ddr_data_control_1.lpddr_long_odt_en;
+ const uint8_t rcven_turnoff = max_rcven + 18 + 2 * rcven_drift + lpddr_long_odt;
+ const union ddr_data_control_0_reg ddr_data_control_0 = {
+ .raw = ctrl->dq_control_0[channel],
+ };
+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
+ union ddr_data_control_2_reg ddr_data_control_2 = {
+ .raw = ctrl->dq_control_2[channel][byte],
+ };
+ if (ddr_data_control_0.odt_samp_extend_en) {
+ if (ddr_data_control_2.rx_clk_stg_num < rcven_turnoff)
+ ddr_data_control_2.rx_clk_stg_num = rcven_turnoff;
+ } else {
+ const int8_t o_on = ddr_data_control_1.odt_delay;
+ const int8_t o_off = ddr_data_control_1.odt_duration;
+ ddr_data_control_2.rx_clk_stg_num = MAX(17, o_on + o_off + 14);
+ }
+ ctrl->dq_control_2[channel][byte] = ddr_data_control_2.raw;
+ mchbar_write32(DQ_CONTROL_2(channel, byte), ddr_data_control_2.raw);
+ }
+}
+
+#define SELF_REFRESH_IDLE_COUNT 0x200
+
+static void enter_sr(void)
+{
+ mchbar_write32(PM_SREF_CONFIG, SELF_REFRESH_IDLE_COUNT | BIT(16));
+ udelay(1);
+}
+
+enum power_down_mode {
+ PDM_NO_PD = 0,
+ PDM_APD = 1,
+ PDM_PPD = 2,
+ PDM_PPD_DLL_OFF = 6,
+};
+
+static void power_down_config(struct sysinfo *ctrl)
+{
+ const enum power_down_mode pd_mode = ctrl->lpddr ? PDM_PPD : PDM_PPD_DLL_OFF;
+ mchbar_write32(PM_PDWN_CONFIG, pd_mode << 12 | 0x40);
+}
+
+static void train_power_modes_post(struct sysinfo *ctrl)
+{
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ /* Adjust tCPDED and tPRPDEN */
+ if (ctrl->mem_clock_mhz >= 933)
+ ctrl->tc_bankrank_d[channel].tCPDED = 2;
+
+ if (ctrl->mem_clock_mhz >= 1066)
+ ctrl->tc_bankrank_d[channel].tPRPDEN = 2;
+
+ mchbar_write32(TC_BANK_RANK_D_ch(channel), ctrl->tc_bankrank_d[channel].raw);
+ }
+ power_down_config(ctrl);
+ mchbar_write32(MCDECS_CBIT, BIT(30)); /* dis_msg_clk_gate */
+}
+
+static uint8_t compute_burst_end_odt_delay(const struct sysinfo *const ctrl)
+{
+ /* Must be disabled for LPDDR */
+ if (ctrl->lpddr)
+ return 0;
+
+ const uint8_t beod = MIN(7, DIV_ROUND_CLOSEST(14300 * 20 / 100, ctrl->qclkps));
+ if (beod < 3)
+ return 0;
+
+ if (beod < 4)
+ return 4;
+
+ return beod;
+}
+
+static void program_burst_end_odt_delay(struct sysinfo *ctrl)
+{
+ /* Program burst_end_odt_delay - it should be zero during training steps */
+ const uint8_t beod = compute_burst_end_odt_delay(ctrl);
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
+ union ddr_data_control_1_reg ddr_data_control_1 = {
+ .raw = ctrl->dq_control_1[channel][byte],
+ };
+ ddr_data_control_1.burst_end_odt_delay = beod;
+ ctrl->dq_control_1[channel][byte] = ddr_data_control_1.raw;
+ mchbar_write32(DQ_CONTROL_1(channel, byte), ddr_data_control_1.raw);
+ }
+ }
+}
+
+/*
+ * Return a random value to use for scrambler seeds. Try to use RDRAND
+ * first and fall back to hardcoded values if RDRAND does not succeed.
+ */
+static uint16_t get_random_number(const uint8_t channel)
+{
+ /* The RDRAND instruction is only available 100k cycles after reset */
+ for (size_t i = 0; i < 100000; i++) {
+ uint32_t status;
+ uint32_t random;
+ /** TODO: Clean up asm **/
+ __asm__ __volatile__(
+ "\n\t .byte 0x0F, 0xC7, 0xF0"
+ "\n\t movl %%eax, %0"
+ "\n\t pushf"
+ "\n\t pop %%eax"
+ "\n\t movl %%eax, %1"
+ : "=m"(random),
+ "=m"(status)
+ : /* No inputs */
+ : "eax", "cc");
+
+ /* Only consider non-zero random values as valid */
+ if (status & 1 && random)
+ return random;
+ }
+
+ /* https://xkcd.com/221 */
+ if (channel)
+ return 0x28f4;
+ else
+ return 0x893e;
+}
+
+/* Work around "error: 'typeof' applied to a bit-field" */
+static inline uint32_t max(const uint32_t a, const uint32_t b)
+{
+ return MAX(a, b);
+}
+
+enum raminit_status activate_mc(struct sysinfo *ctrl)
+{
+ const bool enable_scrambling = true;
+ const bool enable_cmd_tristate = true;
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ if (enable_scrambling && ctrl->stepping < STEPPING_C0) {
+ /* Make sure tRDRD_(sr, dr, dd) are at least 6 for scrambler W/A */
+ union tc_bank_rank_a_reg tc_bank_rank_a = {
+ .raw = mchbar_read32(TC_BANK_RANK_A_ch(channel)),
+ };
+ tc_bank_rank_a.tRDRD_sr = max(tc_bank_rank_a.tRDRD_sr, 6);
+ tc_bank_rank_a.tRDRD_dr = max(tc_bank_rank_a.tRDRD_dr, 6);
+ tc_bank_rank_a.tRDRD_dd = max(tc_bank_rank_a.tRDRD_dd, 6);
+ mchbar_write32(TC_BANK_RANK_A_ch(channel), tc_bank_rank_a.raw);
+ }
+ if (enable_scrambling) {
+ const union ddr_scramble_reg ddr_scramble = {
+ .scram_key = get_random_number(channel),
+ .scram_en = 1,
+ };
+ mchbar_write32(DDR_SCRAMBLE_ch(channel), ddr_scramble.raw);
+ }
+ if (ctrl->tCMD == 1) {
+ /* If we are in 1N mode, enable and set command rate limit to 3 */
+ union mcmain_command_rate_limit_reg cmd_rate_limit = {
+ .raw = mchbar_read32(COMMAND_RATE_LIMIT_ch(channel)),
+ };
+ cmd_rate_limit.enable_cmd_limit = 1;
+ cmd_rate_limit.cmd_rate_limit = 3;
+ mchbar_write32(COMMAND_RATE_LIMIT_ch(channel), cmd_rate_limit.raw);
+ }
+ if (enable_cmd_tristate) {
+ /* Enable command tri-state at the end of training */
+ union tc_bank_rank_a_reg tc_bank_rank_a = {
+ .raw = mchbar_read32(TC_BANK_RANK_A_ch(channel)),
+ };
+ tc_bank_rank_a.cmd_3st_dis = 0;
+ mchbar_write32(TC_BANK_RANK_A_ch(channel), tc_bank_rank_a.raw);
+ }
+ /* Set MC to normal mode and clean the ODT and CKE */
+ mchbar_write32(REUT_ch_SEQ_CFG(channel), REUT_MODE_NOP << 12);
+ /* Set again the rank occupancy */
+ mchbar_write8(MC_INIT_STATE_ch(channel), ctrl->rankmap[channel]);
+ if (ctrl->is_ecc) {
+ /* Enable ECC I/O and logic */
+ union mad_dimm_reg mad_dimm = {
+ .raw = mchbar_read32(MAD_DIMM(channel)),
+ };
+ mad_dimm.ecc_mode = 3;
+ mchbar_write32(MAD_DIMM(channel), mad_dimm.raw);
+ }
+ }
+
+ if (!is_hsw_ult())
+ update_internal_clocks_on(ctrl);
+
+ update_sdll_length(ctrl);
+
+ program_burst_end_odt_delay(ctrl);
+
+ if (is_hsw_ult()) {
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ if (!does_ch_exist(ctrl, channel))
+ continue;
+
+ set_rx_clk_stg_num(ctrl, channel);
+ }
+ /** TODO: Program DDRPL_CR_DDR_TX_DELAY if Memory Trace is enabled **/
+ }
+
+ /* Enable periodic COMP */
+ mchbar_write32(M_COMP, (union pcu_comp_reg) {
+ .comp_interval = COMP_INT,
+ }.raw);
+
+ /* Enable the power mode before PCU starts working */
+ train_power_modes_post(ctrl);
+
+ /* Set idle timer and self refresh enable bits */
+ enter_sr();
+
+ /** FIXME: Do not hardcode power weights and RAPL settings **/
+ mchbar_write32(0x5888, 0x00000d0d);
+ mchbar_write32(0x5884, 0x00000004); /* 58.2 pJ */
+
+ mchbar_write32(0x58e0, 0);
+ mchbar_write32(0x58e4, 0);
+
+ mchbar_write32(0x5890, 0xffff);
+ mchbar_write32(0x5894, 0xffff);
+ mchbar_write32(0x5898, 0xffff);
+ mchbar_write32(0x589c, 0xffff);
+ mchbar_write32(0x58d0, 0xffff);
+ mchbar_write32(0x58d4, 0xffff);
+ mchbar_write32(0x58d8, 0xffff);
+ mchbar_write32(0x58dc, 0xffff);
+
+ /* Overwrite thermal parameters */
+ for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+ mchbar_write32(_MCMAIN_C(0x42ec, channel), 0x0000000f);
+ mchbar_write32(_MCMAIN_C(0x42f0, channel), 0x00000009);
+ mchbar_write32(_MCMAIN_C(0x42f4, channel), 0x00000093);
+ mchbar_write32(_MCMAIN_C(0x42f8, channel), 0x00000087);
+ mchbar_write32(_MCMAIN_C(0x42fc, channel), 0x000000de);
+
+ /** TODO: Differs for LPDDR **/
+ mchbar_write32(PM_THRT_CKE_MIN_ch(channel), 0x30);
+ }
+ mchbar_write32(PCU_DDR_PTM_CTL, 0x40);
+ return RAMINIT_STATUS_SUCCESS;
+}
+
+static void mc_lockdown(void)
+{
+ /* Lock memory controller registers */
+ mchbar_write32(MC_LOCK, 0x8f);
+
+ /* MPCOHTRK_GDXC_OCLA_ADDRESS_HI_LOCK is set when programming the memory map */
+
+ /* Lock memory map registers */
+ pci_or_config16(HOST_BRIDGE, GGC, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, DPR, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, MESEG_LIMIT, 1 << 10);
+ pci_or_config32(HOST_BRIDGE, REMAPBASE, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, REMAPLIMIT, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, TOM, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, TOUUD, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, BDSM, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, BGSM, 1 << 0);
+ pci_or_config32(HOST_BRIDGE, TOLUD, 1 << 0);
+}
+
+enum raminit_status raminit_done(struct sysinfo *ctrl)
+{
+ union mc_init_state_g_reg mc_init_state_g = {
+ .raw = mchbar_read32(MC_INIT_STATE_G),
+ };
+ mc_init_state_g.refresh_enable = 1;
+ mc_init_state_g.pu_mrc_done = 1;
+ mc_init_state_g.mrc_done = 1;
+ mchbar_write32(MC_INIT_STATE_G, mc_init_state_g.raw);
+
+ /* Lock the memory controller to enable normal operation */
+ mc_lockdown();
+
+ /* Poll for mc_init_done_ack to make sure memory initialization is complete */
+ printk(BIOS_DEBUG, "Waiting for mc_init_done acknowledgement... ");
+
+ struct stopwatch timer;
+ stopwatch_init_msecs_expire(&timer, 2000);
+ do {
+ mc_init_state_g.raw = mchbar_read32(MC_INIT_STATE_G);
+
+ /* DRAM will NOT work without the acknowledgement. There is no hope. */
+ if (stopwatch_expired(&timer))
+ die("\nTimed out waiting for mc_init_done acknowledgement\n");
+
+ } while (mc_init_state_g.mc_init_done_ack == 0);
+ printk(BIOS_DEBUG, "DONE!\n");
+
+ /* Provide some data for the graphics driver. Yes, it's hardcoded. */
+ mchbar_write32(SSKPD + 0, 0x05a2404f);
+ mchbar_write32(SSKPD + 4, 0x140000a0);
+ return RAMINIT_STATUS_SUCCESS;
+}
diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
index 1ff23be615..3a65fb01fb 100644
--- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c
+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
@@ -63,6 +63,8 @@ static const struct task_entry cold_boot[] = {
{ train_receive_enable, true, "RCVET", },
{ train_read_mpr, true, "RDMPRT", },
{ train_jedec_write_leveling, true, "JWRL", },
+ { activate_mc, true, "ACTIVATE", },
+ { raminit_done, true, "RAMINITEND", },
};
/* Return a generic stepping value to make stepping checks simpler */
@@ -143,7 +145,4 @@ void raminit_main(const enum raminit_boot_mode bootmode)
if (status != RAMINIT_STATUS_SUCCESS)
die("Memory initialization was met with utmost failure and misery\n");
-
- /** TODO: Implement the required magic **/
- die("NATIVE RAMINIT: More Magic (tm) required.\n");
}
diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.c b/src/northbridge/intel/haswell/native_raminit/raminit_native.c
index 2fed93de5b..5f7ceec222 100644
--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.c
+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.c
@@ -199,8 +199,6 @@ void perform_raminit(const int s3resume)
else
me_status = ME_INIT_STATUS_SUCCESS;
- /** TODO: Remove this once raminit is implemented **/
- me_status = ME_INIT_STATUS_ERROR;
intel_early_me_init_done(me_status);
}
@@ -214,7 +212,8 @@ void perform_raminit(const int s3resume)
}
/* Save training data on non-S3 resumes */
- if (!s3resume)
+ /** TODO: Enable this once training data is populated **/
+ if (0 && !s3resume)
save_mrc_data(&md);
/** TODO: setup_sdram_meminfo **/
diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
index 86d89f2120..9bab57b518 100644
--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
@@ -447,6 +447,8 @@ enum raminit_status do_jedec_init(struct sysinfo *ctrl);
enum raminit_status train_receive_enable(struct sysinfo *ctrl);
enum raminit_status train_read_mpr(struct sysinfo *ctrl);
enum raminit_status train_jedec_write_leveling(struct sysinfo *ctrl);
+enum raminit_status activate_mc(struct sysinfo *ctrl);
+enum raminit_status raminit_done(struct sysinfo *ctrl);
void configure_timings(struct sysinfo *ctrl);
void configure_refresh(struct sysinfo *ctrl);
diff --git a/src/northbridge/intel/haswell/native_raminit/reg_structs.h b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
index a0e36ed082..0d9aaa1f7c 100644
--- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h
+++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
@@ -294,6 +294,18 @@ union ddr_cke_ctl_controls_reg {
uint32_t raw;
};
+union ddr_scramble_reg {
+ struct __packed {
+ uint32_t scram_en : 1; // Bits 0:0
+ uint32_t scram_key : 16; // Bits 16:1
+ uint32_t clk_gate_ab : 2; // Bits 18:17
+ uint32_t clk_gate_c : 2; // Bits 20:19
+ uint32_t en_dbi_ab : 1; // Bits 21:21
+ uint32_t : 10; // Bits 31:17
+ };
+ uint32_t raw;
+};
+
union ddr_scram_misc_control_reg {
struct __packed {
uint32_t wl_wake_cycles : 2; // Bits 1:0
diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
index 7c0b5a49de..49a215aa71 100644
--- a/src/northbridge/intel/haswell/registers/mchbar.h
+++ b/src/northbridge/intel/haswell/registers/mchbar.h
@@ -20,6 +20,7 @@
#define DDR_DATA_TRAIN_FEEDBACK(ch, byte) _DDRIO_C_R_B(0x0054, ch, 0, byte)
+#define DQ_CONTROL_1(ch, byte) _DDRIO_C_R_B(0x0060, 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)
@@ -147,6 +148,8 @@
#define QCLK_ch_LDAT_SDAT(ch) _MCMAIN_C(0x42d4, ch)
#define QCLK_ch_LDAT_DATA_IN_x(ch, x) _MCMAIN_C_X(0x42dc, ch, x) /* x in 0 .. 1 */
+#define PM_THRT_CKE_MIN_ch(ch) _MCMAIN_C(0x4328, ch)
+
#define REUT_GLOBAL_CTL 0x4800
#define REUT_GLOBAL_ERR 0x4804
@@ -175,6 +178,8 @@
#define MCSCHEDS_DFT_MISC 0x4c30
+#define PM_PDWN_CONFIG 0x4cb0
+
#define REUT_ERR_DATA_STATUS 0x4ce0
#define REUT_MISC_CKE_CTRL 0x4d90
@@ -186,8 +191,10 @@
#define MAD_CHNL 0x5000 /* Address Decoder Channel Configuration */
#define MAD_DIMM(ch) (0x5004 + (ch) * 4)
#define MAD_ZR 0x5014
+#define MCDECS_CBIT 0x501c
#define MC_INIT_STATE_G 0x5030
#define MRC_REVISION 0x5034 /* MRC Revision */
+#define PM_SREF_CONFIG 0x5060
#define RCOMP_TIMER 0x5084
--
2.39.2