From 8b1e4567284200c4999842e76949dcbb828dd86f Mon Sep 17 00:00:00 2001 From: chenxing Date: Sat, 10 Aug 2013 09:50:19 +0800 Subject: [PATCH] rk30xx: add dvfs table auto adjust by leakage interface --- arch/arm/mach-rk30/dvfs.c | 81 ++++++++++++++++++++++++++ arch/arm/mach-rk30/include/mach/dvfs.h | 2 + arch/arm/plat-rk/efuse.c | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-rk30/dvfs.c b/arch/arm/mach-rk30/dvfs.c index 0d6e5aef869d..0b3cbd52e01a 100755 --- a/arch/arm/mach-rk30/dvfs.c +++ b/arch/arm/mach-rk30/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) @@ -76,6 +77,86 @@ static int rk_dvfs_clk_notifier_event(struct notifier_block *this, 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 = 3, .maxvolt = 1350 * 1000}, + {.leakage_level = 6, .maxvolt = 1300 * 1000}, + {.leakage_level = 15, .maxvolt = 1250 * 1000}, +}; +static int leakage_level = 0; +#define MHZ (1000 * 1000) +#define KHZ (1000) +// Delayline bound for nandc = 148.5MHz, Varm = Vlog = 1.00V +#define HIGH_DELAYLINE 125 +#define LOW_DELAYLINE 125 +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; + if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(table)) { + DVFS_ERR("%s: clk error OR table error\n", __func__); + return ; + } + + leakage_level = rk_leakage_val(); + printk("DVFS MSG: %s: %s get leakage_level = %d\n", clk->name, __func__, leakage_level); + if (leakage_level == 0) { + + /* + * This is for delayline auto scale voltage, + * FIXME: HIGH_DELAYLINE / LOW_DELAYLINE value maybe redefined under + * Varm = Vlog = 1.00V. + * Warning: this value is frequency/voltage sensitive, care + * about Freq nandc/Volt log. + * + */ + + unsigned long delayline_val = 0; + unsigned long high_delayline = 0, low_delayline = 0; + unsigned long rate_nandc = 0; + + // rk3168: do nothing + return; + + rate_nandc = clk_get_rate(clk_get(NULL, "nandc")) / KHZ; + printk("Get nandc rate = %lu KHz\n", rate_nandc); + high_delayline = HIGH_DELAYLINE * 148500 / rate_nandc; + low_delayline = LOW_DELAYLINE * 148500 / rate_nandc; + delayline_val = rk30_get_avs_val(); + printk("This chip no leakage msg, use delayline instead, val = %lu.(HDL=%lu, LDL=%lu)\n", + delayline_val, high_delayline, low_delayline); + + 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, high voltage request\n"); + + } 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); + } + } +} #ifdef CONFIG_ARCH_RK3066B static int g_arm_high_logic = 0 * 1000; static int g_logic_high_arm = 50 * 1000; diff --git a/arch/arm/mach-rk30/include/mach/dvfs.h b/arch/arm/mach-rk30/include/mach/dvfs.h index cd9f96bbb613..b10f53e41ed7 100644 --- a/arch/arm/mach-rk30/include/mach/dvfs.h +++ b/arch/arm/mach-rk30/include/mach/dvfs.h @@ -5,8 +5,10 @@ #ifdef CONFIG_DVFS int rk_dvfs_init(void); +void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table); #else static inline int rk_dvfs_init(void){ return 0; } +static inline void dvfs_adjust_table_lmtvolt(struct clk *clk, struct cpufreq_frequency_table *table){} #endif #endif diff --git a/arch/arm/plat-rk/efuse.c b/arch/arm/plat-rk/efuse.c index ff46d9eb9509..3a5821c3bb2d 100644 --- a/arch/arm/plat-rk/efuse.c +++ b/arch/arm/plat-rk/efuse.c @@ -12,7 +12,7 @@ #include #include -#if defined(CONFIG_ARCH_RK3188) || defined(CONFIG_SOC_RK3028) +#if defined(CONFIG_ARCH_RK3188) || defined(CONFIG_SOC_RK3028) || defined(CONFIG_ARCH_RK3066B) #define efuse_readl(offset) readl_relaxed(RK30_EFUSE_BASE + offset) #define efuse_writel(val, offset) writel_relaxed(val, RK30_EFUSE_BASE + offset) #endif -- 2.34.1