1 /* 2 * Copyright 2009 Extreme Engineering Solutions, Inc. 3 * Copyright 2007-2008 Freescale Semiconductor, Inc. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 #include <i2c.h> 26 #include <asm/fsl_ddr_sdram.h> 27 #include <asm/fsl_ddr_dimm_params.h> 28 29 static void get_spd(ddr2_spd_eeprom_t *spd, unsigned char i2c_address) 30 { 31 i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd, 32 sizeof(ddr2_spd_eeprom_t)); 33 } 34 35 unsigned int fsl_ddr_get_mem_data_rate(void) 36 { 37 return get_bus_freq(0); 38 } 39 40 void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd, 41 unsigned int ctrl_num) 42 { 43 unsigned int i; 44 unsigned int i2c_address = 0; 45 46 for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { 47 if (ctrl_num == 0) { 48 i2c_address = SPD_EEPROM_ADDRESS1; 49 #ifdef SPD_EEPROM_ADDRESS2 50 } else if (ctrl_num == 1) { 51 i2c_address = SPD_EEPROM_ADDRESS2; 52 #endif 53 } else { 54 /* An inalid ctrl number was give, use default SPD */ 55 printf("ERROR: invalid DDR ctrl: %d\n", ctrl_num); 56 i2c_address = SPD_EEPROM_ADDRESS1; 57 } 58 59 get_spd(&(ctrl_dimms_spd[i]), i2c_address); 60 } 61 } 62 63 /* 64 * There are four board-specific SDRAM timing parameters which must be 65 * calculated based on the particular PCB artwork. These are: 66 * 1.) CPO (Read Capture Delay) 67 * - TIMING_CFG_2 register 68 * Source: Calculation based on board trace lengths and 69 * chip-specific internal delays. 70 * 2.) WR_DATA_DELAY (Write Command to Data Strobe Delay) 71 * - TIMING_CFG_2 register 72 * Source: Calculation based on board trace lengths. 73 * Unless clock and DQ lanes are very different 74 * lengths (>2"), this should be set to the nominal value 75 * of 1/2 clock delay. 76 * 3.) CLK_ADJUST (Clock and Addr/Cmd alignment control) 77 * - DDR_SDRAM_CLK_CNTL register 78 * Source: Signal Integrity Simulations 79 * 4.) 2T Timing on Addr/Ctl 80 * - TIMING_CFG_2 register 81 * Source: Signal Integrity Simulations 82 * Usually only needed with heavy load/very high speed (>DDR2-800) 83 * 84 * PCB routing on the XPedite5170 is nearly identical to the XPedite5370 85 * so we use the XPedite5370 settings as a basis for the XPedite5170. 86 */ 87 88 typedef struct board_memctl_options { 89 uint16_t datarate_mhz_low; 90 uint16_t datarate_mhz_high; 91 uint8_t clk_adjust; 92 uint8_t cpo_override; 93 uint8_t write_data_delay; 94 } board_memctl_options_t; 95 96 static struct board_memctl_options bopts_ctrl[][2] = { 97 { 98 /* Controller 0 */ 99 { 100 /* DDR2 600/667 */ 101 .datarate_mhz_low = 500, 102 .datarate_mhz_high = 750, 103 .clk_adjust = 5, 104 .cpo_override = 8, 105 .write_data_delay = 2, 106 }, 107 { 108 /* DDR2 800 */ 109 .datarate_mhz_low = 750, 110 .datarate_mhz_high = 850, 111 .clk_adjust = 5, 112 .cpo_override = 9, 113 .write_data_delay = 2, 114 }, 115 }, 116 { 117 /* Controller 1 */ 118 { 119 /* DDR2 600/667 */ 120 .datarate_mhz_low = 500, 121 .datarate_mhz_high = 750, 122 .clk_adjust = 5, 123 .cpo_override = 7, 124 .write_data_delay = 2, 125 }, 126 { 127 /* DDR2 800 */ 128 .datarate_mhz_low = 750, 129 .datarate_mhz_high = 850, 130 .clk_adjust = 5, 131 .cpo_override = 8, 132 .write_data_delay = 2, 133 }, 134 }, 135 }; 136 137 void fsl_ddr_board_options(memctl_options_t *popts, 138 dimm_params_t *pdimm, 139 unsigned int ctrl_num) 140 { 141 struct board_memctl_options *bopts = bopts_ctrl[ctrl_num]; 142 sys_info_t sysinfo; 143 int i; 144 unsigned int datarate; 145 146 get_sys_info(&sysinfo); 147 datarate = fsl_ddr_get_mem_data_rate() / 1000000; 148 149 for (i = 0; i < ARRAY_SIZE(bopts_ctrl[ctrl_num]); i++) { 150 if ((bopts[i].datarate_mhz_low <= datarate) && 151 (bopts[i].datarate_mhz_high >= datarate)) { 152 debug("controller %d:\n", ctrl_num); 153 debug(" clk_adjust = %d\n", bopts[i].clk_adjust); 154 debug(" cpo = %d\n", bopts[i].cpo_override); 155 debug(" write_data_delay = %d\n", 156 bopts[i].write_data_delay); 157 popts->clk_adjust = bopts[i].clk_adjust; 158 popts->cpo_override = bopts[i].cpo_override; 159 popts->write_data_delay = bopts[i].write_data_delay; 160 } 161 } 162 163 /* 164 * Factors to consider for half-strength driver enable: 165 * - number of DIMMs installed 166 */ 167 popts->half_strength_driver_enable = 0; 168 } 169