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 void fsl_ddr_get_spd(ddr2_spd_eeprom_t *ctrl_dimms_spd, 36 unsigned int ctrl_num) 37 { 38 unsigned int i; 39 unsigned int i2c_address = 0; 40 41 for (i = 0; i < CONFIG_DIMM_SLOTS_PER_CTLR; i++) { 42 if (ctrl_num == 0) { 43 i2c_address = SPD_EEPROM_ADDRESS1; 44 #ifdef SPD_EEPROM_ADDRESS2 45 } else if (ctrl_num == 1) { 46 i2c_address = SPD_EEPROM_ADDRESS2; 47 #endif 48 } else { 49 /* An inalid ctrl number was give, use default SPD */ 50 printf("ERROR: invalid DDR ctrl: %d\n", ctrl_num); 51 i2c_address = SPD_EEPROM_ADDRESS1; 52 } 53 54 get_spd(&(ctrl_dimms_spd[i]), i2c_address); 55 } 56 } 57 58 /* 59 * There are four board-specific SDRAM timing parameters which must be 60 * calculated based on the particular PCB artwork. These are: 61 * 1.) CPO (Read Capture Delay) 62 * - TIMING_CFG_2 register 63 * Source: Calculation based on board trace lengths and 64 * chip-specific internal delays. 65 * 2.) WR_DATA_DELAY (Write Command to Data Strobe Delay) 66 * - TIMING_CFG_2 register 67 * Source: Calculation based on board trace lengths. 68 * Unless clock and DQ lanes are very different 69 * lengths (>2"), this should be set to the nominal value 70 * of 1/2 clock delay. 71 * 3.) CLK_ADJUST (Clock and Addr/Cmd alignment control) 72 * - DDR_SDRAM_CLK_CNTL register 73 * Source: Signal Integrity Simulations 74 * 4.) 2T Timing on Addr/Ctl 75 * - TIMING_CFG_2 register 76 * Source: Signal Integrity Simulations 77 * Usually only needed with heavy load/very high speed (>DDR2-800) 78 * 79 * PCB routing on the XPedite5170 is nearly identical to the XPedite5370 80 * so we use the XPedite5370 settings as a basis for the XPedite5170. 81 */ 82 83 typedef struct board_memctl_options { 84 uint16_t datarate_mhz_low; 85 uint16_t datarate_mhz_high; 86 uint8_t clk_adjust; 87 uint8_t cpo_override; 88 uint8_t write_data_delay; 89 } board_memctl_options_t; 90 91 static struct board_memctl_options bopts_ctrl[][2] = { 92 { 93 /* Controller 0 */ 94 { 95 /* DDR2 600/667 */ 96 .datarate_mhz_low = 500, 97 .datarate_mhz_high = 750, 98 .clk_adjust = 5, 99 .cpo_override = 8, 100 .write_data_delay = 2, 101 }, 102 { 103 /* DDR2 800 */ 104 .datarate_mhz_low = 750, 105 .datarate_mhz_high = 850, 106 .clk_adjust = 5, 107 .cpo_override = 9, 108 .write_data_delay = 2, 109 }, 110 }, 111 { 112 /* Controller 1 */ 113 { 114 /* DDR2 600/667 */ 115 .datarate_mhz_low = 500, 116 .datarate_mhz_high = 750, 117 .clk_adjust = 5, 118 .cpo_override = 7, 119 .write_data_delay = 2, 120 }, 121 { 122 /* DDR2 800 */ 123 .datarate_mhz_low = 750, 124 .datarate_mhz_high = 850, 125 .clk_adjust = 5, 126 .cpo_override = 8, 127 .write_data_delay = 2, 128 }, 129 }, 130 }; 131 132 void fsl_ddr_board_options(memctl_options_t *popts, 133 dimm_params_t *pdimm, 134 unsigned int ctrl_num) 135 { 136 struct board_memctl_options *bopts = bopts_ctrl[ctrl_num]; 137 sys_info_t sysinfo; 138 int i; 139 unsigned int datarate; 140 141 get_sys_info(&sysinfo); 142 datarate = get_ddr_freq(0) / 1000000; 143 144 for (i = 0; i < ARRAY_SIZE(bopts_ctrl[ctrl_num]); i++) { 145 if ((bopts[i].datarate_mhz_low <= datarate) && 146 (bopts[i].datarate_mhz_high >= datarate)) { 147 debug("controller %d:\n", ctrl_num); 148 debug(" clk_adjust = %d\n", bopts[i].clk_adjust); 149 debug(" cpo = %d\n", bopts[i].cpo_override); 150 debug(" write_data_delay = %d\n", 151 bopts[i].write_data_delay); 152 popts->clk_adjust = bopts[i].clk_adjust; 153 popts->cpo_override = bopts[i].cpo_override; 154 popts->write_data_delay = bopts[i].write_data_delay; 155 } 156 } 157 158 /* 159 * Factors to consider for half-strength driver enable: 160 * - number of DIMMs installed 161 */ 162 popts->half_strength_driver_enable = 0; 163 } 164