RK3188:ENABLE_DDR_CLCOK_GPLL_PATH,curtail idle_port and
authorcym <cym@rock-chips.com>
Sat, 27 Apr 2013 01:30:57 +0000 (09:30 +0800)
committercym <cym@rock-chips.com>
Sat, 27 Apr 2013 01:30:57 +0000 (09:30 +0800)
    disable fiq/irq time when change_ddr_freq

arch/arm/mach-rk30/ddr.c
arch/arm/plat-rk/include/plat/ddr.h

index 178e715bc3cc3dd5361c2ffed2a9d67ce0c51a40..55b6f5d9cdb62b330cd56f4a4dee0c8ad00aaba4 100755 (executable)
@@ -24,6 +24,8 @@
 
 typedef uint32_t uint32;
 
+#define ENABLE_DDR_CLCOK_GPLL_PATH  //for RK3188
+
 #define DDR3_DDR2_DLL_DISABLE_FREQ    (125)
 #define DDR3_DDR2_ODT_DISABLE_FREQ    (333)
 #define SR_IDLE                       (0x1)   //unit:32*DDR clk cycle, and 0 for disable auto self-refresh
@@ -1447,6 +1449,11 @@ void __sramlocalfunc ddr_set_dll_bypass(uint32 freq)
 static __sramdata uint32_t clkr;
 static __sramdata uint32_t clkf;
 static __sramdata uint32_t clkod;
+
+static __sramdata uint32_t dpllvaluel=0;
+static __sramdata uint32_t gpllvaluel=0;
+static __sramdata bool ddr_select_gpll=false;
+
 /*****************************************
 NR   NO     NF               Fout                       freq Step     finally use
 1    8      12.5 - 62.5      37.5MHz  - 187.5MHz        3MHz          50MHz   <= 150MHz
@@ -1548,61 +1555,126 @@ uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set)
 
     if(!set)
     {
-        if(nMHz <= 150)
-        {
-            clkod = 14;
-        }
-        else if(nMHz <= 200)
-        {
-            clkod = 8;
-        }
-        else if(nMHz <= 300)
-        {
-            clkod = 6;
-        }
-        else if(nMHz <= 550)
-        {
-            clkod = 4;
-        }
-        else if(nMHz <= 1100)
+         // freq = (Fin/NR)*NF/OD
+        if(((pCRU_Reg->CRU_MODE_CON>>4)&3) == 1)             // DPLL Normal mode
+            dpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[1][1]&0xffff)+1)    // NF = 2*(CLKF+1)
+                    /((((pCRU_Reg->CRU_PLL_CON[1][0]>>8)&0x3f)+1)           // NR = CLKR+1
+                    *((pCRU_Reg->CRU_PLL_CON[1][0]&0x3F)+1));             // OD = 2^CLKOD
+        else
+            dpllvaluel = 24;
+
+                 // freq = (Fin/NR)*NF/OD
+        if(((pCRU_Reg->CRU_MODE_CON>>12)&3) == 1)             // GPLL Normal mode
+            gpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[3][1]&0xffff)+1)    // NF = 2*(CLKF+1)
+                    /((((pCRU_Reg->CRU_PLL_CON[3][0]>>8)&0x3f)+1)           // NR = CLKR+1
+                    *((pCRU_Reg->CRU_PLL_CON[3][0]&0x3F)+1));             // OD = 2^CLKOD
+        else
+            gpllvaluel = 24;
+
+        if(ddr_select_gpll == true)
         {
-            clkod = 2;
+            if(gpllvaluel > 800)
+                ret = gpllvaluel/4;       
+            else if(gpllvaluel > 400)
+                ret = gpllvaluel/2;
+            else
+                ret=gpllvaluel;
         }
         else
         {
-            clkod = 1;
+            if(nMHz <= 150)
+            {
+                clkod = 14;
+            }
+            else if(nMHz <= 200)
+            {
+                clkod = 8;
+            }
+            else if(nMHz <= 300)
+            {
+                clkod = 6;
+            }
+            else if(nMHz <= 550)
+            {
+                clkod = 4;
+            }
+            else if(nMHz <= 1100)
+            {
+                clkod = 2;
+            }
+            else
+            {
+                clkod = 1;
+            }
+            clkr = 1;
+            clkf=(nMHz*clkr*clkod)/24;
+            ret = (24*clkf)/(clkr*clkod);
         }
-        clkr = 1;
-        clkf=(nMHz*clkr*clkod)/24;
-        ret = (24*clkf)/(clkr*clkod);
+
     }
     else
     {
-        pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16)) | (0x0<<(pll_id*4));            //PLL slow-mode
-        dsb();
-
-        pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B;
-       ddr_delayus(1);
-        pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod);
-        pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf);
-//     pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1);
-        ddr_delayus(1);
-        pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B;
-        dsb();
-        while (delay > 0) 
+         if(ddr_select_gpll == true)
         {
+            if(gpllvaluel > 800)
+            {
+                pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000;
+                pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
+                                                          | (0x1<<8)     //clk_ddr_src = G PLL
+                                                          | 2;           //clk_ddr_src:clk_ddrphy = 4:1
+            }
+            if(gpllvaluel > 400)
+            {
+                pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000;
+                pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
+                                                          | (0x1<<8)     //clk_ddr_src = G PLL
+                                                          | 1;           //clk_ddr_src:clk_ddrphy = 2:1
+            }
+            else
+            {
+                pCRU_Reg->CRU_CLKGATE_CON[1] = 0x00800000;
+                pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
+                                                          | (0x1<<8)     //clk_ddr_src = G PLL
+                                                          | 0;           //clk_ddr_src:clk_ddrphy = 1:1
+            }
+            dsb();
+        }
+        else if(nMHz==dpllvaluel)
+        {
+            // ddr_pll_clk: clk_ddr=1:1     
+            pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
+                                                          | (0x0<<8)     //clk_ddr_src = DDR PLL
+                                                          | 0;           //clk_ddr_src:clk_ddrphy = 1:1
+            dsb();
+        }
+        else
+        {         
+            pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16)) | (0x0<<(pll_id*4));            //PLL slow-mode
+            dsb();
+    
+            pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B;
+            ddr_delayus(1);
+            pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod);
+            pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf);
+            //     pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1);
             ddr_delayus(1);
-            if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
-                break;
-            delay--;
+            pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B;
+            dsb();
+            while (delay > 0) 
+            {
+                ddr_delayus(1);
+                if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
+                    break;
+                delay--;
+            }
+    
+            pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
+                                                          | (0x0<<8)     //clk_ddr_src = DDR PLL
+                                                          | 0;           //clk_ddr_src:clk_ddrphy = 1:1
+    
+            pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16))  | (0x1<<(pll_id*4));            //PLL normal
+            dsb();
         }
-
-        pCRU_Reg->CRU_CLKSEL_CON[26] = ((0x3 | (0x1<<8))<<16)
-                                                      | (0x0<<8)     //clk_ddr_src = DDR PLL
-                                                      | 0;           //clk_ddr_src:clk_ddrphy = 1:1
-
-        pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16))  | (0x1<<(pll_id*4));            //PLL normal
-        dsb();
     }
 out:
     return ret;
@@ -3318,7 +3390,7 @@ void __sramlocalfunc ddr_set_pll_exit_3168(uint32 freq_slew,uint32_t dqstr_value
 }
 #endif
 
-uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
+uint32_t __sramfunc ddr_change_freq_sram(uint32_t nMHz)
 {
     uint32_t ret;
     u32 i;
@@ -3365,27 +3437,16 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     isb();
     DDR_SAVE_SP(save_sp);
 
-#if defined(CONFIG_ARCH_RK3066B)
-    for(i=0;i<4;i++)     //16KB
-    {
-        n=temp[1024*i];
-        barrier();
-    }
-#endif
-#if defined(CONFIG_ARCH_RK3188)
-    for(i=0;i<8;i++)     //32KB
-    {
-        n=temp[1024*i];
-        barrier();
-    }
+#if defined(CONFIG_ARCH_RK30)
+#define SRAM_SIZE       RK30_IMEM_SIZE
+#elif defined(CONFIG_ARCH_RK3188)
+#define SRAM_SIZE       RK3188_IMEM_SIZE
 #endif
-#if defined(CONFIG_ARCH_RK30XX)
-    for(i=0;i<16;i++)    //64KB
+    for(i=0;i<SRAM_SIZE/4096;i++)     
     {
         n=temp[1024*i];
         barrier();
     }
-#endif
 
     n= pDDR_Reg->SCFG.d32;
     n= pPHY_Reg->RIDR;
@@ -3400,7 +3461,7 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     dsb();
 
     /** 2. ddr enter self-refresh mode or precharge power-down mode */
-    idle_port();
+   idle_port();
 #if defined(CONFIG_ARCH_RK3066B)
     ddr_set_pll_enter_3168(freq_slew);
 #else
@@ -3428,6 +3489,93 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     local_irq_restore(flags);
     return ret;
 }
+
+uint32_t ddr_change_freq(uint32_t nMHz)
+{
+#if defined(ENABLE_DDR_CLCOK_GPLL_PATH) && defined(CONFIG_ARCH_RK3188)
+
+    uint32_t freq_gpll;
+    int delay = 1000;
+    uint32_t pll_id=1;  //DPLL
+
+    if(((pCRU_Reg->CRU_MODE_CON>>12)&3) == 1)             // GPLL Normal mode
+            gpllvaluel= 24 *((pCRU_Reg->CRU_PLL_CON[3][1]&0xffff)+1)    // NF = 2*(CLKF+1)
+                   /((((pCRU_Reg->CRU_PLL_CON[3][0]>>8)&0x3f)+1)           // NR = CLKR+1
+                   *((pCRU_Reg->CRU_PLL_CON[3][0]&0x3F)+1));             // OD = 2^CLKOD
+    else
+           gpllvaluel = 24;
+
+    if(200 < gpllvaluel <1600)      //GPLL:200MHz~1600MHz
+    {
+        if( gpllvaluel > 800)
+            freq_gpll = gpllvaluel/4;
+        else if( gpllvaluel > 400)
+            freq_gpll = gpllvaluel/2;
+        else            
+            freq_gpll = gpllvaluel;
+        
+        ddr_select_gpll=true;
+        ddr_change_freq_sram(freq_gpll);
+        ddr_select_gpll=false;
+        
+        //set DPLL,when ddr_clock select GPLL
+        if(nMHz <= 150)
+        {
+            clkod = 14;
+        }
+        else if(nMHz <= 200)
+        {
+            clkod = 8;
+        }
+        else if(nMHz <= 300)
+        {
+            clkod = 6;
+        }
+        else if(nMHz <= 550)
+        {
+            clkod = 4;
+        }
+        else if(nMHz <= 1100)
+        {
+            clkod = 2;
+        }
+        else
+        {
+            clkod = 1;
+        }
+        clkr = 1;
+        clkf=(nMHz*clkr*clkod)/24;
+    
+        pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16)) | (0x0<<(pll_id*4));            //PLL slow-mode
+        dsb();
+        
+        pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_RESET_RK3066B;
+         ddr_delayus(1);
+        pCRU_Reg->CRU_PLL_CON[pll_id][0] = NR_RK3066B(clkr) | NO_RK3066B(clkod);
+        pCRU_Reg->CRU_PLL_CON[pll_id][1] = NF_RK3066B(clkf);
+        //     pCRU_Reg->CRU_PLL_CON[pll_id][2] = NB(clkf>>1);
+        ddr_delayus(1);
+        pCRU_Reg->CRU_PLL_CON[pll_id][3] = PLL_DE_RESET_RK3066B;
+        dsb();
+        while (delay > 0) 
+        {
+            ddr_delayus(1);
+            if (pGRF_Reg_RK3066B->GRF_SOC_STATUS0 & (0x1<<5))
+                break;
+            delay--;
+        }
+        pCRU_Reg->CRU_MODE_CON = (0x3<<((pll_id*4) +  16))  | (0x1<<(pll_id*4));            //PLL normal
+        //set DPLL end
+    }
+    else
+    {
+        ddr_print("GPLL frequency = %dMHz,Not suitable for ddr_clock \n",gpllvaluel);
+    }
+#endif
+
+    return ddr_change_freq_sram(nMHz);
+
+}
 EXPORT_SYMBOL(ddr_change_freq);
 
 void ddr_set_auto_self_refresh(bool en)
@@ -3447,12 +3595,18 @@ void __sramfunc ddr_suspend(void)
     flush_cache_all();
     outer_flush_all();
     //flush_tlb_all();
-    
-    for(i=0;i<16;i++)
+
+#if defined(CONFIG_ARCH_RK30)
+#define SRAM_SIZE       RK30_IMEM_SIZE
+#elif defined(CONFIG_ARCH_RK3188)
+#define SRAM_SIZE       RK3188_IMEM_SIZE
+#endif
+    for(i=0;i<SRAM_SIZE/4096;i++)     
     {
         n=temp[1024*i];
         barrier();
     }
+
     n= pDDR_Reg->SCFG.d32;
     n= pPHY_Reg->RIDR;
     n= pCRU_Reg->CRU_PLL_CON[0][0];
@@ -3602,7 +3756,7 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
     uint32_t die=1;
     uint32_t gsr,dqstr;
 
-    ddr_print("version 1.00 20130325 \n");
+    ddr_print("version 1.00 20130427 \n");
 
     mem_type = pPHY_Reg->DCR.b.DDRMD;
     ddr_speed_bin = dram_speed_bin;
@@ -3644,9 +3798,9 @@ int ddr_init(uint32_t dram_speed_bin, uint32_t freq)
     ddr_adjust_config(mem_type);
 
     if(freq != 0)
-        value=ddr_change_freq(freq);
+        value=ddr_change_freq_sram(freq);
     else
-        value=ddr_change_freq(clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000);
+        value=ddr_change_freq_sram(clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000);
 
     clk_set_rate(clk_get(NULL, "ddr_pll"), 0);
     ddr_print("init success!!! freq=%luMHz\n", clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000);
index c8187cb7bf4862483d5f4b3574aa2ba0376135e3..574afaf778c107a7745c11ed70d21c303848f15f 100755 (executable)
 void __sramfunc ddr_suspend(void);
 void __sramfunc ddr_resume(void);
 //void __sramlocalfunc delayus(uint32_t us);
-uint32_t __sramfunc ddr_change_freq(uint32_t nMHz);
+uint32_t ddr_change_freq(uint32_t nMHz);
 uint32_t ddr_get_cap(void);
 int ddr_init(uint32_t dram_type, uint32_t freq);
 void ddr_set_auto_self_refresh(bool en);