Angel Pons | a2ee761 | 2020-04-04 18:51:15 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 2 | |
Kyösti Mälkki | 13f6650 | 2019-03-03 08:01:05 +0200 | [diff] [blame] | 3 | #include <device/mmio.h> |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 4 | #include <console/console.h> |
| 5 | #include <delay.h> |
| 6 | #include <soc/addressmap.h> |
| 7 | #include <soc/clock.h> |
Julius Werner | f0d21ff3 | 2014-10-20 13:24:14 -0700 | [diff] [blame] | 8 | #include <soc/emc.h> |
| 9 | #include <soc/mc.h> |
| 10 | #include <soc/pmc.h> |
| 11 | #include <soc/sdram.h> |
Julius Werner | ec5e5e0 | 2014-08-20 15:29:56 -0700 | [diff] [blame] | 12 | #include <symbols.h> |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 13 | |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 14 | static void sdram_patch(uintptr_t addr, uint32_t value) |
| 15 | { |
| 16 | if (addr) |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 17 | write32((uint32_t *)addr, value); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 18 | } |
| 19 | |
| 20 | static void writebits(uint32_t value, uint32_t *addr, uint32_t mask) |
| 21 | { |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 22 | clrsetbits32(addr, mask, (value & mask)); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 23 | } |
| 24 | |
| 25 | /* PMC must be configured before clock-enable and de-reset of MC/EMC. */ |
| 26 | static void sdram_configure_pmc(const struct sdram_params *param, |
| 27 | struct tegra_pmc_regs *regs) |
| 28 | { |
| 29 | /* VDDP Select */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 30 | write32(®s->vddp_sel, param->PmcVddpSel); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 31 | udelay(param->PmcVddpSelWait); |
| 32 | |
| 33 | /* Set DDR pad voltage */ |
| 34 | writebits(param->PmcDdrPwr, ®s->ddr_pwr, PMC_DDR_PWR_VAL_MASK); |
| 35 | |
| 36 | /* Set package and DPD pad control */ |
| 37 | writebits(param->PmcDdrCfg, ®s->ddr_cfg, |
| 38 | (PMC_DDR_CFG_PKG_MASK | PMC_DDR_CFG_IF_MASK | |
| 39 | PMC_DDR_CFG_XM0_RESET_TRI_MASK | |
| 40 | PMC_DDR_CFG_XM0_RESET_DPDIO_MASK)); |
| 41 | |
| 42 | /* Turn on MEM IO Power */ |
| 43 | writebits(param->PmcNoIoPower, ®s->no_iopower, |
| 44 | (PMC_NO_IOPOWER_MEM_MASK | PMC_NO_IOPOWER_MEM_COMP_MASK)); |
| 45 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 46 | write32(®s->reg_short, param->PmcRegShort); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | static void sdram_start_clocks(const struct sdram_params *param) |
| 50 | { |
| 51 | u32 is_same_freq = (param->McEmemArbMisc0 & |
| 52 | MC_EMEM_ARB_MISC0_MC_EMC_SAME_FREQ_MASK) ? 1 : 0; |
| 53 | |
| 54 | clock_sdram(param->PllMInputDivider, param->PllMFeedbackDivider, |
| 55 | param->PllMSelectDiv2, param->PllMSetupControl, |
| 56 | param->PllMPDLshiftPh45, param->PllMPDLshiftPh90, |
| 57 | param->PllMPDLshiftPh135, param->PllMKVCO, |
| 58 | param->PllMKCP, param->PllMStableTime, |
| 59 | param->EmcClockSource, is_same_freq); |
| 60 | } |
| 61 | |
| 62 | static void sdram_deassert_clock_enable_signal(const struct sdram_params *param, |
| 63 | struct tegra_pmc_regs *regs) |
| 64 | { |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 65 | clrbits32(®s->por_dpd_ctrl, |
| 66 | PMC_POR_DPD_CTRL_MEM0_HOLD_CKE_LOW_OVR_MASK); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 67 | udelay(param->PmcPorDpdCtrlWait); |
| 68 | } |
| 69 | |
| 70 | static void sdram_deassert_sel_dpd(const struct sdram_params *param, |
| 71 | struct tegra_pmc_regs *regs) |
| 72 | { |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 73 | clrbits32(®s->por_dpd_ctrl, |
| 74 | (PMC_POR_DPD_CTRL_MEM0_ADDR0_CLK_SEL_DPD_MASK | |
| 75 | PMC_POR_DPD_CTRL_MEM0_ADDR1_CLK_SEL_DPD_MASK)); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 76 | /* |
| 77 | * Note NVIDIA recommended to always do 10us delay here and ignore |
| 78 | * BCT.PmcPorDpdCtrlWait. |
| 79 | * */ |
| 80 | udelay(10); |
| 81 | } |
| 82 | |
| 83 | static void sdram_set_swizzle(const struct sdram_params *param, |
| 84 | struct tegra_emc_regs *regs) |
| 85 | { |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 86 | write32(®s->swizzle_rank0_byte_cfg, param->EmcSwizzleRank0ByteCfg); |
| 87 | write32(®s->swizzle_rank0_byte0, param->EmcSwizzleRank0Byte0); |
| 88 | write32(®s->swizzle_rank0_byte1, param->EmcSwizzleRank0Byte1); |
| 89 | write32(®s->swizzle_rank0_byte2, param->EmcSwizzleRank0Byte2); |
| 90 | write32(®s->swizzle_rank0_byte3, param->EmcSwizzleRank0Byte3); |
| 91 | write32(®s->swizzle_rank1_byte_cfg, param->EmcSwizzleRank1ByteCfg); |
| 92 | write32(®s->swizzle_rank1_byte0, param->EmcSwizzleRank1Byte0); |
| 93 | write32(®s->swizzle_rank1_byte1, param->EmcSwizzleRank1Byte1); |
| 94 | write32(®s->swizzle_rank1_byte2, param->EmcSwizzleRank1Byte2); |
| 95 | write32(®s->swizzle_rank1_byte3, param->EmcSwizzleRank1Byte3); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | static void sdram_set_pad_controls(const struct sdram_params *param, |
| 99 | struct tegra_emc_regs *regs) |
| 100 | { |
| 101 | /* Program the pad controls */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 102 | write32(®s->xm2cmdpadctrl, param->EmcXm2CmdPadCtrl); |
| 103 | write32(®s->xm2cmdpadctrl2, param->EmcXm2CmdPadCtrl2); |
| 104 | write32(®s->xm2cmdpadctrl3, param->EmcXm2CmdPadCtrl3); |
| 105 | write32(®s->xm2cmdpadctrl4, param->EmcXm2CmdPadCtrl4); |
| 106 | write32(®s->xm2cmdpadctrl5, param->EmcXm2CmdPadCtrl5); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 107 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 108 | write32(®s->xm2dqspadctrl, param->EmcXm2DqsPadCtrl); |
| 109 | write32(®s->xm2dqspadctrl2, param->EmcXm2DqsPadCtrl2); |
| 110 | write32(®s->xm2dqspadctrl3, param->EmcXm2DqsPadCtrl3); |
| 111 | write32(®s->xm2dqspadctrl4, param->EmcXm2DqsPadCtrl4); |
| 112 | write32(®s->xm2dqspadctrl5, param->EmcXm2DqsPadCtrl5); |
| 113 | write32(®s->xm2dqspadctrl6, param->EmcXm2DqsPadCtrl6); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 114 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 115 | write32(®s->xm2dqpadctrl, param->EmcXm2DqPadCtrl); |
| 116 | write32(®s->xm2dqpadctrl2, param->EmcXm2DqPadCtrl2); |
| 117 | write32(®s->xm2dqpadctrl3, param->EmcXm2DqPadCtrl3); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 118 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 119 | write32(®s->xm2clkpadctrl, param->EmcXm2ClkPadCtrl); |
| 120 | write32(®s->xm2clkpadctrl2, param->EmcXm2ClkPadCtrl2); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 121 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 122 | write32(®s->xm2comppadctrl, param->EmcXm2CompPadCtrl); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 123 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 124 | write32(®s->xm2vttgenpadctrl, param->EmcXm2VttGenPadCtrl); |
| 125 | write32(®s->xm2vttgenpadctrl2, param->EmcXm2VttGenPadCtrl2); |
| 126 | write32(®s->xm2vttgenpadctrl3, param->EmcXm2VttGenPadCtrl3); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 127 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 128 | write32(®s->ctt_term_ctrl, param->EmcCttTermCtrl); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | static void sdram_trigger_emc_timing_update(struct tegra_emc_regs *regs) |
| 132 | { |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 133 | write32(®s->timing_control, EMC_TIMING_CONTROL_TIMING_UPDATE); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 134 | } |
| 135 | |
| 136 | static void sdram_init_mc(const struct sdram_params *param, |
| 137 | struct tegra_mc_regs *regs) |
| 138 | { |
| 139 | /* Initialize MC VPR settings */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 140 | write32(®s->display_snap_ring, param->McDisplaySnapRing); |
| 141 | write32(®s->video_protect_bom, param->McVideoProtectBom); |
| 142 | write32(®s->video_protect_bom_adr_hi, |
| 143 | param->McVideoProtectBomAdrHi); |
| 144 | write32(®s->video_protect_size_mb, param->McVideoProtectSizeMb); |
| 145 | write32(®s->video_protect_vpr_override, |
| 146 | param->McVideoProtectVprOverride); |
| 147 | write32(®s->video_protect_vpr_override1, |
| 148 | param->McVideoProtectVprOverride1); |
| 149 | write32(®s->video_protect_gpu_override_0, |
| 150 | param->McVideoProtectGpuOverride0); |
| 151 | write32(®s->video_protect_gpu_override_1, |
| 152 | param->McVideoProtectGpuOverride1); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 153 | |
| 154 | /* Program SDRAM geometry paarameters */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 155 | write32(®s->emem_adr_cfg, param->McEmemAdrCfg); |
| 156 | write32(®s->emem_adr_cfg_dev0, param->McEmemAdrCfgDev0); |
| 157 | write32(®s->emem_adr_cfg_dev1, param->McEmemAdrCfgDev1); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 158 | |
| 159 | /* Program bank swizzling */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 160 | write32(®s->emem_bank_swizzle_cfg0, param->McEmemAdrCfgBankMask0); |
| 161 | write32(®s->emem_bank_swizzle_cfg1, param->McEmemAdrCfgBankMask1); |
| 162 | write32(®s->emem_bank_swizzle_cfg2, param->McEmemAdrCfgBankMask2); |
| 163 | write32(®s->emem_bank_swizzle_cfg3, |
| 164 | param->McEmemAdrCfgBankSwizzle3); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 165 | |
| 166 | /* Program external memory aperature (base and size) */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 167 | write32(®s->emem_cfg, param->McEmemCfg); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 168 | |
| 169 | /* Program SEC carveout (base and size) */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 170 | write32(®s->sec_carveout_bom, param->McSecCarveoutBom); |
| 171 | write32(®s->sec_carveout_adr_hi, param->McSecCarveoutAdrHi); |
| 172 | write32(®s->sec_carveout_size_mb, param->McSecCarveoutSizeMb); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 173 | |
| 174 | /* Program MTS carveout (base and size) */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 175 | write32(®s->mts_carveout_bom, param->McMtsCarveoutBom); |
| 176 | write32(®s->mts_carveout_adr_hi, param->McMtsCarveoutAdrHi); |
| 177 | write32(®s->mts_carveout_size_mb, param->McMtsCarveoutSizeMb); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 178 | |
| 179 | /* Program the memory arbiter */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 180 | write32(®s->emem_arb_cfg, param->McEmemArbCfg); |
| 181 | write32(®s->emem_arb_outstanding_req, |
| 182 | param->McEmemArbOutstandingReq); |
| 183 | write32(®s->emem_arb_timing_rcd, param->McEmemArbTimingRcd); |
| 184 | write32(®s->emem_arb_timing_rp, param->McEmemArbTimingRp); |
| 185 | write32(®s->emem_arb_timing_rc, param->McEmemArbTimingRc); |
| 186 | write32(®s->emem_arb_timing_ras, param->McEmemArbTimingRas); |
| 187 | write32(®s->emem_arb_timing_faw, param->McEmemArbTimingFaw); |
| 188 | write32(®s->emem_arb_timing_rrd, param->McEmemArbTimingRrd); |
| 189 | write32(®s->emem_arb_timing_rap2pre, param->McEmemArbTimingRap2Pre); |
| 190 | write32(®s->emem_arb_timing_wap2pre, param->McEmemArbTimingWap2Pre); |
| 191 | write32(®s->emem_arb_timing_r2r, param->McEmemArbTimingR2R); |
| 192 | write32(®s->emem_arb_timing_w2w, param->McEmemArbTimingW2W); |
| 193 | write32(®s->emem_arb_timing_r2w, param->McEmemArbTimingR2W); |
| 194 | write32(®s->emem_arb_timing_w2r, param->McEmemArbTimingW2R); |
| 195 | write32(®s->emem_arb_da_turns, param->McEmemArbDaTurns); |
| 196 | write32(®s->emem_arb_da_covers, param->McEmemArbDaCovers); |
| 197 | write32(®s->emem_arb_misc0, param->McEmemArbMisc0); |
| 198 | write32(®s->emem_arb_misc1, param->McEmemArbMisc1); |
| 199 | write32(®s->emem_arb_ring1_throttle, param->McEmemArbRing1Throttle); |
| 200 | write32(®s->emem_arb_override, param->McEmemArbOverride); |
| 201 | write32(®s->emem_arb_override_1, param->McEmemArbOverride1); |
| 202 | write32(®s->emem_arb_rsv, param->McEmemArbRsv); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 203 | |
| 204 | /* Program extra snap levels for display client */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 205 | write32(®s->dis_extra_snap_levels, param->McDisExtraSnapLevels); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 206 | |
| 207 | /* Trigger MC timing update */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 208 | write32(®s->timing_control, MC_TIMING_CONTROL_TIMING_UPDATE); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 209 | |
| 210 | /* Program second-level clock enable overrides */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 211 | write32(®s->clken_override, param->McClkenOverride); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 212 | |
| 213 | /* Program statistics gathering */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 214 | write32(®s->stat_control, param->McStatControl); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 215 | } |
| 216 | |
| 217 | static void sdram_init_emc(const struct sdram_params *param, |
| 218 | struct tegra_emc_regs *regs) |
| 219 | { |
| 220 | /* Program SDRAM geometry parameters */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 221 | write32(®s->adr_cfg, param->EmcAdrCfg); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 222 | |
| 223 | /* Program second-level clock enable overrides */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 224 | write32(®s->clken_override, param->EmcClkenOverride); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 225 | |
| 226 | /* Program EMC pad auto calibration */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 227 | write32(®s->auto_cal_interval, param->EmcAutoCalInterval); |
| 228 | write32(®s->auto_cal_config2, param->EmcAutoCalConfig2); |
| 229 | write32(®s->auto_cal_config3, param->EmcAutoCalConfig3); |
| 230 | write32(®s->auto_cal_config, param->EmcAutoCalConfig); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 231 | udelay(param->EmcAutoCalWait); |
| 232 | } |
| 233 | |
| 234 | static void sdram_set_emc_timing(const struct sdram_params *param, |
| 235 | struct tegra_emc_regs *regs) |
| 236 | { |
| 237 | /* Program EMC timing configuration */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 238 | write32(®s->cfg_2, param->EmcCfg2); |
| 239 | write32(®s->cfg_pipe, param->EmcCfgPipe); |
| 240 | write32(®s->dbg, param->EmcDbg); |
| 241 | write32(®s->cmdq, param->EmcCmdQ); |
| 242 | write32(®s->mc2emcq, param->EmcMc2EmcQ); |
| 243 | write32(®s->mrs_wait_cnt, param->EmcMrsWaitCnt); |
| 244 | write32(®s->mrs_wait_cnt2, param->EmcMrsWaitCnt2); |
| 245 | write32(®s->fbio_cfg5, param->EmcFbioCfg5); |
| 246 | write32(®s->rc, param->EmcRc); |
| 247 | write32(®s->rfc, param->EmcRfc); |
| 248 | write32(®s->rfc_slr, param->EmcRfcSlr); |
| 249 | write32(®s->ras, param->EmcRas); |
| 250 | write32(®s->rp, param->EmcRp); |
| 251 | write32(®s->r2r, param->EmcR2r); |
| 252 | write32(®s->w2w, param->EmcW2w); |
| 253 | write32(®s->r2w, param->EmcR2w); |
| 254 | write32(®s->w2r, param->EmcW2r); |
| 255 | write32(®s->r2p, param->EmcR2p); |
| 256 | write32(®s->w2p, param->EmcW2p); |
| 257 | write32(®s->rd_rcd, param->EmcRdRcd); |
| 258 | write32(®s->wr_rcd, param->EmcWrRcd); |
| 259 | write32(®s->rrd, param->EmcRrd); |
| 260 | write32(®s->rext, param->EmcRext); |
| 261 | write32(®s->wext, param->EmcWext); |
| 262 | write32(®s->wdv, param->EmcWdv); |
| 263 | write32(®s->wdv_mask, param->EmcWdvMask); |
| 264 | write32(®s->quse, param->EmcQUse); |
| 265 | write32(®s->quse_width, param->EmcQuseWidth); |
| 266 | write32(®s->ibdly, param->EmcIbdly); |
| 267 | write32(®s->einput, param->EmcEInput); |
| 268 | write32(®s->einput_duration, param->EmcEInputDuration); |
| 269 | write32(®s->puterm_extra, param->EmcPutermExtra); |
| 270 | write32(®s->puterm_width, param->EmcPutermWidth); |
| 271 | write32(®s->puterm_adj, param->EmcPutermAdj); |
| 272 | write32(®s->cdb_cntl_1, param->EmcCdbCntl1); |
| 273 | write32(®s->cdb_cntl_2, param->EmcCdbCntl2); |
| 274 | write32(®s->cdb_cntl_3, param->EmcCdbCntl3); |
| 275 | write32(®s->qrst, param->EmcQRst); |
| 276 | write32(®s->qsafe, param->EmcQSafe); |
| 277 | write32(®s->rdv, param->EmcRdv); |
| 278 | write32(®s->rdv_mask, param->EmcRdvMask); |
| 279 | write32(®s->qpop, param->EmcQpop); |
| 280 | write32(®s->ctt, param->EmcCtt); |
| 281 | write32(®s->ctt_duration, param->EmcCttDuration); |
| 282 | write32(®s->refresh, param->EmcRefresh); |
| 283 | write32(®s->burst_refresh_num, param->EmcBurstRefreshNum); |
| 284 | write32(®s->pre_refresh_req_cnt, param->EmcPreRefreshReqCnt); |
| 285 | write32(®s->pdex2wr, param->EmcPdEx2Wr); |
| 286 | write32(®s->pdex2rd, param->EmcPdEx2Rd); |
| 287 | write32(®s->pchg2pden, param->EmcPChg2Pden); |
| 288 | write32(®s->act2pden, param->EmcAct2Pden); |
| 289 | write32(®s->ar2pden, param->EmcAr2Pden); |
| 290 | write32(®s->rw2pden, param->EmcRw2Pden); |
| 291 | write32(®s->txsr, param->EmcTxsr); |
| 292 | write32(®s->txsrdll, param->EmcTxsrDll); |
| 293 | write32(®s->tcke, param->EmcTcke); |
| 294 | write32(®s->tckesr, param->EmcTckesr); |
| 295 | write32(®s->tpd, param->EmcTpd); |
| 296 | write32(®s->tfaw, param->EmcTfaw); |
| 297 | write32(®s->trpab, param->EmcTrpab); |
| 298 | write32(®s->tclkstable, param->EmcTClkStable); |
| 299 | write32(®s->tclkstop, param->EmcTClkStop); |
| 300 | write32(®s->trefbw, param->EmcTRefBw); |
| 301 | write32(®s->odt_write, param->EmcOdtWrite); |
| 302 | write32(®s->odt_read, param->EmcOdtRead); |
| 303 | write32(®s->fbio_cfg6, param->EmcFbioCfg6); |
| 304 | write32(®s->cfg_dig_dll, param->EmcCfgDigDll); |
| 305 | write32(®s->cfg_dig_dll_period, param->EmcCfgDigDllPeriod); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 306 | |
| 307 | /* Don't write bit 1: addr swizzle lock bit. Written at end of sequence. */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 308 | write32(®s->fbio_spare, param->EmcFbioSpare & 0xfffffffd); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 309 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 310 | write32(®s->cfg_rsv, param->EmcCfgRsv); |
| 311 | write32(®s->dll_xform_dqs0, param->EmcDllXformDqs0); |
| 312 | write32(®s->dll_xform_dqs1, param->EmcDllXformDqs1); |
| 313 | write32(®s->dll_xform_dqs2, param->EmcDllXformDqs2); |
| 314 | write32(®s->dll_xform_dqs3, param->EmcDllXformDqs3); |
| 315 | write32(®s->dll_xform_dqs4, param->EmcDllXformDqs4); |
| 316 | write32(®s->dll_xform_dqs5, param->EmcDllXformDqs5); |
| 317 | write32(®s->dll_xform_dqs6, param->EmcDllXformDqs6); |
| 318 | write32(®s->dll_xform_dqs7, param->EmcDllXformDqs7); |
| 319 | write32(®s->dll_xform_dqs8, param->EmcDllXformDqs8); |
| 320 | write32(®s->dll_xform_dqs9, param->EmcDllXformDqs9); |
| 321 | write32(®s->dll_xform_dqs10, param->EmcDllXformDqs10); |
| 322 | write32(®s->dll_xform_dqs11, param->EmcDllXformDqs11); |
| 323 | write32(®s->dll_xform_dqs12, param->EmcDllXformDqs12); |
| 324 | write32(®s->dll_xform_dqs13, param->EmcDllXformDqs13); |
| 325 | write32(®s->dll_xform_dqs14, param->EmcDllXformDqs14); |
| 326 | write32(®s->dll_xform_dqs15, param->EmcDllXformDqs15); |
| 327 | write32(®s->dll_xform_quse0, param->EmcDllXformQUse0); |
| 328 | write32(®s->dll_xform_quse1, param->EmcDllXformQUse1); |
| 329 | write32(®s->dll_xform_quse2, param->EmcDllXformQUse2); |
| 330 | write32(®s->dll_xform_quse3, param->EmcDllXformQUse3); |
| 331 | write32(®s->dll_xform_quse4, param->EmcDllXformQUse4); |
| 332 | write32(®s->dll_xform_quse5, param->EmcDllXformQUse5); |
| 333 | write32(®s->dll_xform_quse6, param->EmcDllXformQUse6); |
| 334 | write32(®s->dll_xform_quse7, param->EmcDllXformQUse7); |
| 335 | write32(®s->dll_xform_quse8, param->EmcDllXformQUse8); |
| 336 | write32(®s->dll_xform_quse9, param->EmcDllXformQUse9); |
| 337 | write32(®s->dll_xform_quse10, param->EmcDllXformQUse10); |
| 338 | write32(®s->dll_xform_quse11, param->EmcDllXformQUse11); |
| 339 | write32(®s->dll_xform_quse12, param->EmcDllXformQUse12); |
| 340 | write32(®s->dll_xform_quse13, param->EmcDllXformQUse13); |
| 341 | write32(®s->dll_xform_quse14, param->EmcDllXformQUse14); |
| 342 | write32(®s->dll_xform_quse15, param->EmcDllXformQUse15); |
| 343 | write32(®s->dll_xform_dq0, param->EmcDllXformDq0); |
| 344 | write32(®s->dll_xform_dq1, param->EmcDllXformDq1); |
| 345 | write32(®s->dll_xform_dq2, param->EmcDllXformDq2); |
| 346 | write32(®s->dll_xform_dq3, param->EmcDllXformDq3); |
| 347 | write32(®s->dll_xform_dq4, param->EmcDllXformDq4); |
| 348 | write32(®s->dll_xform_dq5, param->EmcDllXformDq5); |
| 349 | write32(®s->dll_xform_dq6, param->EmcDllXformDq6); |
| 350 | write32(®s->dll_xform_dq7, param->EmcDllXformDq7); |
| 351 | write32(®s->dll_xform_addr0, param->EmcDllXformAddr0); |
| 352 | write32(®s->dll_xform_addr1, param->EmcDllXformAddr1); |
| 353 | write32(®s->dll_xform_addr2, param->EmcDllXformAddr2); |
| 354 | write32(®s->dll_xform_addr3, param->EmcDllXformAddr3); |
| 355 | write32(®s->dll_xform_addr4, param->EmcDllXformAddr4); |
| 356 | write32(®s->dll_xform_addr5, param->EmcDllXformAddr5); |
| 357 | write32(®s->acpd_control, param->EmcAcpdControl); |
| 358 | write32(®s->dsr_vttgen_drv, param->EmcDsrVttgenDrv); |
| 359 | write32(®s->txdsrvttgen, param->EmcTxdsrvttgen); |
| 360 | write32(®s->bgbias_ctl0, param->EmcBgbiasCtl0); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 361 | |
| 362 | /* |
| 363 | * Set pipe bypass enable bits before sending any DRAM commands. |
| 364 | * Note other bits in EMC_CFG must be set AFTER REFCTRL is configured. |
| 365 | */ |
| 366 | writebits(param->EmcCfg, ®s->cfg, |
| 367 | (EMC_CFG_EMC2PMACRO_CFG_BYPASS_ADDRPIPE_MASK | |
| 368 | EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE1_MASK | |
| 369 | EMC_CFG_EMC2PMACRO_CFG_BYPASS_DATAPIPE2_MASK)); |
| 370 | } |
| 371 | |
| 372 | static void sdram_patch_bootrom(const struct sdram_params *param, |
| 373 | struct tegra_mc_regs *regs) |
| 374 | { |
| 375 | if (param->BootRomPatchControl & BOOT_ROM_PATCH_CONTROL_ENABLE_MASK) { |
| 376 | uintptr_t addr = ((param->BootRomPatchControl & |
| 377 | BOOT_ROM_PATCH_CONTROL_OFFSET_MASK) >> |
| 378 | BOOT_ROM_PATCH_CONTROL_OFFSET_SHIFT); |
| 379 | addr = BOOT_ROM_PATCH_CONTROL_BASE_ADDRESS + (addr << 2); |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 380 | write32((uint32_t *)addr, param->BootRomPatchData); |
| 381 | write32(®s->timing_control, 1); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 382 | } |
| 383 | } |
| 384 | |
| 385 | static void sdram_set_dpd3(const struct sdram_params *param, |
| 386 | struct tegra_pmc_regs *regs) |
| 387 | { |
| 388 | /* Program DPD request */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 389 | write32(®s->io_dpd3_req, param->PmcIoDpd3Req); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 390 | udelay(param->PmcIoDpd3ReqWait); |
| 391 | } |
| 392 | |
| 393 | static void sdram_set_dli_trims(const struct sdram_params *param, |
| 394 | struct tegra_emc_regs *regs) |
| 395 | { |
| 396 | /* Program DLI trims */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 397 | write32(®s->dli_trim_txdqs0, param->EmcDliTrimTxDqs0); |
| 398 | write32(®s->dli_trim_txdqs1, param->EmcDliTrimTxDqs1); |
| 399 | write32(®s->dli_trim_txdqs2, param->EmcDliTrimTxDqs2); |
| 400 | write32(®s->dli_trim_txdqs3, param->EmcDliTrimTxDqs3); |
| 401 | write32(®s->dli_trim_txdqs4, param->EmcDliTrimTxDqs4); |
| 402 | write32(®s->dli_trim_txdqs5, param->EmcDliTrimTxDqs5); |
| 403 | write32(®s->dli_trim_txdqs6, param->EmcDliTrimTxDqs6); |
| 404 | write32(®s->dli_trim_txdqs7, param->EmcDliTrimTxDqs7); |
| 405 | write32(®s->dli_trim_txdqs8, param->EmcDliTrimTxDqs8); |
| 406 | write32(®s->dli_trim_txdqs9, param->EmcDliTrimTxDqs9); |
| 407 | write32(®s->dli_trim_txdqs10, param->EmcDliTrimTxDqs10); |
| 408 | write32(®s->dli_trim_txdqs11, param->EmcDliTrimTxDqs11); |
| 409 | write32(®s->dli_trim_txdqs12, param->EmcDliTrimTxDqs12); |
| 410 | write32(®s->dli_trim_txdqs13, param->EmcDliTrimTxDqs13); |
| 411 | write32(®s->dli_trim_txdqs14, param->EmcDliTrimTxDqs14); |
| 412 | write32(®s->dli_trim_txdqs15, param->EmcDliTrimTxDqs15); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 413 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 414 | write32(®s->ca_training_timing_cntl1, |
| 415 | param->EmcCaTrainingTimingCntl1); |
| 416 | write32(®s->ca_training_timing_cntl2, |
| 417 | param->EmcCaTrainingTimingCntl2); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 418 | |
| 419 | sdram_trigger_emc_timing_update(regs); |
| 420 | udelay(param->EmcTimingControlWait); |
| 421 | } |
| 422 | |
| 423 | static void sdram_set_clock_enable_signal(const struct sdram_params *param, |
| 424 | struct tegra_emc_regs *regs) |
| 425 | { |
| 426 | volatile uint32_t dummy = 0; |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 427 | clrbits32(®s->pin, (EMC_PIN_RESET_MASK | EMC_PIN_DQM_MASK | |
| 428 | EMC_PIN_CKE_MASK)); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 429 | /* |
| 430 | * Assert dummy read of PIN register to ensure above write to PIN |
| 431 | * register went through. 200 is the recommended value by NVIDIA. |
| 432 | */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 433 | dummy |= read32(®s->pin); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 434 | udelay(200 + param->EmcPinExtraWait); |
| 435 | |
| 436 | /* Deassert reset */ |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 437 | setbits32(®s->pin, EMC_PIN_RESET_INACTIVE); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 438 | /* |
| 439 | * Assert dummy read of PIN register to ensure above write to PIN |
| 440 | * register went through. 200 is the recommended value by NVIDIA. |
| 441 | */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 442 | dummy |= read32(®s->pin); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 443 | udelay(500 + param->EmcPinExtraWait); |
| 444 | |
| 445 | /* Enable clock enable signal */ |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 446 | setbits32(®s->pin, EMC_PIN_CKE_NORMAL); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 447 | /* |
| 448 | * Assert dummy read of PIN register to ensure above write to PIN |
| 449 | * register went through. 200 is the recommended value by NVIDIA. |
| 450 | */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 451 | dummy |= read32(®s->pin); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 452 | udelay(param->EmcPinProgramWait); |
| 453 | |
| 454 | if (!dummy) { |
| 455 | die("Failed to program EMC pin."); |
| 456 | } |
| 457 | |
| 458 | /* Send NOP (trigger) */ |
| 459 | writebits(((1 << EMC_NOP_NOP_CMD_SHIFT) | |
| 460 | (param->EmcDevSelect << EMC_NOP_NOP_DEV_SELECTN_SHIFT)), |
| 461 | ®s->nop, |
| 462 | EMC_NOP_NOP_CMD_MASK | EMC_NOP_NOP_DEV_SELECTN_MASK); |
| 463 | |
| 464 | /* Write mode registers */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 465 | write32(®s->emrs2, param->EmcEmrs2); |
| 466 | write32(®s->emrs3, param->EmcEmrs3); |
| 467 | write32(®s->emrs, param->EmcEmrs); |
| 468 | write32(®s->mrs, param->EmcMrs); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 469 | |
| 470 | if (param->EmcExtraModeRegWriteEnable) { |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 471 | write32(®s->mrs, param->EmcMrwExtra); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 472 | } |
| 473 | } |
| 474 | |
| 475 | static void sdram_init_zq_calibration(const struct sdram_params *param, |
| 476 | struct tegra_emc_regs *regs) |
| 477 | { |
| 478 | if ((param->EmcZcalWarmColdBootEnables & |
| 479 | EMC_ZCAL_WARM_COLD_BOOT_ENABLES_COLDBOOT_MASK) == 1) { |
| 480 | /* Need to initialize ZCAL on coldboot. */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 481 | write32(®s->zq_cal, param->EmcZcalInitDev0); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 482 | udelay(param->EmcZcalInitWait); |
| 483 | |
| 484 | if ((param->EmcDevSelect & 2) == 0) { |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 485 | write32(®s->zq_cal, param->EmcZcalInitDev1); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 486 | udelay(param->EmcZcalInitWait); |
| 487 | } |
| 488 | } else { |
| 489 | udelay(param->EmcZcalInitWait); |
| 490 | } |
| 491 | } |
| 492 | |
| 493 | static void sdram_set_zq_calibration(const struct sdram_params *param, |
| 494 | struct tegra_emc_regs *regs) |
| 495 | { |
| 496 | /* Start periodic ZQ calibration */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 497 | write32(®s->zcal_interval, param->EmcZcalInterval); |
| 498 | write32(®s->zcal_wait_cnt, param->EmcZcalWaitCnt); |
| 499 | write32(®s->zcal_mrw_cmd, param->EmcZcalMrwCmd); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 500 | } |
| 501 | |
| 502 | static void sdram_set_refresh(const struct sdram_params *param, |
| 503 | struct tegra_emc_regs *regs) |
| 504 | { |
| 505 | /* Insert burst refresh */ |
| 506 | if (param->EmcExtraRefreshNum > 0) { |
| 507 | uint32_t refresh_num = (1 << param->EmcExtraRefreshNum) - 1; |
| 508 | writebits((EMC_REF_CMD_REFRESH | EMC_REF_NORMAL_ENABLED | |
| 509 | (refresh_num << EMC_REF_NUM_SHIFT) | |
| 510 | (param->EmcDevSelect << EMC_REF_DEV_SELECTN_SHIFT)), |
| 511 | ®s->ref, (EMC_REF_CMD_MASK | EMC_REF_NORMAL_MASK | |
| 512 | EMC_REF_NUM_MASK | |
| 513 | EMC_REF_DEV_SELECTN_MASK)); |
| 514 | } |
| 515 | |
| 516 | /* Enable refresh */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 517 | write32(®s->refctrl, |
| 518 | (param->EmcDevSelect | EMC_REFCTRL_REF_VALID_ENABLED)); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 519 | |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 520 | write32(®s->dyn_self_ref_control, param->EmcDynSelfRefControl); |
| 521 | write32(®s->cfg, param->EmcCfg); |
| 522 | write32(®s->sel_dpd_ctrl, param->EmcSelDpdCtrl); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 523 | |
| 524 | /* Write addr swizzle lock bit */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 525 | write32(®s->fbio_spare, param->EmcFbioSpare); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 526 | |
| 527 | /* Re-trigger timing to latch power saving functions */ |
| 528 | sdram_trigger_emc_timing_update(regs); |
| 529 | } |
| 530 | |
| 531 | static void sdram_enable_arbiter(const struct sdram_params *param) |
| 532 | { |
| 533 | /* TODO(hungte) Move values here to standalone header file. */ |
| 534 | uint32_t *AHB_ARBITRATION_XBAR_CTRL = (uint32_t*)(0x6000c000 + 0xe0); |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 535 | setbits32(AHB_ARBITRATION_XBAR_CTRL, |
| 536 | param->AhbArbitrationXbarCtrlMemInitDone << 16); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 537 | } |
| 538 | |
| 539 | static void sdram_lock_carveouts(const struct sdram_params *param, |
| 540 | struct tegra_mc_regs *regs) |
| 541 | { |
| 542 | /* Lock carveouts, and emem_cfg registers */ |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 543 | write32(®s->video_protect_reg_ctrl, |
| 544 | param->McVideoProtectWriteAccess); |
| 545 | write32(®s->emem_cfg_access_ctrl, |
| 546 | MC_EMEM_CFG_ACCESS_CTRL_WRITE_ACCESS_DISABLED); |
| 547 | write32(®s->sec_carveout_reg_ctrl, |
| 548 | param->McSecCarveoutProtectWriteAccess); |
| 549 | write32(®s->mts_carveout_reg_ctrl, param->McMtsCarveoutRegCtrl); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 550 | } |
| 551 | |
| 552 | void sdram_init(const struct sdram_params *param) |
| 553 | { |
| 554 | struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; |
| 555 | struct tegra_mc_regs *mc = (struct tegra_mc_regs*)TEGRA_MC_BASE; |
| 556 | struct tegra_emc_regs *emc = (struct tegra_emc_regs*)TEGRA_EMC_BASE; |
| 557 | |
Tom Warren | 64982c50 | 2014-01-23 13:37:50 -0700 | [diff] [blame] | 558 | printk(BIOS_DEBUG, "Initializing SDRAM of type %d with %dKHz\n", |
Julius Werner | e57c303 | 2014-04-11 18:23:12 -0700 | [diff] [blame] | 559 | param->MemoryType, clock_get_pll_input_khz() * |
Tom Warren | 64982c50 | 2014-01-23 13:37:50 -0700 | [diff] [blame] | 560 | param->PllMFeedbackDivider / param->PllMInputDivider / |
| 561 | (1 + param->PllMSelectDiv2)); |
| 562 | if (param->MemoryType != NvBootMemoryType_Ddr3) |
| 563 | die("Unsupported memory type!\n"); |
| 564 | |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 565 | sdram_configure_pmc(param, pmc); |
| 566 | sdram_patch(param->EmcBctSpare0, param->EmcBctSpare1); |
| 567 | |
| 568 | sdram_start_clocks(param); |
| 569 | sdram_patch(param->EmcBctSpare2, param->EmcBctSpare3); |
| 570 | |
| 571 | sdram_deassert_sel_dpd(param, pmc); |
| 572 | sdram_set_swizzle(param, emc); |
| 573 | sdram_set_pad_controls(param, emc); |
| 574 | sdram_patch(param->EmcBctSpare4, param->EmcBctSpare5); |
| 575 | |
| 576 | sdram_trigger_emc_timing_update(emc); |
| 577 | sdram_init_mc(param, mc); |
| 578 | sdram_init_emc(param, emc); |
| 579 | sdram_patch(param->EmcBctSpare6, param->EmcBctSpare7); |
| 580 | |
| 581 | sdram_set_emc_timing(param, emc); |
| 582 | sdram_patch_bootrom(param, mc); |
| 583 | sdram_set_dpd3(param, pmc); |
| 584 | sdram_set_dli_trims(param, emc); |
| 585 | sdram_deassert_clock_enable_signal(param, pmc); |
| 586 | sdram_set_clock_enable_signal(param, emc); |
| 587 | sdram_init_zq_calibration(param, emc); |
| 588 | sdram_patch(param->EmcBctSpare8, param->EmcBctSpare9); |
| 589 | |
| 590 | sdram_set_zq_calibration(param, emc); |
| 591 | sdram_patch(param->EmcBctSpare10, param->EmcBctSpare11); |
| 592 | |
| 593 | sdram_trigger_emc_timing_update(emc); |
| 594 | sdram_set_refresh(param, emc); |
| 595 | sdram_enable_arbiter(param); |
| 596 | sdram_lock_carveouts(param, mc); |
Tom Warren | 64982c50 | 2014-01-23 13:37:50 -0700 | [diff] [blame] | 597 | |
| 598 | sdram_lp0_save_params(param); |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 599 | } |
| 600 | |
| 601 | uint32_t sdram_get_ram_code(void) |
| 602 | { |
| 603 | struct tegra_pmc_regs *pmc = (struct tegra_pmc_regs*)TEGRA_PMC_BASE; |
Julius Werner | 2f37bd6 | 2015-02-19 14:51:15 -0800 | [diff] [blame] | 604 | return ((read32(&pmc->strapping_opt_a) & |
Andrew Bresticker | 24d4f7f | 2013-12-18 22:41:34 -0800 | [diff] [blame] | 605 | PMC_STRAPPING_OPT_A_RAM_CODE_MASK) >> |
| 606 | PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT); |
| 607 | } |
Tom Warren | 64982c50 | 2014-01-23 13:37:50 -0700 | [diff] [blame] | 608 | |
| 609 | /* returns total amount of DRAM (in MB) from memory controller registers */ |
| 610 | int sdram_size_mb(void) |
| 611 | { |
| 612 | struct tegra_mc_regs *mc = (struct tegra_mc_regs *)TEGRA_MC_BASE; |
| 613 | static int total_size = 0; |
| 614 | |
| 615 | if (total_size) |
| 616 | return total_size; |
| 617 | |
| 618 | /* |
| 619 | * This obtains memory size from the External Memory Aperture |
| 620 | * Configuration register. Nvidia confirmed that it is safe to assume |
| 621 | * this value represents the total physical DRAM size. |
| 622 | */ |
| 623 | total_size = (read32(&mc->emem_cfg) >> |
| 624 | MC_EMEM_CFG_SIZE_MB_SHIFT) & MC_EMEM_CFG_SIZE_MB_MASK; |
| 625 | |
| 626 | printk(BIOS_DEBUG, "%s: Total SDRAM (MB): %u\n", __func__, total_size); |
| 627 | return total_size; |
| 628 | } |
Gabe Black | 5cbbc70 | 2014-02-08 05:17:38 -0800 | [diff] [blame] | 629 | |
| 630 | uintptr_t sdram_max_addressable_mb(void) |
| 631 | { |
Julius Werner | ec5e5e0 | 2014-08-20 15:29:56 -0700 | [diff] [blame] | 632 | return MIN(((uintptr_t)_dram/MiB) + sdram_size_mb(), 4096); |
Gabe Black | 5cbbc70 | 2014-02-08 05:17:38 -0800 | [diff] [blame] | 633 | } |