116662dc4SJiafei Pan /*
216662dc4SJiafei Pan * Copyright 2018-2022 NXP
316662dc4SJiafei Pan *
416662dc4SJiafei Pan * SPDX-License-Identifier: BSD-3-Clause
516662dc4SJiafei Pan */
616662dc4SJiafei Pan
716662dc4SJiafei Pan #include <assert.h>
816662dc4SJiafei Pan #include <errno.h>
916662dc4SJiafei Pan
1016662dc4SJiafei Pan #include <common/debug.h>
1116662dc4SJiafei Pan #include <ddr.h>
1216662dc4SJiafei Pan #include <lib/utils.h>
1316662dc4SJiafei Pan
1416662dc4SJiafei Pan #include <errata.h>
15*885e2683SClaus Pedersen #include "platform_def.h"
1616662dc4SJiafei Pan
1716662dc4SJiafei Pan static const struct rc_timing rce[] = {
1816662dc4SJiafei Pan {U(1600), U(8), U(7)},
1916662dc4SJiafei Pan {U(1867), U(8), U(7)},
2016662dc4SJiafei Pan {U(2134), U(8), U(9)},
2116662dc4SJiafei Pan {}
2216662dc4SJiafei Pan };
2316662dc4SJiafei Pan
2416662dc4SJiafei Pan static const struct board_timing udimm[] = {
2516662dc4SJiafei Pan {U(0x04), rce, U(0x01020304), U(0x06070805)},
2616662dc4SJiafei Pan };
2716662dc4SJiafei Pan
ddr_board_options(struct ddr_info * priv)2816662dc4SJiafei Pan int ddr_board_options(struct ddr_info *priv)
2916662dc4SJiafei Pan {
3016662dc4SJiafei Pan int ret;
3116662dc4SJiafei Pan struct memctl_opt *popts = &priv->opt;
3216662dc4SJiafei Pan
3316662dc4SJiafei Pan if (popts->rdimm) {
3416662dc4SJiafei Pan debug("RDIMM parameters not set.\n");
3516662dc4SJiafei Pan return -EINVAL;
3616662dc4SJiafei Pan }
3716662dc4SJiafei Pan
3816662dc4SJiafei Pan ret = cal_board_params(priv, udimm, ARRAY_SIZE(udimm));
3916662dc4SJiafei Pan if (ret != 0) {
4016662dc4SJiafei Pan return ret;
4116662dc4SJiafei Pan }
4216662dc4SJiafei Pan
4316662dc4SJiafei Pan popts->wrlvl_override = U(1);
4416662dc4SJiafei Pan popts->wrlvl_sample = U(0x0); /* 32 clocks */
4516662dc4SJiafei Pan popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
4616662dc4SJiafei Pan DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
4716662dc4SJiafei Pan popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
4816662dc4SJiafei Pan DDR_CDR2_VREF_TRAIN_EN |
4916662dc4SJiafei Pan DDR_CDR2_VREF_RANGE_2;
5016662dc4SJiafei Pan
5116662dc4SJiafei Pan /* optimize cpo for erratum A-009942 */
5216662dc4SJiafei Pan popts->cpo_sample = U(0x70);
5316662dc4SJiafei Pan
5416662dc4SJiafei Pan return 0;
5516662dc4SJiafei Pan }
5616662dc4SJiafei Pan
init_ddr(void)5716662dc4SJiafei Pan long long init_ddr(void)
5816662dc4SJiafei Pan {
5916662dc4SJiafei Pan int spd_addr[] = { NXP_SPD_EEPROM0 };
6016662dc4SJiafei Pan struct ddr_info info;
6116662dc4SJiafei Pan struct sysinfo sys;
6216662dc4SJiafei Pan long long dram_size;
6316662dc4SJiafei Pan
6416662dc4SJiafei Pan zeromem(&sys, sizeof(sys));
6516662dc4SJiafei Pan if (get_clocks(&sys)) {
6616662dc4SJiafei Pan ERROR("System clocks are not set\n");
6716662dc4SJiafei Pan assert(0);
6816662dc4SJiafei Pan }
6916662dc4SJiafei Pan debug("platform clock %lu\n", sys.freq_platform);
7016662dc4SJiafei Pan debug("DDR PLL1 %lu\n", sys.freq_ddr_pll0);
7116662dc4SJiafei Pan debug("DDR PLL2 %lu\n", sys.freq_ddr_pll1);
7216662dc4SJiafei Pan
7316662dc4SJiafei Pan zeromem(&info, sizeof(struct ddr_info));
7416662dc4SJiafei Pan info.num_ctlrs = 1;
7516662dc4SJiafei Pan info.dimm_on_ctlr = 1;
7616662dc4SJiafei Pan info.clk = get_ddr_freq(&sys, 0);
7716662dc4SJiafei Pan info.spd_addr = spd_addr;
7816662dc4SJiafei Pan info.ddr[0] = (void *)NXP_DDR_ADDR;
7916662dc4SJiafei Pan
8016662dc4SJiafei Pan dram_size = dram_init(&info);
8116662dc4SJiafei Pan
8216662dc4SJiafei Pan if (dram_size < 0) {
8316662dc4SJiafei Pan ERROR("DDR init failed.\n");
8416662dc4SJiafei Pan }
8516662dc4SJiafei Pan
8616662dc4SJiafei Pan #ifdef ERRATA_SOC_A008850
8716662dc4SJiafei Pan erratum_a008850_post();
8816662dc4SJiafei Pan #endif
8916662dc4SJiafei Pan
9016662dc4SJiafei Pan return dram_size;
9116662dc4SJiafei Pan }
92