1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2018-2021 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu * 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <errno.h> 10*91f16700Schasinglulu #include <stdbool.h> 11*91f16700Schasinglulu #include <stdint.h> 12*91f16700Schasinglulu #include <stdio.h> 13*91f16700Schasinglulu #include <stdlib.h> 14*91f16700Schasinglulu #include <string.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <common/debug.h> 17*91f16700Schasinglulu #include <ddr.h> 18*91f16700Schasinglulu #include <lib/utils.h> 19*91f16700Schasinglulu #include <load_img.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #include "plat_common.h" 22*91f16700Schasinglulu #include <platform_def.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu #ifdef CONFIG_STATIC_DDR 25*91f16700Schasinglulu 26*91f16700Schasinglulu const struct ddr_cfg_regs static_3200 = { 27*91f16700Schasinglulu .cs[0].bnds = U(0x03FFU), 28*91f16700Schasinglulu .cs[1].bnds = U(0x03FF), 29*91f16700Schasinglulu .cs[0].config = U(0x80050422), 30*91f16700Schasinglulu .cs[1].config = U(0x80000422), 31*91f16700Schasinglulu .cs[2].bnds = U(0x00), 32*91f16700Schasinglulu .cs[3].bnds = U(0x00), 33*91f16700Schasinglulu .cs[2].config = U(0x00), 34*91f16700Schasinglulu .cs[3].config = U(0x00), 35*91f16700Schasinglulu .timing_cfg[0] = U(0xFFAA0018), 36*91f16700Schasinglulu .timing_cfg[1] = U(0x646A8844), 37*91f16700Schasinglulu .timing_cfg[2] = U(0x00058022), 38*91f16700Schasinglulu .timing_cfg[3] = U(0x13622100), 39*91f16700Schasinglulu .timing_cfg[4] = U(0x02), 40*91f16700Schasinglulu .timing_cfg[5] = U(0x07401400), 41*91f16700Schasinglulu .timing_cfg[7] = U(0x3BB00000), 42*91f16700Schasinglulu .timing_cfg[8] = U(0x0944AC00), 43*91f16700Schasinglulu .sdram_cfg[0] = U(0x65044008), 44*91f16700Schasinglulu .sdram_cfg[1] = U(0x00401011), 45*91f16700Schasinglulu .sdram_cfg[2] = U(0x00), 46*91f16700Schasinglulu .sdram_mode[0] = U(0x06010C50), 47*91f16700Schasinglulu .sdram_mode[1] = U(0x00280400), 48*91f16700Schasinglulu .sdram_mode[2] = U(0x00), 49*91f16700Schasinglulu .sdram_mode[3] = U(0x00), 50*91f16700Schasinglulu .sdram_mode[4] = U(0x00), 51*91f16700Schasinglulu .sdram_mode[5] = U(0x00), 52*91f16700Schasinglulu .sdram_mode[6] = U(0x00), 53*91f16700Schasinglulu .sdram_mode[7] = U(0x00), 54*91f16700Schasinglulu .sdram_mode[8] = U(0x0500), 55*91f16700Schasinglulu .sdram_mode[9] = U(0x10240000), 56*91f16700Schasinglulu .sdram_mode[10] = U(0x00), 57*91f16700Schasinglulu .sdram_mode[11] = U(0x00), 58*91f16700Schasinglulu .sdram_mode[12] = U(0x00), 59*91f16700Schasinglulu .sdram_mode[13] = U(0x00), 60*91f16700Schasinglulu .sdram_mode[14] = U(0x00), 61*91f16700Schasinglulu .sdram_mode[15] = U(0x00), 62*91f16700Schasinglulu .md_cntl = U(0x00), 63*91f16700Schasinglulu .interval = U(0x30C00000), 64*91f16700Schasinglulu .data_init = U(0xDEADBEEF), 65*91f16700Schasinglulu .init_addr = U(0x00), 66*91f16700Schasinglulu .zq_cntl = U(0x8A090705), 67*91f16700Schasinglulu .sdram_rcw[0] = U(0x00), 68*91f16700Schasinglulu .sdram_rcw[1] = U(0x00), 69*91f16700Schasinglulu .sdram_rcw[2] = U(0x00), 70*91f16700Schasinglulu .sdram_rcw[3] = U(0x00), 71*91f16700Schasinglulu .sdram_rcw[4] = U(0x00), 72*91f16700Schasinglulu .sdram_rcw[5] = U(0x00), 73*91f16700Schasinglulu .err_disable = U(0x00), 74*91f16700Schasinglulu .err_int_en = U(0x00), 75*91f16700Schasinglulu }; 76*91f16700Schasinglulu 77*91f16700Schasinglulu const struct ddr_cfg_regs static_2900 = { 78*91f16700Schasinglulu .cs[0].bnds = U(0x03FF), 79*91f16700Schasinglulu .cs[1].bnds = U(0x03FF), 80*91f16700Schasinglulu .cs[0].config = U(0x80050422), 81*91f16700Schasinglulu .cs[1].config = U(0x80000422), 82*91f16700Schasinglulu .cs[2].bnds = U(0x00), 83*91f16700Schasinglulu .cs[3].bnds = U(0x00), 84*91f16700Schasinglulu .cs[2].config = U(0x00), 85*91f16700Schasinglulu .cs[3].config = U(0x00), 86*91f16700Schasinglulu .timing_cfg[0] = U(0xFF990018), 87*91f16700Schasinglulu .timing_cfg[1] = U(0x4F4A4844), 88*91f16700Schasinglulu .timing_cfg[2] = U(0x0005601F), 89*91f16700Schasinglulu .timing_cfg[3] = U(0x125F2100), 90*91f16700Schasinglulu .timing_cfg[4] = U(0x02), 91*91f16700Schasinglulu .timing_cfg[5] = U(0x07401400), 92*91f16700Schasinglulu .timing_cfg[7] = U(0x3AA00000), 93*91f16700Schasinglulu .timing_cfg[8] = U(0x09449B00), 94*91f16700Schasinglulu .sdram_cfg[0] = U(0x65044008), 95*91f16700Schasinglulu .sdram_cfg[1] = U(0x00401011), 96*91f16700Schasinglulu .sdram_cfg[2] = U(0x00), 97*91f16700Schasinglulu .sdram_mode[0] = U(0x06010C50), 98*91f16700Schasinglulu .sdram_mode[1] = U(0x00280400), 99*91f16700Schasinglulu .sdram_mode[2] = U(0x00), 100*91f16700Schasinglulu .sdram_mode[3] = U(0x00), 101*91f16700Schasinglulu .sdram_mode[4] = U(0x00), 102*91f16700Schasinglulu .sdram_mode[5] = U(0x00), 103*91f16700Schasinglulu .sdram_mode[6] = U(0x00), 104*91f16700Schasinglulu .sdram_mode[7] = U(0x00), 105*91f16700Schasinglulu .sdram_mode[8] = U(0x0500), 106*91f16700Schasinglulu .sdram_mode[9] = U(0x10240000), 107*91f16700Schasinglulu .sdram_mode[10] = U(0x00), 108*91f16700Schasinglulu .sdram_mode[11] = U(0x00), 109*91f16700Schasinglulu .sdram_mode[12] = U(0x00), 110*91f16700Schasinglulu .sdram_mode[13] = U(0x00), 111*91f16700Schasinglulu .sdram_mode[14] = U(0x00), 112*91f16700Schasinglulu .sdram_mode[15] = U(0x00), 113*91f16700Schasinglulu .md_cntl = U(0x00), 114*91f16700Schasinglulu .interval = U(0x2C2E0000), 115*91f16700Schasinglulu .data_init = U(0xDEADBEEF), 116*91f16700Schasinglulu .init_addr = U(0x00), 117*91f16700Schasinglulu .zq_cntl = U(0x8A090705), 118*91f16700Schasinglulu .sdram_rcw[0] = U(0x00), 119*91f16700Schasinglulu .sdram_rcw[1] = U(0x00), 120*91f16700Schasinglulu .sdram_rcw[2] = U(0x00), 121*91f16700Schasinglulu .sdram_rcw[3] = U(0x00), 122*91f16700Schasinglulu .sdram_rcw[4] = U(0x00), 123*91f16700Schasinglulu .sdram_rcw[5] = U(0x00), 124*91f16700Schasinglulu .err_disable = U(0x00), 125*91f16700Schasinglulu .err_int_en = U(0x00), 126*91f16700Schasinglulu }; 127*91f16700Schasinglulu 128*91f16700Schasinglulu const struct ddr_cfg_regs static_2600 = { 129*91f16700Schasinglulu .cs[0].bnds = U(0x03FF), 130*91f16700Schasinglulu .cs[1].bnds = U(0x03FF), 131*91f16700Schasinglulu .cs[0].config = U(0x80050422), 132*91f16700Schasinglulu .cs[1].config = U(0x80000422), 133*91f16700Schasinglulu .cs[2].bnds = U(0x00), 134*91f16700Schasinglulu .cs[3].bnds = U(0x00), 135*91f16700Schasinglulu .cs[2].config = U(0x00), 136*91f16700Schasinglulu .cs[3].config = U(0x00), 137*91f16700Schasinglulu .timing_cfg[0] = U(0xFF880018), 138*91f16700Schasinglulu .timing_cfg[1] = U(0x2A24F444), 139*91f16700Schasinglulu .timing_cfg[2] = U(0x007141DC), 140*91f16700Schasinglulu .timing_cfg[3] = U(0x125B2100), 141*91f16700Schasinglulu .timing_cfg[4] = U(0x02), 142*91f16700Schasinglulu .timing_cfg[5] = U(0x06401400), 143*91f16700Schasinglulu .timing_cfg[7] = U(0x28800000), 144*91f16700Schasinglulu .timing_cfg[8] = U(0x07338A00), 145*91f16700Schasinglulu .sdram_cfg[0] = U(0x65044008), 146*91f16700Schasinglulu .sdram_cfg[1] = U(0x00401011), 147*91f16700Schasinglulu .sdram_cfg[2] = U(0x00), 148*91f16700Schasinglulu .sdram_mode[0] = U(0x06010A70), 149*91f16700Schasinglulu .sdram_mode[1] = U(0x00200400), 150*91f16700Schasinglulu .sdram_mode[2] = U(0x00), 151*91f16700Schasinglulu .sdram_mode[3] = U(0x00), 152*91f16700Schasinglulu .sdram_mode[4] = U(0x00), 153*91f16700Schasinglulu .sdram_mode[5] = U(0x00), 154*91f16700Schasinglulu .sdram_mode[6] = U(0x00), 155*91f16700Schasinglulu .sdram_mode[7] = U(0x00), 156*91f16700Schasinglulu .sdram_mode[8] = U(0x0500), 157*91f16700Schasinglulu .sdram_mode[9] = U(0x0C240000), 158*91f16700Schasinglulu .sdram_mode[10] = U(0x00), 159*91f16700Schasinglulu .sdram_mode[11] = U(0x00), 160*91f16700Schasinglulu .sdram_mode[12] = U(0x00), 161*91f16700Schasinglulu .sdram_mode[13] = U(0x00), 162*91f16700Schasinglulu .sdram_mode[14] = U(0x00), 163*91f16700Schasinglulu .sdram_mode[15] = U(0x00), 164*91f16700Schasinglulu .md_cntl = U(0x00), 165*91f16700Schasinglulu .interval = U(0x279C0000), 166*91f16700Schasinglulu .data_init = U(0xDEADBEEF), 167*91f16700Schasinglulu .init_addr = U(0x00), 168*91f16700Schasinglulu .zq_cntl = U(0x8A090705), 169*91f16700Schasinglulu .sdram_rcw[0] = U(0x00), 170*91f16700Schasinglulu .sdram_rcw[1] = U(0x00), 171*91f16700Schasinglulu .sdram_rcw[2] = U(0x00), 172*91f16700Schasinglulu .sdram_rcw[3] = U(0x00), 173*91f16700Schasinglulu .sdram_rcw[4] = U(0x00), 174*91f16700Schasinglulu .sdram_rcw[5] = U(0x00), 175*91f16700Schasinglulu .err_disable = U(0x00), 176*91f16700Schasinglulu .err_int_en = U(0x00), 177*91f16700Schasinglulu }; 178*91f16700Schasinglulu 179*91f16700Schasinglulu const struct dimm_params static_dimm = { 180*91f16700Schasinglulu .rdimm = 0U, 181*91f16700Schasinglulu .primary_sdram_width = 64U, 182*91f16700Schasinglulu .ec_sdram_width = 8U, 183*91f16700Schasinglulu .n_ranks = 2U, 184*91f16700Schasinglulu .device_width = 8U, 185*91f16700Schasinglulu .mirrored_dimm = 1U, 186*91f16700Schasinglulu }; 187*91f16700Schasinglulu 188*91f16700Schasinglulu /* Sample code using two UDIMM MT18ASF1G72AZ-2G6B1, on each DDR controller */ 189*91f16700Schasinglulu unsigned long long board_static_ddr(struct ddr_info *priv) 190*91f16700Schasinglulu { 191*91f16700Schasinglulu memcpy(&priv->ddr_reg, &static_2900, sizeof(static_2900)); 192*91f16700Schasinglulu memcpy(&priv->dimm, &static_dimm, sizeof(static_dimm)); 193*91f16700Schasinglulu priv->conf.cs_on_dimm[0] = 0x3; 194*91f16700Schasinglulu ddr_board_options(priv); 195*91f16700Schasinglulu compute_ddr_phy(priv); 196*91f16700Schasinglulu 197*91f16700Schasinglulu return ULL(0x400000000); 198*91f16700Schasinglulu } 199*91f16700Schasinglulu 200*91f16700Schasinglulu #elif defined(CONFIG_DDR_NODIMM) 201*91f16700Schasinglulu /* 202*91f16700Schasinglulu * Sample code to bypass reading SPD. This is a sample, not recommended 203*91f16700Schasinglulu * for boards with slots. DDR model number: UDIMM MT18ASF1G72AZ-2G6B1. 204*91f16700Schasinglulu */ 205*91f16700Schasinglulu struct dimm_params ddr_raw_timing = { 206*91f16700Schasinglulu .n_ranks = 2U, 207*91f16700Schasinglulu .rank_density = U(0x200000000), 208*91f16700Schasinglulu .capacity = U(0x400000000), 209*91f16700Schasinglulu .primary_sdram_width = 64U, 210*91f16700Schasinglulu .ec_sdram_width = 8U, 211*91f16700Schasinglulu .device_width = 8U, 212*91f16700Schasinglulu .die_density = U(0x5), 213*91f16700Schasinglulu .rdimm = 0U, 214*91f16700Schasinglulu .mirrored_dimm = 1U, 215*91f16700Schasinglulu .n_row_addr = 16U, 216*91f16700Schasinglulu .n_col_addr = 10U, 217*91f16700Schasinglulu .bank_addr_bits = 0U, 218*91f16700Schasinglulu .bank_group_bits = 2U, 219*91f16700Schasinglulu .edc_config = 2U, 220*91f16700Schasinglulu .burst_lengths_bitmask = U(0x0c), 221*91f16700Schasinglulu .tckmin_x_ps = 625, 222*91f16700Schasinglulu .tckmax_ps = 1600, 223*91f16700Schasinglulu .caslat_x = U(0x15FFFC00), 224*91f16700Schasinglulu .taa_ps = 13750, 225*91f16700Schasinglulu .trcd_ps = 13750, 226*91f16700Schasinglulu .trp_ps = 13750, 227*91f16700Schasinglulu .tras_ps = 32000, 228*91f16700Schasinglulu .trc_ps = 457500, 229*91f16700Schasinglulu .twr_ps = 15000, 230*91f16700Schasinglulu .trfc1_ps = 350000, 231*91f16700Schasinglulu .trfc2_ps = 260000, 232*91f16700Schasinglulu .trfc4_ps = 160000, 233*91f16700Schasinglulu .tfaw_ps = 21000, 234*91f16700Schasinglulu .trrds_ps = 2500, 235*91f16700Schasinglulu .trrdl_ps = 4900, 236*91f16700Schasinglulu .tccdl_ps = 5000, 237*91f16700Schasinglulu .refresh_rate_ps = 7800000U, 238*91f16700Schasinglulu }; 239*91f16700Schasinglulu 240*91f16700Schasinglulu int ddr_get_ddr_params(struct dimm_params *pdimm, 241*91f16700Schasinglulu struct ddr_conf *conf) 242*91f16700Schasinglulu { 243*91f16700Schasinglulu static const char dimm_model[] = "Fixed DDR on board"; 244*91f16700Schasinglulu 245*91f16700Schasinglulu conf->dimm_in_use[0] = 1; /* Modify accordingly */ 246*91f16700Schasinglulu memcpy(pdimm, &ddr_raw_timing, sizeof(struct dimm_params)); 247*91f16700Schasinglulu memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); 248*91f16700Schasinglulu 249*91f16700Schasinglulu /* valid DIMM mask, change accordingly, together with dimm_on_ctlr. */ 250*91f16700Schasinglulu return 0x5; 251*91f16700Schasinglulu } 252*91f16700Schasinglulu #endif /* CONFIG_DDR_NODIMM */ 253*91f16700Schasinglulu 254*91f16700Schasinglulu int ddr_board_options(struct ddr_info *priv) 255*91f16700Schasinglulu { 256*91f16700Schasinglulu struct memctl_opt *popts = &priv->opt; 257*91f16700Schasinglulu const struct ddr_conf *conf = &priv->conf; 258*91f16700Schasinglulu 259*91f16700Schasinglulu popts->vref_dimm = U(0x19); /* range 1, 83.4% */ 260*91f16700Schasinglulu popts->rtt_override = 1U; 261*91f16700Schasinglulu popts->rtt_override_value = 0x5U; /* RTT being used as 60 ohm */ 262*91f16700Schasinglulu popts->rtt_park = 120U; 263*91f16700Schasinglulu popts->otf_burst_chop_en = 0; 264*91f16700Schasinglulu popts->burst_length = DDR_BL8; 265*91f16700Schasinglulu popts->trwt_override = 1U; 266*91f16700Schasinglulu popts->bstopre = 0U; /* auto precharge */ 267*91f16700Schasinglulu popts->addr_hash = 1; 268*91f16700Schasinglulu 269*91f16700Schasinglulu /* Set ODT impedance on PHY side */ 270*91f16700Schasinglulu switch (conf->cs_on_dimm[1]) { 271*91f16700Schasinglulu case 0xc: /* Two slots dual rank */ 272*91f16700Schasinglulu case 0x4: /* Two slots single rank, not valid for interleaving */ 273*91f16700Schasinglulu popts->trwt = U(0xf); 274*91f16700Schasinglulu popts->twrt = U(0x7); 275*91f16700Schasinglulu popts->trrt = U(0x7); 276*91f16700Schasinglulu popts->twwt = U(0x7); 277*91f16700Schasinglulu popts->vref_phy = U(0x6B); /* 83.6% */ 278*91f16700Schasinglulu popts->odt = 60U; 279*91f16700Schasinglulu popts->phy_tx_impedance = 28U; 280*91f16700Schasinglulu break; 281*91f16700Schasinglulu case 0: /* Ont slot used */ 282*91f16700Schasinglulu default: 283*91f16700Schasinglulu popts->trwt = U(0x3); 284*91f16700Schasinglulu popts->twrt = U(0x3); 285*91f16700Schasinglulu popts->trrt = U(0x3); 286*91f16700Schasinglulu popts->twwt = U(0x3); 287*91f16700Schasinglulu popts->vref_phy = U(0x5D); /* 72% */ 288*91f16700Schasinglulu popts->odt = 60U; 289*91f16700Schasinglulu popts->phy_tx_impedance = 28U; 290*91f16700Schasinglulu break; 291*91f16700Schasinglulu } 292*91f16700Schasinglulu 293*91f16700Schasinglulu return 0; 294*91f16700Schasinglulu } 295*91f16700Schasinglulu 296*91f16700Schasinglulu #ifdef NXP_WARM_BOOT 297*91f16700Schasinglulu long long init_ddr(uint32_t wrm_bt_flg) 298*91f16700Schasinglulu #else 299*91f16700Schasinglulu long long init_ddr(void) 300*91f16700Schasinglulu #endif 301*91f16700Schasinglulu { 302*91f16700Schasinglulu int spd_addr[] = { 0x51, 0x52, 0x53, 0x54 }; 303*91f16700Schasinglulu struct ddr_info info; 304*91f16700Schasinglulu struct sysinfo sys; 305*91f16700Schasinglulu long long dram_size; 306*91f16700Schasinglulu 307*91f16700Schasinglulu zeromem(&sys, sizeof(sys)); 308*91f16700Schasinglulu if (get_clocks(&sys) != 0) { 309*91f16700Schasinglulu ERROR("System clocks are not set\n"); 310*91f16700Schasinglulu panic(); 311*91f16700Schasinglulu } 312*91f16700Schasinglulu debug("platform clock %lu\n", sys.freq_platform); 313*91f16700Schasinglulu debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); 314*91f16700Schasinglulu debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); 315*91f16700Schasinglulu 316*91f16700Schasinglulu zeromem(&info, sizeof(info)); 317*91f16700Schasinglulu 318*91f16700Schasinglulu /* Set two DDRC. Unused DDRC will be removed automatically. */ 319*91f16700Schasinglulu info.num_ctlrs = NUM_OF_DDRC; 320*91f16700Schasinglulu info.spd_addr = spd_addr; 321*91f16700Schasinglulu info.ddr[0] = (void *)NXP_DDR_ADDR; 322*91f16700Schasinglulu info.ddr[1] = (void *)NXP_DDR2_ADDR; 323*91f16700Schasinglulu info.phy[0] = (void *)NXP_DDR_PHY1_ADDR; 324*91f16700Schasinglulu info.phy[1] = (void *)NXP_DDR_PHY2_ADDR; 325*91f16700Schasinglulu info.clk = get_ddr_freq(&sys, 0); 326*91f16700Schasinglulu info.img_loadr = load_img; 327*91f16700Schasinglulu info.phy_gen2_fw_img_buf = PHY_GEN2_FW_IMAGE_BUFFER; 328*91f16700Schasinglulu if (info.clk == 0) { 329*91f16700Schasinglulu info.clk = get_ddr_freq(&sys, 1); 330*91f16700Schasinglulu } 331*91f16700Schasinglulu info.dimm_on_ctlr = DDRC_NUM_DIMM; 332*91f16700Schasinglulu 333*91f16700Schasinglulu info.warm_boot_flag = DDR_WRM_BOOT_NT_SUPPORTED; 334*91f16700Schasinglulu #ifdef NXP_WARM_BOOT 335*91f16700Schasinglulu if (wrm_bt_flg != 0) { 336*91f16700Schasinglulu info.warm_boot_flag = DDR_WARM_BOOT; 337*91f16700Schasinglulu } else { 338*91f16700Schasinglulu info.warm_boot_flag = DDR_COLD_BOOT; 339*91f16700Schasinglulu } 340*91f16700Schasinglulu #endif 341*91f16700Schasinglulu 342*91f16700Schasinglulu dram_size = dram_init(&info 343*91f16700Schasinglulu #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) 344*91f16700Schasinglulu , NXP_CCN_HN_F_0_ADDR 345*91f16700Schasinglulu #endif 346*91f16700Schasinglulu ); 347*91f16700Schasinglulu 348*91f16700Schasinglulu 349*91f16700Schasinglulu if (dram_size < 0) { 350*91f16700Schasinglulu ERROR("DDR init failed.\n"); 351*91f16700Schasinglulu } 352*91f16700Schasinglulu 353*91f16700Schasinglulu return dram_size; 354*91f16700Schasinglulu } 355