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