1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2009 Extreme Engineering Solutions, Inc. 4 * Copyright 2007-2008 Freescale Semiconductor, Inc. 5 */ 6 7 #include <common.h> 8 #include <i2c.h> 9 #include <fsl_ddr_sdram.h> 10 #include <fsl_ddr_dimm_params.h> 11 12 void get_spd(ddr2_spd_eeprom_t *spd, u8 i2c_address) 13 { 14 i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd, 15 sizeof(ddr2_spd_eeprom_t)); 16 } 17 18 /* 19 * There are four board-specific SDRAM timing parameters which must be 20 * calculated based on the particular PCB artwork. These are: 21 * 1.) CPO (Read Capture Delay) 22 * - TIMING_CFG_2 register 23 * Source: Calculation based on board trace lengths and 24 * chip-specific internal delays. 25 * 2.) WR_DATA_DELAY (Write Command to Data Strobe Delay) 26 * - TIMING_CFG_2 register 27 * Source: Calculation based on board trace lengths. 28 * Unless clock and DQ lanes are very different 29 * lengths (>2"), this should be set to the nominal value 30 * of 1/2 clock delay. 31 * 3.) CLK_ADJUST (Clock and Addr/Cmd alignment control) 32 * - DDR_SDRAM_CLK_CNTL register 33 * Source: Signal Integrity Simulations 34 * 4.) 2T Timing on Addr/Ctl 35 * - TIMING_CFG_2 register 36 * Source: Signal Integrity Simulations 37 * Usually only needed with heavy load/very high speed (>DDR2-800) 38 * 39 * PCB routing on the XPedite5170 is nearly identical to the XPedite5370 40 * so we use the XPedite5370 settings as a basis for the XPedite5170. 41 */ 42 43 typedef struct board_memctl_options { 44 uint16_t datarate_mhz_low; 45 uint16_t datarate_mhz_high; 46 uint8_t clk_adjust; 47 uint8_t cpo_override; 48 uint8_t write_data_delay; 49 } board_memctl_options_t; 50 51 static struct board_memctl_options bopts_ctrl[][2] = { 52 { 53 /* Controller 0 */ 54 { 55 /* DDR2 600/667 */ 56 .datarate_mhz_low = 500, 57 .datarate_mhz_high = 750, 58 .clk_adjust = 5, 59 .cpo_override = 8, 60 .write_data_delay = 2, 61 }, 62 { 63 /* DDR2 800 */ 64 .datarate_mhz_low = 750, 65 .datarate_mhz_high = 850, 66 .clk_adjust = 5, 67 .cpo_override = 9, 68 .write_data_delay = 2, 69 }, 70 }, 71 { 72 /* Controller 1 */ 73 { 74 /* DDR2 600/667 */ 75 .datarate_mhz_low = 500, 76 .datarate_mhz_high = 750, 77 .clk_adjust = 5, 78 .cpo_override = 7, 79 .write_data_delay = 2, 80 }, 81 { 82 /* DDR2 800 */ 83 .datarate_mhz_low = 750, 84 .datarate_mhz_high = 850, 85 .clk_adjust = 5, 86 .cpo_override = 8, 87 .write_data_delay = 2, 88 }, 89 }, 90 }; 91 92 void fsl_ddr_board_options(memctl_options_t *popts, 93 dimm_params_t *pdimm, 94 unsigned int ctrl_num) 95 { 96 struct board_memctl_options *bopts = bopts_ctrl[ctrl_num]; 97 sys_info_t sysinfo; 98 int i; 99 unsigned int datarate; 100 101 get_sys_info(&sysinfo); 102 datarate = get_ddr_freq(0) / 1000000; 103 104 for (i = 0; i < ARRAY_SIZE(bopts_ctrl[ctrl_num]); i++) { 105 if ((bopts[i].datarate_mhz_low <= datarate) && 106 (bopts[i].datarate_mhz_high >= datarate)) { 107 debug("controller %d:\n", ctrl_num); 108 debug(" clk_adjust = %d\n", bopts[i].clk_adjust); 109 debug(" cpo = %d\n", bopts[i].cpo_override); 110 debug(" write_data_delay = %d\n", 111 bopts[i].write_data_delay); 112 popts->clk_adjust = bopts[i].clk_adjust; 113 popts->cpo_override = bopts[i].cpo_override; 114 popts->write_data_delay = bopts[i].write_data_delay; 115 } 116 } 117 118 /* 119 * Factors to consider for half-strength driver enable: 120 * - number of DIMMs installed 121 */ 122 popts->half_strength_driver_enable = 0; 123 } 124