144937214SPrabhakar Kushwaha /*
244937214SPrabhakar Kushwaha * Copyright 2015 Freescale Semiconductor, Inc.
344937214SPrabhakar Kushwaha *
444937214SPrabhakar Kushwaha * SPDX-License-Identifier: GPL-2.0+
544937214SPrabhakar Kushwaha */
644937214SPrabhakar Kushwaha
744937214SPrabhakar Kushwaha #include <common.h>
844937214SPrabhakar Kushwaha #include <fsl_ddr_sdram.h>
944937214SPrabhakar Kushwaha #include <fsl_ddr_dimm_params.h>
103c1d218aSYork Sun #include <asm/arch/soc.h>
11*6e2941d7SSimon Glass #include <asm/arch/clock.h>
1244937214SPrabhakar Kushwaha #include "ddr.h"
1344937214SPrabhakar Kushwaha
1444937214SPrabhakar Kushwaha DECLARE_GLOBAL_DATA_PTR;
1544937214SPrabhakar Kushwaha
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)1644937214SPrabhakar Kushwaha void fsl_ddr_board_options(memctl_options_t *popts,
1744937214SPrabhakar Kushwaha dimm_params_t *pdimm,
1844937214SPrabhakar Kushwaha unsigned int ctrl_num)
1944937214SPrabhakar Kushwaha {
2044937214SPrabhakar Kushwaha #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
2144937214SPrabhakar Kushwaha u8 dq_mapping_0, dq_mapping_2, dq_mapping_3;
2244937214SPrabhakar Kushwaha #endif
2344937214SPrabhakar Kushwaha const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
2444937214SPrabhakar Kushwaha ulong ddr_freq;
2544937214SPrabhakar Kushwaha int slot;
2644937214SPrabhakar Kushwaha
2744937214SPrabhakar Kushwaha if (ctrl_num > 2) {
2844937214SPrabhakar Kushwaha printf("Not supported controller number %d\n", ctrl_num);
2944937214SPrabhakar Kushwaha return;
3044937214SPrabhakar Kushwaha }
3144937214SPrabhakar Kushwaha
3244937214SPrabhakar Kushwaha for (slot = 0; slot < CONFIG_DIMM_SLOTS_PER_CTLR; slot++) {
3344937214SPrabhakar Kushwaha if (pdimm[slot].n_ranks)
3444937214SPrabhakar Kushwaha break;
3544937214SPrabhakar Kushwaha }
3644937214SPrabhakar Kushwaha
3744937214SPrabhakar Kushwaha if (slot >= CONFIG_DIMM_SLOTS_PER_CTLR)
3844937214SPrabhakar Kushwaha return;
3944937214SPrabhakar Kushwaha
4044937214SPrabhakar Kushwaha /*
4144937214SPrabhakar Kushwaha * we use identical timing for all slots. If needed, change the code
4244937214SPrabhakar Kushwaha * to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num];
4344937214SPrabhakar Kushwaha */
4444937214SPrabhakar Kushwaha if (popts->registered_dimm_en)
4544937214SPrabhakar Kushwaha pbsp = rdimms[ctrl_num];
4644937214SPrabhakar Kushwaha else
4744937214SPrabhakar Kushwaha pbsp = udimms[ctrl_num];
4844937214SPrabhakar Kushwaha
4944937214SPrabhakar Kushwaha
5044937214SPrabhakar Kushwaha /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr
5144937214SPrabhakar Kushwaha * freqency and n_banks specified in board_specific_parameters table.
5244937214SPrabhakar Kushwaha */
5344937214SPrabhakar Kushwaha ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
5444937214SPrabhakar Kushwaha while (pbsp->datarate_mhz_high) {
5544937214SPrabhakar Kushwaha if (pbsp->n_ranks == pdimm[slot].n_ranks &&
5644937214SPrabhakar Kushwaha (pdimm[slot].rank_density >> 30) >= pbsp->rank_gb) {
5744937214SPrabhakar Kushwaha if (ddr_freq <= pbsp->datarate_mhz_high) {
5844937214SPrabhakar Kushwaha popts->clk_adjust = pbsp->clk_adjust;
5944937214SPrabhakar Kushwaha popts->wrlvl_start = pbsp->wrlvl_start;
6044937214SPrabhakar Kushwaha popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
6144937214SPrabhakar Kushwaha popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
6244937214SPrabhakar Kushwaha goto found;
6344937214SPrabhakar Kushwaha }
6444937214SPrabhakar Kushwaha pbsp_highest = pbsp;
6544937214SPrabhakar Kushwaha }
6644937214SPrabhakar Kushwaha pbsp++;
6744937214SPrabhakar Kushwaha }
6844937214SPrabhakar Kushwaha
6944937214SPrabhakar Kushwaha if (pbsp_highest) {
7044937214SPrabhakar Kushwaha printf("Error: board specific timing not found for data rate %lu MT/s\n"
7144937214SPrabhakar Kushwaha "Trying to use the highest speed (%u) parameters\n",
7244937214SPrabhakar Kushwaha ddr_freq, pbsp_highest->datarate_mhz_high);
7344937214SPrabhakar Kushwaha popts->clk_adjust = pbsp_highest->clk_adjust;
7444937214SPrabhakar Kushwaha popts->wrlvl_start = pbsp_highest->wrlvl_start;
7544937214SPrabhakar Kushwaha popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
7644937214SPrabhakar Kushwaha popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
7744937214SPrabhakar Kushwaha } else {
7844937214SPrabhakar Kushwaha panic("DIMM is not supported by this board");
7944937214SPrabhakar Kushwaha }
8044937214SPrabhakar Kushwaha found:
8144937214SPrabhakar Kushwaha debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
8244937214SPrabhakar Kushwaha "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n",
8344937214SPrabhakar Kushwaha pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
8444937214SPrabhakar Kushwaha pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
8544937214SPrabhakar Kushwaha pbsp->wrlvl_ctl_3);
8644937214SPrabhakar Kushwaha #ifdef CONFIG_SYS_FSL_HAS_DP_DDR
8744937214SPrabhakar Kushwaha if (ctrl_num == CONFIG_DP_DDR_CTRL) {
8844937214SPrabhakar Kushwaha /* force DDR bus width to 32 bits */
8944937214SPrabhakar Kushwaha popts->data_bus_width = 1;
9044937214SPrabhakar Kushwaha popts->otf_burst_chop_en = 0;
9144937214SPrabhakar Kushwaha popts->burst_length = DDR_BL8;
9244937214SPrabhakar Kushwaha popts->bstopre = 0; /* enable auto precharge */
9344937214SPrabhakar Kushwaha /*
9444937214SPrabhakar Kushwaha * Layout optimization results byte mapping
9544937214SPrabhakar Kushwaha * Byte 0 -> Byte ECC
9644937214SPrabhakar Kushwaha * Byte 1 -> Byte 3
9744937214SPrabhakar Kushwaha * Byte 2 -> Byte 2
9844937214SPrabhakar Kushwaha * Byte 3 -> Byte 1
9944937214SPrabhakar Kushwaha * Byte ECC -> Byte 0
10044937214SPrabhakar Kushwaha */
10144937214SPrabhakar Kushwaha dq_mapping_0 = pdimm[slot].dq_mapping[0];
10244937214SPrabhakar Kushwaha dq_mapping_2 = pdimm[slot].dq_mapping[2];
10344937214SPrabhakar Kushwaha dq_mapping_3 = pdimm[slot].dq_mapping[3];
10444937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[0] = pdimm[slot].dq_mapping[8];
10544937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[1] = pdimm[slot].dq_mapping[9];
10644937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[2] = pdimm[slot].dq_mapping[6];
10744937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[3] = pdimm[slot].dq_mapping[7];
10844937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[6] = dq_mapping_2;
10944937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[7] = dq_mapping_3;
11044937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[8] = dq_mapping_0;
11144937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[9] = 0;
11244937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[10] = 0;
11344937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[11] = 0;
11444937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[12] = 0;
11544937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[13] = 0;
11644937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[14] = 0;
11744937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[15] = 0;
11844937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[16] = 0;
11944937214SPrabhakar Kushwaha pdimm[slot].dq_mapping[17] = 0;
12044937214SPrabhakar Kushwaha }
12144937214SPrabhakar Kushwaha #endif
12244937214SPrabhakar Kushwaha /* To work at higher than 1333MT/s */
12344937214SPrabhakar Kushwaha popts->half_strength_driver_enable = 0;
12444937214SPrabhakar Kushwaha /*
12544937214SPrabhakar Kushwaha * Write leveling override
12644937214SPrabhakar Kushwaha */
12744937214SPrabhakar Kushwaha popts->wrlvl_override = 1;
12844937214SPrabhakar Kushwaha popts->wrlvl_sample = 0x0; /* 32 clocks */
12944937214SPrabhakar Kushwaha
13044937214SPrabhakar Kushwaha /*
13144937214SPrabhakar Kushwaha * Rtt and Rtt_WR override
13244937214SPrabhakar Kushwaha */
13344937214SPrabhakar Kushwaha popts->rtt_override = 0;
13444937214SPrabhakar Kushwaha
13544937214SPrabhakar Kushwaha /* Enable ZQ calibration */
13644937214SPrabhakar Kushwaha popts->zq_en = 1;
13744937214SPrabhakar Kushwaha
13890101386SShengzhou Liu /* optimize cpo for erratum A-009942 */
13990101386SShengzhou Liu popts->cpo_sample = 0x6e;
14090101386SShengzhou Liu
14144937214SPrabhakar Kushwaha if (ddr_freq < 2350) {
1423901978dSYork Sun if (pdimm[0].n_ranks == 2 && pdimm[1].n_ranks == 2) {
1433901978dSYork Sun /* four chip-selects */
1443901978dSYork Sun popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
1453901978dSYork Sun DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
1463901978dSYork Sun popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm);
1473901978dSYork Sun popts->twot_en = 1; /* enable 2T timing */
1483901978dSYork Sun } else {
14944937214SPrabhakar Kushwaha popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
15044937214SPrabhakar Kushwaha DDR_CDR1_ODT(DDR_CDR_ODT_60ohm);
15144937214SPrabhakar Kushwaha popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) |
15244937214SPrabhakar Kushwaha DDR_CDR2_VREF_RANGE_2;
1533901978dSYork Sun }
15444937214SPrabhakar Kushwaha } else {
15544937214SPrabhakar Kushwaha popts->ddr_cdr1 = DDR_CDR1_DHC_EN |
15644937214SPrabhakar Kushwaha DDR_CDR1_ODT(DDR_CDR_ODT_100ohm);
15744937214SPrabhakar Kushwaha popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_100ohm) |
15844937214SPrabhakar Kushwaha DDR_CDR2_VREF_RANGE_2;
15944937214SPrabhakar Kushwaha }
16044937214SPrabhakar Kushwaha }
16144937214SPrabhakar Kushwaha
fsl_initdram(void)1623eace37eSSimon Glass int fsl_initdram(void)
16344937214SPrabhakar Kushwaha {
16444937214SPrabhakar Kushwaha #if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD)
165088454cdSSimon Glass gd->ram_size = fsl_ddr_sdram_size();
16644937214SPrabhakar Kushwaha #else
16744937214SPrabhakar Kushwaha puts("Initializing DDR....using SPD\n");
16844937214SPrabhakar Kushwaha
169088454cdSSimon Glass gd->ram_size = fsl_ddr_sdram();
17044937214SPrabhakar Kushwaha #endif
17144937214SPrabhakar Kushwaha
172088454cdSSimon Glass return 0;
17344937214SPrabhakar Kushwaha }
174