#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
static struct notifier_block rk_dvfs_clk_notifier = {\r
.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 = 3, .maxvolt = 1350 * 1000},\r
+ {.leakage_level = 6, .maxvolt = 1300 * 1000},\r
+ {.leakage_level = 15, .maxvolt = 1250 * 1000},\r
+};\r
+static int leakage_level = 0;\r
+#define MHZ (1000 * 1000)\r
+#define KHZ (1000)\r
+// Delayline bound for nandc = 148.5MHz, Varm = Vlog = 1.00V\r
+#define HIGH_DELAYLINE 125\r
+#define LOW_DELAYLINE 125\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
+ if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(table)) {\r
+ DVFS_ERR("%s: clk error OR table error\n", __func__);\r
+ return ;\r
+ }\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
+\r
+ /*\r
+ * This is for delayline auto scale voltage,\r
+ * FIXME: HIGH_DELAYLINE / LOW_DELAYLINE value maybe redefined under\r
+ * Varm = Vlog = 1.00V.\r
+ * Warning: this value is frequency/voltage sensitive, care\r
+ * about Freq nandc/Volt log.\r
+ *\r
+ */\r
+\r
+ unsigned long delayline_val = 0;\r
+ unsigned long high_delayline = 0, low_delayline = 0;\r
+ unsigned long rate_nandc = 0;\r
+\r
+ // rk3168: do nothing\r
+ return;\r
+\r
+ rate_nandc = clk_get_rate(clk_get(NULL, "nandc")) / KHZ;\r
+ printk("Get nandc rate = %lu KHz\n", rate_nandc);\r
+ high_delayline = HIGH_DELAYLINE * 148500 / rate_nandc;\r
+ low_delayline = LOW_DELAYLINE * 148500 / rate_nandc;\r
+ delayline_val = rk30_get_avs_val();\r
+ printk("This chip no leakage msg, use delayline instead, val = %lu.(HDL=%lu, LDL=%lu)\n",\r
+ delayline_val, high_delayline, low_delayline);\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, high voltage request\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
#ifdef CONFIG_ARCH_RK3066B\r
static int g_arm_high_logic = 0 * 1000;\r
static int g_logic_high_arm = 50 * 1000;\r