rk3188: use leakage or delayline auto scale voltage
authorchenxing <chenxing@rock-chips.com>
Mon, 17 Jun 2013 06:39:08 +0000 (14:39 +0800)
committerchenxing <chenxing@rock-chips.com>
Mon, 17 Jun 2013 06:39:08 +0000 (14:39 +0800)
arch/arm/mach-rk3188/cpufreq.c
arch/arm/mach-rk3188/dvfs.c
arch/arm/mach-rk3188/include/mach/dvfs.h

index 12a41f312e2704a027c3e6416686dbc5c6bc2b81..599fe9cae0fe0b792d4870b2392a31e4089500a0 100644 (file)
@@ -346,6 +346,7 @@ static int rk3188_cpufreq_verify(struct cpufreq_policy *policy)
 static int rk3188_cpufreq_init_cpu0(struct cpufreq_policy *policy)
 {
        unsigned int i;
+       struct cpufreq_frequency_table *table_adjust;
 
        gpu_is_mali400 = cpu_is_rk3188();
        gpu_clk = clk_get(NULL, "gpu");
@@ -363,6 +364,14 @@ static int rk3188_cpufreq_init_cpu0(struct cpufreq_policy *policy)
        if (IS_ERR(cpu_clk))
                return PTR_ERR(cpu_clk);
 
+       if (soc_is_rk3188()) {
+               /* Adjust dvfs table avoid overheat */
+               table_adjust = dvfs_get_freq_volt_table(cpu_clk);
+               dvfs_adjust_table_lmtvolt(cpu_clk, table_adjust);
+               table_adjust = dvfs_get_freq_volt_table(gpu_clk);
+               dvfs_adjust_table_lmtvolt(gpu_clk, table_adjust);
+       }
+
        dvfs_clk_register_set_rate_callback(cpu_clk, cpufreq_scale_rate_for_dvfs);
        freq_table = dvfs_get_freq_volt_table(cpu_clk);
        if (freq_table == NULL) {
index 6f409c7524971c3daac2da38347934bebe6d21ac..772af60ae6f998c56474f15c0d447248f9745fef 100755 (executable)
@@ -26,6 +26,7 @@
 #include <linux/delay.h>\r
 #include <linux/io.h>\r
 #include <linux/hrtimer.h>\r
+#include <plat/efuse.h>\r
 \r
 static int rk_dvfs_clk_notifier_event(struct notifier_block *this,\r
                unsigned long event, void *ptr)\r
@@ -77,6 +78,59 @@ static struct notifier_block rk_dvfs_clk_notifier = {
        .notifier_call = rk_dvfs_clk_notifier_event,\r
 };\r
 \r
+struct lkg_maxvolt {\r
+       int leakage_level;\r
+       unsigned int maxvolt;\r
+};\r
+static struct lkg_maxvolt lkg_volt_table[] = {\r
+       {.leakage_level = 1,    .maxvolt = 1350 * 1000},\r
+       {.leakage_level = 3,    .maxvolt = 1275 * 1000},\r
+       {.leakage_level = 15,   .maxvolt = 1200 * 1000},\r
+};\r
+\r
+static int leakage_level = 0;\r
+#define HIGH_DELAYLINE 125\r
+#define LOW_DELAYLINE  110\r
+static u8 rk30_get_avs_val(void);\r
+void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table)\r
+{\r
+       int i = 0;\r
+       unsigned int maxvolt = 0;\r
+\r
+       leakage_level = rk_leakage_val();\r
+       printk("DVFS MSG: %s: %s get leakage_level = %d\n", clk->name, __func__, leakage_level);\r
+       if (leakage_level == 0) {\r
+               int delayline_val = 0;\r
+               delayline_val = rk30_get_avs_val();\r
+               printk("This chip no leakage msg, use delayline instead, val = %d\n", delayline_val);\r
+\r
+               if (delayline_val >= HIGH_DELAYLINE) {\r
+                       leakage_level = 4;      //same as leakage_level > 4\r
+\r
+               } else if (delayline_val <= LOW_DELAYLINE) {\r
+                       leakage_level = 1;\r
+                       printk("Delayline TOO LOW, maybe need high voltage\n");\r
+\r
+               } else\r
+                       leakage_level = 2;      //same as leakage_level = 3\r
+       }\r
+\r
+       for (i = 0; i < ARRAY_SIZE(lkg_volt_table); i++) {\r
+               if (leakage_level <= lkg_volt_table[i].leakage_level) {\r
+                       maxvolt = lkg_volt_table[i].maxvolt;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) {\r
+               if (table[i].index > maxvolt) {\r
+                       printk("\t\tadjust table freq=%d KHz, index=%d mV", table[i].frequency, table[i].index);\r
+                       table[i].index = maxvolt;\r
+                       printk(" to index=%d mV\n", table[i].index);\r
+               }\r
+       }\r
+}\r
+\r
 #define NO_VOLT_DIFF\r
 #ifdef NO_VOLT_DIFF\r
 \r
index 9a9b3bdbc8e415de70e28e8ced602dafcf56fd8d..77d5949e6928fc38e9086f267323995484533d89 100644 (file)
@@ -5,8 +5,10 @@
 
 #ifdef CONFIG_DVFS
 int rk3188_dvfs_init(void);
+void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table);
 #else
 static inline int rk3188_dvfs_init(void){ return 0; }
+static inline void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table){}
 #endif
 
 #endif