forked from rrcarlosr/Jetpack
125 lines
3.4 KiB
C
125 lines
3.4 KiB
C
|
/*
|
||
|
* Copyright 2009 Extreme Engineering Solutions, Inc.
|
||
|
* Copyright 2007-2008 Freescale Semiconductor, Inc.
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <i2c.h>
|
||
|
#include <fsl_ddr_sdram.h>
|
||
|
#include <fsl_ddr_dimm_params.h>
|
||
|
|
||
|
void get_spd(ddr2_spd_eeprom_t *spd, u8 i2c_address)
|
||
|
{
|
||
|
i2c_read(i2c_address, SPD_EEPROM_OFFSET, 2, (uchar *)spd,
|
||
|
sizeof(ddr2_spd_eeprom_t));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* There are four board-specific SDRAM timing parameters which must be
|
||
|
* calculated based on the particular PCB artwork. These are:
|
||
|
* 1.) CPO (Read Capture Delay)
|
||
|
* - TIMING_CFG_2 register
|
||
|
* Source: Calculation based on board trace lengths and
|
||
|
* chip-specific internal delays.
|
||
|
* 2.) WR_DATA_DELAY (Write Command to Data Strobe Delay)
|
||
|
* - TIMING_CFG_2 register
|
||
|
* Source: Calculation based on board trace lengths.
|
||
|
* Unless clock and DQ lanes are very different
|
||
|
* lengths (>2"), this should be set to the nominal value
|
||
|
* of 1/2 clock delay.
|
||
|
* 3.) CLK_ADJUST (Clock and Addr/Cmd alignment control)
|
||
|
* - DDR_SDRAM_CLK_CNTL register
|
||
|
* Source: Signal Integrity Simulations
|
||
|
* 4.) 2T Timing on Addr/Ctl
|
||
|
* - TIMING_CFG_2 register
|
||
|
* Source: Signal Integrity Simulations
|
||
|
* Usually only needed with heavy load/very high speed (>DDR2-800)
|
||
|
*
|
||
|
* PCB routing on the XPedite5170 is nearly identical to the XPedite5370
|
||
|
* so we use the XPedite5370 settings as a basis for the XPedite5170.
|
||
|
*/
|
||
|
|
||
|
typedef struct board_memctl_options {
|
||
|
uint16_t datarate_mhz_low;
|
||
|
uint16_t datarate_mhz_high;
|
||
|
uint8_t clk_adjust;
|
||
|
uint8_t cpo_override;
|
||
|
uint8_t write_data_delay;
|
||
|
} board_memctl_options_t;
|
||
|
|
||
|
static struct board_memctl_options bopts_ctrl[][2] = {
|
||
|
{
|
||
|
/* Controller 0 */
|
||
|
{
|
||
|
/* DDR2 600/667 */
|
||
|
.datarate_mhz_low = 500,
|
||
|
.datarate_mhz_high = 750,
|
||
|
.clk_adjust = 5,
|
||
|
.cpo_override = 8,
|
||
|
.write_data_delay = 2,
|
||
|
},
|
||
|
{
|
||
|
/* DDR2 800 */
|
||
|
.datarate_mhz_low = 750,
|
||
|
.datarate_mhz_high = 850,
|
||
|
.clk_adjust = 5,
|
||
|
.cpo_override = 9,
|
||
|
.write_data_delay = 2,
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
/* Controller 1 */
|
||
|
{
|
||
|
/* DDR2 600/667 */
|
||
|
.datarate_mhz_low = 500,
|
||
|
.datarate_mhz_high = 750,
|
||
|
.clk_adjust = 5,
|
||
|
.cpo_override = 7,
|
||
|
.write_data_delay = 2,
|
||
|
},
|
||
|
{
|
||
|
/* DDR2 800 */
|
||
|
.datarate_mhz_low = 750,
|
||
|
.datarate_mhz_high = 850,
|
||
|
.clk_adjust = 5,
|
||
|
.cpo_override = 8,
|
||
|
.write_data_delay = 2,
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
void fsl_ddr_board_options(memctl_options_t *popts,
|
||
|
dimm_params_t *pdimm,
|
||
|
unsigned int ctrl_num)
|
||
|
{
|
||
|
struct board_memctl_options *bopts = bopts_ctrl[ctrl_num];
|
||
|
sys_info_t sysinfo;
|
||
|
int i;
|
||
|
unsigned int datarate;
|
||
|
|
||
|
get_sys_info(&sysinfo);
|
||
|
datarate = get_ddr_freq(0) / 1000000;
|
||
|
|
||
|
for (i = 0; i < ARRAY_SIZE(bopts_ctrl[ctrl_num]); i++) {
|
||
|
if ((bopts[i].datarate_mhz_low <= datarate) &&
|
||
|
(bopts[i].datarate_mhz_high >= datarate)) {
|
||
|
debug("controller %d:\n", ctrl_num);
|
||
|
debug(" clk_adjust = %d\n", bopts[i].clk_adjust);
|
||
|
debug(" cpo = %d\n", bopts[i].cpo_override);
|
||
|
debug(" write_data_delay = %d\n",
|
||
|
bopts[i].write_data_delay);
|
||
|
popts->clk_adjust = bopts[i].clk_adjust;
|
||
|
popts->cpo_override = bopts[i].cpo_override;
|
||
|
popts->write_data_delay = bopts[i].write_data_delay;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Factors to consider for half-strength driver enable:
|
||
|
* - number of DIMMs installed
|
||
|
*/
|
||
|
popts->half_strength_driver_enable = 0;
|
||
|
}
|