1550e3dc0SWang Huan /* 2550e3dc0SWang Huan * Copyright 2014 Freescale Semiconductor, Inc. 3550e3dc0SWang Huan * 4550e3dc0SWang Huan * SPDX-License-Identifier: GPL-2.0+ 5550e3dc0SWang Huan */ 6550e3dc0SWang Huan 7550e3dc0SWang Huan #include <common.h> 8550e3dc0SWang Huan #include <fsl_ddr_sdram.h> 9550e3dc0SWang Huan #include <fsl_ddr_dimm_params.h> 10550e3dc0SWang Huan #include "ddr.h" 11550e3dc0SWang Huan 12550e3dc0SWang Huan DECLARE_GLOBAL_DATA_PTR; 13550e3dc0SWang Huan 14550e3dc0SWang Huan void fsl_ddr_board_options(memctl_options_t *popts, 15550e3dc0SWang Huan dimm_params_t *pdimm, 16550e3dc0SWang Huan unsigned int ctrl_num) 17550e3dc0SWang Huan { 18550e3dc0SWang Huan const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; 19550e3dc0SWang Huan ulong ddr_freq; 20550e3dc0SWang Huan 21550e3dc0SWang Huan if (ctrl_num > 3) { 22550e3dc0SWang Huan printf("Not supported controller number %d\n", ctrl_num); 23550e3dc0SWang Huan return; 24550e3dc0SWang Huan } 25550e3dc0SWang Huan if (!pdimm->n_ranks) 26550e3dc0SWang Huan return; 27550e3dc0SWang Huan 28550e3dc0SWang Huan pbsp = udimms[0]; 29550e3dc0SWang Huan 30550e3dc0SWang Huan /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr 31550e3dc0SWang Huan * freqency and n_banks specified in board_specific_parameters table. 32550e3dc0SWang Huan */ 33550e3dc0SWang Huan ddr_freq = get_ddr_freq(0) / 1000000; 34550e3dc0SWang Huan while (pbsp->datarate_mhz_high) { 35550e3dc0SWang Huan if (pbsp->n_ranks == pdimm->n_ranks) { 36550e3dc0SWang Huan if (ddr_freq <= pbsp->datarate_mhz_high) { 37550e3dc0SWang Huan popts->clk_adjust = pbsp->clk_adjust; 38550e3dc0SWang Huan popts->wrlvl_start = pbsp->wrlvl_start; 39550e3dc0SWang Huan popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; 40550e3dc0SWang Huan popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; 41550e3dc0SWang Huan popts->cpo_override = pbsp->cpo_override; 42550e3dc0SWang Huan popts->write_data_delay = 43550e3dc0SWang Huan pbsp->write_data_delay; 44550e3dc0SWang Huan goto found; 45550e3dc0SWang Huan } 46550e3dc0SWang Huan pbsp_highest = pbsp; 47550e3dc0SWang Huan } 48550e3dc0SWang Huan pbsp++; 49550e3dc0SWang Huan } 50550e3dc0SWang Huan 51550e3dc0SWang Huan if (pbsp_highest) { 52550e3dc0SWang Huan printf("Error: board specific timing not found for %lu MT/s\n", 53550e3dc0SWang Huan ddr_freq); 54550e3dc0SWang Huan printf("Trying to use the highest speed (%u) parameters\n", 55550e3dc0SWang Huan pbsp_highest->datarate_mhz_high); 56550e3dc0SWang Huan popts->clk_adjust = pbsp_highest->clk_adjust; 57550e3dc0SWang Huan popts->wrlvl_start = pbsp_highest->wrlvl_start; 58550e3dc0SWang Huan popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; 59550e3dc0SWang Huan popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; 60550e3dc0SWang Huan } else { 61550e3dc0SWang Huan panic("DIMM is not supported by this board"); 62550e3dc0SWang Huan } 63550e3dc0SWang Huan found: 64550e3dc0SWang Huan debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n", 65550e3dc0SWang Huan pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb); 66550e3dc0SWang Huan 67550e3dc0SWang Huan /* force DDR bus width to 32 bits */ 68550e3dc0SWang Huan popts->data_bus_width = 1; 69550e3dc0SWang Huan popts->otf_burst_chop_en = 0; 70550e3dc0SWang Huan popts->burst_length = DDR_BL8; 71550e3dc0SWang Huan 72550e3dc0SWang Huan /* 73550e3dc0SWang Huan * Factors to consider for half-strength driver enable: 74550e3dc0SWang Huan * - number of DIMMs installed 75550e3dc0SWang Huan */ 76550e3dc0SWang Huan popts->half_strength_driver_enable = 1; 77550e3dc0SWang Huan /* 78550e3dc0SWang Huan * Write leveling override 79550e3dc0SWang Huan */ 80550e3dc0SWang Huan popts->wrlvl_override = 1; 81550e3dc0SWang Huan popts->wrlvl_sample = 0xf; 82550e3dc0SWang Huan 83550e3dc0SWang Huan /* 84550e3dc0SWang Huan * Rtt and Rtt_WR override 85550e3dc0SWang Huan */ 86550e3dc0SWang Huan popts->rtt_override = 0; 87550e3dc0SWang Huan 88550e3dc0SWang Huan /* Enable ZQ calibration */ 89550e3dc0SWang Huan popts->zq_en = 1; 90550e3dc0SWang Huan 91*c7eae7fcSYork Sun #ifdef CONFIG_SYS_FSL_DDR4 92*c7eae7fcSYork Sun popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_80ohm); 93*c7eae7fcSYork Sun popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_80ohm) | 94*c7eae7fcSYork Sun DDR_CDR2_VREF_OVRD(70); /* Vref = 70% */ 95*c7eae7fcSYork Sun #else 96*c7eae7fcSYork Sun popts->cswl_override = DDR_CSWL_CS0; 97*c7eae7fcSYork Sun 98550e3dc0SWang Huan /* DHC_EN =1, ODT = 75 Ohm */ 99550e3dc0SWang Huan popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_75ohm); 100550e3dc0SWang Huan popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_75ohm); 101*c7eae7fcSYork Sun #endif 102550e3dc0SWang Huan } 103550e3dc0SWang Huan 104550e3dc0SWang Huan #ifdef CONFIG_SYS_DDR_RAW_TIMING 105550e3dc0SWang Huan dimm_params_t ddr_raw_timing = { 106550e3dc0SWang Huan .n_ranks = 1, 107550e3dc0SWang Huan .rank_density = 1073741824u, 108550e3dc0SWang Huan .capacity = 1073741824u, 109550e3dc0SWang Huan .primary_sdram_width = 32, 110550e3dc0SWang Huan .ec_sdram_width = 0, 111550e3dc0SWang Huan .registered_dimm = 0, 112550e3dc0SWang Huan .mirrored_dimm = 0, 113550e3dc0SWang Huan .n_row_addr = 15, 114550e3dc0SWang Huan .n_col_addr = 10, 115550e3dc0SWang Huan .n_banks_per_sdram_device = 8, 116550e3dc0SWang Huan .edc_config = 0, 117550e3dc0SWang Huan .burst_lengths_bitmask = 0x0c, 118550e3dc0SWang Huan 119550e3dc0SWang Huan .tckmin_x_ps = 1071, 120550e3dc0SWang Huan .caslat_x = 0xfe << 4, /* 5,6,7,8 */ 121550e3dc0SWang Huan .taa_ps = 13125, 122550e3dc0SWang Huan .twr_ps = 15000, 123550e3dc0SWang Huan .trcd_ps = 13125, 124550e3dc0SWang Huan .trrd_ps = 7500, 125550e3dc0SWang Huan .trp_ps = 13125, 126550e3dc0SWang Huan .tras_ps = 37500, 127550e3dc0SWang Huan .trc_ps = 50625, 128550e3dc0SWang Huan .trfc_ps = 160000, 129550e3dc0SWang Huan .twtr_ps = 7500, 130550e3dc0SWang Huan .trtp_ps = 7500, 131550e3dc0SWang Huan .refresh_rate_ps = 7800000, 132550e3dc0SWang Huan .tfaw_ps = 37500, 133550e3dc0SWang Huan }; 134550e3dc0SWang Huan 135550e3dc0SWang Huan int fsl_ddr_get_dimm_params(dimm_params_t *pdimm, 136550e3dc0SWang Huan unsigned int controller_number, 137550e3dc0SWang Huan unsigned int dimm_number) 138550e3dc0SWang Huan { 139550e3dc0SWang Huan static const char dimm_model[] = "Fixed DDR on board"; 140550e3dc0SWang Huan 141550e3dc0SWang Huan if (((controller_number == 0) && (dimm_number == 0)) || 142550e3dc0SWang Huan ((controller_number == 1) && (dimm_number == 0))) { 143550e3dc0SWang Huan memcpy(pdimm, &ddr_raw_timing, sizeof(dimm_params_t)); 144550e3dc0SWang Huan memset(pdimm->mpart, 0, sizeof(pdimm->mpart)); 145550e3dc0SWang Huan memcpy(pdimm->mpart, dimm_model, sizeof(dimm_model) - 1); 146550e3dc0SWang Huan } 147550e3dc0SWang Huan 148550e3dc0SWang Huan return 0; 149550e3dc0SWang Huan } 150550e3dc0SWang Huan #endif 151550e3dc0SWang Huan 152550e3dc0SWang Huan phys_size_t initdram(int board_type) 153550e3dc0SWang Huan { 154550e3dc0SWang Huan phys_size_t dram_size; 155550e3dc0SWang Huan 156550e3dc0SWang Huan puts("Initializing DDR....using SPD\n"); 157550e3dc0SWang Huan dram_size = fsl_ddr_sdram(); 158550e3dc0SWang Huan 159550e3dc0SWang Huan return dram_size; 160550e3dc0SWang Huan } 161550e3dc0SWang Huan 162550e3dc0SWang Huan void dram_init_banksize(void) 163550e3dc0SWang Huan { 164550e3dc0SWang Huan gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 165550e3dc0SWang Huan gd->bd->bi_dram[0].size = gd->ram_size; 166550e3dc0SWang Huan } 167