#include <mach/ddr.h>
typedef uint32_t uint32;
+
+#define DDR3_DDR2_DLL_DISABLE_FREQ (125)
+#define DDR3_DDR2_ODT_DISABLE_FREQ (333)
+
#define PMU_BASE_ADDR RK30_PMU_BASE
#define SDRAMC_BASE_ADDR RK30_DDR_PCTL_BASE
#define DDR_PUBL_BASE RK30_DDR_PUBL_BASE
#define DDR3_BC4 (2)
#define DDR3_CL(n) (((((n)-4)&0x7)<<4)|((((n)-4)&0x8)>>1))
#define DDR3_WR(n) (((n)&0x7)<<9)
-#define DDR3_MR0_DLL_RESET (1<<8)
-#define DDR3_MR0_DLL_NOR (0<<8)
+#define DDR3_DLL_RESET (1<<8)
+#define DDR3_DLL_DISABLE (0<<8)
//mr1 for ddr3
#define DDR3_MR1_AL(n) (((n)&0x7)<<3)
#define DDR2_BL8 (3)
#define DDR2_CL(n) (((n)&0x7)<<4)
#define DDR2_WR(n) ((((n)-1)&0x7)<<9)
+#define DDR2_DLL_RESET (1<<8)
+#define DDR2_DLL_DISABLE (0<<8)
//EMR; //Extended Mode Register
#define DDR2_STR_FULL (0)
#define DRAMINIT (1<<6)
#define QSTRN (1<<7)
#define EYETRN (1<<8)
+#define ICPC (1<<16)
#define DLLBYP (1<<17)
#define CTLDINIT (1<<18)
#define CLRSR (1<<28)
((53<<16)|50) //DDR3_DEFAULT
};
-static __sramdata uint32_t mem_type; // 0:DDR2, 1:DDR3, 2:LPDDR
+__sramdata uint32_t mem_type; // 0:LPDDR, 1:DDR, 2:DDR2, 3:DDR3, 4:LPDDR2
static __sramdata uint32_t ddr_type; // used for ddr3 only
static __sramdata uint32_t capability; // one chip cs capability
/****************************************************************************
Internal sram us delay function
-Cpu highest frequency is 1.2 GHz
-1 cycle = 1/1.2 ns
-1 us = 1000 ns = 1000 * 1.2 cycles = 1200 cycles
+Cpu highest frequency is 1.6 GHz
+1 cycle = 1/1.6 ns
+1 us = 1000 ns = 1000 * 1.6 cycles = 1600 cycles
*****************************************************************************/
static __sramdata uint32_t loops_per_us;
-#define LPJ_100MHZ 499728UL
+#define LPJ_100MHZ 999456UL
/*static*/ void __sramlocalfunc delayus(uint32_t us)
{
barrier();
}
-static __sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words)
+__sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words)
{
uint32 i;
}
}
-static uint32 get_row(void)
+uint32 get_row(void)
{
uint32 i;
uint32 row;
return row;
}
-static uint32 get_bank(void)
+uint32 get_bank(void)
{
uint32 i;
return ddr_cfg_2_rbc[i].bank;
}
-static uint32 get_col(void)
+uint32 get_col(void)
{
uint32 i;
return ddr_cfg_2_rbc[i].col;
}
-static uint32_t get_datatraing_addr(void)
+uint32_t get_datatraing_addr(void)
{
uint32_t value=0;
uint32_t addr;
return value;
}
-static __sramfunc void idle_port(void)
-{
- pPMU_Reg->PMU_MISC_CON1 = (pPMU_Reg->PMU_MISC_CON1 & (~(0x1F<<1)))
- | idle_req_cpu_cfg
- | idle_req_peri_cfg
- | idle_req_gpu_cfg
- | idle_req_video_cfg
- | idle_req_vio_cfg;
- while(((pPMU_Reg->PMU_PWRDN_ST) & (idle_peri
- | idle_gpu
- | idle_cpu
- | idle_video
- | idle_vio)) != (idle_peri
- | idle_gpu
- | idle_cpu
- | idle_video
- | idle_vio));
-}
-
-
-static __sramfunc void deIdle_port(void)
-{
- pPMU_Reg->PMU_MISC_CON1 &= ~(idle_req_peri_cfg
- | idle_req_gpu_cfg
- | idle_req_cpu_cfg
- | idle_req_video_cfg
- | idle_req_vio_cfg);
-}
-
-static __sramlocalfunc void reset_dll(void)
+__sramlocalfunc void reset_dll(void)
{
pPHY_Reg->ACDLLCR &= ~0x40000000;
pPHY_Reg->DATX8[0].DXDLLCR &= ~0x40000000;
pPHY_Reg->DATX8[1].DXDLLCR &= ~0x40000000;
pPHY_Reg->DATX8[2].DXDLLCR &= ~0x40000000;
pPHY_Reg->DATX8[3].DXDLLCR &= ~0x40000000;
- delayus(10);
+ delayus(1);
pPHY_Reg->ACDLLCR |= 0x40000000;
pPHY_Reg->DATX8[0].DXDLLCR |= 0x40000000;
pPHY_Reg->DATX8[1].DXDLLCR |= 0x40000000;
pPHY_Reg->DATX8[2].DXDLLCR |= 0x40000000;
pPHY_Reg->DATX8[3].DXDLLCR |= 0x40000000;
- delayus(10);
+ delayus(1);
}
-static __sramfunc void move_to_Lowpower_state(void)
+
+__sramfunc void move_to_Lowpower_state(void)
{
volatile uint32 value;
}
}
-static __sramfunc void move_to_Access_state(void)
+__sramfunc void move_to_Access_state(void)
{
volatile uint32 value;
}
}
-static __sramfunc void move_to_Config_state(void)
+__sramfunc void move_to_Config_state(void)
{
volatile uint32 value;
}
//arg°üÀ¨bank_addrºÍcmd_addr
-static void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg)
+void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg)
{
uint32 i;
pDDR_Reg->MCMD = (start_cmd | (rank<<20) | arg | cmd);
//¶ÔtypeÀàÐ͵ÄDDRµÄ¼¸¸öcs½øÐÐDTT
//0 DTT³É¹¦
//!0 DTTʧ°Ü
-static uint32_t __sramlocalfunc data_training(void)
+uint32_t __sramlocalfunc data_training(void)
{
- uint32 i,value;
+ uint32 i,value,cs;
+ // disable auto refresh
value = pDDR_Reg->TREFI;
pDDR_Reg->TREFI = 0;
-
- pPHY_Reg->PIR = INIT | CLRSR;
- delayus(1);
- pPHY_Reg->PIR = INIT | QSTRN | LOCKBYP | ZCALBYP | CLRSR;
+ // clear DTDONE status
+ pPHY_Reg->PIR |= CLRSR;
+ cs = ((pPHY_Reg->PGCR>>18) & 0xF);
+ // trigger DTT
+ pPHY_Reg->PIR |= INIT | QSTRN | LOCKBYP | ZCALBYP | CLRSR | ICPC;
for (i = 0; i < 10; i ++) {;}
- while((pPHY_Reg->PGSR & (IDONE | DTDONE)) != (IDONE | DTDONE));
-
- pDDR_Reg->TREFI = value>>3;
- delayus(20);
+ // wait echo byte DTDONE
+ while((pPHY_Reg->DATX8[0].DXGSR[0] & cs) != cs);
+ while((pPHY_Reg->DATX8[1].DXGSR[0] & cs) != cs);
+ while((pPHY_Reg->DATX8[2].DXGSR[0] & cs) != cs);
+ while((pPHY_Reg->DATX8[3].DXGSR[0] & cs) != cs); //²âµ½1¸öCSµÄDTT×ʱ¼äÊÇ10.7us¡£×î¶à²¹2´ÎË¢ÐÂ
+ // send some auto refresh to complement the lost while DTT
+ if(cs > 1)
+ {
+ send_command(cs, REF_cmd, 0);
+ send_command(cs, REF_cmd, 0);
+ send_command(cs, REF_cmd, 0);
+ send_command(cs, REF_cmd, 0);
+ }
+ else
+ {
+ send_command(cs, REF_cmd, 0);
+ send_command(cs, REF_cmd, 0);
+ }
+ // resume auto refresh
pDDR_Reg->TREFI = value;
if(pPHY_Reg->PGSR & DTERR)
}
}
-static void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
+void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
{
if(freq<=150)
{
pPHY_Reg->DATX8[1].DXDLLCR |= 0x80000000;
pPHY_Reg->DATX8[2].DXDLLCR |= 0x80000000;
pPHY_Reg->DATX8[3].DXDLLCR |= 0x80000000;
+ pPHY_Reg->PIR |= DLLBYP;
}
else if(freq<=250)
{
pPHY_Reg->DATX8[1].DXDLLCR |= 0x80000000;
pPHY_Reg->DATX8[2].DXDLLCR |= 0x80000000;
pPHY_Reg->DATX8[3].DXDLLCR |= 0x80000000;
+ pPHY_Reg->PIR |= DLLBYP;
}
else
{
pPHY_Reg->DATX8[1].DXDLLCR &= ~0x80000000;
pPHY_Reg->DATX8[2].DXDLLCR &= ~0x80000000;
pPHY_Reg->DATX8[3].DXDLLCR &= ~0x80000000;
+ pPHY_Reg->PIR &= ~DLLBYP;
}
}
1 2 12.5 - 62.5 150MHz - 750MHz 12MHz 300MHz <= 600MHz
1 1 12.5 - 62.5 300MHz - 1500MHz 24MHz 600MHz <= 1200MHz
******************************************/
-static uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set)
+uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set)
{
uint32_t ret = 0;
int delay = 1000;
while (delay > 0)
{
delayus(1);
- //if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
- // break;
+ if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
+ break;
delay--;
}
return ret;
}
-static __sramfunc void ddr_adjust_config(uint32_t dram_type)
-{
- uint32 value;
- unsigned long save_sp;
- u32 i;
- volatile u32 n;
- volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET;
-
- //get data training address before idle port
- value = get_datatraing_addr();
-
- /** 1. Make sure there is no host access */
- flush_cache_all();
- outer_flush_all();
- flush_tlb_all();
- DDR_SAVE_SP(save_sp);
-
- for(i=0;i<16;i++)
- {
- n=temp[1024*i];
- barrier();
- }
- n= pDDR_Reg->SCFG.d32;
- n= pPHY_Reg->RIDR;
- n= pCRU_Reg->CRU_PLL_CON[0][0];
- n= pPMU_Reg->PMU_WAKEUP_CFG[0];
- n= *(volatile uint32_t *)SysSrv_DdrConf;
- dsb();
-
- //enter config state
- idle_port();
- move_to_Config_state();
-
- //extend capability for debug
- if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
- {
- pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
- }
-
- //set data training address
- pPHY_Reg->DTAR = value;
-
- //set auto power down idle
- pDDR_Reg->MCFG=(pDDR_Reg->MCFG&0xffff00ff)|(0x40<<8);
-
- //adjust DRV and ODT
- if(dram_type == DDR3)
- {
- pPHY_Reg->ZQ0CR[1] = 0x1B; //DS=40ohm,ODT=120ohm
- pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger
- }
- else if (dram_type == DDR2)
- {
- pPHY_Reg->ZQ0CR[1] = 0x4B; //DS=40ohm,ODT=75ohm
- pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger
- }
- else
- {
- pPHY_Reg->ZQ0CR[1] = 0x1B; //DS=40ohm,ODT=120ohm
- pPHY_Reg->ZQ0CR[0] |= (1<<30); //trigger
- }
- delayus(10);
- while(!(pPHY_Reg->ZQ0SR[0] & (0x1u<<31)));
- if(pPHY_Reg->ZQ0SR[0] & (0x1u<<30))
- {
- ddr_print("ZQCR error!\n");
- }
-
- //enter access state
- move_to_Access_state();
- deIdle_port();
-
- DDR_RESTORE_SP(save_sp);
-}
-
-static uint32_t ddr_get_parameter(uint32_t nMHz)
+uint32_t ddr_get_parameter(uint32_t nMHz)
{
uint32_t tmp;
uint32_t ret = 0;
cwl = ddr3_cl_cwl[ddr_type][tmp] & 0x0ff;
if(cl == 0)
ret = -4;
- p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_120;
+ if(nMHz <= DDR3_DDR2_ODT_DISABLE_FREQ)
+ {
+ p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_DIS;
+ }
+ else
+ {
+ p_ddr_timing->phy_timing.mr[1] = DDR3_DS_40 | DDR3_Rtt_Nom_120;
+ }
p_ddr_timing->phy_timing.mr[2] = DDR3_MR2_CWL(cwl) /* | DDR3_Rtt_WR_60 */;
p_ddr_timing->phy_timing.mr[3] = 0;
/**************************************************
#define LPDDR2_tFAW_GREAT_200MHz (50) //ns
#define LPDDR2_tFAW_LITTLE_200MHz (60) //ns
#define LPDDR2_tDLLK (2) //tCK
- #define LPDDR2_tDQSCK_MAX (5) //ns
- #define LPDDR2_tDQSCK_MIN (2) //ns
+ #define LPDDR2_tDQSCK_MAX (3) //tCK
+ #define LPDDR2_tDQSCK_MIN (0) //tCK
#define LPDDR2_tDQSS (1) //tCK
al = 0;
p_ddr_timing->phy_timing.dtpr0.b.tRC = (((LPDDR2_tRP_4_BANK+LPDDR2_tRAS)*nMHz+999)/1000)&0xF;
}
- p_ddr_timing->pctl_timing.trtw = (cl+((LPDDR2_tDQSCK_MIN*nMHz+(nMHz>>1)+999)/1000)-cwl);//LPDDR2_tRTW;
+ p_ddr_timing->pctl_timing.trtw = (cl+LPDDR2_tDQSCK_MAX+(bl/2)+1-cwl);//LPDDR2_tRTW;
p_ddr_timing->phy_timing.dtpr1.b.tRTW = 0;
/*
* RdToWr=RL+tDQSCK-WL
*/
- p_ddr_timing->noc_timing.b.RdToWr = ((cl+((LPDDR2_tDQSCK_MIN*nMHz+(nMHz>>1)+999)/1000)-cwl)&0x1F);
+ p_ddr_timing->noc_timing.b.RdToWr = ((cl+LPDDR2_tDQSCK_MAX+1-cwl)&0x1F);
p_ddr_timing->pctl_timing.tal = al;
p_ddr_timing->pctl_timing.tcl = cl;
p_ddr_timing->pctl_timing.tcwl = cwl;
/*
* tDQSCKmax,5.5ns
*/
- tmp = ((LPDDR2_tDQSCK_MAX*nMHz+(nMHz>>1)+999)/1000);
- p_ddr_timing->phy_timing.dtpr1.b.tDQSCKmax = 3;
+ p_ddr_timing->phy_timing.dtpr1.b.tDQSCKmax = LPDDR2_tDQSCK_MAX;
/*
* tDQSCKmin,2.5ns
*/
- tmp = ((LPDDR2_tDQSCK_MAX*nMHz+(nMHz>>1))/1000);
- p_ddr_timing->phy_timing.dtpr1.b.tDQSCK = 2;
+ p_ddr_timing->phy_timing.dtpr1.b.tDQSCK = LPDDR2_tDQSCK_MIN;
/*
* tRTODT, 0:ODT may be turned on immediately after read post-amble
* 1:ODT may not be turned on until one clock after the read post-amble
cl = 7;
}
cwl = cl -1;
- p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_75;
+ if(nMHz <= DDR3_DDR2_ODT_DISABLE_FREQ)
+ {
+ p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_DIS;
+ }
+ else
+ {
+ p_ddr_timing->phy_timing.mr[1] = DDR2_STR_REDUCE | DDR2_Rtt_Nom_75;
+ }
p_ddr_timing->phy_timing.mr[2] = 0;
p_ddr_timing->phy_timing.mr[3] = 0;
/**************************************************
return ret;
}
-static uint32_t __sramlocalfunc ddr_update_timing(void)
+uint32_t __sramlocalfunc ddr_update_timing(void)
{
uint32_t i;
DDR_TIMING_T *p_ddr_timing=&ddr_timing;
}
i = ((pPHY_Reg->DTPR[1] >> 27) & 0x7) - ((pPHY_Reg->DTPR[1] >> 24) & 0x7);
pPHY_Reg->DSGCR = (pPHY_Reg->DSGCR & (~(0x3F<<5))) | (i<<5) | (i<<8); //tDQSCKmax-tDQSCK
- pDDR_Reg->DFITRDDATAEN = pDDR_Reg->TCL;
+ pDDR_Reg->DFITRDDATAEN = pDDR_Reg->TCL-1;
pDDR_Reg->DFITPHYWRLAT = pDDR_Reg->TCWL;
}
else if(mem_type == DDR2)
return 0;
}
-static uint32_t __sramlocalfunc ddr_update_mr(void)
+uint32_t __sramlocalfunc ddr_update_mr(void)
{
DDR_TIMING_T *p_ddr_timing=&ddr_timing;
+ uint32_t cs;
+ cs = ((pPHY_Reg->PGCR>>18) & 0xF);
copy((uint32_t *)&(pPHY_Reg->MR[0]), (uint32_t*)&(p_ddr_timing->phy_timing.mr[0]), 4);
- if(mem_type == DDR3)
+ if((mem_type == DDR3) || (mem_type == DDR2))
{
- send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[0]))|(0X1<<8)));
- delayus(100);
- send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
- send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1])));
- send_command(3, MRS_cmd, bank_addr(0x2) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2])));
+ if(ddr_freq>DDR3_DDR2_DLL_DISABLE_FREQ)
+ {
+ if(pPHY_Reg->MR[1] & DDR3_DLL_DISABLE) // off -> on
+ {
+ send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1]))); //DLL enable
+ send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[0]))| DDR3_DLL_RESET)); //DLL reset
+ delayus(2); //at least 200 DDR cycle
+ send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
+ }
+ else // on -> on
+ {
+ send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1])));
+ send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
+ }
+ }
+ else
+ {
+ pPHY_Reg->MR[1] = (((uint8_t)(p_ddr_timing->phy_timing.mr[1])) | DDR3_DLL_DISABLE);
+ send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr(((uint8_t)(p_ddr_timing->phy_timing.mr[1])) | DDR3_DLL_DISABLE)); //DLL disable
+ send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
+ }
+ send_command(cs, MRS_cmd, bank_addr(0x2) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2])));
}
else if(mem_type == LPDDR2)
{
- send_command(3, MRS_cmd, lpddr2_ma(0x1) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[1])));
- send_command(3, MRS_cmd, lpddr2_ma(0x2) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[2])));
- send_command(3, MRS_cmd, lpddr2_ma(0x3) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[3])));
+ send_command(cs, MRS_cmd, lpddr2_ma(0x1) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[1])));
+ send_command(cs, MRS_cmd, lpddr2_ma(0x2) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[2])));
+ send_command(cs, MRS_cmd, lpddr2_ma(0x3) | lpddr2_op((uint8_t)(p_ddr_timing->phy_timing.mr[3])));
}
- else if(mem_type == DDR2)
+ else //mDDR
{
- send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
- send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[1])));
+ send_command(cs, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
+ send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); //mr[2] is mDDR MR1
}
- else //if(mem_type == LPDDR)
+ return 0;
+}
+
+void __sramlocalfunc ddr_update_odt(void)
+{
+ uint32_t cs,tmp;
+
+ //adjust DRV and ODT
+ if((mem_type == DDR3) || (mem_type == DDR2))
+ {
+ if(ddr_freq <= DDR3_DDR2_ODT_DISABLE_FREQ)
+ {
+ pPHY_Reg->DATX8[0].DXGCR &= ~(0x3<<9); //dynamic RTT disable
+ pPHY_Reg->DATX8[1].DXGCR &= ~(0x3<<9);
+ pPHY_Reg->DATX8[2].DXGCR &= ~(0x3<<9);
+ pPHY_Reg->DATX8[3].DXGCR &= ~(0x3<<9);
+ }
+ else
+ {
+ pPHY_Reg->DATX8[0].DXGCR |= (0x3<<9); //dynamic RTT enable
+ pPHY_Reg->DATX8[1].DXGCR |= (0x3<<9);
+ pPHY_Reg->DATX8[2].DXGCR |= (0x3<<9);
+ pPHY_Reg->DATX8[3].DXGCR |= (0x3<<9);
+ }
+ }
+ else
+ {
+ pPHY_Reg->DATX8[0].DXGCR &= ~(0x3<<9); //dynamic RTT disable
+ pPHY_Reg->DATX8[1].DXGCR &= ~(0x3<<9);
+ pPHY_Reg->DATX8[2].DXGCR &= ~(0x3<<9);
+ pPHY_Reg->DATX8[3].DXGCR &= ~(0x3<<9);
+ }
+ tmp = (0x1<<28) | (0x2<<15) | (0x2<<10) | (0xb<<5) | 0xb; //DS=34ohm,ODT=171ohm
+ cs = ((pPHY_Reg->PGCR>>18) & 0xF);
+ if(cs > 1)
+ {
+ pPHY_Reg->ZQ1CR[0] = tmp;
+ }
+ pPHY_Reg->ZQ0CR[0] = tmp;
+}
+
+__sramfunc void ddr_adjust_config(uint32_t dram_type)
+{
+ uint32 value;
+ unsigned long save_sp;
+ u32 i;
+ volatile u32 n;
+ volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET;
+
+ //get data training address before idle port
+ value = get_datatraing_addr();
+
+ /** 1. Make sure there is no host access */
+ flush_cache_all();
+ outer_flush_all();
+ flush_tlb_all();
+ DDR_SAVE_SP(save_sp);
+
+ for(i=0;i<16;i++)
{
- send_command(3, MRS_cmd, bank_addr(0x0) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[0])));
- send_command(3, MRS_cmd, bank_addr(0x1) | cmd_addr((uint8_t)(p_ddr_timing->phy_timing.mr[2]))); //mr[2] is mDDR MR1
+ n=temp[1024*i];
+ barrier();
}
+ n= pDDR_Reg->SCFG.d32;
+ n= pPHY_Reg->RIDR;
+ n= pCRU_Reg->CRU_PLL_CON[0][0];
+ n= pPMU_Reg->PMU_WAKEUP_CFG[0];
+ n= *(volatile uint32_t *)SysSrv_DdrConf;
+ dsb();
- return 0;
+ //enter config state
+ move_to_Config_state();
+
+ //extend capability for debug
+ if(pGRF_Reg->GRF_SOC_CON[2] & (0x1<<1))
+ {
+ pGRF_Reg->GRF_SOC_CON[2] = rank_to_row15_en;
+ }
+
+ //set data training address
+ pPHY_Reg->DTAR = value;
+
+ //set auto power down idle
+ pDDR_Reg->MCFG=(pDDR_Reg->MCFG&0xffff00ff)|(0x40<<8);
+
+ ddr_update_odt();
+
+ //enter access state
+ move_to_Access_state();
+
+ DDR_RESTORE_SP(save_sp);
}
-static void __sramlocalfunc ddr_selfrefresh_enter(void)
+void __sramlocalfunc ddr_selfrefresh_enter(uint32 nMHz)
{
- idle_port();
+ uint32 cs;
+
+ move_to_Config_state();
+ pDDR_Reg->TZQCSI = 0;
+ if((nMHz<=DDR3_DDR2_DLL_DISABLE_FREQ) && ((mem_type == DDR3) || (mem_type == DDR2))) // DLL disable
+ {
+ cs = ((pPHY_Reg->PGCR>>18) & 0xF);
+ pPHY_Reg->MR[1] = (((uint8_t)(ddr_timing.phy_timing.mr[1])) | DDR3_DLL_DISABLE);
+ send_command(cs, MRS_cmd, bank_addr(0x1) | cmd_addr(((uint8_t)(ddr_timing.phy_timing.mr[1])) | DDR3_DLL_DISABLE));
+ }
move_to_Lowpower_state();
- //pPHY_Reg->ACDLLCR &= ~0x40000000;
- //pPHY_Reg->DATX8[0].DXDLLCR &= ~0x40000000;
- //pPHY_Reg->DATX8[1].DXDLLCR &= ~0x40000000;
- //pPHY_Reg->DATX8[2].DXDLLCR &= ~0x40000000;
- //pPHY_Reg->DATX8[3].DXDLLCR &= ~0x40000000; //reset DLL
- //delayus(1);
- //pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16)|(0x1<<2); //close DDR PHY clock
- //phy_dll_bypass_set(0); //dll bypass
+ phy_dll_bypass_set(0); //dll bypass
+ pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock
+ delayus(1);
}
-static void __sramlocalfunc ddr_selfrefresh_exit(void)
+void __sramlocalfunc ddr_selfrefresh_exit(void)
{
uint32 n;
- //pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16)|(0x0<<2); //open DDR PHY clock
- //delayus(1000);
- //pPHY_Reg->ACDLLCR |= 0x40000000;
- //pPHY_Reg->DATX8[0].DXDLLCR |= 0x40000000;
- //pPHY_Reg->DATX8[1].DXDLLCR |= 0x40000000;
- //pPHY_Reg->DATX8[2].DXDLLCR |= 0x40000000;
- //pPHY_Reg->DATX8[3].DXDLLCR |= 0x40000000; //de-reset DLL
- //delayus(10);
- //pPHY_Reg->PIR = INIT | ITMSRST | LOCKBYP | ZCALBYP | CLRSR; //reset ITM
-
+
+ pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock
+ dsb();
+ phy_dll_bypass_set(ddr_freq);
+ reset_dll();
+ //delayus(10); //wait DLL lock
+
move_to_Config_state();
ddr_update_timing();
ddr_update_mr();
+ ddr_update_odt();
n = data_training();
move_to_Access_state();
- deIdle_port();
if(n!=0)
{
- ddr_print("DTT failed!\n");
+ sram_printascii("DTT failed!\n");
}
}
unsigned long flags;
volatile unsigned int * temp=(volatile unsigned int *)SRAM_CODE_OFFSET;
unsigned long save_sp;
+ uint32_t regvalue = pCRU_Reg->CRU_PLL_CON[0][0];
+ uint32_t freq;
+
+ // freq = (Fin/NR)*NF/OD
+ if((pCRU_Reg->CRU_MODE_CON&3) == 1) // CPLL Normal mode
+ freq = 24 *((pCRU_Reg->CRU_PLL_CON[0][1]&0x1fff)+1) // NF = 2*(CLKF+1)
+ /((((regvalue>>8)&0x3f)+1) // NR = CLKR+1
+ *((regvalue&0xF)+1)); // OD = 2^CLKOD
+ else
+ freq = 24;
+
+ loops_per_us = LPJ_100MHZ*freq / 1000000;
ret=ddr_set_pll(nMHz,0);
ddr_get_parameter(ret);
dsb();
/** 2. ddr enter self-refresh mode or precharge power-down mode */
- ddr_selfrefresh_enter();
-
- phy_dll_bypass_set(0); //dll bypass
- dsb();
- pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock
- delayus(1);
+ ddr_selfrefresh_enter(ret);
/** 3. change frequence */
ddr_set_pll(ret,1);
ddr_freq = ret;
- pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock
- dsb();
- delayus(1000); //wait pll lock
- phy_dll_bypass_set(ret);
- dsb();
-
- reset_dll();
- dsb();
/** 5. Issues a Mode Exit command */
ddr_selfrefresh_exit();
dsb();
n= *(volatile uint32_t *)SysSrv_DdrConf;
dsb();
- //idle_port();
- move_to_Lowpower_state();
+ ddr_selfrefresh_enter(0);
- phy_dll_bypass_set(0); //dll bypass
- pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2); //disable DDR PHY clock
+ pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x0<<(1*4)); //PLL slow-mode
dsb();
- delayus(1);
- pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x0<<(1*4)); //PLL slow-mode
+ delayus(1);
+ pCRU_Reg->CRU_PLL_CON[1][3] = ((0x1<<1)<<16) | (0x1<<1); //PLL power-down
dsb();
delayus(1);
- pPHY_Reg->DSGCR = pPHY_Reg->DSGCR&(~((0x1<<28)|(0x1<<29)));
+ pPHY_Reg->DSGCR = pPHY_Reg->DSGCR&(~((0x1<<28)|(0x1<<29))); //CKOE
}
EXPORT_SYMBOL(ddr_suspend);
void __sramfunc ddr_resume(void)
{
- pPHY_Reg->DSGCR = pPHY_Reg->DSGCR|((0x1<<28)|(0x1<<29));
+ int delay=1000;
+ pPHY_Reg->DSGCR = pPHY_Reg->DSGCR|((0x1<<28)|(0x1<<29)); //CKOE
dsb();
- pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal
+ pCRU_Reg->CRU_PLL_CON[1][3] = ((0x1<<1)<<16) | (0x0<<1); //PLL no power-down
dsb();
- pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2); //enable DDR PHY clock
+ while (delay > 0)
+ {
+ delayus(1);
+ if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
+ break;
+ delay--;
+ }
+
+ pCRU_Reg->CRU_MODE_CON = (0x3<<((1*4) + 16)) | (0x1<<(1*4)); //PLL normal
dsb();
- delayus(10); //wait pll lock
- phy_dll_bypass_set(ddr_freq);
- reset_dll();
- move_to_Access_state();
- //deIdle_port();
+
+ ddr_selfrefresh_exit();
}
EXPORT_SYMBOL(ddr_resume);
int ddr_init(uint32_t dram_type, uint32_t freq)
{
volatile uint32_t value = 0;
- uint32_t cs;
+ uint32_t cs,die=1;
uint32_t gsr,dqstr;
- ddr_print("version 1.00 20120505 \n");
+ ddr_print("version 1.00 20120529 \n");
mem_type = pPHY_Reg->DCR.b.DDRMD;
ddr_type = dram_type;
switch(mem_type)
{
case DDR3:
+ die = 2; //there is two die DDR3 at least
ddr_print("DDR3 Device\n");
break;
case LPDDR2:
break;
}
//get capability per chip, not total size, used for calculate tRFC
- capability = ddr_get_cap()/cs;
+ capability = ddr_get_cap()/(cs*die);
ddr_print("%d CS, ROW=%d, Bank=%d, COL=%d, Total Capability=%dMB\n",
cs, \
get_row(), \