@ -1,7 +1,7 @@
/*
/*
* Copyright ( C ) 2016 Socionext Inc .
* Copyright ( C ) 2016 Socionext Inc .
*
*
* based on commit f7a4c9efe333fb1536efa86f9e96dc0ee109fedd of Diag
* based on commit a3c28918e86ad57127cf07bf8b32950cab20c03c of Diag
*
*
* SPDX - License - Identifier : GPL - 2.0 +
* SPDX - License - Identifier : GPL - 2.0 +
*/
*/
@ -18,6 +18,7 @@
# include "umc64-regs.h"
# include "umc64-regs.h"
# define DRAM_CH_NR 3
# define DRAM_CH_NR 3
# define CONFIG_DDR_FREQ 1866
enum dram_freq {
enum dram_freq {
DRAM_FREQ_1866M ,
DRAM_FREQ_1866M ,
@ -30,6 +31,268 @@ enum dram_size {
DRAM_SZ_NR ,
DRAM_SZ_NR ,
} ;
} ;
enum dram_board { /* board type */
DRAM_BOARD_LD20_REF , /* LD20 reference */
DRAM_BOARD_LD20_GLOBAL , /* LD20 TV */
DRAM_BOARD_LD21_REF , /* LD21 reference */
DRAM_BOARD_LD21_GLOBAL , /* LD21 TV */
DRAM_BOARD_NR ,
} ;
# define MSK_PHY_LANE_SEL 0x000000FF
# define MSK_BIT_SEL 0x00000F00
# define MSK_DLL_MAS_DLY 0xFF000000
# define MSK_MAS_DLY 0x7F000000
# define MSK_DLLS_TRIM_CLK 0x000000FF
# define PHY_DLL_MAS_DLY_WIDTH 8
# define PHY_SLV_DLY_WIDTH 6
static void ddrphy_maskwritel ( u32 data , u32 mask , void * addr )
{
u32 value ;
value = ( readl ( addr ) & ~ mask ) | ( data & mask ) ;
writel ( value , addr ) ;
}
static u32 ddrphy_maskreadl ( u32 mask , void * addr )
{
return readl ( addr ) & mask ;
}
/* set phy_lane_sel.phy_lane_sel */
static void ddrphy_set_phy_lane_sel ( int val , void __iomem * phy_base )
{
ddrphy_maskwritel ( val , MSK_PHY_LANE_SEL , phy_base + PHY_LANE_SEL ) ;
}
/* set phy_lane_sel.bit_sel */
static void ddrphy_set_bit_sel ( int bit , void __iomem * phy_base )
{
ddrphy_maskwritel ( bit < < 8 , MSK_BIT_SEL , phy_base + PHY_LANE_SEL ) ;
}
/* Calculating step for PUB-byte */
static int ddrphy_hpstep ( int delay , void __iomem * phy_base )
{
int mdl , freq ;
freq = CONFIG_DDR_FREQ ; /* FIXME */
mdl = ddrphy_maskreadl ( MSK_DLL_MAS_DLY , phy_base + PHY_DLL_ADRCTRL ) > > 24 ;
return DIV_ROUND_CLOSEST ( freq * delay * mdl , 2 * 1000000 ) ;
}
static void ddrphy_set_dll_trim_clk ( int delay_ckoffset , void __iomem * phy_base )
{
u8 ck_step ; /* ckoffset_step for clock */
u32 ck_step_all ;
/* CK-Offset */
if ( delay_ckoffset > = 0 ) {
/* shift + direction */
ck_step = min ( ddrphy_hpstep ( delay_ckoffset , phy_base ) , 127 ) ;
ck_step_all = ( ( 0x1 < < ( PHY_SLV_DLY_WIDTH + 1 ) ) | ck_step ) ;
} else {
/* shift - direction */
ck_step = min ( ddrphy_hpstep ( - 1 * delay_ckoffset , phy_base ) , 127 ) ;
ck_step_all = ck_step ;
}
ddrphy_set_phy_lane_sel ( 0 , phy_base ) ;
ddrphy_maskwritel ( ck_step_all , MSK_DLLS_TRIM_CLK , phy_base + PHY_DLL_TRIM_CLK ) ;
}
static void ddrphy_set_dll_recalib ( int delay_qoffset , u32 recalib_cnt ,
u8 disable_recalib , u8 ctr_start_val ,
void __iomem * phy_base )
{
u8 dlls_trim_adrctrl_ma , incr_dly_adrctrl_ma ; /* qoffset_step and flag for inc/dec */
u32 recalib_all ; /* all fields of register dll_recalib */
/* Q-Offset */
if ( delay_qoffset > = 0 ) {
dlls_trim_adrctrl_ma = min ( ddrphy_hpstep ( delay_qoffset , phy_base ) , 63 ) ;
incr_dly_adrctrl_ma = 0x1 ;
} else {
dlls_trim_adrctrl_ma = min ( ddrphy_hpstep ( - 1 * delay_qoffset , phy_base ) , 63 ) ;
incr_dly_adrctrl_ma = 0x0 ;
}
recalib_all = ( ( ctr_start_val & 0xf ) < < 28 ) |
( incr_dly_adrctrl_ma < < 27 ) |
( ( disable_recalib & 0x1 ) < < 26 ) |
( ( recalib_cnt & 0x3ffff ) < < 8 ) |
( dlls_trim_adrctrl_ma & 0x3f ) ;
/* write value for all bits other than bit[7:6] */
ddrphy_maskwritel ( recalib_all , ~ 0xc0 , phy_base + PHY_DLL_RECALIB ) ;
}
static void ddrphy_set_dll_adrctrl ( int delay_qoffset , u8 override_adrctrl ,
void __iomem * phy_base )
{
u8 dlls_trim_adrctrl , incr_dly_adrctrl ; /* qoffset_step for clock */
u32 adrctrl_all ;
if ( delay_qoffset > = 0 ) {
dlls_trim_adrctrl = min ( ddrphy_hpstep ( delay_qoffset , phy_base ) , 63 ) ;
incr_dly_adrctrl = 0x1 ;
} else {
dlls_trim_adrctrl = min ( ddrphy_hpstep ( - delay_qoffset , phy_base ) , 63 ) ;
incr_dly_adrctrl = 0x0 ;
}
adrctrl_all = ( incr_dly_adrctrl < < 9 ) |
( ( override_adrctrl & 0x1 ) < < 8 ) |
dlls_trim_adrctrl ;
ddrphy_maskwritel ( adrctrl_all , 0x33f , phy_base + PHY_DLL_ADRCTRL ) ;
}
/* dio */
static int dio_adrctrl_0 [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] = {
{ 268 - 262 , 268 - 263 , 268 - 378 } , /* LD20 reference */
{ 268 - 262 , 268 - 263 , 268 - 378 } , /* LD20 TV */
{ 268 - 212 , 268 - 268 , 0 } , /* LD21 reference */
{ 268 - 212 , 268 - 268 , 0 } , /* LD21 TV */
} ;
static int dio_dlltrimclk_0 [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] = {
{ 268 , 268 , 268 } , /* LD20 reference */
{ 268 , 268 , 268 } , /* LD20 TV */
{ 268 , 268 + 252 , 0 } , /* LD21 reference */
{ 268 , 268 + 202 , 0 } , /* LD21 TV */
} ;
static int dio_dllrecalib_0 [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] = {
{ 268 - 378 , 268 - 263 , 268 - 378 } , /* LD20 reference */
{ 268 - 378 , 268 - 263 , 268 - 378 } , /* LD20 TV */
{ 268 - 212 , 268 - 536 , 0 } , /* LD21 reference */
{ 268 - 212 , 268 - 536 , 0 } , /* LD21 TV */
} ;
static u32 dio_phy_pad_ctrl [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] = {
{ 0x50B840B1 , 0x50B840B1 , 0x50B840B1 } , /* LD20 reference */
{ 0x50BB40B1 , 0x50BB40B1 , 0x50BB40B1 } , /* LD20 TV */
{ 0x50BB40B4 , 0x50B840B1 , 0x50BB40B1 } , /* LD21 reference */
{ 0x50BB40B4 , 0x50B840B1 , 0x50BB40B1 } , /* LD21 TV */
} ;
static u32 dio_scl_gate_timing [ DRAM_CH_NR ] = { 0x00000140 , 0x00000180 , 0x00000140 } ;
static int dio_op_dq_shift_val [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] [ 32 ] = {
{ /* LD20 reference */
{
2 , 1 , 0 , 1 , 2 , 1 , 1 , 1 , 2 , 1 , 1 , 2 , 1 , 1 , 1 , 1 ,
1 , 2 , 1 , 1 , 1 , 2 , 1 , 1 , 2 , 2 , 0 , 1 , 1 , 2 , 2 , 1 ,
} ,
{
1 , 1 , 0 , 1 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 2 , 1 , 2 , 1 ,
} ,
{
2 , 2 , 0 , 2 , 1 , 1 , 2 , 1 , 1 , 1 , 0 , 1 , 1 , - 1 , 1 , 1 ,
2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 2 , 2 , 1 , 2 ,
} ,
} ,
{ /* LD20 TV */
{
2 , 1 , 0 , 1 , 2 , 1 , 1 , 1 , 2 , 1 , 1 , 2 , 1 , 1 , 1 , 1 ,
1 , 2 , 1 , 1 , 1 , 2 , 1 , 1 , 2 , 2 , 0 , 1 , 1 , 2 , 2 , 1 ,
} ,
{
1 , 1 , 0 , 1 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 2 , 1 , 2 , 1 ,
} ,
{
2 , 2 , 0 , 2 , 1 , 1 , 2 , 1 , 1 , 1 , 0 , 1 , 1 , - 1 , 1 , 1 ,
2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 2 , 2 , 1 , 2 ,
} ,
} ,
{ /* LD21 reference */
{
1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 2 ,
1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1 ,
} ,
{ 1 , 0 , 2 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 ,
1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 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 , 0 , 0 , 0 ,
} ,
} ,
{ /* LD21 TV */
{
1 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 0 , 2 ,
1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1 ,
} ,
{ 1 , 0 , 2 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 ,
1 , 0 , 1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 , 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 , 0 , 0 , 0 ,
} ,
} ,
} ;
static int dio_ip_dq_shift_val [ DRAM_BOARD_NR ] [ DRAM_CH_NR ] [ 32 ] = {
{ /* LD20 reference */
{
3 , 3 , 3 , 2 , 3 , 2 , 0 , 2 , 2 , 3 , 3 , 1 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 0 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 0 , 2 , 2 ,
} ,
{
2 , 2 , 1 , 1 , - 1 , 1 , 1 , 1 , 2 , 0 , 2 , 2 , 2 , 1 , 0 , 2 ,
2 , 1 , 2 , 1 , 0 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
} ,
{
2 , 2 , 3 , 2 , 1 , 2 , 2 , 2 , 2 , 3 , 4 , 2 , 3 , 4 , 3 , 3 ,
2 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 1 ,
} ,
} ,
{ /* LD20 TV */
{
3 , 3 , 3 , 2 , 3 , 2 , 0 , 2 , 2 , 3 , 3 , 1 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 0 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 0 , 2 , 2 ,
} ,
{
2 , 2 , 1 , 1 , - 1 , 1 , 1 , 1 , 2 , 0 , 2 , 2 , 2 , 1 , 0 , 2 ,
2 , 1 , 2 , 1 , 0 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
} ,
{
2 , 2 , 3 , 2 , 1 , 2 , 2 , 2 , 2 , 3 , 4 , 2 , 3 , 4 , 3 , 3 ,
2 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 1 ,
} ,
} ,
{ /* LD21 reference */
{
2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 2 , 2 , 2 , 2 , 2 ,
2 , 1 , 2 , 2 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 1 , 2 , 2 , 2 ,
} ,
{
3 , 4 , 4 , 1 , 0 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 3 , 2 ,
1 , 0 , 2 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 1 ,
} ,
{
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 , 0 ,
} ,
} ,
{ /* LD21 TV */
{
2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 2 , 2 , 2 , 2 , 2 ,
2 , 1 , 2 , 2 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 1 , 2 , 2 , 2 ,
} ,
{
3 , 4 , 4 , 1 , 0 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 3 , 2 ,
1 , 0 , 2 , 1 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 1 , 1 , 0 , 1 ,
} ,
{
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 , 0 ,
} ,
} ,
} ;
/* umc */
/* umc */
static u32 umc_initctla [ DRAM_FREQ_NR ] = { 0x71016D11 } ;
static u32 umc_initctla [ DRAM_FREQ_NR ] = { 0x71016D11 } ;
static u32 umc_initctlb [ DRAM_FREQ_NR ] = { 0x07E390AC } ;
static u32 umc_initctlb [ DRAM_FREQ_NR ] = { 0x07E390AC } ;
@ -37,15 +300,24 @@ static u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
static u32 umc_drmmr0 [ DRAM_FREQ_NR ] = { 0x00000114 } ;
static u32 umc_drmmr0 [ DRAM_FREQ_NR ] = { 0x00000114 } ;
static u32 umc_drmmr2 [ DRAM_FREQ_NR ] = { 0x000002a0 } ;
static u32 umc_drmmr2 [ DRAM_FREQ_NR ] = { 0x000002a0 } ;
static u32 umc_memconf0a [ DRAM_FREQ_NR ] = { 0x00000801 } ;
static u32 umc_memconf0a [ DRAM_FREQ_NR ] [ DRAM_SZ_NR ] = {
static u32 umc_memconf0b [ DRAM_FREQ_NR ] = { 0x00000130 } ;
/* 256MB 512MB */
static u32 umc_memconfch [ DRAM_FREQ_NR ] = { 0x00033803 } ;
{ 0x00000601 , 0x00000801 } , /* 1866 MHz */
} ;
static u32 umc_memconf0b [ DRAM_FREQ_NR ] [ DRAM_SZ_NR ] = {
/* 256MB 512MB */
{ 0x00000120 , 0x00000130 } , /* 1866 MHz */
} ;
static u32 umc_memconfch [ DRAM_FREQ_NR ] [ DRAM_SZ_NR ] = {
/* 256MB 512MB */
{ 0x00033603 , 0x00033803 } , /* 1866 MHz */
} ;
static u32 umc_cmdctla [ DRAM_FREQ_NR ] = { 0x060D0D20 } ;
static u32 umc_cmdctla [ DRAM_FREQ_NR ] = { 0x060D0D20 } ;
static u32 umc_cmdctlb [ DRAM_FREQ_NR ] = { 0x2D211C08 } ;
static u32 umc_cmdctlb [ DRAM_FREQ_NR ] = { 0x2D211C08 } ;
static u32 umc_cmdctlc [ DRAM_FREQ_NR ] = { 0x00150C04 } ;
static u32 umc_cmdctlc [ DRAM_FREQ_NR ] = { 0x00150C04 } ;
static u32 umc_cmdctle [ DRAM_FREQ_NR ] [ DRAM_SZ_NR ] = {
static u32 umc_cmdctle [ DRAM_FREQ_NR ] [ DRAM_SZ_NR ] = {
{ 0x0049071D , 0x0078071D } ,
/* 256MB 512MB */
{ 0x0049071D , 0x0078071D } , /* 1866 MHz */
} ;
} ;
static u32 umc_rdatactl_d0 [ DRAM_FREQ_NR ] = { 0x00000610 } ;
static u32 umc_rdatactl_d0 [ DRAM_FREQ_NR ] = { 0x00000610 } ;
@ -61,12 +333,22 @@ static u32 umc_directbusctrla[DRAM_CH_NR] = {
0x00000000 , 0x00000001 , 0x00000001
0x00000000 , 0x00000001 , 0x00000001
} ;
} ;
/* polling function for PHY Init Complete */
static void ddrphy_init_complete ( void __iomem * dc_base )
{
/* Wait for PHY Init Complete */
while ( ! ( readl ( dc_base + UMC_DFISTCTLC ) & BIT ( 0 ) ) )
cpu_relax ( ) ;
}
/* DDR PHY */
/* DDR PHY */
static void ddrphy_init ( void __iomem * phy_base , enum dram_freq freq )
static void ddrphy_init ( void __iomem * phy_base , void __iomem * dc_base ,
enum dram_freq freq , enum dram_board board , int ch )
{
{
writel ( 0x00000001 , phy_base + PHY_UNIQUIFY_TSMC_IO_1 ) ;
writel ( 0x0C001 001 , phy_base + PHY_UNIQUIFY_TSMC_IO_1 ) ;
while ( ( readl ( phy_base + PHY_UNIQUIFY_TSMC_IO_1 ) & BIT ( 1 ) ) )
while ( ! ( readl ( phy_base + PHY_UNIQUIFY_TSMC_IO_1 ) & BIT ( 1 ) ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x0C001000 , phy_base + PHY_UNIQUIFY_TSMC_IO_1 ) ;
writel ( 0x00000000 , phy_base + PHY_DLL_INCR_TRIM_3 ) ;
writel ( 0x00000000 , phy_base + PHY_DLL_INCR_TRIM_3 ) ;
writel ( 0x00000000 , phy_base + PHY_DLL_INCR_TRIM_1 ) ;
writel ( 0x00000000 , phy_base + PHY_DLL_INCR_TRIM_1 ) ;
@ -84,14 +366,14 @@ static void ddrphy_init(void __iomem *phy_base, enum dram_freq freq)
writel ( 0x0000000a , phy_base + PHY_DLL_TRIM_3 ) ;
writel ( 0x0000000a , phy_base + PHY_DLL_TRIM_3 ) ;
writel ( 0x00000001 , phy_base + PHY_SCL_WINDOW_TRIM ) ;
writel ( 0x00000001 , phy_base + PHY_SCL_WINDOW_TRIM ) ;
writel ( 0x00000000 , phy_base + PHY_UNQ_ANALOG_DLL_1 ) ;
writel ( 0x00000000 , phy_base + PHY_UNQ_ANALOG_DLL_1 ) ;
writel ( 0x50bb40b1 , phy_base + PHY_PAD_CTRL ) ;
writel ( dio_phy_pad_ctrl [ board ] [ ch ] , phy_base + PHY_PAD_CTRL ) ;
writel ( 0x00000070 , phy_base + PHY_VREF_TRAINING ) ;
writel ( 0x00000070 , phy_base + PHY_VREF_TRAINING ) ;
writel ( 0x01000075 , phy_base + PHY_SCL_CONFIG_1 ) ;
writel ( 0x01000075 , phy_base + PHY_SCL_CONFIG_1 ) ;
writel ( 0x00000501 , phy_base + PHY_SCL_CONFIG_2 ) ;
writel ( 0x00000501 , phy_base + PHY_SCL_CONFIG_2 ) ;
writel ( 0x00000000 , phy_base + PHY_SCL_CONFIG_3 ) ;
writel ( 0x00000000 , phy_base + PHY_SCL_CONFIG_3 ) ;
writel ( 0x000261c0 , phy_base + PHY_DYNAMIC_WRITE_BIT_LVL ) ;
writel ( 0x000261c0 , phy_base + PHY_DYNAMIC_WRITE_BIT_LVL ) ;
writel ( 0x00000000 , phy_base + PHY_SCL_CONFIG_4 ) ;
writel ( 0x00000000 , phy_base + PHY_SCL_CONFIG_4 ) ;
writel ( 0x000000a0 , phy_base + PHY_SCL_GATE_TIMING ) ;
writel ( dio_scl_gate_timing [ ch ] , phy_base + PHY_SCL_GATE_TIMING ) ;
writel ( 0x02a000a0 , phy_base + PHY_WRLVL_DYN_ODT ) ;
writel ( 0x02a000a0 , phy_base + PHY_WRLVL_DYN_ODT ) ;
writel ( 0x00840004 , phy_base + PHY_WRLVL_ON_OFF ) ;
writel ( 0x00840004 , phy_base + PHY_WRLVL_ON_OFF ) ;
writel ( 0x0000020d , phy_base + PHY_DLL_ADRCTRL ) ;
writel ( 0x0000020d , phy_base + PHY_DLL_ADRCTRL ) ;
@ -99,30 +381,96 @@ static void ddrphy_init(void __iomem *phy_base, enum dram_freq freq)
writel ( 0x0000008d , phy_base + PHY_DLL_TRIM_CLK ) ;
writel ( 0x0000008d , phy_base + PHY_DLL_TRIM_CLK ) ;
writel ( 0xa800100d , phy_base + PHY_DLL_RECALIB ) ;
writel ( 0xa800100d , phy_base + PHY_DLL_RECALIB ) ;
writel ( 0x00005076 , phy_base + PHY_SCL_LATENCY ) ;
writel ( 0x00005076 , phy_base + PHY_SCL_LATENCY ) ;
ddrphy_init_complete ( dc_base ) ;
ddrphy_set_dll_adrctrl ( dio_adrctrl_0 [ board ] [ ch ] , 0 , phy_base ) ;
ddrphy_set_dll_trim_clk ( dio_dlltrimclk_0 [ board ] [ ch ] , phy_base ) ;
ddrphy_set_dll_recalib ( dio_dllrecalib_0 [ board ] [ ch ] , 0x10 , 0 , 0xa ,
phy_base ) ;
}
static void ddrphy_shift_dq ( u32 reg_mask , u32 reg_addr , int shift_val ,
void __iomem * phy_base )
{
u32 reg_val ;
int dq_val ;
reg_val = ddrphy_maskreadl ( reg_mask , phy_base + reg_addr ) & 0x7f ;
dq_val = reg_val & 0x3f ;
if ( ( reg_val & 0x40 ) = = 0x00 )
dq_val = - 1 * dq_val ;
/* value shift*/
dq_val = dq_val + shift_val ;
if ( dq_val > = 0 )
reg_val = 0x40 + ( dq_val & 0x3f ) ;
else
reg_val = ( ( - 1 * dq_val ) & 0x3f ) ;
ddrphy_maskwritel ( reg_val , reg_mask , phy_base + reg_addr ) ;
}
}
static int ddrphy_training ( void __iomem * phy_base )
static void ddrphy_shift ( void __iomem * phy_base , enum dram_board board , int ch )
{
u32 dx , bit ;
/* set override = 1 */
ddrphy_maskwritel ( MSK_OVERRIDE , MSK_OVERRIDE ,
phy_base + PHY_OP_DQ_DM_DQS_BITWISE_TRIM ) ;
ddrphy_maskwritel ( MSK_OVERRIDE , MSK_OVERRIDE ,
phy_base + PHY_IP_DQ_DQS_BITWISE_TRIM ) ;
for ( dx = 0 ; dx < 4 ; dx + + ) {
/* set byte to PHY_LANE_SEL.phy_lane_sel= dx * (PHY_BITLVL_DLY_WIDTH+1) */
ddrphy_set_phy_lane_sel ( dx * ( PHY_BITLVL_DLY_WIDTH + 1 ) ,
phy_base ) ;
for ( bit = 0 ; bit < 8 ; bit + + ) {
ddrphy_set_bit_sel ( bit , phy_base ) ;
/* shift write reg value*/
ddrphy_shift_dq ( MSK_OP_DQ_DM_DQS_BITWISE_TRIM ,
PHY_OP_DQ_DM_DQS_BITWISE_TRIM ,
dio_op_dq_shift_val [ board ] [ ch ] [ dx * 8 + bit ] ,
phy_base ) ;
/* shift read reg value */
ddrphy_shift_dq ( MSK_IP_DQ_DQS_BITWISE_TRIM ,
PHY_IP_DQ_DQS_BITWISE_TRIM ,
dio_ip_dq_shift_val [ board ] [ ch ] [ dx * 8 + bit ] ,
phy_base ) ;
}
}
ddrphy_set_phy_lane_sel ( 0 , phy_base ) ;
ddrphy_set_bit_sel ( 0 , phy_base ) ;
}
static int ddrphy_training ( void __iomem * phy_base , enum dram_board board ,
int ch )
{
{
writel ( 0x0000000f , phy_base + PHY_WRLVL_AUTOINC_TRIM ) ;
writel ( 0x0000000f , phy_base + PHY_WRLVL_AUTOINC_TRIM ) ;
writel ( 0x00010000 , phy_base + PHY_DLL_TRIM_2 ) ;
writel ( 0x00010000 , phy_base + PHY_DLL_TRIM_2 ) ;
writel ( 0x50000000 , phy_base + PHY_SCL_START ) ;
writel ( 0x50000000 , phy_base + PHY_SCL_START ) ;
while ( ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) ) )
while ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x00000000 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
writel ( 0x00000000 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
writel ( 0xff00ff00 , phy_base + PHY_SCL_DATA_0 ) ;
writel ( 0xff00ff00 , phy_base + PHY_SCL_DATA_0 ) ;
writel ( 0xff00ff00 , phy_base + PHY_SCL_DATA_1 ) ;
writel ( 0xff00ff00 , phy_base + PHY_SCL_DATA_1 ) ;
writel ( 0x00080000 , phy_base + PHY_SCL_START_ADDR ) ;
writel ( 0xFBF8FFFF , phy_base + PHY_SCL_START_ADDR ) ;
writel ( 0x11000000 , phy_base + PHY_SCL_START ) ;
writel ( 0x11000000 , phy_base + PHY_SCL_START ) ;
while ( ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) ) )
while ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x00000000 , phy_base + PHY_SCL_START_ADDR ) ;
writel ( 0xFBF0FFFF , phy_base + PHY_SCL_START_ADDR ) ;
writel ( 0x30500000 , phy_base + PHY_SCL_START ) ;
writel ( 0x30500000 , phy_base + PHY_SCL_START ) ;
while ( ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) ) )
while ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x00000001 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
writel ( 0x00000001 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
@ -131,16 +479,22 @@ static int ddrphy_training(void __iomem *phy_base)
writel ( 0xf10e4a56 , phy_base + PHY_SCL_DATA_1 ) ;
writel ( 0xf10e4a56 , phy_base + PHY_SCL_DATA_1 ) ;
writel ( 0x11000000 , phy_base + PHY_SCL_START ) ;
writel ( 0x11000000 , phy_base + PHY_SCL_START ) ;
while ( ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) ) )
while ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x34000000 , phy_base + PHY_SCL_START ) ;
writel ( 0x34000000 , phy_base + PHY_SCL_START ) ;
while ( ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) ) )
while ( readl ( phy_base + PHY_SCL_START ) & BIT ( 28 ) )
cpu_relax ( ) ;
cpu_relax ( ) ;
writel ( 0x00000003 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
writel ( 0x00000003 , phy_base + PHY_DISABLE_GATING_FOR_SCL ) ;
writel ( 0x000261c0 , phy_base + PHY_DYNAMIC_WRITE_BIT_LVL ) ;
writel ( 0x00003270 , phy_base + PHY_DYNAMIC_BIT_LVL ) ;
writel ( 0x011BD0C4 , phy_base + PHY_DSCL_CNT ) ;
/* shift ip_dq, op_dq trim */
ddrphy_shift ( phy_base , board , ch ) ;
return 0 ;
return 0 ;
}
}
@ -164,10 +518,6 @@ static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
return - EINVAL ;
return - EINVAL ;
}
}
/* Wait for PHY Init Complete */
while ( ! ( readl ( dc_base + UMC_DFISTCTLC ) & BIT ( 0 ) ) )
cpu_relax ( ) ;
writel ( 0x00000001 , dc_base + UMC_DFICSOVRRD ) ;
writel ( 0x00000001 , dc_base + UMC_DFICSOVRRD ) ;
writel ( 0x00000000 , dc_base + UMC_DFITURNOFF ) ;
writel ( 0x00000000 , dc_base + UMC_DFITURNOFF ) ;
@ -180,9 +530,9 @@ static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
writel ( umc_drmmr2 [ freq ] , dc_base + UMC_DRMMR2 ) ;
writel ( umc_drmmr2 [ freq ] , dc_base + UMC_DRMMR2 ) ;
writel ( 0x00000000 , dc_base + UMC_DRMMR3 ) ;
writel ( 0x00000000 , dc_base + UMC_DRMMR3 ) ;
writel ( umc_memconf0a [ freq ] , dc_base + UMC_MEMCONF0A ) ;
writel ( umc_memconf0a [ freq ] [ size_e ] , dc_base + UMC_MEMCONF0A ) ;
writel ( umc_memconf0b [ freq ] , dc_base + UMC_MEMCONF0B ) ;
writel ( umc_memconf0b [ freq ] [ size_e ] , dc_base + UMC_MEMCONF0B ) ;
writel ( umc_memconfch [ freq ] , dc_base + UMC_MEMCONFCH ) ;
writel ( umc_memconfch [ freq ] [ size_e ] , dc_base + UMC_MEMCONFCH ) ;
writel ( 0x00000008 , dc_base + UMC_MEMMAPSET ) ;
writel ( 0x00000008 , dc_base + UMC_MEMMAPSET ) ;
writel ( umc_cmdctla [ freq ] , dc_base + UMC_CMDCTLA ) ;
writel ( umc_cmdctla [ freq ] , dc_base + UMC_CMDCTLA ) ;
@ -227,7 +577,8 @@ static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
}
}
static int umc_ch_init ( void __iomem * umc_ch_base , void __iomem * phy_ch_base ,
static int umc_ch_init ( void __iomem * umc_ch_base , void __iomem * phy_ch_base ,
enum dram_freq freq , unsigned long size , int ch )
enum dram_freq freq , enum dram_board board ,
unsigned long size , int ch )
{
{
void __iomem * dc_base = umc_ch_base + 0x00011000 ;
void __iomem * dc_base = umc_ch_base + 0x00011000 ;
void __iomem * phy_base = phy_ch_base ;
void __iomem * phy_base = phy_ch_base ;
@ -240,13 +591,13 @@ static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
writel ( UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST ,
writel ( UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST ,
dc_base + UMC_DIOCTLA ) ;
dc_base + UMC_DIOCTLA ) ;
ddrphy_init ( phy_base , freq ) ;
ddrphy_init ( phy_base , dc_base , freq , board , ch ) ;
ret = umc_dc_init ( dc_base , freq , size , ch ) ;
ret = umc_dc_init ( dc_base , freq , size , ch ) ;
if ( ret )
if ( ret )
return ret ;
return ret ;
ret = ddrphy_training ( phy_base ) ;
ret = ddrphy_training ( phy_base , board , ch ) ;
if ( ret )
if ( ret )
return ret ;
return ret ;
@ -274,6 +625,7 @@ int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
void __iomem * umc_ch_base = ( void __iomem * ) 0x5b800000 ;
void __iomem * umc_ch_base = ( void __iomem * ) 0x5b800000 ;
void __iomem * phy_ch_base = ( void __iomem * ) 0x6e200000 ;
void __iomem * phy_ch_base = ( void __iomem * ) 0x6e200000 ;
enum dram_freq freq ;
enum dram_freq freq ;
enum dram_board board ;
int ch , ret ;
int ch , ret ;
switch ( bd - > dram_freq ) {
switch ( bd - > dram_freq ) {
@ -285,11 +637,30 @@ int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
return - EINVAL ;
return - EINVAL ;
}
}
switch ( UNIPHIER_BD_BOARD_GET_TYPE ( bd - > flags ) ) {
case UNIPHIER_BD_BOARD_LD20_REF :
board = DRAM_BOARD_LD20_REF ;
break ;
case UNIPHIER_BD_BOARD_LD20_GLOBAL :
board = DRAM_BOARD_LD20_GLOBAL ;
break ;
case UNIPHIER_BD_BOARD_LD21_REF :
board = DRAM_BOARD_LD21_REF ;
break ;
case UNIPHIER_BD_BOARD_LD21_GLOBAL :
board = DRAM_BOARD_LD21_GLOBAL ;
break ;
default :
pr_err ( " unsupported board type %d \n " ,
UNIPHIER_BD_BOARD_GET_TYPE ( bd - > flags ) ) ;
return - EINVAL ;
}
for ( ch = 0 ; ch < bd - > dram_nr_ch ; ch + + ) {
for ( ch = 0 ; ch < bd - > dram_nr_ch ; ch + + ) {
unsigned long size = bd - > dram_ch [ ch ] . size ;
unsigned long size = bd - > dram_ch [ ch ] . size ;
unsigned int width = bd - > dram_ch [ ch ] . width ;
unsigned int width = bd - > dram_ch [ ch ] . width ;
ret = umc_ch_init ( umc_ch_base , phy_ch_base , freq ,
ret = umc_ch_init ( umc_ch_base , phy_ch_base , freq , board ,
size / ( width / 16 ) , ch ) ;
size / ( width / 16 ) , ch ) ;
if ( ret ) {
if ( ret ) {
pr_err ( " failed to initialize UMC ch%d \n " , ch ) ;
pr_err ( " failed to initialize UMC ch%d \n " , ch ) ;