mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk30xx: add dvfs table auto adjust by leakage interface
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <plat/efuse.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <plat/efuse.h>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user