fix data training bug, add ODT disable frequency macro,
authorhecanyang <hcy@ubuntu-fs.(none)>
Tue, 29 May 2012 06:18:18 +0000 (14:18 +0800)
committerhecanyang <hcy@ubuntu-fs.(none)>
Tue, 29 May 2012 06:21:52 +0000 (14:21 +0800)
  and reduce change frequency period

arch/arm/mach-rk30/ddr.c
arch/arm/mach-rk30/pm.c

index 3404abcece4e0ab069267d10c7b90438f963c8b2..a7d82bdf120151a276cc2e1d0770d0ae7243c225 100755 (executable)
 #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
@@ -112,8 +116,8 @@ typedef uint32_t uint32;
 #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)
@@ -139,6 +143,8 @@ typedef uint32_t uint32;
 #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)
@@ -542,6 +548,7 @@ typedef volatile struct DDR_REG_Tag
 #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)
@@ -879,7 +886,7 @@ uint32_t __sramdata ddr3_tRC_tFAW[22]={
 
     ((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
 
@@ -892,13 +899,13 @@ static __sramdata uint32_t ddr_freq;
 
 /****************************************************************************
 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)
 {   
@@ -909,7 +916,7 @@ static __sramdata uint32_t loops_per_us;
         barrier();
 }
 
-static __sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words)
+__sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words)
 {
     uint32 i;
 
@@ -919,7 +926,7 @@ static __sramfunc void copy(uint32 *pDest, uint32 *pSrc, uint32 words)
     }
 }
 
-static uint32 get_row(void)
+uint32 get_row(void)
 {
     uint32 i;
     uint32 row;
@@ -933,7 +940,7 @@ static uint32 get_row(void)
     return row;
 }
 
-static uint32 get_bank(void)
+uint32 get_bank(void)
 {
     uint32 i;
 
@@ -941,7 +948,7 @@ static uint32 get_bank(void)
     return ddr_cfg_2_rbc[i].bank;
 }
 
-static uint32 get_col(void)
+uint32 get_col(void)
 {
     uint32 i;
 
@@ -949,7 +956,7 @@ static uint32 get_col(void)
     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;
@@ -987,51 +994,23 @@ static uint32_t get_datatraing_addr(void)
     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;
 
@@ -1061,7 +1040,7 @@ static __sramfunc void move_to_Lowpower_state(void)
     }
 }
 
-static __sramfunc void move_to_Access_state(void)
+__sramfunc void move_to_Access_state(void)
 {
     volatile uint32 value;
 
@@ -1093,7 +1072,7 @@ static __sramfunc void move_to_Access_state(void)
     }
 }
 
-static __sramfunc void move_to_Config_state(void)
+__sramfunc void move_to_Config_state(void)
 {
     volatile uint32 value;
 
@@ -1122,7 +1101,7 @@ static __sramfunc void move_to_Config_state(void)
 }
 
 //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);
@@ -1133,21 +1112,38 @@ static void __sramlocalfunc send_command(uint32 rank, uint32 cmd, uint32 arg)
 //¶Ô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)
@@ -1160,7 +1156,7 @@ static uint32_t __sramlocalfunc data_training(void)
     }
 }
 
-static void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
+void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
 {
     if(freq<=150)
     {
@@ -1170,6 +1166,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
         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)
     {
@@ -1179,6 +1176,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
         pPHY_Reg->DATX8[1].DXDLLCR |= 0x80000000;
         pPHY_Reg->DATX8[2].DXDLLCR |= 0x80000000;
         pPHY_Reg->DATX8[3].DXDLLCR |= 0x80000000;
+        pPHY_Reg->PIR |= DLLBYP;
     }
     else
     {
@@ -1188,6 +1186,7 @@ static void __sramlocalfunc phy_dll_bypass_set(uint32 freq)
         pPHY_Reg->DATX8[1].DXDLLCR &= ~0x80000000;
         pPHY_Reg->DATX8[2].DXDLLCR &= ~0x80000000;
         pPHY_Reg->DATX8[3].DXDLLCR &= ~0x80000000;
+        pPHY_Reg->PIR &= ~DLLBYP;
     }
 }
 
@@ -1202,7 +1201,7 @@ NR   NO     NF               Fout                       freq Step     finally us
 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;
@@ -1255,8 +1254,8 @@ static uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set)
         while (delay > 0) 
         {
            delayus(1);
-               //if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
-               //      break;
+               if (pGRF_Reg->GRF_SOC_STATUS0 & (0x1<<4))
+                       break;
                delay--;
        }
         
@@ -1270,82 +1269,7 @@ out:
     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;
@@ -1411,7 +1335,14 @@ static uint32_t ddr_get_parameter(uint32_t nMHz)
         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;
         /**************************************************
@@ -1708,8 +1639,8 @@ static uint32_t ddr_get_parameter(uint32_t nMHz)
         #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;
@@ -1830,12 +1761,12 @@ static uint32_t ddr_get_parameter(uint32_t nMHz)
             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;
@@ -1960,13 +1891,11 @@ static uint32_t ddr_get_parameter(uint32_t nMHz)
         /*
          * 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
@@ -2041,7 +1970,14 @@ static uint32_t ddr_get_parameter(uint32_t nMHz)
             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;
         /**************************************************
@@ -2552,7 +2488,7 @@ out:
     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;
@@ -2579,7 +2515,7 @@ static uint32_t __sramlocalfunc ddr_update_timing(void)
         }
         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)
@@ -2593,76 +2529,180 @@ static uint32_t __sramlocalfunc ddr_update_timing(void)
     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");
     }
 }
 
@@ -2674,6 +2714,18 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     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);
@@ -2698,25 +2750,12 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     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();     
@@ -2751,35 +2790,39 @@ void __sramfunc ddr_suspend(void)
     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);
 
@@ -2818,10 +2861,10 @@ EXPORT_SYMBOL(ddr_get_cap);
 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;
@@ -2829,6 +2872,7 @@ int ddr_init(uint32_t dram_type, uint32_t freq)
     switch(mem_type)
     {
         case DDR3:
+            die = 2;  //there is two die DDR3 at least
             ddr_print("DDR3 Device\n");
             break;
         case LPDDR2:
@@ -2859,7 +2903,7 @@ int ddr_init(uint32_t dram_type, uint32_t freq)
             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(), \
index 5e081fddcce330a30e7f1e6b3d14a9e7591b99ce..6ff619ed0560298fd0f3f8a06708a4c8a2287c15 100755 (executable)
@@ -82,25 +82,46 @@ static int inline calc_crc32(u32 addr, size_t len)
        return crc32_le(~0, (const unsigned char *)addr, len);
 }
 
+extern __sramdata uint32_t mem_type;
 static void __sramfunc ddr_testmode(void)
 {
        int32_t g_crc1, g_crc2;
        uint32_t nMHz;
        uint32_t n = 0;
+       uint32_t min,max;
        extern char _stext[], _etext[];
 
+
        if (ddr_debug == 1) {
+           switch(mem_type)
+           {
+               case 0:  //LPDDR
+               case 1:  //DDR
+                   max = 210;
+                   min = 100;
+                   break;
+               case 2:  //DDR2
+               case 4:  //LPDDR2
+                   max=410;
+                   min=100;
+                   break;
+               case 3:  //DDR3
+               default:
+                   max=500;
+                   min=100;
+                   break;
+           }
                for (;;) {
                        sram_printascii("\n change freq:");
                        g_crc1 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));
                        do
                        {
-                           nMHz = 300 + random32();
-                           nMHz %= 500;
-                       }while(nMHz < 300);
-                       nMHz = ddr_change_freq(nMHz);
+                           nMHz = min + random32();
+                           nMHz %= max;
+                       }while(nMHz < min);
                        sram_printhex(nMHz);
                        sram_printch(' ');
+                       nMHz = ddr_change_freq(nMHz);                   
                        sram_printhex(n++);
                        sram_printch(' ');
                        g_crc2 = calc_crc32((u32)_stext, (size_t)(_etext-_stext));