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