Ejemplo n.º 1
0
/*
*********************************************************************************************************
*                                   DRAM INIT
*
* Description: dram init function
*
* Arguments  : para     dram config parameter
*
*
* Returns    : result
*
* Note       :
*********************************************************************************************************
*/
void mctl_ddr3_reset(void)
{
    __u32 reg_val;
#ifdef CONFIG_ARCH_SUN4I
    __u32 i=0;

    mctl_write_w(TIMER_CPU_CFG_REG, 0);
    reg_val = mctl_read_w(TIMER_CPU_CFG_REG);
    reg_val >>=6;
    reg_val &=0x3;
    if(reg_val == 0)
    {
#endif
        reg_val = mctl_read_w(SDR_CR);
        reg_val &= ~(0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
        standby_delay(0x100);
        reg_val = mctl_read_w(SDR_CR);
        reg_val |= (0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
#ifdef CONFIG_ARCH_SUN4I
    }
    else
    {
        reg_val = mctl_read_w(SDR_CR);
        reg_val |= (0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
        standby_delay(0x100);
        reg_val = mctl_read_w(SDR_CR);
        reg_val &= ~(0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
    }
#endif
}
Ejemplo n.º 2
0
/*
*********************************************************************************************************
*                                     TIMER INIT
*
* Description: initialise timer for standby.
*
* Arguments  : none
*
* Returns    : EPDK_TRUE/EPDK_FALSE;
*********************************************************************************************************
*/
__s32 standby_tmr_init(void)
{
    __s32       i;

    /* set timer register base */
    TmrReg = (__mem_tmr_reg_t *)SW_VA_TIMERC_IO_BASE;

    /* backup timer registers */
    TmrIntCtl   = TmrReg->IntCtl;
    Tmr0Ctl     = TmrReg->Tmr0Ctl;
    Tmr0IntVal  = TmrReg->Tmr0IntVal;
    Tmr0CntVal  = TmrReg->Tmr0CntVal;
    Tmr1Ctl     = TmrReg->Tmr1Ctl;
    Tmr1IntVal  = TmrReg->Tmr1IntVal;
    Tmr1CntVal  = TmrReg->Tmr1CntVal;

    /* config timer interrrupt */
    TmrReg->IntCtl   = 0;
    TmrReg->IntSta   = 1;

    /* config timer1 for process udelay */
    TmrReg->Tmr1Ctl  = 0;
    standby_delay(1000);
    TmrReg->Tmr1Ctl  = (1<<7)|(5<<4);
    standby_delay(1000);

    return 0;
}
Ejemplo n.º 3
0
/*
*********************************************************************************************************
*                                   DRAM INIT
*
* Description: dram init function
*
* Arguments  : para     dram config parameter
*
*
* Returns    : result
*
* Note       :
*********************************************************************************************************
*/
void mctl_ddr3_reset(void)
{
    __u32 reg_val;
    __u32 i=0;

    mctl_write_w(TIMER_CPU_CFG_REG, 0);
    reg_val = mctl_read_w(TIMER_CPU_CFG_REG);
    reg_val >>=6;
    reg_val &=0x3;
    if(reg_val == 0)
    {
        reg_val = mctl_read_w(SDR_CR);
        reg_val &= ~(0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
        standby_delay(0x100);
        reg_val = mctl_read_w(SDR_CR);
        reg_val |= (0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
    }
    else
    {
        reg_val = mctl_read_w(SDR_CR);
        reg_val |= (0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
        standby_delay(0x100);
        reg_val = mctl_read_w(SDR_CR);
        reg_val &= ~(0x1<<12);
        mctl_write_w(SDR_CR, reg_val);
    }
}
Ejemplo n.º 4
0
void DRAMC_enter_selfrefresh(void)
{
    __u32 reg_val;

    //	//disable all port
    //	for(i=0; i<31; i++)
    //	{
    //		DRAMC_hostport_on_off(i, 0x0);
    //	}
    //	for(i=0; i<8; i++)
    //	{
    //		mctl_write_w(SDR_HPCR + (i<<2), 0);
    //	}
    //
    //	for(i=16; i<28; i++)
    //	{
    //		mctl_write_w(SDR_HPCR + (i<<2), 0);
    //	}
    //
    //	mctl_write_w(SDR_HPCR + (29<<2), 0);
    //	mctl_write_w(SDR_HPCR + (31<<2), 0);
    /*
    //disable auto-fresh
    reg_val = mctl_read_w(SDR_DRR);
    reg_val |= 0x1U<<31;
    mctl_write_w(SDR_DRR, reg_val);
    */
    //issue prechage all command
    //	mctl_precharge_all();

    //disable auto-fresh			//by cpl 2013-5-6
    reg_val = mctl_read_w(SDR_DRR);
    reg_val |= 0x1U<<31;
    mctl_write_w(SDR_DRR, reg_val);


    //enter into self-refresh
    reg_val = mctl_read_w(SDR_DCR);
    reg_val &= ~(0x1fU<<27);
    reg_val |= 0x12U<<27;
    mctl_write_w(SDR_DCR, reg_val);
    while( mctl_read_w(SDR_DCR)& (0x1U<<31) );
    standby_delay(0x100);

    reg_val = mctl_read_w(SDR_CR);
    reg_val &= ~(0x3<<28);
    reg_val |= 0x2<<28;
    mctl_write_w(SDR_CR, reg_val);

    //dram pad odt hold
    mctl_write_w(SDR_DPCR, 0x16510001);

    while(!(mctl_read_w(SDR_DPCR) & 0x1));
    standby_delay(0x100);

}
Ejemplo n.º 5
0
void mctl_enable_dll0(void)
{
    __u32 i = 0;

    mctl_write_w(SDR_DLLCR0, mctl_read_w(SDR_DLLCR0) & ~0x40000000 | 0x80000000);
	standby_delay(0x100);

    mctl_write_w(SDR_DLLCR0, mctl_read_w(SDR_DLLCR0) & ~0xC0000000);
	standby_delay(0x1000);

    mctl_write_w(SDR_DLLCR0, mctl_read_w(SDR_DLLCR0) & ~0x80000000 | 0x40000000);
    standby_delay(0x1000);
}
Ejemplo n.º 6
0
void DRAMC_exit_selfrefresh(void)
{
	__u32 i;
	__u32 reg_val;

	//exit self-refresh state
	mctl_mode_exit();

	//issue a refresh command
	reg_val = mctl_read_w(SDR_DCR);
	reg_val &= ~(0x1fU<<27);
	reg_val |= 0x13U<<27;
	mctl_write_w(SDR_DCR, reg_val);
	while( mctl_read_w(SDR_DCR)& (0x1U<<31) );
    standby_delay(0x100);

	//enable auto-fresh
	reg_val = mctl_read_w(SDR_DRR);
	reg_val &= ~(0x1U<<31);
	mctl_write_w(SDR_DRR, reg_val);

	//enable all port
	for(i=0; i<31; i++)
	{
		DRAMC_hostport_on_off(i, 0x1);
	}
}
Ejemplo n.º 7
0
void DRAMC_enter_selfrefresh(void)
{
	__u32 i;
	__u32 reg_val;

	//disable all port
	for(i=0; i<31; i++)
	{
		DRAMC_hostport_on_off(i, 0x0);
	}
/*
	//disable auto-fresh
	reg_val = mctl_read_w(SDR_DRR);
	reg_val |= 0x1U<<31;
	mctl_write_w(SDR_DRR, reg_val);
*/
	//issue prechage all command
	mctl_precharge_all();

	//enter into self-refresh
	reg_val = mctl_read_w(SDR_DCR);
	reg_val &= ~(0x1fU<<27);
	reg_val |= 0x12U<<27;
	mctl_write_w(SDR_DCR, reg_val);
	while( mctl_read_w(SDR_DCR)& (0x1U<<31) );
	standby_delay(0x100);

	//dram pad odt hold
	mctl_write_w(SDR_DPCR, 0x1);
}
Ejemplo n.º 8
0
void standby_restore_env(struct sys_reg_t *restore_env)
{
    /*restore 24M and LDO*/
    aw_writel(restore_env->cmu_regs.aud_hosc,SW_CCM_AUDIO_HOSC_PLL_REG);
    //standby_delay(50);

    /*COREPLL to 24M*/
    aw_writel((aw_readl(SW_CCM_AHB_APB_CFG_REG)&BUS_CCLK_MASK)|BUS_CCLK_24M,SW_CCM_AHB_APB_CFG_REG);
    standby_delay(50);

    /*restore core power*/
#if EN_POWER_D
    twi_byte_rw(TWI_OP_WR,0x34,0x23,&data[0]);
    standby_twi_exit();
#endif

    /* restore cmu regs*/
    aw_writel(restore_env->cmu_regs.core_pll,SW_CCM_CORE_VE_PLL_REG);
    aw_writel(restore_env->cmu_regs.ddr_pll,SW_CCM_SDRAM_PLL_REG);
    aw_writel(restore_env->cmu_regs.bus_clk,SW_CCM_AHB_APB_CFG_REG);
#if MODIFY_AHB_APB_EN
    aw_writel(restore_env->cmu_regs.ahb_clk,SW_CCM_AHB_GATE_REG);
    aw_writel(restore_env->cmu_regs.apb_clk,SW_CCM_APB_GATE_REG);
#endif
}
Ejemplo n.º 9
0
void mctl_setup_dram_clock(__u32 clk)
{
    __u32 i;
    __u32 reg_val;

    //setup DRAM PLL
    reg_val = mctl_read_w(DRAM_CCM_SDRAM_PLL_REG);
    reg_val &= ~0x3;
    reg_val |= 0x1;                     //m factor
    reg_val &= ~(0x3<<4);
    reg_val |= 0x1<<4;                  //k factor
    reg_val &= ~(0x1f<<8);
    reg_val |= (standby_uldiv((__u64)clk, 24)&0x1f)<<8;      //n factor
    reg_val &= ~(0x3<<16);
    reg_val |= 0x1<<16;                 //p factor
    reg_val &= ~(0x1<<29);                                         //PLL on
    reg_val |= (__u32)0x1<<31;          //PLL En
    mctl_write_w(DRAM_CCM_SDRAM_PLL_REG, reg_val);
    standby_delay(0x100000);
    reg_val = mctl_read_w(DRAM_CCM_SDRAM_PLL_REG);
	reg_val |= 0x1<<29;
    mctl_write_w(DRAM_CCM_SDRAM_PLL_REG, reg_val);

    //reset GPS
    reg_val = mctl_read_w(DRAM_CCM_GPS_CLK_REG);
    reg_val &= ~0x3;
    mctl_write_w(DRAM_CCM_GPS_CLK_REG, reg_val);
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val |= (0x1<<26);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
    standby_delay(0x20);
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val &= ~(0x1<<26);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);

    //open DRAMC AHB clock
    //close it first
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val &= ~(0x1<<14);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
	standby_delay(0x1000);

    //then open it
    reg_val |= 0x1<<14;
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
	standby_delay(0x1000);
}
Ejemplo n.º 10
0
/*
*********************************************************************************************************
*                                   DRAM INIT
*
* Description: dram init function
*
* Arguments  : para     dram config parameter
*
*
* Returns    : result
*
* Note       :
*********************************************************************************************************
*/
void mctl_ddr3_reset(void)
{
	__u32 reg_val;

	reg_val = mctl_read_w(SDR_CR);
	reg_val &= ~(0x1<<12);
	mctl_write_w(SDR_CR, reg_val);
	standby_delay(0x100);
	reg_val = mctl_read_w(SDR_CR);
	reg_val |= (0x1<<12);
	mctl_write_w(SDR_CR, reg_val);
}
Ejemplo n.º 11
0
/*
 *********************************************************************************************************
 *                 DRAM ENTER SELF REFRESH
 *
 * Description: dram enter/exit self-refresh;
 *
 * Arguments  : none
 *
 * Returns    : none
 *
 * Note       :
 *********************************************************************************************************
 */
void mctl_precharge_all(void)
{
    __u32 reg_val;

    reg_val = mctl_read_w(SDR_DCR);
    reg_val &= ~(0x1fU<<27);
    reg_val |= 0x15U<<27;
    mctl_write_w(SDR_DCR, reg_val);

    //check whether command has been executed
    while( mctl_read_w(SDR_DCR)& (0x1U<<31) );
    standby_delay(0x100);
}
Ejemplo n.º 12
0
/*
*********************************************************************************************************
*                 DRAM POWER DOWN
*
* Description: enter/exit dram power down state
*
* Arguments  :
*
* Returns    : none;
*
* Note       :
*********************************************************************************************************
*/
void DRAMC_enter_power_down(void)
{
	__u32 i;
	__u32 reg_val;

	reg_val = mctl_read_w(SDR_DCR);
	reg_val &= ~(0x1fU<<27);
	reg_val |= 0x1eU<<27;
	mctl_write_w(SDR_DCR, reg_val);

	//check whether command has been executed
	while( mctl_read_w(SDR_DCR)& (0x1U<<31) );
	standby_delay(0x100);
}
Ejemplo n.º 13
0
void standby_enter_low(void)
{
    /*sdram self-refresh*/
    aw_writel(aw_readl(SW_DRAM_SDR_CTL_REG)|SDR_ENTER_SELFRFH,SW_DRAM_SDR_CTL_REG);
    while(!(aw_readl(SW_DRAM_SDR_CTL_REG)&SDR_SELFRFH_STATUS));

    /*gate off sdram*/
    aw_writel(aw_readl(SW_CCM_SDRAM_PLL_REG)&~SDR_CLOCK_GATE_EN,SW_CCM_SDRAM_PLL_REG);

    /*disable VE pll*/
    aw_writel(aw_readl(SW_CCM_CORE_VE_PLL_REG)&~(1<<15),SW_CCM_CORE_VE_PLL_REG);

    /*COREPLL to 24M*/
    aw_writel((aw_readl(SW_CCM_AHB_APB_CFG_REG)&BUS_CCLK_MASK)|BUS_CCLK_24M,SW_CCM_AHB_APB_CFG_REG);
    standby_delay(100);

    /*down core power*/
#if EN_POWER_D
    standby_twi_init(0);
    twi_byte_rw(TWI_OP_RD,0x34,0x23,&data[0]);
    data[2] = 0x0C;  	// 1V
    twi_byte_rw(TWI_OP_WR,0x34,0x23,&data[2]);
#endif

    /*COREPLL to 32K*/
    aw_writel((aw_readl(SW_CCM_AHB_APB_CFG_REG)&BUS_CCLK_MASK)|BUS_CCLK_32K,SW_CCM_AHB_APB_CFG_REG);
    standby_delay(50);

    /*disable HOSC and LDO*/
    aw_writel(aw_readl(SW_CCM_AUDIO_HOSC_PLL_REG)&~(1|(1<<15)),SW_CCM_AUDIO_HOSC_PLL_REG);

#if MODIFY_AHB_APB_EN
    aw_writel((1<<13)|(1<<16)|(1),SW_CCM_AHB_GATE_REG);
    aw_writel((1<<5)|1,SW_CCM_APB_GATE_REG);
#endif

}
Ejemplo n.º 14
0
void mctl_enable_dllx(void)
{
    __u32 i = 0;

    for(i=1; i<5; i++)
    {
        mctl_write_w(SDR_DLLCR0+(i<<2), mctl_read_w(SDR_DLLCR0+(i<<2)) & ~0x40000000 | 0x80000000);
    }

	standby_delay(0x100);

    for(i=1; i<5; i++)
    {
        mctl_write_w(SDR_DLLCR0+(i<<2), mctl_read_w(SDR_DLLCR0+(i<<2)) & ~0xC0000000);
    }

	standby_delay(0x1000);

    for(i=1; i<5; i++)
    {
        mctl_write_w(SDR_DLLCR0+(i<<2), mctl_read_w(SDR_DLLCR0+(i<<2)) & ~0x80000000 | 0x40000000);
    }
    standby_delay(0x1000);
}
Ejemplo n.º 15
0
/*
*********************************************************************************************************
*                           standby_tmr_mdlay
*
*Description: delay ms
*
*Arguments  : ms    time for delay;
*
*Return     : none
*
*Notes      :
*
*********************************************************************************************************
*/
void standby_tmr_mdlay(int ms)
{
    int     i;

    if(ms < 30){
        ms = 30;
    }

    TmrReg->Tmr1IntVal = ms;
    TmrReg->Tmr1Ctl   |= (1<<1);
    TmrReg->Tmr1Ctl   |= (1<<0);
    standby_delay(3000);
    while(TmrReg->Tmr1CntVal);

    return;
}
Ejemplo n.º 16
0
/*
*********************************************************************************************************
*                                     SYSTEM PWM ENTER STANDBY MODE
*
* Description: enter standby mode.
*
* Arguments  : none
*
* Returns    : none;
*********************************************************************************************************
*/
static void standby(void)
{
    /* gating off dram clock */
    standby_clk_dramgating(0);

    /* switch cpu clock to HOSC, and disable pll */
    standby_clk_core2hosc();
    standby_clk_plldisable();

    /* backup voltages */
    dcdc2 = standby_get_voltage(POWER_VOL_DCDC2);
    dcdc3 = standby_get_voltage(POWER_VOL_DCDC3);

    /* adjust voltage */
    standby_set_voltage(POWER_VOL_DCDC3, STANDBY_DCDC3_VOL);
    standby_set_voltage(POWER_VOL_DCDC2, STANDBY_DCDC2_VOL);

    /* set clock division cpu:axi:ahb:apb = 2:2:2:1 */
    standby_clk_getdiv(&clk_div);
    tmp_clk_div.axi_div = 0;
    tmp_clk_div.ahb_div = 0;
    tmp_clk_div.apb_div = 0;
    standby_clk_setdiv(&tmp_clk_div);
    /* swtich apb1 to losc */
    standby_clk_apb2losc();
    standby_mdelay(10);
    /* switch cpu to 32k */
    standby_clk_core2losc();
    #if(ALLOW_DISABLE_HOSC)
    // disable HOSC, and disable LDO
    standby_clk_hoscdisable();
    standby_clk_ldodisable();
    #endif

    /* cpu enter sleep, wait wakeup by interrupt */
    asm("WFI");

    #if(ALLOW_DISABLE_HOSC)
    /* enable LDO, enable HOSC */
    standby_clk_ldoenable();
    /* delay 1ms for power be stable */
    standby_delay(1);
    standby_clk_hoscenable();
    standby_delay(1);
    #endif
    /* swtich apb1 to hosc */
    standby_clk_apb2hosc();
    /* switch clock to hosc */
    standby_clk_core2hosc();
    /* restore clock division */
    standby_clk_setdiv(&clk_div);

    /* check system wakeup event */
    pm_info.standby_para.event = 0;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_EXTNMI)? 0:SUSPEND_WAKEUP_SRC_EXINT;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_USB0)? 0:SUSPEND_WAKEUP_SRC_USB;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_LRADC)? 0:SUSPEND_WAKEUP_SRC_KEY;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_IR0)? 0:SUSPEND_WAKEUP_SRC_IR;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_ALARM)? 0:SUSPEND_WAKEUP_SRC_ALARM;
    pm_info.standby_para.event |= standby_query_int(INT_SOURCE_TIMER0)? 0:SUSPEND_WAKEUP_SRC_TIMEOFF;

    /* restore voltage for exit standby */
    standby_set_voltage(POWER_VOL_DCDC2, dcdc2);
    standby_set_voltage(POWER_VOL_DCDC3, dcdc3);
    standby_mdelay(10);

    /* enable pll */
    standby_clk_pllenable();
    standby_mdelay(10);
    /* switch cpu clock to core pll */
    standby_clk_core2pll();
    standby_mdelay(10);

    /* gating on dram clock */
    standby_clk_dramgating(1);

    return;
}
Ejemplo n.º 17
0
void mctl_setup_dram_clock(__u32 clk)
{
    __u32 reg_val;
#if   defined(CONFIG_ARCH_SUN4I)
    const __u32 clocks = 0x1;
#elif defined(CONFIG_ARCH_SUN5I)
    const __u32 clocks = 0x3;
#else
#error Unsupported sunxi architecture.
#endif

    //setup DRAM PLL
    reg_val = mctl_read_w(DRAM_CCM_SDRAM_PLL_REG);
    reg_val &= ~0x3;
    reg_val |= 0x1;                     //m factor
    reg_val &= ~(0x3<<4);
    reg_val |= 0x1<<4;                  //k factor
    reg_val &= ~(0x1f<<8);
    reg_val |= (standby_uldiv((__u64)clk, 24)&0x1f)<<8;      //n factor
    reg_val &= ~(0x3<<16);
    reg_val |= 0x1<<16;                 //p factor
    reg_val &= ~(0x1<<29);                                         //PLL on
    reg_val |= (__u32)0x1<<31;          //PLL En
    mctl_write_w(DRAM_CCM_SDRAM_PLL_REG, reg_val);
    standby_delay(0x100000);
    reg_val = mctl_read_w(DRAM_CCM_SDRAM_PLL_REG);
	reg_val |= 0x1<<29;
    mctl_write_w(DRAM_CCM_SDRAM_PLL_REG, reg_val);

#if   defined(CONFIG_ARCH_SUN4I)
    //reset GPS
    reg_val = mctl_read_w(DRAM_CCM_GPS_CLK_REG);
    reg_val &= ~0x3;
    mctl_write_w(DRAM_CCM_GPS_CLK_REG, reg_val);
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val |= (0x1<<26);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
    standby_delay(0x20);
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val &= ~(0x1<<26);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
#elif defined(CONFIG_ARCH_SUN5I)
    //setup MBUS clock
    reg_val &= (0x1<<31)|(0x2<<24)|(0x1);
    mctl_write_w(DRAM_CCM_MUS_CLK_REG, reg_val);
#else
#error Unsupported sunxi architecture.
#endif

    //open DRAMC AHB clock ( & DLL register clock on sun5i )
    //close it first
    reg_val = mctl_read_w(DRAM_CCM_AHB_GATE_REG);
    reg_val &= ~(clocks<<14);
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
	standby_delay(0x1000);

    //then open it
    reg_val |= clocks<<14;
    mctl_write_w(DRAM_CCM_AHB_GATE_REG, reg_val);
	standby_delay(0x1000);
}
Ejemplo n.º 18
0
/*
*********************************************************************************************************
*                           mdelay
*
*Description: mdelay function
*
*Arguments  :
*
*Return     :
*
*Notes      :
*
*********************************************************************************************************
*/
void standby_mdelay(int ms)
{
    standby_delay(ms * cpu_ms_loopcnt);
}
Ejemplo n.º 19
0
__s32 DRAMC_init(__dram_para_t *para)
{
    __u32 i;
    __u32 reg_val;
    __s32 ret_val;

    //check input dram parameter structure
    if(!para)
    {
        //dram parameter is invalid
        return -1;
    }

    //setup DRAM relative clock
    mctl_setup_dram_clock(para->dram_clk);

    //reset external DRAM
    mctl_ddr3_reset();
    mctl_set_drive();

    //dram clock off
    DRAMC_clock_output_en(0);

    //select dram controller 1
    mctl_write_w(SDR_SCSR, 0x16237495);

    mctl_itm_disable();
    mctl_enable_dll0();

    //configure external DRAM
    reg_val = 0;
    if(para->dram_type == 3)
        reg_val |= 0x1;
    reg_val |= (para->dram_io_width>>3) <<1;

    if(para->dram_chip_density == 256)
        reg_val |= 0x0<<3;
    else if(para->dram_chip_density == 512)
        reg_val |= 0x1<<3;
    else if(para->dram_chip_density == 1024)
        reg_val |= 0x2<<3;
    else if(para->dram_chip_density == 2048)
        reg_val |= 0x3<<3;
    else if(para->dram_chip_density == 4096)
        reg_val |= 0x4<<3;
    else if(para->dram_chip_density == 8192)
        reg_val |= 0x5<<3;
    else
        reg_val |= 0x0<<3;
    reg_val |= ((para->dram_bus_width>>3) - 1)<<6;
    reg_val |= (para->dram_rank_num -1)<<10;
    reg_val |= 0x1<<12;
    reg_val |= ((0x1)&0x3)<<13;
    mctl_write_w(SDR_DCR, reg_val);

    //dram clock on
    DRAMC_clock_output_en(1);
	standby_delay(0x10);
    while(mctl_read_w(SDR_CCR) & (0x1U<<31)) {};

		mctl_enable_dllx();

		//set odt impendance divide ratio
		reg_val = mctl_read_w(SDR_ZQCR0);
		reg_val &= ~(0xff<<20);
		reg_val |= ((para->dram_zq)&0xff)<<20;
		mctl_write_w(SDR_ZQCR0, reg_val);

		//set I/O configure register
		reg_val = 0x00cc0000;
		reg_val |= (para->dram_odt_en)&0x3;
		reg_val |= ((para->dram_odt_en)&0x3)<<30;
		mctl_write_w(SDR_IOCR, reg_val);

		//set refresh period
    DRAMC_set_autorefresh_cycle(para->dram_clk);

    //set timing parameters
    mctl_write_w(SDR_TPR0, para->dram_tpr0);
    mctl_write_w(SDR_TPR1, para->dram_tpr1);
    mctl_write_w(SDR_TPR2, para->dram_tpr2);

    //set mode register
    if(para->dram_type==3)                  //ddr3
    {
        reg_val = 0x0;
        reg_val |= (para->dram_cas - 4)<<4;
        reg_val |= 0x5<<9;
    }
    else if(para->dram_type==2)             //ddr2
    {
        reg_val = 0x2;
        reg_val |= para->dram_cas<<4;
        reg_val |= 0x5<<9;
    }
    mctl_write_w(SDR_MR, reg_val);

    reg_val = 0x0;
    mctl_write_w(SDR_EMR, para->dram_emr1);
    reg_val = 0x0;
		mctl_write_w(SDR_EMR2, para->dram_emr2);
    reg_val = 0x0;
		mctl_write_w(SDR_EMR3, para->dram_emr3);

	//set DQS window mode
	reg_val = mctl_read_w(SDR_CCR);
	reg_val |= 0x1U<<14;
	reg_val &= ~(0x1U<<17);
	mctl_write_w(SDR_CCR, reg_val);

    //initial external DRAM
    reg_val = mctl_read_w(SDR_CCR);
    reg_val |= 0x1U<<31;
    mctl_write_w(SDR_CCR, reg_val);

    while(mctl_read_w(SDR_CCR) & (0x1U<<31)) {};

    //scan read pipe value
    mctl_itm_enable();
    ret_val = DRAMC_scan_readpipe();

    if(ret_val < 0)
    {
        return 0;
    }
    //configure all host port
    mctl_configure_hostport();

    return DRAMC_get_dram_size();
}