add /sys/pm_tests/ support
author陈亮 <cl@rock-chips.com>
Fri, 28 Mar 2014 02:44:10 +0000 (19:44 -0700)
committer陈亮 <cl@rock-chips.com>
Fri, 28 Mar 2014 02:44:10 +0000 (19:44 -0700)
13 files changed:
arch/arm/mach-rockchip/Kconfig
arch/arm/mach-rockchip/Makefile
arch/arm/mach-rockchip/rk_pm_tests/Makefile [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h [new file with mode: 0644]

index 38be8148c6900df0b6c380713925ab8c16e55205..4f8e4e76c3e1b4d6529733a4fac1c931f243cb9f 100755 (executable)
@@ -54,6 +54,11 @@ config DVFS
        select PM_OPP
        select CPU_FREQ
 
+config RK_PM_TESTS
+       bool "/sys/pm_tests/ support"
+       default n
+       select DVFS
+
 config RK_VPU
        tristate "VPU (Video Processing Unit) service driver in kernel"
        depends on ARCH_ROCKCHIP
index 1d183fde52b45a0ddc9f9c078143af24efae6a05..e2c2c878eece35b31e629bea04f35337540af4ee 100755 (executable)
@@ -14,3 +14,4 @@ obj-$(CONFIG_RK_VCODEC) += vcodec_service.o
 obj-$(CONFIG_RK_VPU) += vpu_service.o
 obj-$(CONFIG_RK_PL330_DMA_TEST) += dma_memcpy_test.o
 obj-$(CONFIG_BLOCK_RKNAND) += rknandbase.o
+obj-$(CONFIG_RK_PM_TESTS) += rk_pm_tests/
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/Makefile b/arch/arm/mach-rockchip/rk_pm_tests/Makefile
new file mode 100644 (file)
index 0000000..f83d41c
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y += rk_pm_tests.o
+obj-y += clk_rate.o
+obj-y += clk_volt.o
+obj-y += clk_volt.o
+obj-y += dvfs_table_scan.o
\ No newline at end of file
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c
new file mode 100644 (file)
index 0000000..ec9aed6
--- /dev/null
@@ -0,0 +1,154 @@
+#include <linux/clk.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/resume-trace.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+
+#include <linux/fs.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include <linux/rockchip/dvfs.h>
+
+#include "rk_pm_tests.h"
+#include "clk_rate.h"
+/***************************************************************************/
+#define FILE_GOV_MODE "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
+#define FILE_SETSPEED "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
+#define FILE_CUR_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
+
+static int file_read(char *file_path, char *buf)
+{
+       struct file *file = NULL;
+       mm_segment_t old_fs;
+       loff_t offset = 0;
+
+       PM_DBG("read %s\n", file_path);
+       file = filp_open(file_path, O_RDONLY, 0);
+
+       if (IS_ERR(file)) {
+               PM_ERR("%s error open file  %s\n", __func__, file_path);
+               return -1;
+       }
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       file->f_op->read(file, (char *)buf, 32, &offset);
+       sscanf(buf, "%s", buf);
+
+       set_fs(old_fs);
+       filp_close(file, NULL);  
+
+       file = NULL;
+
+       return 0;
+
+}
+
+static int file_write(char *file_path, char *buf)
+{
+       struct file *file = NULL;
+       mm_segment_t old_fs;
+       loff_t offset = 0;
+
+       PM_DBG("write %s %s size = %d\n", file_path, buf, strlen(buf));
+       file = filp_open(file_path, O_RDWR, 0);
+
+       if (IS_ERR(file)) {
+               PM_ERR("%s error open file  %s\n", __func__, file_path);
+               return -1;
+       }
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       file->f_op->write(file, (char *)buf, strlen(buf), &offset);
+
+       set_fs(old_fs);
+       filp_close(file, NULL);  
+
+       file = NULL;
+
+       return 0;
+
+}
+
+ssize_t clk_rate_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       char *str = buf;
+       str += sprintf(str, "set        [clk_name]      [rate(Hz)]\n"
+                       "reset  [clk_name]      [rate(Hz) = 0]\n");
+       if (str != buf)
+               *(str - 1) = '\n';
+       return (str - buf);
+
+}
+
+ssize_t clk_rate_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n)
+{
+       struct dvfs_node *clk_dvfs_node = NULL;
+       char cmd[20], clk_name[20], msg[50];
+       int rate;
+       printk("%s: %s\n", __func__, buf);
+       sscanf(buf, "%s %s %d", cmd, clk_name, &rate);
+
+       clk_dvfs_node = clk_get_dvfs_node(clk_name);
+       if (!clk_dvfs_node) {
+               PM_ERR("%s: clk(%s) get dvfs node error\n", __func__, clk_name);
+               return n;
+       }
+
+       if (0 == strncmp(cmd, "set", strlen("set"))) {
+               PM_DBG("Get command set %s %dHz\n", clk_name, rate);
+               if (file_read(FILE_GOV_MODE, msg) != 0) {
+                       PM_ERR("read current governor error\n");
+                       return n;
+               } else {
+                       PM_DBG("current governor = %s\n", msg);
+               }
+
+               strcpy(msg, "userspace");
+               if (file_write(FILE_GOV_MODE, msg) != 0) {
+                       PM_ERR("set current governor error\n");
+                       return n;
+               }
+
+               dvfs_clk_enable_limit(clk_dvfs_node, rate, rate);
+               dvfs_clk_set_rate(clk_dvfs_node, rate);
+
+       } else if (0 == strncmp(cmd, "reset", strlen("reset"))) {       
+               PM_DBG("Get command reset %s\n", clk_name);
+               if (file_read(FILE_GOV_MODE, msg) != 0) {
+                       PM_ERR("read current governor error\n");
+                       return n;
+               } else {
+                       PM_DBG("current governor = %s\n", msg);
+               }
+
+               strcpy(msg, "interactive");
+               if (file_write(FILE_GOV_MODE, msg) != 0) {
+                       PM_ERR("set current governor error\n");
+                       return n;
+               }
+
+               dvfs_clk_disable_limit(clk_dvfs_node);
+       }
+       
+       return n;
+}
+
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h
new file mode 100644 (file)
index 0000000..bfb649d
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _CLK_RATE_H_
+#define _CLK_RATE_H_
+ssize_t clk_rate_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf);
+ssize_t clk_rate_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n);
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c
new file mode 100644 (file)
index 0000000..6314145
--- /dev/null
@@ -0,0 +1,93 @@
+#include <linux/clk.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/resume-trace.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/regulator/machine.h>
+//#include <plat/dma-pl330.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/rockchip/dvfs.h>
+
+//#include <mach/ddr.h>
+//#include <mach/dvfs.h>
+
+#include "rk_pm_tests.h"
+#include "clk_volt.h"
+/***************************************************************************/
+ssize_t clk_volt_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       char *str = buf;
+       str += sprintf(str, "usage:\n");
+       str += sprintf(str, "get voltage:get [regulaotr_name]\n");
+       str += sprintf(str, "set voltage:set [regulaotr_name] [voltage(uV)]\n");
+       str += sprintf(str, "set suspend voltage:set [regulaotr_name] [voltage(uV)+1]\n");
+       if (str != buf)
+               *(str - 1) = '\n';
+       return (str - buf);
+
+}
+
+#define SET_SUSPEND_VOLT_FLAG  (1<<0)
+
+ssize_t clk_volt_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n)
+{
+       char cmd[20], regulator_name[20];
+       unsigned int volt;
+       int ret = 0;
+       int need_put_regulator=0;
+       struct regulator *regulator;
+
+       printk("%s: %s\n", __func__, buf);
+       sscanf(buf, "%s %s %u", cmd, regulator_name, &volt);
+
+       regulator = dvfs_get_regulator(regulator_name);
+       if (IS_ERR_OR_NULL(regulator)) {
+               regulator = regulator_get(NULL, regulator_name);
+               if (IS_ERR(regulator)){
+                       PM_ERR("%s get dvfs_regulator %s error\n", __func__, regulator_name);
+                       return n;
+               }
+               need_put_regulator = 1;
+       }       
+
+       if (0 == strncmp(cmd, "set", strlen("set"))){
+               if (volt & SET_SUSPEND_VOLT_FLAG){
+                       volt &= ~SET_SUSPEND_VOLT_FLAG;
+                       //ret = regulator_set_suspend_voltage(regulator, volt); 
+                       if (!ret)
+                               printk("set %s suspend volt to %uuV ok\n", regulator_name, volt);
+                       else
+                               printk("regulator_set_suspend_voltage err:%d\n", ret);
+               }else{
+                       ret = regulator_set_voltage(regulator, volt, volt); 
+                       if (!ret)
+                               printk("set %s volt to %uuV ok\n", regulator_name, regulator_get_voltage(regulator));
+                       else
+                               printk("regulator_set_voltage err:%d\n", ret);
+               }
+               
+       }
+       if (0 == strncmp(cmd, "get", strlen("get"))){
+               printk("%s:%duV\n", regulator_name, regulator_get_voltage(regulator));
+       }
+
+       if (need_put_regulator)
+               regulator_put(regulator);
+
+//     if (0 == strncmp(cmd, "enable", strlen("enable"))) {
+       return n;
+}
+
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h
new file mode 100644 (file)
index 0000000..346bd20
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _CLK_VOLT_H_
+#define _CLK_VOLT_H_
+ssize_t clk_volt_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf);
+ssize_t clk_volt_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n);
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c
new file mode 100644 (file)
index 0000000..3089e3d
--- /dev/null
@@ -0,0 +1,139 @@
+#include <linux/clk.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/resume-trace.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/regulator/machine.h>
+#include <plat/dma-pl330.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <mach/cru.h>
+#include <mach/dvfs.h>
+#include <mach/sram.h>
+#include <linux/random.h>
+
+#include <linux/fs.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include "rk_pm_tests.h"
+#include "cpu_usage.h"
+/***************************************************************************/
+static DEFINE_PER_CPU(struct work_struct, work_cpu_usage);
+static DEFINE_PER_CPU(struct workqueue_struct *, workqueue_cpu_usage);
+
+int cpu_usage_run = 0;
+int cpu_usage_percent = 0;
+
+struct timer_list arm_mode_timer;
+#define ARM_MODE_TIMER_MSEC    100
+static void arm_mode_timer_handler(unsigned long data)
+{
+       int i;
+       PM_DBG("enter %s\n", __func__);
+       if (cpu_usage_run == 0) {
+               PM_DBG("STOP\n");
+               return ;
+       }
+
+       arm_mode_timer.expires  = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC);
+       add_timer(&arm_mode_timer);
+       for(i = 0; i < cpu_usage_percent; i++) {
+               mdelay(1);
+       }
+}
+
+static void handler_cpu_usage(struct work_struct *work)
+{      
+#if 1
+       while(cpu_usage_run) {
+               barrier();
+       }
+#else
+       del_timer(&arm_mode_timer);
+       arm_mode_timer.expires  = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC);
+       add_timer(&arm_mode_timer);
+#endif
+}
+ssize_t cpu_usage_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       char *str = buf;
+       str += sprintf(str, "HELLO\n");
+       if (str != buf)
+               *(str - 1) = '\n';
+       return (str - buf);
+
+}
+ssize_t cpu_usage_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n)
+{
+       struct workqueue_struct *workqueue;
+       struct work_struct *work;
+       char cmd[20];
+       int usage = 0;
+       int cpu;
+
+       sscanf(buf, "%s %d", cmd, &usage);
+
+       if((strncmp(cmd, "start", strlen("start")) == 0)) {
+               PM_DBG("get cmd start\n");
+               cpu_usage_run = 1;
+               
+               cpu_usage_percent = (ARM_MODE_TIMER_MSEC * usage) / 100;
+
+
+               for_each_online_cpu(cpu){
+                       work = &per_cpu(work_cpu_usage, cpu);
+                       workqueue = per_cpu(workqueue_cpu_usage, cpu);
+                       if (!work || !workqueue){
+                               PM_ERR("work or workqueue NULL\n");
+                               return n;
+                       }       
+                       queue_work_on(cpu, workqueue, work);
+               }
+#if 0
+               del_timer(&arm_mode_timer);
+               arm_mode_timer.expires  = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC);
+               add_timer(&arm_mode_timer);
+#endif
+       
+       } else if (strncmp(cmd, "stop", strlen("stop")) == 0) {
+               PM_DBG("get cmd stop\n");
+               cpu_usage_run = 0;
+       }
+
+       return n;
+}
+
+static int __init cpu_usage_init(void)
+{
+       struct workqueue_struct **workqueue;
+       struct work_struct      *work;
+       int cpu;
+       
+       for_each_online_cpu(cpu){       
+               work = &per_cpu(work_cpu_usage, cpu);
+               workqueue = &per_cpu(workqueue_cpu_usage, cpu);
+               if (!work || !workqueue){
+                       PM_ERR("work or workqueue NULL\n");
+                       return -1;
+               }
+                       
+               *workqueue = create_singlethread_workqueue("workqueue_cpu_usage");
+               INIT_WORK(work, handler_cpu_usage);
+       }
+
+       setup_timer(&arm_mode_timer, arm_mode_timer_handler, (unsigned int)NULL);
+       return 0;
+}
+late_initcall(cpu_usage_init);
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h
new file mode 100644 (file)
index 0000000..0c45ad4
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _CPU_USAGE_H_
+#define _CPU_USAGE_H_
+ssize_t cpu_usage_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf);
+ssize_t cpu_usage_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n);
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c
new file mode 100644 (file)
index 0000000..2f68ee5
--- /dev/null
@@ -0,0 +1,94 @@
+#include <linux/clk.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/resume-trace.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/regulator/machine.h>
+//#include <plat/dma-pl330.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+//#include <mach/ddr.h>
+//#include <mach/dvfs.h>
+#include <linux/watchdog.h>
+
+
+#include <linux/fs.h>
+#include <asm/unistd.h>
+#include <asm/uaccess.h>
+#include "rk_pm_tests.h"
+#include "rk_pm_tests.h"
+#include "dvfs_table_scan.h"
+/***************************************************************************/
+struct workqueue_struct        *workqueue_dvfs_table_scan;
+struct work_struct     work_dvfs_table_scan;
+struct timer_list dvfs_table_scan_timer;
+#define DVFS_TABLE_T_MSEC      1000
+struct file *file = NULL;
+mm_segment_t old_fs;
+loff_t offset = 0;
+static int dvfs_table_scan_run = 0;
+
+ssize_t dvfs_table_scan_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       char *str = buf;
+       str += sprintf(str, "start: \tstart scan dvfs table, send alive every 1s\n"
+                       "stop: \tstop send alive signal\n");
+       if (str != buf)
+               *(str - 1) = '\n';
+       return (str - buf);
+
+}
+void rk29_wdt_start(void);
+void rk29_wdt_stop(void);
+void rk29_wdt_keepalive(void);
+int rk29_wdt_set_heartbeat(int timeout);
+
+#define ALIVE_INTERVAL                 2       //s
+#define WATCHDOG_TIMEOUT               (10*ALIVE_INTERVAL)
+#define RESERVE_TIME_FOR_TIMEOUT       600000  //ms
+
+ssize_t dvfs_table_scan_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n)
+{
+       char cmd[20];
+       int cur_test_need_time=0; //ms
+       static int cur_test_timeout_cnt = 0, start_flag = 0;
+
+       sscanf(buf, "%s %d", cmd, &cur_test_need_time);
+
+       printk("%s: get command <%s>\n", __func__, cmd);
+       if (0 == strncmp(cmd, "start", strlen("start"))) {
+               if (cur_test_need_time == 0)
+                       return n;
+               cur_test_timeout_cnt = (cur_test_need_time + RESERVE_TIME_FOR_TIMEOUT)/1000/ALIVE_INTERVAL;
+               rk29_wdt_start();
+               rk29_wdt_set_heartbeat(WATCHDOG_TIMEOUT);
+               start_flag = 1;
+       } else if (0 == strncmp(cmd, "alive", strlen("alive"))) {
+               if(start_flag == 0)
+                       return n;
+               printk("cur_test_timeout_cnt:%d\n", cur_test_timeout_cnt);
+               if (cur_test_timeout_cnt-- > 0)         
+                       rk29_wdt_keepalive();
+
+       } else if (0 == strncmp(cmd, "stop", strlen("stop"))) {
+               if(start_flag == 0)
+                       return n;
+               cur_test_timeout_cnt = -1;
+               rk29_wdt_stop();
+               start_flag = 0;
+       }
+
+       return n;
+}
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h
new file mode 100644 (file)
index 0000000..bef9f7b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _DVFS_TABLE_SCAN_H_
+#define _DVFS_TABLE_SCAN_H_
+ssize_t dvfs_table_scan_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf);
+ssize_t dvfs_table_scan_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n);
+
+#endif
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c
new file mode 100644 (file)
index 0000000..f924302
--- /dev/null
@@ -0,0 +1,105 @@
+/* arch/arm/mach-rk30/rk_pm_tests.c
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+
+/*************************************************************************/
+/*       COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.*/
+/*************************************************************************
+FILE           :         rk_pm_tests.c
+DESC           :         Power management in dynning state
+AUTHOR         :         chenxing
+DATE           :         2012-7-2
+NOTES          :
+$LOG: GPIO.C,V $
+REVISION 0.01
+#include <linux/clk.h>
+#include <linux/kobject.h>
+ ***************************************************************************/
+#include <linux/string.h>
+#include <linux/resume-trace.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/regulator/machine.h>
+//#include <plat/dma-pl330.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+//#include <mach/ddr.h>
+
+#include "rk_pm_tests.h"
+
+#include "clk_rate.h"
+#include "clk_volt.h"
+#include "cpu_usage.h"
+#include "dvfs_table_scan.h"
+
+static struct kobject *pm_tests_kobj;
+struct pm_attribute {
+       struct attribute        attr;
+       ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
+                       char *buf);
+       ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
+                       const char *buf, size_t n);
+};
+
+static struct pm_attribute pm_attrs[] = {
+       /* node_name    permision       show_func       store_func*/
+       __ATTR(clk_rate, S_IRUGO | S_IWUSR | S_IWUGO, clk_rate_show, clk_rate_store),
+       __ATTR(clk_volt, S_IRUGO | S_IWUSR | S_IWUGO, clk_volt_show, clk_volt_store),
+       __ATTR(dvfs_table_scan, S_IRUGO | S_IWUSR | S_IWUGO, dvfs_table_scan_show, dvfs_table_scan_store),
+/*
+       __ATTR(maxfreq_volt, S_IRUGO | S_IWUSR, maxfreq_show, maxfreq_store),
+       __ATTR(freq_limit, S_IRUGO | S_IWUSR, freq_limit_show, freq_limit_store),
+       __ATTR(cpu_usage, S_IRUGO | S_IWUSR, cpu_usage_show, cpu_usage_store),
+       __ATTR(auto_wakeup, S_IRUGO | S_IWUSR, auto_wakeup_show, auto_wakeup_store),
+       __ATTR(suspend_test,   S_IRUGO | S_IWUSR,   suspend_test_show, suspend_test_store),
+       __ATTR(clk_auto_volt, S_IRUGO | S_IWUSR, clk_auto_volt_show, clk_auto_volt_store),
+*/
+};
+
+static void __exit rk_pm_tests_exit(void)
+{
+       kobject_put(pm_tests_kobj);
+}
+
+static int __init rk_pm_tests_init(void)
+{
+       int i, ret = 0;
+       pm_tests_kobj = kobject_create_and_add("pm_tests", NULL);
+
+       if (!pm_tests_kobj)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(pm_attrs); i++) {
+               ret = sysfs_create_file(pm_tests_kobj, &pm_attrs[i].attr);
+               if (ret != 0) {
+                       PM_ERR("create index %d error\n", i);
+                       return ret;
+               }
+       }
+       
+       return ret;
+}
+
+late_initcall(rk_pm_tests_init);
+module_exit(rk_pm_tests_exit);
diff --git a/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h
new file mode 100644 (file)
index 0000000..2d4abb5
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef _RK_PM_TESTS_H_
+#define _RK_PM_TESTS_H_
+#define PM_DBG(fmt, args...) printk(KERN_INFO "PM_TESTS_DBG:\t"fmt, ##args)
+#define PM_ERR(fmt, args...) printk(KERN_ERR "PM_TESTS_ERR:\t"fmt, ##args)
+#endif