@ -170,6 +170,628 @@ static void emif_update_timings(u32 base, const struct emif_regs *regs)
}
}
# ifndef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
# define print_timing_reg(reg) debug(#reg" - 0x%08x\n", (reg))
static u32 * const T_num = ( u32 * ) OMAP4_SRAM_SCRATCH_EMIF_T_NUM ;
static u32 * const T_den = ( u32 * ) OMAP4_SRAM_SCRATCH_EMIF_T_DEN ;
static u32 * const emif_sizes = ( u32 * ) OMAP4_SRAM_SCRATCH_EMIF_SIZE ;
/*
* Organization and refresh requirements for LPDDR2 devices of different
* types and densities . Derived from JESD209 - 2 section 2.4
*/
const struct lpddr2_addressing addressing_table [ ] = {
/* Banks tREFIx10 rowx32,rowx16 colx32,colx16 density */
{ BANKS4 , T_REFI_15_6 , { ROW_12 , ROW_12 } , { COL_7 , COL_8 } } , /*64M */
{ BANKS4 , T_REFI_15_6 , { ROW_12 , ROW_12 } , { COL_8 , COL_9 } } , /*128M */
{ BANKS4 , T_REFI_7_8 , { ROW_13 , ROW_13 } , { COL_8 , COL_9 } } , /*256M */
{ BANKS4 , T_REFI_7_8 , { ROW_13 , ROW_13 } , { COL_9 , COL_10 } } , /*512M */
{ BANKS8 , T_REFI_7_8 , { ROW_13 , ROW_13 } , { COL_9 , COL_10 } } , /*1GS4 */
{ BANKS8 , T_REFI_3_9 , { ROW_14 , ROW_14 } , { COL_9 , COL_10 } } , /*2GS4 */
{ BANKS8 , T_REFI_3_9 , { ROW_14 , ROW_14 } , { COL_10 , COL_11 } } , /*4G */
{ BANKS8 , T_REFI_3_9 , { ROW_15 , ROW_15 } , { COL_10 , COL_11 } } , /*8G */
{ BANKS4 , T_REFI_7_8 , { ROW_14 , ROW_14 } , { COL_9 , COL_10 } } , /*1GS2 */
{ BANKS4 , T_REFI_3_9 , { ROW_15 , ROW_15 } , { COL_9 , COL_10 } } , /*2GS2 */
} ;
static const u32 lpddr2_density_2_size_in_mbytes [ ] = {
8 , /* 64Mb */
16 , /* 128Mb */
32 , /* 256Mb */
64 , /* 512Mb */
128 , /* 1Gb */
256 , /* 2Gb */
512 , /* 4Gb */
1024 , /* 8Gb */
2048 , /* 16Gb */
4096 /* 32Gb */
} ;
/*
* Calculate the period of DDR clock from frequency value and set the
* denominator and numerator in global variables for easy access later
*/
static void set_ddr_clk_period ( u32 freq )
{
/*
* period = 1 / freq
* period_in_ns = 10 ^ 9 / freq
*/
* T_num = 1000000000 ;
* T_den = freq ;
cancel_out ( T_num , T_den , 200 ) ;
}
/*
* Convert time in nano seconds to number of cycles of DDR clock
*/
static inline u32 ns_2_cycles ( u32 ns )
{
return ( ( ns * ( * T_den ) ) + ( * T_num ) - 1 ) / ( * T_num ) ;
}
/*
* ns_2_cycles with the difference that the time passed is 2 times the actual
* value ( to avoid fractions ) . The cycles returned is for the original value of
* the timing parameter
*/
static inline u32 ns_x2_2_cycles ( u32 ns )
{
return ( ( ns * ( * T_den ) ) + ( * T_num ) * 2 - 1 ) / ( ( * T_num ) * 2 ) ;
}
/*
* Find addressing table index based on the device ' s type ( S2 or S4 ) and
* density
*/
s8 addressing_table_index ( u8 type , u8 density , u8 width )
{
u8 index ;
if ( ( density > LPDDR2_DENSITY_8Gb ) | | ( width = = LPDDR2_IO_WIDTH_8 ) )
return - 1 ;
/*
* Look at the way ADDR_TABLE_INDEX * values have been defined
* in emif . h compared to LPDDR2_DENSITY_ * values
* The table is layed out in the increasing order of density
* ( ignoring type ) . The exceptions 1 GS2 and 2 GS2 have been placed
* at the end
*/
if ( ( type = = LPDDR2_TYPE_S2 ) & & ( density = = LPDDR2_DENSITY_1Gb ) )
index = ADDR_TABLE_INDEX1GS2 ;
else if ( ( type = = LPDDR2_TYPE_S2 ) & & ( density = = LPDDR2_DENSITY_2Gb ) )
index = ADDR_TABLE_INDEX2GS2 ;
else
index = density ;
debug ( " emif: addressing table index %d \n " , index ) ;
return index ;
}
/*
* Find the the right timing table from the array of timing
* tables of the device using DDR clock frequency
*/
static const struct lpddr2_ac_timings * get_timings_table ( const struct
lpddr2_ac_timings const * const * device_timings ,
u32 freq )
{
u32 i , temp , freq_nearest ;
const struct lpddr2_ac_timings * timings = 0 ;
emif_assert ( freq < = MAX_LPDDR2_FREQ ) ;
emif_assert ( device_timings ) ;
/*
* Start with the maximum allowed frequency - that is always safe
*/
freq_nearest = MAX_LPDDR2_FREQ ;
/*
* Find the timings table that has the max frequency value :
* i . Above or equal to the DDR frequency - safe
* ii . The lowest that satisfies condition ( i ) - optimal
*/
for ( i = 0 ; ( i < MAX_NUM_SPEEDBINS ) & & device_timings [ i ] ; i + + ) {
temp = device_timings [ i ] - > max_freq ;
if ( ( temp > = freq ) & & ( temp < = freq_nearest ) ) {
freq_nearest = temp ;
timings = device_timings [ i ] ;
}
}
debug ( " emif: timings table: %d \n " , freq_nearest ) ;
return timings ;
}
/*
* Finds the value of emif_sdram_config_reg
* All parameters are programmed based on the device on CS0 .
* If there is a device on CS1 , it will be same as that on CS0 or
* it will be NVM . We don ' t support NVM yet .
* If cs1_device pointer is NULL it is assumed that there is no device
* on CS1
*/
static u32 get_sdram_config_reg ( const struct lpddr2_device_details * cs0_device ,
const struct lpddr2_device_details * cs1_device ,
const struct lpddr2_addressing * addressing ,
u8 RL )
{
u32 config_reg = 0 ;
config_reg | = ( cs0_device - > type + 4 ) < < OMAP44XX_REG_SDRAM_TYPE_SHIFT ;
config_reg | = EMIF_INTERLEAVING_POLICY_MAX_INTERLEAVING < <
OMAP44XX_REG_IBANK_POS_SHIFT ;
config_reg | = cs0_device - > io_width < < OMAP44XX_REG_NARROW_MODE_SHIFT ;
config_reg | = RL < < OMAP44XX_REG_CL_SHIFT ;
config_reg | = addressing - > row_sz [ cs0_device - > io_width ] < <
OMAP44XX_REG_ROWSIZE_SHIFT ;
config_reg | = addressing - > num_banks < < OMAP44XX_REG_IBANK_SHIFT ;
config_reg | = ( cs1_device ? EBANK_CS1_EN : EBANK_CS1_DIS ) < <
OMAP44XX_REG_EBANK_SHIFT ;
config_reg | = addressing - > col_sz [ cs0_device - > io_width ] < <
OMAP44XX_REG_PAGESIZE_SHIFT ;
return config_reg ;
}
static u32 get_sdram_ref_ctrl ( u32 freq ,
const struct lpddr2_addressing * addressing )
{
u32 ref_ctrl = 0 , val = 0 , freq_khz ;
freq_khz = freq / 1000 ;
/*
* refresh rate to be set is ' tREFI * freq in MHz
* division by 10000 to account for khz and x10 in t_REFI_us_x10
*/
val = addressing - > t_REFI_us_x10 * freq_khz / 10000 ;
ref_ctrl | = val < < OMAP44XX_REG_REFRESH_RATE_SHIFT ;
return ref_ctrl ;
}
static u32 get_sdram_tim_1_reg ( const struct lpddr2_ac_timings * timings ,
const struct lpddr2_min_tck * min_tck ,
const struct lpddr2_addressing * addressing )
{
u32 tim1 = 0 , val = 0 ;
val = max ( min_tck - > tWTR , ns_x2_2_cycles ( timings - > tWTRx2 ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_WTR_SHIFT ;
if ( addressing - > num_banks = = BANKS8 )
val = ( timings - > tFAW * ( * T_den ) + 4 * ( * T_num ) - 1 ) /
( 4 * ( * T_num ) ) - 1 ;
else
val = max ( min_tck - > tRRD , ns_2_cycles ( timings - > tRRD ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_RRD_SHIFT ;
val = ns_2_cycles ( timings - > tRASmin + timings - > tRPab ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_RC_SHIFT ;
val = max ( min_tck - > tRAS_MIN , ns_2_cycles ( timings - > tRASmin ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_RAS_SHIFT ;
val = max ( min_tck - > tWR , ns_2_cycles ( timings - > tWR ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_WR_SHIFT ;
val = max ( min_tck - > tRCD , ns_2_cycles ( timings - > tRCD ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_RCD_SHIFT ;
val = max ( min_tck - > tRP_AB , ns_2_cycles ( timings - > tRPab ) ) - 1 ;
tim1 | = val < < OMAP44XX_REG_T_RP_SHIFT ;
return tim1 ;
}
static u32 get_sdram_tim_2_reg ( const struct lpddr2_ac_timings * timings ,
const struct lpddr2_min_tck * min_tck )
{
u32 tim2 = 0 , val = 0 ;
val = max ( min_tck - > tCKE , timings - > tCKE ) - 1 ;
tim2 | = val < < OMAP44XX_REG_T_CKE_SHIFT ;
val = max ( min_tck - > tRTP , ns_x2_2_cycles ( timings - > tRTPx2 ) ) - 1 ;
tim2 | = val < < OMAP44XX_REG_T_RTP_SHIFT ;
/*
* tXSRD = tRFCab + 10 ns . XSRD and XSNR should have the
* same value
*/
val = ns_2_cycles ( timings - > tXSR ) - 1 ;
tim2 | = val < < OMAP44XX_REG_T_XSRD_SHIFT ;
tim2 | = val < < OMAP44XX_REG_T_XSNR_SHIFT ;
val = max ( min_tck - > tXP , ns_x2_2_cycles ( timings - > tXPx2 ) ) - 1 ;
tim2 | = val < < OMAP44XX_REG_T_XP_SHIFT ;
return tim2 ;
}
static u32 get_sdram_tim_3_reg ( const struct lpddr2_ac_timings * timings ,
const struct lpddr2_min_tck * min_tck ,
const struct lpddr2_addressing * addressing )
{
u32 tim3 = 0 , val = 0 ;
val = min ( timings - > tRASmax * 10 / addressing - > t_REFI_us_x10 - 1 , 0xF ) ;
tim3 | = val < < OMAP44XX_REG_T_RAS_MAX_SHIFT ;
val = ns_2_cycles ( timings - > tRFCab ) - 1 ;
tim3 | = val < < OMAP44XX_REG_T_RFC_SHIFT ;
val = ns_x2_2_cycles ( timings - > tDQSCKMAXx2 ) - 1 ;
tim3 | = val < < OMAP44XX_REG_T_TDQSCKMAX_SHIFT ;
val = ns_2_cycles ( timings - > tZQCS ) - 1 ;
tim3 | = val < < OMAP44XX_REG_ZQ_ZQCS_SHIFT ;
val = max ( min_tck - > tCKESR , ns_2_cycles ( timings - > tCKESR ) ) - 1 ;
tim3 | = val < < OMAP44XX_REG_T_CKESR_SHIFT ;
return tim3 ;
}
static u32 get_zq_config_reg ( const struct lpddr2_device_details * cs1_device ,
const struct lpddr2_addressing * addressing ,
u8 volt_ramp )
{
u32 zq = 0 , val = 0 ;
if ( volt_ramp )
val =
EMIF_ZQCS_INTERVAL_DVFS_IN_US * 10 /
addressing - > t_REFI_us_x10 ;
else
val =
EMIF_ZQCS_INTERVAL_NORMAL_IN_US * 10 /
addressing - > t_REFI_us_x10 ;
zq | = val < < OMAP44XX_REG_ZQ_REFINTERVAL_SHIFT ;
zq | = ( REG_ZQ_ZQCL_MULT - 1 ) < < OMAP44XX_REG_ZQ_ZQCL_MULT_SHIFT ;
zq | = ( REG_ZQ_ZQINIT_MULT - 1 ) < < OMAP44XX_REG_ZQ_ZQINIT_MULT_SHIFT ;
zq | = REG_ZQ_SFEXITEN_ENABLE < < OMAP44XX_REG_ZQ_SFEXITEN_SHIFT ;
/*
* Assuming that two chipselects have a single calibration resistor
* If there are indeed two calibration resistors , then this flag should
* be enabled to take advantage of dual calibration feature .
* This data should ideally come from board files . But considering
* that none of the boards today have calibration resistors per CS ,
* it would be an unnecessary overhead .
*/
zq | = REG_ZQ_DUALCALEN_DISABLE < < OMAP44XX_REG_ZQ_DUALCALEN_SHIFT ;
zq | = REG_ZQ_CS0EN_ENABLE < < OMAP44XX_REG_ZQ_CS0EN_SHIFT ;
zq | = ( cs1_device ? 1 : 0 ) < < OMAP44XX_REG_ZQ_CS1EN_SHIFT ;
return zq ;
}
static u32 get_temp_alert_config ( const struct lpddr2_device_details * cs1_device ,
const struct lpddr2_addressing * addressing ,
u8 is_derated )
{
u32 alert = 0 , interval ;
interval =
TEMP_ALERT_POLL_INTERVAL_MS * 10000 / addressing - > t_REFI_us_x10 ;
if ( is_derated )
interval * = 4 ;
alert | = interval < < OMAP44XX_REG_TA_REFINTERVAL_SHIFT ;
alert | = TEMP_ALERT_CONFIG_DEVCT_1 < < OMAP44XX_REG_TA_DEVCNT_SHIFT ;
alert | = TEMP_ALERT_CONFIG_DEVWDT_32 < < OMAP44XX_REG_TA_DEVWDT_SHIFT ;
alert | = 1 < < OMAP44XX_REG_TA_SFEXITEN_SHIFT ;
alert | = 1 < < OMAP44XX_REG_TA_CS0EN_SHIFT ;
alert | = ( cs1_device ? 1 : 0 ) < < OMAP44XX_REG_TA_CS1EN_SHIFT ;
return alert ;
}
static u32 get_read_idle_ctrl_reg ( u8 volt_ramp )
{
u32 idle = 0 , val = 0 ;
if ( volt_ramp )
val = ns_2_cycles ( READ_IDLE_INTERVAL_DVFS ) / 64 + 1 ;
else
/*Maximum value in normal conditions - suggested by hw team */
val = 0x1FF ;
idle | = val < < OMAP44XX_REG_READ_IDLE_INTERVAL_SHIFT ;
idle | = EMIF_REG_READ_IDLE_LEN_VAL < < OMAP44XX_REG_READ_IDLE_LEN_SHIFT ;
return idle ;
}
static u32 get_ddr_phy_ctrl_1 ( u32 freq , u8 RL )
{
u32 phy = 0 , val = 0 ;
phy | = ( RL + 2 ) < < OMAP44XX_REG_READ_LATENCY_SHIFT ;
if ( freq < = 100000000 )
val = EMIF_DLL_SLAVE_DLY_CTRL_100_MHZ_AND_LESS ;
else if ( freq < = 200000000 )
val = EMIF_DLL_SLAVE_DLY_CTRL_200_MHZ ;
else
val = EMIF_DLL_SLAVE_DLY_CTRL_400_MHZ ;
phy | = val < < OMAP44XX_REG_DLL_SLAVE_DLY_CTRL_SHIFT ;
/* Other fields are constant magic values. Hardcode them together */
phy | = EMIF_DDR_PHY_CTRL_1_BASE_VAL < <
OMAP44XX_EMIF_DDR_PHY_CTRL_1_BASE_VAL_SHIFT ;
return phy ;
}
static u32 get_emif_mem_size ( struct emif_device_details * devices )
{
u32 size_mbytes = 0 , temp ;
if ( ! devices )
return 0 ;
if ( devices - > cs0_device_details ) {
temp = devices - > cs0_device_details - > density ;
size_mbytes + = lpddr2_density_2_size_in_mbytes [ temp ] ;
}
if ( devices - > cs1_device_details ) {
temp = devices - > cs1_device_details - > density ;
size_mbytes + = lpddr2_density_2_size_in_mbytes [ temp ] ;
}
/* convert to bytes */
return size_mbytes < < 20 ;
}
/* Gets the encoding corresponding to a given DMM section size */
u32 get_dmm_section_size_map ( u32 section_size )
{
/*
* Section size mapping :
* 0x0 : 16 - MiB section
* 0x1 : 32 - MiB section
* 0x2 : 64 - MiB section
* 0x3 : 128 - MiB section
* 0x4 : 256 - MiB section
* 0x5 : 512 - MiB section
* 0x6 : 1 - GiB section
* 0x7 : 2 - GiB section
*/
section_size > > = 24 ; /* divide by 16 MB */
return log_2_n_round_down ( section_size ) ;
}
static void emif_calculate_regs (
const struct emif_device_details * emif_dev_details ,
u32 freq , struct emif_regs * regs )
{
u32 temp , sys_freq ;
const struct lpddr2_addressing * addressing ;
const struct lpddr2_ac_timings * timings ;
const struct lpddr2_min_tck * min_tck ;
const struct lpddr2_device_details * cs0_dev_details =
emif_dev_details - > cs0_device_details ;
const struct lpddr2_device_details * cs1_dev_details =
emif_dev_details - > cs1_device_details ;
const struct lpddr2_device_timings * cs0_dev_timings =
emif_dev_details - > cs0_device_timings ;
emif_assert ( emif_dev_details ) ;
emif_assert ( regs ) ;
/*
* You can not have a device on CS1 without one on CS0
* So configuring EMIF without a device on CS0 doesn ' t
* make sense
*/
emif_assert ( cs0_dev_details ) ;
emif_assert ( cs0_dev_details - > type ! = LPDDR2_TYPE_NVM ) ;
/*
* If there is a device on CS1 it should be same type as CS0
* ( or NVM . But NVM is not supported in this driver yet )
*/
emif_assert ( ( cs1_dev_details = = NULL ) | |
( cs1_dev_details - > type = = LPDDR2_TYPE_NVM ) | |
( cs0_dev_details - > type = = cs1_dev_details - > type ) ) ;
emif_assert ( freq < = MAX_LPDDR2_FREQ ) ;
set_ddr_clk_period ( freq ) ;
/*
* The device on CS0 is used for all timing calculations
* There is only one set of registers for timings per EMIF . So , if the
* second CS ( CS1 ) has a device , it should have the same timings as the
* device on CS0
*/
timings = get_timings_table ( cs0_dev_timings - > ac_timings , freq ) ;
emif_assert ( timings ) ;
min_tck = cs0_dev_timings - > min_tck ;
temp = addressing_table_index ( cs0_dev_details - > type ,
cs0_dev_details - > density ,
cs0_dev_details - > io_width ) ;
emif_assert ( ( temp > = 0 ) ) ;
addressing = & ( addressing_table [ temp ] ) ;
emif_assert ( addressing ) ;
sys_freq = get_sys_clk_freq ( ) ;
regs - > sdram_config_init = get_sdram_config_reg ( cs0_dev_details ,
cs1_dev_details ,
addressing , RL_BOOT ) ;
regs - > sdram_config = get_sdram_config_reg ( cs0_dev_details ,
cs1_dev_details ,
addressing , RL_FINAL ) ;
regs - > ref_ctrl = get_sdram_ref_ctrl ( freq , addressing ) ;
regs - > sdram_tim1 = get_sdram_tim_1_reg ( timings , min_tck , addressing ) ;
regs - > sdram_tim2 = get_sdram_tim_2_reg ( timings , min_tck ) ;
regs - > sdram_tim3 = get_sdram_tim_3_reg ( timings , min_tck , addressing ) ;
regs - > read_idle_ctrl = get_read_idle_ctrl_reg ( LPDDR2_VOLTAGE_STABLE ) ;
regs - > temp_alert_config =
get_temp_alert_config ( cs1_dev_details , addressing , 0 ) ;
regs - > zq_config = get_zq_config_reg ( cs1_dev_details , addressing ,
LPDDR2_VOLTAGE_STABLE ) ;
regs - > emif_ddr_phy_ctlr_1_init =
get_ddr_phy_ctrl_1 ( sys_freq / 2 , RL_BOOT ) ;
regs - > emif_ddr_phy_ctlr_1 =
get_ddr_phy_ctrl_1 ( freq , RL_FINAL ) ;
regs - > freq = freq ;
print_timing_reg ( regs - > sdram_config_init ) ;
print_timing_reg ( regs - > sdram_config ) ;
print_timing_reg ( regs - > ref_ctrl ) ;
print_timing_reg ( regs - > sdram_tim1 ) ;
print_timing_reg ( regs - > sdram_tim2 ) ;
print_timing_reg ( regs - > sdram_tim3 ) ;
print_timing_reg ( regs - > read_idle_ctrl ) ;
print_timing_reg ( regs - > temp_alert_config ) ;
print_timing_reg ( regs - > zq_config ) ;
print_timing_reg ( regs - > emif_ddr_phy_ctlr_1 ) ;
print_timing_reg ( regs - > emif_ddr_phy_ctlr_1_init ) ;
}
# endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */
# ifdef CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS
/* Base AC Timing values specified by JESD209-2 for 400MHz operation */
static const struct lpddr2_ac_timings timings_jedec_400_mhz = {
. max_freq = 400000000 ,
. RL = 6 ,
. tRPab = 21 ,
. tRCD = 18 ,
. tWR = 15 ,
. tRASmin = 42 ,
. tRRD = 10 ,
. tWTRx2 = 15 ,
. tXSR = 140 ,
. tXPx2 = 15 ,
. tRFCab = 130 ,
. tRTPx2 = 15 ,
. tCKE = 3 ,
. tCKESR = 15 ,
. tZQCS = 90 ,
. tZQCL = 360 ,
. tZQINIT = 1000 ,
. tDQSCKMAXx2 = 11 ,
. tRASmax = 70 ,
. tFAW = 50
} ;
/* Base AC Timing values specified by JESD209-2 for 333 MHz operation */
static const struct lpddr2_ac_timings timings_jedec_333_mhz = {
. max_freq = 333000000 ,
. RL = 5 ,
. tRPab = 21 ,
. tRCD = 18 ,
. tWR = 15 ,
. tRASmin = 42 ,
. tRRD = 10 ,
. tWTRx2 = 15 ,
. tXSR = 140 ,
. tXPx2 = 15 ,
. tRFCab = 130 ,
. tRTPx2 = 15 ,
. tCKE = 3 ,
. tCKESR = 15 ,
. tZQCS = 90 ,
. tZQCL = 360 ,
. tZQINIT = 1000 ,
. tDQSCKMAXx2 = 11 ,
. tRASmax = 70 ,
. tFAW = 50
} ;
/* Base AC Timing values specified by JESD209-2 for 200 MHz operation */
static const struct lpddr2_ac_timings timings_jedec_200_mhz = {
. max_freq = 200000000 ,
. RL = 3 ,
. tRPab = 21 ,
. tRCD = 18 ,
. tWR = 15 ,
. tRASmin = 42 ,
. tRRD = 10 ,
. tWTRx2 = 20 ,
. tXSR = 140 ,
. tXPx2 = 15 ,
. tRFCab = 130 ,
. tRTPx2 = 15 ,
. tCKE = 3 ,
. tCKESR = 15 ,
. tZQCS = 90 ,
. tZQCL = 360 ,
. tZQINIT = 1000 ,
. tDQSCKMAXx2 = 11 ,
. tRASmax = 70 ,
. tFAW = 50
} ;
/*
* Min tCK values specified by JESD209 - 2
* Min tCK specifies the minimum duration of some AC timing parameters in terms
* of the number of cycles . If the calculated number of cycles based on the
* absolute time value is less than the min tCK value , min tCK value should
* be used instead . This typically happens at low frequencies .
*/
static const struct lpddr2_min_tck min_tck_jedec = {
. tRL = 3 ,
. tRP_AB = 3 ,
. tRCD = 3 ,
. tWR = 3 ,
. tRAS_MIN = 3 ,
. tRRD = 2 ,
. tWTR = 2 ,
. tXP = 2 ,
. tRTP = 2 ,
. tCKE = 3 ,
. tCKESR = 3 ,
. tFAW = 8
} ;
static const struct lpddr2_ac_timings const *
jedec_ac_timings [ MAX_NUM_SPEEDBINS ] = {
& timings_jedec_200_mhz ,
& timings_jedec_333_mhz ,
& timings_jedec_400_mhz
} ;
static const struct lpddr2_device_timings jedec_default_timings = {
. ac_timings = jedec_ac_timings ,
. min_tck = & min_tck_jedec
} ;
void emif_get_device_timings ( u32 emif_nr ,
const struct lpddr2_device_timings * * cs0_device_timings ,
const struct lpddr2_device_timings * * cs1_device_timings )
{
/* Assume Identical devices on EMIF1 & EMIF2 */
* cs0_device_timings = & jedec_default_timings ;
* cs1_device_timings = & jedec_default_timings ;
}
# endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */
static void do_sdram_init ( u32 base )
{
const struct emif_regs * regs ;
@ -180,11 +802,54 @@ static void do_sdram_init(u32 base)
in_sdram = running_from_sdram ( ) ;
emif_nr = ( base = = OMAP44XX_EMIF1 ) ? 1 : 2 ;
# ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
emif_get_reg_dump ( emif_nr , & regs ) ;
if ( ! regs ) {
debug ( " EMIF: reg dump not provided \n " ) ;
return ;
}
# else
/*
* The user has not provided the register values . We need to
* calculate it based on the timings and the DDR frequency
*/
struct emif_device_details dev_details ;
struct emif_regs calculated_regs ;
/*
* Get device details :
* - Discovered if CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION is set
* - Obtained from user otherwise
*/
struct lpddr2_device_details cs0_dev_details , cs1_dev_details ;
emif_get_device_details ( emif_nr , & cs0_dev_details ,
& cs1_dev_details ) ;
dev_details . cs0_device_details = & cs0_dev_details ;
dev_details . cs1_device_details = & cs1_dev_details ;
/* Return if no devices on this EMIF */
if ( ! dev_details . cs0_device_details & &
! dev_details . cs1_device_details ) {
emif_sizes [ emif_nr - 1 ] = 0 ;
return ;
}
if ( ! in_sdram )
emif_sizes [ emif_nr - 1 ] = get_emif_mem_size ( & dev_details ) ;
/*
* Get device timings :
* - Default timings specified by JESD209 - 2 if
* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS is set
* - Obtained from user otherwise
*/
emif_get_device_timings ( emif_nr , & dev_details . cs0_device_timings ,
& dev_details . cs1_device_timings ) ;
/* Calculate the register values */
emif_calculate_regs ( & dev_details , omap4_ddr_clk ( ) , & calculated_regs ) ;
regs = & calculated_regs ;
# endif /* CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS */
/*
* Initializing the LPDDR2 device can not happen from SDRAM .
@ -242,8 +907,82 @@ static void dmm_init(u32 base)
{
const struct dmm_lisa_map_regs * lisa_map_regs ;
# ifdef CONFIG_SYS_EMIF_PRECALCULATED_TIMING_REGS
emif_get_dmm_regs ( & lisa_map_regs ) ;
# else
u32 emif1_size , emif2_size , mapped_size , section_map = 0 ;
u32 section_cnt , sys_addr ;
struct dmm_lisa_map_regs lis_map_regs_calculated = { 0 } ;
mapped_size = 0 ;
section_cnt = 3 ;
sys_addr = CONFIG_SYS_SDRAM_BASE ;
emif1_size = emif_sizes [ 0 ] ;
emif2_size = emif_sizes [ 1 ] ;
debug ( " emif1_size 0x%x emif2_size 0x%x \n " , emif1_size , emif2_size ) ;
if ( ! emif1_size & & ! emif2_size )
return ;
/* symmetric interleaved section */
if ( emif1_size & & emif2_size ) {
mapped_size = min ( emif1_size , emif2_size ) ;
section_map = DMM_LISA_MAP_INTERLEAVED_BASE_VAL ;
section_map | = 0 < < OMAP44XX_SDRC_ADDR_SHIFT ;
/* only MSB */
section_map | = ( sys_addr > > 24 ) < <
OMAP44XX_SYS_ADDR_SHIFT ;
section_map | = get_dmm_section_size_map ( mapped_size * 2 )
< < OMAP44XX_SYS_SIZE_SHIFT ;
lis_map_regs_calculated . dmm_lisa_map_3 = section_map ;
emif1_size - = mapped_size ;
emif2_size - = mapped_size ;
sys_addr + = ( mapped_size * 2 ) ;
section_cnt - - ;
}
/*
* Single EMIF section ( we can have a maximum of 1 single EMIF
* section - either EMIF1 or EMIF2 or none , but not both )
*/
if ( emif1_size ) {
section_map = DMM_LISA_MAP_EMIF1_ONLY_BASE_VAL ;
section_map | = get_dmm_section_size_map ( emif1_size )
< < OMAP44XX_SYS_SIZE_SHIFT ;
/* only MSB */
section_map | = ( mapped_size > > 24 ) < <
OMAP44XX_SDRC_ADDR_SHIFT ;
/* only MSB */
section_map | = ( sys_addr > > 24 ) < < OMAP44XX_SYS_ADDR_SHIFT ;
section_cnt - - ;
}
if ( emif2_size ) {
section_map = DMM_LISA_MAP_EMIF2_ONLY_BASE_VAL ;
section_map | = get_dmm_section_size_map ( emif2_size ) < <
OMAP44XX_SYS_SIZE_SHIFT ;
/* only MSB */
section_map | = mapped_size > > 24 < < OMAP44XX_SDRC_ADDR_SHIFT ;
/* only MSB */
section_map | = sys_addr > > 24 < < OMAP44XX_SYS_ADDR_SHIFT ;
section_cnt - - ;
}
if ( section_cnt = = 2 ) {
/* Only 1 section - either symmetric or single EMIF */
lis_map_regs_calculated . dmm_lisa_map_3 = section_map ;
lis_map_regs_calculated . dmm_lisa_map_2 = 0 ;
lis_map_regs_calculated . dmm_lisa_map_1 = 0 ;
} else {
/* 2 sections - 1 symmetric, 1 single EMIF */
lis_map_regs_calculated . dmm_lisa_map_2 = section_map ;
lis_map_regs_calculated . dmm_lisa_map_1 = 0 ;
}
/* TRAP for invalid TILER mappings in section 0 */
lis_map_regs_calculated . dmm_lisa_map_0 = DMM_LISA_MAP_0_INVAL_ADDR_TRAP ;
lisa_map_regs = & lis_map_regs_calculated ;
# endif
struct dmm_lisa_map_regs * hw_lisa_map_regs =
( struct dmm_lisa_map_regs * ) base ;