1bfe18815SJohn Schmoller /* 2bfe18815SJohn Schmoller * Copyright 2010 Extreme Engineering Solutions, Inc. 3bfe18815SJohn Schmoller * Copyright 2007-2008 Freescale Semiconductor, Inc. 4bfe18815SJohn Schmoller * 5bfe18815SJohn Schmoller * See file CREDITS for list of people who contributed to this 6bfe18815SJohn Schmoller * project. 7bfe18815SJohn Schmoller * 8bfe18815SJohn Schmoller * This program is free software; you can redistribute it and/or 9bfe18815SJohn Schmoller * modify it under the terms of the GNU General Public License as 10bfe18815SJohn Schmoller * published by the Free Software Foundation; either version 2 of 11bfe18815SJohn Schmoller * the License, or (at your option) any later version. 12bfe18815SJohn Schmoller * 13bfe18815SJohn Schmoller * This program is distributed in the hope that it will be useful, 14bfe18815SJohn Schmoller * but WITHOUT ANY WARRANTY; without even the implied warranty of 15bfe18815SJohn Schmoller * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16bfe18815SJohn Schmoller * GNU General Public License for more details. 17bfe18815SJohn Schmoller * 18bfe18815SJohn Schmoller * You should have received a copy of the GNU General Public License 19bfe18815SJohn Schmoller * along with this program; if not, write to the Free Software 20bfe18815SJohn Schmoller * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21bfe18815SJohn Schmoller * MA 02111-1307 USA 22bfe18815SJohn Schmoller */ 23bfe18815SJohn Schmoller 24bfe18815SJohn Schmoller #include <common.h> 25bfe18815SJohn Schmoller #include <i2c.h> 26bfe18815SJohn Schmoller 27bfe18815SJohn Schmoller #include <asm/fsl_ddr_sdram.h> 28bfe18815SJohn Schmoller #include <asm/fsl_ddr_dimm_params.h> 29bfe18815SJohn Schmoller 30*c39f44dcSKumar Gala void get_spd(ddr3_spd_eeprom_t *spd, u8 i2c_address) 31bfe18815SJohn Schmoller { 32bfe18815SJohn Schmoller i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd, 33bfe18815SJohn Schmoller sizeof(ddr3_spd_eeprom_t)); 34bfe18815SJohn Schmoller } 35bfe18815SJohn Schmoller 36bfe18815SJohn Schmoller /* 37bfe18815SJohn Schmoller * There are traditionally three board-specific SDRAM timing parameters 38bfe18815SJohn Schmoller * which must be calculated based on the particular PCB artwork. These are: 39bfe18815SJohn Schmoller * 1.) CPO (Read Capture Delay) 40bfe18815SJohn Schmoller * - TIMING_CFG_2 register 41bfe18815SJohn Schmoller * Source: Calculation based on board trace lengths and 42bfe18815SJohn Schmoller * chip-specific internal delays. 43bfe18815SJohn Schmoller * 2.) CLK_ADJUST (Clock and Addr/Cmd alignment control) 44bfe18815SJohn Schmoller * - DDR_SDRAM_CLK_CNTL register 45bfe18815SJohn Schmoller * Source: Signal Integrity Simulations 46bfe18815SJohn Schmoller * 3.) 2T Timing on Addr/Ctl 47bfe18815SJohn Schmoller * - TIMING_CFG_2 register 48bfe18815SJohn Schmoller * Source: Signal Integrity Simulations 49bfe18815SJohn Schmoller * Usually only needed with heavy load/very high speed (>DDR2-800) 50bfe18815SJohn Schmoller * 51bfe18815SJohn Schmoller * ====== XPedite550x DDR3-800 read delay calculations ====== 52bfe18815SJohn Schmoller * 53bfe18815SJohn Schmoller * The P2020 processor provides an autoleveling option. Setting CPO to 54bfe18815SJohn Schmoller * 0x1f enables this auto configuration. 55bfe18815SJohn Schmoller */ 56bfe18815SJohn Schmoller 57bfe18815SJohn Schmoller typedef struct { 58bfe18815SJohn Schmoller unsigned short datarate_mhz_low; 59bfe18815SJohn Schmoller unsigned short datarate_mhz_high; 60bfe18815SJohn Schmoller unsigned char clk_adjust; 61bfe18815SJohn Schmoller unsigned char cpo; 62bfe18815SJohn Schmoller } board_specific_parameters_t; 63bfe18815SJohn Schmoller 64bfe18815SJohn Schmoller const board_specific_parameters_t board_specific_parameters[][20] = { 65bfe18815SJohn Schmoller { 66bfe18815SJohn Schmoller /* Controller 0 */ 67bfe18815SJohn Schmoller { 68bfe18815SJohn Schmoller /* DDR3-600/667 */ 69bfe18815SJohn Schmoller .datarate_mhz_low = 500, 70bfe18815SJohn Schmoller .datarate_mhz_high = 750, 71bfe18815SJohn Schmoller .clk_adjust = 5, 72bfe18815SJohn Schmoller .cpo = 31, 73bfe18815SJohn Schmoller }, 74bfe18815SJohn Schmoller { 75bfe18815SJohn Schmoller /* DDR3-800 */ 76bfe18815SJohn Schmoller .datarate_mhz_low = 750, 77bfe18815SJohn Schmoller .datarate_mhz_high = 850, 78bfe18815SJohn Schmoller .clk_adjust = 5, 79bfe18815SJohn Schmoller .cpo = 31, 80bfe18815SJohn Schmoller }, 81bfe18815SJohn Schmoller }, 82bfe18815SJohn Schmoller }; 83bfe18815SJohn Schmoller 84bfe18815SJohn Schmoller void fsl_ddr_board_options(memctl_options_t *popts, 85bfe18815SJohn Schmoller dimm_params_t *pdimm, 86bfe18815SJohn Schmoller unsigned int ctrl_num) 87bfe18815SJohn Schmoller { 88bfe18815SJohn Schmoller const board_specific_parameters_t *pbsp = 89bfe18815SJohn Schmoller &(board_specific_parameters[ctrl_num][0]); 90bfe18815SJohn Schmoller u32 num_params = sizeof(board_specific_parameters[ctrl_num]) / 91bfe18815SJohn Schmoller sizeof(board_specific_parameters[0][0]); 92bfe18815SJohn Schmoller u32 i; 93bfe18815SJohn Schmoller ulong ddr_freq; 94bfe18815SJohn Schmoller 95bfe18815SJohn Schmoller /* 96bfe18815SJohn Schmoller * Set odt_rd_cfg and odt_wr_cfg. If the there is only one dimm in 97bfe18815SJohn Schmoller * that controller, set odt_wr_cfg to 4 for CS0, and 0 to CS1. If 98bfe18815SJohn Schmoller * there are two dimms in the controller, set odt_rd_cfg to 3 and 99bfe18815SJohn Schmoller * odt_wr_cfg to 3 for the even CS, 0 for the odd CS. 100bfe18815SJohn Schmoller */ 101bfe18815SJohn Schmoller for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { 102bfe18815SJohn Schmoller if (i&1) { /* odd CS */ 103bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_rd_cfg = 0; 104bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_wr_cfg = 0; 105bfe18815SJohn Schmoller } else { /* even CS */ 106bfe18815SJohn Schmoller if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) { 107bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_rd_cfg = 0; 108bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_wr_cfg = 4; 109bfe18815SJohn Schmoller } else if (CONFIG_DIMM_SLOTS_PER_CTLR == 2) { 110bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_rd_cfg = 3; 111bfe18815SJohn Schmoller popts->cs_local_opts[i].odt_wr_cfg = 3; 112bfe18815SJohn Schmoller } 113bfe18815SJohn Schmoller } 114bfe18815SJohn Schmoller } 115bfe18815SJohn Schmoller 116bfe18815SJohn Schmoller /* 117bfe18815SJohn Schmoller * Get clk_adjust, cpo, write_data_delay,2T, according to the board ddr 118bfe18815SJohn Schmoller * freqency and n_banks specified in board_specific_parameters table. 119bfe18815SJohn Schmoller */ 120bfe18815SJohn Schmoller ddr_freq = get_ddr_freq(0) / 1000000; 121bfe18815SJohn Schmoller 122bfe18815SJohn Schmoller for (i = 0; i < num_params; i++) { 123bfe18815SJohn Schmoller if (ddr_freq >= pbsp->datarate_mhz_low && 124bfe18815SJohn Schmoller ddr_freq <= pbsp->datarate_mhz_high) { 125bfe18815SJohn Schmoller popts->clk_adjust = pbsp->clk_adjust; 126bfe18815SJohn Schmoller popts->cpo_override = pbsp->cpo; 127bfe18815SJohn Schmoller popts->twoT_en = 0; 128bfe18815SJohn Schmoller } 129bfe18815SJohn Schmoller pbsp++; 130bfe18815SJohn Schmoller } 131bfe18815SJohn Schmoller 132bfe18815SJohn Schmoller /* 133bfe18815SJohn Schmoller * Factors to consider for half-strength driver enable: 134bfe18815SJohn Schmoller * - number of DIMMs installed 135bfe18815SJohn Schmoller */ 136bfe18815SJohn Schmoller popts->half_strength_driver_enable = 0; 137bfe18815SJohn Schmoller 138bfe18815SJohn Schmoller /* 139bfe18815SJohn Schmoller * Enable on-die termination. 140bfe18815SJohn Schmoller * From the Micron Technical Node TN-41-04, RTT_Nom should typically 141bfe18815SJohn Schmoller * be 30 to 40 ohms, while RTT_WR should be 120 ohms. Setting RTT_WR 142bfe18815SJohn Schmoller * is handled in the Freescale DDR3 driver. Set RTT_Nom here. 143bfe18815SJohn Schmoller */ 144bfe18815SJohn Schmoller popts->rtt_override = 1; 145bfe18815SJohn Schmoller popts->rtt_override_value = 3; 146bfe18815SJohn Schmoller } 147