From 576021075c4f2d6eb6a0735f316bff397f39ba5d Mon Sep 17 00:00:00 2001 From: chenxing Date: Mon, 17 Jun 2013 14:19:09 +0800 Subject: [PATCH] rk3188: use leakage or delayline auto scale voltage --- arch/arm/mach-rk3188/cpufreq.c | 9 ++++ arch/arm/mach-rk3188/dvfs.c | 55 ++++++++++++++++++++++++ arch/arm/mach-rk3188/include/mach/dvfs.h | 2 + 3 files changed, 66 insertions(+) diff --git a/arch/arm/mach-rk3188/cpufreq.c b/arch/arm/mach-rk3188/cpufreq.c index 12a41f312e27..599fe9cae0fe 100644 --- a/arch/arm/mach-rk3188/cpufreq.c +++ b/arch/arm/mach-rk3188/cpufreq.c @@ -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) { diff --git a/arch/arm/mach-rk3188/dvfs.c b/arch/arm/mach-rk3188/dvfs.c index 6f409c752497..0e41237278aa 100755 --- a/arch/arm/mach-rk3188/dvfs.c +++ b/arch/arm/mach-rk3188/dvfs.c @@ -26,6 +26,7 @@ #include #include #include +#include static int rk_dvfs_clk_notifier_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -77,6 +78,60 @@ static struct notifier_block rk_dvfs_clk_notifier = { .notifier_call = rk_dvfs_clk_notifier_event, }; +struct lkg_maxvolt { + int leakage_level; + unsigned int maxvolt; +}; +static struct lkg_maxvolt lkg_volt_table[] = { + {.leakage_level = 1, .maxvolt = 1350 * 1000}, + {.leakage_level = 3, .maxvolt = 1275 * 1000}, + {.leakage_level = 15, .maxvolt = 1200 * 1000}, +}; + +static int leakage_level = 0; +#define HIGH_DELAYLINE 125 +#define LOW_DELAYLINE 110 +static u8 rk30_get_avs_val(void); +void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table) +{ + int i = 0; + unsigned int maxvolt = 0; + + leakage_level = rk_leakage_val(); + printk("DVFS MSG: %s: %s get leakage_level = %d\n", clk->name, __func__, leakage_level); + if (leakage_level == 0) { + int delayline_val = 0; + delayline_val = rk30_get_avs_val(); + printk("This chip no leakage msg, use delayline instead, val = %d\n", delayline_val); + + if (delayline_val >= HIGH_DELAYLINE) { + leakage_level = 4; //same as leakage_level > 4 + + } else if (delayline_val <= LOW_DELAYLINE) { + leakage_level = 1; + printk("Delayline TOO LOW, maybe need high voltage, ignore this chip\n"); + while(1); + + } else + leakage_level = 2; //same as leakage_level = 3 + } + + for (i = 0; i < ARRAY_SIZE(lkg_volt_table); i++) { + if (leakage_level <= lkg_volt_table[i].leakage_level) { + maxvolt = lkg_volt_table[i].maxvolt; + break; + } + } + + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { + if (table[i].index > maxvolt) { + printk("\t\tadjust table freq=%d KHz, index=%d mV", table[i].frequency, table[i].index); + table[i].index = maxvolt; + printk(" to index=%d mV\n", table[i].index); + } + } +} + #define NO_VOLT_DIFF #ifdef NO_VOLT_DIFF diff --git a/arch/arm/mach-rk3188/include/mach/dvfs.h b/arch/arm/mach-rk3188/include/mach/dvfs.h index 9a9b3bdbc8e4..77d5949e6928 100644 --- a/arch/arm/mach-rk3188/include/mach/dvfs.h +++ b/arch/arm/mach-rk3188/include/mach/dvfs.h @@ -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 -- 2.34.1