1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright 2021 NXP 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <errno.h> 8*91f16700Schasinglulu #include <inttypes.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu #include <stdio.h> 11*91f16700Schasinglulu #include <stdlib.h> 12*91f16700Schasinglulu #include <string.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <ddr.h> 16*91f16700Schasinglulu #ifndef CONFIG_DDR_NODIMM 17*91f16700Schasinglulu #include <i2c.h> 18*91f16700Schasinglulu #endif 19*91f16700Schasinglulu #include <nxp_timer.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu struct dynamic_odt { 22*91f16700Schasinglulu unsigned int odt_rd_cfg; 23*91f16700Schasinglulu unsigned int odt_wr_cfg; 24*91f16700Schasinglulu unsigned int odt_rtt_norm; 25*91f16700Schasinglulu unsigned int odt_rtt_wr; 26*91f16700Schasinglulu }; 27*91f16700Schasinglulu 28*91f16700Schasinglulu #ifndef CONFIG_STATIC_DDR 29*91f16700Schasinglulu #if defined(PHY_GEN2_FW_IMAGE_BUFFER) && !defined(NXP_DDR_PHY_GEN2) 30*91f16700Schasinglulu #error Missing NXP_DDR_PHY_GEN2 31*91f16700Schasinglulu #endif 32*91f16700Schasinglulu #ifdef NXP_DDR_PHY_GEN2 33*91f16700Schasinglulu static const struct dynamic_odt single_D[4] = { 34*91f16700Schasinglulu { /* cs0 */ 35*91f16700Schasinglulu DDR_ODT_NEVER, 36*91f16700Schasinglulu DDR_ODT_ALL, 37*91f16700Schasinglulu DDR4_RTT_80_OHM, 38*91f16700Schasinglulu DDR4_RTT_WR_OFF 39*91f16700Schasinglulu }, 40*91f16700Schasinglulu { /* cs1 */ 41*91f16700Schasinglulu DDR_ODT_NEVER, 42*91f16700Schasinglulu DDR_ODT_NEVER, 43*91f16700Schasinglulu DDR4_RTT_OFF, 44*91f16700Schasinglulu DDR4_RTT_WR_OFF 45*91f16700Schasinglulu }, 46*91f16700Schasinglulu {}, 47*91f16700Schasinglulu {} 48*91f16700Schasinglulu }; 49*91f16700Schasinglulu 50*91f16700Schasinglulu static const struct dynamic_odt single_S[4] = { 51*91f16700Schasinglulu { /* cs0 */ 52*91f16700Schasinglulu DDR_ODT_NEVER, 53*91f16700Schasinglulu DDR_ODT_ALL, 54*91f16700Schasinglulu DDR4_RTT_80_OHM, 55*91f16700Schasinglulu DDR4_RTT_WR_OFF 56*91f16700Schasinglulu }, 57*91f16700Schasinglulu {}, 58*91f16700Schasinglulu {}, 59*91f16700Schasinglulu {}, 60*91f16700Schasinglulu }; 61*91f16700Schasinglulu 62*91f16700Schasinglulu static const struct dynamic_odt dual_DD[4] = { 63*91f16700Schasinglulu { /* cs0 */ 64*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 65*91f16700Schasinglulu DDR_ODT_ALL, 66*91f16700Schasinglulu DDR4_RTT_60_OHM, 67*91f16700Schasinglulu DDR4_RTT_WR_240_OHM 68*91f16700Schasinglulu }, 69*91f16700Schasinglulu { /* cs1 */ 70*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 71*91f16700Schasinglulu DDR_ODT_ALL, 72*91f16700Schasinglulu DDR4_RTT_60_OHM, 73*91f16700Schasinglulu DDR4_RTT_WR_240_OHM 74*91f16700Schasinglulu }, 75*91f16700Schasinglulu { /* cs2 */ 76*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 77*91f16700Schasinglulu DDR_ODT_ALL, 78*91f16700Schasinglulu DDR4_RTT_60_OHM, 79*91f16700Schasinglulu DDR4_RTT_WR_240_OHM 80*91f16700Schasinglulu }, 81*91f16700Schasinglulu { /* cs3 */ 82*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 83*91f16700Schasinglulu DDR_ODT_ALL, 84*91f16700Schasinglulu DDR4_RTT_60_OHM, 85*91f16700Schasinglulu DDR4_RTT_WR_240_OHM 86*91f16700Schasinglulu } 87*91f16700Schasinglulu }; 88*91f16700Schasinglulu 89*91f16700Schasinglulu static const struct dynamic_odt dual_SS[4] = { 90*91f16700Schasinglulu { /* cs0 */ 91*91f16700Schasinglulu DDR_ODT_NEVER, 92*91f16700Schasinglulu DDR_ODT_ALL, 93*91f16700Schasinglulu DDR4_RTT_80_OHM, 94*91f16700Schasinglulu DDR4_RTT_WR_OFF 95*91f16700Schasinglulu }, 96*91f16700Schasinglulu {}, 97*91f16700Schasinglulu { /* cs2 */ 98*91f16700Schasinglulu DDR_ODT_NEVER, 99*91f16700Schasinglulu DDR_ODT_ALL, 100*91f16700Schasinglulu DDR4_RTT_80_OHM, 101*91f16700Schasinglulu DDR4_RTT_WR_OFF 102*91f16700Schasinglulu }, 103*91f16700Schasinglulu {} 104*91f16700Schasinglulu }; 105*91f16700Schasinglulu 106*91f16700Schasinglulu static const struct dynamic_odt dual_D0[4] = { 107*91f16700Schasinglulu { /* cs0 */ 108*91f16700Schasinglulu DDR_ODT_NEVER, 109*91f16700Schasinglulu DDR_ODT_SAME_DIMM, 110*91f16700Schasinglulu DDR4_RTT_80_OHM, 111*91f16700Schasinglulu DDR4_RTT_WR_OFF 112*91f16700Schasinglulu }, 113*91f16700Schasinglulu { /* cs1 */ 114*91f16700Schasinglulu DDR_ODT_NEVER, 115*91f16700Schasinglulu DDR_ODT_NEVER, 116*91f16700Schasinglulu DDR4_RTT_80_OHM, 117*91f16700Schasinglulu DDR4_RTT_WR_OFF 118*91f16700Schasinglulu }, 119*91f16700Schasinglulu {}, 120*91f16700Schasinglulu {} 121*91f16700Schasinglulu }; 122*91f16700Schasinglulu 123*91f16700Schasinglulu static const struct dynamic_odt dual_S0[4] = { 124*91f16700Schasinglulu { /* cs0 */ 125*91f16700Schasinglulu DDR_ODT_NEVER, 126*91f16700Schasinglulu DDR_ODT_CS, 127*91f16700Schasinglulu DDR4_RTT_80_OHM, 128*91f16700Schasinglulu DDR4_RTT_WR_OFF 129*91f16700Schasinglulu }, 130*91f16700Schasinglulu {}, 131*91f16700Schasinglulu {}, 132*91f16700Schasinglulu {} 133*91f16700Schasinglulu }; 134*91f16700Schasinglulu #else 135*91f16700Schasinglulu static const struct dynamic_odt single_D[4] = { 136*91f16700Schasinglulu { /* cs0 */ 137*91f16700Schasinglulu DDR_ODT_NEVER, 138*91f16700Schasinglulu DDR_ODT_ALL, 139*91f16700Schasinglulu DDR4_RTT_40_OHM, 140*91f16700Schasinglulu DDR4_RTT_WR_OFF 141*91f16700Schasinglulu }, 142*91f16700Schasinglulu { /* cs1 */ 143*91f16700Schasinglulu DDR_ODT_NEVER, 144*91f16700Schasinglulu DDR_ODT_NEVER, 145*91f16700Schasinglulu DDR4_RTT_OFF, 146*91f16700Schasinglulu DDR4_RTT_WR_OFF 147*91f16700Schasinglulu }, 148*91f16700Schasinglulu {}, 149*91f16700Schasinglulu {} 150*91f16700Schasinglulu }; 151*91f16700Schasinglulu 152*91f16700Schasinglulu static const struct dynamic_odt single_S[4] = { 153*91f16700Schasinglulu { /* cs0 */ 154*91f16700Schasinglulu DDR_ODT_NEVER, 155*91f16700Schasinglulu DDR_ODT_ALL, 156*91f16700Schasinglulu DDR4_RTT_40_OHM, 157*91f16700Schasinglulu DDR4_RTT_WR_OFF 158*91f16700Schasinglulu }, 159*91f16700Schasinglulu {}, 160*91f16700Schasinglulu {}, 161*91f16700Schasinglulu {}, 162*91f16700Schasinglulu }; 163*91f16700Schasinglulu 164*91f16700Schasinglulu static const struct dynamic_odt dual_DD[4] = { 165*91f16700Schasinglulu { /* cs0 */ 166*91f16700Schasinglulu DDR_ODT_NEVER, 167*91f16700Schasinglulu DDR_ODT_SAME_DIMM, 168*91f16700Schasinglulu DDR4_RTT_120_OHM, 169*91f16700Schasinglulu DDR4_RTT_WR_OFF 170*91f16700Schasinglulu }, 171*91f16700Schasinglulu { /* cs1 */ 172*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 173*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 174*91f16700Schasinglulu DDR4_RTT_34_OHM, 175*91f16700Schasinglulu DDR4_RTT_WR_OFF 176*91f16700Schasinglulu }, 177*91f16700Schasinglulu { /* cs2 */ 178*91f16700Schasinglulu DDR_ODT_NEVER, 179*91f16700Schasinglulu DDR_ODT_SAME_DIMM, 180*91f16700Schasinglulu DDR4_RTT_120_OHM, 181*91f16700Schasinglulu DDR4_RTT_WR_OFF 182*91f16700Schasinglulu }, 183*91f16700Schasinglulu { /* cs3 */ 184*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 185*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 186*91f16700Schasinglulu DDR4_RTT_34_OHM, 187*91f16700Schasinglulu DDR4_RTT_WR_OFF 188*91f16700Schasinglulu } 189*91f16700Schasinglulu }; 190*91f16700Schasinglulu 191*91f16700Schasinglulu static const struct dynamic_odt dual_SS[4] = { 192*91f16700Schasinglulu { /* cs0 */ 193*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 194*91f16700Schasinglulu DDR_ODT_ALL, 195*91f16700Schasinglulu DDR4_RTT_34_OHM, 196*91f16700Schasinglulu DDR4_RTT_WR_120_OHM 197*91f16700Schasinglulu }, 198*91f16700Schasinglulu {}, 199*91f16700Schasinglulu { /* cs2 */ 200*91f16700Schasinglulu DDR_ODT_OTHER_DIMM, 201*91f16700Schasinglulu DDR_ODT_ALL, 202*91f16700Schasinglulu DDR4_RTT_34_OHM, 203*91f16700Schasinglulu DDR4_RTT_WR_120_OHM 204*91f16700Schasinglulu }, 205*91f16700Schasinglulu {} 206*91f16700Schasinglulu }; 207*91f16700Schasinglulu 208*91f16700Schasinglulu static const struct dynamic_odt dual_D0[4] = { 209*91f16700Schasinglulu { /* cs0 */ 210*91f16700Schasinglulu DDR_ODT_NEVER, 211*91f16700Schasinglulu DDR_ODT_SAME_DIMM, 212*91f16700Schasinglulu DDR4_RTT_40_OHM, 213*91f16700Schasinglulu DDR4_RTT_WR_OFF 214*91f16700Schasinglulu }, 215*91f16700Schasinglulu { /* cs1 */ 216*91f16700Schasinglulu DDR_ODT_NEVER, 217*91f16700Schasinglulu DDR_ODT_NEVER, 218*91f16700Schasinglulu DDR4_RTT_OFF, 219*91f16700Schasinglulu DDR4_RTT_WR_OFF 220*91f16700Schasinglulu }, 221*91f16700Schasinglulu {}, 222*91f16700Schasinglulu {} 223*91f16700Schasinglulu }; 224*91f16700Schasinglulu 225*91f16700Schasinglulu static const struct dynamic_odt dual_S0[4] = { 226*91f16700Schasinglulu { /* cs0 */ 227*91f16700Schasinglulu DDR_ODT_NEVER, 228*91f16700Schasinglulu DDR_ODT_CS, 229*91f16700Schasinglulu DDR4_RTT_40_OHM, 230*91f16700Schasinglulu DDR4_RTT_WR_OFF 231*91f16700Schasinglulu }, 232*91f16700Schasinglulu {}, 233*91f16700Schasinglulu {}, 234*91f16700Schasinglulu {} 235*91f16700Schasinglulu }; 236*91f16700Schasinglulu #endif /* NXP_DDR_PHY_GEN2 */ 237*91f16700Schasinglulu 238*91f16700Schasinglulu /* 239*91f16700Schasinglulu * Automatically select bank interleaving mode based on DIMMs 240*91f16700Schasinglulu * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null. 241*91f16700Schasinglulu * This function only deal with one or two slots per controller. 242*91f16700Schasinglulu */ 243*91f16700Schasinglulu static inline unsigned int auto_bank_intlv(const int cs_in_use, 244*91f16700Schasinglulu const struct dimm_params *pdimm) 245*91f16700Schasinglulu { 246*91f16700Schasinglulu switch (cs_in_use) { 247*91f16700Schasinglulu case 0xf: 248*91f16700Schasinglulu return DDR_BA_INTLV_CS0123; 249*91f16700Schasinglulu case 0x3: 250*91f16700Schasinglulu return DDR_BA_INTLV_CS01; 251*91f16700Schasinglulu case 0x1: 252*91f16700Schasinglulu return DDR_BA_NONE; 253*91f16700Schasinglulu case 0x5: 254*91f16700Schasinglulu return DDR_BA_NONE; 255*91f16700Schasinglulu default: 256*91f16700Schasinglulu break; 257*91f16700Schasinglulu } 258*91f16700Schasinglulu 259*91f16700Schasinglulu return 0U; 260*91f16700Schasinglulu } 261*91f16700Schasinglulu 262*91f16700Schasinglulu static int cal_odt(const unsigned int clk, 263*91f16700Schasinglulu struct memctl_opt *popts, 264*91f16700Schasinglulu struct ddr_conf *conf, 265*91f16700Schasinglulu struct dimm_params *pdimm, 266*91f16700Schasinglulu const int dimm_slot_per_ctrl) 267*91f16700Schasinglulu 268*91f16700Schasinglulu { 269*91f16700Schasinglulu unsigned int i; 270*91f16700Schasinglulu const struct dynamic_odt *pdodt = NULL; 271*91f16700Schasinglulu 272*91f16700Schasinglulu static const struct dynamic_odt *table[2][5] = { 273*91f16700Schasinglulu {single_S, single_D, NULL, NULL}, 274*91f16700Schasinglulu {dual_SS, dual_DD, NULL, NULL}, 275*91f16700Schasinglulu }; 276*91f16700Schasinglulu 277*91f16700Schasinglulu if (dimm_slot_per_ctrl != 1 && dimm_slot_per_ctrl != 2) { 278*91f16700Schasinglulu ERROR("Unsupported number of DIMMs\n"); 279*91f16700Schasinglulu return -EINVAL; 280*91f16700Schasinglulu } 281*91f16700Schasinglulu 282*91f16700Schasinglulu pdodt = table[dimm_slot_per_ctrl - 1][pdimm->n_ranks - 1]; 283*91f16700Schasinglulu if (pdodt == dual_SS) { 284*91f16700Schasinglulu pdodt = (conf->cs_in_use == 0x5) ? dual_SS : 285*91f16700Schasinglulu ((conf->cs_in_use == 0x1) ? dual_S0 : NULL); 286*91f16700Schasinglulu } else if (pdodt == dual_DD) { 287*91f16700Schasinglulu pdodt = (conf->cs_in_use == 0xf) ? dual_DD : 288*91f16700Schasinglulu ((conf->cs_in_use == 0x3) ? dual_D0 : NULL); 289*91f16700Schasinglulu } 290*91f16700Schasinglulu if (pdodt == dual_DD && pdimm->package_3ds) { 291*91f16700Schasinglulu ERROR("Too many 3DS DIMMs.\n"); 292*91f16700Schasinglulu return -EINVAL; 293*91f16700Schasinglulu } 294*91f16700Schasinglulu 295*91f16700Schasinglulu if (pdodt == NULL) { 296*91f16700Schasinglulu ERROR("Error determining ODT.\n"); 297*91f16700Schasinglulu return -EINVAL; 298*91f16700Schasinglulu } 299*91f16700Schasinglulu 300*91f16700Schasinglulu /* Pick chip-select local options. */ 301*91f16700Schasinglulu for (i = 0U; i < DDRC_NUM_CS; i++) { 302*91f16700Schasinglulu debug("cs %d\n", i); 303*91f16700Schasinglulu popts->cs_odt[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; 304*91f16700Schasinglulu debug(" odt_rd_cfg 0x%x\n", 305*91f16700Schasinglulu popts->cs_odt[i].odt_rd_cfg); 306*91f16700Schasinglulu popts->cs_odt[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; 307*91f16700Schasinglulu debug(" odt_wr_cfg 0x%x\n", 308*91f16700Schasinglulu popts->cs_odt[i].odt_wr_cfg); 309*91f16700Schasinglulu popts->cs_odt[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; 310*91f16700Schasinglulu debug(" odt_rtt_norm 0x%x\n", 311*91f16700Schasinglulu popts->cs_odt[i].odt_rtt_norm); 312*91f16700Schasinglulu popts->cs_odt[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; 313*91f16700Schasinglulu debug(" odt_rtt_wr 0x%x\n", 314*91f16700Schasinglulu popts->cs_odt[i].odt_rtt_wr); 315*91f16700Schasinglulu popts->cs_odt[i].auto_precharge = 0; 316*91f16700Schasinglulu debug(" auto_precharge %d\n", 317*91f16700Schasinglulu popts->cs_odt[i].auto_precharge); 318*91f16700Schasinglulu } 319*91f16700Schasinglulu 320*91f16700Schasinglulu return 0; 321*91f16700Schasinglulu } 322*91f16700Schasinglulu 323*91f16700Schasinglulu static int cal_opts(const unsigned int clk, 324*91f16700Schasinglulu struct memctl_opt *popts, 325*91f16700Schasinglulu struct ddr_conf *conf, 326*91f16700Schasinglulu struct dimm_params *pdimm, 327*91f16700Schasinglulu const int dimm_slot_per_ctrl, 328*91f16700Schasinglulu const unsigned int ip_rev) 329*91f16700Schasinglulu { 330*91f16700Schasinglulu popts->rdimm = pdimm->rdimm; 331*91f16700Schasinglulu popts->mirrored_dimm = pdimm->mirrored_dimm; 332*91f16700Schasinglulu #ifdef CONFIG_DDR_ECC_EN 333*91f16700Schasinglulu popts->ecc_mode = pdimm->edc_config == 0x02 ? 1 : 0; 334*91f16700Schasinglulu #endif 335*91f16700Schasinglulu popts->ctlr_init_ecc = popts->ecc_mode; 336*91f16700Schasinglulu debug("ctlr_init_ecc %d\n", popts->ctlr_init_ecc); 337*91f16700Schasinglulu popts->self_refresh_in_sleep = 1; 338*91f16700Schasinglulu popts->dynamic_power = 0; 339*91f16700Schasinglulu 340*91f16700Schasinglulu /* 341*91f16700Schasinglulu * check sdram width, allow platform override 342*91f16700Schasinglulu * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit 343*91f16700Schasinglulu */ 344*91f16700Schasinglulu if (pdimm->primary_sdram_width == 64) { 345*91f16700Schasinglulu popts->data_bus_dimm = DDR_DBUS_64; 346*91f16700Schasinglulu popts->otf_burst_chop_en = 1; 347*91f16700Schasinglulu } else if (pdimm->primary_sdram_width == 32) { 348*91f16700Schasinglulu popts->data_bus_dimm = DDR_DBUS_32; 349*91f16700Schasinglulu popts->otf_burst_chop_en = 0; 350*91f16700Schasinglulu } else if (pdimm->primary_sdram_width == 16) { 351*91f16700Schasinglulu popts->data_bus_dimm = DDR_DBUS_16; 352*91f16700Schasinglulu popts->otf_burst_chop_en = 0; 353*91f16700Schasinglulu } else { 354*91f16700Schasinglulu ERROR("primary sdram width invalid!\n"); 355*91f16700Schasinglulu return -EINVAL; 356*91f16700Schasinglulu } 357*91f16700Schasinglulu popts->data_bus_used = popts->data_bus_dimm; 358*91f16700Schasinglulu popts->x4_en = (pdimm->device_width == 4) ? 1 : 0; 359*91f16700Schasinglulu debug("x4_en %d\n", popts->x4_en); 360*91f16700Schasinglulu 361*91f16700Schasinglulu /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ 362*91f16700Schasinglulu if (popts->rdimm != 0) { 363*91f16700Schasinglulu popts->ap_en = 1; /* 0 = disable, 1 = enable */ 364*91f16700Schasinglulu } else { 365*91f16700Schasinglulu popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ 366*91f16700Schasinglulu } 367*91f16700Schasinglulu 368*91f16700Schasinglulu if (ip_rev == 0x50500) { 369*91f16700Schasinglulu popts->ap_en = 0; 370*91f16700Schasinglulu } 371*91f16700Schasinglulu 372*91f16700Schasinglulu debug("ap_en %d\n", popts->ap_en); 373*91f16700Schasinglulu 374*91f16700Schasinglulu /* BSTTOPRE precharge interval uses 1/4 of refint value. */ 375*91f16700Schasinglulu popts->bstopre = picos_to_mclk(clk, pdimm->refresh_rate_ps) >> 2; 376*91f16700Schasinglulu popts->tfaw_ps = pdimm->tfaw_ps; 377*91f16700Schasinglulu 378*91f16700Schasinglulu return 0; 379*91f16700Schasinglulu } 380*91f16700Schasinglulu 381*91f16700Schasinglulu static void cal_intlv(const int num_ctlrs, 382*91f16700Schasinglulu struct memctl_opt *popts, 383*91f16700Schasinglulu struct ddr_conf *conf, 384*91f16700Schasinglulu struct dimm_params *pdimm) 385*91f16700Schasinglulu { 386*91f16700Schasinglulu #ifdef NXP_DDR_INTLV_256B 387*91f16700Schasinglulu if (num_ctlrs == 2) { 388*91f16700Schasinglulu popts->ctlr_intlv = 1; 389*91f16700Schasinglulu popts->ctlr_intlv_mode = DDR_256B_INTLV; 390*91f16700Schasinglulu } 391*91f16700Schasinglulu #endif 392*91f16700Schasinglulu debug("ctlr_intlv %d\n", popts->ctlr_intlv); 393*91f16700Schasinglulu debug("ctlr_intlv_mode %d\n", popts->ctlr_intlv_mode); 394*91f16700Schasinglulu 395*91f16700Schasinglulu popts->ba_intlv = auto_bank_intlv(conf->cs_in_use, pdimm); 396*91f16700Schasinglulu debug("ba_intlv 0x%x\n", popts->ba_intlv); 397*91f16700Schasinglulu } 398*91f16700Schasinglulu 399*91f16700Schasinglulu static int update_burst_length(struct memctl_opt *popts) 400*91f16700Schasinglulu { 401*91f16700Schasinglulu /* Choose burst length. */ 402*91f16700Schasinglulu if ((popts->data_bus_used == DDR_DBUS_32) || 403*91f16700Schasinglulu (popts->data_bus_used == DDR_DBUS_16)) { 404*91f16700Schasinglulu /* 32-bit or 16-bit bus */ 405*91f16700Schasinglulu popts->otf_burst_chop_en = 0; 406*91f16700Schasinglulu popts->burst_length = DDR_BL8; 407*91f16700Schasinglulu } else if (popts->otf_burst_chop_en != 0) { /* on-the-fly burst chop */ 408*91f16700Schasinglulu popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ 409*91f16700Schasinglulu } else { 410*91f16700Schasinglulu popts->burst_length = DDR_BL8; 411*91f16700Schasinglulu } 412*91f16700Schasinglulu debug("data_bus_used %d\n", popts->data_bus_used); 413*91f16700Schasinglulu debug("otf_burst_chop_en %d\n", popts->otf_burst_chop_en); 414*91f16700Schasinglulu debug("burst_length 0x%x\n", popts->burst_length); 415*91f16700Schasinglulu /* 416*91f16700Schasinglulu * If a reduced data width is requested, but the SPD 417*91f16700Schasinglulu * specifies a physically wider device, adjust the 418*91f16700Schasinglulu * computed dimm capacities accordingly before 419*91f16700Schasinglulu * assigning addresses. 420*91f16700Schasinglulu * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit 421*91f16700Schasinglulu */ 422*91f16700Schasinglulu if (popts->data_bus_dimm > popts->data_bus_used) { 423*91f16700Schasinglulu ERROR("Data bus configuration error\n"); 424*91f16700Schasinglulu return -EINVAL; 425*91f16700Schasinglulu } 426*91f16700Schasinglulu popts->dbw_cap_shift = popts->data_bus_used - popts->data_bus_dimm; 427*91f16700Schasinglulu debug("dbw_cap_shift %d\n", popts->dbw_cap_shift); 428*91f16700Schasinglulu 429*91f16700Schasinglulu return 0; 430*91f16700Schasinglulu } 431*91f16700Schasinglulu 432*91f16700Schasinglulu int cal_board_params(struct ddr_info *priv, 433*91f16700Schasinglulu const struct board_timing *dimm, 434*91f16700Schasinglulu int len) 435*91f16700Schasinglulu { 436*91f16700Schasinglulu const unsigned long speed = priv->clk / 1000000; 437*91f16700Schasinglulu const struct dimm_params *pdimm = &priv->dimm; 438*91f16700Schasinglulu struct memctl_opt *popts = &priv->opt; 439*91f16700Schasinglulu struct rc_timing const *prt = NULL; 440*91f16700Schasinglulu struct rc_timing const *chosen = NULL; 441*91f16700Schasinglulu int i; 442*91f16700Schasinglulu 443*91f16700Schasinglulu for (i = 0; i < len; i++) { 444*91f16700Schasinglulu if (pdimm->rc == dimm[i].rc) { 445*91f16700Schasinglulu prt = dimm[i].p; 446*91f16700Schasinglulu break; 447*91f16700Schasinglulu } 448*91f16700Schasinglulu } 449*91f16700Schasinglulu if (prt == NULL) { 450*91f16700Schasinglulu ERROR("Board parameters no match.\n"); 451*91f16700Schasinglulu return -EINVAL; 452*91f16700Schasinglulu } 453*91f16700Schasinglulu while (prt->speed_bin != 0) { 454*91f16700Schasinglulu if (speed <= prt->speed_bin) { 455*91f16700Schasinglulu chosen = prt; 456*91f16700Schasinglulu break; 457*91f16700Schasinglulu } 458*91f16700Schasinglulu prt++; 459*91f16700Schasinglulu } 460*91f16700Schasinglulu if (chosen == NULL) { 461*91f16700Schasinglulu ERROR("timing no match for speed %lu\n", speed); 462*91f16700Schasinglulu return -EINVAL; 463*91f16700Schasinglulu } 464*91f16700Schasinglulu popts->clk_adj = prt->clk_adj; 465*91f16700Schasinglulu popts->wrlvl_start = prt->wrlvl; 466*91f16700Schasinglulu popts->wrlvl_ctl_2 = (prt->wrlvl * 0x01010101 + dimm[i].add1) & 467*91f16700Schasinglulu 0xFFFFFFFF; 468*91f16700Schasinglulu popts->wrlvl_ctl_3 = (prt->wrlvl * 0x01010101 + dimm[i].add2) & 469*91f16700Schasinglulu 0xFFFFFFFF; 470*91f16700Schasinglulu 471*91f16700Schasinglulu return 0; 472*91f16700Schasinglulu } 473*91f16700Schasinglulu 474*91f16700Schasinglulu static int synthesize_ctlr(struct ddr_info *priv) 475*91f16700Schasinglulu { 476*91f16700Schasinglulu int ret; 477*91f16700Schasinglulu 478*91f16700Schasinglulu ret = cal_odt(priv->clk, 479*91f16700Schasinglulu &priv->opt, 480*91f16700Schasinglulu &priv->conf, 481*91f16700Schasinglulu &priv->dimm, 482*91f16700Schasinglulu priv->dimm_on_ctlr); 483*91f16700Schasinglulu if (ret != 0) { 484*91f16700Schasinglulu return ret; 485*91f16700Schasinglulu } 486*91f16700Schasinglulu 487*91f16700Schasinglulu ret = cal_opts(priv->clk, 488*91f16700Schasinglulu &priv->opt, 489*91f16700Schasinglulu &priv->conf, 490*91f16700Schasinglulu &priv->dimm, 491*91f16700Schasinglulu priv->dimm_on_ctlr, 492*91f16700Schasinglulu priv->ip_rev); 493*91f16700Schasinglulu 494*91f16700Schasinglulu if (ret != 0) { 495*91f16700Schasinglulu return ret; 496*91f16700Schasinglulu } 497*91f16700Schasinglulu 498*91f16700Schasinglulu cal_intlv(priv->num_ctlrs, &priv->opt, &priv->conf, &priv->dimm); 499*91f16700Schasinglulu ret = ddr_board_options(priv); 500*91f16700Schasinglulu if (ret != 0) { 501*91f16700Schasinglulu ERROR("Failed matching board timing.\n"); 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu ret = update_burst_length(&priv->opt); 505*91f16700Schasinglulu 506*91f16700Schasinglulu return ret; 507*91f16700Schasinglulu } 508*91f16700Schasinglulu 509*91f16700Schasinglulu /* Return the bit mask of valid DIMMs found */ 510*91f16700Schasinglulu static int parse_spd(struct ddr_info *priv) 511*91f16700Schasinglulu { 512*91f16700Schasinglulu struct ddr_conf *conf = &priv->conf; 513*91f16700Schasinglulu struct dimm_params *dimm = &priv->dimm; 514*91f16700Schasinglulu int j, valid_mask = 0; 515*91f16700Schasinglulu 516*91f16700Schasinglulu #ifdef CONFIG_DDR_NODIMM 517*91f16700Schasinglulu valid_mask = ddr_get_ddr_params(dimm, conf); 518*91f16700Schasinglulu if (valid_mask < 0) { 519*91f16700Schasinglulu ERROR("DDR params error\n"); 520*91f16700Schasinglulu return valid_mask; 521*91f16700Schasinglulu } 522*91f16700Schasinglulu #else 523*91f16700Schasinglulu const int *spd_addr = priv->spd_addr; 524*91f16700Schasinglulu const int num_ctlrs = priv->num_ctlrs; 525*91f16700Schasinglulu const int num_dimm = priv->dimm_on_ctlr; 526*91f16700Schasinglulu struct ddr4_spd spd[2]; 527*91f16700Schasinglulu unsigned int spd_checksum[2]; 528*91f16700Schasinglulu int addr_idx = 0; 529*91f16700Schasinglulu int spd_idx = 0; 530*91f16700Schasinglulu int ret, addr, i; 531*91f16700Schasinglulu 532*91f16700Schasinglulu /* Scan all DIMMs */ 533*91f16700Schasinglulu for (i = 0; i < num_ctlrs; i++) { 534*91f16700Schasinglulu debug("Controller %d\n", i); 535*91f16700Schasinglulu for (j = 0; j < num_dimm; j++, addr_idx++) { 536*91f16700Schasinglulu debug("DIMM %d\n", j); 537*91f16700Schasinglulu addr = spd_addr[addr_idx]; 538*91f16700Schasinglulu if (addr == 0) { 539*91f16700Schasinglulu if (j == 0) { 540*91f16700Schasinglulu ERROR("First SPD addr wrong.\n"); 541*91f16700Schasinglulu return -EINVAL; 542*91f16700Schasinglulu } 543*91f16700Schasinglulu continue; 544*91f16700Schasinglulu } 545*91f16700Schasinglulu debug("addr 0x%x\n", addr); 546*91f16700Schasinglulu ret = read_spd(addr, &spd[spd_idx], 547*91f16700Schasinglulu sizeof(struct ddr4_spd)); 548*91f16700Schasinglulu if (ret != 0) { /* invalid */ 549*91f16700Schasinglulu debug("Invalid SPD at address 0x%x\n", addr); 550*91f16700Schasinglulu continue; 551*91f16700Schasinglulu } 552*91f16700Schasinglulu 553*91f16700Schasinglulu spd_checksum[spd_idx] = 554*91f16700Schasinglulu (spd[spd_idx].crc[1] << 24) | 555*91f16700Schasinglulu (spd[spd_idx].crc[0] << 16) | 556*91f16700Schasinglulu (spd[spd_idx].mod_section.uc[127] << 8) | 557*91f16700Schasinglulu (spd[spd_idx].mod_section.uc[126] << 0); 558*91f16700Schasinglulu debug("checksum 0x%x\n", spd_checksum[spd_idx]); 559*91f16700Schasinglulu if (spd_checksum[spd_idx] == 0) { 560*91f16700Schasinglulu debug("Bad checksum, ignored.\n"); 561*91f16700Schasinglulu continue; 562*91f16700Schasinglulu } 563*91f16700Schasinglulu if (spd_idx == 0) { 564*91f16700Schasinglulu /* first valid SPD */ 565*91f16700Schasinglulu ret = cal_dimm_params(&spd[0], dimm); 566*91f16700Schasinglulu if (ret != 0) { 567*91f16700Schasinglulu ERROR("SPD calculation error\n"); 568*91f16700Schasinglulu return -EINVAL; 569*91f16700Schasinglulu } 570*91f16700Schasinglulu } 571*91f16700Schasinglulu 572*91f16700Schasinglulu if (spd_idx != 0 && spd_checksum[0] != 573*91f16700Schasinglulu spd_checksum[spd_idx]) { 574*91f16700Schasinglulu ERROR("Not identical DIMMs.\n"); 575*91f16700Schasinglulu return -EINVAL; 576*91f16700Schasinglulu } 577*91f16700Schasinglulu conf->dimm_in_use[j] = 1; 578*91f16700Schasinglulu valid_mask |= 1 << addr_idx; 579*91f16700Schasinglulu spd_idx = 1; 580*91f16700Schasinglulu } 581*91f16700Schasinglulu debug("done with controller %d\n", i); 582*91f16700Schasinglulu } 583*91f16700Schasinglulu switch (num_ctlrs) { 584*91f16700Schasinglulu case 1: 585*91f16700Schasinglulu if ((valid_mask & 0x1) == 0) { 586*91f16700Schasinglulu ERROR("First slot cannot be empty.\n"); 587*91f16700Schasinglulu return -EINVAL; 588*91f16700Schasinglulu } 589*91f16700Schasinglulu break; 590*91f16700Schasinglulu case 2: 591*91f16700Schasinglulu switch (num_dimm) { 592*91f16700Schasinglulu case 1: 593*91f16700Schasinglulu if (valid_mask == 0) { 594*91f16700Schasinglulu ERROR("Both slot empty\n"); 595*91f16700Schasinglulu return -EINVAL; 596*91f16700Schasinglulu } 597*91f16700Schasinglulu break; 598*91f16700Schasinglulu case 2: 599*91f16700Schasinglulu if (valid_mask != 0x5 && 600*91f16700Schasinglulu valid_mask != 0xf && 601*91f16700Schasinglulu (valid_mask & 0x7) != 0x4 && 602*91f16700Schasinglulu (valid_mask & 0xd) != 0x1) { 603*91f16700Schasinglulu ERROR("Invalid DIMM combination.\n"); 604*91f16700Schasinglulu return -EINVAL; 605*91f16700Schasinglulu } 606*91f16700Schasinglulu break; 607*91f16700Schasinglulu default: 608*91f16700Schasinglulu ERROR("Invalid number of DIMMs.\n"); 609*91f16700Schasinglulu return -EINVAL; 610*91f16700Schasinglulu } 611*91f16700Schasinglulu break; 612*91f16700Schasinglulu default: 613*91f16700Schasinglulu ERROR("Invalid number of controllers.\n"); 614*91f16700Schasinglulu return -EINVAL; 615*91f16700Schasinglulu } 616*91f16700Schasinglulu /* now we have valid and identical DIMMs on controllers */ 617*91f16700Schasinglulu #endif /* CONFIG_DDR_NODIMM */ 618*91f16700Schasinglulu 619*91f16700Schasinglulu debug("cal cs\n"); 620*91f16700Schasinglulu conf->cs_in_use = 0; 621*91f16700Schasinglulu for (j = 0; j < DDRC_NUM_DIMM; j++) { 622*91f16700Schasinglulu if (conf->dimm_in_use[j] == 0) { 623*91f16700Schasinglulu continue; 624*91f16700Schasinglulu } 625*91f16700Schasinglulu switch (dimm->n_ranks) { 626*91f16700Schasinglulu case 4: 627*91f16700Schasinglulu ERROR("Quad-rank DIMM not supported\n"); 628*91f16700Schasinglulu return -EINVAL; 629*91f16700Schasinglulu case 2: 630*91f16700Schasinglulu conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT); 631*91f16700Schasinglulu conf->cs_in_use |= conf->cs_on_dimm[j]; 632*91f16700Schasinglulu break; 633*91f16700Schasinglulu case 1: 634*91f16700Schasinglulu conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT); 635*91f16700Schasinglulu conf->cs_in_use |= conf->cs_on_dimm[j]; 636*91f16700Schasinglulu break; 637*91f16700Schasinglulu default: 638*91f16700Schasinglulu ERROR("SPD error with n_ranks\n"); 639*91f16700Schasinglulu return -EINVAL; 640*91f16700Schasinglulu } 641*91f16700Schasinglulu debug("cs_in_use = %x\n", conf->cs_in_use); 642*91f16700Schasinglulu debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]); 643*91f16700Schasinglulu } 644*91f16700Schasinglulu #ifndef CONFIG_DDR_NODIMM 645*91f16700Schasinglulu if (priv->dimm.rdimm != 0) { 646*91f16700Schasinglulu NOTICE("RDIMM %s\n", priv->dimm.mpart); 647*91f16700Schasinglulu } else { 648*91f16700Schasinglulu NOTICE("UDIMM %s\n", priv->dimm.mpart); 649*91f16700Schasinglulu } 650*91f16700Schasinglulu #else 651*91f16700Schasinglulu NOTICE("%s\n", priv->dimm.mpart); 652*91f16700Schasinglulu #endif 653*91f16700Schasinglulu 654*91f16700Schasinglulu return valid_mask; 655*91f16700Schasinglulu } 656*91f16700Schasinglulu 657*91f16700Schasinglulu static unsigned long long assign_intlv_addr( 658*91f16700Schasinglulu const struct dimm_params *pdimm, 659*91f16700Schasinglulu const struct memctl_opt *opt, 660*91f16700Schasinglulu struct ddr_conf *conf, 661*91f16700Schasinglulu const unsigned long long current_mem_base) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu int i; 664*91f16700Schasinglulu int ctlr_density_mul = 0; 665*91f16700Schasinglulu const unsigned long long rank_density = pdimm->rank_density >> 666*91f16700Schasinglulu opt->dbw_cap_shift; 667*91f16700Schasinglulu unsigned long long total_ctlr_mem; 668*91f16700Schasinglulu 669*91f16700Schasinglulu debug("rank density 0x%llx\n", rank_density); 670*91f16700Schasinglulu switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { 671*91f16700Schasinglulu case DDR_BA_INTLV_CS0123: 672*91f16700Schasinglulu ctlr_density_mul = 4; 673*91f16700Schasinglulu break; 674*91f16700Schasinglulu case DDR_BA_INTLV_CS01: 675*91f16700Schasinglulu ctlr_density_mul = 2; 676*91f16700Schasinglulu break; 677*91f16700Schasinglulu default: 678*91f16700Schasinglulu ctlr_density_mul = 1; 679*91f16700Schasinglulu break; 680*91f16700Schasinglulu } 681*91f16700Schasinglulu debug("ctlr density mul %d\n", ctlr_density_mul); 682*91f16700Schasinglulu switch (opt->ctlr_intlv_mode) { 683*91f16700Schasinglulu case DDR_256B_INTLV: 684*91f16700Schasinglulu total_ctlr_mem = 2 * ctlr_density_mul * rank_density; 685*91f16700Schasinglulu break; 686*91f16700Schasinglulu default: 687*91f16700Schasinglulu ERROR("Unknown interleaving mode"); 688*91f16700Schasinglulu return 0; 689*91f16700Schasinglulu } 690*91f16700Schasinglulu conf->base_addr = current_mem_base; 691*91f16700Schasinglulu conf->total_mem = total_ctlr_mem; 692*91f16700Schasinglulu 693*91f16700Schasinglulu /* overwrite cs_in_use bitmask with controller interleaving */ 694*91f16700Schasinglulu conf->cs_in_use = (1 << ctlr_density_mul) - 1; 695*91f16700Schasinglulu debug("Overwrite cs_in_use as %x\n", conf->cs_in_use); 696*91f16700Schasinglulu 697*91f16700Schasinglulu /* Fill addr with each cs in use */ 698*91f16700Schasinglulu for (i = 0; i < ctlr_density_mul; i++) { 699*91f16700Schasinglulu conf->cs_base_addr[i] = current_mem_base; 700*91f16700Schasinglulu conf->cs_size[i] = total_ctlr_mem; 701*91f16700Schasinglulu debug("CS %d\n", i); 702*91f16700Schasinglulu debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); 703*91f16700Schasinglulu debug(" size 0x%llx\n", conf->cs_size[i]); 704*91f16700Schasinglulu } 705*91f16700Schasinglulu 706*91f16700Schasinglulu return total_ctlr_mem; 707*91f16700Schasinglulu } 708*91f16700Schasinglulu 709*91f16700Schasinglulu static unsigned long long assign_non_intlv_addr( 710*91f16700Schasinglulu const struct dimm_params *pdimm, 711*91f16700Schasinglulu const struct memctl_opt *opt, 712*91f16700Schasinglulu struct ddr_conf *conf, 713*91f16700Schasinglulu unsigned long long current_mem_base) 714*91f16700Schasinglulu { 715*91f16700Schasinglulu int i; 716*91f16700Schasinglulu const unsigned long long rank_density = pdimm->rank_density >> 717*91f16700Schasinglulu opt->dbw_cap_shift; 718*91f16700Schasinglulu unsigned long long total_ctlr_mem = 0ULL; 719*91f16700Schasinglulu 720*91f16700Schasinglulu debug("rank density 0x%llx\n", rank_density); 721*91f16700Schasinglulu conf->base_addr = current_mem_base; 722*91f16700Schasinglulu 723*91f16700Schasinglulu /* assign each cs */ 724*91f16700Schasinglulu switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { 725*91f16700Schasinglulu case DDR_BA_INTLV_CS0123: 726*91f16700Schasinglulu for (i = 0; i < DDRC_NUM_CS; i++) { 727*91f16700Schasinglulu conf->cs_base_addr[i] = current_mem_base; 728*91f16700Schasinglulu conf->cs_size[i] = rank_density << 2; 729*91f16700Schasinglulu total_ctlr_mem += rank_density; 730*91f16700Schasinglulu } 731*91f16700Schasinglulu break; 732*91f16700Schasinglulu case DDR_BA_INTLV_CS01: 733*91f16700Schasinglulu for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && i < 2; i++) { 734*91f16700Schasinglulu conf->cs_base_addr[i] = current_mem_base; 735*91f16700Schasinglulu conf->cs_size[i] = rank_density << 1; 736*91f16700Schasinglulu total_ctlr_mem += rank_density; 737*91f16700Schasinglulu } 738*91f16700Schasinglulu current_mem_base += total_ctlr_mem; 739*91f16700Schasinglulu for (; ((conf->cs_in_use & (1 << i)) != 0) && i < DDRC_NUM_CS; 740*91f16700Schasinglulu i++) { 741*91f16700Schasinglulu conf->cs_base_addr[i] = current_mem_base; 742*91f16700Schasinglulu conf->cs_size[i] = rank_density; 743*91f16700Schasinglulu total_ctlr_mem += rank_density; 744*91f16700Schasinglulu current_mem_base += rank_density; 745*91f16700Schasinglulu } 746*91f16700Schasinglulu break; 747*91f16700Schasinglulu case DDR_BA_NONE: 748*91f16700Schasinglulu for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && 749*91f16700Schasinglulu (i < DDRC_NUM_CS); i++) { 750*91f16700Schasinglulu conf->cs_base_addr[i] = current_mem_base; 751*91f16700Schasinglulu conf->cs_size[i] = rank_density; 752*91f16700Schasinglulu current_mem_base += rank_density; 753*91f16700Schasinglulu total_ctlr_mem += rank_density; 754*91f16700Schasinglulu } 755*91f16700Schasinglulu break; 756*91f16700Schasinglulu default: 757*91f16700Schasinglulu ERROR("Unsupported bank interleaving\n"); 758*91f16700Schasinglulu return 0; 759*91f16700Schasinglulu } 760*91f16700Schasinglulu for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && 761*91f16700Schasinglulu (i < DDRC_NUM_CS); i++) { 762*91f16700Schasinglulu debug("CS %d\n", i); 763*91f16700Schasinglulu debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); 764*91f16700Schasinglulu debug(" size 0x%llx\n", conf->cs_size[i]); 765*91f16700Schasinglulu } 766*91f16700Schasinglulu 767*91f16700Schasinglulu return total_ctlr_mem; 768*91f16700Schasinglulu } 769*91f16700Schasinglulu 770*91f16700Schasinglulu unsigned long long assign_addresses(struct ddr_info *priv) 771*91f16700Schasinglulu __attribute__ ((weak)); 772*91f16700Schasinglulu 773*91f16700Schasinglulu unsigned long long assign_addresses(struct ddr_info *priv) 774*91f16700Schasinglulu { 775*91f16700Schasinglulu struct memctl_opt *opt = &priv->opt; 776*91f16700Schasinglulu const struct dimm_params *dimm = &priv->dimm; 777*91f16700Schasinglulu struct ddr_conf *conf = &priv->conf; 778*91f16700Schasinglulu unsigned long long current_mem_base = priv->mem_base; 779*91f16700Schasinglulu unsigned long long total_mem; 780*91f16700Schasinglulu 781*91f16700Schasinglulu total_mem = 0ULL; 782*91f16700Schasinglulu debug("ctlr_intlv %d\n", opt->ctlr_intlv); 783*91f16700Schasinglulu if (opt->ctlr_intlv != 0) { 784*91f16700Schasinglulu total_mem = assign_intlv_addr(dimm, opt, conf, 785*91f16700Schasinglulu current_mem_base); 786*91f16700Schasinglulu } else { 787*91f16700Schasinglulu /* 788*91f16700Schasinglulu * Simple linear assignment if memory controllers are not 789*91f16700Schasinglulu * interleaved. This is only valid for SoCs with single DDRC. 790*91f16700Schasinglulu */ 791*91f16700Schasinglulu total_mem = assign_non_intlv_addr(dimm, opt, conf, 792*91f16700Schasinglulu current_mem_base); 793*91f16700Schasinglulu } 794*91f16700Schasinglulu conf->total_mem = total_mem; 795*91f16700Schasinglulu debug("base 0x%llx\n", current_mem_base); 796*91f16700Schasinglulu debug("Total mem by assignment is 0x%llx\n", total_mem); 797*91f16700Schasinglulu 798*91f16700Schasinglulu return total_mem; 799*91f16700Schasinglulu } 800*91f16700Schasinglulu 801*91f16700Schasinglulu static int cal_ddrc_regs(struct ddr_info *priv) 802*91f16700Schasinglulu { 803*91f16700Schasinglulu int ret; 804*91f16700Schasinglulu 805*91f16700Schasinglulu ret = compute_ddrc(priv->clk, 806*91f16700Schasinglulu &priv->opt, 807*91f16700Schasinglulu &priv->conf, 808*91f16700Schasinglulu &priv->ddr_reg, 809*91f16700Schasinglulu &priv->dimm, 810*91f16700Schasinglulu priv->ip_rev); 811*91f16700Schasinglulu if (ret != 0) { 812*91f16700Schasinglulu ERROR("Calculating DDR registers failed\n"); 813*91f16700Schasinglulu } 814*91f16700Schasinglulu 815*91f16700Schasinglulu return ret; 816*91f16700Schasinglulu } 817*91f16700Schasinglulu 818*91f16700Schasinglulu #endif /* CONFIG_STATIC_DDR */ 819*91f16700Schasinglulu 820*91f16700Schasinglulu static int write_ddrc_regs(struct ddr_info *priv) 821*91f16700Schasinglulu { 822*91f16700Schasinglulu int i; 823*91f16700Schasinglulu int ret; 824*91f16700Schasinglulu 825*91f16700Schasinglulu for (i = 0; i < priv->num_ctlrs; i++) { 826*91f16700Schasinglulu ret = ddrc_set_regs(priv->clk, &priv->ddr_reg, priv->ddr[i], 0); 827*91f16700Schasinglulu if (ret != 0) { 828*91f16700Schasinglulu ERROR("Writing DDR register(s) failed\n"); 829*91f16700Schasinglulu return ret; 830*91f16700Schasinglulu } 831*91f16700Schasinglulu } 832*91f16700Schasinglulu 833*91f16700Schasinglulu return 0; 834*91f16700Schasinglulu } 835*91f16700Schasinglulu 836*91f16700Schasinglulu long long dram_init(struct ddr_info *priv 837*91f16700Schasinglulu #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) 838*91f16700Schasinglulu , uintptr_t nxp_ccn_hn_f0_addr 839*91f16700Schasinglulu #endif 840*91f16700Schasinglulu ) 841*91f16700Schasinglulu { 842*91f16700Schasinglulu uint64_t time __unused; 843*91f16700Schasinglulu long long dram_size; 844*91f16700Schasinglulu int ret; 845*91f16700Schasinglulu const uint64_t time_base = get_timer_val(0); 846*91f16700Schasinglulu unsigned int ip_rev = get_ddrc_version(priv->ddr[0]); 847*91f16700Schasinglulu 848*91f16700Schasinglulu int valid_spd_mask __unused; 849*91f16700Schasinglulu int scratch = 0x0; 850*91f16700Schasinglulu 851*91f16700Schasinglulu priv->ip_rev = ip_rev; 852*91f16700Schasinglulu 853*91f16700Schasinglulu #ifndef CONFIG_STATIC_DDR 854*91f16700Schasinglulu INFO("time base %" PRIu64 " ms\n", time_base); 855*91f16700Schasinglulu debug("Parse DIMM SPD(s)\n"); 856*91f16700Schasinglulu valid_spd_mask = parse_spd(priv); 857*91f16700Schasinglulu 858*91f16700Schasinglulu if (valid_spd_mask < 0) { 859*91f16700Schasinglulu ERROR("Parsing DIMM Error\n"); 860*91f16700Schasinglulu return valid_spd_mask; 861*91f16700Schasinglulu } 862*91f16700Schasinglulu 863*91f16700Schasinglulu #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) 864*91f16700Schasinglulu if (priv->num_ctlrs == 2 || priv->num_ctlrs == 1) { 865*91f16700Schasinglulu ret = disable_unused_ddrc(priv, valid_spd_mask, 866*91f16700Schasinglulu nxp_ccn_hn_f0_addr); 867*91f16700Schasinglulu if (ret != 0) { 868*91f16700Schasinglulu return ret; 869*91f16700Schasinglulu } 870*91f16700Schasinglulu } 871*91f16700Schasinglulu #endif 872*91f16700Schasinglulu 873*91f16700Schasinglulu time = get_timer_val(time_base); 874*91f16700Schasinglulu INFO("Time after parsing SPD %" PRIu64 " ms\n", time); 875*91f16700Schasinglulu debug("Synthesize configurations\n"); 876*91f16700Schasinglulu ret = synthesize_ctlr(priv); 877*91f16700Schasinglulu if (ret != 0) { 878*91f16700Schasinglulu ERROR("Synthesize config error\n"); 879*91f16700Schasinglulu return ret; 880*91f16700Schasinglulu } 881*91f16700Schasinglulu 882*91f16700Schasinglulu debug("Assign binding addresses\n"); 883*91f16700Schasinglulu dram_size = assign_addresses(priv); 884*91f16700Schasinglulu if (dram_size == 0) { 885*91f16700Schasinglulu ERROR("Assigning address error\n"); 886*91f16700Schasinglulu return -EINVAL; 887*91f16700Schasinglulu } 888*91f16700Schasinglulu 889*91f16700Schasinglulu debug("Calculate controller registers\n"); 890*91f16700Schasinglulu ret = cal_ddrc_regs(priv); 891*91f16700Schasinglulu if (ret != 0) { 892*91f16700Schasinglulu ERROR("Calculate register error\n"); 893*91f16700Schasinglulu return ret; 894*91f16700Schasinglulu } 895*91f16700Schasinglulu 896*91f16700Schasinglulu ret = compute_ddr_phy(priv); 897*91f16700Schasinglulu if (ret != 0) 898*91f16700Schasinglulu ERROR("Calculating DDR PHY registers failed.\n"); 899*91f16700Schasinglulu 900*91f16700Schasinglulu #else 901*91f16700Schasinglulu dram_size = board_static_ddr(priv); 902*91f16700Schasinglulu if (dram_size == 0) { 903*91f16700Schasinglulu ERROR("Error getting static DDR settings.\n"); 904*91f16700Schasinglulu return -EINVAL; 905*91f16700Schasinglulu } 906*91f16700Schasinglulu #endif 907*91f16700Schasinglulu 908*91f16700Schasinglulu if (priv->warm_boot_flag == DDR_WARM_BOOT) { 909*91f16700Schasinglulu scratch = (priv->ddr_reg).sdram_cfg[1]; 910*91f16700Schasinglulu scratch = scratch & ~(SDRAM_CFG2_D_INIT); 911*91f16700Schasinglulu priv->ddr_reg.sdram_cfg[1] = scratch; 912*91f16700Schasinglulu } 913*91f16700Schasinglulu 914*91f16700Schasinglulu time = get_timer_val(time_base); 915*91f16700Schasinglulu INFO("Time before programming controller %" PRIu64 " ms\n", time); 916*91f16700Schasinglulu debug("Program controller registers\n"); 917*91f16700Schasinglulu ret = write_ddrc_regs(priv); 918*91f16700Schasinglulu if (ret != 0) { 919*91f16700Schasinglulu ERROR("Programming DDRC error\n"); 920*91f16700Schasinglulu return ret; 921*91f16700Schasinglulu } 922*91f16700Schasinglulu 923*91f16700Schasinglulu puts(""); 924*91f16700Schasinglulu NOTICE("%lld GB ", dram_size >> 30); 925*91f16700Schasinglulu print_ddr_info(priv->ddr[0]); 926*91f16700Schasinglulu 927*91f16700Schasinglulu time = get_timer_val(time_base); 928*91f16700Schasinglulu INFO("Time used by DDR driver %" PRIu64 " ms\n", time); 929*91f16700Schasinglulu 930*91f16700Schasinglulu return dram_size; 931*91f16700Schasinglulu } 932