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