1*16662dc4SJiafei Pan /* 2*16662dc4SJiafei Pan * Copyright 2018-2022 NXP 3*16662dc4SJiafei Pan * 4*16662dc4SJiafei Pan * SPDX-License-Identifier: BSD-3-Clause 5*16662dc4SJiafei Pan */ 6*16662dc4SJiafei Pan 7*16662dc4SJiafei Pan #include <assert.h> 8*16662dc4SJiafei Pan #include <errno.h> 9*16662dc4SJiafei Pan 10*16662dc4SJiafei Pan #include <common/debug.h> 11*16662dc4SJiafei Pan #include <ddr.h> 12*16662dc4SJiafei Pan #include <lib/utils.h> 13*16662dc4SJiafei Pan 14*16662dc4SJiafei Pan #include <errata.h> 15*16662dc4SJiafei Pan 16*16662dc4SJiafei Pan static const struct rc_timing rce[] = { 17*16662dc4SJiafei Pan {U(1600), U(8), U(7)}, 18*16662dc4SJiafei Pan {U(1867), U(8), U(7)}, 19*16662dc4SJiafei Pan {U(2134), U(8), U(9)}, 20*16662dc4SJiafei Pan {} 21*16662dc4SJiafei Pan }; 22*16662dc4SJiafei Pan 23*16662dc4SJiafei Pan static const struct board_timing udimm[] = { 24*16662dc4SJiafei Pan {U(0x04), rce, U(0x01020304), U(0x06070805)}, 25*16662dc4SJiafei Pan }; 26*16662dc4SJiafei Pan 27*16662dc4SJiafei Pan int ddr_board_options(struct ddr_info *priv) 28*16662dc4SJiafei Pan { 29*16662dc4SJiafei Pan int ret; 30*16662dc4SJiafei Pan struct memctl_opt *popts = &priv->opt; 31*16662dc4SJiafei Pan 32*16662dc4SJiafei Pan if (popts->rdimm) { 33*16662dc4SJiafei Pan debug("RDIMM parameters not set.\n"); 34*16662dc4SJiafei Pan return -EINVAL; 35*16662dc4SJiafei Pan } 36*16662dc4SJiafei Pan 37*16662dc4SJiafei Pan ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm)); 38*16662dc4SJiafei Pan if (ret != 0) { 39*16662dc4SJiafei Pan return ret; 40*16662dc4SJiafei Pan } 41*16662dc4SJiafei Pan 42*16662dc4SJiafei Pan popts->wrlvl_override = U(1); 43*16662dc4SJiafei Pan popts->wrlvl_sample = U(0x0); /* 32 clocks */ 44*16662dc4SJiafei Pan popts->ddr_cdr1 = DDR_CDR1_DHC_EN | 45*16662dc4SJiafei Pan DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); 46*16662dc4SJiafei Pan popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | 47*16662dc4SJiafei Pan DDR_CDR2_VREF_TRAIN_EN | 48*16662dc4SJiafei Pan DDR_CDR2_VREF_RANGE_2; 49*16662dc4SJiafei Pan 50*16662dc4SJiafei Pan /* optimize cpo for erratum A-009942 */ 51*16662dc4SJiafei Pan popts->cpo_sample = U(0x70); 52*16662dc4SJiafei Pan 53*16662dc4SJiafei Pan return 0; 54*16662dc4SJiafei Pan } 55*16662dc4SJiafei Pan 56*16662dc4SJiafei Pan long long init_ddr(void) 57*16662dc4SJiafei Pan { 58*16662dc4SJiafei Pan int spd_addr[] = { NXP_SPD_EEPROM0 }; 59*16662dc4SJiafei Pan struct ddr_info info; 60*16662dc4SJiafei Pan struct sysinfo sys; 61*16662dc4SJiafei Pan long long dram_size; 62*16662dc4SJiafei Pan 63*16662dc4SJiafei Pan zeromem(&sys, sizeof(sys)); 64*16662dc4SJiafei Pan if (get_clocks(&sys)) { 65*16662dc4SJiafei Pan ERROR("System clocks are not set\n"); 66*16662dc4SJiafei Pan assert(0); 67*16662dc4SJiafei Pan } 68*16662dc4SJiafei Pan debug("platform clock %lu\n", sys.freq_platform); 69*16662dc4SJiafei Pan debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0); 70*16662dc4SJiafei Pan debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1); 71*16662dc4SJiafei Pan 72*16662dc4SJiafei Pan zeromem(&info, sizeof(struct ddr_info)); 73*16662dc4SJiafei Pan info.num_ctlrs = 1; 74*16662dc4SJiafei Pan info.dimm_on_ctlr = 1; 75*16662dc4SJiafei Pan info.clk = get_ddr_freq(&sys, 0); 76*16662dc4SJiafei Pan info.spd_addr = spd_addr; 77*16662dc4SJiafei Pan info.ddr[0] = (void *)NXP_DDR_ADDR; 78*16662dc4SJiafei Pan 79*16662dc4SJiafei Pan dram_size = dram_init(&info); 80*16662dc4SJiafei Pan 81*16662dc4SJiafei Pan if (dram_size < 0) { 82*16662dc4SJiafei Pan ERROR("DDR init failed.\n"); 83*16662dc4SJiafei Pan } 84*16662dc4SJiafei Pan 85*16662dc4SJiafei Pan #ifdef ERRATA_SOC_A008850 86*16662dc4SJiafei Pan erratum_a008850_post(); 87*16662dc4SJiafei Pan #endif 88*16662dc4SJiafei Pan 89*16662dc4SJiafei Pan return dram_size; 90*16662dc4SJiafei Pan } 91