123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- From b64d728bfe7c8ee44af252338257e95d87864659 Mon Sep 17 00:00:00 2001
- From: Angel Pons <th3fanbus@gmail.com>
- Date: Sat, 7 May 2022 20:59:58 +0200
- Subject: [PATCH 14/26] haswell NRI: Add timings/refresh programming
- Program the registers with timing and refresh parameters.
- Change-Id: Id2ea339d2c9ea8b56c71d6e88ec76949653ff5c2
- Signed-off-by: Angel Pons <th3fanbus@gmail.com>
- ---
- .../haswell/native_raminit/lookup_timings.c | 102 ++++++++
- .../haswell/native_raminit/raminit_native.h | 14 ++
- .../haswell/native_raminit/reg_structs.h | 93 +++++++
- .../haswell/native_raminit/timings_refresh.c | 233 +++++++++++++++++-
- .../intel/haswell/registers/mchbar.h | 12 +
- 5 files changed, 452 insertions(+), 2 deletions(-)
- diff --git a/src/northbridge/intel/haswell/native_raminit/lookup_timings.c b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c
- index 038686c844..afe2c615d2 100644
- --- a/src/northbridge/intel/haswell/native_raminit/lookup_timings.c
- +++ b/src/northbridge/intel/haswell/native_raminit/lookup_timings.c
- @@ -60,3 +60,105 @@ uint32_t get_tXP(const uint32_t mem_clock_mhz)
- };
- return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- }
- +
- +static uint32_t get_lpddr_tCKE(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 533, 4 },
- + { 666, 5 },
- + { fmax, 6 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +static uint32_t get_ddr_tCKE(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 533, 3 },
- + { 800, 4 },
- + { 933, 5 },
- + { 1200, 6 },
- + { fmax, 7 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +uint32_t get_tCKE(const uint32_t mem_clock_mhz, const bool lpddr)
- +{
- + return lpddr ? get_lpddr_tCKE(mem_clock_mhz) : get_ddr_tCKE(mem_clock_mhz);
- +}
- +
- +uint32_t get_tXPDLL(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 400, 10 },
- + { 533, 13 },
- + { 666, 16 },
- + { 800, 20 },
- + { 933, 23 },
- + { 1066, 26 },
- + { 1200, 29 },
- + { fmax, 32 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +uint32_t get_tAONPD(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 400, 4 },
- + { 533, 5 },
- + { 666, 6 },
- + { 800, 7 }, /* SNB had 8 */
- + { 933, 8 },
- + { 1066, 10 },
- + { 1200, 11 },
- + { fmax, 12 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +uint32_t get_tMOD(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 800, 12 },
- + { 933, 14 },
- + { 1066, 16 },
- + { 1200, 18 },
- + { fmax, 20 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +uint32_t get_tXS_offset(const uint32_t mem_clock_mhz)
- +{
- + return DIV_ROUND_UP(mem_clock_mhz, 100);
- +}
- +
- +static uint32_t get_lpddr_tZQOPER(const uint32_t mem_clock_mhz)
- +{
- + return (mem_clock_mhz * 360) / 1000;
- +}
- +
- +static uint32_t get_ddr_tZQOPER(const uint32_t mem_clock_mhz)
- +{
- + const struct timing_lookup lut[] = {
- + { 800, 256 },
- + { 933, 299 },
- + { 1066, 342 },
- + { 1200, 384 },
- + { fmax, 427 },
- + };
- + return lookup_timing(mem_clock_mhz, lut, ARRAY_SIZE(lut));
- +}
- +
- +/* tZQOPER defines the period required for ZQCL after SR exit */
- +uint32_t get_tZQOPER(const uint32_t mem_clock_mhz, const bool lpddr)
- +{
- + return lpddr ? get_lpddr_tZQOPER(mem_clock_mhz) : get_ddr_tZQOPER(mem_clock_mhz);
- +}
- +
- +uint32_t get_tZQCS(const uint32_t mem_clock_mhz, const bool lpddr)
- +{
- + return DIV_ROUND_UP(get_tZQOPER(mem_clock_mhz, lpddr), 4);
- +}
- diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- index aa86b9aa39..cd1f2eb2a5 100644
- --- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- +++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- @@ -155,6 +155,12 @@ struct sysinfo {
- uint8_t cke_cmd_pi_code[NUM_CHANNELS][NUM_GROUPS];
- uint8_t cmd_north_pi_code[NUM_CHANNELS][NUM_GROUPS];
- uint8_t cmd_south_pi_code[NUM_CHANNELS][NUM_GROUPS];
- +
- + union tc_bank_reg tc_bank[NUM_CHANNELS];
- + union tc_bank_rank_a_reg tc_bankrank_a[NUM_CHANNELS];
- + union tc_bank_rank_b_reg tc_bankrank_b[NUM_CHANNELS];
- + union tc_bank_rank_c_reg tc_bankrank_c[NUM_CHANNELS];
- + union tc_bank_rank_d_reg tc_bankrank_d[NUM_CHANNELS];
- };
-
- static inline bool is_hsw_ult(void)
- @@ -200,6 +206,14 @@ enum raminit_status configure_mc(struct sysinfo *ctrl);
- void configure_timings(struct sysinfo *ctrl);
- void configure_refresh(struct sysinfo *ctrl);
-
- +uint32_t get_tCKE(uint32_t mem_clock_mhz, bool lpddr);
- +uint32_t get_tXPDLL(uint32_t mem_clock_mhz);
- +uint32_t get_tAONPD(uint32_t mem_clock_mhz);
- +uint32_t get_tMOD(uint32_t mem_clock_mhz);
- +uint32_t get_tXS_offset(uint32_t mem_clock_mhz);
- +uint32_t get_tZQOPER(uint32_t mem_clock_mhz, bool lpddr);
- +uint32_t get_tZQCS(uint32_t mem_clock_mhz, bool lpddr);
- +
- enum raminit_status wait_for_first_rcomp(void);
-
- uint8_t get_rx_bias(const 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 d11cda4b3d..70487e1640 100644
- --- a/src/northbridge/intel/haswell/native_raminit/reg_structs.h
- +++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
- @@ -335,6 +335,99 @@ union mcscheds_cbit_reg {
- uint32_t raw;
- };
-
- +union tc_bank_reg {
- + struct __packed {
- + uint32_t tRCD : 5; // Bits 4:0
- + uint32_t tRP : 5; // Bits 9:5
- + uint32_t tRAS : 6; // Bits 15:10
- + uint32_t tRDPRE : 4; // Bits 19:16
- + uint32_t tWRPRE : 6; // Bits 25:20
- + uint32_t tRRD : 4; // Bits 29:26
- + uint32_t tRPab_ext : 2; // Bits 31:30
- + };
- + uint32_t raw;
- +};
- +
- +union tc_bank_rank_a_reg {
- + struct __packed {
- + uint32_t tCKE : 4; // Bits 3:0
- + uint32_t tFAW : 8; // Bits 11:4
- + uint32_t tRDRD_sr : 3; // Bits 14:12
- + uint32_t tRDRD_dr : 4; // Bits 18:15
- + uint32_t tRDRD_dd : 4; // Bits 22:19
- + uint32_t tRDPDEN : 5; // Bits 27:23
- + uint32_t : 1; // Bits 28:28
- + uint32_t cmd_3st_dis : 1; // Bits 29:29
- + uint32_t cmd_stretch : 2; // Bits 31:30
- + };
- + uint32_t raw;
- +};
- +
- +union tc_bank_rank_b_reg {
- + struct __packed {
- + uint32_t tWRRD_sr : 6; // Bits 5:0
- + uint32_t tWRRD_dr : 4; // Bits 9:6
- + uint32_t tWRRD_dd : 4; // Bits 13:10
- + uint32_t tWRWR_sr : 3; // Bits 16:14
- + uint32_t tWRWR_dr : 4; // Bits 20:17
- + uint32_t tWRWR_dd : 4; // Bits 24:21
- + uint32_t tWRPDEN : 6; // Bits 30:25
- + uint32_t dec_wrd : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union tc_bank_rank_c_reg {
- + struct __packed {
- + uint32_t tXPDLL : 6; // Bits 5:0
- + uint32_t tXP : 4; // Bits 9:6
- + uint32_t tAONPD : 4; // Bits 13:10
- + uint32_t tRDWR_sr : 5; // Bits 18:14
- + uint32_t tRDWR_dr : 5; // Bits 23:19
- + uint32_t tRDWR_dd : 5; // Bits 28:24
- + uint32_t : 3; // Bits 31:29
- + };
- + uint32_t raw;
- +};
- +
- +/* NOTE: Non-ULT only implements the lower 21 bits (odt_write_delay is 2 bits) */
- +union tc_bank_rank_d_reg {
- + struct __packed {
- + uint32_t tAA : 5; // Bits 4:0
- + uint32_t tCWL : 5; // Bits 9:5
- + uint32_t tCPDED : 2; // Bits 11:10
- + uint32_t tPRPDEN : 2; // Bits 13:12
- + uint32_t odt_read_delay : 3; // Bits 16:14
- + uint32_t odt_read_duration : 2; // Bits 18:17
- + uint32_t odt_write_duration : 3; // Bits 21:19
- + uint32_t odt_write_delay : 3; // Bits 24:22
- + uint32_t odt_always_rank_0 : 1; // Bits 25:25
- + uint32_t cmd_delay : 2; // Bits 27:26
- + uint32_t : 4; // Bits 31:28
- + };
- + uint32_t raw;
- +};
- +
- +union tc_rftp_reg {
- + struct __packed {
- + uint32_t tREFI : 16; // Bits 15:0
- + uint32_t tRFC : 9; // Bits 24:16
- + uint32_t tREFIx9 : 7; // Bits 31:25
- + };
- + uint32_t raw;
- +};
- +
- +union tc_srftp_reg {
- + struct __packed {
- + uint32_t tXSDLL : 12; // Bits 11:0
- + uint32_t tXS_offset : 4; // Bits 15:12
- + uint32_t tZQOPER : 10; // Bits 25:16
- + uint32_t : 2; // Bits 27:26
- + uint32_t tMOD : 4; // Bits 31:28
- + };
- + uint32_t raw;
- +};
- +
- union mcmain_command_rate_limit_reg {
- struct __packed {
- uint32_t enable_cmd_limit : 1; // Bits 0:0
- diff --git a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- index a9d960f31b..20a05b359b 100644
- --- a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- +++ b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- @@ -1,13 +1,242 @@
- /* SPDX-License-Identifier: GPL-2.0-or-later */
-
- +#include <assert.h>
- +#include <commonlib/clamp.h>
- +#include <console/console.h>
- +#include <delay.h>
- +#include <device/pci_ops.h>
- +#include <northbridge/intel/haswell/haswell.h>
- +
- #include "raminit_native.h"
-
- +#define BL 8 /* Burst length */
- +#define tCCD 4
- +#define tRPRE 1
- +#define tWPRE 1
- +#define tDLLK 512
- +
- +static bool is_sodimm(const enum spd_dimm_type_ddr3 type)
- +{
- + return type == SPD_DDR3_DIMM_TYPE_SO_DIMM || type == SPD_DDR3_DIMM_TYPE_72B_SO_UDIMM;
- +}
- +
- +static uint8_t get_odt_stretch(const struct sysinfo *const ctrl)
- +{
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + /* Only stretch with 2 DIMMs per channel */
- + if (ctrl->dpc[channel] != 2)
- + continue;
- +
- + const struct raminit_dimm_info *dimms = ctrl->dimms[channel];
- +
- + /* Only stretch when using SO-DIMMs */
- + if (!is_sodimm(dimms[0].data.dimm_type) || !is_sodimm(dimms[1].data.dimm_type))
- + continue;
- +
- + /* Only stretch with mismatched card types */
- + if (dimms[0].data.reference_card == dimms[1].data.reference_card)
- + continue;
- +
- + /* Stretch if one SO-DIMM is card F */
- + for (uint8_t slot = 0; slot < NUM_SLOTS; slot++) {
- + if (dimms[slot].data.reference_card == 5)
- + return 1;
- + }
- + }
- + return 0;
- +}
- +
- +static union tc_bank_reg make_tc_bank(struct sysinfo *const ctrl)
- +{
- + return (union tc_bank_reg) {
- + .tRCD = ctrl->tRCD,
- + .tRP = ctrl->tRP,
- + .tRAS = ctrl->tRAS,
- + .tRDPRE = ctrl->tRTP,
- + .tWRPRE = 4 + ctrl->tCWL + ctrl->tWR,
- + .tRRD = ctrl->tRRD,
- + .tRPab_ext = 0, /** TODO: For LPDDR, this is ctrl->tRPab - ctrl->tRP **/
- + };
- +}
- +
- +static union tc_bank_rank_a_reg make_tc_bankrank_a(struct sysinfo *ctrl, uint8_t odt_stretch)
- +{
- + /* Use 3N mode for DDR during training, but always use 1N mode for LPDDR */
- + const uint32_t tCMD = ctrl->lpddr ? 0 : 3;
- + const uint32_t tRDRD_drdd = BL / 2 + 1 + tRPRE + odt_stretch + !!ctrl->lpddr;
- +
- + return (union tc_bank_rank_a_reg) {
- + .tCKE = get_tCKE(ctrl->mem_clock_mhz, ctrl->lpddr),
- + .tFAW = ctrl->tFAW,
- + .tRDRD_sr = tCCD,
- + .tRDRD_dr = tRDRD_drdd,
- + .tRDRD_dd = tRDRD_drdd,
- + .tRDPDEN = ctrl->tAA + BL / 2 + 1,
- + .cmd_3st_dis = 1, /* Disable command tri-state before training */
- + .cmd_stretch = tCMD,
- + };
- +}
- +
- +static union tc_bank_rank_b_reg make_tc_bankrank_b(struct sysinfo *const ctrl)
- +{
- + const uint8_t tWRRD_drdd = ctrl->tCWL - ctrl->tAA + BL / 2 + 2 + tRPRE;
- + const uint8_t tWRWR_drdd = BL / 2 + 2 + tWPRE;
- +
- + return (union tc_bank_rank_b_reg) {
- + .tWRRD_sr = tCCD + ctrl->tCWL + ctrl->tWTR + 2,
- + .tWRRD_dr = ctrl->lpddr ? 8 : tWRRD_drdd,
- + .tWRRD_dd = ctrl->lpddr ? 8 : tWRRD_drdd,
- + .tWRWR_sr = tCCD,
- + .tWRWR_dr = tWRWR_drdd,
- + .tWRWR_dd = tWRWR_drdd,
- + .tWRPDEN = ctrl->tWR + ctrl->tCWL + BL / 2,
- + .dec_wrd = ctrl->tCWL >= 6,
- + };
- +}
- +
- +static uint32_t get_tRDWR_sr(const struct sysinfo *ctrl)
- +{
- + if (ctrl->lpddr) {
- + const uint32_t tdqsck_max = DIV_ROUND_UP(5500, ctrl->qclkps * 2);
- + return ctrl->tAA - ctrl->tCWL + tCCD + tWPRE + tdqsck_max + 1;
- + } else {
- + const bool fast_clock = ctrl->mem_clock_mhz > 666;
- + return ctrl->tAA - ctrl->tCWL + tCCD + tWPRE + 2 + fast_clock;
- + }
- +}
- +
- +static union tc_bank_rank_c_reg make_tc_bankrank_c(struct sysinfo *ctrl, uint8_t odt_stretch)
- +{
- + const uint32_t tRDWR_sr = get_tRDWR_sr(ctrl);
- + const uint32_t tRDWR_drdd = tRDWR_sr + odt_stretch;
- +
- + return (union tc_bank_rank_c_reg) {
- + .tXPDLL = get_tXPDLL(ctrl->mem_clock_mhz),
- + .tXP = MAX(ctrl->tXP, 7), /* Use a higher tXP for training */
- + .tAONPD = get_tAONPD(ctrl->mem_clock_mhz),
- + .tRDWR_sr = tRDWR_sr,
- + .tRDWR_dr = tRDWR_drdd,
- + .tRDWR_dd = tRDWR_drdd,
- + };
- +}
- +
- +static union tc_bank_rank_d_reg make_tc_bankrank_d(struct sysinfo *ctrl, uint8_t odt_stretch)
- +{
- + const uint32_t odt_rd_delay = ctrl->tAA - ctrl->tCWL;
- + if (!ctrl->lpddr) {
- + return (union tc_bank_rank_d_reg) {
- + .tAA = ctrl->tAA,
- + .tCWL = ctrl->tCWL,
- + .tCPDED = 1,
- + .tPRPDEN = 1,
- + .odt_read_delay = odt_rd_delay,
- + .odt_read_duration = odt_stretch,
- + };
- + }
- +
- + /* tCWL has 1 extra clock because of tDQSS, subtract it here */
- + const uint32_t tCWL_lpddr = ctrl->tCWL - 1;
- + const uint32_t odt_wr_delay = tCWL_lpddr + DIV_ROUND_UP(3500, ctrl->qclkps * 2);
- + const uint32_t odt_wr_duration = DIV_ROUND_UP(3500 - 1750, ctrl->qclkps * 2) + 1;
- +
- + return (union tc_bank_rank_d_reg) {
- + .tAA = ctrl->tAA,
- + .tCWL = tCWL_lpddr,
- + .tCPDED = 2, /* Required by JEDEC LPDDR3 spec */
- + .tPRPDEN = 1,
- + .odt_read_delay = odt_rd_delay,
- + .odt_read_duration = odt_stretch,
- + .odt_write_delay = odt_wr_delay,
- + .odt_write_duration = odt_wr_duration,
- + .odt_always_rank_0 = ctrl->lpddr_dram_odt
- + };
- +}
- +
- +/* ZQCS period values, in (tREFI * 128) units */
- +#define ZQCS_PERIOD_DDR3 128 /* tREFI * 128 = 7.8 us * 128 = 1ms */
- +#define ZQCS_PERIOD_LPDDR3 256 /* tREFI * 128 = 3.9 us * 128 = 0.5ms */
- +
- +static uint32_t make_tc_zqcal(const struct sysinfo *const ctrl)
- +{
- + const uint32_t zqcs_period = ctrl->lpddr ? ZQCS_PERIOD_LPDDR3 : ZQCS_PERIOD_DDR3;
- + const uint32_t tZQCS = get_tZQCS(ctrl->mem_clock_mhz, ctrl->lpddr);
- + return tZQCS << (is_hsw_ult() ? 10 : 8) | zqcs_period;
- +}
- +
- +static union tc_rftp_reg make_tc_rftp(const struct sysinfo *const ctrl)
- +{
- + /*
- + * The tREFIx9 field should be programmed to minimum of 8.9 * tREFI (to allow
- + * for possible delays from ZQ or isoc) and tRASmax (70us) divided by 1024.
- + */
- + return (union tc_rftp_reg) {
- + .tREFI = ctrl->tREFI,
- + .tRFC = ctrl->tRFC,
- + .tREFIx9 = ctrl->tREFI * 89 / 10240,
- + };
- +}
- +
- +static union tc_srftp_reg make_tc_srftp(const struct sysinfo *const ctrl)
- +{
- + return (union tc_srftp_reg) {
- + .tXSDLL = tDLLK,
- + .tXS_offset = get_tXS_offset(ctrl->mem_clock_mhz),
- + .tZQOPER = get_tZQOPER(ctrl->mem_clock_mhz, ctrl->lpddr),
- + .tMOD = get_tMOD(ctrl->mem_clock_mhz) - 8,
- + };
- +}
- +
- void configure_timings(struct sysinfo *ctrl)
- {
- - /** TODO: Stub **/
- + if (ctrl->lpddr)
- + die("%s: Missing support for LPDDR\n");
- +
- + const uint8_t odt_stretch = get_odt_stretch(ctrl);
- + const union tc_bank_reg tc_bank = make_tc_bank(ctrl);
- + const union tc_bank_rank_a_reg tc_bank_rank_a = make_tc_bankrank_a(ctrl, odt_stretch);
- + const union tc_bank_rank_b_reg tc_bank_rank_b = make_tc_bankrank_b(ctrl);
- + const union tc_bank_rank_c_reg tc_bank_rank_c = make_tc_bankrank_c(ctrl, odt_stretch);
- + const union tc_bank_rank_d_reg tc_bank_rank_d = make_tc_bankrank_d(ctrl, odt_stretch);
- +
- + const uint8_t wr_delay = tc_bank_rank_b.dec_wrd + 1;
- + uint8_t sc_wr_add_delay = 0;
- + sc_wr_add_delay |= wr_delay << 0;
- + sc_wr_add_delay |= wr_delay << 2;
- + sc_wr_add_delay |= wr_delay << 4;
- + sc_wr_add_delay |= wr_delay << 6;
- +
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel))
- + continue;
- +
- + ctrl->tc_bank[channel] = tc_bank;
- + ctrl->tc_bankrank_a[channel] = tc_bank_rank_a;
- + ctrl->tc_bankrank_b[channel] = tc_bank_rank_b;
- + ctrl->tc_bankrank_c[channel] = tc_bank_rank_c;
- + ctrl->tc_bankrank_d[channel] = tc_bank_rank_d;
- +
- + mchbar_write32(TC_BANK_ch(channel), ctrl->tc_bank[channel].raw);
- + mchbar_write32(TC_BANK_RANK_A_ch(channel), ctrl->tc_bankrank_a[channel].raw);
- + mchbar_write32(TC_BANK_RANK_B_ch(channel), ctrl->tc_bankrank_b[channel].raw);
- + mchbar_write32(TC_BANK_RANK_C_ch(channel), ctrl->tc_bankrank_c[channel].raw);
- + mchbar_write32(TC_BANK_RANK_D_ch(channel), ctrl->tc_bankrank_d[channel].raw);
- + mchbar_write8(SC_WR_ADD_DELAY_ch(channel), sc_wr_add_delay);
- + }
- }
-
- void configure_refresh(struct sysinfo *ctrl)
- {
- - /** TODO: Stub **/
- + const union tc_srftp_reg tc_srftp = make_tc_srftp(ctrl);
- + const union tc_rftp_reg tc_rftp = make_tc_rftp(ctrl);
- + const uint32_t tc_zqcal = make_tc_zqcal(ctrl);
- +
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel))
- + continue;
- +
- + mchbar_setbits32(TC_RFP_ch(channel), 0xff);
- + mchbar_write32(TC_RFTP_ch(channel), tc_rftp.raw);
- + mchbar_write32(TC_SRFTP_ch(channel), tc_srftp.raw);
- + mchbar_write32(TC_ZQCAL_ch(channel), tc_zqcal);
- + }
- }
- diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
- index 4c3f399b5d..2acc5cbbc8 100644
- --- a/src/northbridge/intel/haswell/registers/mchbar.h
- +++ b/src/northbridge/intel/haswell/registers/mchbar.h
- @@ -86,9 +86,21 @@
- #define DDR_COMP_VSSHI_CONTROL 0x3a24
-
- /* MCMAIN per-channel */
- +#define TC_BANK_ch(ch) _MCMAIN_C(0x4000, ch)
- +#define TC_BANK_RANK_A_ch(ch) _MCMAIN_C(0x4004, ch)
- +#define TC_BANK_RANK_B_ch(ch) _MCMAIN_C(0x4008, ch)
- +#define TC_BANK_RANK_C_ch(ch) _MCMAIN_C(0x400c, ch)
- #define COMMAND_RATE_LIMIT_ch(ch) _MCMAIN_C(0x4010, ch)
- +#define TC_BANK_RANK_D_ch(ch) _MCMAIN_C(0x4014, ch)
- +#define SC_ROUNDT_LAT_ch(ch) _MCMAIN_C(0x4024, ch)
-
- +#define SC_WR_ADD_DELAY_ch(ch) _MCMAIN_C(0x40d0, ch)
- +
- +#define TC_ZQCAL_ch(ch) _MCMAIN_C(0x4290, ch)
- +#define TC_RFP_ch(ch) _MCMAIN_C(0x4294, ch)
- +#define TC_RFTP_ch(ch) _MCMAIN_C(0x4298, ch)
- #define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch)
- +#define TC_SRFTP_ch(ch) _MCMAIN_C(0x42a4, ch)
-
- /* MCMAIN broadcast */
- #define MCSCHEDS_CBIT 0x4c20
- --
- 2.39.2
|