17d436078SPrabhakar Kushwaha /*
2c60dee03SYork Sun * Copyright 2013-2014 Freescale Semiconductor, Inc.
37d436078SPrabhakar Kushwaha *
47d436078SPrabhakar Kushwaha * SPDX-License-Identifier: GPL-2.0+
57d436078SPrabhakar Kushwaha */
67d436078SPrabhakar Kushwaha
77d436078SPrabhakar Kushwaha #include <common.h>
87d436078SPrabhakar Kushwaha #include <i2c.h>
97d436078SPrabhakar Kushwaha #include <hwconfig.h>
107d436078SPrabhakar Kushwaha #include <asm/mmu.h>
115614e71bSYork Sun #include <fsl_ddr_sdram.h>
125614e71bSYork Sun #include <fsl_ddr_dimm_params.h>
137d436078SPrabhakar Kushwaha #include <asm/fsl_law.h>
147d0e97a2Stang yuantian #include <asm/mpc85xx_gpio.h>
157d436078SPrabhakar Kushwaha #include "ddr.h"
167d436078SPrabhakar Kushwaha
177d436078SPrabhakar Kushwaha DECLARE_GLOBAL_DATA_PTR;
187d436078SPrabhakar Kushwaha
fsl_ddr_board_options(memctl_options_t * popts,dimm_params_t * pdimm,unsigned int ctrl_num)197d436078SPrabhakar Kushwaha void fsl_ddr_board_options(memctl_options_t *popts,
207d436078SPrabhakar Kushwaha dimm_params_t *pdimm,
217d436078SPrabhakar Kushwaha unsigned int ctrl_num)
227d436078SPrabhakar Kushwaha {
237d436078SPrabhakar Kushwaha const struct board_specific_parameters *pbsp, *pbsp_highest = NULL;
247d436078SPrabhakar Kushwaha ulong ddr_freq;
257d436078SPrabhakar Kushwaha
267d436078SPrabhakar Kushwaha if (ctrl_num > 2) {
277d436078SPrabhakar Kushwaha printf("Not supported controller number %d\n", ctrl_num);
287d436078SPrabhakar Kushwaha return;
297d436078SPrabhakar Kushwaha }
307d436078SPrabhakar Kushwaha if (!pdimm->n_ranks)
317d436078SPrabhakar Kushwaha return;
327d436078SPrabhakar Kushwaha
337d436078SPrabhakar Kushwaha pbsp = udimms[0];
347d436078SPrabhakar Kushwaha
357d436078SPrabhakar Kushwaha /* Get clk_adjust, cpo, write_data_delay,2t, according to the board ddr
367d436078SPrabhakar Kushwaha * freqency and n_banks specified in board_specific_parameters table.
377d436078SPrabhakar Kushwaha */
387d436078SPrabhakar Kushwaha ddr_freq = get_ddr_freq(0) / 1000000;
397d436078SPrabhakar Kushwaha while (pbsp->datarate_mhz_high) {
407d436078SPrabhakar Kushwaha if (pbsp->n_ranks == pdimm->n_ranks &&
417d436078SPrabhakar Kushwaha (pdimm->rank_density >> 30) >= pbsp->rank_gb) {
427d436078SPrabhakar Kushwaha if (ddr_freq <= pbsp->datarate_mhz_high) {
437d436078SPrabhakar Kushwaha popts->clk_adjust = pbsp->clk_adjust;
447d436078SPrabhakar Kushwaha popts->wrlvl_start = pbsp->wrlvl_start;
457d436078SPrabhakar Kushwaha popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
467d436078SPrabhakar Kushwaha popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
477d436078SPrabhakar Kushwaha goto found;
487d436078SPrabhakar Kushwaha }
497d436078SPrabhakar Kushwaha pbsp_highest = pbsp;
507d436078SPrabhakar Kushwaha }
517d436078SPrabhakar Kushwaha pbsp++;
527d436078SPrabhakar Kushwaha }
537d436078SPrabhakar Kushwaha
547d436078SPrabhakar Kushwaha if (pbsp_highest) {
557d436078SPrabhakar Kushwaha printf("Error: board specific timing not found\n");
567d436078SPrabhakar Kushwaha printf("for data rate %lu MT/s\n", ddr_freq);
577d436078SPrabhakar Kushwaha printf("Trying to use the highest speed (%u) parameters\n",
587d436078SPrabhakar Kushwaha pbsp_highest->datarate_mhz_high);
597d436078SPrabhakar Kushwaha popts->clk_adjust = pbsp_highest->clk_adjust;
607d436078SPrabhakar Kushwaha popts->wrlvl_start = pbsp_highest->wrlvl_start;
617d436078SPrabhakar Kushwaha popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2;
627d436078SPrabhakar Kushwaha popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3;
637d436078SPrabhakar Kushwaha } else {
647d436078SPrabhakar Kushwaha panic("DIMM is not supported by this board");
657d436078SPrabhakar Kushwaha }
667d436078SPrabhakar Kushwaha found:
677d436078SPrabhakar Kushwaha debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n"
687d436078SPrabhakar Kushwaha "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, "
697d436078SPrabhakar Kushwaha "wrlvl_ctrl_3 0x%x\n",
707d436078SPrabhakar Kushwaha pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb,
717d436078SPrabhakar Kushwaha pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2,
727d436078SPrabhakar Kushwaha pbsp->wrlvl_ctl_3);
737d436078SPrabhakar Kushwaha
747d436078SPrabhakar Kushwaha /*
757d436078SPrabhakar Kushwaha * Factors to consider for half-strength driver enable:
767d436078SPrabhakar Kushwaha * - number of DIMMs installed
777d436078SPrabhakar Kushwaha */
78c60dee03SYork Sun popts->half_strength_driver_enable = 1;
797d436078SPrabhakar Kushwaha /*
807d436078SPrabhakar Kushwaha * Write leveling override
817d436078SPrabhakar Kushwaha */
827d436078SPrabhakar Kushwaha popts->wrlvl_override = 1;
837d436078SPrabhakar Kushwaha popts->wrlvl_sample = 0xf;
847d436078SPrabhakar Kushwaha
857d436078SPrabhakar Kushwaha /*
867d436078SPrabhakar Kushwaha * rtt and rtt_wr override
877d436078SPrabhakar Kushwaha */
887d436078SPrabhakar Kushwaha popts->rtt_override = 0;
897d436078SPrabhakar Kushwaha
907d436078SPrabhakar Kushwaha /* Enable ZQ calibration */
917d436078SPrabhakar Kushwaha popts->zq_en = 1;
927d436078SPrabhakar Kushwaha
937d436078SPrabhakar Kushwaha /* DHC_EN =1, ODT = 75 Ohm */
94c60dee03SYork Sun #ifdef CONFIG_SYS_FSL_DDR4
95c60dee03SYork Sun popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm);
96c60dee03SYork Sun popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) |
97c60dee03SYork Sun DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */
9890101386SShengzhou Liu
9990101386SShengzhou Liu /* optimize cpo for erratum A-009942 */
10090101386SShengzhou Liu popts->cpo_sample = 0x69;
101c60dee03SYork Sun #else
1027d436078SPrabhakar Kushwaha popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm);
1037d436078SPrabhakar Kushwaha popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm);
104c60dee03SYork Sun #endif
1057d436078SPrabhakar Kushwaha }
1067d436078SPrabhakar Kushwaha
1077d0e97a2Stang yuantian #if defined(CONFIG_DEEP_SLEEP)
board_mem_sleep_setup(void)1087d0e97a2Stang yuantian void board_mem_sleep_setup(void)
1097d0e97a2Stang yuantian {
1107d0e97a2Stang yuantian void __iomem *qixis_base = (void *)QIXIS_BASE;
1117d0e97a2Stang yuantian
1127d0e97a2Stang yuantian /* does not provide HW signals for power management */
1137d0e97a2Stang yuantian clrbits_8(qixis_base + 0x21, 0x2);
1147d0e97a2Stang yuantian /* Disable MCKE isolation */
1157d0e97a2Stang yuantian gpio_set_value(2, 0);
1167d0e97a2Stang yuantian udelay(1);
1177d0e97a2Stang yuantian }
1187d0e97a2Stang yuantian #endif
1197d0e97a2Stang yuantian
dram_init(void)120*f1683aa7SSimon Glass int dram_init(void)
1217d436078SPrabhakar Kushwaha {
1227d436078SPrabhakar Kushwaha phys_size_t dram_size;
1237d436078SPrabhakar Kushwaha
1247d436078SPrabhakar Kushwaha puts("Initializing....using SPD\n");
1257d436078SPrabhakar Kushwaha
1267d436078SPrabhakar Kushwaha dram_size = fsl_ddr_sdram();
1277d436078SPrabhakar Kushwaha
1287d436078SPrabhakar Kushwaha dram_size = setup_ddr_tlbs(dram_size / 0x100000);
1297d436078SPrabhakar Kushwaha dram_size *= 0x100000;
1307d436078SPrabhakar Kushwaha
1317d436078SPrabhakar Kushwaha puts(" DDR: ");
1327d0e97a2Stang yuantian
1337d0e97a2Stang yuantian #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
1347d0e97a2Stang yuantian fsl_dp_resume();
1357d0e97a2Stang yuantian #endif
1367d0e97a2Stang yuantian
137088454cdSSimon Glass gd->ram_size = dram_size;
138088454cdSSimon Glass
139088454cdSSimon Glass return 0;
1407d436078SPrabhakar Kushwaha }
141