183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
202b5d2edSShaohui Xie /*
302b5d2edSShaohui Xie * Copyright 2015 Freescale Semiconductor, Inc.
402b5d2edSShaohui Xie */
502b5d2edSShaohui Xie
602b5d2edSShaohui Xie #include <common.h>
702b5d2edSShaohui Xie #include <fsl_ddr_sdram.h>
802b5d2edSShaohui Xie #include <fsl_ddr_dimm_params.h>
902b5d2edSShaohui Xie #ifdef CONFIG_FSL_DEEP_SLEEP
1002b5d2edSShaohui Xie #include <fsl_sleep.h>
1102b5d2edSShaohui Xie #endif
126e2941d7SSimon Glass #include <asm/arch/clock.h>
1302b5d2edSShaohui Xie #include "ddr.h"
1402b5d2edSShaohui Xie
1502b5d2edSShaohui Xie DECLARE_GLOBAL_DATA_PTR;
1602b5d2edSShaohui Xie
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)1702b5d2edSShaohui Xie void fsl_ddr_board_options(memctl_options_t *popts,
1802b5d2edSShaohui Xie dimm_params_t *pdimm,
1902b5d2edSShaohui Xie unsigned int ctrl_num)
2002b5d2edSShaohui Xie {
2102b5d2edSShaohui Xie const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
2202b5d2edSShaohui Xie ulong ddr_freq;
2302b5d2edSShaohui Xie
2402b5d2edSShaohui Xie if (ctrl_num > 3) {
2502b5d2edSShaohui Xie printf("Not supported controller number %d\n", ctrl_num);
2602b5d2edSShaohui Xie return;
2702b5d2edSShaohui Xie }
2802b5d2edSShaohui Xie if (!pdimm->n_ranks)
2902b5d2edSShaohui Xie return;
3002b5d2edSShaohui Xie
3102b5d2edSShaohui Xie pbsp = udimms[0];
3202b5d2edSShaohui Xie
3302b5d2edSShaohui Xie /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
3402b5d2edSShaohui Xie * freqency and n_banks specified in board_specific_parameters table.
3502b5d2edSShaohui Xie */
3602b5d2edSShaohui Xie ddr_freq = get_ddr_freq(0) / 1000000;
3702b5d2edSShaohui Xie while (pbsp->datarate_mhz_high) {
3802b5d2edSShaohui Xie if (pbsp->n_ranks == pdimm->n_ranks) {
3902b5d2edSShaohui Xie if (ddr_freq <= pbsp->datarate_mhz_high) {
4002b5d2edSShaohui Xie popts->clk_adjust = pbsp->clk_adjust;
4102b5d2edSShaohui Xie popts->wrlvl_start = pbsp->wrlvl_start;
4202b5d2edSShaohui Xie popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
4302b5d2edSShaohui Xie popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
4402b5d2edSShaohui Xie popts->cpo_override = pbsp->cpo_override;
4502b5d2edSShaohui Xie popts->write_data_delay =
4602b5d2edSShaohui Xie pbsp->write_data_delay;
4702b5d2edSShaohui Xie goto found;
4802b5d2edSShaohui Xie }
4902b5d2edSShaohui Xie pbsp_highest = pbsp;
5002b5d2edSShaohui Xie }
5102b5d2edSShaohui Xie pbsp++;
5202b5d2edSShaohui Xie }
5302b5d2edSShaohui Xie
5402b5d2edSShaohui Xie if (pbsp_highest) {
5502b5d2edSShaohui Xie printf("Error: board specific timing not found for %lu MT/s\n",
5602b5d2edSShaohui Xie ddr_freq);
5702b5d2edSShaohui Xie printf("Trying to use the highest speed (%u) parameters\n",
5802b5d2edSShaohui Xie pbsp_highest->datarate_mhz_high);
5902b5d2edSShaohui Xie popts->clk_adjust = pbsp_highest->clk_adjust;
6002b5d2edSShaohui Xie popts->wrlvl_start = pbsp_highest->wrlvl_start;
6102b5d2edSShaohui Xie popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
6202b5d2edSShaohui Xie popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
6302b5d2edSShaohui Xie } else {
6402b5d2edSShaohui Xie panic("DIMM is not supported by this board");
6502b5d2edSShaohui Xie }
6602b5d2edSShaohui Xie found:
6702b5d2edSShaohui Xie debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n",
6802b5d2edSShaohui Xie pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb);
6902b5d2edSShaohui Xie
7002b5d2edSShaohui Xie /* force DDR bus width to 32 bits */
7102b5d2edSShaohui Xie popts->data_bus_width = 1;
7202b5d2edSShaohui Xie popts->otf_burst_chop_en = 0;
7302b5d2edSShaohui Xie popts->burst_length = DDR_BL8;
7402b5d2edSShaohui Xie popts->bstopre = 0; /* enable auto precharge */
7502b5d2edSShaohui Xie
7602b5d2edSShaohui Xie /*
7702b5d2edSShaohui Xie * Factors to consider for half-strength driver enable:
7802b5d2edSShaohui Xie * - number of DIMMs installed
7902b5d2edSShaohui Xie */
8002b5d2edSShaohui Xie popts->half_strength_driver_enable = 1;
8102b5d2edSShaohui Xie /*
8202b5d2edSShaohui Xie * Write leveling override
8302b5d2edSShaohui Xie */
8402b5d2edSShaohui Xie popts->wrlvl_override = 1;
8502b5d2edSShaohui Xie popts->wrlvl_sample = 0xf;
8602b5d2edSShaohui Xie
8702b5d2edSShaohui Xie /*
8802b5d2edSShaohui Xie * Rtt and Rtt_WR override
8902b5d2edSShaohui Xie */
9002b5d2edSShaohui Xie popts->rtt_override = 0;
9102b5d2edSShaohui Xie
9202b5d2edSShaohui Xie /* Enable ZQ calibration */
9302b5d2edSShaohui Xie popts->zq_en = 1;
9402b5d2edSShaohui Xie
9502b5d2edSShaohui Xie #ifdef CONFIG_SYS_FSL_DDR4
9602b5d2edSShaohui Xie popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
9702b5d2edSShaohui Xie popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
9802b5d2edSShaohui Xie DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
9990101386SShengzhou Liu
10090101386SShengzhou Liu /* optimize cpo for erratum A-009942 */
10190101386SShengzhou Liu popts->cpo_sample = 0x59;
10202b5d2edSShaohui Xie #else
10302b5d2edSShaohui Xie popts->cswl_override = DDR_CSWL_CS0;
10402b5d2edSShaohui Xie
10502b5d2edSShaohui Xie /* DHC_EN =1, ODT = 75 Ohm */
10602b5d2edSShaohui Xie popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
10702b5d2edSShaohui Xie popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
10802b5d2edSShaohui Xie #endif
10902b5d2edSShaohui Xie }
11002b5d2edSShaohui Xie
111*8aa6b17aSRajesh Bhagat #ifdef CONFIG_TFABOOT
fsl_initdram(void)112*8aa6b17aSRajesh Bhagat int fsl_initdram(void)
113*8aa6b17aSRajesh Bhagat {
114*8aa6b17aSRajesh Bhagat gd->ram_size = tfa_get_dram_size();
115*8aa6b17aSRajesh Bhagat if (!gd->ram_size)
116*8aa6b17aSRajesh Bhagat gd->ram_size = fsl_ddr_sdram_size();
117*8aa6b17aSRajesh Bhagat
118*8aa6b17aSRajesh Bhagat return 0;
119*8aa6b17aSRajesh Bhagat }
120*8aa6b17aSRajesh Bhagat #else
fsl_initdram(void)1213eace37eSSimon Glass int fsl_initdram(void)
12202b5d2edSShaohui Xie {
12302b5d2edSShaohui Xie phys_size_t dram_size;
12402b5d2edSShaohui Xie
12502b5d2edSShaohui Xie #if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
126fedebf0dSYork Sun gd->ram_size = fsl_ddr_sdram_size();
127fedebf0dSYork Sun
128fedebf0dSYork Sun return 0;
12902b5d2edSShaohui Xie #else
13002b5d2edSShaohui Xie puts("Initializing DDR....using SPD\n");
13102b5d2edSShaohui Xie
13202b5d2edSShaohui Xie dram_size = fsl_ddr_sdram();
13302b5d2edSShaohui Xie #endif
134074596c0SShengzhou Liu erratum_a008850_post();
13502b5d2edSShaohui Xie
13602b5d2edSShaohui Xie #ifdef CONFIG_FSL_DEEP_SLEEP
13702b5d2edSShaohui Xie fsl_dp_ddr_restore();
13802b5d2edSShaohui Xie #endif
13902b5d2edSShaohui Xie
140088454cdSSimon Glass gd->ram_size = dram_size;
141088454cdSSimon Glass
142088454cdSSimon Glass return 0;
14302b5d2edSShaohui Xie }
144*8aa6b17aSRajesh Bhagat #endif
145