@ -1,5 +1,5 @@
/*
* Copyright 2008 - 2011 Freescale Semiconductor , Inc .
* Copyright 2008 - 2012 Freescale Semiconductor , Inc .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
@ -15,13 +15,15 @@
# include <common.h>
# include <i2c.h>
# include <asm/fsl_ddr_sdram.h>
# include <asm/fsl_law.h>
# include "ddr.h"
extern void fsl_ddr_set_lawbar (
void fsl_ddr_set_lawbar (
const common_timing_params_t * memctl_common_params ,
unsigned int memctl_interleaved ,
unsigned int ctrl_num ) ;
void fsl_ddr_set_intl3r ( const unsigned int granule_size ) ;
/* processor specific function */
extern void fsl_ddr_set_memctl_regs ( const fsl_ddr_cfg_regs_t * regs ,
@ -51,6 +53,22 @@ u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
[ 1 ] [ 0 ] = SPD_EEPROM_ADDRESS3 , /* controller 2 */
[ 1 ] [ 1 ] = SPD_EEPROM_ADDRESS4 , /* controller 2 */
} ;
# elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 1)
u8 spd_i2c_addr [ CONFIG_NUM_DDR_CONTROLLERS ] [ CONFIG_DIMM_SLOTS_PER_CTLR ] = {
[ 0 ] [ 0 ] = SPD_EEPROM_ADDRESS1 , /* controller 1 */
[ 1 ] [ 0 ] = SPD_EEPROM_ADDRESS2 , /* controller 2 */
[ 2 ] [ 0 ] = SPD_EEPROM_ADDRESS3 , /* controller 3 */
} ;
# elif (CONFIG_NUM_DDR_CONTROLLERS == 3) && (CONFIG_DIMM_SLOTS_PER_CTLR == 2)
u8 spd_i2c_addr [ CONFIG_NUM_DDR_CONTROLLERS ] [ CONFIG_DIMM_SLOTS_PER_CTLR ] = {
[ 0 ] [ 0 ] = SPD_EEPROM_ADDRESS1 , /* controller 1 */
[ 0 ] [ 1 ] = SPD_EEPROM_ADDRESS2 , /* controller 1 */
[ 1 ] [ 0 ] = SPD_EEPROM_ADDRESS3 , /* controller 2 */
[ 1 ] [ 1 ] = SPD_EEPROM_ADDRESS4 , /* controller 2 */
[ 2 ] [ 0 ] = SPD_EEPROM_ADDRESS5 , /* controller 3 */
[ 2 ] [ 1 ] = SPD_EEPROM_ADDRESS6 , /* controller 3 */
} ;
# endif
static void __get_spd ( generic_spd_eeprom_t * spd , u8 i2c_address )
@ -156,12 +174,12 @@ const char * step_to_string(unsigned int step) {
return step_string_tbl [ s ] ;
}
int step_assign_addresses ( fsl_ddr_info_t * pinfo ,
unsigned int dbw_cap_adj [ ] ,
unsigned int * all_memctl_interleaving ,
unsigned int * all_ctlr_rank_interleaving )
unsigned long long step_assign_addresses ( fsl_ddr_info_t * pinfo ,
unsigned int dbw_cap_adj [ ] )
{
int i , j ;
unsigned long long total_mem , current_mem_base , total_ctlr_mem ;
unsigned long long rank_density , ctlr_density = 0 ;
/*
* If a reduced data width is requested , but the SPD
@ -220,86 +238,108 @@ int step_assign_addresses(fsl_ddr_info_t *pinfo,
" specified controller %u \n " , i ) ;
return 1 ;
}
debug ( " dbw_cap_adj[%d]=%d \n " , i , dbw_cap_adj [ i ] ) ;
}
j = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + )
if ( pinfo - > memctl_opts [ i ] . memctl_interleaving )
j + + ;
/*
* Not support less than all memory controllers interleaving
* if more than two controllers
*/
if ( j = = CONFIG_NUM_DDR_CONTROLLERS )
* all_memctl_interleaving = 1 ;
/* Check that all controllers are rank interleaving. */
j = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + )
if ( pinfo - > memctl_opts [ i ] . ba_intlv_ctl )
j + + ;
/*
* All memory controllers must be populated to qualify for
* all controller rank interleaving
*/
if ( j = = CONFIG_NUM_DDR_CONTROLLERS )
* all_ctlr_rank_interleaving = 1 ;
if ( * all_memctl_interleaving ) {
unsigned long long addr , total_mem_per_ctlr = 0 ;
/*
* If interleaving between memory controllers ,
* make each controller start at a base address
* of 0.
*
* Also , if bank interleaving ( chip select
* interleaving ) is enabled on each memory
* controller , CS0 needs to be programmed to
* cover the entire memory range on that memory
* controller
*
* Bank interleaving also implies that each
* addressed chip select is identical in size .
*/
current_mem_base = 0ull ;
total_mem = 0 ;
if ( pinfo - > memctl_opts [ 0 ] . memctl_interleaving ) {
rank_density = pinfo - > dimm_params [ 0 ] [ 0 ] . rank_density > >
dbw_cap_adj [ 0 ] ;
switch ( pinfo - > memctl_opts [ 0 ] . ba_intlv_ctl &
FSL_DDR_CS0_CS1_CS2_CS3 ) {
case FSL_DDR_CS0_CS1_CS2_CS3 :
ctlr_density = 4 * rank_density ;
break ;
case FSL_DDR_CS0_CS1 :
case FSL_DDR_CS0_CS1_AND_CS2_CS3 :
ctlr_density = 2 * rank_density ;
break ;
case FSL_DDR_CS2_CS3 :
default :
ctlr_density = rank_density ;
break ;
}
debug ( " rank density is 0x%llx, ctlr density is 0x%llx \n " ,
rank_density , ctlr_density ) ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
addr = 0 ;
pinfo - > common_timing_params [ i ] . base_address = 0ull ;
for ( j = 0 ; j < CONFIG_DIMM_SLOTS_PER_CTLR ; j + + ) {
unsigned long long cap
= pinfo - > dimm_params [ i ] [ j ] . capacity ;
pinfo - > dimm_params [ i ] [ j ] . base_address = addr ;
addr + = cap > > dbw_cap_adj [ i ] ;
total_mem_per_ctlr + = cap > > dbw_cap_adj [ i ] ;
if ( pinfo - > memctl_opts [ i ] . memctl_interleaving ) {
switch ( pinfo - > memctl_opts [ i ] . memctl_interleaving_mode ) {
case FSL_DDR_CACHE_LINE_INTERLEAVING :
case FSL_DDR_PAGE_INTERLEAVING :
case FSL_DDR_BANK_INTERLEAVING :
case FSL_DDR_SUPERBANK_INTERLEAVING :
total_ctlr_mem = 2 * ctlr_density ;
break ;
case FSL_DDR_3WAY_1KB_INTERLEAVING :
case FSL_DDR_3WAY_4KB_INTERLEAVING :
case FSL_DDR_3WAY_8KB_INTERLEAVING :
total_ctlr_mem = 3 * ctlr_density ;
break ;
case FSL_DDR_4WAY_1KB_INTERLEAVING :
case FSL_DDR_4WAY_4KB_INTERLEAVING :
case FSL_DDR_4WAY_8KB_INTERLEAVING :
total_ctlr_mem = 4 * ctlr_density ;
break ;
default :
panic ( " Unknown interleaving mode " ) ;
}
pinfo - > common_timing_params [ i ] . base_address =
current_mem_base ;
pinfo - > common_timing_params [ i ] . total_mem =
total_ctlr_mem ;
total_mem = current_mem_base + total_ctlr_mem ;
debug ( " ctrl %d base 0x%llx \n " , i , current_mem_base ) ;
debug ( " ctrl %d total 0x%llx \n " , i , total_ctlr_mem ) ;
} else {
/* when 3rd controller not interleaved */
current_mem_base = total_mem ;
total_ctlr_mem = 0 ;
pinfo - > common_timing_params [ i ] . base_address =
current_mem_base ;
for ( j = 0 ; j < CONFIG_DIMM_SLOTS_PER_CTLR ; j + + ) {
unsigned long long cap =
pinfo - > dimm_params [ i ] [ j ] . capacity > > dbw_cap_adj [ i ] ;
pinfo - > dimm_params [ i ] [ j ] . base_address =
current_mem_base ;
debug ( " ctrl %d dimm %d base 0x%llx \n " , i , j , current_mem_base ) ;
current_mem_base + = cap ;
total_ctlr_mem + = cap ;
}
debug ( " ctrl %d total 0x%llx \n " , i , total_ctlr_mem ) ;
pinfo - > common_timing_params [ i ] . total_mem =
total_ctlr_mem ;
total_mem + = total_ctlr_mem ;
}
}
pinfo - > common_timing_params [ 0 ] . total_mem = total_mem_per_ctlr ;
} else {
/*
* Simple linear assignment if memory
* controllers are not interleaved .
*/
unsigned long long cur_memsize = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
u64 total_mem_per_ctlr = 0 ;
total_ctlr_mem = 0 ;
pinfo - > common_timing_params [ i ] . base_address =
cur_memsize ;
current _mem_ba se ;
for ( j = 0 ; j < CONFIG_DIMM_SLOTS_PER_CTLR ; j + + ) {
/* Compute DIMM base addresses. */
unsigned long long cap =
pinfo - > dimm_params [ i ] [ j ] . capacity ;
pinfo - > dimm_params [ i ] [ j ] . capacity > > dbw_cap_adj [ i ] ;
pinfo - > dimm_params [ i ] [ j ] . base_address =
cur_memsize ;
cur_memsize + = cap > > dbw_cap_adj [ i ] ;
total_mem_per_ctlr + = cap > > dbw_cap_adj [ i ] ;
current_mem_base ;
debug ( " ctrl %d dimm %d base 0x%llx \n " , i , j , current_mem_base ) ;
current_mem_base + = cap ;
total_ctlr_mem + = cap ;
}
debug ( " ctrl %d total 0x%llx \n " , i , total_ctlr_mem ) ;
pinfo - > common_timing_params [ i ] . total_mem =
total_mem_per_ctlr ;
total_ctlr_mem ;
total_mem + = total_ctlr_mem ;
}
}
debug ( " Total mem by %s is 0x%llx \n " , __func__ , total_mem ) ;
return 0 ;
return total_mem ;
}
unsigned long long
@ -307,8 +347,6 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
unsigned int size_only )
{
unsigned int i , j ;
unsigned int all_controllers_memctl_interleaving = 0 ;
unsigned int all_controllers_rank_interleaving = 0 ;
unsigned long long total_mem = 0 ;
fsl_ddr_cfg_regs_t * ddr_reg = pinfo - > fsl_ddr_config_reg ;
@ -346,8 +384,9 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
retval = compute_dimm_parameters ( spd , pdimm , i ) ;
# ifdef CONFIG_SYS_DDR_RAW_TIMING
if ( retval ! = 0 ) {
printf ( " SPD error! Trying fallback to "
" raw timing calculation \n " ) ;
printf ( " SPD error on controller %d! "
" Trying fallback to raw timing "
" calculation \n " , i ) ;
fsl_ddr_get_dimm_params ( pdimm , i , j ) ;
}
# else
@ -407,17 +446,14 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
& pinfo - > memctl_opts [ i ] ,
pinfo - > dimm_params [ i ] , i ) ;
}
check_interleaving_options ( pinfo ) ;
case STEP_ASSIGN_ADDRESSES :
/* STEP 5: Assign addresses to chip selects */
step_assign_addresses ( pinfo ,
dbw_capacity_adjust ,
& all_controllers_memctl_interleaving ,
& all_controllers_rank_interleaving ) ;
check_interleaving_options ( pinfo ) ;
total_mem = step_assign_addresses ( pinfo , dbw_capacity_adjust ) ;
case STEP_COMPUTE_REGS :
/* STEP 6: compute controller register values */
debug ( " FSL Memory ctrl cg register computation \n " ) ;
debug ( " FSL Memory ctrl register computation \n " ) ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
if ( timing_params [ i ] . ndimms_present = = 0 ) {
memset ( & ddr_reg [ i ] , 0 ,
@ -437,21 +473,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
break ;
}
/* Compute the total amount of memory. */
/*
* If bank interleaving but NOT memory controller interleaving
* CS_BNDS describe the quantity of memory on each memory
* controller , so the total is the sum across .
*/
if ( ! all_controllers_memctl_interleaving
& & all_controllers_rank_interleaving ) {
total_mem = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
total_mem + = timing_params [ i ] . total_mem ;
}
} else {
{
/*
* Compute the amount of memory available just by
* looking for the highest valid CSn_BNDS value .
@ -489,7 +511,7 @@ fsl_ddr_compute(fsl_ddr_info_t *pinfo, unsigned int start_step,
phys_size_t fsl_ddr_sdram ( void )
{
unsigned int i ;
unsigned int memctl_interleaved ;
unsigned int law_memctl = LAW_TRGT_IF_DDR_1 ;
unsigned long long total_memory ;
fsl_ddr_info_t info ;
@ -504,34 +526,6 @@ phys_size_t fsl_ddr_sdram(void)
# endif
total_memory = fsl_ddr_compute ( & info , STEP_GET_SPD , 0 ) ;
/* Check for memory controller interleaving. */
memctl_interleaved = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
memctl_interleaved + =
info . memctl_opts [ i ] . memctl_interleaving ;
}
if ( memctl_interleaved ) {
if ( memctl_interleaved = = CONFIG_NUM_DDR_CONTROLLERS ) {
debug ( " memctl interleaving \n " ) ;
/*
* Change the meaning of memctl_interleaved
* to be " boolean " .
*/
memctl_interleaved = 1 ;
} else {
printf ( " Warning: memctl interleaving not "
" properly configured on all controllers \n " ) ;
memctl_interleaved = 0 ;
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + )
info . memctl_opts [ i ] . memctl_interleaving = 0 ;
debug ( " Recomputing with memctl_interleaving off. \n " ) ;
total_memory = fsl_ddr_compute ( & info ,
STEP_ASSIGN_ADDRESSES ,
0 ) ;
}
}
/* Program configuration registers. */
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
debug ( " Programming controller %u \n " , i ) ;
@ -544,24 +538,69 @@ phys_size_t fsl_ddr_sdram(void)
fsl_ddr_set_memctl_regs ( & ( info . fsl_ddr_config_reg [ i ] ) , i ) ;
}
if ( memctl_interleaved ) {
const unsigned int ctrl_num = 0 ;
/* Only set LAWBAR1 if memory controller interleaving is on. */
fsl_ddr_set_lawbar ( & info . common_timing_params [ 0 ] ,
memctl_interleaved , ctrl_num ) ;
} else {
/*
* Memory controller interleaving is NOT on ;
* set each lawbar individually .
*/
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
/* program LAWs */
for ( i = 0 ; i < CONFIG_NUM_DDR_CONTROLLERS ; i + + ) {
if ( info . memctl_opts [ i ] . memctl_interleaving ) {
switch ( info . memctl_opts [ i ] . memctl_interleaving_mode ) {
case FSL_DDR_CACHE_LINE_INTERLEAVING :
case FSL_DDR_PAGE_INTERLEAVING :
case FSL_DDR_BANK_INTERLEAVING :
case FSL_DDR_SUPERBANK_INTERLEAVING :
if ( i = = 0 ) {
law_memctl = LAW_TRGT_IF_DDR_INTRLV ;
fsl_ddr_set_lawbar ( & info . common_timing_params [ i ] ,
law_memctl , i ) ;
} else if ( i = = 2 ) {
law_memctl = LAW_TRGT_IF_DDR_INTLV_34 ;
fsl_ddr_set_lawbar ( & info . common_timing_params [ i ] ,
law_memctl , i ) ;
}
break ;
case FSL_DDR_3WAY_1KB_INTERLEAVING :
case FSL_DDR_3WAY_4KB_INTERLEAVING :
case FSL_DDR_3WAY_8KB_INTERLEAVING :
law_memctl = LAW_TRGT_IF_DDR_INTLV_123 ;
if ( i = = 0 ) {
fsl_ddr_set_intl3r ( info . memctl_opts [ i ] . memctl_interleaving_mode ) ;
fsl_ddr_set_lawbar ( & info . common_timing_params [ i ] ,
law_memctl , i ) ;
}
break ;
case FSL_DDR_4WAY_1KB_INTERLEAVING :
case FSL_DDR_4WAY_4KB_INTERLEAVING :
case FSL_DDR_4WAY_8KB_INTERLEAVING :
law_memctl = LAW_TRGT_IF_DDR_INTLV_1234 ;
if ( i = = 0 )
fsl_ddr_set_lawbar ( & info . common_timing_params [ i ] ,
law_memctl , i ) ;
/* place holder for future 4-way interleaving */
break ;
default :
break ;
}
} else {
switch ( i ) {
case 0 :
law_memctl = LAW_TRGT_IF_DDR_1 ;
break ;
case 1 :
law_memctl = LAW_TRGT_IF_DDR_2 ;
break ;
case 2 :
law_memctl = LAW_TRGT_IF_DDR_3 ;
break ;
case 3 :
law_memctl = LAW_TRGT_IF_DDR_4 ;
break ;
default :
break ;
}
fsl_ddr_set_lawbar ( & info . common_timing_params [ i ] ,
0 , i ) ;
law_memctl , i ) ;
}
}
debug ( " total_memory = %llu \n " , total_memory ) ;
debug ( " total_memory by %s = %llu \n " , __func__ , total_memory ) ;
# if !defined(CONFIG_PHYS_64BIT)
/* Check for 4G or more. Bad. */