diff options
author | Leah Rowe <leah@libreboot.org> | 2024-08-10 14:43:19 +0100 |
---|---|---|
committer | Leah Rowe <leah@libreboot.org> | 2024-08-10 14:48:01 +0100 |
commit | 877f5d6aeb6a1a62f09c95cc214c874d057310d6 (patch) | |
tree | 4a40b0d1a0ec5edb5f501087e5ed881262b896b1 /config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch | |
parent | a15347ef1e677ca711ce706877db2416ddfd451a (diff) |
coreboot/default: merge coreboot/haswell
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch')
-rw-r--r-- | config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch | 570 |
1 files changed, 570 insertions, 0 deletions
diff --git a/config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch b/config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch new file mode 100644 index 00000000..db111ee1 --- /dev/null +++ b/config/coreboot/default/patches/0057-haswell-NRI-Add-final-raminit-steps.patch @@ -0,0 +1,570 @@ +From e30c9c431ef11d87c6f46071ec43cc34391b8349 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/17] 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 d6b11b9d3c..a0a913f926 100644 +--- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h ++++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h +@@ -448,6 +448,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 + |