148c6f328SShengzhou Liu /*
248c6f328SShengzhou Liu * Copyright 2014 Freescale Semiconductor, Inc.
348c6f328SShengzhou Liu *
448c6f328SShengzhou Liu * SPDX-License-Identifier: GPL-2.0+
548c6f328SShengzhou Liu */
648c6f328SShengzhou Liu
748c6f328SShengzhou Liu #include <common.h>
848c6f328SShengzhou Liu #include <i2c.h>
948c6f328SShengzhou Liu #include <hwconfig.h>
1048c6f328SShengzhou Liu #include <asm/mmu.h>
1148c6f328SShengzhou Liu #include <fsl_ddr_sdram.h>
1248c6f328SShengzhou Liu #include <fsl_ddr_dimm_params.h>
1348c6f328SShengzhou Liu #include <asm/fsl_law.h>
14f49b8c1bStang yuantian #include <asm/mpc85xx_gpio.h>
1548c6f328SShengzhou Liu
1648c6f328SShengzhou Liu DECLARE_GLOBAL_DATA_PTR;
1748c6f328SShengzhou Liu
1848c6f328SShengzhou Liu struct board_specific_parameters {
1948c6f328SShengzhou Liu u32 n_ranks;
2048c6f328SShengzhou Liu u32 datarate_mhz_high;
2148c6f328SShengzhou Liu u32 rank_gb;
2248c6f328SShengzhou Liu u32 clk_adjust;
2348c6f328SShengzhou Liu u32 wrlvl_start;
2448c6f328SShengzhou Liu u32 wrlvl_ctl_2;
2548c6f328SShengzhou Liu u32 wrlvl_ctl_3;
2648c6f328SShengzhou Liu };
2748c6f328SShengzhou Liu
2848c6f328SShengzhou Liu /*
2948c6f328SShengzhou Liu * datarate_mhz_high values need to be in ascending order
3048c6f328SShengzhou Liu */
3148c6f328SShengzhou Liu static const struct board_specific_parameters udimm0[] = {
3248c6f328SShengzhou Liu /*
3348c6f328SShengzhou Liu * memory controller 0
3448c6f328SShengzhou Liu * num| hi| rank| clk| wrlvl | wrlvl | wrlvl |
3548c6f328SShengzhou Liu * ranks| mhz| GB |adjst| start | ctl2 | ctl3 |
3648c6f328SShengzhou Liu */
37e04f9d0cSShengzhou Liu {2, 833, 0, 8, 6, 0x06060607, 0x08080807,},
38e04f9d0cSShengzhou Liu {2, 1350, 0, 8, 7, 0x0708080A, 0x0A0B0C09,},
39e04f9d0cSShengzhou Liu {2, 1666, 0, 8, 7, 0x0808090B, 0x0C0D0E0A,},
40e04f9d0cSShengzhou Liu {1, 833, 0, 8, 6, 0x06060607, 0x08080807,},
41e04f9d0cSShengzhou Liu {1, 1350, 0, 8, 7, 0x0708080A, 0x0A0B0C09,},
42e04f9d0cSShengzhou Liu {1, 1666, 0, 8, 7, 0x0808090B, 0x0C0D0E0A,},
4348c6f328SShengzhou Liu {}
4448c6f328SShengzhou Liu };
4548c6f328SShengzhou Liu
4648c6f328SShengzhou Liu static const struct board_specific_parameters *udimms[] = {
4748c6f328SShengzhou Liu udimm0,
4848c6f328SShengzhou Liu };
4948c6f328SShengzhou Liu
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)5048c6f328SShengzhou Liu void fsl_ddr_board_options(memctl_options_t *popts,
5148c6f328SShengzhou Liu dimm_params_t *pdimm,
5248c6f328SShengzhou Liu unsigned int ctrl_num)
5348c6f328SShengzhou Liu {
5448c6f328SShengzhou Liu const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
5548c6f328SShengzhou Liu ulong ddr_freq;
5648c6f328SShengzhou Liu struct cpu_type *cpu = gd->arch.cpu;
5748c6f328SShengzhou Liu
5848c6f328SShengzhou Liu if (ctrl_num > 1) {
5948c6f328SShengzhou Liu printf("Not supported controller number %d\n", ctrl_num);
6048c6f328SShengzhou Liu return;
6148c6f328SShengzhou Liu }
6248c6f328SShengzhou Liu if (!pdimm->n_ranks)
6348c6f328SShengzhou Liu return;
6448c6f328SShengzhou Liu
6548c6f328SShengzhou Liu pbsp = udimms[0];
6648c6f328SShengzhou Liu
6748c6f328SShengzhou Liu /* Get clk_adjust according to the board ddr freqency and n_banks
6848c6f328SShengzhou Liu * specified in board_specific_parameters table.
6948c6f328SShengzhou Liu */
7048c6f328SShengzhou Liu ddr_freq = get_ddr_freq(0) / 1000000;
7148c6f328SShengzhou Liu while (pbsp->datarate_mhz_high) {
7248c6f328SShengzhou Liu if (pbsp->n_ranks == pdimm->n_ranks &&
7348c6f328SShengzhou Liu (pdimm->rank_density >> 30) >= pbsp->rank_gb) {
7448c6f328SShengzhou Liu if (ddr_freq <= pbsp->datarate_mhz_high) {
7548c6f328SShengzhou Liu popts->clk_adjust = pbsp->clk_adjust;
7648c6f328SShengzhou Liu popts->wrlvl_start = pbsp->wrlvl_start;
7748c6f328SShengzhou Liu popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
7848c6f328SShengzhou Liu popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
7948c6f328SShengzhou Liu goto found;
8048c6f328SShengzhou Liu }
8148c6f328SShengzhou Liu pbsp_highest = pbsp;
8248c6f328SShengzhou Liu }
8348c6f328SShengzhou Liu pbsp++;
8448c6f328SShengzhou Liu }
8548c6f328SShengzhou Liu
8648c6f328SShengzhou Liu if (pbsp_highest) {
8748c6f328SShengzhou Liu printf("Error: board specific timing not found\n");
8848c6f328SShengzhou Liu printf("for data rate %lu MT/s\n", ddr_freq);
8948c6f328SShengzhou Liu printf("Trying to use the highest speed (%u) parameters\n",
9048c6f328SShengzhou Liu pbsp_highest->datarate_mhz_high);
9148c6f328SShengzhou Liu popts->clk_adjust = pbsp_highest->clk_adjust;
9248c6f328SShengzhou Liu popts->wrlvl_start = pbsp_highest->wrlvl_start;
9348c6f328SShengzhou Liu popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
9448c6f328SShengzhou Liu popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
9548c6f328SShengzhou Liu } else {
9648c6f328SShengzhou Liu panic("DIMM is not supported by this board");
9748c6f328SShengzhou Liu }
9848c6f328SShengzhou Liu found:
9948c6f328SShengzhou Liu debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n",
10048c6f328SShengzhou Liu pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb);
10148c6f328SShengzhou Liu debug("\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, ",
10248c6f328SShengzhou Liu pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2);
10348c6f328SShengzhou Liu debug("wrlvl_ctrl_3 0x%x\n", pbsp->wrlvl_ctl_3);
10448c6f328SShengzhou Liu
10548c6f328SShengzhou Liu /*
10648c6f328SShengzhou Liu * Factors to consider for half-strength driver enable:
10748c6f328SShengzhou Liu * - number of DIMMs installed
10848c6f328SShengzhou Liu */
10948c6f328SShengzhou Liu popts->half_strength_driver_enable = 0;
11048c6f328SShengzhou Liu /*
11148c6f328SShengzhou Liu * Write leveling override
11248c6f328SShengzhou Liu */
11348c6f328SShengzhou Liu popts->wrlvl_override = 1;
11448c6f328SShengzhou Liu popts->wrlvl_sample = 0xf;
11548c6f328SShengzhou Liu
11648c6f328SShengzhou Liu /*
11748c6f328SShengzhou Liu * rtt and rtt_wr override
11848c6f328SShengzhou Liu */
11948c6f328SShengzhou Liu popts->rtt_override = 0;
12048c6f328SShengzhou Liu
12148c6f328SShengzhou Liu /* Enable ZQ calibration */
12248c6f328SShengzhou Liu popts->zq_en = 1;
12348c6f328SShengzhou Liu
12448c6f328SShengzhou Liu /* DHC_EN =1, ODT = 75 Ohm */
12548c6f328SShengzhou Liu popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_OFF);
12648c6f328SShengzhou Liu popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_OFF);
12748c6f328SShengzhou Liu
12848c6f328SShengzhou Liu /* T1023 supports max DDR bus 32bit width, T1024 supports DDR 64bit,
12948c6f328SShengzhou Liu * force DDR bus width to 32bit for T1023
13048c6f328SShengzhou Liu */
13148c6f328SShengzhou Liu if (cpu->soc_ver == SVR_T1023)
13248c6f328SShengzhou Liu popts->data_bus_width = DDR_DATA_BUS_WIDTH_32;
13348c6f328SShengzhou Liu
13448c6f328SShengzhou Liu #ifdef CONFIG_FORCE_DDR_DATA_BUS_WIDTH_32
13548c6f328SShengzhou Liu /* for DDR bus 32bit test on T1024 */
13648c6f328SShengzhou Liu popts->data_bus_width = DDR_DATA_BUS_WIDTH_32;
13748c6f328SShengzhou Liu #endif
138e8a7f1c3SShengzhou Liu
1399082405dSYork Sun #ifdef CONFIG_TARGET_T1023RDB
140e8a7f1c3SShengzhou Liu popts->wrlvl_ctl_2 = 0x07070606;
141e8a7f1c3SShengzhou Liu popts->half_strength_driver_enable = 1;
14290101386SShengzhou Liu popts->cpo_sample = 0x43;
143960286b6SYork Sun #elif defined(CONFIG_TARGET_T1024RDB)
14490101386SShengzhou Liu /* optimize cpo for erratum A-009942 */
14590101386SShengzhou Liu popts->cpo_sample = 0x52;
146e8a7f1c3SShengzhou Liu #endif
14748c6f328SShengzhou Liu }
14848c6f328SShengzhou Liu
149e8a7f1c3SShengzhou Liu #ifdef CONFIG_SYS_DDR_RAW_TIMING
150e8a7f1c3SShengzhou Liu /* 2GB discrete DDR4 MT40A512M8HX on T1023RDB */
151e8a7f1c3SShengzhou Liu dimm_params_t ddr_raw_timing = {
152e8a7f1c3SShengzhou Liu .n_ranks = 1,
153e8a7f1c3SShengzhou Liu .rank_density = 0x80000000,
154e8a7f1c3SShengzhou Liu .capacity = 0x80000000,
155e8a7f1c3SShengzhou Liu .primary_sdram_width = 32,
156e8a7f1c3SShengzhou Liu .ec_sdram_width = 8,
157e8a7f1c3SShengzhou Liu .registered_dimm = 0,
158e8a7f1c3SShengzhou Liu .mirrored_dimm = 0,
159e8a7f1c3SShengzhou Liu .n_row_addr = 15,
160e8a7f1c3SShengzhou Liu .n_col_addr = 10,
161e8a7f1c3SShengzhou Liu .bank_addr_bits = 2,
162e8a7f1c3SShengzhou Liu .bank_group_bits = 2,
163e8a7f1c3SShengzhou Liu .edc_config = 0,
164e8a7f1c3SShengzhou Liu .burst_lengths_bitmask = 0x0c,
165e8a7f1c3SShengzhou Liu .tckmin_x_ps = 938,
166e8a7f1c3SShengzhou Liu .tckmax_ps = 1500,
167e8a7f1c3SShengzhou Liu .caslat_x = 0x000DFA00,
168e8a7f1c3SShengzhou Liu .taa_ps = 13500,
169e8a7f1c3SShengzhou Liu .trcd_ps = 13500,
170e8a7f1c3SShengzhou Liu .trp_ps = 13500,
171e8a7f1c3SShengzhou Liu .tras_ps = 33000,
172e8a7f1c3SShengzhou Liu .trc_ps = 46500,
173e8a7f1c3SShengzhou Liu .trfc1_ps = 260000,
174e8a7f1c3SShengzhou Liu .trfc2_ps = 160000,
175e8a7f1c3SShengzhou Liu .trfc4_ps = 110000,
176e8a7f1c3SShengzhou Liu .tfaw_ps = 25000,
177e8a7f1c3SShengzhou Liu .trrds_ps = 3700,
178e8a7f1c3SShengzhou Liu .trrdl_ps = 5300,
179e8a7f1c3SShengzhou Liu .tccdl_ps = 5355,
180e8a7f1c3SShengzhou Liu .refresh_rate_ps = 7800000,
181e8a7f1c3SShengzhou Liu .dq_mapping[0] = 0x0,
182e8a7f1c3SShengzhou Liu .dq_mapping[1] = 0x0,
183e8a7f1c3SShengzhou Liu .dq_mapping[2] = 0x0,
184e8a7f1c3SShengzhou Liu .dq_mapping[3] = 0x0,
185e8a7f1c3SShengzhou Liu .dq_mapping[4] = 0x0,
186e8a7f1c3SShengzhou Liu .dq_mapping[5] = 0x0,
187e8a7f1c3SShengzhou Liu .dq_mapping[6] = 0x0,
188e8a7f1c3SShengzhou Liu .dq_mapping[7] = 0x0,
189e8a7f1c3SShengzhou Liu .dq_mapping[8] = 0x0,
190e8a7f1c3SShengzhou Liu .dq_mapping[9] = 0x0,
191e8a7f1c3SShengzhou Liu .dq_mapping[10] = 0x0,
192e8a7f1c3SShengzhou Liu .dq_mapping[11] = 0x0,
193e8a7f1c3SShengzhou Liu .dq_mapping[12] = 0x0,
194e8a7f1c3SShengzhou Liu .dq_mapping[13] = 0x0,
195e8a7f1c3SShengzhou Liu .dq_mapping[14] = 0x0,
196e8a7f1c3SShengzhou Liu .dq_mapping[15] = 0x0,
197e8a7f1c3SShengzhou Liu .dq_mapping[16] = 0x0,
198e8a7f1c3SShengzhou Liu .dq_mapping[17] = 0x0,
199e8a7f1c3SShengzhou Liu .dq_mapping_ors = 1,
200e8a7f1c3SShengzhou Liu };
201e8a7f1c3SShengzhou Liu
fsl_ddr_get_dimm_params(dimm_params_t * pdimm,unsigned int controller_number,unsigned int dimm_number)202e8a7f1c3SShengzhou Liu int fsl_ddr_get_dimm_params(dimm_params_t *pdimm,
203e8a7f1c3SShengzhou Liu unsigned int controller_number,
204e8a7f1c3SShengzhou Liu unsigned int dimm_number)
205e8a7f1c3SShengzhou Liu {
206e8a7f1c3SShengzhou Liu const char dimm_model[] = "Fixed DDR4 on board";
207e8a7f1c3SShengzhou Liu
208e8a7f1c3SShengzhou Liu if (((controller_number == 0) && (dimm_number == 0)) ||
209e8a7f1c3SShengzhou Liu ((controller_number == 1) && (dimm_number == 0))) {
210e8a7f1c3SShengzhou Liu memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t));
211e8a7f1c3SShengzhou Liu memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
212e8a7f1c3SShengzhou Liu memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1);
213e8a7f1c3SShengzhou Liu }
214e8a7f1c3SShengzhou Liu
215e8a7f1c3SShengzhou Liu return 0;
216e8a7f1c3SShengzhou Liu }
217e8a7f1c3SShengzhou Liu #endif
218e8a7f1c3SShengzhou Liu
219f49b8c1bStang yuantian #if defined(CONFIG_DEEP_SLEEP)
board_mem_sleep_setup(void)220f49b8c1bStang yuantian void board_mem_sleep_setup(void)
221f49b8c1bStang yuantian {
222f49b8c1bStang yuantian void __iomem *cpld_base = (void *)CONFIG_SYS_CPLD_BASE;
223f49b8c1bStang yuantian
224f49b8c1bStang yuantian /* does not provide HW signals for power management */
225f49b8c1bStang yuantian clrbits_8(cpld_base + 0x17, 0x40);
226f49b8c1bStang yuantian /* Disable MCKE isolation */
227f49b8c1bStang yuantian gpio_set_value(2, 0);
228f49b8c1bStang yuantian udelay(1);
229f49b8c1bStang yuantian }
230f49b8c1bStang yuantian #endif
231f49b8c1bStang yuantian
dram_init(void)232*f1683aa7SSimon Glass int dram_init(void)
23348c6f328SShengzhou Liu {
23448c6f328SShengzhou Liu phys_size_t dram_size;
23548c6f328SShengzhou Liu
23648c6f328SShengzhou Liu #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
237e8a7f1c3SShengzhou Liu #ifndef CONFIG_SYS_DDR_RAW_TIMING
23848c6f328SShengzhou Liu puts("Initializing....using SPD\n");
239e8a7f1c3SShengzhou Liu #endif
24048c6f328SShengzhou Liu dram_size = fsl_ddr_sdram();
24148c6f328SShengzhou Liu #else
24248c6f328SShengzhou Liu /* DDR has been initialised by first stage boot loader */
24348c6f328SShengzhou Liu dram_size = fsl_ddr_sdram_size();
24448c6f328SShengzhou Liu #endif
24553499282SShengzhou Liu dram_size = setup_ddr_tlbs(dram_size / 0x100000);
24653499282SShengzhou Liu dram_size *= 0x100000;
247f49b8c1bStang yuantian
248f49b8c1bStang yuantian #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
249f49b8c1bStang yuantian fsl_dp_resume();
250f49b8c1bStang yuantian #endif
251f49b8c1bStang yuantian
252088454cdSSimon Glass gd->ram_size = dram_size;
253088454cdSSimon Glass
254088454cdSSimon Glass return 0;
25548c6f328SShengzhou Liu }
256