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); }
//***************************************************************************** // void mctl_self_refresh_exit() // Description: Exit from self refresh state to active state // // Arguments: // // Return Value: 1: Success 0: Fail //***************************************************************************** void mctl_self_refresh_exit(uint32 channel_num) { uint32 reg_val; uint32 ch_id; if(channel_num == 1) ch_id = 0x1000; else ch_id = 0x0; //set SLEEP command reg_val = 0x4; mctl_write_w(ch_id + SDR_SCTL, reg_val); //check whether in Low Power State while( (mctl_read_w(ch_id + SDR_SSTAT)&0x7) != 0x3 ) {}; }
int dram_power_save_process(void) { unsigned int reg_val; //mctl_deep_sleep_entry(); mctl_self_refresh_entry(0); //printk("enter self refresh\n"); //if(MCTL_CHANNEL_NUM == 2) if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_self_refresh_entry(1); } //8x8; dram = 19.7mA; sys = 157.8mA //ITM reset mctl_write_w(0 + SDR_PIR, 0x11); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) mctl_write_w(0x1000 + SDR_PIR, 0x11); //turn off SCLK reg_val = mctl_read_w(SDR_COM_CCR); reg_val &= ~(0x7<<0); mctl_write_w(SDR_COM_CCR, reg_val); //turn off SDRPLL reg_val = mctl_read_w(SDR_COM_CCR); reg_val |= (0x3<<3); mctl_write_w(SDR_COM_CCR, reg_val); //8x8; dram = 20.3mA; sys = 83.4mA //gate off DRAMC AHB clk reg_val = mctl_read_w(CCM_AHB1_GATE0_CTRL); reg_val &=~(0x1<<14); mctl_write_w(CCM_AHB1_GATE0_CTRL, reg_val); //gate off DRAMC MDFS clk reg_val = mctl_read_w(CCM_MDFS_CLK_CTRL); reg_val &= ~(0x1U<<31); mctl_write_w(CCM_MDFS_CLK_CTRL, reg_val); //8x8; dram = 20.7mA; sys = 80.3mA //turn off PLL5 // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val &= ~(0x1U<<31); // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // //PLL5 configuration update(validate PLL5) // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val |= 0x1U<<20; // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // while(mctl_read_w(CCM_PLL5_DDR_CTRL) & (0x1U<<20)); return 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); }
/* ********************************************************************************************************* * CHECK DDR READPIPE * * Description: check ddr readpipe; * * Arguments : none * * Returns : result, 0:fail, 1:success; * * Note : ********************************************************************************************************* */ __s32 DRAMC_scan_readpipe(void) { __u32 reg_val; //data training trigger reg_val = mctl_read_w(SDR_CCR); reg_val |= 0x1<<30; mctl_write_w(SDR_CCR, reg_val); //check whether data training process is end while(mctl_read_w(SDR_CCR) & (0x1<<30)) {}; //check data training result reg_val = mctl_read_w(SDR_CSR); if(reg_val & (0x1<<20)) { return -1; } return (0); }
/* ********************************************************************************************************* * DRAM CLOCK CONTROL * * Description: dram get clock * * Arguments : on dram clock output (0: disable, 1: enable) * * Returns : none * * Note : ********************************************************************************************************* */ void DRAMC_clock_output_en(__u32 on) { __u32 reg_val; #if defined(CONFIG_ARCH_SUN4I) __const __u32 reg = DRAM_CCM_SDRAM_CLK_REG; __const __u32 magic = 15; #elif defined(CONFIG_ARCH_SUN5I) __const __u32 reg = SDR_CR; __const __u32 magic = 16; #else #error Unsupported sunxi architecture. #endif reg_val = mctl_read_w(reg); if(on) reg_val |= 0x1 << magic; else reg_val &= ~(0x1 << magic); mctl_write_w(reg, reg_val); }
/* ********************************************************************************************************* * Description: Set autorefresh cycle * * Arguments : clock value in MHz unit * * Returns : none * * Note : ********************************************************************************************************* */ void DRAMC_set_autorefresh_cycle(__u32 clk) { __u32 reg_val; __u32 dram_size; __u32 tmp_val; dram_size = mctl_read_w(SDR_DCR); dram_size >>=3; dram_size &= 0x7; if(clk < 600) { if(dram_size<=0x2) tmp_val = (131*clk)>>10; else tmp_val = (336*clk)>>10; reg_val = tmp_val; tmp_val = (7987*clk)>>10; tmp_val = tmp_val*9 - 200; reg_val |= tmp_val<<8; reg_val |= 0x8<<24; mctl_write_w(SDR_DRR, reg_val); }
int dram_power_up_process(void) { unsigned int reg_val; boot_dram_para_t *dram_parameters = (boot_dram_para_t *)BOOT_STANDBY_DRAM_PARA_ADDR; // __dram_para_t parameters = { // 240, // 3, // 0x0fb, // 0, // 0x10e40800, // 0x1211, // 0x1A50, // 0, // 0x18, // 0, // 0, // 0x80000800, // 0x39a70140, // 0xa092e74c, // 0x2948c209, // 0x8944422c, // 0x30028480, // 0x2a3297, // 0x5034fa8, // 0x36353d8, // 0, // 0, // 0, // 0 // }; // // mctl_deep_sleep_exit(¶meters); //make sure to turn off pll5 // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val &= ~(0x1U<<31); // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // //config PLL5 DRAM CLOCK: PLL5 = (24*N*K)/M // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val &= ~((0x3<<0) | (0x3<<4) | (0x1F<<8)); // reg_val |= ((0x0<<0) | (0x1<<4)); //K = M = 2; // reg_val |= (((dram_parameters->dram_clk)/24-1)<<0x8);//N // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // //PLL5 enable // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val |= 0x1U<<31; // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // //PLL5 configuration update(validate PLL5) // reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); // reg_val |= 0x1U<<20; // mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); // // while(mctl_read_w(CCM_PLL5_DDR_CTRL) & (0x1U<<20)); // // while(!(mctl_read_w(CCM_PLL5_DDR_CTRL) & (0x1U<<28))); //8x8; dram = 20.5mA; sys = 80.3mA standby_timer_delay(10); //Setup mdfs clk = PLL6 600M / 3 = 200M reg_val = mctl_read_w(CCM_MDFS_CLK_CTRL); reg_val &= ~((0x3<<24) | (0x3<<16) | (0xf<<0)); reg_val |= (0x1u<<31) | (0x1<<24) | (0x0<<16) | (0x2<<0); mctl_write_w(CCM_MDFS_CLK_CTRL, reg_val); //turn on DRAMC AHB clk reg_val = mctl_read_w(CCM_AHB1_GATE0_CTRL); reg_val |= (0x1<<14); mctl_write_w(CCM_AHB1_GATE0_CTRL, reg_val); //8x8; dram = 20.5mA; sys = 83.1mA //turn on SDRPLL reg_val = mctl_read_w(SDR_COM_CCR); reg_val &= ~(0x3<<3); mctl_write_w(SDR_COM_CCR, reg_val); standby_timer_delay(10); //reset dll mctl_write_w(0 + SDR_ACDLLCR,0x80000000); mctl_write_w(0 + SDR_DX0DLLCR,0x80000000); mctl_write_w(0 + SDR_DX1DLLCR,0x80000000); mctl_write_w(0 + SDR_DX2DLLCR,0x80000000); mctl_write_w(0 + SDR_DX3DLLCR,0x80000000); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0x80000000); mctl_write_w(0x1000 + SDR_DX0DLLCR,0x80000000); mctl_write_w(0x1000 + SDR_DX1DLLCR,0x80000000); mctl_write_w(0x1000 + SDR_DX2DLLCR,0x80000000); mctl_write_w(0x1000 + SDR_DX3DLLCR,0x80000000); } standby_timer_delay(1); //enable dll mctl_write_w(0 + SDR_ACDLLCR,0x0); mctl_write_w(0 + SDR_DX0DLLCR,0x0); mctl_write_w(0 + SDR_DX1DLLCR,0x0); mctl_write_w(0 + SDR_DX2DLLCR,0x0); mctl_write_w(0 + SDR_DX3DLLCR,0x0); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0x0); mctl_write_w(0x1000 + SDR_DX0DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX1DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX2DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX3DLLCR,0x0); } standby_timer_delay(1); //release reset dll mctl_write_w(0 + SDR_ACDLLCR,0x40000000); mctl_write_w(0 + SDR_DX0DLLCR,0x40000000); mctl_write_w(0 + SDR_DX1DLLCR,0x40000000); mctl_write_w(0 + SDR_DX2DLLCR,0x40000000); mctl_write_w(0 + SDR_DX3DLLCR,0x40000000); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX0DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX1DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX2DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX3DLLCR,0x40000000); } //ITM reset release mctl_write_w(0 + SDR_PIR, 0x01); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) mctl_write_w(0x1000 + SDR_PIR, 0x01); //8x8; dram = 20.3mA; sys = 102.9mA //turn on SCLK reg_val = mctl_read_w(SDR_COM_CCR); reg_val |= (0x5<<0); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) reg_val |= (0x7<<0); mctl_write_w(SDR_COM_CCR, reg_val); //8x8; dram = 20.3mA; sys = 156.4mA // mctl_power_up_process(); mctl_self_refresh_exit(0); //if(MCTL_CHANNEL_NUM == 2) if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_self_refresh_exit(1); } return 0; }
int dram_exit_self_refresh(void) { unsigned int reg_val; boot_dram_para_t *dram_parameters = (boot_dram_para_t *)BOOT_STANDBY_DRAM_PARA_ADDR; //reset dll mctl_write_w(0 + SDR_ACDLLCR,0x80000000); mctl_write_w(0 + SDR_DX0DLLCR,0x80000000); mctl_write_w(0 + SDR_DX1DLLCR,0x80000000); mctl_write_w(0 + SDR_DX2DLLCR,0x80000000); mctl_write_w(0 + SDR_DX3DLLCR,0x80000000); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0X1000 + SDR_ACDLLCR,0x80000000); mctl_write_w(0X1000 + SDR_DX0DLLCR,0x80000000); mctl_write_w(0X1000 + SDR_DX1DLLCR,0x80000000); mctl_write_w(0X1000 + SDR_DX2DLLCR,0x80000000); mctl_write_w(0X1000 + SDR_DX3DLLCR,0x80000000); } standby_timer_delay(0x200); //enable dll mctl_write_w(0 + SDR_ACDLLCR,0x0); mctl_write_w(0 + SDR_DX0DLLCR,0x0); mctl_write_w(0 + SDR_DX1DLLCR,0x0); mctl_write_w(0 + SDR_DX2DLLCR,0x0); mctl_write_w(0 + SDR_DX3DLLCR,0x0); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0x0); mctl_write_w(0x1000 + SDR_DX0DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX1DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX2DLLCR,0x0); mctl_write_w(0x1000 + SDR_DX3DLLCR,0x0); } standby_timer_delay(0x200); //release reset dll mctl_write_w(0 + SDR_ACDLLCR,0x40000000); mctl_write_w(0 + SDR_DX0DLLCR,0x40000000); mctl_write_w(0 + SDR_DX1DLLCR,0x40000000); mctl_write_w(0 + SDR_DX2DLLCR,0x40000000); mctl_write_w(0 + SDR_DX3DLLCR,0x40000000); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX0DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX1DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX2DLLCR,0x40000000); mctl_write_w(0x1000 + SDR_DX3DLLCR,0x40000000); } standby_timer_delay(0x200); // //config PLL5 DRAM CLOCK: PLL5 = (24*N*K)/M reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); reg_val &= ~((0x3<<0) | (0x3<<4) | (0x1F<<8)); reg_val |= ((0x0<<0) | (0x1<<4)); //K = 2 M = 1; reg_val |= ((dram_parameters->dram_clk/24-1)<<0x8);//N mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); //PLL5 enable reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); reg_val |= 0x1U<<31; mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); //PLL5 configuration update(validate PLL5) reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); reg_val |= 0x1U<<20; mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); while(mctl_read_w(CCM_PLL5_DDR_CTRL) & (0x1<<20)){ } while(!(mctl_read_w(CCM_PLL5_DDR_CTRL) & (0x1<<28))){ } mctl_self_refresh_exit(0); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_self_refresh_exit(1); } return 0; }
int dram_enter_self_refresh(void) { unsigned int reg_val; mctl_self_refresh_entry(0); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_self_refresh_entry(1); } //PLL5 disable reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); reg_val &= ~(0x1U<<31); mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); //PLL5 configuration update(validate PLL5) reg_val = mctl_read_w(CCM_PLL5_DDR_CTRL); reg_val |= 0x1U<<20; mctl_write_w(CCM_PLL5_DDR_CTRL, reg_val); mctl_write_w(0 + SDR_ACDLLCR,0xC0000000); mctl_write_w(0 + SDR_DX0DLLCR,0xC0000000); mctl_write_w(0 + SDR_DX1DLLCR,0xC0000000); mctl_write_w(0 + SDR_DX2DLLCR,0xC0000000); mctl_write_w(0 + SDR_DX3DLLCR,0xC0000000); if(mctl_read_w(SDR_COM_CR) & (0x1<<19)) { mctl_write_w(0x1000 + SDR_ACDLLCR,0xC0000000); mctl_write_w(0x1000 + SDR_DX0DLLCR,0xC0000000); mctl_write_w(0x1000 + SDR_DX1DLLCR,0xC0000000); mctl_write_w(0x1000 + SDR_DX2DLLCR,0xC0000000); mctl_write_w(0x1000 + SDR_DX3DLLCR,0xC0000000); } return 0; }
uint32 mctl_channel_init(uint32 ch_index) { uint32 reg_val; uint32 clkmhz; uint32 ch_id; if(ch_index == 1) ch_id = 0x1000; else ch_id = 0x0; //set PHY genereral configuration register reg_val = 0x01042202; mctl_write_w(ch_id + SDR_PGCR, reg_val); //set mode register mctl_write_w(ch_id + SDR_MR0, MCTL_MR0); mctl_write_w(ch_id + SDR_MR1, MCTL_MR1); mctl_write_w(ch_id + SDR_MR2, MCTL_MR2); mctl_write_w(ch_id + SDR_MR3, MCTL_MR3); //set PHY DDR mode if(MCTL_DDR_TYPE==2) //DDR2 reg_val = 0xa; else if(MCTL_DDR_TYPE==3) //DDR3 reg_val = 0xb; else if(MCTL_DDR_TYPE==5) //LPDDR reg_val = 0x8; else //LPDDR2 reg_val = 0xc; mctl_write_w(ch_id + SDR_DCR, reg_val); #ifndef FPGA_PLATFORM //set DDR system general configuration register reg_val = 0xd200013b; mctl_write_w(ch_id + SDR_DSGCR, reg_val); //set DATX8 common configuration register reg_val = 0x910; mctl_write_w(ch_id + SDR_DXCCR, reg_val); #endif //set COM sclk enable register reg_val = mctl_read_w(SDR_COM_CCR); reg_val |= (0x4 | (0x1<<ch_index)); mctl_write_w(SDR_COM_CCR, reg_val); //*********************************************** // check dram PHY status //*********************************************** while( (mctl_read_w(ch_id + SDR_PGSR)&0x3)!= 0x3 ) {}; //init external dram #ifdef FPGA_PLATFORM reg_val = 0x69; #else reg_val = 0xe9; #endif mctl_write_w(ch_id + SDR_PIR, reg_val); #ifndef SYSTEM_SIMULATION aw_delay(0x10); #endif //wait init done while( (mctl_read_w(ch_id + SDR_PGSR)&0x1) == 0x0) {}; //*********************************************** // set dram MCTL register //*********************************************** //move to configure state reg_val = 0x1; mctl_write_w(ch_id + SDR_SCTL, reg_val); while( (mctl_read_w(ch_id + SDR_SSTAT)&0x7) != 0x1 ) {}; //set memory timing regitsers clkmhz = MCTL_CLK; clkmhz = clkmhz/1000000; reg_val = clkmhz; mctl_write_w(ch_id + SDR_TOGCNT1U, reg_val); //1us reg_val = clkmhz/10; mctl_write_w(ch_id + SDR_TOGCNT100N, reg_val); //100ns mctl_write_w(ch_id + SDR_TREFI ,MCTL_TREFI); mctl_write_w(ch_id + SDR_TMRD ,MCTL_TMRD); mctl_write_w(ch_id + SDR_TRFC ,MCTL_TRFC); mctl_write_w(ch_id + SDR_TRP ,MCTL_TRP|(MCTL_TPREA<<16)); mctl_write_w(ch_id + SDR_TRTW ,MCTL_TRTW); mctl_write_w(ch_id + SDR_TAL ,MCTL_TAL); mctl_write_w(ch_id + SDR_TCL ,MCTL_TCL); mctl_write_w(ch_id + SDR_TCWL ,MCTL_TCWL); mctl_write_w(ch_id + SDR_TRAS ,MCTL_TRAS); mctl_write_w(ch_id + SDR_TRC ,MCTL_TRC); mctl_write_w(ch_id + SDR_TRCD ,MCTL_TRCD); mctl_write_w(ch_id + SDR_TRRD ,MCTL_TRRD); mctl_write_w(ch_id + SDR_TRTP ,MCTL_TRTP); mctl_write_w(ch_id + SDR_TWR ,MCTL_TWR); mctl_write_w(ch_id + SDR_TWTR ,MCTL_TWTR); mctl_write_w(ch_id + SDR_TEXSR ,MCTL_TEXSR); mctl_write_w(ch_id + SDR_TXP ,MCTL_TXP); mctl_write_w(ch_id + SDR_TXPDLL,MCTL_TXPDLL); mctl_write_w(ch_id + SDR_TZQCS ,MCTL_TZQCS); mctl_write_w(ch_id + SDR_TZQCSI,MCTL_TZQCSI); mctl_write_w(ch_id + SDR_TDQS ,MCTL_TDQS); mctl_write_w(ch_id + SDR_TCKSRE,MCTL_TCKSRE); mctl_write_w(ch_id + SDR_TCKSRX,MCTL_TCKSRX); mctl_write_w(ch_id + SDR_TCKE ,MCTL_TCKE); mctl_write_w(ch_id + SDR_TMOD ,MCTL_TMOD); mctl_write_w(ch_id + SDR_TRSTL ,MCTL_TRSTL); mctl_write_w(ch_id + SDR_TZQCL ,MCTL_TZQCL); mctl_write_w(ch_id + SDR_TMRR ,MCTL_TMRR); mctl_write_w(ch_id + SDR_TCKESR,MCTL_TCKESR); mctl_write_w(ch_id + SDR_TDPD ,MCTL_TDPD); //select 16/32-bits mode for MCTL reg_val = 0x0; if(MCTL_BUS_WIDTH==16) reg_val = 0x1; mctl_write_w(ch_id + SDR_PPCFG, reg_val); //set DFI timing registers mctl_write_w(ch_id + SDR_DFITPHYWRL, 1); reg_val = MCTL_TCWL - 1; mctl_write_w(ch_id + SDR_DFITPHYWRL, reg_val); reg_val = MCTL_TCL - 2; mctl_write_w(ch_id + SDR_DFITRDDEN, reg_val); mctl_write_w(ch_id + SDR_DFITPHYRDL, 15); reg_val = 0x5; mctl_write_w(ch_id + SDR_DFISTCFG0, reg_val); //configure memory related attributes of mctl if(MCTL_DDR_TYPE==2) //DDR2 reg_val = 0x71040; else if(MCTL_DDR_TYPE==3) //DDR3 reg_val = 0x71061; else if(MCTL_DDR_TYPE==5) //LPDDR reg_val = 0x971040; else //LPDDR2 reg_val = 0xd71040; mctl_write_w(ch_id + SDR_MCFG, reg_val); //DFI update configuration register reg_val = 0x2; mctl_write_w(ch_id + SDR_DFIUPDCFG, reg_val); reg_val = 0x80000000; mctl_write_w(ch_id + SDR_MCMD, reg_val); //move to access state reg_val = 0x2; mctl_write_w(ch_id + SDR_SCTL, reg_val); while( (mctl_read_w(ch_id + SDR_SSTAT)&0x7) != 0x3 ) {}; #ifndef SYSTEM_SIMULATION aw_delay(0x10); #endif return (1); }
uint32 mctl_dll_init(uint32 ch_index) { uint32 ch_id; if(ch_index == 1) ch_id = 0x1000; else ch_id = 0x0; //*********************************************** // set dram PHY register //*********************************************** //reset dll mctl_write_w(ch_id + SDR_ACDLLCR,0x80000000); mctl_write_w(ch_id + SDR_DX0DLLCR,0x80000000); mctl_write_w(ch_id + SDR_DX1DLLCR,0x80000000); mctl_write_w(ch_id + SDR_DX2DLLCR,0x80000000); mctl_write_w(ch_id + SDR_DX3DLLCR,0x80000000); #ifndef SYSTEM_SIMULATION aw_delay(0x10); #endif //enable dll mctl_write_w(ch_id + SDR_ACDLLCR,0x0); mctl_write_w(ch_id + SDR_DX0DLLCR,0x0); mctl_write_w(ch_id + SDR_DX1DLLCR,0x0); mctl_write_w(ch_id + SDR_DX2DLLCR,0x0); mctl_write_w(ch_id + SDR_DX3DLLCR,0x0); #ifndef SYSTEM_SIMULATION aw_delay(0x10); #endif //release reset dll mctl_write_w(ch_id + SDR_ACDLLCR,0x40000000); mctl_write_w(ch_id + SDR_DX0DLLCR,0x40000000); mctl_write_w(ch_id + SDR_DX1DLLCR,0x40000000); mctl_write_w(ch_id + SDR_DX2DLLCR,0x40000000); mctl_write_w(ch_id + SDR_DX3DLLCR,0x40000000); #ifndef SYSTEM_SIMULATION aw_delay(0x10); #endif return (1); }
__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(); }
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); }