1*b35ce0c4SPankaj Gupta /* 2*b35ce0c4SPankaj Gupta * Copyright 2021 NXP 3*b35ce0c4SPankaj Gupta * 4*b35ce0c4SPankaj Gupta * SPDX-License-Identifier: BSD-3-Clause 5*b35ce0c4SPankaj Gupta * 6*b35ce0c4SPankaj Gupta */ 7*b35ce0c4SPankaj Gupta 8*b35ce0c4SPankaj Gupta #include <errno.h> 9*b35ce0c4SPankaj Gupta #include <stdbool.h> 10*b35ce0c4SPankaj Gupta #include <stdint.h> 11*b35ce0c4SPankaj Gupta #include <stdio.h> 12*b35ce0c4SPankaj Gupta #include <stdlib.h> 13*b35ce0c4SPankaj Gupta 14*b35ce0c4SPankaj Gupta #include <common/debug.h> 15*b35ce0c4SPankaj Gupta #include <ddr.h> 16*b35ce0c4SPankaj Gupta #include <lib/utils.h> 17*b35ce0c4SPankaj Gupta 18*b35ce0c4SPankaj Gupta static inline unsigned int cal_cwl(const unsigned long clk) 19*b35ce0c4SPankaj Gupta { 20*b35ce0c4SPankaj Gupta const unsigned int mclk_ps = get_memory_clk_ps(clk); 21*b35ce0c4SPankaj Gupta 22*b35ce0c4SPankaj Gupta return mclk_ps >= 1250U ? 9U : 23*b35ce0c4SPankaj Gupta (mclk_ps >= 1070U ? 10U : 24*b35ce0c4SPankaj Gupta (mclk_ps >= 935U ? 11U : 25*b35ce0c4SPankaj Gupta (mclk_ps >= 833U ? 12U : 26*b35ce0c4SPankaj Gupta (mclk_ps >= 750U ? 14U : 27*b35ce0c4SPankaj Gupta (mclk_ps >= 625U ? 16U : 18U))))); 28*b35ce0c4SPankaj Gupta } 29*b35ce0c4SPankaj Gupta 30*b35ce0c4SPankaj Gupta static void cal_csn_config(int i, 31*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 32*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 33*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 34*b35ce0c4SPankaj Gupta { 35*b35ce0c4SPankaj Gupta unsigned int intlv_en = 0U; 36*b35ce0c4SPankaj Gupta unsigned int intlv_ctl = 0U; 37*b35ce0c4SPankaj Gupta const unsigned int cs_n_en = 1U; 38*b35ce0c4SPankaj Gupta const unsigned int ap_n_en = popts->cs_odt[i].auto_precharge; 39*b35ce0c4SPankaj Gupta const unsigned int odt_rd_cfg = popts->cs_odt[i].odt_rd_cfg; 40*b35ce0c4SPankaj Gupta const unsigned int odt_wr_cfg = popts->cs_odt[i].odt_wr_cfg; 41*b35ce0c4SPankaj Gupta const unsigned int ba_bits_cs_n = pdimm->bank_addr_bits; 42*b35ce0c4SPankaj Gupta const unsigned int row_bits_cs_n = pdimm->n_row_addr - 12U; 43*b35ce0c4SPankaj Gupta const unsigned int col_bits_cs_n = pdimm->n_col_addr - 8U; 44*b35ce0c4SPankaj Gupta const unsigned int bg_bits_cs_n = pdimm->bank_group_bits; 45*b35ce0c4SPankaj Gupta 46*b35ce0c4SPankaj Gupta if (i == 0) { 47*b35ce0c4SPankaj Gupta /* These fields only available in CS0_CONFIG */ 48*b35ce0c4SPankaj Gupta if (popts->ctlr_intlv != 0) { 49*b35ce0c4SPankaj Gupta switch (popts->ctlr_intlv_mode) { 50*b35ce0c4SPankaj Gupta case DDR_256B_INTLV: 51*b35ce0c4SPankaj Gupta intlv_en = popts->ctlr_intlv; 52*b35ce0c4SPankaj Gupta intlv_ctl = popts->ctlr_intlv_mode; 53*b35ce0c4SPankaj Gupta break; 54*b35ce0c4SPankaj Gupta default: 55*b35ce0c4SPankaj Gupta break; 56*b35ce0c4SPankaj Gupta } 57*b35ce0c4SPankaj Gupta } 58*b35ce0c4SPankaj Gupta } 59*b35ce0c4SPankaj Gupta regs->cs[i].config = ((cs_n_en & 0x1) << 31) | 60*b35ce0c4SPankaj Gupta ((intlv_en & 0x3) << 29) | 61*b35ce0c4SPankaj Gupta ((intlv_ctl & 0xf) << 24) | 62*b35ce0c4SPankaj Gupta ((ap_n_en & 0x1) << 23) | 63*b35ce0c4SPankaj Gupta ((odt_rd_cfg & 0x7) << 20) | 64*b35ce0c4SPankaj Gupta ((odt_wr_cfg & 0x7) << 16) | 65*b35ce0c4SPankaj Gupta ((ba_bits_cs_n & 0x3) << 14) | 66*b35ce0c4SPankaj Gupta ((row_bits_cs_n & 0x7) << 8) | 67*b35ce0c4SPankaj Gupta ((bg_bits_cs_n & 0x3) << 4) | 68*b35ce0c4SPankaj Gupta ((col_bits_cs_n & 0x7) << 0); 69*b35ce0c4SPankaj Gupta debug("cs%d\n", i); 70*b35ce0c4SPankaj Gupta debug(" _config = 0x%x\n", regs->cs[i].config); 71*b35ce0c4SPankaj Gupta } 72*b35ce0c4SPankaj Gupta 73*b35ce0c4SPankaj Gupta static inline int avoid_odt_overlap(const struct ddr_conf *conf, 74*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 75*b35ce0c4SPankaj Gupta { 76*b35ce0c4SPankaj Gupta if ((conf->cs_in_use == 0xf) != 0) { 77*b35ce0c4SPankaj Gupta return 2; 78*b35ce0c4SPankaj Gupta } 79*b35ce0c4SPankaj Gupta 80*b35ce0c4SPankaj Gupta #if DDRC_NUM_DIMM >= 2 81*b35ce0c4SPankaj Gupta if (conf->dimm_in_use[0] != 0 && conf->dimm_in_use[1] != 0) { 82*b35ce0c4SPankaj Gupta return 1; 83*b35ce0c4SPankaj Gupta } 84*b35ce0c4SPankaj Gupta #endif 85*b35ce0c4SPankaj Gupta return 0; 86*b35ce0c4SPankaj Gupta } 87*b35ce0c4SPankaj Gupta 88*b35ce0c4SPankaj Gupta /* Requires rcw2 set first */ 89*b35ce0c4SPankaj Gupta static void cal_timing_cfg(const unsigned long clk, 90*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 91*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 92*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm, 93*b35ce0c4SPankaj Gupta const struct ddr_conf *conf, 94*b35ce0c4SPankaj Gupta unsigned int cas_latency, 95*b35ce0c4SPankaj Gupta unsigned int additive_latency) 96*b35ce0c4SPankaj Gupta { 97*b35ce0c4SPankaj Gupta const unsigned int mclk_ps = get_memory_clk_ps(clk); 98*b35ce0c4SPankaj Gupta /* tXP=max(4nCK, 6ns) */ 99*b35ce0c4SPankaj Gupta const int txp = max((int)mclk_ps * 4, 6000); 100*b35ce0c4SPankaj Gupta /* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */ 101*b35ce0c4SPankaj Gupta static const int wrrec_table[] = { 102*b35ce0c4SPankaj Gupta 10, 10, 10, 10, 10, 103*b35ce0c4SPankaj Gupta 10, 10, 10, 10, 10, 104*b35ce0c4SPankaj Gupta 12, 12, 14, 14, 16, 105*b35ce0c4SPankaj Gupta 16, 18, 18, 20, 20, 106*b35ce0c4SPankaj Gupta 24, 24, 24, 24, 107*b35ce0c4SPankaj Gupta }; 108*b35ce0c4SPankaj Gupta int trwt_mclk = (clk / 1000000 > 1900) ? 3 : 2; 109*b35ce0c4SPankaj Gupta int twrt_mclk; 110*b35ce0c4SPankaj Gupta int trrt_mclk; 111*b35ce0c4SPankaj Gupta int twwt_mclk; 112*b35ce0c4SPankaj Gupta const int act_pd_exit_mclk = picos_to_mclk(clk, txp); 113*b35ce0c4SPankaj Gupta const int pre_pd_exit_mclk = act_pd_exit_mclk; 114*b35ce0c4SPankaj Gupta const int taxpd_mclk = 0; 115*b35ce0c4SPankaj Gupta /* 116*b35ce0c4SPankaj Gupta * MRS_CYC = max(tMRD, tMOD) 117*b35ce0c4SPankaj Gupta * tMRD = 8nCK, tMOD = max(24nCK, 15ns) 118*b35ce0c4SPankaj Gupta */ 119*b35ce0c4SPankaj Gupta const int tmrd_mclk = max(24U, picos_to_mclk(clk, 15000)); 120*b35ce0c4SPankaj Gupta const int pretoact_mclk = picos_to_mclk(clk, pdimm->trp_ps); 121*b35ce0c4SPankaj Gupta const int acttopre_mclk = picos_to_mclk(clk, pdimm->tras_ps); 122*b35ce0c4SPankaj Gupta const int acttorw_mclk = picos_to_mclk(clk, pdimm->trcd_ps); 123*b35ce0c4SPankaj Gupta const int caslat_ctrl = (cas_latency - 1) << 1; 124*b35ce0c4SPankaj Gupta const int trfc1_min = pdimm->die_density >= 0x3 ? 16000 : 125*b35ce0c4SPankaj Gupta (pdimm->die_density == 0x4 ? 26000 : 126*b35ce0c4SPankaj Gupta (pdimm->die_density == 0x5 ? 35000 : 127*b35ce0c4SPankaj Gupta 55000)); 128*b35ce0c4SPankaj Gupta const int refrec_ctrl = picos_to_mclk(clk, 129*b35ce0c4SPankaj Gupta pdimm->trfc1_ps) - 8; 130*b35ce0c4SPankaj Gupta int wrrec_mclk = picos_to_mclk(clk, pdimm->twr_ps); 131*b35ce0c4SPankaj Gupta const int acttoact_mclk = max(picos_to_mclk(clk, 132*b35ce0c4SPankaj Gupta pdimm->trrds_ps), 133*b35ce0c4SPankaj Gupta 4U); 134*b35ce0c4SPankaj Gupta int wrtord_mclk = max(2U, picos_to_mclk(clk, 2500)); 135*b35ce0c4SPankaj Gupta const unsigned int cpo = 0U; 136*b35ce0c4SPankaj Gupta const int wr_lat = cal_cwl(clk); 137*b35ce0c4SPankaj Gupta int rd_to_pre = picos_to_mclk(clk, 7500); 138*b35ce0c4SPankaj Gupta const int wr_data_delay = popts->wr_data_delay; 139*b35ce0c4SPankaj Gupta const int cke_pls = max(3U, picos_to_mclk(clk, 5000)); 140*b35ce0c4SPankaj Gupta #ifdef ERRATA_DDR_A050450 141*b35ce0c4SPankaj Gupta const unsigned short four_act = ((popts->twot_en == 0) && 142*b35ce0c4SPankaj Gupta (popts->threet_en == 0) && 143*b35ce0c4SPankaj Gupta (popts->tfaw_ps % 2 == 0)) ? 144*b35ce0c4SPankaj Gupta (picos_to_mclk(clk, popts->tfaw_ps) + 1) : 145*b35ce0c4SPankaj Gupta picos_to_mclk(clk, popts->tfaw_ps); 146*b35ce0c4SPankaj Gupta #else 147*b35ce0c4SPankaj Gupta const unsigned short four_act = picos_to_mclk(clk, 148*b35ce0c4SPankaj Gupta popts->tfaw_ps); 149*b35ce0c4SPankaj Gupta #endif 150*b35ce0c4SPankaj Gupta const unsigned int cntl_adj = 0U; 151*b35ce0c4SPankaj Gupta const unsigned int ext_pretoact = picos_to_mclk(clk, 152*b35ce0c4SPankaj Gupta pdimm->trp_ps) >> 4U; 153*b35ce0c4SPankaj Gupta const unsigned int ext_acttopre = picos_to_mclk(clk, 154*b35ce0c4SPankaj Gupta pdimm->tras_ps) >> 4U; 155*b35ce0c4SPankaj Gupta const unsigned int ext_acttorw = picos_to_mclk(clk, 156*b35ce0c4SPankaj Gupta pdimm->trcd_ps) >> 4U; 157*b35ce0c4SPankaj Gupta const unsigned int ext_caslat = (2U * cas_latency - 1U) >> 4U; 158*b35ce0c4SPankaj Gupta const unsigned int ext_add_lat = additive_latency >> 4U; 159*b35ce0c4SPankaj Gupta const unsigned int ext_refrec = (picos_to_mclk(clk, 160*b35ce0c4SPankaj Gupta pdimm->trfc1_ps) - 8U) >> 4U; 161*b35ce0c4SPankaj Gupta const unsigned int ext_wrrec = (picos_to_mclk(clk, pdimm->twr_ps) + 162*b35ce0c4SPankaj Gupta (popts->otf_burst_chop_en ? 2U : 0U)) >> 4U; 163*b35ce0c4SPankaj Gupta const unsigned int rwt_same_cs = 0U; 164*b35ce0c4SPankaj Gupta const unsigned int wrt_same_cs = 0U; 165*b35ce0c4SPankaj Gupta const unsigned int rrt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; 166*b35ce0c4SPankaj Gupta const unsigned int wwt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; 167*b35ce0c4SPankaj Gupta const unsigned int dll_lock = 2U; 168*b35ce0c4SPankaj Gupta unsigned int rodt_on = 0U; 169*b35ce0c4SPankaj Gupta const unsigned int rodt_off = 4U; 170*b35ce0c4SPankaj Gupta const unsigned int wodt_on = 1U; 171*b35ce0c4SPankaj Gupta const unsigned int wodt_off = 4U; 172*b35ce0c4SPankaj Gupta const unsigned int hs_caslat = 0U; 173*b35ce0c4SPankaj Gupta const unsigned int hs_wrlat = 0U; 174*b35ce0c4SPankaj Gupta const unsigned int hs_wrrec = 0U; 175*b35ce0c4SPankaj Gupta const unsigned int hs_clkadj = 0U; 176*b35ce0c4SPankaj Gupta const unsigned int hs_wrlvl_start = 0U; 177*b35ce0c4SPankaj Gupta const unsigned int txpr = max(5U, 178*b35ce0c4SPankaj Gupta picos_to_mclk(clk, 179*b35ce0c4SPankaj Gupta pdimm->trfc1_ps + 10000U)); 180*b35ce0c4SPankaj Gupta const unsigned int tcksre = max(5U, picos_to_mclk(clk, 10000U)); 181*b35ce0c4SPankaj Gupta const unsigned int tcksrx = max(5U, picos_to_mclk(clk, 10000U)); 182*b35ce0c4SPankaj Gupta const unsigned int cs_to_cmd = 0U; 183*b35ce0c4SPankaj Gupta const unsigned int cke_rst = txpr <= 200U ? 0U : 184*b35ce0c4SPankaj Gupta (txpr <= 256U ? 1U : 185*b35ce0c4SPankaj Gupta (txpr <= 512U ? 2U : 3U)); 186*b35ce0c4SPankaj Gupta const unsigned int cksre = tcksre <= 19U ? tcksre - 5U : 15U; 187*b35ce0c4SPankaj Gupta const unsigned int cksrx = tcksrx <= 19U ? tcksrx - 5U : 15U; 188*b35ce0c4SPankaj Gupta unsigned int par_lat = 0U; 189*b35ce0c4SPankaj Gupta const int tccdl = max(5U, picos_to_mclk(clk, pdimm->tccdl_ps)); 190*b35ce0c4SPankaj Gupta int rwt_bg = cas_latency + 2 + 4 - wr_lat; 191*b35ce0c4SPankaj Gupta int wrt_bg = wr_lat + 4 + 1 - cas_latency; 192*b35ce0c4SPankaj Gupta const int rrt_bg = popts->burst_length == DDR_BL8 ? 193*b35ce0c4SPankaj Gupta tccdl - 4 : tccdl - 2; 194*b35ce0c4SPankaj Gupta const int wwt_bg = popts->burst_length == DDR_BL8 ? 195*b35ce0c4SPankaj Gupta tccdl - 4 : tccdl - 2; 196*b35ce0c4SPankaj Gupta const unsigned int acttoact_bg = picos_to_mclk(clk, pdimm->trrdl_ps); 197*b35ce0c4SPankaj Gupta const unsigned int wrtord_bg = max(4U, picos_to_mclk(clk, 7500)) + 198*b35ce0c4SPankaj Gupta (popts->otf_burst_chop_en ? 2 : 0); 199*b35ce0c4SPankaj Gupta const unsigned int pre_all_rec = 0; 200*b35ce0c4SPankaj Gupta const unsigned int refrec_cid_mclk = pdimm->package_3ds ? 201*b35ce0c4SPankaj Gupta picos_to_mclk(clk, pdimm->trfc_slr_ps) : 0; 202*b35ce0c4SPankaj Gupta const unsigned int acttoact_cid_mclk = pdimm->package_3ds ? 4U : 0; 203*b35ce0c4SPankaj Gupta 204*b35ce0c4SPankaj Gupta 205*b35ce0c4SPankaj Gupta /* for two dual-rank DIMMs to avoid ODT overlap */ 206*b35ce0c4SPankaj Gupta if (avoid_odt_overlap(conf, pdimm) == 2) { 207*b35ce0c4SPankaj Gupta twrt_mclk = 2; 208*b35ce0c4SPankaj Gupta twwt_mclk = 2; 209*b35ce0c4SPankaj Gupta trrt_mclk = 2; 210*b35ce0c4SPankaj Gupta } else { 211*b35ce0c4SPankaj Gupta twrt_mclk = 1; 212*b35ce0c4SPankaj Gupta twwt_mclk = 1; 213*b35ce0c4SPankaj Gupta trrt_mclk = 0; 214*b35ce0c4SPankaj Gupta } 215*b35ce0c4SPankaj Gupta 216*b35ce0c4SPankaj Gupta if (popts->trwt_override != 0) { 217*b35ce0c4SPankaj Gupta trwt_mclk = popts->trwt; 218*b35ce0c4SPankaj Gupta if (popts->twrt != 0) { 219*b35ce0c4SPankaj Gupta twrt_mclk = popts->twrt; 220*b35ce0c4SPankaj Gupta } 221*b35ce0c4SPankaj Gupta if (popts->trrt != 0) { 222*b35ce0c4SPankaj Gupta trrt_mclk = popts->trrt; 223*b35ce0c4SPankaj Gupta } 224*b35ce0c4SPankaj Gupta if (popts->twwt != 0) { 225*b35ce0c4SPankaj Gupta twwt_mclk = popts->twwt; 226*b35ce0c4SPankaj Gupta } 227*b35ce0c4SPankaj Gupta } 228*b35ce0c4SPankaj Gupta regs->timing_cfg[0] = (((trwt_mclk & 0x3) << 30) | 229*b35ce0c4SPankaj Gupta ((twrt_mclk & 0x3) << 28) | 230*b35ce0c4SPankaj Gupta ((trrt_mclk & 0x3) << 26) | 231*b35ce0c4SPankaj Gupta ((twwt_mclk & 0x3) << 24) | 232*b35ce0c4SPankaj Gupta ((act_pd_exit_mclk & 0xf) << 20) | 233*b35ce0c4SPankaj Gupta ((pre_pd_exit_mclk & 0xF) << 16) | 234*b35ce0c4SPankaj Gupta ((taxpd_mclk & 0xf) << 8) | 235*b35ce0c4SPankaj Gupta ((tmrd_mclk & 0x1f) << 0)); 236*b35ce0c4SPankaj Gupta debug("timing_cfg[0] = 0x%x\n", regs->timing_cfg[0]); 237*b35ce0c4SPankaj Gupta 238*b35ce0c4SPankaj Gupta if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) { 239*b35ce0c4SPankaj Gupta ERROR("WRREC doesn't support clock %d\n", wrrec_mclk); 240*b35ce0c4SPankaj Gupta } else { 241*b35ce0c4SPankaj Gupta wrrec_mclk = wrrec_table[wrrec_mclk - 1]; 242*b35ce0c4SPankaj Gupta } 243*b35ce0c4SPankaj Gupta 244*b35ce0c4SPankaj Gupta if (popts->otf_burst_chop_en != 0) { 245*b35ce0c4SPankaj Gupta wrrec_mclk += 2; 246*b35ce0c4SPankaj Gupta wrtord_mclk += 2; 247*b35ce0c4SPankaj Gupta } 248*b35ce0c4SPankaj Gupta 249*b35ce0c4SPankaj Gupta if (pdimm->trfc1_ps < trfc1_min) { 250*b35ce0c4SPankaj Gupta ERROR("trfc1_ps (%d) < %d\n", pdimm->trfc1_ps, trfc1_min); 251*b35ce0c4SPankaj Gupta } 252*b35ce0c4SPankaj Gupta 253*b35ce0c4SPankaj Gupta regs->timing_cfg[1] = (((pretoact_mclk & 0x0F) << 28) | 254*b35ce0c4SPankaj Gupta ((acttopre_mclk & 0x0F) << 24) | 255*b35ce0c4SPankaj Gupta ((acttorw_mclk & 0xF) << 20) | 256*b35ce0c4SPankaj Gupta ((caslat_ctrl & 0xF) << 16) | 257*b35ce0c4SPankaj Gupta ((refrec_ctrl & 0xF) << 12) | 258*b35ce0c4SPankaj Gupta ((wrrec_mclk & 0x0F) << 8) | 259*b35ce0c4SPankaj Gupta ((acttoact_mclk & 0x0F) << 4) | 260*b35ce0c4SPankaj Gupta ((wrtord_mclk & 0x0F) << 0)); 261*b35ce0c4SPankaj Gupta debug("timing_cfg[1] = 0x%x\n", regs->timing_cfg[1]); 262*b35ce0c4SPankaj Gupta 263*b35ce0c4SPankaj Gupta if (rd_to_pre < 4) { 264*b35ce0c4SPankaj Gupta rd_to_pre = 4; 265*b35ce0c4SPankaj Gupta } 266*b35ce0c4SPankaj Gupta if (popts->otf_burst_chop_en) { 267*b35ce0c4SPankaj Gupta rd_to_pre += 2; 268*b35ce0c4SPankaj Gupta } 269*b35ce0c4SPankaj Gupta 270*b35ce0c4SPankaj Gupta regs->timing_cfg[2] = (((additive_latency & 0xf) << 28) | 271*b35ce0c4SPankaj Gupta ((cpo & 0x1f) << 23) | 272*b35ce0c4SPankaj Gupta ((wr_lat & 0xf) << 19) | 273*b35ce0c4SPankaj Gupta (((wr_lat & 0x10) >> 4) << 18) | 274*b35ce0c4SPankaj Gupta ((rd_to_pre & 0xf) << 13) | 275*b35ce0c4SPankaj Gupta ((wr_data_delay & 0xf) << 9) | 276*b35ce0c4SPankaj Gupta ((cke_pls & 0x7) << 6) | 277*b35ce0c4SPankaj Gupta ((four_act & 0x3f) << 0)); 278*b35ce0c4SPankaj Gupta debug("timing_cfg[2] = 0x%x\n", regs->timing_cfg[2]); 279*b35ce0c4SPankaj Gupta 280*b35ce0c4SPankaj Gupta regs->timing_cfg[3] = (((ext_pretoact & 0x1) << 28) | 281*b35ce0c4SPankaj Gupta ((ext_acttopre & 0x3) << 24) | 282*b35ce0c4SPankaj Gupta ((ext_acttorw & 0x1) << 22) | 283*b35ce0c4SPankaj Gupta ((ext_refrec & 0x3F) << 16) | 284*b35ce0c4SPankaj Gupta ((ext_caslat & 0x3) << 12) | 285*b35ce0c4SPankaj Gupta ((ext_add_lat & 0x1) << 10) | 286*b35ce0c4SPankaj Gupta ((ext_wrrec & 0x1) << 8) | 287*b35ce0c4SPankaj Gupta ((cntl_adj & 0x7) << 0)); 288*b35ce0c4SPankaj Gupta debug("timing_cfg[3] = 0x%x\n", regs->timing_cfg[3]); 289*b35ce0c4SPankaj Gupta 290*b35ce0c4SPankaj Gupta regs->timing_cfg[4] = (((rwt_same_cs & 0xf) << 28) | 291*b35ce0c4SPankaj Gupta ((wrt_same_cs & 0xf) << 24) | 292*b35ce0c4SPankaj Gupta ((rrt_same_cs & 0xf) << 20) | 293*b35ce0c4SPankaj Gupta ((wwt_same_cs & 0xf) << 16) | 294*b35ce0c4SPankaj Gupta ((trwt_mclk & 0xc) << 12) | 295*b35ce0c4SPankaj Gupta ((twrt_mclk & 0x4) << 10) | 296*b35ce0c4SPankaj Gupta ((trrt_mclk & 0x4) << 8) | 297*b35ce0c4SPankaj Gupta ((twwt_mclk & 0x4) << 6) | 298*b35ce0c4SPankaj Gupta (dll_lock & 0x3)); 299*b35ce0c4SPankaj Gupta debug("timing_cfg[4] = 0x%x\n", regs->timing_cfg[4]); 300*b35ce0c4SPankaj Gupta 301*b35ce0c4SPankaj Gupta /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ 302*b35ce0c4SPankaj Gupta if (cas_latency >= wr_lat) { 303*b35ce0c4SPankaj Gupta rodt_on = cas_latency - wr_lat + 1; 304*b35ce0c4SPankaj Gupta } 305*b35ce0c4SPankaj Gupta 306*b35ce0c4SPankaj Gupta regs->timing_cfg[5] = (((rodt_on & 0x1f) << 24) | 307*b35ce0c4SPankaj Gupta ((rodt_off & 0x7) << 20) | 308*b35ce0c4SPankaj Gupta ((wodt_on & 0x1f) << 12) | 309*b35ce0c4SPankaj Gupta (wodt_off & 0x7) << 8); 310*b35ce0c4SPankaj Gupta debug("timing_cfg[5] = 0x%x\n", regs->timing_cfg[5]); 311*b35ce0c4SPankaj Gupta 312*b35ce0c4SPankaj Gupta regs->timing_cfg[6] = (((hs_caslat & 0x1f) << 24) | 313*b35ce0c4SPankaj Gupta ((hs_wrlat & 0x1f) << 19) | 314*b35ce0c4SPankaj Gupta ((hs_wrrec & 0x1f) << 12) | 315*b35ce0c4SPankaj Gupta ((hs_clkadj & 0x1f) << 6) | 316*b35ce0c4SPankaj Gupta ((hs_wrlvl_start & 0x1f) << 0)); 317*b35ce0c4SPankaj Gupta debug("timing_cfg[6] = 0x%x\n", regs->timing_cfg[6]); 318*b35ce0c4SPankaj Gupta 319*b35ce0c4SPankaj Gupta if (popts->ap_en != 0) { 320*b35ce0c4SPankaj Gupta par_lat = (regs->sdram_rcw[1] & 0xf) + 1; 321*b35ce0c4SPankaj Gupta debug("PAR_LAT = 0x%x\n", par_lat); 322*b35ce0c4SPankaj Gupta } 323*b35ce0c4SPankaj Gupta 324*b35ce0c4SPankaj Gupta regs->timing_cfg[7] = (((cke_rst & 0x3) << 28) | 325*b35ce0c4SPankaj Gupta ((cksre & 0xf) << 24) | 326*b35ce0c4SPankaj Gupta ((cksrx & 0xf) << 20) | 327*b35ce0c4SPankaj Gupta ((par_lat & 0xf) << 16) | 328*b35ce0c4SPankaj Gupta ((cs_to_cmd & 0xf) << 4)); 329*b35ce0c4SPankaj Gupta debug("timing_cfg[7] = 0x%x\n", regs->timing_cfg[7]); 330*b35ce0c4SPankaj Gupta 331*b35ce0c4SPankaj Gupta if (rwt_bg < tccdl) { 332*b35ce0c4SPankaj Gupta rwt_bg = tccdl - rwt_bg; 333*b35ce0c4SPankaj Gupta } else { 334*b35ce0c4SPankaj Gupta rwt_bg = 0; 335*b35ce0c4SPankaj Gupta } 336*b35ce0c4SPankaj Gupta if (wrt_bg < tccdl) { 337*b35ce0c4SPankaj Gupta wrt_bg = tccdl - wrt_bg; 338*b35ce0c4SPankaj Gupta } else { 339*b35ce0c4SPankaj Gupta wrt_bg = 0; 340*b35ce0c4SPankaj Gupta } 341*b35ce0c4SPankaj Gupta regs->timing_cfg[8] = (((rwt_bg & 0xf) << 28) | 342*b35ce0c4SPankaj Gupta ((wrt_bg & 0xf) << 24) | 343*b35ce0c4SPankaj Gupta ((rrt_bg & 0xf) << 20) | 344*b35ce0c4SPankaj Gupta ((wwt_bg & 0xf) << 16) | 345*b35ce0c4SPankaj Gupta ((acttoact_bg & 0xf) << 12) | 346*b35ce0c4SPankaj Gupta ((wrtord_bg & 0xf) << 8) | 347*b35ce0c4SPankaj Gupta ((pre_all_rec & 0x1f) << 0)); 348*b35ce0c4SPankaj Gupta debug("timing_cfg[8] = 0x%x\n", regs->timing_cfg[8]); 349*b35ce0c4SPankaj Gupta 350*b35ce0c4SPankaj Gupta regs->timing_cfg[9] = (refrec_cid_mclk & 0x3ff) << 16 | 351*b35ce0c4SPankaj Gupta (acttoact_cid_mclk & 0xf) << 8; 352*b35ce0c4SPankaj Gupta debug("timing_cfg[9] = 0x%x\n", regs->timing_cfg[9]); 353*b35ce0c4SPankaj Gupta } 354*b35ce0c4SPankaj Gupta 355*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_rcw(const unsigned long clk, 356*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 357*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 358*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 359*b35ce0c4SPankaj Gupta { 360*b35ce0c4SPankaj Gupta const unsigned int freq = clk / 1000000U; 361*b35ce0c4SPankaj Gupta unsigned int rc0a, rc0f; 362*b35ce0c4SPankaj Gupta 363*b35ce0c4SPankaj Gupta if (pdimm->rdimm == 0) { 364*b35ce0c4SPankaj Gupta return; 365*b35ce0c4SPankaj Gupta } 366*b35ce0c4SPankaj Gupta 367*b35ce0c4SPankaj Gupta rc0a = freq > 3200U ? 7U : 368*b35ce0c4SPankaj Gupta (freq > 2933U ? 6U : 369*b35ce0c4SPankaj Gupta (freq > 2666U ? 5U : 370*b35ce0c4SPankaj Gupta (freq > 2400U ? 4U : 371*b35ce0c4SPankaj Gupta (freq > 2133U ? 3U : 372*b35ce0c4SPankaj Gupta (freq > 1866U ? 2U : 373*b35ce0c4SPankaj Gupta (freq > 1600U ? 1U : 0U)))))); 374*b35ce0c4SPankaj Gupta rc0f = freq > 3200U ? 3U : 375*b35ce0c4SPankaj Gupta (freq > 2400U ? 2U : 376*b35ce0c4SPankaj Gupta (freq > 2133U ? 1U : 0U)); 377*b35ce0c4SPankaj Gupta rc0f = (regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) ? rc0f : 4; 378*b35ce0c4SPankaj Gupta regs->sdram_rcw[0] = 379*b35ce0c4SPankaj Gupta pdimm->rcw[0] << 28 | 380*b35ce0c4SPankaj Gupta pdimm->rcw[1] << 24 | 381*b35ce0c4SPankaj Gupta pdimm->rcw[2] << 20 | 382*b35ce0c4SPankaj Gupta pdimm->rcw[3] << 16 | 383*b35ce0c4SPankaj Gupta pdimm->rcw[4] << 12 | 384*b35ce0c4SPankaj Gupta pdimm->rcw[5] << 8 | 385*b35ce0c4SPankaj Gupta pdimm->rcw[6] << 4 | 386*b35ce0c4SPankaj Gupta pdimm->rcw[7]; 387*b35ce0c4SPankaj Gupta regs->sdram_rcw[1] = 388*b35ce0c4SPankaj Gupta pdimm->rcw[8] << 28 | 389*b35ce0c4SPankaj Gupta pdimm->rcw[9] << 24 | 390*b35ce0c4SPankaj Gupta rc0a << 20 | 391*b35ce0c4SPankaj Gupta pdimm->rcw[11] << 16 | 392*b35ce0c4SPankaj Gupta pdimm->rcw[12] << 12 | 393*b35ce0c4SPankaj Gupta pdimm->rcw[13] << 8 | 394*b35ce0c4SPankaj Gupta pdimm->rcw[14] << 4 | 395*b35ce0c4SPankaj Gupta rc0f; 396*b35ce0c4SPankaj Gupta regs->sdram_rcw[2] = 397*b35ce0c4SPankaj Gupta ((freq - 1260 + 19) / 20) << 8; 398*b35ce0c4SPankaj Gupta 399*b35ce0c4SPankaj Gupta debug("sdram_rcw[0] = 0x%x\n", regs->sdram_rcw[0]); 400*b35ce0c4SPankaj Gupta debug("sdram_rcw[1] = 0x%x\n", regs->sdram_rcw[1]); 401*b35ce0c4SPankaj Gupta debug("sdram_rcw[2] = 0x%x\n", regs->sdram_rcw[2]); 402*b35ce0c4SPankaj Gupta } 403*b35ce0c4SPankaj Gupta 404*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_cfg(const unsigned long clk, 405*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 406*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 407*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm, 408*b35ce0c4SPankaj Gupta const unsigned int ip_rev) 409*b35ce0c4SPankaj Gupta { 410*b35ce0c4SPankaj Gupta const unsigned int mem_en = 1U; 411*b35ce0c4SPankaj Gupta const unsigned int sren = popts->self_refresh_in_sleep; 412*b35ce0c4SPankaj Gupta const unsigned int ecc_en = popts->ecc_mode; 413*b35ce0c4SPankaj Gupta const unsigned int rd_en = (pdimm->rdimm != 0U) ? 1U : 0U; 414*b35ce0c4SPankaj Gupta const unsigned int dyn_pwr = popts->dynamic_power; 415*b35ce0c4SPankaj Gupta const unsigned int dbw = popts->data_bus_used; 416*b35ce0c4SPankaj Gupta const unsigned int eight_be = (dbw == 1U || 417*b35ce0c4SPankaj Gupta popts->burst_length == DDR_BL8) ? 1U : 0U; 418*b35ce0c4SPankaj Gupta const unsigned int ncap = 0U; 419*b35ce0c4SPankaj Gupta const unsigned int threet_en = popts->threet_en; 420*b35ce0c4SPankaj Gupta const unsigned int twot_en = pdimm->rdimm ? 421*b35ce0c4SPankaj Gupta 0U : popts->twot_en; 422*b35ce0c4SPankaj Gupta const unsigned int ba_intlv = popts->ba_intlv; 423*b35ce0c4SPankaj Gupta const unsigned int x32_en = 0U; 424*b35ce0c4SPankaj Gupta const unsigned int pchb8 = 0U; 425*b35ce0c4SPankaj Gupta const unsigned int hse = popts->half_strength_drive_en; 426*b35ce0c4SPankaj Gupta const unsigned int acc_ecc_en = (dbw != 0U && ecc_en == 1U) ? 1U : 0U; 427*b35ce0c4SPankaj Gupta const unsigned int mem_halt = 0U; 428*b35ce0c4SPankaj Gupta #ifdef PHY_GEN2 429*b35ce0c4SPankaj Gupta const unsigned int bi = 1U; 430*b35ce0c4SPankaj Gupta #else 431*b35ce0c4SPankaj Gupta const unsigned int bi = 0U; 432*b35ce0c4SPankaj Gupta #endif 433*b35ce0c4SPankaj Gupta const unsigned int sdram_type = SDRAM_TYPE_DDR4; 434*b35ce0c4SPankaj Gupta unsigned int odt_cfg = 0U; 435*b35ce0c4SPankaj Gupta const unsigned int frc_sr = 0U; 436*b35ce0c4SPankaj Gupta const unsigned int sr_ie = popts->self_refresh_irq_en; 437*b35ce0c4SPankaj Gupta const unsigned int num_pr = pdimm->package_3ds + 1U; 438*b35ce0c4SPankaj Gupta const unsigned int slow = (clk < 1249000000U) ? 1U : 0U; 439*b35ce0c4SPankaj Gupta const unsigned int x4_en = popts->x4_en; 440*b35ce0c4SPankaj Gupta const unsigned int obc_cfg = popts->otf_burst_chop_en; 441*b35ce0c4SPankaj Gupta const unsigned int ap_en = ip_rev == 0x50500U ? 0U : popts->ap_en; 442*b35ce0c4SPankaj Gupta const unsigned int d_init = popts->ctlr_init_ecc; 443*b35ce0c4SPankaj Gupta const unsigned int rcw_en = popts->rdimm; 444*b35ce0c4SPankaj Gupta const unsigned int md_en = popts->mirrored_dimm; 445*b35ce0c4SPankaj Gupta const unsigned int qd_en = popts->quad_rank_present; 446*b35ce0c4SPankaj Gupta const unsigned int unq_mrs_en = ip_rev < 0x50500U ? 1U : 0U; 447*b35ce0c4SPankaj Gupta const unsigned int rd_pre = popts->quad_rank_present; 448*b35ce0c4SPankaj Gupta int i; 449*b35ce0c4SPankaj Gupta 450*b35ce0c4SPankaj Gupta regs->sdram_cfg[0] = ((mem_en & 0x1) << 31) | 451*b35ce0c4SPankaj Gupta ((sren & 0x1) << 30) | 452*b35ce0c4SPankaj Gupta ((ecc_en & 0x1) << 29) | 453*b35ce0c4SPankaj Gupta ((rd_en & 0x1) << 28) | 454*b35ce0c4SPankaj Gupta ((sdram_type & 0x7) << 24) | 455*b35ce0c4SPankaj Gupta ((dyn_pwr & 0x1) << 21) | 456*b35ce0c4SPankaj Gupta ((dbw & 0x3) << 19) | 457*b35ce0c4SPankaj Gupta ((eight_be & 0x1) << 18) | 458*b35ce0c4SPankaj Gupta ((ncap & 0x1) << 17) | 459*b35ce0c4SPankaj Gupta ((threet_en & 0x1) << 16) | 460*b35ce0c4SPankaj Gupta ((twot_en & 0x1) << 15) | 461*b35ce0c4SPankaj Gupta ((ba_intlv & 0x7F) << 8) | 462*b35ce0c4SPankaj Gupta ((x32_en & 0x1) << 5) | 463*b35ce0c4SPankaj Gupta ((pchb8 & 0x1) << 4) | 464*b35ce0c4SPankaj Gupta ((hse & 0x1) << 3) | 465*b35ce0c4SPankaj Gupta ((acc_ecc_en & 0x1) << 2) | 466*b35ce0c4SPankaj Gupta ((mem_halt & 0x1) << 1) | 467*b35ce0c4SPankaj Gupta ((bi & 0x1) << 0); 468*b35ce0c4SPankaj Gupta debug("sdram_cfg[0] = 0x%x\n", regs->sdram_cfg[0]); 469*b35ce0c4SPankaj Gupta 470*b35ce0c4SPankaj Gupta for (i = 0; i < DDRC_NUM_CS; i++) { 471*b35ce0c4SPankaj Gupta if (popts->cs_odt[i].odt_rd_cfg != 0 || 472*b35ce0c4SPankaj Gupta popts->cs_odt[i].odt_wr_cfg != 0) { 473*b35ce0c4SPankaj Gupta odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; 474*b35ce0c4SPankaj Gupta break; 475*b35ce0c4SPankaj Gupta } 476*b35ce0c4SPankaj Gupta } 477*b35ce0c4SPankaj Gupta 478*b35ce0c4SPankaj Gupta regs->sdram_cfg[1] = (0 479*b35ce0c4SPankaj Gupta | ((frc_sr & 0x1) << 31) 480*b35ce0c4SPankaj Gupta | ((sr_ie & 0x1) << 30) 481*b35ce0c4SPankaj Gupta | ((odt_cfg & 0x3) << 21) 482*b35ce0c4SPankaj Gupta | ((num_pr & 0xf) << 12) 483*b35ce0c4SPankaj Gupta | ((slow & 1) << 11) 484*b35ce0c4SPankaj Gupta | (x4_en << 10) 485*b35ce0c4SPankaj Gupta | (qd_en << 9) 486*b35ce0c4SPankaj Gupta | (unq_mrs_en << 8) 487*b35ce0c4SPankaj Gupta | ((obc_cfg & 0x1) << 6) 488*b35ce0c4SPankaj Gupta | ((ap_en & 0x1) << 5) 489*b35ce0c4SPankaj Gupta | ((d_init & 0x1) << 4) 490*b35ce0c4SPankaj Gupta | ((rcw_en & 0x1) << 2) 491*b35ce0c4SPankaj Gupta | ((md_en & 0x1) << 0) 492*b35ce0c4SPankaj Gupta ); 493*b35ce0c4SPankaj Gupta debug("sdram_cfg[1] = 0x%x\n", regs->sdram_cfg[1]); 494*b35ce0c4SPankaj Gupta 495*b35ce0c4SPankaj Gupta regs->sdram_cfg[2] = (rd_pre & 0x1) << 16 | 496*b35ce0c4SPankaj Gupta (popts->rdimm ? 1 : 0); 497*b35ce0c4SPankaj Gupta if (pdimm->package_3ds != 0) { 498*b35ce0c4SPankaj Gupta if (((pdimm->package_3ds + 1) & 0x1) != 0) { 499*b35ce0c4SPankaj Gupta WARN("Unsupported 3DS DIMM\n"); 500*b35ce0c4SPankaj Gupta } else { 501*b35ce0c4SPankaj Gupta regs->sdram_cfg[2] |= ((pdimm->package_3ds + 1) >> 1) 502*b35ce0c4SPankaj Gupta << 4; 503*b35ce0c4SPankaj Gupta } 504*b35ce0c4SPankaj Gupta } 505*b35ce0c4SPankaj Gupta debug("sdram_cfg[2] = 0x%x\n", regs->sdram_cfg[2]); 506*b35ce0c4SPankaj Gupta } 507*b35ce0c4SPankaj Gupta 508*b35ce0c4SPankaj Gupta 509*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_interval(const unsigned long clk, 510*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 511*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 512*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 513*b35ce0c4SPankaj Gupta { 514*b35ce0c4SPankaj Gupta const unsigned int refint = picos_to_mclk(clk, pdimm->refresh_rate_ps); 515*b35ce0c4SPankaj Gupta const unsigned int bstopre = popts->bstopre; 516*b35ce0c4SPankaj Gupta 517*b35ce0c4SPankaj Gupta regs->interval = ((refint & 0xFFFF) << 16) | 518*b35ce0c4SPankaj Gupta ((bstopre & 0x3FFF) << 0); 519*b35ce0c4SPankaj Gupta debug("interval = 0x%x\n", regs->interval); 520*b35ce0c4SPankaj Gupta } 521*b35ce0c4SPankaj Gupta 522*b35ce0c4SPankaj Gupta /* Require cs and cfg first */ 523*b35ce0c4SPankaj Gupta static void cal_ddr_sdram_mode(const unsigned long clk, 524*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 525*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 526*b35ce0c4SPankaj Gupta const struct ddr_conf *conf, 527*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm, 528*b35ce0c4SPankaj Gupta unsigned int cas_latency, 529*b35ce0c4SPankaj Gupta unsigned int additive_latency, 530*b35ce0c4SPankaj Gupta const unsigned int ip_rev) 531*b35ce0c4SPankaj Gupta { 532*b35ce0c4SPankaj Gupta int i; 533*b35ce0c4SPankaj Gupta unsigned short esdmode; /* Extended SDRAM mode */ 534*b35ce0c4SPankaj Gupta unsigned short sdmode; /* SDRAM mode */ 535*b35ce0c4SPankaj Gupta 536*b35ce0c4SPankaj Gupta /* Mode Register - MR1 */ 537*b35ce0c4SPankaj Gupta const unsigned int qoff = 0; 538*b35ce0c4SPankaj Gupta const unsigned int tdqs_en = 0; 539*b35ce0c4SPankaj Gupta unsigned int rtt; 540*b35ce0c4SPankaj Gupta const unsigned int wrlvl_en = 0; 541*b35ce0c4SPankaj Gupta unsigned int al = 0; 542*b35ce0c4SPankaj Gupta unsigned int dic = 0; 543*b35ce0c4SPankaj Gupta const unsigned int dll_en = 1; 544*b35ce0c4SPankaj Gupta 545*b35ce0c4SPankaj Gupta /* Mode Register - MR0 */ 546*b35ce0c4SPankaj Gupta unsigned int wr = 0; 547*b35ce0c4SPankaj Gupta const unsigned int dll_rst = 0; 548*b35ce0c4SPankaj Gupta const unsigned int mode = 0; 549*b35ce0c4SPankaj Gupta unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ 550*b35ce0c4SPankaj Gupta /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ 551*b35ce0c4SPankaj Gupta const unsigned int bt = 0; 552*b35ce0c4SPankaj Gupta const unsigned int bl = popts->burst_length == DDR_BL8 ? 0 : 553*b35ce0c4SPankaj Gupta (popts->burst_length == DDR_BC4 ? 2 : 1); 554*b35ce0c4SPankaj Gupta 555*b35ce0c4SPankaj Gupta const unsigned int wr_mclk = picos_to_mclk(clk, pdimm->twr_ps); 556*b35ce0c4SPankaj Gupta /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */ 557*b35ce0c4SPankaj Gupta static const int wr_table[] = { 558*b35ce0c4SPankaj Gupta 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6 559*b35ce0c4SPankaj Gupta }; 560*b35ce0c4SPankaj Gupta /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */ 561*b35ce0c4SPankaj Gupta static const int cas_latency_table[] = { 562*b35ce0c4SPankaj Gupta 0, 1, 2, 3, 4, 5, 6, 7, 13, 8, 563*b35ce0c4SPankaj Gupta 14, 9, 15, 10, 12, 11, 16, 17, 564*b35ce0c4SPankaj Gupta 18, 19, 20, 21, 22, 23 565*b35ce0c4SPankaj Gupta }; 566*b35ce0c4SPankaj Gupta const unsigned int unq_mrs_en = ip_rev < U(0x50500) ? 1U : 0U; 567*b35ce0c4SPankaj Gupta unsigned short esdmode2 = 0U; 568*b35ce0c4SPankaj Gupta unsigned short esdmode3 = 0U; 569*b35ce0c4SPankaj Gupta const unsigned int wr_crc = 0U; 570*b35ce0c4SPankaj Gupta unsigned int rtt_wr = 0U; 571*b35ce0c4SPankaj Gupta const unsigned int srt = 0U; 572*b35ce0c4SPankaj Gupta unsigned int cwl = cal_cwl(clk); 573*b35ce0c4SPankaj Gupta const unsigned int mpr = 0U; 574*b35ce0c4SPankaj Gupta const unsigned int mclk_ps = get_memory_clk_ps(clk); 575*b35ce0c4SPankaj Gupta const unsigned int wc_lat = 0U; 576*b35ce0c4SPankaj Gupta unsigned short esdmode4 = 0U; 577*b35ce0c4SPankaj Gupta unsigned short esdmode5; 578*b35ce0c4SPankaj Gupta int rtt_park_all = 0; 579*b35ce0c4SPankaj Gupta unsigned int rtt_park; 580*b35ce0c4SPankaj Gupta const bool four_cs = conf->cs_in_use == 0xf ? true : false; 581*b35ce0c4SPankaj Gupta unsigned short esdmode6 = 0U; /* Extended SDRAM mode 6 */ 582*b35ce0c4SPankaj Gupta unsigned short esdmode7 = 0U; /* Extended SDRAM mode 7 */ 583*b35ce0c4SPankaj Gupta const unsigned int tccdl_min = max(5U, 584*b35ce0c4SPankaj Gupta picos_to_mclk(clk, pdimm->tccdl_ps)); 585*b35ce0c4SPankaj Gupta 586*b35ce0c4SPankaj Gupta if (popts->rtt_override != 0U) { 587*b35ce0c4SPankaj Gupta rtt = popts->rtt_override_value; 588*b35ce0c4SPankaj Gupta } else { 589*b35ce0c4SPankaj Gupta rtt = popts->cs_odt[0].odt_rtt_norm; 590*b35ce0c4SPankaj Gupta } 591*b35ce0c4SPankaj Gupta 592*b35ce0c4SPankaj Gupta if (additive_latency == (cas_latency - 1)) { 593*b35ce0c4SPankaj Gupta al = 1; 594*b35ce0c4SPankaj Gupta } 595*b35ce0c4SPankaj Gupta if (additive_latency == (cas_latency - 2)) { 596*b35ce0c4SPankaj Gupta al = 2; 597*b35ce0c4SPankaj Gupta } 598*b35ce0c4SPankaj Gupta 599*b35ce0c4SPankaj Gupta if (popts->quad_rank_present != 0 || popts->output_driver_impedance != 0) { 600*b35ce0c4SPankaj Gupta dic = 1; /* output driver impedance 240/7 ohm */ 601*b35ce0c4SPankaj Gupta } 602*b35ce0c4SPankaj Gupta 603*b35ce0c4SPankaj Gupta esdmode = (((qoff & 0x1) << 12) | 604*b35ce0c4SPankaj Gupta ((tdqs_en & 0x1) << 11) | 605*b35ce0c4SPankaj Gupta ((rtt & 0x7) << 8) | 606*b35ce0c4SPankaj Gupta ((wrlvl_en & 0x1) << 7) | 607*b35ce0c4SPankaj Gupta ((al & 0x3) << 3) | 608*b35ce0c4SPankaj Gupta ((dic & 0x3) << 1) | 609*b35ce0c4SPankaj Gupta ((dll_en & 0x1) << 0)); 610*b35ce0c4SPankaj Gupta 611*b35ce0c4SPankaj Gupta if (wr_mclk >= 10 && wr_mclk <= 24) { 612*b35ce0c4SPankaj Gupta wr = wr_table[wr_mclk - 10]; 613*b35ce0c4SPankaj Gupta } else { 614*b35ce0c4SPankaj Gupta ERROR("unsupported wc_mclk = %d for mode register\n", wr_mclk); 615*b35ce0c4SPankaj Gupta } 616*b35ce0c4SPankaj Gupta 617*b35ce0c4SPankaj Gupta /* look up table to get the cas latency bits */ 618*b35ce0c4SPankaj Gupta if (cas_latency >= 9 && cas_latency <= 32) { 619*b35ce0c4SPankaj Gupta caslat = cas_latency_table[cas_latency - 9]; 620*b35ce0c4SPankaj Gupta } else { 621*b35ce0c4SPankaj Gupta WARN("Error: unsupported cas latency for mode register\n"); 622*b35ce0c4SPankaj Gupta } 623*b35ce0c4SPankaj Gupta 624*b35ce0c4SPankaj Gupta sdmode = (((caslat & 0x10) << 8) | 625*b35ce0c4SPankaj Gupta ((wr & 0x7) << 9) | 626*b35ce0c4SPankaj Gupta ((dll_rst & 0x1) << 8) | 627*b35ce0c4SPankaj Gupta ((mode & 0x1) << 7) | 628*b35ce0c4SPankaj Gupta (((caslat >> 1) & 0x7) << 4) | 629*b35ce0c4SPankaj Gupta ((bt & 0x1) << 3) | 630*b35ce0c4SPankaj Gupta ((caslat & 1) << 2) | 631*b35ce0c4SPankaj Gupta ((bl & 0x3) << 0)); 632*b35ce0c4SPankaj Gupta 633*b35ce0c4SPankaj Gupta regs->sdram_mode[0] = (((esdmode & 0xFFFF) << 16) | 634*b35ce0c4SPankaj Gupta ((sdmode & 0xFFFF) << 0)); 635*b35ce0c4SPankaj Gupta debug("sdram_mode[0] = 0x%x\n", regs->sdram_mode[0]); 636*b35ce0c4SPankaj Gupta 637*b35ce0c4SPankaj Gupta switch (cwl) { 638*b35ce0c4SPankaj Gupta case 9: 639*b35ce0c4SPankaj Gupta case 10: 640*b35ce0c4SPankaj Gupta case 11: 641*b35ce0c4SPankaj Gupta case 12: 642*b35ce0c4SPankaj Gupta cwl -= 9; 643*b35ce0c4SPankaj Gupta break; 644*b35ce0c4SPankaj Gupta case 14: 645*b35ce0c4SPankaj Gupta cwl -= 10; 646*b35ce0c4SPankaj Gupta break; 647*b35ce0c4SPankaj Gupta case 16: 648*b35ce0c4SPankaj Gupta cwl -= 11; 649*b35ce0c4SPankaj Gupta break; 650*b35ce0c4SPankaj Gupta case 18: 651*b35ce0c4SPankaj Gupta cwl -= 12; 652*b35ce0c4SPankaj Gupta break; 653*b35ce0c4SPankaj Gupta case 20: 654*b35ce0c4SPankaj Gupta cwl -= 13; 655*b35ce0c4SPankaj Gupta break; 656*b35ce0c4SPankaj Gupta default: 657*b35ce0c4SPankaj Gupta printf("Error CWL\n"); 658*b35ce0c4SPankaj Gupta break; 659*b35ce0c4SPankaj Gupta } 660*b35ce0c4SPankaj Gupta 661*b35ce0c4SPankaj Gupta if (popts->rtt_override != 0) { 662*b35ce0c4SPankaj Gupta rtt_wr = popts->rtt_wr_override_value; 663*b35ce0c4SPankaj Gupta } else { 664*b35ce0c4SPankaj Gupta rtt_wr = popts->cs_odt[0].odt_rtt_wr; 665*b35ce0c4SPankaj Gupta } 666*b35ce0c4SPankaj Gupta 667*b35ce0c4SPankaj Gupta esdmode2 = ((wr_crc & 0x1) << 12) | 668*b35ce0c4SPankaj Gupta ((rtt_wr & 0x7) << 9) | 669*b35ce0c4SPankaj Gupta ((srt & 0x3) << 6) | 670*b35ce0c4SPankaj Gupta ((cwl & 0x7) << 3); 671*b35ce0c4SPankaj Gupta esdmode3 = ((mpr & 0x3) << 11) | ((wc_lat & 0x3) << 9); 672*b35ce0c4SPankaj Gupta 673*b35ce0c4SPankaj Gupta regs->sdram_mode[1] = ((esdmode2 & 0xFFFF) << 16) | 674*b35ce0c4SPankaj Gupta ((esdmode3 & 0xFFFF) << 0); 675*b35ce0c4SPankaj Gupta debug("sdram_mode[1] = 0x%x\n", regs->sdram_mode[1]); 676*b35ce0c4SPankaj Gupta 677*b35ce0c4SPankaj Gupta esdmode6 = ((tccdl_min - 4) & 0x7) << 10; 678*b35ce0c4SPankaj Gupta if (popts->vref_dimm != 0) { 679*b35ce0c4SPankaj Gupta esdmode6 |= popts->vref_dimm & 0x7f; 680*b35ce0c4SPankaj Gupta } else if ((popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) != 0) { 681*b35ce0c4SPankaj Gupta esdmode6 |= 1 << 6; /* Range 2 */ 682*b35ce0c4SPankaj Gupta } 683*b35ce0c4SPankaj Gupta 684*b35ce0c4SPankaj Gupta regs->sdram_mode[9] = ((esdmode6 & 0xffff) << 16) | 685*b35ce0c4SPankaj Gupta ((esdmode7 & 0xffff) << 0); 686*b35ce0c4SPankaj Gupta debug("sdram_mode[9] = 0x%x\n", regs->sdram_mode[9]); 687*b35ce0c4SPankaj Gupta 688*b35ce0c4SPankaj Gupta rtt_park = (popts->rtt_park != 0) ? popts->rtt_park : 240; 689*b35ce0c4SPankaj Gupta switch (rtt_park) { 690*b35ce0c4SPankaj Gupta case 240: 691*b35ce0c4SPankaj Gupta rtt_park = 0x4; 692*b35ce0c4SPankaj Gupta break; 693*b35ce0c4SPankaj Gupta case 120: 694*b35ce0c4SPankaj Gupta rtt_park = 0x2; 695*b35ce0c4SPankaj Gupta break; 696*b35ce0c4SPankaj Gupta case 80: 697*b35ce0c4SPankaj Gupta rtt_park = 0x6; 698*b35ce0c4SPankaj Gupta break; 699*b35ce0c4SPankaj Gupta case 60: 700*b35ce0c4SPankaj Gupta rtt_park = 0x1; 701*b35ce0c4SPankaj Gupta break; 702*b35ce0c4SPankaj Gupta case 48: 703*b35ce0c4SPankaj Gupta rtt_park = 0x5; 704*b35ce0c4SPankaj Gupta break; 705*b35ce0c4SPankaj Gupta case 40: 706*b35ce0c4SPankaj Gupta rtt_park = 0x3; 707*b35ce0c4SPankaj Gupta break; 708*b35ce0c4SPankaj Gupta case 34: 709*b35ce0c4SPankaj Gupta rtt_park = 0x7; 710*b35ce0c4SPankaj Gupta break; 711*b35ce0c4SPankaj Gupta default: 712*b35ce0c4SPankaj Gupta rtt_park = 0; 713*b35ce0c4SPankaj Gupta break; 714*b35ce0c4SPankaj Gupta } 715*b35ce0c4SPankaj Gupta 716*b35ce0c4SPankaj Gupta for (i = 0; i < DDRC_NUM_CS; i++) { 717*b35ce0c4SPankaj Gupta if (i != 0 && unq_mrs_en == 0) { 718*b35ce0c4SPankaj Gupta break; 719*b35ce0c4SPankaj Gupta } 720*b35ce0c4SPankaj Gupta 721*b35ce0c4SPankaj Gupta if (popts->rtt_override != 0) { 722*b35ce0c4SPankaj Gupta rtt = popts->rtt_override_value; 723*b35ce0c4SPankaj Gupta rtt_wr = popts->rtt_wr_override_value; 724*b35ce0c4SPankaj Gupta } else { 725*b35ce0c4SPankaj Gupta rtt = popts->cs_odt[i].odt_rtt_norm; 726*b35ce0c4SPankaj Gupta rtt_wr = popts->cs_odt[i].odt_rtt_wr; 727*b35ce0c4SPankaj Gupta } 728*b35ce0c4SPankaj Gupta 729*b35ce0c4SPankaj Gupta esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */ 730*b35ce0c4SPankaj Gupta esdmode |= (rtt & 0x7) << 8; 731*b35ce0c4SPankaj Gupta esdmode2 &= 0xF9FF; /* clear bit 10, 9 */ 732*b35ce0c4SPankaj Gupta esdmode2 |= (rtt_wr & 0x3) << 9; 733*b35ce0c4SPankaj Gupta esdmode5 = (popts->x4_en) ? 0 : 0x400; /* data mask */ 734*b35ce0c4SPankaj Gupta 735*b35ce0c4SPankaj Gupta if (rtt_park_all == 0 && 736*b35ce0c4SPankaj Gupta ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) != 0)) { 737*b35ce0c4SPankaj Gupta esdmode5 |= rtt_park << 6; 738*b35ce0c4SPankaj Gupta rtt_park_all = four_cs ? 0 : 1; 739*b35ce0c4SPankaj Gupta } 740*b35ce0c4SPankaj Gupta 741*b35ce0c4SPankaj Gupta if (((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) && 742*b35ce0c4SPankaj Gupta (popts->rdimm == 0)) { 743*b35ce0c4SPankaj Gupta if (mclk_ps >= 935) { 744*b35ce0c4SPankaj Gupta esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; 745*b35ce0c4SPankaj Gupta } else if (mclk_ps >= 833) { 746*b35ce0c4SPankaj Gupta esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; 747*b35ce0c4SPankaj Gupta } else { 748*b35ce0c4SPankaj Gupta esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; 749*b35ce0c4SPankaj Gupta WARN("mclk_ps not supported %d", mclk_ps); 750*b35ce0c4SPankaj Gupta 751*b35ce0c4SPankaj Gupta } 752*b35ce0c4SPankaj Gupta } 753*b35ce0c4SPankaj Gupta 754*b35ce0c4SPankaj Gupta switch (i) { 755*b35ce0c4SPankaj Gupta case 0: 756*b35ce0c4SPankaj Gupta regs->sdram_mode[8] = ((esdmode4 & 0xffff) << 16) | 757*b35ce0c4SPankaj Gupta ((esdmode5 & 0xffff) << 0); 758*b35ce0c4SPankaj Gupta debug("sdram_mode[8] = 0x%x\n", regs->sdram_mode[8]); 759*b35ce0c4SPankaj Gupta break; 760*b35ce0c4SPankaj Gupta case 1: 761*b35ce0c4SPankaj Gupta regs->sdram_mode[2] = (((esdmode & 0xFFFF) << 16) | 762*b35ce0c4SPankaj Gupta ((sdmode & 0xFFFF) << 0)); 763*b35ce0c4SPankaj Gupta regs->sdram_mode[3] = ((esdmode2 & 0xFFFF) << 16) | 764*b35ce0c4SPankaj Gupta ((esdmode3 & 0xFFFF) << 0); 765*b35ce0c4SPankaj Gupta regs->sdram_mode[10] = ((esdmode4 & 0xFFFF) << 16) | 766*b35ce0c4SPankaj Gupta ((esdmode5 & 0xFFFF) << 0); 767*b35ce0c4SPankaj Gupta regs->sdram_mode[11] = ((esdmode6 & 0xFFFF) << 16) | 768*b35ce0c4SPankaj Gupta ((esdmode7 & 0xFFFF) << 0); 769*b35ce0c4SPankaj Gupta debug("sdram_mode[2] = 0x%x\n", regs->sdram_mode[2]); 770*b35ce0c4SPankaj Gupta debug("sdram_mode[3] = 0x%x\n", regs->sdram_mode[3]); 771*b35ce0c4SPankaj Gupta debug("sdram_mode[10] = 0x%x\n", regs->sdram_mode[10]); 772*b35ce0c4SPankaj Gupta debug("sdram_mode[11] = 0x%x\n", regs->sdram_mode[11]); 773*b35ce0c4SPankaj Gupta break; 774*b35ce0c4SPankaj Gupta case 2: 775*b35ce0c4SPankaj Gupta regs->sdram_mode[4] = (((esdmode & 0xFFFF) << 16) | 776*b35ce0c4SPankaj Gupta ((sdmode & 0xFFFF) << 0)); 777*b35ce0c4SPankaj Gupta regs->sdram_mode[5] = ((esdmode2 & 0xFFFF) << 16) | 778*b35ce0c4SPankaj Gupta ((esdmode3 & 0xFFFF) << 0); 779*b35ce0c4SPankaj Gupta regs->sdram_mode[12] = ((esdmode4 & 0xFFFF) << 16) | 780*b35ce0c4SPankaj Gupta ((esdmode5 & 0xFFFF) << 0); 781*b35ce0c4SPankaj Gupta regs->sdram_mode[13] = ((esdmode6 & 0xFFFF) << 16) | 782*b35ce0c4SPankaj Gupta ((esdmode7 & 0xFFFF) << 0); 783*b35ce0c4SPankaj Gupta debug("sdram_mode[4] = 0x%x\n", regs->sdram_mode[4]); 784*b35ce0c4SPankaj Gupta debug("sdram_mode[5] = 0x%x\n", regs->sdram_mode[5]); 785*b35ce0c4SPankaj Gupta debug("sdram_mode[12] = 0x%x\n", regs->sdram_mode[12]); 786*b35ce0c4SPankaj Gupta debug("sdram_mode[13] = 0x%x\n", regs->sdram_mode[13]); 787*b35ce0c4SPankaj Gupta break; 788*b35ce0c4SPankaj Gupta case 3: 789*b35ce0c4SPankaj Gupta regs->sdram_mode[6] = (((esdmode & 0xFFFF) << 16) | 790*b35ce0c4SPankaj Gupta ((sdmode & 0xFFFF) << 0)); 791*b35ce0c4SPankaj Gupta regs->sdram_mode[7] = ((esdmode2 & 0xFFFF) << 16) | 792*b35ce0c4SPankaj Gupta ((esdmode3 & 0xFFFF) << 0); 793*b35ce0c4SPankaj Gupta regs->sdram_mode[14] = ((esdmode4 & 0xFFFF) << 16) | 794*b35ce0c4SPankaj Gupta ((esdmode5 & 0xFFFF) << 0); 795*b35ce0c4SPankaj Gupta regs->sdram_mode[15] = ((esdmode6 & 0xFFFF) << 16) | 796*b35ce0c4SPankaj Gupta ((esdmode7 & 0xFFFF) << 0); 797*b35ce0c4SPankaj Gupta debug("sdram_mode[6] = 0x%x\n", regs->sdram_mode[6]); 798*b35ce0c4SPankaj Gupta debug("sdram_mode[7] = 0x%x\n", regs->sdram_mode[7]); 799*b35ce0c4SPankaj Gupta debug("sdram_mode[14] = 0x%x\n", regs->sdram_mode[14]); 800*b35ce0c4SPankaj Gupta debug("sdram_mode[15] = 0x%x\n", regs->sdram_mode[15]); 801*b35ce0c4SPankaj Gupta break; 802*b35ce0c4SPankaj Gupta default: 803*b35ce0c4SPankaj Gupta break; 804*b35ce0c4SPankaj Gupta } 805*b35ce0c4SPankaj Gupta } 806*b35ce0c4SPankaj Gupta } 807*b35ce0c4SPankaj Gupta 808*b35ce0c4SPankaj Gupta #ifndef CONFIG_MEM_INIT_VALUE 809*b35ce0c4SPankaj Gupta #define CONFIG_MEM_INIT_VALUE 0xDEADBEEF 810*b35ce0c4SPankaj Gupta #endif 811*b35ce0c4SPankaj Gupta static void cal_ddr_data_init(struct ddr_cfg_regs *regs) 812*b35ce0c4SPankaj Gupta { 813*b35ce0c4SPankaj Gupta regs->data_init = CONFIG_MEM_INIT_VALUE; 814*b35ce0c4SPankaj Gupta } 815*b35ce0c4SPankaj Gupta 816*b35ce0c4SPankaj Gupta static void cal_ddr_dq_mapping(struct ddr_cfg_regs *regs, 817*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 818*b35ce0c4SPankaj Gupta { 819*b35ce0c4SPankaj Gupta const unsigned int acc_ecc_en = (regs->sdram_cfg[0] >> 2) & 0x1; 820*b35ce0c4SPankaj Gupta /* FIXME: revert the dq mapping from DIMM */ 821*b35ce0c4SPankaj Gupta regs->dq_map[0] = ((pdimm->dq_mapping[0] & 0x3F) << 26) | 822*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[1] & 0x3F) << 20) | 823*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[2] & 0x3F) << 14) | 824*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[3] & 0x3F) << 8) | 825*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[4] & 0x3F) << 2); 826*b35ce0c4SPankaj Gupta 827*b35ce0c4SPankaj Gupta regs->dq_map[1] = ((pdimm->dq_mapping[5] & 0x3F) << 26) | 828*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[6] & 0x3F) << 20) | 829*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[7] & 0x3F) << 14) | 830*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[10] & 0x3F) << 8) | 831*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[11] & 0x3F) << 2); 832*b35ce0c4SPankaj Gupta 833*b35ce0c4SPankaj Gupta regs->dq_map[2] = ((pdimm->dq_mapping[12] & 0x3F) << 26) | 834*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[13] & 0x3F) << 20) | 835*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[14] & 0x3F) << 14) | 836*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[15] & 0x3F) << 8) | 837*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[16] & 0x3F) << 2); 838*b35ce0c4SPankaj Gupta 839*b35ce0c4SPankaj Gupta /* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */ 840*b35ce0c4SPankaj Gupta regs->dq_map[3] = ((pdimm->dq_mapping[17] & 0x3F) << 26) | 841*b35ce0c4SPankaj Gupta ((pdimm->dq_mapping[8] & 0x3F) << 20) | 842*b35ce0c4SPankaj Gupta ((acc_ecc_en != 0) ? 0 : 843*b35ce0c4SPankaj Gupta (pdimm->dq_mapping[9] & 0x3F) << 14) | 844*b35ce0c4SPankaj Gupta pdimm->dq_mapping_ors; 845*b35ce0c4SPankaj Gupta debug("dq_map[0] = 0x%x\n", regs->dq_map[0]); 846*b35ce0c4SPankaj Gupta debug("dq_map[1] = 0x%x\n", regs->dq_map[1]); 847*b35ce0c4SPankaj Gupta debug("dq_map[2] = 0x%x\n", regs->dq_map[2]); 848*b35ce0c4SPankaj Gupta debug("dq_map[3] = 0x%x\n", regs->dq_map[3]); 849*b35ce0c4SPankaj Gupta } 850*b35ce0c4SPankaj Gupta static void cal_ddr_zq_cntl(struct ddr_cfg_regs *regs) 851*b35ce0c4SPankaj Gupta { 852*b35ce0c4SPankaj Gupta const unsigned int zqinit = 10U; /* 1024 clocks */ 853*b35ce0c4SPankaj Gupta const unsigned int zqoper = 9U; /* 512 clocks */ 854*b35ce0c4SPankaj Gupta const unsigned int zqcs = 7U; /* 128 clocks */ 855*b35ce0c4SPankaj Gupta const unsigned int zqcs_init = 5U; /* 1024 refresh seqences */ 856*b35ce0c4SPankaj Gupta const unsigned int zq_en = 1U; /* enabled */ 857*b35ce0c4SPankaj Gupta 858*b35ce0c4SPankaj Gupta regs->zq_cntl = ((zq_en & 0x1) << 31) | 859*b35ce0c4SPankaj Gupta ((zqinit & 0xF) << 24) | 860*b35ce0c4SPankaj Gupta ((zqoper & 0xF) << 16) | 861*b35ce0c4SPankaj Gupta ((zqcs & 0xF) << 8) | 862*b35ce0c4SPankaj Gupta ((zqcs_init & 0xF) << 0); 863*b35ce0c4SPankaj Gupta debug("zq_cntl = 0x%x\n", regs->zq_cntl); 864*b35ce0c4SPankaj Gupta } 865*b35ce0c4SPankaj Gupta 866*b35ce0c4SPankaj Gupta static void cal_ddr_sr_cntr(struct ddr_cfg_regs *regs, 867*b35ce0c4SPankaj Gupta const struct memctl_opt *popts) 868*b35ce0c4SPankaj Gupta { 869*b35ce0c4SPankaj Gupta const unsigned int sr_it = (popts->auto_self_refresh_en) ? 870*b35ce0c4SPankaj Gupta popts->sr_it : 0; 871*b35ce0c4SPankaj Gupta 872*b35ce0c4SPankaj Gupta regs->ddr_sr_cntr = (sr_it & 0xF) << 16; 873*b35ce0c4SPankaj Gupta debug("ddr_sr_cntr = 0x%x\n", regs->ddr_sr_cntr); 874*b35ce0c4SPankaj Gupta } 875*b35ce0c4SPankaj Gupta 876*b35ce0c4SPankaj Gupta static void cal_ddr_eor(struct ddr_cfg_regs *regs, 877*b35ce0c4SPankaj Gupta const struct memctl_opt *popts) 878*b35ce0c4SPankaj Gupta { 879*b35ce0c4SPankaj Gupta if (popts->addr_hash != 0) { 880*b35ce0c4SPankaj Gupta regs->eor = 0x40000000; /* address hash enable */ 881*b35ce0c4SPankaj Gupta debug("eor = 0x%x\n", regs->eor); 882*b35ce0c4SPankaj Gupta } 883*b35ce0c4SPankaj Gupta } 884*b35ce0c4SPankaj Gupta 885*b35ce0c4SPankaj Gupta static void cal_ddr_csn_bnds(struct ddr_cfg_regs *regs, 886*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 887*b35ce0c4SPankaj Gupta const struct ddr_conf *conf, 888*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm) 889*b35ce0c4SPankaj Gupta { 890*b35ce0c4SPankaj Gupta int i; 891*b35ce0c4SPankaj Gupta unsigned long long ea, sa; 892*b35ce0c4SPankaj Gupta 893*b35ce0c4SPankaj Gupta /* Chip Select Memory Bounds (CSn_BNDS) */ 894*b35ce0c4SPankaj Gupta for (i = 0; 895*b35ce0c4SPankaj Gupta i < DDRC_NUM_CS && conf->cs_size[i]; 896*b35ce0c4SPankaj Gupta i++) { 897*b35ce0c4SPankaj Gupta debug("cs_in_use = 0x%x\n", conf->cs_in_use); 898*b35ce0c4SPankaj Gupta if (conf->cs_in_use != 0) { 899*b35ce0c4SPankaj Gupta sa = conf->cs_base_addr[i]; 900*b35ce0c4SPankaj Gupta ea = sa + conf->cs_size[i] - 1; 901*b35ce0c4SPankaj Gupta sa >>= 24; 902*b35ce0c4SPankaj Gupta ea >>= 24; 903*b35ce0c4SPankaj Gupta regs->cs[i].bnds = ((sa & 0xffff) << 16) | 904*b35ce0c4SPankaj Gupta ((ea & 0xffff) << 0); 905*b35ce0c4SPankaj Gupta cal_csn_config(i, regs, popts, pdimm); 906*b35ce0c4SPankaj Gupta } else { 907*b35ce0c4SPankaj Gupta /* setting bnds to 0xffffffff for inactive CS */ 908*b35ce0c4SPankaj Gupta regs->cs[i].bnds = 0xffffffff; 909*b35ce0c4SPankaj Gupta } 910*b35ce0c4SPankaj Gupta 911*b35ce0c4SPankaj Gupta debug("cs[%d].bnds = 0x%x\n", i, regs->cs[i].bnds); 912*b35ce0c4SPankaj Gupta } 913*b35ce0c4SPankaj Gupta } 914*b35ce0c4SPankaj Gupta 915*b35ce0c4SPankaj Gupta static void cal_ddr_addr_dec(struct ddr_cfg_regs *regs) 916*b35ce0c4SPankaj Gupta { 917*b35ce0c4SPankaj Gupta #ifdef CONFIG_DDR_ADDR_DEC 918*b35ce0c4SPankaj Gupta unsigned int ba_bits __unused; 919*b35ce0c4SPankaj Gupta char p __unused; 920*b35ce0c4SPankaj Gupta const unsigned int cs0_config = regs->cs[0].config; 921*b35ce0c4SPankaj Gupta const int cacheline = PLATFORM_CACHE_LINE_SHIFT; 922*b35ce0c4SPankaj Gupta unsigned int bg_bits; 923*b35ce0c4SPankaj Gupta unsigned int row_bits; 924*b35ce0c4SPankaj Gupta unsigned int col_bits; 925*b35ce0c4SPankaj Gupta unsigned int cs; 926*b35ce0c4SPankaj Gupta unsigned int map_row[18]; 927*b35ce0c4SPankaj Gupta unsigned int map_col[11]; 928*b35ce0c4SPankaj Gupta unsigned int map_ba[2]; 929*b35ce0c4SPankaj Gupta unsigned int map_cid[2] = {0x3F, 0x3F}; 930*b35ce0c4SPankaj Gupta unsigned int map_bg[2] = {0x3F, 0x3F}; 931*b35ce0c4SPankaj Gupta unsigned int map_cs[2] = {0x3F, 0x3F}; 932*b35ce0c4SPankaj Gupta unsigned int dbw; 933*b35ce0c4SPankaj Gupta unsigned int ba_intlv; 934*b35ce0c4SPankaj Gupta int placement; 935*b35ce0c4SPankaj Gupta int intlv; 936*b35ce0c4SPankaj Gupta int abort = 0; 937*b35ce0c4SPankaj Gupta int i; 938*b35ce0c4SPankaj Gupta int j; 939*b35ce0c4SPankaj Gupta 940*b35ce0c4SPankaj Gupta col_bits = (cs0_config >> 0) & 0x7; 941*b35ce0c4SPankaj Gupta if (col_bits < 4) { 942*b35ce0c4SPankaj Gupta col_bits += 8; 943*b35ce0c4SPankaj Gupta } else if (col_bits < 7 || col_bits > 10) { 944*b35ce0c4SPankaj Gupta ERROR("Error %s col_bits = %d\n", __func__, col_bits); 945*b35ce0c4SPankaj Gupta } 946*b35ce0c4SPankaj Gupta row_bits = ((cs0_config >> 8) & 0x7) + 12; 947*b35ce0c4SPankaj Gupta ba_bits = ((cs0_config >> 14) & 0x3) + 2; 948*b35ce0c4SPankaj Gupta bg_bits = ((cs0_config >> 4) & 0x3) + 0; 949*b35ce0c4SPankaj Gupta intlv = (cs0_config >> 24) & 0xf; 950*b35ce0c4SPankaj Gupta ba_intlv = (regs->sdram_cfg[0] >> 8) & 0x7f; 951*b35ce0c4SPankaj Gupta switch (ba_intlv) { 952*b35ce0c4SPankaj Gupta case DDR_BA_INTLV_CS01: 953*b35ce0c4SPankaj Gupta cs = 1; 954*b35ce0c4SPankaj Gupta break; 955*b35ce0c4SPankaj Gupta case DDR_BA_INTLV_CS0123: 956*b35ce0c4SPankaj Gupta cs = 2; 957*b35ce0c4SPankaj Gupta break; 958*b35ce0c4SPankaj Gupta case DDR_BA_NONE: 959*b35ce0c4SPankaj Gupta cs = 0; 960*b35ce0c4SPankaj Gupta break; 961*b35ce0c4SPankaj Gupta default: 962*b35ce0c4SPankaj Gupta ERROR("%s ba_intlv 0x%x\n", __func__, ba_intlv); 963*b35ce0c4SPankaj Gupta return; 964*b35ce0c4SPankaj Gupta } 965*b35ce0c4SPankaj Gupta debug("col %d, row %d, ba %d, bg %d, intlv %d\n", 966*b35ce0c4SPankaj Gupta col_bits, row_bits, ba_bits, bg_bits, intlv); 967*b35ce0c4SPankaj Gupta /* 968*b35ce0c4SPankaj Gupta * Example mapping of 15x2x2x10 969*b35ce0c4SPankaj Gupta * ---- --rr rrrr rrrr rrrr rCBB Gccc cccI cGcc cbbb 970*b35ce0c4SPankaj Gupta */ 971*b35ce0c4SPankaj Gupta dbw = (regs->sdram_cfg[0] >> 19) & 0x3; 972*b35ce0c4SPankaj Gupta switch (dbw) { 973*b35ce0c4SPankaj Gupta case 0: /* 64-bit */ 974*b35ce0c4SPankaj Gupta placement = 3; 975*b35ce0c4SPankaj Gupta break; 976*b35ce0c4SPankaj Gupta case 1: /* 32-bit */ 977*b35ce0c4SPankaj Gupta placement = 2; 978*b35ce0c4SPankaj Gupta break; 979*b35ce0c4SPankaj Gupta default: 980*b35ce0c4SPankaj Gupta ERROR("%s dbw = %d\n", __func__, dbw); 981*b35ce0c4SPankaj Gupta return; 982*b35ce0c4SPankaj Gupta } 983*b35ce0c4SPankaj Gupta debug("cacheline size %d\n", cacheline); 984*b35ce0c4SPankaj Gupta for (i = 0; placement < cacheline; i++) { 985*b35ce0c4SPankaj Gupta map_col[i] = placement++; 986*b35ce0c4SPankaj Gupta } 987*b35ce0c4SPankaj Gupta map_bg[0] = placement++; 988*b35ce0c4SPankaj Gupta for ( ; i < col_bits; i++) { 989*b35ce0c4SPankaj Gupta map_col[i] = placement++; 990*b35ce0c4SPankaj Gupta if (placement == intlv) { 991*b35ce0c4SPankaj Gupta placement++; 992*b35ce0c4SPankaj Gupta } 993*b35ce0c4SPankaj Gupta } 994*b35ce0c4SPankaj Gupta for ( ; i < 11; i++) { 995*b35ce0c4SPankaj Gupta map_col[i] = 0x3F; /* unused col bits */ 996*b35ce0c4SPankaj Gupta } 997*b35ce0c4SPankaj Gupta 998*b35ce0c4SPankaj Gupta if (bg_bits >= 2) { 999*b35ce0c4SPankaj Gupta map_bg[1] = placement++; 1000*b35ce0c4SPankaj Gupta } 1001*b35ce0c4SPankaj Gupta map_ba[0] = placement++; 1002*b35ce0c4SPankaj Gupta map_ba[1] = placement++; 1003*b35ce0c4SPankaj Gupta if (cs != 0U) { 1004*b35ce0c4SPankaj Gupta map_cs[0] = placement++; 1005*b35ce0c4SPankaj Gupta if (cs == 2U) { 1006*b35ce0c4SPankaj Gupta map_cs[1] = placement++; 1007*b35ce0c4SPankaj Gupta } 1008*b35ce0c4SPankaj Gupta } else { 1009*b35ce0c4SPankaj Gupta map_cs[0] = U(0x3F); 1010*b35ce0c4SPankaj Gupta } 1011*b35ce0c4SPankaj Gupta 1012*b35ce0c4SPankaj Gupta for (i = 0; i < row_bits; i++) { 1013*b35ce0c4SPankaj Gupta map_row[i] = placement++; 1014*b35ce0c4SPankaj Gupta } 1015*b35ce0c4SPankaj Gupta 1016*b35ce0c4SPankaj Gupta for ( ; i < 18; i++) { 1017*b35ce0c4SPankaj Gupta map_row[i] = 0x3F; /* unused row bits */ 1018*b35ce0c4SPankaj Gupta } 1019*b35ce0c4SPankaj Gupta 1020*b35ce0c4SPankaj Gupta for (i = 39; i >= 0 ; i--) { 1021*b35ce0c4SPankaj Gupta if (i == intlv) { 1022*b35ce0c4SPankaj Gupta placement = 8; 1023*b35ce0c4SPankaj Gupta p = 'I'; 1024*b35ce0c4SPankaj Gupta } else if (i < 3) { 1025*b35ce0c4SPankaj Gupta p = 'b'; 1026*b35ce0c4SPankaj Gupta placement = 0; 1027*b35ce0c4SPankaj Gupta } else { 1028*b35ce0c4SPankaj Gupta placement = 0; 1029*b35ce0c4SPankaj Gupta p = '-'; 1030*b35ce0c4SPankaj Gupta } 1031*b35ce0c4SPankaj Gupta for (j = 0; j < 18; j++) { 1032*b35ce0c4SPankaj Gupta if (map_row[j] != i) { 1033*b35ce0c4SPankaj Gupta continue; 1034*b35ce0c4SPankaj Gupta } 1035*b35ce0c4SPankaj Gupta if (placement != 0) { 1036*b35ce0c4SPankaj Gupta abort = 1; 1037*b35ce0c4SPankaj Gupta ERROR("%s wrong address bit %d\n", __func__, i); 1038*b35ce0c4SPankaj Gupta } 1039*b35ce0c4SPankaj Gupta placement = i; 1040*b35ce0c4SPankaj Gupta p = 'r'; 1041*b35ce0c4SPankaj Gupta } 1042*b35ce0c4SPankaj Gupta for (j = 0; j < 11; j++) { 1043*b35ce0c4SPankaj Gupta if (map_col[j] != i) { 1044*b35ce0c4SPankaj Gupta continue; 1045*b35ce0c4SPankaj Gupta } 1046*b35ce0c4SPankaj Gupta if (placement != 0) { 1047*b35ce0c4SPankaj Gupta abort = 1; 1048*b35ce0c4SPankaj Gupta ERROR("%s wrong address bit %d\n", __func__, i); 1049*b35ce0c4SPankaj Gupta } 1050*b35ce0c4SPankaj Gupta placement = i; 1051*b35ce0c4SPankaj Gupta p = 'c'; 1052*b35ce0c4SPankaj Gupta } 1053*b35ce0c4SPankaj Gupta for (j = 0; j < 2; j++) { 1054*b35ce0c4SPankaj Gupta if (map_ba[j] != i) { 1055*b35ce0c4SPankaj Gupta continue; 1056*b35ce0c4SPankaj Gupta } 1057*b35ce0c4SPankaj Gupta if (placement != 0) { 1058*b35ce0c4SPankaj Gupta abort = 1; 1059*b35ce0c4SPankaj Gupta ERROR("%s wrong address bit %d\n", __func__, i); 1060*b35ce0c4SPankaj Gupta } 1061*b35ce0c4SPankaj Gupta placement = i; 1062*b35ce0c4SPankaj Gupta p = 'B'; 1063*b35ce0c4SPankaj Gupta } 1064*b35ce0c4SPankaj Gupta for (j = 0; j < 2; j++) { 1065*b35ce0c4SPankaj Gupta if (map_bg[j] != i) { 1066*b35ce0c4SPankaj Gupta continue; 1067*b35ce0c4SPankaj Gupta } 1068*b35ce0c4SPankaj Gupta if (placement != 0) { 1069*b35ce0c4SPankaj Gupta abort = 1; 1070*b35ce0c4SPankaj Gupta ERROR("%s wrong address bit %d\n", __func__, i); 1071*b35ce0c4SPankaj Gupta } 1072*b35ce0c4SPankaj Gupta placement = i; 1073*b35ce0c4SPankaj Gupta p = 'G'; 1074*b35ce0c4SPankaj Gupta } 1075*b35ce0c4SPankaj Gupta for (j = 0; j < 2; j++) { 1076*b35ce0c4SPankaj Gupta if (map_cs[j] != i) { 1077*b35ce0c4SPankaj Gupta continue; 1078*b35ce0c4SPankaj Gupta } 1079*b35ce0c4SPankaj Gupta if (placement != 0) { 1080*b35ce0c4SPankaj Gupta abort = 1; 1081*b35ce0c4SPankaj Gupta ERROR("%s wrong address bit %d\n", __func__, i); 1082*b35ce0c4SPankaj Gupta } 1083*b35ce0c4SPankaj Gupta placement = i; 1084*b35ce0c4SPankaj Gupta p = 'C'; 1085*b35ce0c4SPankaj Gupta } 1086*b35ce0c4SPankaj Gupta #ifdef DDR_DEBUG 1087*b35ce0c4SPankaj Gupta printf("%c", p); 1088*b35ce0c4SPankaj Gupta if ((i % 4) == 0) { 1089*b35ce0c4SPankaj Gupta printf(" "); 1090*b35ce0c4SPankaj Gupta } 1091*b35ce0c4SPankaj Gupta #endif 1092*b35ce0c4SPankaj Gupta } 1093*b35ce0c4SPankaj Gupta #ifdef DDR_DEBUG 1094*b35ce0c4SPankaj Gupta puts("\n"); 1095*b35ce0c4SPankaj Gupta #endif 1096*b35ce0c4SPankaj Gupta 1097*b35ce0c4SPankaj Gupta if (abort != 0) { 1098*b35ce0c4SPankaj Gupta return; 1099*b35ce0c4SPankaj Gupta } 1100*b35ce0c4SPankaj Gupta 1101*b35ce0c4SPankaj Gupta regs->dec[0] = map_row[17] << 26 | 1102*b35ce0c4SPankaj Gupta map_row[16] << 18 | 1103*b35ce0c4SPankaj Gupta map_row[15] << 10 | 1104*b35ce0c4SPankaj Gupta map_row[14] << 2; 1105*b35ce0c4SPankaj Gupta regs->dec[1] = map_row[13] << 26 | 1106*b35ce0c4SPankaj Gupta map_row[12] << 18 | 1107*b35ce0c4SPankaj Gupta map_row[11] << 10 | 1108*b35ce0c4SPankaj Gupta map_row[10] << 2; 1109*b35ce0c4SPankaj Gupta regs->dec[2] = map_row[9] << 26 | 1110*b35ce0c4SPankaj Gupta map_row[8] << 18 | 1111*b35ce0c4SPankaj Gupta map_row[7] << 10 | 1112*b35ce0c4SPankaj Gupta map_row[6] << 2; 1113*b35ce0c4SPankaj Gupta regs->dec[3] = map_row[5] << 26 | 1114*b35ce0c4SPankaj Gupta map_row[4] << 18 | 1115*b35ce0c4SPankaj Gupta map_row[3] << 10 | 1116*b35ce0c4SPankaj Gupta map_row[2] << 2; 1117*b35ce0c4SPankaj Gupta regs->dec[4] = map_row[1] << 26 | 1118*b35ce0c4SPankaj Gupta map_row[0] << 18 | 1119*b35ce0c4SPankaj Gupta map_col[10] << 10 | 1120*b35ce0c4SPankaj Gupta map_col[9] << 2; 1121*b35ce0c4SPankaj Gupta regs->dec[5] = map_col[8] << 26 | 1122*b35ce0c4SPankaj Gupta map_col[7] << 18 | 1123*b35ce0c4SPankaj Gupta map_col[6] << 10 | 1124*b35ce0c4SPankaj Gupta map_col[5] << 2; 1125*b35ce0c4SPankaj Gupta regs->dec[6] = map_col[4] << 26 | 1126*b35ce0c4SPankaj Gupta map_col[3] << 18 | 1127*b35ce0c4SPankaj Gupta map_col[2] << 10 | 1128*b35ce0c4SPankaj Gupta map_col[1] << 2; 1129*b35ce0c4SPankaj Gupta regs->dec[7] = map_col[0] << 26 | 1130*b35ce0c4SPankaj Gupta map_ba[1] << 18 | 1131*b35ce0c4SPankaj Gupta map_ba[0] << 10 | 1132*b35ce0c4SPankaj Gupta map_cid[1] << 2; 1133*b35ce0c4SPankaj Gupta regs->dec[8] = map_cid[1] << 26 | 1134*b35ce0c4SPankaj Gupta map_cs[1] << 18 | 1135*b35ce0c4SPankaj Gupta map_cs[0] << 10 | 1136*b35ce0c4SPankaj Gupta map_bg[1] << 2; 1137*b35ce0c4SPankaj Gupta regs->dec[9] = map_bg[0] << 26 | 1138*b35ce0c4SPankaj Gupta 1; 1139*b35ce0c4SPankaj Gupta for (i = 0; i < 10; i++) { 1140*b35ce0c4SPankaj Gupta debug("dec[%d] = 0x%x\n", i, regs->dec[i]); 1141*b35ce0c4SPankaj Gupta } 1142*b35ce0c4SPankaj Gupta #endif 1143*b35ce0c4SPankaj Gupta } 1144*b35ce0c4SPankaj Gupta static unsigned int skip_caslat(unsigned int tckmin_ps, 1145*b35ce0c4SPankaj Gupta unsigned int taamin_ps, 1146*b35ce0c4SPankaj Gupta unsigned int mclk_ps, 1147*b35ce0c4SPankaj Gupta unsigned int package_3ds) 1148*b35ce0c4SPankaj Gupta { 1149*b35ce0c4SPankaj Gupta int i, j, k; 1150*b35ce0c4SPankaj Gupta struct cas { 1151*b35ce0c4SPankaj Gupta const unsigned int tckmin_ps; 1152*b35ce0c4SPankaj Gupta const unsigned int caslat[4]; 1153*b35ce0c4SPankaj Gupta }; 1154*b35ce0c4SPankaj Gupta struct speed { 1155*b35ce0c4SPankaj Gupta const struct cas *cl; 1156*b35ce0c4SPankaj Gupta const unsigned int taamin_ps[4]; 1157*b35ce0c4SPankaj Gupta }; 1158*b35ce0c4SPankaj Gupta const struct cas cl_3200[] = { 1159*b35ce0c4SPankaj Gupta {625, {0xa00000, 0xb00000, 0xf000000,} }, 1160*b35ce0c4SPankaj Gupta {750, { 0x20000, 0x60000, 0xe00000,} }, 1161*b35ce0c4SPankaj Gupta {833, { 0x8000, 0x18000, 0x38000,} }, 1162*b35ce0c4SPankaj Gupta {937, { 0x4000, 0x4000, 0xc000,} }, 1163*b35ce0c4SPankaj Gupta {1071, { 0x1000, 0x1000, 0x3000,} }, 1164*b35ce0c4SPankaj Gupta {1250, { 0x400, 0x400, 0xc00,} }, 1165*b35ce0c4SPankaj Gupta {1500, { 0, 0x600, 0x200,} }, 1166*b35ce0c4SPankaj Gupta }; 1167*b35ce0c4SPankaj Gupta const struct cas cl_2933[] = { 1168*b35ce0c4SPankaj Gupta {682, { 0, 0x80000, 0x180000, 0x380000} }, 1169*b35ce0c4SPankaj Gupta {750, { 0x20000, 0x60000, 0x60000, 0xe0000} }, 1170*b35ce0c4SPankaj Gupta {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, 1171*b35ce0c4SPankaj Gupta {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, 1172*b35ce0c4SPankaj Gupta {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, 1173*b35ce0c4SPankaj Gupta {1250, { 0x400, 0x400, 0x400, 0xc00} }, 1174*b35ce0c4SPankaj Gupta {1500, { 0, 0x200, 0x200, 0x200} }, 1175*b35ce0c4SPankaj Gupta }; 1176*b35ce0c4SPankaj Gupta const struct cas cl_2666[] = { 1177*b35ce0c4SPankaj Gupta {750, { 0, 0x20000, 0x60000, 0xe0000} }, 1178*b35ce0c4SPankaj Gupta {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, 1179*b35ce0c4SPankaj Gupta {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, 1180*b35ce0c4SPankaj Gupta {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, 1181*b35ce0c4SPankaj Gupta {1250, { 0x400, 0x400, 0x400, 0xc00} }, 1182*b35ce0c4SPankaj Gupta {1500, { 0, 0, 0x200, 0x200} }, 1183*b35ce0c4SPankaj Gupta }; 1184*b35ce0c4SPankaj Gupta const struct cas cl_2400[] = { 1185*b35ce0c4SPankaj Gupta {833, { 0, 0x8000, 0x18000, 0x38000} }, 1186*b35ce0c4SPankaj Gupta {937, { 0xc000, 0x4000, 0x4000, 0xc000} }, 1187*b35ce0c4SPankaj Gupta {1071, { 0x3000, 0x1000, 0x1000, 0x3000} }, 1188*b35ce0c4SPankaj Gupta {1250, { 0xc00, 0x400, 0x400, 0xc00} }, 1189*b35ce0c4SPankaj Gupta {1500, { 0, 0x400, 0x200, 0x200} }, 1190*b35ce0c4SPankaj Gupta }; 1191*b35ce0c4SPankaj Gupta const struct cas cl_2133[] = { 1192*b35ce0c4SPankaj Gupta {937, { 0, 0x4000, 0xc000,} }, 1193*b35ce0c4SPankaj Gupta {1071, { 0x2000, 0, 0x2000,} }, 1194*b35ce0c4SPankaj Gupta {1250, { 0x800, 0, 0x800,} }, 1195*b35ce0c4SPankaj Gupta {1500, { 0, 0x400, 0x200,} }, 1196*b35ce0c4SPankaj Gupta }; 1197*b35ce0c4SPankaj Gupta const struct cas cl_1866[] = { 1198*b35ce0c4SPankaj Gupta {1071, { 0, 0x1000, 0x3000,} }, 1199*b35ce0c4SPankaj Gupta {1250, { 0xc00, 0x400, 0xc00,} }, 1200*b35ce0c4SPankaj Gupta {1500, { 0, 0x400, 0x200,} }, 1201*b35ce0c4SPankaj Gupta }; 1202*b35ce0c4SPankaj Gupta const struct cas cl_1600[] = { 1203*b35ce0c4SPankaj Gupta {1250, { 0, 0x400, 0xc00,} }, 1204*b35ce0c4SPankaj Gupta {1500, { 0, 0x400, 0x200,} }, 1205*b35ce0c4SPankaj Gupta }; 1206*b35ce0c4SPankaj Gupta const struct speed bin_0[] = { 1207*b35ce0c4SPankaj Gupta {cl_3200, {12500, 13750, 15000,} }, 1208*b35ce0c4SPankaj Gupta {cl_2933, {12960, 13640, 13750, 15000,} }, 1209*b35ce0c4SPankaj Gupta {cl_2666, {12750, 13500, 13750, 15000,} }, 1210*b35ce0c4SPankaj Gupta {cl_2400, {12500, 13320, 13750, 15000,} }, 1211*b35ce0c4SPankaj Gupta {cl_2133, {13130, 13500, 15000,} }, 1212*b35ce0c4SPankaj Gupta {cl_1866, {12850, 13500, 15000,} }, 1213*b35ce0c4SPankaj Gupta {cl_1600, {12500, 13500, 15000,} } 1214*b35ce0c4SPankaj Gupta }; 1215*b35ce0c4SPankaj Gupta const struct cas cl_3200_3ds[] = { 1216*b35ce0c4SPankaj Gupta {625, { 0xa000000, 0xb000000, 0xf000000,} }, 1217*b35ce0c4SPankaj Gupta {750, { 0xaa00000, 0xab00000, 0xef00000,} }, 1218*b35ce0c4SPankaj Gupta {833, { 0xaac0000, 0xaac0000, 0xebc0000,} }, 1219*b35ce0c4SPankaj Gupta {937, { 0xaab0000, 0xaab0000, 0xeaf0000,} }, 1220*b35ce0c4SPankaj Gupta {1071, { 0xaaa4000, 0xaaac000, 0xeaec000,} }, 1221*b35ce0c4SPankaj Gupta {1250, { 0xaaa0000, 0xaaa2000, 0xeaeb000,} }, 1222*b35ce0c4SPankaj Gupta }; 1223*b35ce0c4SPankaj Gupta const struct cas cl_2666_3ds[] = { 1224*b35ce0c4SPankaj Gupta {750, { 0xa00000, 0xb00000, 0xf00000,} }, 1225*b35ce0c4SPankaj Gupta {833, { 0xac0000, 0xac0000, 0xbc0000,} }, 1226*b35ce0c4SPankaj Gupta {937, { 0xab0000, 0xab0000, 0xaf0000,} }, 1227*b35ce0c4SPankaj Gupta {1071, { 0xaa4000, 0xaac000, 0xaac000,} }, 1228*b35ce0c4SPankaj Gupta {1250, { 0xaa0000, 0xaaa000, 0xaaa000,} }, 1229*b35ce0c4SPankaj Gupta }; 1230*b35ce0c4SPankaj Gupta const struct cas cl_2400_3ds[] = { 1231*b35ce0c4SPankaj Gupta {833, { 0xe00000, 0xe40000, 0xec0000, 0xb00000} }, 1232*b35ce0c4SPankaj Gupta {937, { 0xe00000, 0xe00000, 0xea0000, 0xae0000} }, 1233*b35ce0c4SPankaj Gupta {1071, { 0xe00000, 0xe04000, 0xeac000, 0xaec000} }, 1234*b35ce0c4SPankaj Gupta {1250, { 0xe00000, 0xe00000, 0xeaa000, 0xae2000} }, 1235*b35ce0c4SPankaj Gupta }; 1236*b35ce0c4SPankaj Gupta const struct cas cl_2133_3ds[] = { 1237*b35ce0c4SPankaj Gupta {937, { 0x90000, 0xb0000, 0xf0000,} }, 1238*b35ce0c4SPankaj Gupta {1071, { 0x84000, 0xac000, 0xec000,} }, 1239*b35ce0c4SPankaj Gupta {1250, { 0x80000, 0xa2000, 0xe2000,} }, 1240*b35ce0c4SPankaj Gupta }; 1241*b35ce0c4SPankaj Gupta const struct cas cl_1866_3ds[] = { 1242*b35ce0c4SPankaj Gupta {1071, { 0, 0x4000, 0xc000,} }, 1243*b35ce0c4SPankaj Gupta {1250, { 0, 0x1000, 0x3000,} }, 1244*b35ce0c4SPankaj Gupta }; 1245*b35ce0c4SPankaj Gupta const struct cas cl_1600_3ds[] = { 1246*b35ce0c4SPankaj Gupta {1250, { 0, 0x1000, 0x3000,} }, 1247*b35ce0c4SPankaj Gupta }; 1248*b35ce0c4SPankaj Gupta const struct speed bin_3ds[] = { 1249*b35ce0c4SPankaj Gupta {cl_3200_3ds, {15000, 16250, 17140,} }, 1250*b35ce0c4SPankaj Gupta {cl_2666_3ds, {15000, 16500, 17140,} }, 1251*b35ce0c4SPankaj Gupta {cl_2400_3ds, {15000, 15830, 16670, 17140} }, 1252*b35ce0c4SPankaj Gupta {cl_2133_3ds, {15950, 16880, 17140,} }, 1253*b35ce0c4SPankaj Gupta {cl_1866_3ds, {15000, 16070, 17140,} }, 1254*b35ce0c4SPankaj Gupta {cl_1600_3ds, {15000, 16250, 17500,} }, 1255*b35ce0c4SPankaj Gupta }; 1256*b35ce0c4SPankaj Gupta const struct speed *bin; 1257*b35ce0c4SPankaj Gupta int size; 1258*b35ce0c4SPankaj Gupta unsigned int taamin_max, tck_max; 1259*b35ce0c4SPankaj Gupta 1260*b35ce0c4SPankaj Gupta if (taamin_ps > ((package_3ds != 0) ? 21500 : 18000)) { 1261*b35ce0c4SPankaj Gupta ERROR("taamin_ps %u invalid\n", taamin_ps); 1262*b35ce0c4SPankaj Gupta return 0; 1263*b35ce0c4SPankaj Gupta } 1264*b35ce0c4SPankaj Gupta if (package_3ds != 0) { 1265*b35ce0c4SPankaj Gupta bin = bin_3ds; 1266*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(bin_3ds); 1267*b35ce0c4SPankaj Gupta taamin_max = 1250; 1268*b35ce0c4SPankaj Gupta tck_max = 1500; 1269*b35ce0c4SPankaj Gupta } else { 1270*b35ce0c4SPankaj Gupta bin = bin_0; 1271*b35ce0c4SPankaj Gupta size = ARRAY_SIZE(bin_0); 1272*b35ce0c4SPankaj Gupta taamin_max = 1500; 1273*b35ce0c4SPankaj Gupta tck_max = 1600; 1274*b35ce0c4SPankaj Gupta } 1275*b35ce0c4SPankaj Gupta if (mclk_ps < 625 || mclk_ps > tck_max) { 1276*b35ce0c4SPankaj Gupta ERROR("mclk %u invalid\n", mclk_ps); 1277*b35ce0c4SPankaj Gupta return 0; 1278*b35ce0c4SPankaj Gupta } 1279*b35ce0c4SPankaj Gupta 1280*b35ce0c4SPankaj Gupta for (i = 0; i < size; i++) { 1281*b35ce0c4SPankaj Gupta if (bin[i].cl[0].tckmin_ps >= tckmin_ps) { 1282*b35ce0c4SPankaj Gupta break; 1283*b35ce0c4SPankaj Gupta } 1284*b35ce0c4SPankaj Gupta } 1285*b35ce0c4SPankaj Gupta if (i >= size) { 1286*b35ce0c4SPankaj Gupta ERROR("speed bin not found\n"); 1287*b35ce0c4SPankaj Gupta return 0; 1288*b35ce0c4SPankaj Gupta } 1289*b35ce0c4SPankaj Gupta if (bin[i].cl[0].tckmin_ps > tckmin_ps && i > 0) { 1290*b35ce0c4SPankaj Gupta i--; 1291*b35ce0c4SPankaj Gupta } 1292*b35ce0c4SPankaj Gupta 1293*b35ce0c4SPankaj Gupta for (j = 0; j < 4; j++) { 1294*b35ce0c4SPankaj Gupta if ((bin[i].taamin_ps[j] == 0) || 1295*b35ce0c4SPankaj Gupta bin[i].taamin_ps[j] >= taamin_ps) { 1296*b35ce0c4SPankaj Gupta break; 1297*b35ce0c4SPankaj Gupta } 1298*b35ce0c4SPankaj Gupta } 1299*b35ce0c4SPankaj Gupta 1300*b35ce0c4SPankaj Gupta if (j >= 4) { 1301*b35ce0c4SPankaj Gupta ERROR("taamin_ps out of range.\n"); 1302*b35ce0c4SPankaj Gupta return 0; 1303*b35ce0c4SPankaj Gupta } 1304*b35ce0c4SPankaj Gupta 1305*b35ce0c4SPankaj Gupta if ((bin[i].taamin_ps[j] == 0) || 1306*b35ce0c4SPankaj Gupta (bin[i].taamin_ps[j] > taamin_ps && j > 0)) { 1307*b35ce0c4SPankaj Gupta j--; 1308*b35ce0c4SPankaj Gupta } 1309*b35ce0c4SPankaj Gupta 1310*b35ce0c4SPankaj Gupta for (k = 0; bin[i].cl[k].tckmin_ps < mclk_ps && 1311*b35ce0c4SPankaj Gupta bin[i].cl[k].tckmin_ps < taamin_max; k++) 1312*b35ce0c4SPankaj Gupta ; 1313*b35ce0c4SPankaj Gupta if (bin[i].cl[k].tckmin_ps > mclk_ps && k > 0) { 1314*b35ce0c4SPankaj Gupta k--; 1315*b35ce0c4SPankaj Gupta } 1316*b35ce0c4SPankaj Gupta 1317*b35ce0c4SPankaj Gupta debug("Skip CL mask for this speed 0x%x\n", bin[i].cl[k].caslat[j]); 1318*b35ce0c4SPankaj Gupta 1319*b35ce0c4SPankaj Gupta return bin[i].cl[k].caslat[j]; 1320*b35ce0c4SPankaj Gupta } 1321*b35ce0c4SPankaj Gupta 1322*b35ce0c4SPankaj Gupta int compute_ddrc(const unsigned long clk, 1323*b35ce0c4SPankaj Gupta const struct memctl_opt *popts, 1324*b35ce0c4SPankaj Gupta const struct ddr_conf *conf, 1325*b35ce0c4SPankaj Gupta struct ddr_cfg_regs *regs, 1326*b35ce0c4SPankaj Gupta const struct dimm_params *pdimm, 1327*b35ce0c4SPankaj Gupta unsigned int ip_rev) 1328*b35ce0c4SPankaj Gupta { 1329*b35ce0c4SPankaj Gupta unsigned int cas_latency; 1330*b35ce0c4SPankaj Gupta unsigned int caslat_skip; 1331*b35ce0c4SPankaj Gupta unsigned int additive_latency; 1332*b35ce0c4SPankaj Gupta const unsigned int mclk_ps = get_memory_clk_ps(clk); 1333*b35ce0c4SPankaj Gupta int i; 1334*b35ce0c4SPankaj Gupta 1335*b35ce0c4SPankaj Gupta zeromem(regs, sizeof(struct ddr_cfg_regs)); 1336*b35ce0c4SPankaj Gupta 1337*b35ce0c4SPankaj Gupta if (mclk_ps < pdimm->tckmin_x_ps) { 1338*b35ce0c4SPankaj Gupta ERROR("DDR Clk: MCLK cycle is %u ps.\n", mclk_ps); 1339*b35ce0c4SPankaj Gupta ERROR("DDR Clk is faster than DIMM can support.\n"); 1340*b35ce0c4SPankaj Gupta } 1341*b35ce0c4SPankaj Gupta 1342*b35ce0c4SPankaj Gupta /* calculate cas latency, override first */ 1343*b35ce0c4SPankaj Gupta cas_latency = (popts->caslat_override != 0) ? 1344*b35ce0c4SPankaj Gupta popts->caslat_override_value : 1345*b35ce0c4SPankaj Gupta (pdimm->taa_ps + mclk_ps - 1) / mclk_ps; 1346*b35ce0c4SPankaj Gupta 1347*b35ce0c4SPankaj Gupta /* skip unsupported caslat based on speed bin */ 1348*b35ce0c4SPankaj Gupta caslat_skip = skip_caslat(pdimm->tckmin_x_ps, 1349*b35ce0c4SPankaj Gupta pdimm->taa_ps, 1350*b35ce0c4SPankaj Gupta mclk_ps, 1351*b35ce0c4SPankaj Gupta pdimm->package_3ds); 1352*b35ce0c4SPankaj Gupta debug("Skip caslat 0x%x\n", caslat_skip); 1353*b35ce0c4SPankaj Gupta 1354*b35ce0c4SPankaj Gupta /* Check if DIMM supports the cas latency */ 1355*b35ce0c4SPankaj Gupta i = 24; 1356*b35ce0c4SPankaj Gupta while (((pdimm->caslat_x & ~caslat_skip & (1 << cas_latency)) == 0) && 1357*b35ce0c4SPankaj Gupta (i-- > 0)) { 1358*b35ce0c4SPankaj Gupta cas_latency++; 1359*b35ce0c4SPankaj Gupta } 1360*b35ce0c4SPankaj Gupta 1361*b35ce0c4SPankaj Gupta if (i <= 0) { 1362*b35ce0c4SPankaj Gupta ERROR("Failed to find a proper cas latency\n"); 1363*b35ce0c4SPankaj Gupta return -EINVAL; 1364*b35ce0c4SPankaj Gupta } 1365*b35ce0c4SPankaj Gupta /* Verify cas latency does not exceed 18ns for DDR4 */ 1366*b35ce0c4SPankaj Gupta if (cas_latency * mclk_ps > 18000) { 1367*b35ce0c4SPankaj Gupta ERROR("cas latency is too large %d\n", cas_latency); 1368*b35ce0c4SPankaj Gupta return -EINVAL; 1369*b35ce0c4SPankaj Gupta } 1370*b35ce0c4SPankaj Gupta 1371*b35ce0c4SPankaj Gupta additive_latency = (popts->addt_lat_override != 0) ? 1372*b35ce0c4SPankaj Gupta popts->addt_lat_override_value : 0; 1373*b35ce0c4SPankaj Gupta 1374*b35ce0c4SPankaj Gupta cal_ddr_csn_bnds(regs, popts, conf, pdimm); 1375*b35ce0c4SPankaj Gupta cal_ddr_sdram_cfg(clk, regs, popts, pdimm, ip_rev); 1376*b35ce0c4SPankaj Gupta cal_ddr_sdram_rcw(clk, regs, popts, pdimm); 1377*b35ce0c4SPankaj Gupta cal_timing_cfg(clk, regs, popts, pdimm, conf, cas_latency, 1378*b35ce0c4SPankaj Gupta additive_latency); 1379*b35ce0c4SPankaj Gupta cal_ddr_dq_mapping(regs, pdimm); 1380*b35ce0c4SPankaj Gupta 1381*b35ce0c4SPankaj Gupta if (ip_rev >= 0x50500) { 1382*b35ce0c4SPankaj Gupta cal_ddr_addr_dec(regs); 1383*b35ce0c4SPankaj Gupta } 1384*b35ce0c4SPankaj Gupta 1385*b35ce0c4SPankaj Gupta cal_ddr_sdram_mode(clk, regs, popts, conf, pdimm, cas_latency, 1386*b35ce0c4SPankaj Gupta additive_latency, ip_rev); 1387*b35ce0c4SPankaj Gupta cal_ddr_eor(regs, popts); 1388*b35ce0c4SPankaj Gupta cal_ddr_data_init(regs); 1389*b35ce0c4SPankaj Gupta cal_ddr_sdram_interval(clk, regs, popts, pdimm); 1390*b35ce0c4SPankaj Gupta cal_ddr_zq_cntl(regs); 1391*b35ce0c4SPankaj Gupta cal_ddr_sr_cntr(regs, popts); 1392*b35ce0c4SPankaj Gupta 1393*b35ce0c4SPankaj Gupta return 0; 1394*b35ce0c4SPankaj Gupta } 1395