@ -792,6 +792,244 @@ void emif_get_device_timings(u32 emif_nr,
}
# endif /* CONFIG_SYS_DEFAULT_LPDDR2_TIMINGS */
# ifdef CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION
const char * get_lpddr2_type ( u8 type_id )
{
switch ( type_id ) {
case LPDDR2_TYPE_S4 :
return " LPDDR2-S4 " ;
case LPDDR2_TYPE_S2 :
return " LPDDR2-S2 " ;
default :
return NULL ;
}
}
const char * get_lpddr2_io_width ( u8 width_id )
{
switch ( width_id ) {
case LPDDR2_IO_WIDTH_8 :
return " x8 " ;
case LPDDR2_IO_WIDTH_16 :
return " x16 " ;
case LPDDR2_IO_WIDTH_32 :
return " x32 " ;
default :
return NULL ;
}
}
const char * get_lpddr2_manufacturer ( u32 manufacturer )
{
switch ( manufacturer ) {
case LPDDR2_MANUFACTURER_SAMSUNG :
return " Samsung " ;
case LPDDR2_MANUFACTURER_QIMONDA :
return " Qimonda " ;
case LPDDR2_MANUFACTURER_ELPIDA :
return " Elpida " ;
case LPDDR2_MANUFACTURER_ETRON :
return " Etron " ;
case LPDDR2_MANUFACTURER_NANYA :
return " Nanya " ;
case LPDDR2_MANUFACTURER_HYNIX :
return " Hynix " ;
case LPDDR2_MANUFACTURER_MOSEL :
return " Mosel " ;
case LPDDR2_MANUFACTURER_WINBOND :
return " Winbond " ;
case LPDDR2_MANUFACTURER_ESMT :
return " ESMT " ;
case LPDDR2_MANUFACTURER_SPANSION :
return " Spansion " ;
case LPDDR2_MANUFACTURER_SST :
return " SST " ;
case LPDDR2_MANUFACTURER_ZMOS :
return " ZMOS " ;
case LPDDR2_MANUFACTURER_INTEL :
return " Intel " ;
case LPDDR2_MANUFACTURER_NUMONYX :
return " Numonyx " ;
case LPDDR2_MANUFACTURER_MICRON :
return " Micron " ;
default :
return NULL ;
}
}
static void display_sdram_details ( u32 emif_nr , u32 cs ,
struct lpddr2_device_details * device )
{
const char * mfg_str ;
const char * type_str ;
char density_str [ 10 ] ;
u32 density ;
debug ( " EMIF%d CS%d \t " , emif_nr , cs ) ;
if ( ! device ) {
debug ( " None \n " ) ;
return ;
}
mfg_str = get_lpddr2_manufacturer ( device - > manufacturer ) ;
type_str = get_lpddr2_type ( device - > type ) ;
density = lpddr2_density_2_size_in_mbytes [ device - > density ] ;
if ( ( density / 1024 * 1024 ) = = density ) {
density / = 1024 ;
sprintf ( density_str , " %d GB " , density ) ;
} else
sprintf ( density_str , " %d MB " , density ) ;
if ( mfg_str & & type_str )
debug ( " %s \t \t %s \t %s \n " , mfg_str , type_str , density_str ) ;
}
static u8 is_lpddr2_sdram_present ( u32 base , u32 cs ,
struct lpddr2_device_details * lpddr2_device )
{
u32 mr = 0 , temp ;
mr = get_mr ( base , cs , LPDDR2_MR0 ) ;
if ( mr > 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
temp = ( mr & LPDDR2_MR0_DI_MASK ) > > LPDDR2_MR0_DI_SHIFT ;
if ( temp ) {
/* Not SDRAM */
return 0 ;
}
temp = ( mr & LPDDR2_MR0_DNVI_MASK ) > > LPDDR2_MR0_DNVI_SHIFT ;
if ( temp ) {
/* DNV supported - But DNV is only supported for NVM */
return 0 ;
}
mr = get_mr ( base , cs , LPDDR2_MR4 ) ;
if ( mr > 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
mr = get_mr ( base , cs , LPDDR2_MR5 ) ;
if ( mr > = 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
if ( ! get_lpddr2_manufacturer ( mr ) ) {
/* Manufacturer not identified */
return 0 ;
}
lpddr2_device - > manufacturer = mr ;
mr = get_mr ( base , cs , LPDDR2_MR6 ) ;
if ( mr > = 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
mr = get_mr ( base , cs , LPDDR2_MR7 ) ;
if ( mr > = 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
mr = get_mr ( base , cs , LPDDR2_MR8 ) ;
if ( mr > = 0xFF ) {
/* Mode register value bigger than 8 bit */
return 0 ;
}
temp = ( mr & MR8_TYPE_MASK ) > > MR8_TYPE_SHIFT ;
if ( ! get_lpddr2_type ( temp ) ) {
/* Not SDRAM */
return 0 ;
}
lpddr2_device - > type = temp ;
temp = ( mr & MR8_DENSITY_MASK ) > > MR8_DENSITY_SHIFT ;
if ( temp > LPDDR2_DENSITY_32Gb ) {
/* Density not supported */
return 0 ;
}
lpddr2_device - > density = temp ;
temp = ( mr & MR8_IO_WIDTH_MASK ) > > MR8_IO_WIDTH_SHIFT ;
if ( ! get_lpddr2_io_width ( temp ) ) {
/* IO width unsupported value */
return 0 ;
}
lpddr2_device - > io_width = temp ;
/*
* If all the above tests pass we should
* have a device on this chip - select
*/
return 1 ;
}
static struct lpddr2_device_details * get_lpddr2_details ( u32 base , u8 cs ,
struct lpddr2_device_details * lpddr2_dev_details )
{
u32 phy ;
struct emif_reg_struct * emif = ( struct emif_reg_struct * ) base ;
if ( ! lpddr2_dev_details )
return NULL ;
/* Do the minimum init for mode register accesses */
if ( ! running_from_sdram ( ) ) {
phy = get_ddr_phy_ctrl_1 ( get_sys_clk_freq ( ) / 2 , RL_BOOT ) ;
writel ( phy , & emif - > emif_ddr_phy_ctrl_1 ) ;
}
if ( ! ( is_lpddr2_sdram_present ( base , cs , lpddr2_dev_details ) ) )
return NULL ;
display_sdram_details ( emif_num ( base ) , cs , lpddr2_dev_details ) ;
return lpddr2_dev_details ;
}
void emif_get_device_details ( u32 emif_nr ,
struct lpddr2_device_details * cs0_device_details ,
struct lpddr2_device_details * cs1_device_details )
{
u32 base = ( emif_nr = = 1 ) ? OMAP44XX_EMIF1 : OMAP44XX_EMIF2 ;
if ( running_from_sdram ( ) ) {
/*
* We can not do automatic discovery running from SDRAM
* Most likely we came here by mistake . Indicate error
* by returning NULL
*/
cs0_device_details = NULL ;
cs1_device_details = NULL ;
} else {
/*
* Automatically find the device details :
*
* Reset the PHY after each call to get_lpddr2_details ( ) .
* If there is nothing connected to a given chip select
* ( typically CS1 ) mode register reads will mess up with
* the PHY state and subsequent initialization won ' t work .
* PHY reset brings back PHY to a good state .
*/
cs0_device_details =
get_lpddr2_details ( base , CS0 , cs0_device_details ) ;
emif_reset_phy ( base ) ;
cs1_device_details =
get_lpddr2_details ( base , CS1 , cs1_device_details ) ;
emif_reset_phy ( base ) ;
}
}
# endif /* CONFIG_SYS_AUTOMATIC_SDRAM_DETECTION */
static void do_sdram_init ( u32 base )
{
const struct emif_regs * regs ;