背景:使用esFileManager无法获取cpu频率信息
利用systeminfo pro也只能查看到current frequency
修改方法:通过参考s3c64xx的cpufreq驱动,添加一个驱动到自己的平台,修改相关的配置文件以实现
说明:我们的产品不支持变频,故将获取的cpu主频赋给一个全局变量。
patch:
From afee80a0d7fe5af0c7bea09c2fcd9c8a0245cf1a Mon Sep 17 00:00:00 2001
From: wangxiaodong
Date: Thu, 5 Jan 2012 11:08:28 +0800
Subject: [PATCH] add emxx_cpufreq driver and display cpufreq info
---
arch/arm/Kconfig | 4 +-
arch/arm/configs/emev_defconfig | 16 +++
arch/arm/mach-emxx/Kconfig | 3 +
arch/arm/mach-emxx/Makefile | 1 +
arch/arm/mach-emxx/emxx_cpufreq.c | 220 +++++++++++++++++++++++++++++++++++++
5 files changed, 242 insertions(+), 2 deletions(-)
mode change 100644 => 100755 arch/arm/Kconfig
create mode 100755 arch/arm/mach-emxx/emxx_cpufreq.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
old mode 100644
new mode 100755
index ec5abe8..1547628
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1589,7 +1589,7 @@ endmenu
menu "CPU Power Management"
-if ARCH_HAS_CPUFREQ
+#if ARCH_HAS_CPUFREQ
source "drivers/cpufreq/Kconfig"
@@ -1666,7 +1666,7 @@ config CPU_FREQ_S3C24XX_DEBUGFS
help
Export status information via debugfs.
-endif
+#endif
source "drivers/cpuidle/Kconfig"
diff --git a/arch/arm/configs/emev_defconfig b/arch/arm/configs/emev_defconfig
index 8d2789e..11397ff 100755
--- a/arch/arm/configs/emev_defconfig
+++ b/arch/arm/configs/emev_defconfig
@@ -263,6 +263,7 @@ CONFIG_EMXX_SPI=y
CONFIG_EMXX_PWM=m
# CONFIG_EMXX_DTV is not set
# CONFIG_EMXX_DM2016 is not set
+CONFIG_EMXX_CPUFREQ=y
CONFIG_EMXX_AXP192_PWC=y
CONFIG_EMXX_AXP192_REGRW=y
CONFIG_EMXX_EXTIO=y
@@ -385,6 +386,21 @@ CONFIG_CMDLINE=""
#
# CPU Power Management
#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_IDLE is not set
#
diff --git a/arch/arm/mach-emxx/Kconfig b/arch/arm/mach-emxx/Kconfig
index fcecfdf..ff555d4 100755
--- a/arch/arm/mach-emxx/Kconfig
+++ b/arch/arm/mach-emxx/Kconfig
@@ -105,6 +105,9 @@ config EMXX_DM2016
bool "EMEV DM2016 driver support"
depends on I2C
default n
+config EMXX_CPUFREQ
+ bool "EMEV cpufreq driver support"
+ default y
config EMXX_AXP192_PWC
bool "EMEV AXP 192 driver support"
diff --git a/arch/arm/mach-emxx/Makefile b/arch/arm/mach-emxx/Makefile
index e25f27e..e6bac1f 100755
--- a/arch/arm/mach-emxx/Makefile
+++ b/arch/arm/mach-emxx/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_PM) += pm_pmu.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_EMXX_CPUFREQ) += emxx_cpufreq.o
diff --git a/arch/arm/mach-emxx/emxx_cpufreq.c b/arch/arm/mach-emxx/emxx_cpufreq.c
new file mode 100755
index 0000000..210433c
--- /dev/null
+++ b/arch/arm/mach-emxx/emxx_cpufreq.c
@@ -0,0 +1,220 @@
+/* linux/arch/arm/plat-s3c64xx/cpufreq.c
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * S3C64xx CPUfreq Support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+static struct regulator *vddarm;
+
+static unsigned long regulator_latency;
+static unsigned long emxx_cpufreq;
+struct emxx_dvfs {
+ unsigned int vddarm_min;
+ unsigned int vddarm_max;
+};
+
+static struct emxx_dvfs emxx_dvfs_table[] = {
+ [0] = { 1000000, 1150000 },
+ [1] = { 1050000, 1150000 },
+ [2] = { 1100000, 1150000 },
+ [3] = { 1200000, 1350000 },
+};
+
+static struct cpufreq_frequency_table emxx_freq_table[] = {
+ { 0, 1062000 },
+ { 0, 1062000 },
+ { 1, 1062000 },
+ { 1, 1062000 },
+ { 2, 1062000 },
+ { 2, 1062000 },
+ { 2, 1062000 },
+ { 2, 1062000 },
+ { 3, 1062000 },
+ { 0, CPUFREQ_TABLE_END },
+};
+
+static int emxx_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, emxx_freq_table);
+}
+
+static unsigned int emxx_cpufreq_get_speed(unsigned int cpu)
+{
+ return emxx_cpufreq;
+}
+
+static int emxx_cpufreq_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ int ret;
+ unsigned int i;
+ struct cpufreq_freqs freqs;
+ struct emxx_dvfs *dvfs;
+
+ ret = cpufreq_frequency_table_target(policy, emxx_freq_table,
+ target_freq, relation, &i);
+ if (ret != 0)
+ return ret;
+
+ freqs.cpu = 0;
+ freqs.old = emxx_cpufreq;
+ freqs.new = emxx_freq_table[i].frequency;
+ freqs.flags = 0;
+ dvfs = &emxx_dvfs_table[emxx_freq_table[i].index];
+
+ if (freqs.old == freqs.new)
+ return 0;
+
+ pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_REGULATOR
+ if (vddarm && freqs.new < freqs.old) {
+ ret = regulator_set_voltage(vddarm,
+ dvfs->vddarm_min,
+ dvfs->vddarm_max);
+ if (ret != 0) {
+ pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+ freqs.new, ret);
+ goto err_clk;
+ }
+ }
+#endif
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
+}
+
+#ifdef CONFIG_REGULATOR
+static void __init emxx_cpufreq_config_regulator(void)
+{
+ int count, v, i, found;
+ struct cpufreq_frequency_table *freq;
+ struct emxx_dvfs *dvfs;
+
+ count = regulator_count_voltages(vddarm);
+ if (count < 0) {
+ pr_err("cpufreq: Unable to check supported voltages\n");
+ }
+
+ freq = emxx_freq_table;
+ while (count > 0 && freq->frequency != CPUFREQ_TABLE_END) {
+ if (freq->frequency == CPUFREQ_ENTRY_INVALID)
+ continue;
+
+ dvfs = &emxx_dvfs_table[freq->index];
+ found = 0;
+
+ for (i = 0; i < count; i++) {
+ v = regulator_list_voltage(vddarm, i);
+ if (v >= dvfs->vddarm_min && v <= dvfs->vddarm_max)
+ found = 1;
+ }
+
+ if (!found) {
+ pr_debug("cpufreq: %dkHz unsupported by regulator\n",
+ freq->frequency);
+ freq->frequency = CPUFREQ_ENTRY_INVALID;
+ }
+
+ freq++;
+ }
+
+ /* Guess based on having to do an I2C/SPI write; in future we
+ * will be able to query the regulator performance here. */
+ regulator_latency = 1 * 1000 * 1000;
+}
+#endif
+
+static int __init emxx_cpufreq_driver_init(struct cpufreq_policy *policy)
+{
+ int ret;
+ unsigned int i;
+ unsigned int bogomips = 0;
+ struct cpufreq_frequency_table *freq;
+
+ if (emxx_freq_table == NULL) {
+ pr_err("cpufreq: No frequency information for this CPU\n");
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_REGULATOR
+ vddarm = regulator_get(NULL, "vddarm");
+ if (IS_ERR(vddarm)) {
+ ret = PTR_ERR(vddarm);
+ pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
+ pr_err("cpufreq: Only frequency scaling available\n");
+ vddarm = NULL;
+ } else {
+ emxx_cpufreq_config_regulator();
+ }
+#endif
+
+ for_each_online_cpu(i)
+ {
+ bogomips = per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ);
+ }
+
+ emxx_cpufreq = (bogomips + 5)* 1000 / 2;
+
+ freq = emxx_freq_table;
+ while (freq->frequency != CPUFREQ_TABLE_END) {
+
+ if (emxx_cpufreq != freq->frequency) {
+
+ freq->frequency = emxx_cpufreq;
+ }
+
+ freq++;
+ }
+
+ policy->cur = emxx_cpufreq;
+
+ /* Datasheet says PLL stabalisation time (if we were to use
+ * the PLLs, which we don't currently) is ~300us worst case,
+ * but add some fudge.
+ */
+ policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;
+
+ ret = cpufreq_frequency_table_cpuinfo(policy, emxx_freq_table);
+ if (ret != 0) {
+ pr_err("cpufreq: Failed to configure frequency table: %d\n",
+ ret);
+ regulator_put(vddarm);
+ }
+ return ret;
+}
+
+static struct cpufreq_driver emxx_cpufreq_driver = {
+ .owner = THIS_MODULE,
+ .flags = 0,
+ .verify = emxx_cpufreq_verify_speed,
+ .target = emxx_cpufreq_set_target,
+ .get = emxx_cpufreq_get_speed,
+ .init = emxx_cpufreq_driver_init,
+ .name = "emev",
+};
+
+static int __init emxx_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&emxx_cpufreq_driver);
+}
+module_init(emxx_cpufreq_init);
--
1.7.5.4
阅读(2881) | 评论(0) | 转发(0) |