@ -57,6 +57,10 @@ struct rk3288_sdram_params {
struct regmap * map ;
} ;
# define TEST_PATTEN 0x5aa5f00f
# define DQS_GATE_TRAINING_ERROR_RANK0 (1 << 4)
# define DQS_GATE_TRAINING_ERROR_RANK1 (2 << 4)
# ifdef CONFIG_SPL_BUILD
static void copy_to_reg ( u32 * dest , const u32 * src , u32 n )
{
@ -214,7 +218,7 @@ static void ddr_set_en_bst_odt(struct rk3288_grf *grf, uint channel,
}
static void pctl_cfg ( u32 channel , struct rk3288_ddr_pctl * pctl ,
const struct rk3288_sdram_params * sdram_params ,
struct rk3288_sdram_params * sdram_params ,
struct rk3288_grf * grf )
{
unsigned int burstlen ;
@ -264,7 +268,7 @@ static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
}
static void phy_cfg ( const struct chan_info * chan , u32 channel ,
const struct rk3288_sdram_params * sdram_params )
struct rk3288_sdram_params * sdram_params )
{
struct rk3288_ddr_publ * publ = chan - > publ ;
struct rk3288_msch * msch = chan - > msch ;
@ -446,7 +450,7 @@ static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
}
static int data_training ( const struct chan_info * chan , u32 channel ,
const struct rk3288_sdram_params * sdram_params )
struct rk3288_sdram_params * sdram_params )
{
unsigned int j ;
int ret = 0 ;
@ -549,7 +553,7 @@ static void move_to_access_state(const struct chan_info *chan)
}
static void dram_cfg_rbc ( const struct chan_info * chan , u32 chnum ,
const struct rk3288_sdram_params * sdram_params )
struct rk3288_sdram_params * sdram_params )
{
struct rk3288_ddr_publ * publ = chan - > publ ;
@ -563,7 +567,7 @@ static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
}
static void dram_all_config ( const struct dram_info * dram ,
const struct rk3288_sdram_params * sdram_params )
struct rk3288_sdram_params * sdram_params )
{
unsigned int chan ;
u32 sys_reg = 0 ;
@ -589,9 +593,191 @@ static void dram_all_config(const struct dram_info *dram,
writel ( sys_reg , & dram - > pmu - > sys_reg [ 2 ] ) ;
rk_clrsetreg ( & dram - > sgrf - > soc_con2 , 0x1f , sdram_params - > base . stride ) ;
}
const int ddrconf_table [ ] = {
/* row col,bw */
0 ,
( ( 1 < < 4 ) | 1 ) ,
( ( 2 < < 4 ) | 1 ) ,
( ( 3 < < 4 ) | 1 ) ,
( ( 4 < < 4 ) | 1 ) ,
( ( 1 < < 4 ) | 2 ) ,
( ( 2 < < 4 ) | 2 ) ,
( ( 3 < < 4 ) | 2 ) ,
( ( 1 < < 4 ) | 0 ) ,
( ( 2 < < 4 ) | 0 ) ,
( ( 3 < < 4 ) | 0 ) ,
0 ,
0 ,
0 ,
0 ,
( ( 4 < < 4 ) | 2 ) ,
} ;
static int sdram_rank_bw_detect ( struct dram_info * dram , int channel ,
struct rk3288_sdram_params * sdram_params )
{
int reg ;
int need_trainig = 0 ;
const struct chan_info * chan = & dram - > chan [ channel ] ;
struct rk3288_ddr_publ * publ = chan - > publ ;
if ( - 1 = = data_training ( chan , channel , sdram_params ) ) {
reg = readl ( & publ - > datx8 [ 0 ] . dxgsr [ 0 ] ) ;
/* Check the result for rank 0 */
if ( ( channel = = 0 ) & & ( reg & DQS_GATE_TRAINING_ERROR_RANK0 ) ) {
debug ( " data training fail! \n " ) ;
return - EIO ;
} else if ( ( channel = = 1 ) & &
( reg & DQS_GATE_TRAINING_ERROR_RANK0 ) ) {
sdram_params - > num_channels = 1 ;
}
/* Check the result for rank 1 */
if ( reg & DQS_GATE_TRAINING_ERROR_RANK1 ) {
sdram_params - > ch [ channel ] . rank = 1 ;
clrsetbits_le32 ( & publ - > pgcr , 0xF < < 18 ,
sdram_params - > ch [ channel ] . rank < < 18 ) ;
need_trainig = 1 ;
}
reg = readl ( & publ - > datx8 [ 2 ] . dxgsr [ 0 ] ) ;
if ( reg & ( 1 < < 4 ) ) {
sdram_params - > ch [ channel ] . bw = 1 ;
set_bandwidth_ratio ( chan , channel ,
sdram_params - > ch [ channel ] . bw ,
dram - > grf ) ;
need_trainig = 1 ;
}
}
/* Assume the Die bit width are the same with the chip bit width */
sdram_params - > ch [ channel ] . dbw = sdram_params - > ch [ channel ] . bw ;
if ( need_trainig & &
( - 1 = = data_training ( chan , channel , sdram_params ) ) ) {
if ( sdram_params - > base . dramtype = = LPDDR3 ) {
ddr_phy_ctl_reset ( dram - > cru , channel , 1 ) ;
udelay ( 10 ) ;
ddr_phy_ctl_reset ( dram - > cru , channel , 0 ) ;
udelay ( 10 ) ;
}
debug ( " 2nd data training failed! " ) ;
return - EIO ;
}
return 0 ;
}
static int sdram_col_row_detect ( struct dram_info * dram , int channel ,
struct rk3288_sdram_params * sdram_params )
{
int row , col ;
unsigned int addr ;
const struct chan_info * chan = & dram - > chan [ channel ] ;
struct rk3288_ddr_pctl * pctl = chan - > pctl ;
struct rk3288_ddr_publ * publ = chan - > publ ;
int ret = 0 ;
/* Detect col */
for ( col = 11 ; col > = 9 ; col - - ) {
writel ( 0 , CONFIG_SYS_SDRAM_BASE ) ;
addr = CONFIG_SYS_SDRAM_BASE +
( 1 < < ( col + sdram_params - > ch [ channel ] . bw - 1 ) ) ;
writel ( TEST_PATTEN , addr ) ;
if ( ( readl ( addr ) = = TEST_PATTEN ) & &
( readl ( CONFIG_SYS_SDRAM_BASE ) = = 0 ) )
break ;
}
if ( col = = 8 ) {
printf ( " Col detect error \n " ) ;
ret = - EINVAL ;
goto out ;
} else {
sdram_params - > ch [ channel ] . col = col ;
}
move_to_config_state ( publ , pctl ) ;
writel ( 4 , & chan - > msch - > ddrconf ) ;
move_to_access_state ( chan ) ;
/* Detect row*/
for ( row = 16 ; row > = 12 ; row - - ) {
writel ( 0 , CONFIG_SYS_SDRAM_BASE ) ;
addr = CONFIG_SYS_SDRAM_BASE + ( 1 < < ( row + 15 - 1 ) ) ;
writel ( TEST_PATTEN , addr ) ;
if ( ( readl ( addr ) = = TEST_PATTEN ) & &
( readl ( CONFIG_SYS_SDRAM_BASE ) = = 0 ) )
break ;
}
if ( row = = 11 ) {
printf ( " Row detect error \n " ) ;
ret = - EINVAL ;
} else {
sdram_params - > ch [ channel ] . cs1_row = row ;
sdram_params - > ch [ channel ] . row_3_4 = 0 ;
debug ( " chn %d col %d, row %d \n " , channel , col , row ) ;
sdram_params - > ch [ channel ] . cs0_row = row ;
}
out :
return ret ;
}
static int sdram_get_niu_config ( struct rk3288_sdram_params * sdram_params )
{
int i , tmp , size , ret = 0 ;
tmp = sdram_params - > ch [ 0 ] . col - 9 ;
tmp - = ( sdram_params - > ch [ 0 ] . bw = = 2 ) ? 0 : 1 ;
tmp | = ( ( sdram_params - > ch [ 0 ] . cs0_row - 12 ) < < 4 ) ;
size = sizeof ( ddrconf_table ) / sizeof ( ddrconf_table [ 0 ] ) ;
for ( i = 0 ; i < size ; i + + )
if ( tmp = = ddrconf_table [ i ] )
break ;
if ( i > = size ) {
printf ( " niu config not found \n " ) ;
ret = - EINVAL ;
} else {
sdram_params - > base . ddrconfig = i ;
}
return ret ;
}
static int sdram_get_stride ( struct rk3288_sdram_params * sdram_params )
{
int stride = - 1 ;
int ret = 0 ;
long cap = sdram_params - > num_channels * ( 1u < <
( sdram_params - > ch [ 0 ] . cs0_row +
sdram_params - > ch [ 0 ] . col +
( sdram_params - > ch [ 0 ] . rank - 1 ) +
sdram_params - > ch [ 0 ] . bw +
3 - 20 ) ) ;
switch ( cap ) {
case 512 :
stride = 0 ;
break ;
case 1024 :
stride = 5 ;
break ;
case 2048 :
stride = 9 ;
break ;
case 4096 :
stride = 0xd ;
break ;
default :
stride = - 1 ;
printf ( " could not find correct stride, cap error! \n " ) ;
ret = - EINVAL ;
break ;
}
sdram_params - > base . stride = stride ;
return ret ;
}
static int sdram_init ( struct dram_info * dram ,
const struct rk3288_sdram_params * sdram_params )
struct rk3288_sdram_params * sdram_params )
{
int channel ;
int zqcr ;
@ -619,12 +805,14 @@ static int sdram_init(struct dram_info *dram,
struct rk3288_ddr_pctl * pctl = chan - > pctl ;
struct rk3288_ddr_publ * publ = chan - > publ ;
/* map all the 4GB space to the current channel */
if ( channel )
rk_clrsetreg ( & dram - > sgrf - > soc_con2 , 0x1f , 0x17 ) ;
else
rk_clrsetreg ( & dram - > sgrf - > soc_con2 , 0x1f , 0x1a ) ;
phy_pctrl_reset ( dram - > cru , publ , channel ) ;
phy_dll_bypass_set ( publ , sdram_params - > base . ddr_freq ) ;
if ( channel > = sdram_params - > num_channels )
continue ;
dfi_cfg ( pctl , sdram_params - > base . dramtype ) ;
pctl_cfg ( channel , pctl , sdram_params , dram - > grf ) ;
@ -658,16 +846,20 @@ static int sdram_init(struct dram_info *dram,
udelay ( 1 ) ;
}
/* Using 32bit bus width for detect */
sdram_params - > ch [ channel ] . bw = 2 ;
set_bandwidth_ratio ( chan , channel ,
sdram_params - > ch [ channel ] . bw , dram - > grf ) ;
/*
* set cs
* set cs , using n = 3 for detect
* CS0 , n = 1
* CS1 , n = 2
* CS0 & CS1 , n = 3
*/
sdram_params - > ch [ channel ] . rank = 2 ,
clrsetbits_le32 ( & publ - > pgcr , 0xF < < 18 ,
( sdram_params - > ch [ channel ] . rank | 1 ) < < 18 ) ;
/* DS=40ohm,ODT=155ohm */
zqcr = 1 < < ZDEN_SHIFT | 2 < < PU_ONDIE_SHIFT |
2 < < PD_ONDIE_SHIFT | 0x19 < < PU_OUTPUT_SHIFT |
@ -693,16 +885,8 @@ static int sdram_init(struct dram_info *dram,
}
}
if ( - 1 = = data_training ( chan , channel , sdram_params ) ) {
if ( sdram_params - > base . dramtype = = LPDDR3 ) {
ddr_phy_ctl_reset ( dram - > cru , channel , 1 ) ;
udelay ( 10 ) ;
ddr_phy_ctl_reset ( dram - > cru , channel , 0 ) ;
udelay ( 10 ) ;
}
debug ( " failed! " ) ;
return - EIO ;
}
/* Detect the rank and bit-width with data-training */
sdram_rank_bw_detect ( dram , channel , sdram_params ) ;
if ( sdram_params - > base . dramtype = = LPDDR3 ) {
u32 i ;
@ -710,12 +894,31 @@ static int sdram_init(struct dram_info *dram,
for ( i = 0 ; i < 17 ; i + + )
send_command_op ( pctl , 1 , MRR_CMD , i , 0 ) ;
}
writel ( 15 , & chan - > msch - > ddrconf ) ;
move_to_access_state ( chan ) ;
/* DDR3 and LPDDR3 are always 8 bank, no need detect */
sdram_params - > ch [ channel ] . bk = 3 ;
/* Detect Col and Row number*/
ret = sdram_col_row_detect ( dram , channel , sdram_params ) ;
if ( ret )
goto error ;
}
/* Find NIU DDR configuration */
ret = sdram_get_niu_config ( sdram_params ) ;
if ( ret )
goto error ;
/* Find stride setting */
ret = sdram_get_stride ( sdram_params ) ;
if ( ret )
goto error ;
dram_all_config ( dram , sdram_params ) ;
debug ( " %s done \n " , __func__ ) ;
return 0 ;
error :
printf ( " DRAM init failed! \n " ) ;
hang ( ) ;
}
# endif /* CONFIG_SPL_BUILD */
@ -743,7 +946,6 @@ size_t sdram_size_mb(struct rk3288_pmu *pmu)
SYS_REG_BW_MASK ) ) ;
row_3_4 = sys_reg > > SYS_REG_ROW_3_4_SHIFT ( ch ) &
SYS_REG_ROW_3_4_MASK ;
chipsize_mb = ( 1 < < ( cs0_row + col + bk + bw - 20 ) ) ;
if ( rank > 1 )
@ -815,21 +1017,10 @@ static int rk3288_dmc_ofdata_to_platdata(struct udevice *dev)
struct rk3288_sdram_params * params = dev_get_platdata ( dev ) ;
const void * blob = gd - > fdt_blob ;
int node = dev - > of_offset ;
int i , ret ;
params - > num_channels = fdtdec_get_int ( blob , node ,
" rockchip,num-channels " , 1 ) ;
for ( i = 0 ; i < params - > num_channels ; i + + ) {
ret = fdtdec_get_byte_array ( blob , node ,
" rockchip,sdram-channel " ,
( u8 * ) & params - > ch [ i ] ,
sizeof ( params - > ch [ i ] ) ) ;
if ( ret ) {
debug ( " %s: Cannot read rockchip,sdram-channel \n " ,
__func__ ) ;
return - EINVAL ;
}
}
int ret ;
/* Rk3288 supports dual-channel, set default channel num to 2 */
params - > num_channels = 2 ;
ret = fdtdec_get_int_array ( blob , node , " rockchip,pctl-timing " ,
( u32 * ) & params - > pctl_timing ,
sizeof ( params - > pctl_timing ) / sizeof ( u32 ) ) ;
@ -870,18 +1061,15 @@ static int conv_of_platdata(struct udevice *dev)
{
struct rk3288_sdram_params * plat = dev_get_platdata ( dev ) ;
struct dtd_rockchip_rk3288_dmc * of_plat = & plat - > of_plat ;
int i , ret ;
int ret ;
for ( i = 0 ; i < 2 ; i + + ) {
memcpy ( & plat - > ch [ i ] , of_plat - > rockchip_sdram_channel ,
sizeof ( plat - > ch [ i ] ) ) ;
}
memcpy ( & plat - > pctl_timing , of_plat - > rockchip_pctl_timing ,
sizeof ( plat - > pctl_timing ) ) ;
memcpy ( & plat - > phy_timing , of_plat - > rockchip_phy_timing ,
sizeof ( plat - > phy_timing ) ) ;
memcpy ( & plat - > base , of_plat - > rockchip_sdram_params , sizeof ( plat - > base ) ) ;
plat - > num_channels = of_plat - > rockchip_num_channels ;
/* Rk3288 supports dual-channel, set default channel num to 2 */
plat - > num_channels = 2 ;
ret = regmap_init_mem_platdata ( dev , of_plat - > reg ,
ARRAY_SIZE ( of_plat - > reg ) / 2 ,
& plat - > map ) ;