@ -15,13 +15,24 @@
# include <asm/arch/dram.h>
# include <linux/kconfig.h>
/*
* The delay parameters below allow to allegedly specify delay times of some
* unknown unit for each individual bit trace in each of the four data bytes
* the 32 - bit wide access consists of . Also three control signals can be
* adjusted individually .
*/
# define BITS_PER_BYTE 8
# define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE)
/* The eight data lines (DQn) plus DM, DQS and DQSN */
# define LINES_PER_BYTE_LANE (BITS_PER_BYTE + 3)
struct dram_para {
u32 read_delays ;
u32 write_delays ;
u16 page_size ;
u8 bus_width ;
u8 dual_rank ;
u8 row_bits ;
const u8 dx_read_delays [ NR_OF_BYTE_LANES ] [ LINES_PER_BYTE_LANE ] ;
const u8 dx_write_delays [ NR_OF_BYTE_LANES ] [ LINES_PER_BYTE_LANE ] ;
const u8 ac_delays [ 31 ] ;
} ;
static inline int ns_to_t ( int nanoseconds )
@ -64,34 +75,25 @@ static void mctl_phy_init(u32 val)
mctl_await_completion ( & mctl_ctl - > pgsr [ 0 ] , PGSR_INIT_DONE , 0x1 ) ;
}
static void mctl_dq_delay ( u32 read , u32 write )
static void mctl_set_bit_delays ( struct dram_para * para )
{
struct sunxi_mctl_ctl_reg * const mctl_ctl =
( struct sunxi_mctl_ctl_reg * ) SUNXI_DRAM_CTL0_BASE ;
int i , j ;
u32 val ;
for ( i = 0 ; i < 4 ; i + + ) {
val = DXBDLR_WRITE_DELAY ( ( write > > ( i * 4 ) ) & 0xf ) |
DXBDLR_READ_DELAY ( ( ( read > > ( i * 4 ) ) & 0xf ) * 2 ) ;
for ( j = DXBDLR_DQ ( 0 ) ; j < = DXBDLR_DM ; j + + )
writel ( val , & mctl_ctl - > dx [ i ] . bdlr [ j ] ) ;
}
clrbits_le32 ( & mctl_ctl - > pgcr [ 0 ] , 1 < < 26 ) ;
for ( i = 0 ; i < 4 ; i + + ) {
val = DXBDLR_WRITE_DELAY ( ( write > > ( 16 + i * 4 ) ) & 0xf ) |
DXBDLR_READ_DELAY ( ( read > > ( 16 + i * 4 ) ) & 0xf ) ;
for ( i = 0 ; i < NR_OF_BYTE_LANES ; i + + )
for ( j = 0 ; j < LINES_PER_BYTE_LANE ; j + + )
writel ( DXBDLR_WRITE_DELAY ( para - > dx_write_delays [ i ] [ j ] ) |
DXBDLR_READ_DELAY ( para - > dx_read_delays [ i ] [ j ] ) ,
& mctl_ctl - > dx [ i ] . bdlr [ j ] ) ;
writel ( val , & mctl_ctl - > dx [ i ] . bdlr [ DXBDLR_DQS ] ) ;
writel ( val , & mctl_ctl - > dx [ i ] . bdlr [ DXBDLR_DQSN ] ) ;
}
for ( i = 0 ; i < 31 ; i + + )
writel ( ACBDLR_WRITE_DELAY ( para - > ac_delays [ i ] ) ,
& mctl_ctl - > acbdlr [ i ] ) ;
setbits_le32 ( & mctl_ctl - > pgcr [ 0 ] , 1 < < 26 ) ;
udelay ( 1 ) ;
}
enum {
@ -412,11 +414,8 @@ static int mctl_channel_init(struct dram_para *para)
clrsetbits_le32 ( & mctl_ctl - > dtcr , 0xf < < 24 ,
( para - > dual_rank ? 0x3 : 0x1 ) < < 24 ) ;
if ( para - > read_delays | | para - > write_delays ) {
mctl_dq_delay ( para - > read_delays , para - > write_delays ) ;
udelay ( 50 ) ;
}
mctl_set_bit_delays ( para ) ;
udelay ( 50 ) ;
mctl_zq_calibration ( para ) ;
@ -490,6 +489,29 @@ static void mctl_auto_detect_dram_size(struct dram_para *para)
break ;
}
/*
* The actual values used here are taken from Allwinner provided boot0
* binaries , though they are probably board specific , so would likely benefit
* from invidual tuning for each board . Apparently a lot of boards copy from
* some Allwinner reference design , so we go with those generic values for now
* in the hope that they are reasonable for most ( all ? ) boards .
*/
# define SUN8I_H3_DX_READ_DELAYS \
{ { 18 , 18 , 18 , 18 , 18 , 18 , 18 , 18 , 18 , 0 , 0 } , \
{ 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 0 , 0 } , \
{ 18 , 18 , 18 , 18 , 18 , 18 , 18 , 18 , 18 , 0 , 0 } , \
{ 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 0 , 0 } }
# define SUN8I_H3_DX_WRITE_DELAYS \
{ { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 } , \
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 } , \
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10 , 10 } , \
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 6 , 6 } }
# define SUN8I_H3_AC_DELAYS \
{ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , \
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , \
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , \
0 , 0 , 0 , 0 , 0 , 0 , 0 }
unsigned long sunxi_dram_init ( void )
{
struct sunxi_mctl_com_reg * const mctl_com =
@ -498,12 +520,13 @@ unsigned long sunxi_dram_init(void)
( struct sunxi_mctl_ctl_reg * ) SUNXI_DRAM_CTL0_BASE ;
struct dram_para para = {
. read_delays = 0x00007979 , /* dram_tpr12 */
. write_delays = 0x6aaa0000 , /* dram_tpr11 */
. dual_rank = 0 ,
. bus_width = 32 ,
. row_bits = 15 ,
. page_size = 4096 ,
. dx_read_delays = SUN8I_H3_DX_READ_DELAYS ,
. dx_write_delays = SUN8I_H3_DX_WRITE_DELAYS ,
. ac_delays = SUN8I_H3_AC_DELAYS ,
} ;
mctl_sys_init ( & para ) ;