1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594 |
- From 1b0b17d85256193de825fa7ff0e04767c818f2fc Mon Sep 17 00:00:00 2001
- From: Angel Pons <th3fanbus@gmail.com>
- Date: Sat, 7 May 2022 17:22:07 +0200
- Subject: [PATCH 13/26] haswell NRI: Configure initial MC settings
- Program initial memory controller settings. Many of these values will be
- adjusted later during training.
- Change-Id: If33846b51cb1bab5d0458fe626e13afb1bdc900e
- Signed-off-by: Angel Pons <th3fanbus@gmail.com>
- ---
- .../intel/haswell/native_raminit/Makefile.inc | 2 +
- .../haswell/native_raminit/configure_mc.c | 822 ++++++++++++++++++
- .../haswell/native_raminit/raminit_main.c | 2 +
- .../haswell/native_raminit/raminit_native.h | 101 +++
- .../haswell/native_raminit/reg_structs.h | 405 +++++++++
- .../haswell/native_raminit/timings_refresh.c | 13 +
- .../intel/haswell/registers/mchbar.h | 94 ++
- 7 files changed, 1439 insertions(+)
- create mode 100644 src/northbridge/intel/haswell/native_raminit/configure_mc.c
- create mode 100644 src/northbridge/intel/haswell/native_raminit/reg_structs.h
- create mode 100644 src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- index 2769e0bbb4..fc55277a65 100644
- --- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- +++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
- @@ -1,8 +1,10 @@
- ## SPDX-License-Identifier: GPL-2.0-or-later
-
- +romstage-y += configure_mc.c
- romstage-y += lookup_timings.c
- romstage-y += init_mpll.c
- romstage-y += io_comp_control.c
- romstage-y += raminit_main.c
- romstage-y += raminit_native.c
- romstage-y += spd_bitmunching.c
- +romstage-y += timings_refresh.c
- diff --git a/src/northbridge/intel/haswell/native_raminit/configure_mc.c b/src/northbridge/intel/haswell/native_raminit/configure_mc.c
- new file mode 100644
- index 0000000000..2a667b075b
- --- /dev/null
- +++ b/src/northbridge/intel/haswell/native_raminit/configure_mc.c
- @@ -0,0 +1,822 @@
- +/* SPDX-License-Identifier: GPL-2.0-or-later */
- +
- +#include <assert.h>
- +#include <commonlib/clamp.h>
- +#include <console/console.h>
- +#include <delay.h>
- +#include <lib.h>
- +#include <northbridge/intel/haswell/haswell.h>
- +#include <string.h>
- +#include <types.h>
- +
- +#include "raminit_native.h"
- +
- +static void program_misc_control(struct sysinfo *ctrl)
- +{
- + if (!is_hsw_ult())
- + return;
- +
- + const union ddr_scram_misc_control_reg ddr_scram_misc_ctrl = {
- + .ddr_no_ch_interleave = !ctrl->dq_pins_interleaved,
- + .lpddr_mode = ctrl->lpddr,
- + .cke_mapping_ch0 = ctrl->lpddr ? ctrl->lpddr_cke_rank_map[0] : 0,
- + .cke_mapping_ch1 = ctrl->lpddr ? ctrl->lpddr_cke_rank_map[1] : 0,
- + };
- + mchbar_write32(DDR_SCRAM_MISC_CONTROL, ddr_scram_misc_ctrl.raw);
- +}
- +
- +static void program_mrc_revision(void)
- +{
- + mchbar_write32(MRC_REVISION, 0x01090000); /* MRC 1.9.0 Build 0 */
- +}
- +
- +static void program_ranks_used(struct sysinfo *ctrl)
- +{
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + mchbar_write8(MC_INIT_STATE_ch(channel), ctrl->rankmap[channel]);
- + if (!does_ch_exist(ctrl, channel)) {
- + mchbar_write32(DDR_CLK_ch_RANKS_USED(channel), 0);
- + mchbar_write32(DDR_CTL_ch_CTL_RANKS_USED(channel), 0);
- + mchbar_write32(DDR_CKE_ch_CTL_RANKS_USED(channel), 0);
- + continue;
- + }
- + uint32_t clk_ranks_used = ctrl->rankmap[channel];
- + if (ctrl->lpddr) {
- + /* With LPDDR, the clock usage goes by group instead */
- + clk_ranks_used = 0;
- + for (uint8_t group = 0; group < NUM_GROUPS; group++) {
- + if (ctrl->dq_byte_map[channel][CT_ITERATION_CLOCK][group])
- + clk_ranks_used |= BIT(group);
- + }
- + }
- + mchbar_write32(DDR_CLK_ch_RANKS_USED(channel), clk_ranks_used);
- +
- + uint32_t ctl_ranks_used = ctrl->rankmap[channel];
- + if (is_hsw_ult()) {
- + /* Set ODT disable bits */
- + /** TODO: May need to do this after JEDEC reset/init **/
- + if (ctrl->lpddr && ctrl->lpddr_dram_odt)
- + ctl_ranks_used |= 2 << 4; /* ODT is used on rank 0 */
- + else
- + ctl_ranks_used |= 3 << 4;
- + }
- + mchbar_write32(DDR_CTL_ch_CTL_RANKS_USED(channel), ctl_ranks_used);
- +
- + uint32_t cke_ranks_used = ctrl->rankmap[channel];
- + if (ctrl->lpddr) {
- + /* Use CKE-to-rank mapping for LPDDR */
- + const uint8_t cke_rank_map = ctrl->lpddr_cke_rank_map[channel];
- + cke_ranks_used = 0;
- + for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) {
- + /* ULT only has 2 ranks per channel */
- + if (rank >= 2)
- + break;
- +
- + if (!rank_in_ch(ctrl, rank, channel))
- + continue;
- +
- + for (uint8_t cke = 0; cke < 4; cke++) {
- + if (rank == ((cke_rank_map >> cke) & 1))
- + cke_ranks_used |= BIT(cke);
- + }
- + }
- + }
- + mchbar_write32(DDR_CKE_ch_CTL_RANKS_USED(channel), cke_ranks_used);
- + }
- +}
- +
- +static const uint8_t rxb_trad[2][5][4] = {
- + { /* Vdd low */
- + /* 1067 MHz, 1333 MHz, 1600 MHz, 1867 MHz, 2133 MHz, */
- + {4, 3, 3, 2}, {4, 4, 3, 2}, {5, 4, 3, 3}, {5, 4, 4, 3}, {5, 4, 4, 3},
- + },
- + { /* Vdd hi */
- + /* 1067 MHz, 1333 MHz, 1600 MHz, 1867 MHz, 2133 MHz, */
- + {4, 3, 3, 2}, {4, 4, 3, 2}, {5, 4, 3, 3}, {5, 4, 4, 3}, {4, 4, 3, 3},
- + },
- +};
- +
- +static const uint8_t rxb_ultx[2][3][4] = {
- + { /* Vdd low */
- + /* 1067 MHz, 1333 MHz, 1600 MHz, */
- + {5, 6, 6, 5}, {5, 6, 6, 5}, {4, 6, 6, 6},
- + },
- + { /* Vdd hi */
- + /* 1067 MHz, 1333 MHz, 1600 MHz, */
- + {7, 6, 6, 5}, {7, 6, 6, 5}, {7, 6, 6, 6},
- + },
- +};
- +
- +uint8_t get_rx_bias(const struct sysinfo *ctrl)
- +{
- + const bool is_ult = is_hsw_ult();
- + const bool vddhi = ctrl->vdd_mv > 1350;
- + const uint8_t max_rxf = is_ult ? ARRAY_SIZE(rxb_ultx[0]) : ARRAY_SIZE(rxb_trad[0]);
- + const uint8_t ref_clk = ctrl->base_freq == 133 ? 4 : 6;
- + const uint8_t rx_f = clamp_s8(0, ctrl->multiplier - ref_clk, max_rxf - 1);
- + const uint8_t rx_cb = mchbar_read32(DDR_CLK_CB_STATUS) & 0x3;
- + if (is_ult)
- + return rxb_ultx[vddhi][rx_f][rx_cb];
- + else
- + return rxb_trad[vddhi][rx_f][rx_cb];
- +}
- +
- +static void program_ddr_data(struct sysinfo *ctrl, const bool dis_odt_static, const bool vddhi)
- +{
- + const bool is_ult = is_hsw_ult();
- +
- + for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) {
- + if (!does_rank_exist(ctrl, rank))
- + continue;
- +
- + const union ddr_data_rx_train_rank_reg rx_train = {
- + .rcven = 64,
- + .dqs_p = 32,
- + .dqs_n = 32,
- + };
- + mchbar_write32(DDR_DATA_RX_TRAIN_RANK(rank), rx_train.raw);
- + mchbar_write32(DDR_DATA_RX_PER_BIT_RANK(rank), 0x88888888);
- +
- + const union ddr_data_tx_train_rank_reg tx_train = {
- + .tx_eq = TXEQFULLDRV | 11,
- + .dq_delay = 96,
- + .dqs_delay = 64,
- + };
- + mchbar_write32(DDR_DATA_TX_TRAIN_RANK(rank), tx_train.raw);
- + mchbar_write32(DDR_DATA_TX_PER_BIT_RANK(rank), 0x88888888);
- +
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
- + ctrl->tx_dq[channel][rank][byte] = tx_train.dq_delay;
- + ctrl->txdqs[channel][rank][byte] = tx_train.dqs_delay;
- + ctrl->tx_eq[channel][rank][byte] = tx_train.tx_eq;
- +
- + ctrl->rcven[channel][rank][byte] = rx_train.rcven;
- + ctrl->rxdqsp[channel][rank][byte] = rx_train.dqs_p;
- + ctrl->rxdqsn[channel][rank][byte] = rx_train.dqs_n;
- + ctrl->rx_eq[channel][rank][byte] = rx_train.rx_eq;
- + }
- + }
- + }
- + mchbar_write32(DDR_DATA_TX_XTALK, 0);
- + mchbar_write32(DDR_DATA_RX_OFFSET_VDQ, 0x88888888);
- + mchbar_write32(DDR_DATA_OFFSET_TRAIN, 0);
- + mchbar_write32(DDR_DATA_OFFSET_COMP, 0);
- +
- + const union ddr_data_control_0_reg data_control_0 = {
- + .internal_clocks_on = !is_ult,
- + .data_vccddq_hi = vddhi,
- + .disable_odt_static = dis_odt_static,
- + .lpddr_mode = ctrl->lpddr,
- + .odt_samp_extend_en = ctrl->lpddr,
- + .early_rleak_en = ctrl->lpddr && ctrl->stepping >= STEPPING_C0,
- + };
- + mchbar_write32(DDR_DATA_CONTROL_0, data_control_0.raw);
- +
- + const union ddr_data_control_1_reg data_control_1 = {
- + .dll_mask = 1,
- + .rx_bias_ctl = get_rx_bias(ctrl),
- + .odt_delay = -2,
- + .odt_duration = 7,
- + .sense_amp_delay = -2,
- + .sense_amp_duration = 7,
- + };
- + mchbar_write32(DDR_DATA_CONTROL_1, data_control_1.raw);
- +
- + clear_data_offset_train_all(ctrl);
- +
- + /* Stagger byte turn-on to reduce dI/dT */
- + const uint8_t byte_stagger[] = { 0, 4, 1, 5, 2, 6, 3, 7, 8 };
- + const uint8_t latency = 2 * ctrl->tAA - 6;
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel))
- + continue;
- +
- + union ddr_data_control_2_reg data_control_2 = {
- + .raw = 0,
- + };
- + if (is_ult) {
- + data_control_2.rx_dqs_amp_offset = 8;
- + data_control_2.rx_clk_stg_num = 0x1f;
- + data_control_2.leaker_comp = ctrl->lpddr ? 3 : 0;
- + }
- + for (uint8_t byte = 0; byte < ctrl->lanes; byte++) {
- + const uint8_t stg = latency * byte_stagger[byte] / ctrl->lanes;
- + data_control_2.rx_stagger_ctl = stg & 0x1f;
- + mchbar_write32(DQ_CONTROL_2(channel, byte), data_control_2.raw);
- + ctrl->data_offset_comp[channel][byte] = 0;
- + ctrl->dq_control_1[channel][byte] = data_control_1.raw;
- + ctrl->dq_control_2[channel][byte] = data_control_2.raw;
- + }
- + ctrl->dq_control_0[channel] = data_control_0.raw;
- + }
- +}
- +
- +static void program_vsshi_control(struct sysinfo *ctrl, const uint16_t vsshi_mv)
- +{
- + const uint32_t vsshi_control_reg = is_hsw_ult() ? 0x366c : 0x306c;
- + const union ddr_comp_vsshi_control_reg ddr_vsshi_control = {
- + .vsshi_target = (vsshi_mv * 192) / ctrl->vdd_mv - 20,
- + .hi_bw_divider = 1,
- + .lo_bw_divider = 1,
- + .bw_error = 2,
- + .panic_driver_en = 1,
- + .panic_voltage = 24 / 8, /* Voltage in 8mV steps */
- + .gain_boost = 1,
- + };
- + mchbar_write32(vsshi_control_reg, ddr_vsshi_control.raw);
- + mchbar_write32(DDR_COMP_VSSHI_CONTROL, ddr_vsshi_control.raw);
- +}
- +
- +static void calc_vt_slope_code(const uint16_t slope, uint8_t *best_a, uint8_t *best_b)
- +{
- + const int16_t coding[] = {0, -125, -62, -31, 250, 125, 62, 31};
- + *best_a = 0;
- + *best_b = 0;
- + int16_t best_err = slope;
- + for (uint8_t b = 0; b < ARRAY_SIZE(coding); b++) {
- + for (uint8_t a = b; a < ARRAY_SIZE(coding); a++) {
- + int16_t error = slope - (coding[a] + coding[b]);
- + if (error < 0)
- + error = -error;
- +
- + if (error < best_err) {
- + best_err = error;
- + *best_a = a;
- + *best_b = b;
- + }
- + }
- + }
- +}
- +
- +static void program_dimm_vref(struct sysinfo *ctrl, const uint16_t vccio_mv, const bool vddhi)
- +{
- + const bool is_ult = is_hsw_ult();
- +
- + /* Static values for ULT */
- + uint8_t vt_slope_a = 4;
- + uint8_t vt_slope_b = 0;
- + if (!is_ult) {
- + /* On non-ULT, compute best slope code */
- + const uint16_t vt_slope = 1500 * vccio_mv / ctrl->vdd_mv - 1000;
- + calc_vt_slope_code(vt_slope, &vt_slope_a, &vt_slope_b);
- + }
- + const union ddr_data_vref_control_reg ddr_vref_control = {
- + .hi_bw_divider = is_ult ? 0 : 3,
- + .lo_bw_divider = 3,
- + .sample_divider = is_ult ? 1 : 3,
- + .slow_bw_error = 1,
- + .hi_bw_enable = 1,
- + .vt_slope_b = vt_slope_b,
- + .vt_slope_a = vt_slope_a,
- + .vt_offset = 0,
- + };
- + mchbar_write32(is_ult ? 0xf68 : 0xf6c, ddr_vref_control.raw); /* Use CH1 byte 7 */
- +
- + const union ddr_data_vref_adjust_reg ddr_vref_adjust = {
- + .en_dimm_vref_ca = 1,
- + .en_dimm_vref_ch0 = 1,
- + .en_dimm_vref_ch1 = 1,
- + .vccddq_hi_qnnn_h = vddhi,
- + .hi_z_timer_ctrl = 3,
- + };
- + ctrl->dimm_vref = ddr_vref_adjust;
- + mchbar_write32(DDR_DATA_VREF_ADJUST, ddr_vref_adjust.raw);
- +}
- +
- +static uint32_t pi_code(const uint32_t code)
- +{
- + return code << 21 | code << 14 | code << 7 | code << 0;
- +}
- +
- +static void program_ddr_ca(struct sysinfo *ctrl, const bool vddhi)
- +{
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel))
- + continue;
- +
- + const union ddr_clk_controls_reg ddr_clk_controls = {
- + .dll_mask = 1,
- + .vccddq_hi = vddhi,
- + .lpddr_mode = ctrl->lpddr,
- + };
- + mchbar_write32(DDR_CLK_ch_CONTROLS(channel), ddr_clk_controls.raw);
- +
- + const union ddr_cmd_controls_reg ddr_cmd_controls = {
- + .dll_mask = 1,
- + .vccddq_hi = vddhi,
- + .lpddr_mode = ctrl->lpddr,
- + .early_weak_drive = 3,
- + .cmd_tx_eq = 1,
- + };
- + mchbar_write32(DDR_CMD_ch_CONTROLS(channel), ddr_cmd_controls.raw);
- +
- + const union ddr_cke_ctl_controls_reg ddr_cke_controls = {
- + .dll_mask = 1,
- + .vccddq_hi = vddhi,
- + .lpddr_mode = ctrl->lpddr,
- + .early_weak_drive = 3,
- + .cmd_tx_eq = 1,
- + .ctl_tx_eq = 1,
- + .ctl_sr_drv = 2,
- + };
- + mchbar_write32(DDR_CKE_ch_CTL_CONTROLS(channel), ddr_cke_controls.raw);
- +
- + const union ddr_cke_ctl_controls_reg ddr_ctl_controls = {
- + .dll_mask = 1,
- + .vccddq_hi = vddhi,
- + .lpddr_mode = ctrl->lpddr,
- + .ctl_tx_eq = 1,
- + .ctl_sr_drv = 2,
- + .la_drv_en_ovrd = 1, /* Must be set on ULT */
- + };
- + mchbar_write32(DDR_CTL_ch_CTL_CONTROLS(channel), ddr_ctl_controls.raw);
- +
- + const uint8_t cmd_pi = ctrl->lpddr ? 96 : 64;
- + mchbar_write32(DDR_CMD_ch_PI_CODING(channel), pi_code(cmd_pi));
- + mchbar_write32(DDR_CKE_ch_CMD_PI_CODING(channel), pi_code(cmd_pi));
- + mchbar_write32(DDR_CKE_CTL_ch_CTL_PI_CODING(channel), pi_code(64));
- + mchbar_write32(DDR_CLK_ch_PI_CODING(channel), pi_code(64));
- +
- + mchbar_write32(DDR_CMD_ch_COMP_OFFSET(channel), 0);
- + mchbar_write32(DDR_CLK_ch_COMP_OFFSET(channel), 0);
- + mchbar_write32(DDR_CKE_CTL_ch_CTL_COMP_OFFSET(channel), 0);
- +
- + for (uint8_t group = 0; group < NUM_GROUPS; group++) {
- + ctrl->cke_cmd_pi_code[channel][group] = cmd_pi;
- + ctrl->cmd_north_pi_code[channel][group] = cmd_pi;
- + ctrl->cmd_south_pi_code[channel][group] = cmd_pi;
- + }
- + for (uint8_t rank = 0; rank < NUM_SLOTRANKS; rank++) {
- + ctrl->clk_pi_code[channel][rank] = 64;
- + ctrl->ctl_pi_code[channel][rank] = 64;
- + }
- + }
- +}
- +
- +enum {
- + RCOMP_RD_ODT = 0,
- + RCOMP_WR_DS_DQ,
- + RCOMP_WR_DS_CMD,
- + RCOMP_WR_DS_CTL,
- + RCOMP_WR_DS_CLK,
- + RCOMP_MAX_CODES,
- +};
- +
- +struct rcomp_info {
- + uint8_t resistor;
- + uint8_t sz_steps;
- + uint8_t target_r;
- + int8_t result;
- +};
- +
- +static void program_rcomp_vref(struct sysinfo *ctrl, const bool dis_odt_static)
- +{
- + const bool is_ult = is_hsw_ult();
- + /*
- + * +-------------------------------+
- + * | Rcomp resistor values in ohms |
- + * +-----------+------+------+-----+
- + * | Ball name | Trad | ULTX | Use |
- + * +-----------+------+------+-----+
- + * | SM_RCOMP0 | 100 | 200 | CMD |
- + * | SM_RCOMP1 | 75 | 120 | DQ |
- + * | SM_RCOMP2 | 100 | 100 | ODT |
- + * +-----------+------+------+-----+
- + */
- + struct rcomp_info rcomp_cfg[RCOMP_MAX_CODES] = {
- + [RCOMP_RD_ODT] = {
- + .resistor = 50,
- + .sz_steps = 96,
- + .target_r = 50,
- + },
- + [RCOMP_WR_DS_DQ] = {
- + .resistor = 25,
- + .sz_steps = 64,
- + .target_r = 33,
- + },
- + [RCOMP_WR_DS_CMD] = {
- + .resistor = 20,
- + .sz_steps = 64,
- + .target_r = 20,
- + },
- + [RCOMP_WR_DS_CTL] = {
- + .resistor = 20,
- + .sz_steps = 64,
- + .target_r = 20,
- + },
- + [RCOMP_WR_DS_CLK] = {
- + .resistor = 25,
- + .sz_steps = 64,
- + .target_r = 29,
- + },
- + };
- + if (is_ult) {
- + rcomp_cfg[RCOMP_WR_DS_DQ].resistor = 40;
- + rcomp_cfg[RCOMP_WR_DS_DQ].target_r = 40;
- + rcomp_cfg[RCOMP_WR_DS_CLK].resistor = 40;
- + } else if (ctrl->dpc[0] == 2 || ctrl->dpc[1] == 2) {
- + rcomp_cfg[RCOMP_RD_ODT].target_r = 60;
- + }
- + for (uint8_t i = 0; i < RCOMP_MAX_CODES; i++) {
- + struct rcomp_info *const r = &rcomp_cfg[i];
- + const int32_t div = 2 * (r->resistor + r->target_r);
- + assert(div);
- + const int32_t vref = (r->sz_steps * (r->resistor - r->target_r)) / div;
- +
- + /* DqOdt is 5 bits wide, the other Rcomp targets are 4 bits wide */
- + const int8_t comp_limit = i == RCOMP_RD_ODT ? 16 : 8;
- + r->result = clamp_s32(-comp_limit, vref, comp_limit - 1);
- + }
- + const union ddr_comp_ctl_0_reg ddr_comp_ctl_0 = {
- + .disable_odt_static = dis_odt_static,
- + .dq_drv_vref = rcomp_cfg[RCOMP_WR_DS_DQ].result,
- + .dq_odt_vref = rcomp_cfg[RCOMP_RD_ODT].result,
- + .cmd_drv_vref = rcomp_cfg[RCOMP_WR_DS_CMD].result,
- + .ctl_drv_vref = rcomp_cfg[RCOMP_WR_DS_CTL].result,
- + .clk_drv_vref = rcomp_cfg[RCOMP_WR_DS_CLK].result,
- + };
- + ctrl->comp_ctl_0 = ddr_comp_ctl_0;
- + mchbar_write32(DDR_COMP_CTL_0, ctrl->comp_ctl_0.raw);
- +}
- +
- +enum {
- + SCOMP_DQ = 0,
- + SCOMP_CMD,
- + SCOMP_CTL,
- + SCOMP_CLK,
- + SCOMP_MAX_CODES,
- +};
- +
- +static void program_slew_rates(struct sysinfo *ctrl, const bool vddhi)
- +{
- + const uint8_t min_cycle_delay[SCOMP_MAX_CODES] = { 46, 70, 70, 46 };
- + uint8_t buffer_stage_delay_ps[SCOMP_MAX_CODES] = { 59, 53, 53, 53 };
- + uint16_t comp_slew_rate_codes[SCOMP_MAX_CODES];
- +
- + /* CMD Slew Rate = 1.8 for 2N */
- + if (ctrl->tCMD == 2)
- + buffer_stage_delay_ps[SCOMP_CMD] = 89;
- +
- + /* CMD Slew Rate = 4 V/ns for double-pumped CMD bus */
- + if (ctrl->lpddr)
- + buffer_stage_delay_ps[SCOMP_CMD] = 63;
- +
- + for (uint8_t i = 0; i < SCOMP_MAX_CODES; i++) {
- + uint16_t stages = DIV_ROUND_CLOSEST(ctrl->qclkps, buffer_stage_delay_ps[i]);
- + if (stages < 5)
- + stages = 5;
- +
- + bool dll_pc = buffer_stage_delay_ps[i] < min_cycle_delay[i] || stages > 16;
- +
- + /* Lock DLL... */
- + if (dll_pc)
- + comp_slew_rate_codes[i] = stages / 2 - 1; /* to a phase */
- + else
- + comp_slew_rate_codes[i] = (stages - 1) | BIT(4); /* to a cycle */
- + }
- + union ddr_comp_ctl_1_reg ddr_comp_ctl_1 = {
- + .dq_scomp = comp_slew_rate_codes[SCOMP_DQ],
- + .cmd_scomp = comp_slew_rate_codes[SCOMP_CMD],
- + .ctl_scomp = comp_slew_rate_codes[SCOMP_CTL],
- + .clk_scomp = comp_slew_rate_codes[SCOMP_CLK],
- + .vccddq_hi = vddhi,
- + };
- + ctrl->comp_ctl_1 = ddr_comp_ctl_1;
- + mchbar_write32(DDR_COMP_CTL_1, ctrl->comp_ctl_1.raw);
- +}
- +
- +static uint32_t ln_x100(const uint32_t input_x100)
- +{
- + uint32_t val = input_x100;
- + uint32_t ret = 0;
- + while (val > 271) {
- + val = (val * 1000) / 2718;
- + ret += 100;
- + }
- + return ret + (-16 * val * val + 11578 * val - 978860) / 10000;
- +}
- +
- +static uint32_t compute_vsshi_vref(struct sysinfo *ctrl, const uint32_t vsshi_tgt, bool up)
- +{
- + const uint32_t delta = 15;
- + const uint32_t c_die_vsshi = 2000;
- + const uint32_t r_cmd_ref = 100 * 10;
- + const uint32_t offset = up ? 64 : 0;
- + const uint32_t ln_vsshi = ln_x100((100 * vsshi_tgt) / (vsshi_tgt - delta));
- + const uint32_t r_target = (ctrl->qclkps * 2000) / (c_die_vsshi * ln_vsshi);
- + const uint32_t r_dividend = 128 * (up ? r_cmd_ref : r_target);
- + return r_dividend / (r_cmd_ref + r_target) - offset;
- +}
- +
- +static void program_vsshi(struct sysinfo *ctrl, const uint16_t vccio_mv, const uint16_t vsshi)
- +{
- + const uint16_t vsshi_down = vsshi + 24; /* Panic threshold of 24 mV */
- + const uint16_t vsshi_up = vccio_mv - vsshi_down;
- + const union ddr_comp_vsshi_reg ddr_comp_vsshi = {
- + .panic_drv_down_vref = compute_vsshi_vref(ctrl, vsshi_down, false),
- + .panic_drv_up_vref = compute_vsshi_vref(ctrl, vsshi_up, true),
- + .vt_offset = 128 * 450 / vccio_mv / 2,
- + .vt_slope_a = 4,
- + };
- + mchbar_write32(DDR_COMP_VSSHI, ddr_comp_vsshi.raw);
- +}
- +
- +static void program_misc(struct sysinfo *ctrl)
- +{
- + ctrl->misc_control_0.raw = mchbar_read32(DDR_SCRAM_MISC_CONTROL);
- + ctrl->misc_control_0.weaklock_latency = 12;
- + ctrl->misc_control_0.wl_sleep_cycles = 5;
- + ctrl->misc_control_0.wl_wake_cycles = 2;
- + mchbar_write32(DDR_SCRAM_MISC_CONTROL, ctrl->misc_control_0.raw);
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + /* Keep scrambling disabled for training */
- + mchbar_write32(DDR_SCRAMBLE_ch(channel), 0);
- + }
- +}
- +
- +/* Very weird, application-specific function */
- +static void override_comp(uint32_t value, uint32_t width, uint32_t shift, uint32_t offset)
- +{
- + const uint32_t mask = (1 << width) - 1;
- + uint32_t reg32 = mchbar_read32(offset);
- + reg32 &= ~(mask << shift);
- + reg32 |= (value << shift);
- + mchbar_write32(offset, reg32);
- +}
- +
- +static void program_ls_comp(struct sysinfo *ctrl)
- +{
- + /* Disable periodic COMP */
- + const union pcu_comp_reg m_comp = {
- + .comp_disable = 1,
- + .comp_interval = COMP_INT,
- + .comp_force = 1,
- + };
- + mchbar_write32(M_COMP, m_comp.raw);
- + udelay(10);
- +
- + /* Override level shifter compensation */
- + const uint32_t ls_comp = 2;
- + override_comp(ls_comp, 3, 28, DDR_DATA_RCOMP_DATA_1);
- + override_comp(ls_comp, 3, 24, DDR_CMD_COMP);
- + override_comp(ls_comp, 3, 24, DDR_CKE_CTL_COMP);
- + override_comp(ls_comp, 3, 23, DDR_CLK_COMP);
- + override_comp(ls_comp, 3, 28, DDR_COMP_DATA_COMP_1);
- + override_comp(ls_comp, 3, 24, DDR_COMP_CMD_COMP);
- + override_comp(ls_comp, 4, 24, DDR_COMP_CTL_COMP);
- + override_comp(ls_comp, 4, 23, DDR_COMP_CLK_COMP);
- + override_comp(ls_comp, 3, 24, DDR_COMP_OVERRIDE);
- +
- + /* Manually update the COMP values */
- + union ddr_scram_misc_control_reg ddr_scram_misc_ctrl = ctrl->misc_control_0;
- + ddr_scram_misc_ctrl.force_comp_update = 1;
- + mchbar_write32(DDR_SCRAM_MISC_CONTROL, ddr_scram_misc_ctrl.raw);
- +
- + /* Use a fixed offset between ODT Up/Dn */
- + const union ddr_comp_data_comp_1_reg data_comp_1 = {
- + .raw = mchbar_read32(DDR_COMP_DATA_COMP_1),
- + };
- + const uint32_t odt_offset = data_comp_1.rcomp_odt_down - data_comp_1.rcomp_odt_up;
- + ctrl->comp_ctl_0.odt_up_down_off = odt_offset;
- + ctrl->comp_ctl_0.fixed_odt_offset = 1;
- + mchbar_write32(DDR_COMP_CTL_0, ctrl->comp_ctl_0.raw);
- +}
- +
- +/** TODO: Deduplicate PCODE stuff, it's already implemented in CPU code **/
- +static bool pcode_ready(void)
- +{
- + const unsigned int delay_step = 10;
- + for (unsigned int i = 0; i < 1000; i += delay_step) {
- + if (!(mchbar_read32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY))
- + return true;
- +
- + udelay(delay_step);
- + };
- + return false;
- +}
- +
- +static uint32_t pcode_mailbox_read(const uint32_t command)
- +{
- + if (!pcode_ready()) {
- + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready\n");
- + return 0;
- + }
- + mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY);
- + if (!pcode_ready()) {
- + printk(BIOS_ERR, "PCODE: mailbox timeout on completion\n");
- + return 0;
- + }
- + return mchbar_read32(BIOS_MAILBOX_DATA);
- +}
- +
- +static int pcode_mailbox_write(const uint32_t command, const uint32_t data)
- +{
- + if (!pcode_ready()) {
- + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready\n");
- + return -1;
- + }
- + mchbar_write32(BIOS_MAILBOX_DATA, data);
- + mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY);
- + if (!pcode_ready()) {
- + printk(BIOS_ERR, "PCODE: mailbox timeout on completion\n");
- + return -1;
- + }
- + return 0;
- +}
- +
- +static void enable_2x_refresh(struct sysinfo *ctrl)
- +{
- + if (!CONFIG(ENABLE_DDR_2X_REFRESH))
- + return;
- +
- + printk(BIOS_DEBUG, "Enabling 2x Refresh\n");
- + const bool asr = ctrl->flags.asr;
- + const bool lpddr = ctrl->lpddr;
- +
- + /* Mutually exclusive */
- + assert(!asr || !lpddr);
- + if (!asr) {
- + uint32_t reg32 = pcode_mailbox_read(MAILBOX_BIOS_CMD_READ_DDR_2X_REFRESH);
- + if (!(reg32 & BIT(31))) { /** TODO: What to do if this is locked? **/
- + reg32 |= BIT(0); /* Enable 2x refresh */
- + reg32 |= BIT(31); /* Lock */
- +
- + if (lpddr)
- + reg32 |= 4 << 1; /* LPDDR MR4 1/2 tREFI */
- +
- + if (pcode_mailbox_write(MAILBOX_BIOS_CMD_WRITE_DDR_2X_REFRESH, reg32))
- + printk(BIOS_ERR, "Could not enable Mailbox 2x Refresh\n");
- + }
- + if (!lpddr)
- + return;
- + }
- + assert(asr || lpddr);
- + uint16_t refi_reduction = 50;
- + if (lpddr) {
- + refi_reduction = 97;
- + mchbar_clrbits32(PCU_DDR_PTM_CTL, 1 << 7); /* DISABLE_DRAM_TS */
- + }
- + /** TODO: Remember why this is only done on cold boots **/
- + if (ctrl->bootmode == BOOTMODE_COLD) {
- + ctrl->tREFI *= refi_reduction;
- + ctrl->tREFI /= 100;
- + }
- +}
- +
- +static void set_pcu_ddr_voltage(const uint16_t vdd_mv)
- +{
- + /** TODO: Handle other voltages? **/
- + uint32_t pcu_ddr_voltage;
- + switch (vdd_mv) {
- + case 1200:
- + pcu_ddr_voltage = 3;
- + break;
- + case 1350:
- + pcu_ddr_voltage = 1;
- + break;
- + default:
- + case 1500:
- + pcu_ddr_voltage = 0;
- + break;
- + }
- + /* Set bits 0..2 */
- + mchbar_write32(PCU_DDR_VOLTAGE, pcu_ddr_voltage);
- +}
- +
- +static void program_scheduler(struct sysinfo *ctrl)
- +{
- + /*
- + * ZQ calibration needs to be serialized for LPDDR3. Otherwise,
- + * the processor issues LPDDR3 ZQ calibration in parallel when
- + * exiting Package C7 or deeper. This causes problems for dual
- + * and quad die packages since all ranks share the same ZQ pin.
- + *
- + * Erratum HSM94: LPDDR3 ZQ Calibration Following Deep Package
- + * C-state Exit May Lead to Unpredictable System Behavior
- + */
- + const union mcscheds_cbit_reg mcscheds_cbit = {
- + .dis_write_gap = 1,
- + .dis_odt = is_hsw_ult() && !(ctrl->lpddr && ctrl->lpddr_dram_odt),
- + .serialize_zq = ctrl->lpddr,
- + };
- + mchbar_write32(MCSCHEDS_CBIT, mcscheds_cbit.raw);
- + mchbar_write32(MCMNTS_SC_WDBWM, 0x553c3038);
- + if (ctrl->lpddr) {
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel))
- + continue;
- +
- + 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);
- + }
- + }
- +}
- +
- +static uint8_t biggest_channel(const struct sysinfo *const ctrl)
- +{
- + _Static_assert(NUM_CHANNELS == 2, "Code assumes exactly two channels");
- + return !!(ctrl->channel_size_mb[0] < ctrl->channel_size_mb[1]);
- +}
- +
- +static void dram_zones(struct sysinfo *ctrl)
- +{
- + /** TODO: Activate channel hash here, if enabled **/
- + const uint8_t biggest = biggest_channel(ctrl);
- + const uint8_t smaller = !biggest;
- +
- + /** TODO: Use stacked mode if Memory Trace is enabled **/
- + const union mad_chnl_reg mad_channel = {
- + .ch_a = biggest,
- + .ch_b = smaller,
- + .ch_c = 2,
- + .lpddr_mode = ctrl->lpddr,
- + };
- + mchbar_write32(MAD_CHNL, mad_channel.raw);
- +
- + const uint8_t channel_b_zone_size = ctrl->channel_size_mb[smaller] / 256;
- + const union mad_zr_reg mad_zr = {
- + .ch_b_double = channel_b_zone_size * 2,
- + .ch_b_single = channel_b_zone_size,
- + };
- + mchbar_write32(MAD_ZR, mad_zr.raw);
- +}
- +
- +static uint8_t biggest_dimm(const struct raminit_dimm_info *dimms)
- +{
- + _Static_assert(NUM_SLOTS <= 2, "Code assumes at most two DIMMs per channel.");
- + if (NUM_SLOTS == 1)
- + return 0;
- +
- + return !!(dimms[0].data.size_mb < dimms[1].data.size_mb);
- +}
- +
- +static void dram_dimm_mapping(struct sysinfo *ctrl)
- +{
- + for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
- + if (!does_ch_exist(ctrl, channel)) {
- + const union mad_dimm_reg mad_dimm = {
- + .rank_interleave = 1,
- + .enh_interleave = 1,
- + };
- + mchbar_write32(MAD_DIMM(channel), mad_dimm.raw);
- + continue;
- + }
- + const uint8_t biggest = biggest_dimm(ctrl->dimms[channel]);
- + const uint8_t smaller = !biggest;
- + const struct dimm_attr_ddr3_st *dimm_a = &ctrl->dimms[channel][biggest].data;
- + const struct dimm_attr_ddr3_st *dimm_b = &ctrl->dimms[channel][smaller].data;
- + union mad_dimm_reg mad_dimm = {
- + .dimm_a_size = dimm_a->size_mb / 256,
- + .dimm_b_size = dimm_b->size_mb / 256,
- + .dimm_a_sel = biggest,
- + .dimm_a_ranks = dimm_a->ranks == 2,
- + .dimm_b_ranks = dimm_b->ranks == 2,
- + .dimm_a_width = dimm_a->width == 16,
- + .dimm_b_width = dimm_b->width == 16,
- + .rank_interleave = 1,
- + .enh_interleave = 1,
- + .ecc_mode = 0, /* Do not enable ECC yet */
- + };
- + if (is_hsw_ult())
- + mad_dimm.dimm_b_width = mad_dimm.dimm_a_width;
- +
- + mchbar_write32(MAD_DIMM(channel), mad_dimm.raw);
- + if (ctrl->lpddr)
- + die("%s: Missing LPDDR support (LPDDR_MR_PARAMS)\n", __func__);
- + }
- +}
- +
- +enum raminit_status configure_mc(struct sysinfo *ctrl)
- +{
- + const uint16_t vccio_mv = 1000;
- + const uint16_t vsshi_mv = ctrl->vdd_mv - 950;
- + const bool dis_odt_static = is_hsw_ult(); /* Disable static ODT legs on ULT */
- + const bool vddhi = ctrl->vdd_mv > 1350;
- +
- + program_misc_control(ctrl);
- + program_mrc_revision();
- + program_ranks_used(ctrl);
- + program_ddr_data(ctrl, dis_odt_static, vddhi);
- + program_vsshi_control(ctrl, vsshi_mv);
- + program_dimm_vref(ctrl, vccio_mv, vddhi);
- + program_ddr_ca(ctrl, vddhi);
- + program_rcomp_vref(ctrl, dis_odt_static);
- + program_slew_rates(ctrl, vddhi);
- + program_vsshi(ctrl, vccio_mv, vsshi_mv);
- + program_misc(ctrl);
- + program_ls_comp(ctrl);
- + enable_2x_refresh(ctrl);
- + set_pcu_ddr_voltage(ctrl->vdd_mv);
- + configure_timings(ctrl);
- + configure_refresh(ctrl);
- + program_scheduler(ctrl);
- + dram_zones(ctrl);
- + dram_dimm_mapping(ctrl);
- +
- + 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 5f2be980d4..3a773cfa19 100644
- --- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c
- +++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
- @@ -23,6 +23,7 @@ static const struct task_entry cold_boot[] = {
- { collect_spd_info, true, "PROCSPD", },
- { initialise_mpll, true, "INITMPLL", },
- { convert_timings, true, "CONVTIM", },
- + { configure_mc, true, "CONFMC", },
- };
-
- /* Return a generic stepping value to make stepping checks simpler */
- @@ -54,6 +55,7 @@ static void initialize_ctrl(struct sysinfo *ctrl)
-
- ctrl->cpu = cpu_get_cpuid();
- ctrl->stepping = get_stepping(ctrl->cpu);
- + ctrl->vdd_mv = is_hsw_ult() ? 1350 : 1500; /** FIXME: Hardcoded, does it matter? **/
- ctrl->dq_pins_interleaved = cfg->dq_pins_interleaved;
- ctrl->bootmode = bootmode;
- }
- diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- index 01e5ed1bd6..aa86b9aa39 100644
- --- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- +++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
- @@ -3,15 +3,40 @@
- #ifndef HASWELL_RAMINIT_NATIVE_H
- #define HASWELL_RAMINIT_NATIVE_H
-
- +#include <assert.h>
- #include <device/dram/ddr3.h>
- #include <northbridge/intel/haswell/haswell.h>
- +#include <string.h>
- +#include <types.h>
- +
- +#include "reg_structs.h"
-
- #define SPD_LEN 256
-
- +/* Each channel has 4 ranks, spread across 2 slots */
- +#define NUM_SLOTRANKS 4
- +
- +#define NUM_GROUPS 2
- +
- /* 8 data lanes + 1 ECC lane */
- #define NUM_LANES 9
- #define NUM_LANES_NO_ECC 8
-
- +#define COMP_INT 10
- +
- +/* Always use 12 legs for emphasis (not trained) */
- +#define TXEQFULLDRV (3 << 4)
- +
- +enum command_training_iteration {
- + CT_ITERATION_CLOCK = 0,
- + CT_ITERATION_CMD_NORTH,
- + CT_ITERATION_CMD_SOUTH,
- + CT_ITERATION_CKE,
- + CT_ITERATION_CTL,
- + CT_ITERATION_CMD_VREF,
- + MAX_CT_ITERATION,
- +};
- +
- enum raminit_boot_mode {
- BOOTMODE_COLD,
- BOOTMODE_WARM,
- @@ -57,6 +82,9 @@ struct sysinfo {
- * LPDDR-specific functions have stubs which will halt upon execution.
- */
- bool lpddr;
- + bool lpddr_dram_odt;
- + uint8_t lpddr_cke_rank_map[NUM_CHANNELS];
- + uint8_t dq_byte_map[NUM_CHANNELS][MAX_CT_ITERATION][2];
-
- struct raminit_dimm_info dimms[NUM_CHANNELS][NUM_SLOTS];
- union dimm_flags_ddr3_st flags;
- @@ -93,16 +121,89 @@ struct sysinfo {
- uint32_t mem_clock_mhz;
- uint32_t mem_clock_fs; /* Memory clock period in femtoseconds */
- uint32_t qclkps; /* Quadrature clock period in picoseconds */
- +
- + uint16_t vdd_mv;
- +
- + union ddr_scram_misc_control_reg misc_control_0;
- +
- + union ddr_comp_ctl_0_reg comp_ctl_0;
- + union ddr_comp_ctl_1_reg comp_ctl_1;
- +
- + union ddr_data_vref_adjust_reg dimm_vref;
- +
- + uint32_t data_offset_train[NUM_CHANNELS][NUM_LANES];
- + uint32_t data_offset_comp[NUM_CHANNELS][NUM_LANES];
- +
- + uint32_t dq_control_0[NUM_CHANNELS];
- + uint32_t dq_control_1[NUM_CHANNELS][NUM_LANES];
- + uint32_t dq_control_2[NUM_CHANNELS][NUM_LANES];
- +
- + uint16_t tx_dq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + uint16_t txdqs[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + uint8_t tx_eq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- +
- + uint16_t rcven[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + uint8_t rx_eq[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + uint8_t rxdqsp[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + uint8_t rxdqsn[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- + int8_t rxvref[NUM_CHANNELS][NUM_SLOTRANKS][NUM_LANES];
- +
- + uint8_t clk_pi_code[NUM_CHANNELS][NUM_SLOTRANKS];
- + uint8_t ctl_pi_code[NUM_CHANNELS][NUM_SLOTRANKS];
- + uint8_t cke_pi_code[NUM_CHANNELS][NUM_SLOTRANKS];
- +
- + 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];
- };
-
- +static inline bool is_hsw_ult(void)
- +{
- + return CONFIG(INTEL_LYNXPOINT_LP);
- +}
- +
- +static inline bool rank_in_mask(uint8_t rank, uint8_t rankmask)
- +{
- + assert(rank < NUM_SLOTRANKS);
- + return !!(BIT(rank) & rankmask);
- +}
- +
- +static inline bool does_ch_exist(const struct sysinfo *ctrl, uint8_t channel)
- +{
- + return !!ctrl->dpc[channel];
- +}
- +
- +static inline bool does_rank_exist(const struct sysinfo *ctrl, uint8_t rank)
- +{
- + return rank_in_mask(rank, ctrl->rankmap[0] | ctrl->rankmap[1]);
- +}
- +
- +static inline bool rank_in_ch(const struct sysinfo *ctrl, uint8_t rank, uint8_t channel)
- +{
- + assert(channel < NUM_CHANNELS);
- + return rank_in_mask(rank, ctrl->rankmap[channel]);
- +}
- +
- +/** TODO: Handling of data_offset_train could be improved, also coupled with reg updates **/
- +static inline void clear_data_offset_train_all(struct sysinfo *ctrl)
- +{
- + memset(ctrl->data_offset_train, 0, sizeof(ctrl->data_offset_train));
- +}
- +
- void raminit_main(enum raminit_boot_mode bootmode);
-
- enum raminit_status collect_spd_info(struct sysinfo *ctrl);
- enum raminit_status initialise_mpll(struct sysinfo *ctrl);
- enum raminit_status convert_timings(struct sysinfo *ctrl);
- +enum raminit_status configure_mc(struct sysinfo *ctrl);
- +
- +void configure_timings(struct sysinfo *ctrl);
- +void configure_refresh(struct sysinfo *ctrl);
-
- enum raminit_status wait_for_first_rcomp(void);
-
- +uint8_t get_rx_bias(const struct sysinfo *ctrl);
- +
- uint8_t get_tCWL(uint32_t mem_clock_mhz);
- uint32_t get_tREFI(uint32_t mem_clock_mhz);
- uint32_t get_tXP(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
- new file mode 100644
- index 0000000000..d11cda4b3d
- --- /dev/null
- +++ b/src/northbridge/intel/haswell/native_raminit/reg_structs.h
- @@ -0,0 +1,405 @@
- +/* SPDX-License-Identifier: GPL-2.0-or-later */
- +
- +#ifndef HASWELL_RAMINIT_REG_STRUCTS_H
- +#define HASWELL_RAMINIT_REG_STRUCTS_H
- +
- +union ddr_data_rx_train_rank_reg {
- + struct __packed {
- + uint32_t rcven : 9; // Bits 8:0
- + uint32_t dqs_p : 6; // Bits 14:9
- + uint32_t rx_eq : 5; // Bits 19:15
- + uint32_t dqs_n : 6; // Bits 25:20
- + int32_t vref : 6; // Bits 31:26
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_data_tx_train_rank_reg {
- + struct __packed {
- + uint32_t dq_delay : 9; // Bits 8:0
- + uint32_t dqs_delay : 9; // Bits 17:9
- + uint32_t : 2; // Bits 19:18
- + uint32_t tx_eq : 6; // Bits 25:20
- + uint32_t : 6; // Bits 31:26
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_data_control_0_reg {
- + struct __packed {
- + uint32_t rx_training_mode : 1; // Bits 0:0
- + uint32_t wl_training_mode : 1; // Bits 1:1
- + uint32_t rl_training_mode : 1; // Bits 2:2
- + uint32_t samp_train_mode : 1; // Bits 3:3
- + uint32_t tx_on : 1; // Bits 4:4
- + uint32_t rf_on : 1; // Bits 5:5
- + uint32_t rx_pi_on : 1; // Bits 6:6
- + uint32_t tx_pi_on : 1; // Bits 7:7
- + uint32_t internal_clocks_on : 1; // Bits 8:8
- + uint32_t repeater_clocks_on : 1; // Bits 9:9
- + uint32_t tx_disable : 1; // Bits 10:10
- + uint32_t rx_disable : 1; // Bits 11:11
- + uint32_t tx_long : 1; // Bits 12:12
- + uint32_t rx_dqs_ctle : 2; // Bits 14:13
- + uint32_t rx_read_pointer : 3; // Bits 17:15
- + uint32_t driver_segment_enable : 1; // Bits 18:18
- + uint32_t data_vccddq_hi : 1; // Bits 19:19
- + uint32_t read_rf_rd : 1; // Bits 20:20
- + uint32_t read_rf_wr : 1; // Bits 21:21
- + uint32_t read_rf_rank : 2; // Bits 23:22
- + uint32_t force_odt_on : 1; // Bits 24:24
- + uint32_t odt_samp_off : 1; // Bits 25:25
- + uint32_t disable_odt_static : 1; // Bits 26:26
- + uint32_t ddr_cr_force_odt_on : 1; // Bits 27:27
- + uint32_t lpddr_mode : 1; // Bits 28:28
- + uint32_t en_read_preamble : 1; // Bits 29:29
- + uint32_t odt_samp_extend_en : 1; // Bits 30:30
- + uint32_t early_rleak_en : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_data_control_1_reg {
- + struct __packed {
- + int32_t ref_pi : 4; // Bits 3:0
- + uint32_t dll_mask : 2; // Bits 5:4
- + uint32_t dll_weaklock : 1; // Bits 6:6
- + uint32_t sdll_segment_disable : 3; // Bits 9:7
- + uint32_t rx_bias_ctl : 3; // Bits 12:10
- + int32_t odt_delay : 4; // Bits 16:13
- + uint32_t odt_duration : 3; // Bits 19:17
- + int32_t sense_amp_delay : 4; // Bits 23:20
- + uint32_t sense_amp_duration : 3; // Bits 26:24
- + uint32_t burst_end_odt_delay : 3; // Bits 29:27 *** TODO: Check Broadwell ***
- + uint32_t lpddr_long_odt_en : 1; // Bits 30:30
- + uint32_t : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +/* NOTE: Bits 31:19 are only valid for Broadwell onwards */
- +union ddr_data_control_2_reg {
- + struct __packed {
- + uint32_t rx_stagger_ctl : 5; // Bits 4:0
- + uint32_t force_bias_on : 1; // Bits 5:5
- + uint32_t force_rx_on : 1; // Bits 6:6
- + uint32_t leaker_comp : 2; // Bits 8:7
- + uint32_t rx_dqs_amp_offset : 4; // Bits 12:9
- + uint32_t rx_clk_stg_num : 5; // Bits 17:13
- + uint32_t wl_long_delay : 1; // Bits 18:18
- + uint32_t enable_vref_pwrdn : 1; // Bits 19:19
- + uint32_t ddr4_mode : 1; // Bits 20:20
- + uint32_t en_vddq_odt : 1; // Bits 21:21
- + uint32_t en_vtt_odt : 1; // Bits 22:22
- + uint32_t en_const_z_eq_tx : 1; // Bits 23:23
- + uint32_t tx_eq_dis : 1; // Bits 24:24
- + uint32_t rx_vref_prog_mfc : 1; // Bits 25:25
- + uint32_t cben : 3; // Bits 28:26
- + uint32_t tx_deskew_disable : 1; // Bits 29:29
- + uint32_t rx_deskew_disable : 1; // Bits 30:30
- + uint32_t dq_slew_dly_byp : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_comp_data_comp_1_reg {
- + struct __packed {
- + uint32_t rcomp_odt_up : 6; // Bits 5:0
- + uint32_t : 3; // Bits 8:6
- + uint32_t rcomp_odt_down : 6; // Bits 14:9
- + uint32_t : 1; // Bits 15:15
- + uint32_t panic_drv_down : 6; // Bits 21:16
- + uint32_t panic_drv_up : 6; // Bits 27:22
- + uint32_t ls_comp : 3; // Bits 30:28
- + uint32_t : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_comp_ctl_0_reg {
- + struct __packed {
- + uint32_t : 3; // Bits 2:0
- + uint32_t disable_odt_static : 1; // Bits 3:3
- + uint32_t odt_up_down_off : 6; // Bits 9:4
- + uint32_t fixed_odt_offset : 1; // Bits 10:10
- + int32_t dq_drv_vref : 4; // Bits 14:11
- + int32_t dq_odt_vref : 5; // Bits 19:15
- + int32_t cmd_drv_vref : 4; // Bits 23:20
- + int32_t ctl_drv_vref : 4; // Bits 27:24
- + int32_t clk_drv_vref : 4; // Bits 31:28
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_comp_ctl_1_reg {
- + struct __packed {
- + uint32_t dq_scomp : 5; // Bits 4:0
- + uint32_t cmd_scomp : 5; // Bits 9:5
- + uint32_t ctl_scomp : 5; // Bits 14:10
- + uint32_t clk_scomp : 5; // Bits 19:15
- + uint32_t tco_cmd_offset : 4; // Bits 23:20
- + uint32_t comp_clk_on : 1; // Bits 24:24
- + uint32_t vccddq_hi : 1; // Bits 25:25
- + uint32_t : 3; // Bits 28:26
- + uint32_t dis_quick_comp : 1; // Bits 29:29
- + uint32_t sin_step : 1; // Bits 30:30
- + uint32_t sin_step_adv : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_data_vref_adjust_reg {
- + struct __packed {
- + int32_t ca_vref_ctrl : 7;// Bits 6:0
- + int32_t ch1_vref_ctrl : 7;// Bits 13:7
- + int32_t ch0_vref_ctrl : 7;// Bits 20:14
- + uint32_t en_dimm_vref_ca : 1;// Bits 21:21
- + uint32_t en_dimm_vref_ch1 : 1;// Bits 22:22
- + uint32_t en_dimm_vref_ch0 : 1;// Bits 23:23
- + uint32_t hi_z_timer_ctrl : 2;// Bits 25:24
- + uint32_t vccddq_hi_qnnn_h : 1;// Bits 26:26
- + uint32_t : 2;// Bits 28:27
- + uint32_t ca_slow_bw : 1;// Bits 29:29
- + uint32_t ch0_slow_bw : 1;// Bits 30:30
- + uint32_t ch1_slow_bw : 1;// Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_data_vref_control_reg {
- + struct __packed {
- + uint32_t hi_bw_divider : 2; // Bits 1:0
- + uint32_t lo_bw_divider : 2; // Bits 3:2
- + uint32_t sample_divider : 3; // Bits 6:4
- + uint32_t open_loop : 1; // Bits 7:7
- + uint32_t slow_bw_error : 2; // Bits 9:8
- + uint32_t hi_bw_enable : 1; // Bits 10:10
- + uint32_t : 1; // Bits 11:11
- + uint32_t vt_slope_b : 3; // Bits 14:12
- + uint32_t vt_slope_a : 3; // Bits 17:15
- + uint32_t vt_offset : 3; // Bits 20:18
- + uint32_t sel_code : 3; // Bits 23:21
- + uint32_t output_code : 8; // Bits 31:24
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_comp_vsshi_reg {
- + struct __packed {
- + uint32_t panic_drv_down_vref : 6; // Bits 5:0
- + uint32_t panic_drv_up_vref : 6; // Bits 11:6
- + uint32_t vt_offset : 5; // Bits 16:12
- + uint32_t vt_slope_a : 3; // Bits 19:17
- + uint32_t vt_slope_b : 3; // Bits 22:20
- + uint32_t : 9; // Bits 31:23
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_comp_vsshi_control_reg {
- + struct __packed {
- + uint32_t vsshi_target : 6; // Bits 5:0
- + uint32_t hi_bw_divider : 2; // Bits 7:6
- + uint32_t lo_bw_divider : 2; // Bits 9:8
- + uint32_t sample_divider : 3; // Bits 12:10
- + uint32_t open_loop : 1; // Bits 13:13
- + uint32_t bw_error : 2; // Bits 15:14
- + uint32_t panic_driver_en : 1; // Bits 16:16
- + uint32_t : 1; // Bits 17:17
- + uint32_t panic_voltage : 4; // Bits 21:18
- + uint32_t gain_boost : 1; // Bits 22:22
- + uint32_t sel_code : 1; // Bits 23:23
- + uint32_t output_code : 8; // Bits 31:24
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_clk_controls_reg {
- + struct __packed {
- + uint32_t ref_pi : 4; // Bits 3:0
- + uint32_t dll_mask : 2; // Bits 5:4
- + uint32_t : 1; // Bits 6:6
- + uint32_t tx_on : 1; // Bits 7:7
- + uint32_t internal_clocks_on : 1; // Bits 8:8
- + uint32_t repeater_clocks_on : 1; // Bits 9:9
- + uint32_t io_lb_ctl : 2; // Bits 11:10
- + uint32_t odt_mode : 1; // Bits 12:12
- + uint32_t : 8; // Bits 20:13
- + uint32_t rx_vref : 6; // Bits 26:21
- + uint32_t vccddq_hi : 1; // Bits 27:27
- + uint32_t dll_weaklock : 1; // Bits 28:28
- + uint32_t lpddr_mode : 1; // Bits 29:29
- + uint32_t : 2; // Bits 31:30
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_cmd_controls_reg {
- + struct __packed {
- + int32_t ref_pi : 4; // Bits 3:0
- + uint32_t dll_mask : 2; // Bits 5:4
- + uint32_t : 1; // Bits 6:6
- + uint32_t tx_on : 1; // Bits 7:7
- + uint32_t internal_clocks_on : 1; // Bits 8:8
- + uint32_t repeater_clocks_on : 1; // Bits 9:9
- + uint32_t io_lb_ctl : 2; // Bits 11:10
- + uint32_t odt_mode : 1; // Bits 12:12
- + uint32_t cmd_tx_eq : 2; // Bits 14:13
- + uint32_t early_weak_drive : 2; // Bits 16:15
- + uint32_t : 4; // Bits 20:17
- + int32_t rx_vref : 6; // Bits 26:21
- + uint32_t vccddq_hi : 1; // Bits 27:27
- + uint32_t dll_weaklock : 1; // Bits 28:28
- + uint32_t lpddr_mode : 1; // Bits 29:29
- + uint32_t lpddr_ca_a_dis : 1; // Bits 30:30
- + uint32_t lpddr_ca_b_dis : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +/* Same register definition for CKE and CTL fubs */
- +union ddr_cke_ctl_controls_reg {
- + struct __packed {
- + int32_t ref_pi : 4; // Bits 3:0
- + uint32_t dll_mask : 2; // Bits 5:4
- + uint32_t : 1; // Bits 6:6
- + uint32_t tx_on : 1; // Bits 7:7
- + uint32_t internal_clocks_on : 1; // Bits 8:8
- + uint32_t repeater_clocks_on : 1; // Bits 9:9
- + uint32_t io_lb_ctl : 2; // Bits 11:10
- + uint32_t odt_mode : 1; // Bits 12:12
- + uint32_t cmd_tx_eq : 2; // Bits 14:13
- + uint32_t early_weak_drive : 2; // Bits 16:15
- + uint32_t ctl_tx_eq : 2; // Bits 18:17
- + uint32_t ctl_sr_drv : 2; // Bits 20:19
- + int32_t rx_vref : 6; // Bits 26:21
- + uint32_t vccddq_hi : 1; // Bits 27:27
- + uint32_t dll_weaklock : 1; // Bits 28:28
- + uint32_t lpddr_mode : 1; // Bits 29:29
- + uint32_t la_drv_en_ovrd : 1; // Bits 30:30
- + uint32_t lpddr_ca_a_dis : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union ddr_scram_misc_control_reg {
- + struct __packed {
- + uint32_t wl_wake_cycles : 2; // Bits 1:0
- + uint32_t wl_sleep_cycles : 3; // Bits 4:2
- + uint32_t force_comp_update : 1; // Bits 5:5
- + uint32_t weaklock_latency : 4; // Bits 9:6
- + uint32_t ddr_no_ch_interleave : 1; // Bits 10:10
- + uint32_t lpddr_mode : 1; // Bits 11:11
- + uint32_t cke_mapping_ch0 : 4; // Bits 15:12
- + uint32_t cke_mapping_ch1 : 4; // Bits 19:16
- + uint32_t : 12; // Bits 31:20
- + };
- + uint32_t raw;
- +};
- +
- +union mcscheds_cbit_reg {
- + struct __packed {
- + uint32_t dis_opp_cas : 1; // Bits 0:0
- + uint32_t dis_opp_is_cas : 1; // Bits 1:1
- + uint32_t dis_opp_ras : 1; // Bits 2:2
- + uint32_t dis_opp_is_ras : 1; // Bits 3:3
- + uint32_t dis_1c_byp : 1; // Bits 4:4
- + uint32_t dis_2c_byp : 1; // Bits 5:5
- + uint32_t dis_deprd_opt : 1; // Bits 6:6
- + uint32_t dis_pt_it : 1; // Bits 7:7
- + uint32_t dis_prcnt_ring : 1; // Bits 8:8
- + uint32_t dis_prcnt_sa : 1; // Bits 9:9
- + uint32_t dis_blkr_ph : 1; // Bits 10:10
- + uint32_t dis_blkr_pe : 1; // Bits 11:11
- + uint32_t dis_blkr_pm : 1; // Bits 12:12
- + uint32_t dis_odt : 1; // Bits 13:13
- + uint32_t oe_always_off : 1; // Bits 14:14
- + uint32_t : 1; // Bits 15:15
- + uint32_t dis_aom : 1; // Bits 16:16
- + uint32_t block_rpq : 1; // Bits 17:17
- + uint32_t block_wpq : 1; // Bits 18:18
- + uint32_t invert_align : 1; // Bits 19:19
- + uint32_t dis_write_gap : 1; // Bits 20:20
- + uint32_t dis_zq : 1; // Bits 21:21
- + uint32_t dis_tt : 1; // Bits 22:22
- + uint32_t dis_opp_ref : 1; // Bits 23:23
- + uint32_t long_zq : 1; // Bits 24:24
- + uint32_t dis_srx_zq : 1; // Bits 25:25
- + uint32_t serialize_zq : 1; // Bits 26:26
- + uint32_t zq_fast_exec : 1; // Bits 27:27
- + uint32_t dis_drive_nop : 1; // Bits 28:28
- + uint32_t pres_wdb_ent : 1; // Bits 29:29
- + uint32_t dis_clk_gate : 1; // Bits 30:30
- + uint32_t : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union mcmain_command_rate_limit_reg {
- + struct __packed {
- + uint32_t enable_cmd_limit : 1; // Bits 0:0
- + uint32_t cmd_rate_limit : 3; // Bits 3:1
- + uint32_t reset_on_command : 4; // Bits 7:4
- + uint32_t reset_delay : 4; // Bits 11:8
- + uint32_t ck_to_cke_delay : 2; // Bits 13:12
- + uint32_t : 17; // Bits 30:14
- + uint32_t init_mrw_2n_cs : 1; // Bits 31:31
- + };
- + uint32_t raw;
- +};
- +
- +union mad_chnl_reg {
- + struct __packed {
- + uint32_t ch_a : 2; // Bits 1:0
- + uint32_t ch_b : 2; // Bits 3:2
- + uint32_t ch_c : 2; // Bits 5:4
- + uint32_t stacked_mode : 1; // Bits 6:6
- + uint32_t stkd_mode_bits : 3; // Bits 9:7
- + uint32_t lpddr_mode : 1; // Bits 10:10
- + uint32_t : 21; // Bits 31:11
- + };
- + uint32_t raw;
- +};
- +
- +union mad_dimm_reg {
- + struct __packed {
- + uint32_t dimm_a_size : 8; // Bits 7:0
- + uint32_t dimm_b_size : 8; // Bits 15:8
- + uint32_t dimm_a_sel : 1; // Bits 16:16
- + uint32_t dimm_a_ranks : 1; // Bits 17:17
- + uint32_t dimm_b_ranks : 1; // Bits 18:18
- + uint32_t dimm_a_width : 1; // Bits 19:19
- + uint32_t dimm_b_width : 1; // Bits 20:20
- + uint32_t rank_interleave : 1; // Bits 21:21
- + uint32_t enh_interleave : 1; // Bits 22:22
- + uint32_t : 1; // Bits 23:23
- + uint32_t ecc_mode : 2; // Bits 25:24
- + uint32_t hori_mode : 1; // Bits 26:26
- + uint32_t hori_address : 3; // Bits 29:27
- + uint32_t : 2; // Bits 31:30
- + };
- + uint32_t raw;
- +};
- +
- +union mad_zr_reg {
- + struct __packed {
- + uint32_t : 16; // Bits 15:0
- + uint32_t ch_b_double : 8; // Bits 23:16
- + uint32_t ch_b_single : 8; // Bits 31:24
- + };
- + uint32_t raw;
- +};
- +
- +/* Same definition for P_COMP, M_COMP, D_COMP */
- +union pcu_comp_reg {
- + struct __packed {
- + uint32_t comp_disable : 1; // Bits 0:0
- + uint32_t comp_interval : 4; // Bits 4:1
- + uint32_t : 3; // Bits 7:5
- + uint32_t comp_force : 1; // Bits 8:8
- + uint32_t : 23; // Bits 31:9
- + };
- + uint32_t raw;
- +};
- +
- +#endif
- diff --git a/src/northbridge/intel/haswell/native_raminit/timings_refresh.c b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- new file mode 100644
- index 0000000000..a9d960f31b
- --- /dev/null
- +++ b/src/northbridge/intel/haswell/native_raminit/timings_refresh.c
- @@ -0,0 +1,13 @@
- +/* SPDX-License-Identifier: GPL-2.0-or-later */
- +
- +#include "raminit_native.h"
- +
- +void configure_timings(struct sysinfo *ctrl)
- +{
- + /** TODO: Stub **/
- +}
- +
- +void configure_refresh(struct sysinfo *ctrl)
- +{
- + /** TODO: Stub **/
- +}
- diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
- index 45f8174995..4c3f399b5d 100644
- --- a/src/northbridge/intel/haswell/registers/mchbar.h
- +++ b/src/northbridge/intel/haswell/registers/mchbar.h
- @@ -7,9 +7,98 @@
- #define NUM_CHANNELS 2
- #define NUM_SLOTS 2
-
- +/* Indexed register helper macros */
- +#define _DDRIO_C_R_B(r, ch, rank, byte) ((r) + 0x100 * (ch) + 0x4 * (rank) + 0x200 * (byte))
- +#define _MCMAIN_C_X(r, ch, x) ((r) + 0x400 * (ch) + 0x4 * (x))
- +#define _MCMAIN_C(r, ch) ((r) + 0x400 * (ch))
- +
- /* Register definitions */
- +
- +/* DDR DATA per-channel per-bytelane */
- +#define DQ_CONTROL_2(ch, byte) _DDRIO_C_R_B(0x0064, ch, 0, byte)
- +
- +/* DDR CKE per-channel */
- +#define DDR_CKE_ch_CMD_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1204, ch, 0, 0)
- +#define DDR_CKE_ch_CMD_PI_CODING(ch) _DDRIO_C_R_B(0x1208, ch, 0, 0)
- +
- +#define DDR_CKE_ch_CTL_CONTROLS(ch) _DDRIO_C_R_B(0x121c, ch, 0, 0)
- +#define DDR_CKE_ch_CTL_RANKS_USED(ch) _DDRIO_C_R_B(0x1220, ch, 0, 0)
- +
- +/* DDR CTL per-channel */
- +#define DDR_CTL_ch_CTL_CONTROLS(ch) _DDRIO_C_R_B(0x1c1c, ch, 0, 0)
- +#define DDR_CTL_ch_CTL_RANKS_USED(ch) _DDRIO_C_R_B(0x1c20, ch, 0, 0)
- +
- +/* DDR CLK per-channel */
- +#define DDR_CLK_ch_RANKS_USED(ch) _DDRIO_C_R_B(0x1800, ch, 0, 0)
- +#define DDR_CLK_ch_COMP_OFFSET(ch) _DDRIO_C_R_B(0x1808, ch, 0, 0)
- +#define DDR_CLK_ch_PI_CODING(ch) _DDRIO_C_R_B(0x180c, ch, 0, 0)
- +#define DDR_CLK_ch_CONTROLS(ch) _DDRIO_C_R_B(0x1810, ch, 0, 0)
- +
- +/* DDR Scrambler */
- +#define DDR_SCRAMBLE_ch(ch) (0x2000 + 4 * (ch))
- +#define DDR_SCRAM_MISC_CONTROL 0x2008
- +
- +/* 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)
- +#define DDR_CMD_ch_CONTROLS(ch) _DDRIO_C_R_B(0x320c, ch, 0, 0)
- +
- +/* DDR CKE/CTL per-channel (writes go to both CKE and CTL fubs) */
- +#define DDR_CKE_CTL_ch_CTL_COMP_OFFSET(ch) _DDRIO_C_R_B(0x3414, ch, 0, 0)
- +#define DDR_CKE_CTL_ch_CTL_PI_CODING(ch) _DDRIO_C_R_B(0x3418, ch, 0, 0)
- +
- +/* DDR DATA broadcast */
- +#define DDR_DATA_RX_TRAIN_RANK(rank) _DDRIO_C_R_B(0x3600, 0, rank, 0)
- +#define DDR_DATA_RX_PER_BIT_RANK(rank) _DDRIO_C_R_B(0x3610, 0, rank, 0)
- +#define DDR_DATA_TX_TRAIN_RANK(rank) _DDRIO_C_R_B(0x3620, 0, rank, 0)
- +#define DDR_DATA_TX_PER_BIT_RANK(rank) _DDRIO_C_R_B(0x3630, 0, rank, 0)
- +
- +#define DDR_DATA_RCOMP_DATA_1 0x3644
- +#define DDR_DATA_TX_XTALK 0x3648
- +#define DDR_DATA_RX_OFFSET_VDQ 0x364c
- +#define DDR_DATA_OFFSET_COMP 0x365c
- +#define DDR_DATA_CONTROL_1 0x3660
- +
- +#define DDR_DATA_OFFSET_TRAIN 0x3670
- +#define DDR_DATA_CONTROL_0 0x3674
- +#define DDR_DATA_VREF_ADJUST 0x3678
- +
- +/* DDR CMD broadcast */
- +#define DDR_CMD_COMP 0x3700
- +
- +/* DDR CKE/CTL broadcast */
- +#define DDR_CKE_CTL_COMP 0x3810
- +
- +/* DDR CLK broadcast */
- +#define DDR_CLK_COMP 0x3904
- +#define DDR_CLK_CONTROLS 0x3910
- +#define DDR_CLK_CB_STATUS 0x3918
- +
- +/* DDR COMP (global) */
- +#define DDR_COMP_DATA_COMP_1 0x3a04
- +#define DDR_COMP_CMD_COMP 0x3a08
- +#define DDR_COMP_CTL_COMP 0x3a0c
- +#define DDR_COMP_CLK_COMP 0x3a10
- +#define DDR_COMP_CTL_0 0x3a14
- +#define DDR_COMP_CTL_1 0x3a18
- +#define DDR_COMP_VSSHI 0x3a1c
- +#define DDR_COMP_OVERRIDE 0x3a20
- +#define DDR_COMP_VSSHI_CONTROL 0x3a24
- +
- +/* MCMAIN per-channel */
- +#define COMMAND_RATE_LIMIT_ch(ch) _MCMAIN_C(0x4010, ch)
- +
- +#define MC_INIT_STATE_ch(ch) _MCMAIN_C(0x42a0, ch)
- +
- +/* MCMAIN broadcast */
- +#define MCSCHEDS_CBIT 0x4c20
- +
- +#define MCMNTS_SC_WDBWM 0x4f8c
- +
- +/* MCDECS */
- #define MAD_CHNL 0x5000 /* Address Decoder Channel Configuration */
- #define MAD_DIMM(ch) (0x5004 + (ch) * 4)
- +#define MAD_ZR 0x5014
- #define MC_INIT_STATE_G 0x5030
- #define MRC_REVISION 0x5034 /* MRC Revision */
-
- @@ -28,6 +117,8 @@
-
- #define PCU_DDR_PTM_CTL 0x5880
-
- +#define PCU_DDR_VOLTAGE 0x58a4
- +
- /* Some power MSRs are also represented in MCHBAR */
- #define MCH_PKG_POWER_LIMIT_LO 0x59a0
- #define MCH_PKG_POWER_LIMIT_HI 0x59a4
- @@ -48,6 +139,8 @@
- #define MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL 0x909
- #define MAILBOX_BIOS_CMD_READ_PCH_POWER 0xa
- #define MAILBOX_BIOS_CMD_READ_PCH_POWER_EXT 0xb
- +#define MAILBOX_BIOS_CMD_READ_DDR_2X_REFRESH 0x17
- +#define MAILBOX_BIOS_CMD_WRITE_DDR_2X_REFRESH 0x18
- #define MAILBOX_BIOS_CMD_READ_C9C10_VOLTAGE 0x26
- #define MAILBOX_BIOS_CMD_WRITE_C9C10_VOLTAGE 0x27
-
- @@ -66,6 +159,7 @@
- #define MC_BIOS_REQ 0x5e00 /* Memory frequency request register */
- #define MC_BIOS_DATA 0x5e04 /* Miscellaneous information for BIOS */
- #define SAPMCTL 0x5f00
- +#define M_COMP 0x5f08
-
- #define HDAUDRID 0x6008
- #define UMAGFXCTL 0x6020
- --
- 2.39.2
|