summaryrefslogtreecommitdiff
path: root/arch/arm/mach-wmt/wmt_cpuidle.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-wmt/wmt_cpuidle.c')
-rwxr-xr-xarch/arm/mach-wmt/wmt_cpuidle.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/arch/arm/mach-wmt/wmt_cpuidle.c b/arch/arm/mach-wmt/wmt_cpuidle.c
new file mode 100755
index 00000000..e4aaf194
--- /dev/null
+++ b/arch/arm/mach-wmt/wmt_cpuidle.c
@@ -0,0 +1,133 @@
+/*++
+linux/arch/arm/mach-wmt/wmt_cpuidle.c
+
+Copyright (c) 2008 WonderMedia Technologies, Inc.
+
+This program is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software Foundation,
+either version 2 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+
+WonderMedia Technologies, Inc.
+10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+--*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <asm/proc-fns.h>
+#include <asm/cpuidle.h>
+
+//#define DEBUG
+#ifdef DEBUG
+static int dbg_mask = 0;
+module_param(dbg_mask, int, S_IRUGO | S_IWUSR);
+#define id_dbg(fmt, args...) \
+ do {\
+ if (dbg_mask) \
+ printk(KERN_ERR "[%s]_%d: " fmt, __func__ , __LINE__, ## args);\
+ } while(0)
+#define id_trace() \
+ do {\
+ if (dbg_mask) \
+ printk(KERN_ERR "trace in %s %d\n", __func__, __LINE__);\
+ } while(0)
+#else
+#define id_dbg(fmt, args...)
+#define id_trace()
+#endif
+
+#define WMT_CPU_IDLE_MAX_STATES 2
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlenex);
+
+/* Actual code that puts the SoC in different idle states */
+static int wmt_enter_idle(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ cpu_do_idle();
+
+ return index;
+}
+
+static struct cpuidle_driver wmt_cpuidle_driver = {
+ .name = "wmt_cpuidle",
+ .owner = THIS_MODULE,
+ .en_core_tk_irqen = 1,
+ /* ARM Wait for interrupt state */
+ .states[0] = ARM_CPUIDLE_WFI_STATE,
+ /* Wait for interrupt and DDR self refresh state */
+ .states[1] = {
+ .enter = wmt_enter_idle,
+ .exit_latency = 10,
+ .target_residency = 100000,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .name = "ZAC_OFF",
+ .desc = "WFI and disable ZAC clock",
+ },
+ .state_count = WMT_CPU_IDLE_MAX_STATES,
+};
+
+static int __init wmt_cpuidle_check_env(void)
+{
+ int ret = 0;
+ int varlen = 128;
+ unsigned int drv_en = 0;
+ unsigned char buf[128] = {0};
+
+ /* uboot env name is: wmt.cpuidle.param/wmt.dvfs.param */
+ ret = wmt_getsyspara("wmt.cpuidle.param", buf, &varlen);
+ if (ret) {
+ printk(KERN_INFO "Can not find uboot env wmt.cpuidle.param\n");
+ ret = -ENODATA;
+ goto out;
+ }
+ id_dbg("wmt.cpuidle.param:%s\n", buf);
+
+ sscanf(buf, "%d", &drv_en);
+ if (!drv_en) {
+ printk(KERN_INFO "wmt cpuidle driver disaled\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static DEFINE_PER_CPU(struct cpuidle_device, wmt_cpuidle_device);
+static int __init wmt_cpuidle_driver_init(void)
+{
+ struct cpuidle_device *device = NULL;
+
+ if (wmt_cpuidle_check_env()) {
+ printk(KERN_WARNING "wmt_cpuidle check env failed!\n");
+ return -EINVAL;
+ }
+
+ device = &per_cpu(wmt_cpuidle_device, smp_processor_id());
+ device->state_count = WMT_CPU_IDLE_MAX_STATES;
+
+ cpuidle_register_driver(&wmt_cpuidle_driver);
+ if (cpuidle_register_device(device)) {
+ printk(KERN_ERR "wmt_cpuidle_driver_init: Failed registering\n");
+ return -EIO;
+ }
+
+ printk(KERN_INFO "WMT cpuidle driver register\n");
+ return 0;
+}
+module_init(wmt_cpuidle_driver_init);
+
+MODULE_AUTHOR("WonderMedia Technologies, Inc");
+MODULE_DESCRIPTION("WMT CPU idle driver");
+MODULE_LICENSE("Dual BSD/GPL");