1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2062ef1a6SPriyanka Jain /*
3062ef1a6SPriyanka Jain * Copyright 2013 Freescale Semiconductor, Inc.
4062ef1a6SPriyanka Jain */
5062ef1a6SPriyanka Jain
6062ef1a6SPriyanka Jain #include <common.h>
7062ef1a6SPriyanka Jain #include <i2c.h>
8062ef1a6SPriyanka Jain #include <hwconfig.h>
9062ef1a6SPriyanka Jain #include <asm/mmu.h>
105614e71bSYork Sun #include <fsl_ddr_sdram.h>
115614e71bSYork Sun #include <fsl_ddr_dimm_params.h>
12062ef1a6SPriyanka Jain #include <asm/fsl_law.h>
1300233528STang Yuantian #include <asm/mpc85xx_gpio.h>
14062ef1a6SPriyanka Jain #include "ddr.h"
15062ef1a6SPriyanka Jain
16062ef1a6SPriyanka Jain DECLARE_GLOBAL_DATA_PTR;
17062ef1a6SPriyanka Jain
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)18062ef1a6SPriyanka Jain void fsl_ddr_board_options(memctl_options_t *popts,
19062ef1a6SPriyanka Jain dimm_params_t *pdimm,
20062ef1a6SPriyanka Jain unsigned int ctrl_num)
21062ef1a6SPriyanka Jain {
22062ef1a6SPriyanka Jain const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
23062ef1a6SPriyanka Jain ulong ddr_freq;
24062ef1a6SPriyanka Jain
25062ef1a6SPriyanka Jain if (ctrl_num > 1) {
26062ef1a6SPriyanka Jain printf("Not supported controller number %d\n", ctrl_num);
27062ef1a6SPriyanka Jain return;
28062ef1a6SPriyanka Jain }
29062ef1a6SPriyanka Jain if (!pdimm->n_ranks)
30062ef1a6SPriyanka Jain return;
31062ef1a6SPriyanka Jain
32062ef1a6SPriyanka Jain pbsp = udimms[0];
33062ef1a6SPriyanka Jain
3496ac18c9SPriyanka Jain /* Get clk_adjust according to the board ddr
35062ef1a6SPriyanka Jain * freqency and n_banks specified in board_specific_parameters table.
36062ef1a6SPriyanka Jain */
37062ef1a6SPriyanka Jain ddr_freq = get_ddr_freq(0) / 1000000;
38062ef1a6SPriyanka Jain while (pbsp->datarate_mhz_high) {
39062ef1a6SPriyanka Jain if (pbsp->n_ranks == pdimm->n_ranks &&
40062ef1a6SPriyanka Jain (pdimm->rank_density >> 30) >= pbsp->rank_gb) {
41062ef1a6SPriyanka Jain if (ddr_freq <= pbsp->datarate_mhz_high) {
42062ef1a6SPriyanka Jain popts->clk_adjust = pbsp->clk_adjust;
43062ef1a6SPriyanka Jain popts->wrlvl_start = pbsp->wrlvl_start;
44062ef1a6SPriyanka Jain popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
45062ef1a6SPriyanka Jain popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
46062ef1a6SPriyanka Jain goto found;
47062ef1a6SPriyanka Jain }
48062ef1a6SPriyanka Jain pbsp_highest = pbsp;
49062ef1a6SPriyanka Jain }
50062ef1a6SPriyanka Jain pbsp++;
51062ef1a6SPriyanka Jain }
52062ef1a6SPriyanka Jain
53062ef1a6SPriyanka Jain if (pbsp_highest) {
54062ef1a6SPriyanka Jain printf("Error: board specific timing not found\n");
55062ef1a6SPriyanka Jain printf("for data rate %lu MT/s\n", ddr_freq);
56062ef1a6SPriyanka Jain printf("Trying to use the highest speed (%u) parameters\n",
57062ef1a6SPriyanka Jain pbsp_highest->datarate_mhz_high);
58062ef1a6SPriyanka Jain popts->clk_adjust = pbsp_highest->clk_adjust;
59062ef1a6SPriyanka Jain popts->wrlvl_start = pbsp_highest->wrlvl_start;
60062ef1a6SPriyanka Jain popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
61062ef1a6SPriyanka Jain popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
62062ef1a6SPriyanka Jain } else {
63062ef1a6SPriyanka Jain panic("DIMM is not supported by this board");
64062ef1a6SPriyanka Jain }
65062ef1a6SPriyanka Jain found:
66062ef1a6SPriyanka Jain debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
67062ef1a6SPriyanka Jain "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, "
68062ef1a6SPriyanka Jain "wrlvl_ctrl_3 0x%x\n",
69062ef1a6SPriyanka Jain pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
70062ef1a6SPriyanka Jain pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
71062ef1a6SPriyanka Jain pbsp->wrlvl_ctl_3);
72062ef1a6SPriyanka Jain
73062ef1a6SPriyanka Jain /*
74062ef1a6SPriyanka Jain * Factors to consider for half-strength driver enable:
75062ef1a6SPriyanka Jain * - number of DIMMs installed
76062ef1a6SPriyanka Jain */
774b6067aeSPriyanka Jain #ifdef CONFIG_SYS_FSL_DDR4
784b6067aeSPriyanka Jain popts->half_strength_driver_enable = 1;
7990101386SShengzhou Liu /* optimize cpo for erratum A-009942 */
8090101386SShengzhou Liu popts->cpo_sample = 0x59;
814b6067aeSPriyanka Jain #else
82062ef1a6SPriyanka Jain popts->half_strength_driver_enable = 0;
834b6067aeSPriyanka Jain #endif
84062ef1a6SPriyanka Jain /*
85062ef1a6SPriyanka Jain * Write leveling override
86062ef1a6SPriyanka Jain */
87062ef1a6SPriyanka Jain popts->wrlvl_override = 1;
88062ef1a6SPriyanka Jain popts->wrlvl_sample = 0xf;
89062ef1a6SPriyanka Jain
90062ef1a6SPriyanka Jain /*
91062ef1a6SPriyanka Jain * rtt and rtt_wr override
92062ef1a6SPriyanka Jain */
93062ef1a6SPriyanka Jain popts->rtt_override = 0;
94062ef1a6SPriyanka Jain
95062ef1a6SPriyanka Jain /* Enable ZQ calibration */
96062ef1a6SPriyanka Jain popts->zq_en = 1;
97062ef1a6SPriyanka Jain
98062ef1a6SPriyanka Jain /* DHC_EN =1, ODT = 75 Ohm */
994b6067aeSPriyanka Jain #ifdef CONFIG_SYS_FSL_DDR4
1004b6067aeSPriyanka Jain popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_120OHM);
1014b6067aeSPriyanka Jain popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_120OHM) |
1024b6067aeSPriyanka Jain DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
1034b6067aeSPriyanka Jain #else
10492f7fed4SPriyanka Jain popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
10592f7fed4SPriyanka Jain popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
1064b6067aeSPriyanka Jain #endif
107062ef1a6SPriyanka Jain }
108062ef1a6SPriyanka Jain
10900233528STang Yuantian #if defined(CONFIG_DEEP_SLEEP)
board_mem_sleep_setup(void)11000233528STang Yuantian void board_mem_sleep_setup(void)
11100233528STang Yuantian {
11200233528STang Yuantian void __iomem *cpld_base = (void *)CONFIG_SYS_CPLD_BASE;
11300233528STang Yuantian
11400233528STang Yuantian /* does not provide HW signals for power management */
11500233528STang Yuantian clrbits_8(cpld_base + 0x17, 0x40);
11600233528STang Yuantian /* Disable MCKE isolation */
11700233528STang Yuantian gpio_set_value(2, 0);
11800233528STang Yuantian udelay(1);
11900233528STang Yuantian }
12000233528STang Yuantian #endif
12100233528STang Yuantian
dram_init(void)122f1683aa7SSimon Glass int dram_init(void)
123062ef1a6SPriyanka Jain {
124062ef1a6SPriyanka Jain phys_size_t dram_size;
125062ef1a6SPriyanka Jain
12618c01445SPrabhakar Kushwaha #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
127062ef1a6SPriyanka Jain puts("Initializing....using SPD\n");
128062ef1a6SPriyanka Jain dram_size = fsl_ddr_sdram();
12918c01445SPrabhakar Kushwaha #else
13018c01445SPrabhakar Kushwaha dram_size = fsl_ddr_sdram_size();
13118c01445SPrabhakar Kushwaha #endif
13253499282SShengzhou Liu dram_size = setup_ddr_tlbs(dram_size / 0x100000);
13353499282SShengzhou Liu dram_size *= 0x100000;
13400233528STang Yuantian
13500233528STang Yuantian #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
13600233528STang Yuantian fsl_dp_resume();
13700233528STang Yuantian #endif
13800233528STang Yuantian
139088454cdSSimon Glass gd->ram_size = dram_size;
140088454cdSSimon Glass
141088454cdSSimon Glass return 0;
142062ef1a6SPriyanka Jain }
143