RK3168 DDR:support DDR change frequency for RK3168
authorcym <cym@rock-chips.com>
Thu, 7 Mar 2013 02:56:17 +0000 (10:56 +0800)
committercym <cym@rock-chips.com>
Thu, 7 Mar 2013 02:56:17 +0000 (10:56 +0800)
arch/arm/mach-rk30/clock_data-rk3066b.c [changed mode: 0644->0755]
arch/arm/mach-rk30/ddr.c
arch/arm/mach-rk3188/clock_data.c
arch/arm/plat-rk/ddr_freq.c [changed mode: 0644->0755]
arch/arm/plat-rk/include/plat/ddr.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index d7b6ce5..3c92e19
@@ -1119,7 +1119,7 @@ static int ddr_clk_set_rate(struct clk *c, unsigned long rate)
 
 static long ddr_clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       return ddr_set_pll(rate / MHZ, 0) * MHZ;
+       return ddr_set_pll_rk3066b(rate / MHZ, 0) * MHZ;
 }
 static unsigned long ddr_clk_recalc_rate(struct clk *clk)
 {
index 5284b006f118814edcb4f9bf2c8c1802729987bc..4a24aa1612eca432ee0708f0eae1a092d97a6d41 100755 (executable)
@@ -1534,7 +1534,7 @@ NR   NO     NF                      Fout                       freq Step     fin
 1    2      46 - 91          550MHz   - 1100MHz         12MHz         550MHz<= 1100MHz
 1    1      46 - 91          1100MHz  - 2200MHz         24MHz         1100MHz<= 2200MHz
 ******************************************/
-uint32_t __sramlocalfunc ddr_set_pll_rk3600b(uint32_t nMHz, uint32_t set)
+uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set)
 {
     uint32_t ret = 0;
     int delay = 1000;
@@ -3230,6 +3230,94 @@ void __sramlocalfunc ddr_selfrefresh_exit(void)
     }
 }
 
+#if defined(CONFIG_ARCH_RK3066B)
+static __sramdata uint32_t data8_dqstr[25][4];
+static __sramdata uint32_t min_ddr_freq,dqstr_flag=false;
+
+int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t min_freq)
+{
+    if(end_flag == true)
+    {
+        dqstr_flag = true;    //complete learn data training value flag
+        min_ddr_freq = min_freq;
+        return 0;
+    }
+
+    data8_dqstr[dqstr_value][0]=pPHY_Reg->DATX8[0].DXDQSTR;
+    data8_dqstr[dqstr_value][1]=pPHY_Reg->DATX8[0].DXDQSTR;
+    data8_dqstr[dqstr_value][2]=pPHY_Reg->DATX8[0].DXDQSTR;
+    data8_dqstr[dqstr_value][3]=pPHY_Reg->DATX8[0].DXDQSTR;
+
+    ddr_print("training %luMhz[%d]:0x%x-0x%x-0x%x-0x%x\n",
+        clk_get_rate(clk_get(NULL, "ddr_pll"))/1000000,dqstr_value,data8_dqstr[dqstr_value][0],data8_dqstr[dqstr_value][1],
+        data8_dqstr[dqstr_value][2],data8_dqstr[dqstr_value][3]);
+    return 0;
+}
+EXPORT_SYMBOL(ddr_get_datatraing_value_3168);
+
+void __sramlocalfunc ddr_set_pll_enter_3168(uint32_t freq_slew)
+{
+    uint32_t value_1u,value_100n;
+    ddr_move_to_Config_state();
+
+    if(freq_slew == 1)
+    {
+        value_100n = ddr_reg.pctl.pctl_timing.togcnt100n;
+        value_1u = ddr_reg.pctl.pctl_timing.togcnt1u;
+        ddr_reg.pctl.pctl_timing.togcnt1u = pDDR_Reg->TOGCNT1U;
+        ddr_reg.pctl.pctl_timing.togcnt100n = pDDR_Reg->TOGCNT100N;
+        ddr_update_timing();
+        ddr_update_mr();
+        ddr_reg.pctl.pctl_timing.togcnt100n = value_100n;
+        ddr_reg.pctl.pctl_timing.togcnt1u = value_1u;
+    }
+    else
+    {
+        pDDR_Reg->TOGCNT100N = ddr_reg.pctl.pctl_timing.togcnt100n;
+        pDDR_Reg->TOGCNT1U = ddr_reg.pctl.pctl_timing.togcnt1u;
+    }
+
+    pDDR_Reg->TZQCSI = 0;
+    ddr_move_to_Lowpower_state();
+
+    ddr_set_dll_bypass(0);  //dll bypass
+    pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (1<<2);  //disable DDR PHY clock
+    dsb();
+}
+
+void __sramlocalfunc ddr_set_pll_exit_3168(uint32 freq_slew,uint32_t dqstr_value)
+{
+    pCRU_Reg->CRU_CLKGATE_CON[0] = ((0x1<<2)<<16) | (0<<2);  //enable DDR PHY clock
+    dsb();
+    ddr_set_dll_bypass(ddr_freq);
+    ddr_reset_dll();
+
+    if(dqstr_flag==true)
+    {
+        pPHY_Reg->DATX8[0].DXDQSTR=data8_dqstr[dqstr_value][0];
+        pPHY_Reg->DATX8[1].DXDQSTR=data8_dqstr[dqstr_value][1];
+        pPHY_Reg->DATX8[2].DXDQSTR=data8_dqstr[dqstr_value][2];
+        pPHY_Reg->DATX8[3].DXDQSTR=data8_dqstr[dqstr_value][3];
+    }
+
+    ddr_update_odt();
+    ddr_move_to_Config_state();
+    if(freq_slew == 1)
+    {
+        pDDR_Reg->TOGCNT100N = ddr_reg.pctl.pctl_timing.togcnt100n;
+        pDDR_Reg->TOGCNT1U = ddr_reg.pctl.pctl_timing.togcnt1u;
+        pDDR_Reg->TZQCSI = ddr_reg.pctl.pctl_timing.tzqcsi;
+    }
+    else
+    {
+        ddr_update_timing();
+        ddr_update_mr();
+    }
+    ddr_data_training();
+    ddr_move_to_Access_state();
+}
+#endif
+
 uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
 {
     uint32_t ret;
@@ -3241,6 +3329,15 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     uint32_t regvalue = pCRU_Reg->CRU_PLL_CON[0][0];
     uint32_t freq;
 
+#if defined(CONFIG_ARCH_RK3066B)
+    uint32_t freq_slew=0,dqstr_value=0;
+    if(dqstr_flag==true)
+    {
+        dqstr_value=(nMHz-min_ddr_freq+1)/50;
+        freq_slew = (nMHz>ddr_freq)? 1 : 0;
+    }
+#endif
+
      // 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]&0xffff)+1)    // NF = 2*(CLKF+1)
@@ -3252,10 +3349,11 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     loops_per_us = LPJ_100MHZ*freq / 1000000;
 
 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
-    ret=ddr_set_pll_rk3600b(nMHz,0);
+    ret=ddr_set_pll_rk3066b(nMHz,0);
 #else
     ret=ddr_set_pll(nMHz,0);
 #endif
+
     ddr_get_parameter(ret);
 
     /** 1. Make sure there is no host access */
@@ -3266,11 +3364,29 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
     flush_tlb_all();
     isb();
     DDR_SAVE_SP(save_sp);
-    for(i=0;i<16;i++)
+
+#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();
+        n=temp[1024*i];
+        barrier();
+    }
+#endif
+#if defined(CONFIG_ARCH_RK30XX)
+    for(i=0;i<16;i++)    //64KB
+    {
+        n=temp[1024*i];
+        barrier();
     }
+#endif
+
     n= pDDR_Reg->SCFG.d32;
     n= pPHY_Reg->RIDR;
     n= pCRU_Reg->CRU_PLL_CON[0][0];
@@ -3285,27 +3401,33 @@ uint32_t __sramfunc ddr_change_freq(uint32_t nMHz)
 
     /** 2. ddr enter self-refresh mode or precharge power-down mode */
     idle_port();
+#if defined(CONFIG_ARCH_RK3066B)
+    ddr_set_pll_enter_3168(freq_slew);
+#else
     ddr_selfrefresh_enter(ret);
+#endif
 
     /** 3. change frequence  */
 #if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)
-    ddr_set_pll_rk3600b(ret,1);
+    ddr_set_pll_rk3066b(ret,1);
 #else
     ddr_set_pll(ret,1);
 #endif
     ddr_freq = ret;
     
     /** 5. Issues a Mode Exit command   */
+#if defined(CONFIG_ARCH_RK3066B)
+    ddr_set_pll_exit_3168(freq_slew,dqstr_value);
+#else
     ddr_selfrefresh_exit();
+#endif
     deidle_port();
-
     dsb();
     DDR_RESTORE_SP(save_sp);
     local_fiq_enable();
     local_irq_restore(flags);
     return ret;
 }
-
 EXPORT_SYMBOL(ddr_change_freq);
 
 void ddr_set_auto_self_refresh(bool en)
@@ -3480,7 +3602,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 20130130 \n");
+    ddr_print("version 1.00 20130307 \n");
 
     mem_type = pPHY_Reg->DCR.b.DDRMD;
     ddr_speed_bin = dram_speed_bin;
index d56fbb96ff76ef432537e384d98d9086a33e0657..eeac5f89e0ff76dd6d6e2d7047a2aff203ba23c2 100755 (executable)
@@ -1138,7 +1138,7 @@ static int ddr_clk_set_rate(struct clk *c, unsigned long rate)
 static long ddr_clk_round_rate(struct clk *clk, unsigned long rate)
 {
        CLKDATA_DBG("%s do nothing for ddr round rate\n", __func__);
-       return ddr_set_pll(rate / MHZ, 0) * MHZ;
+       return ddr_set_pll_rk3066b(rate / MHZ, 0) * MHZ;
 }
 static unsigned long ddr_clk_recalc_rate(struct clk *clk)
 {
old mode 100644 (file)
new mode 100755 (executable)
index db187db..8e2af89
@@ -332,6 +332,43 @@ static int ddr_scale_rate_for_dvfs(struct clk *clk, unsigned long rate, dvfs_set
        return !(clk_get_rate(clk) == rate);
 }
 
+#if defined(CONFIG_ARCH_RK3066B)
+static int ddrfreq_scanfreq_datatraing_3168(void)
+{
+    struct cpufreq_frequency_table *table;
+    uint32_t dqstr_freq,dqstr_value;
+    uint32_t min_freq,max_freq;
+    int i;
+    table = dvfs_get_freq_volt_table(clk_get(NULL, "ddr"));
+    if (!table)
+    {
+        pr_err("failed to get ddr freq volt table\n");
+    }
+    for (i = 0; table && table[i].frequency != CPUFREQ_TABLE_END; i++)
+    {
+        if(i == 0)
+            min_freq = table[i].frequency / 1000;
+
+        max_freq = table[i].frequency / 1000;
+    }
+
+    //get data training value for RK3066B ddr_change_freq
+    for(dqstr_freq=min_freq; dqstr_freq<=max_freq; dqstr_freq=dqstr_freq+50)
+    {
+        if (clk_set_rate(ddr.clk, dqstr_freq*MHZ) != 0)
+        {
+            pr_err("failed to clk_set_rate ddr.clk %dhz\n",dqstr_freq*MHZ);
+        }
+        dqstr_value=(dqstr_freq-min_freq+1)/50;
+
+        ddr_get_datatraing_value_3168(false,dqstr_value,min_freq);
+    }
+    ddr_get_datatraing_value_3168(true,0,min_freq);
+    dprintk(DEBUG_DDR,"get datatraing from %dMhz to %dMhz\n",min_freq,max_freq);
+    return 0;
+}
+#endif
+
 static int ddrfreq_init(void)
 {
        int i, ret;
@@ -427,6 +464,10 @@ static int ddrfreq_late_init(void)
        register_early_suspend(&ddr.early_suspend);
 #endif
 
+#if defined(CONFIG_ARCH_RK3066B)
+       ddrfreq_scanfreq_datatraing_3168();
+#endif
+
        ddr.task = kthread_create(ddrfreq_task, NULL, "ddrfreqd");
        if (IS_ERR(ddr.task)) {
                ret = PTR_ERR(ddr.task);
old mode 100644 (file)
new mode 100755 (executable)
index 89a6ac2..c8187cb
@@ -151,5 +151,9 @@ uint32_t ddr_get_cap(void);
 int ddr_init(uint32_t dram_type, uint32_t freq);
 void ddr_set_auto_self_refresh(bool en);
 uint32_t __sramlocalfunc ddr_set_pll(uint32_t nMHz, uint32_t set);
+uint32_t __sramlocalfunc ddr_set_pll_rk3066b(uint32_t nMHz, uint32_t set);
+#if defined(CONFIG_ARCH_RK3066B)
+int ddr_get_datatraing_value_3168(bool end_flag,uint32_t dqstr_value,uint32_t min_freq);
+#endif
 
 #endif