rk: pm_tests: add auto_wakeup and clk_auto_volt tool
authorchenxing <chenxing@rock-chips.com>
Fri, 22 Mar 2013 08:12:25 +0000 (16:12 +0800)
committerchenxing <chenxing@rock-chips.com>
Fri, 22 Mar 2013 08:12:25 +0000 (16:12 +0800)
arch/arm/plat-rk/rk_pm_tests/Kconfig
arch/arm/plat-rk/rk_pm_tests/Makefile
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c [new file with mode: 0644]
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h [new file with mode: 0644]
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c [new file with mode: 0644]
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h [new file with mode: 0644]
arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c

index a9ad24fc655d96c0b1c7be75aacb13e09d0dbc46..5247989a057cc4b694a7abafa765bff946ec6100 100755 (executable)
@@ -26,4 +26,15 @@ config PM_TEST_CPU_USAGE
        bool "Set cpu running at a fixed frequency"
        help
          Use to Set cpu running at a fixed frequency
+
+config PM_TEST_AUTO_WAKEUP
+       bool "Auto wakeup"
+       help
+         Use to auto wake up system
+
+config PM_TEST_CLK_AUTO_VOLT
+       bool "Auto scale voltage"
+       help
+         Use to auto scale regulator's voltage by step
+
 endif
index 1f742c866a94857c40c4baac35049dffdbfbcd60..6cd4eb6f5c378e1e6d41c0883d6d6767d6026d21 100644 (file)
@@ -5,4 +5,5 @@ obj-$(CONFIG_PM_TEST_CLK_RATE) += clk_rate.o
 obj-$(CONFIG_PM_TEST_CLK_VOLT) += clk_volt.o
 obj-$(CONFIG_PM_TEST_FREQ_LIMIT) += freq_limit.o
 obj-$(CONFIG_PM_TEST_CPU_USAGE) += cpu_usage.o
-
+obj-$(CONFIG_PM_TEST_AUTO_WAKEUP) += auto_wakeup.o
+obj-$(CONFIG_PM_TEST_CLK_AUTO_VOLT) += clk_auto_volt.o
diff --git a/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c b/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c
new file mode 100644 (file)
index 0000000..067dd52
--- /dev/null
@@ -0,0 +1,97 @@
+#include <linux/android_alarm.h>\r
+#include <linux/mutex.h>\r
+#include <linux/kobject.h>\r
+#include <linux/string.h>\r
+\r
+#include "rk_pm_tests.h"\r
+#include "auto_wakeup.h"\r
+static struct alarm alarm;\r
+static struct timespec period;\r
+static int alarm_status = 0;\r
+static DEFINE_MUTEX(mutex);\r
+\r
+static int get_alarm_status(void)\r
+{\r
+       return alarm_status;\r
+}\r
+\r
+static void alarm_update(struct alarm *alarm)\r
+{\r
+       struct timespec now_time;\r
+       struct timespec new_time;\r
+\r
+       now_time = ktime_to_timespec(alarm_get_elapsed_realtime());\r
+\r
+       PM_DBG("now_time %ld\n",now_time.tv_sec);\r
+\r
+       new_time.tv_sec = now_time.tv_sec + period.tv_sec;\r
+       new_time.tv_nsec = now_time.tv_nsec + period.tv_nsec;\r
+\r
+       alarm_start_range(alarm, timespec_to_ktime(new_time), timespec_to_ktime(new_time));\r
+}\r
+\r
+static void stop_auto_wakeup(void)\r
+{\r
+       mutex_lock(&mutex);\r
+\r
+       if(alarm_status) {\r
+               alarm_cancel(&alarm);\r
+               alarm_status = 0;\r
+       }\r
+\r
+       mutex_unlock(&mutex);\r
+}\r
+\r
+static void start_auto_wakeup(long second)\r
+{\r
+       stop_auto_wakeup();\r
+\r
+       mutex_lock(&mutex);\r
+\r
+       period.tv_sec = second;\r
+       period.tv_nsec = 0;\r
+\r
+       alarm_init(&alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, alarm_update);        \r
+       alarm_update(&alarm);\r
+       alarm_status = 1;\r
+\r
+       mutex_unlock(&mutex);\r
+}\r
+\r
+ssize_t auto_wakeup_show(struct kobject *kobj, struct kobj_attribute *attr,\r
+               char *buf)\r
+{\r
+       char *s = buf;\r
+\r
+       if(get_alarm_status())\r
+               s += sprintf(s, "%s\n", "on");\r
+       else\r
+               s += sprintf(s, "%s\n", "off");\r
+\r
+       return (s - buf);\r
+}\r
+\r
+ssize_t auto_wakeup_store(struct kobject *kobj, struct kobj_attribute *attr,\r
+               const char *buf, size_t n)\r
+{\r
+       char cmd[10];\r
+       long val;\r
+       int len;\r
+       int error = -EINVAL;\r
+\r
+       sscanf(buf, "%s %ld", cmd, &val);\r
+       len = strlen(cmd);\r
+\r
+       if (len == strlen("on") && !strncmp(cmd,"on",len)) {\r
+               start_auto_wakeup(val);\r
+               error = 0;\r
+       }\r
+       else if(len == strlen("off") && !strncmp(cmd,"off",len)) {\r
+               stop_auto_wakeup();\r
+               error = 0;\r
+       }\r
+\r
+       return error ? error : n;\r
+}\r
+\r
+\r
diff --git a/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h b/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h
new file mode 100644 (file)
index 0000000..6967730
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __AUTO_WAKEUP_H \r
+#define __AUTO_WAKEUP_H \r
+\r
+ssize_t auto_wakeup_show(struct kobject *kobj, struct kobj_attribute *attr,\r
+               char *buf);\r
+ssize_t auto_wakeup_store(struct kobject *kobj, struct kobj_attribute *attr,\r
+               const char *buf, size_t n);\r
+\r
+#endif\r
+\r
diff --git a/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c b/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c
new file mode 100644 (file)
index 0000000..fefd4d1
--- /dev/null
@@ -0,0 +1,134 @@
+#include <linux/clk.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+#include <linux/regulator/machine.h>
+#include <mach/dvfs.h>
+
+#include "rk_pm_tests.h"
+#include "clk_auto_volt.h"
+/***************************************************************************/
+#define VOLT_UP    1
+#define VOLT_DOWN  0
+
+static int wq_is_run = 0;
+static unsigned int volt_direction;
+static unsigned int begin_volt;
+static unsigned int stop_volt;
+static unsigned int volt;
+static unsigned int volt_step = 25000;
+static struct regulator *regulator = NULL;
+
+static struct workqueue_struct *scal_volt_wq = NULL;
+static struct delayed_work scal_volt_work;
+
+static unsigned int timer_tick;
+
+static void scal_volt_func(struct work_struct *work)
+{
+       int ret = 0;
+
+       ret = regulator_set_voltage(regulator, volt, volt);
+       if (ret) {
+               PM_ERR("regulator_set_voltage failed!\n");
+               PM_ERR("stop!\n");
+               return;
+       }
+       else
+               PM_DBG("regulator_set_voltage: %d(uV)\n",volt);
+
+       if (volt_direction == VOLT_DOWN) {
+               volt = volt - volt_step;
+               if(volt <  stop_volt) {
+                       PM_DBG("stop!\n");
+                       return;
+               }
+       }
+       else if (volt_direction == VOLT_UP) {
+               volt = volt + volt_step;
+               if (volt > stop_volt) {
+                       PM_DBG("stop!\n");
+                       return;
+               }
+       }
+
+       queue_delayed_work(scal_volt_wq, &scal_volt_work, msecs_to_jiffies(timer_tick*1000));           
+}
+
+ssize_t clk_auto_volt_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf)
+{
+       char *str = buf;
+       str += sprintf(str, "[start/stop] [up/down]  [regulator_name]  [begin_volt(uV)]  [stop_volt(uv)]  [volt_step(uv)]  [timer_tick(s)]\n");
+
+       return (str - buf);
+}
+
+ssize_t clk_auto_volt_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n)
+{
+       char cmd[10];
+       char volt_flag[10];
+       char regulator_name[20];
+
+       sscanf(buf, "%s %s %s %u %u %u %u", cmd, volt_flag, regulator_name, &begin_volt, &stop_volt, &volt_step, &timer_tick);
+
+       if (0 == strncmp(cmd, "start", strlen("start"))) {
+               if (0 == strncmp(volt_flag, "up", strlen("up"))) {      
+                       if (begin_volt >= stop_volt) {
+                               PM_ERR("wrong! begin_volt >= stop_volt!\n");
+                               return -EINVAL;
+                       }
+                       volt_direction = VOLT_UP;                       
+
+               } else if (0 == strncmp(volt_flag, "down", strlen("down"))) {   
+                       if (begin_volt <= stop_volt) {
+                               PM_ERR("wrong! begin_volt <= stop_volt!\n");
+                               return -EINVAL;
+                       }
+                       volt_direction = VOLT_DOWN;
+
+               } else {        
+                       PM_ERR("argument %s is invalid!\n",volt_flag);
+                       return -EINVAL;
+               }
+
+               regulator = dvfs_get_regulator(regulator_name);
+               if (IS_ERR_OR_NULL(regulator)) {
+                       PM_ERR("%s get dvfs_regulator %s error\n", __func__, regulator_name);
+                       return -ENOMEM;
+               }               
+
+               if (wq_is_run == 1) {
+                       cancel_delayed_work(&scal_volt_work);
+                       flush_workqueue(scal_volt_wq);
+                       //destroy_workqueue(scal_volt_wq);
+                       wq_is_run = 0;
+               }
+
+               PM_DBG("begin!\n");             
+
+               volt = begin_volt;
+
+               scal_volt_wq = create_workqueue("scal volt wq");
+               INIT_DELAYED_WORK(&scal_volt_work, scal_volt_func);
+               queue_delayed_work(scal_volt_wq, &scal_volt_work, msecs_to_jiffies(timer_tick*1000));   
+
+               wq_is_run = 1;  
+
+       } else if (0 == strncmp(cmd, "stop", strlen("stop"))) {
+               if (wq_is_run == 1) {
+                       cancel_delayed_work(&scal_volt_work);
+                       flush_workqueue(scal_volt_wq);
+                       //destroy_workqueue(scal_volt_wq);
+                       wq_is_run = 0;
+               }
+
+       } else {
+               PM_ERR("argument %s is invalid!\n", cmd);
+               return -EINVAL;
+       }
+
+       return  n;
+}
+
diff --git a/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h b/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h
new file mode 100644 (file)
index 0000000..d90cff5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _CLK_AUTO_VOLT_H_
+#define _CLK_AUTO_VOLT_H_
+ssize_t clk_auto_volt_show(struct kobject *kobj, struct kobj_attribute *attr,
+               char *buf);
+ssize_t clk_auto_volt_store(struct kobject *kobj, struct kobj_attribute *attr,
+               const char *buf, size_t n);
+
+#endif
index 9330c450c0e1f06189c5d8caf9eaf9600ff1e6e0..4ef2b9d8981de10735e03ad9183c4e2f2d9f987a 100644 (file)
@@ -52,6 +52,8 @@ REVISION 0.01
 #include "clk_volt.h"
 #include "freq_limit.h"
 #include "cpu_usage.h"
+#include "auto_wakeup.h"
+#include "clk_auto_volt.h"
 //#include "rk2928_freq.h"
 //#include "rk2928_max_freq.h"
 //#include "cpu_calc.h"
@@ -82,7 +84,12 @@ static struct pm_attribute pm_attrs[] = {
 #ifdef CONFIG_PM_TEST_CPU_USAGE
        __ATTR(cpu_usage, S_IRUGO | S_IWUSR, cpu_usage_show, cpu_usage_store),
 #endif
-               
+#ifdef CONFIG_PM_TEST_AUTO_WAKEUP
+       __ATTR(auto_wakeup, S_IRUGO | S_IWUSR, auto_wakeup_show, auto_wakeup_store),
+#endif
+#ifdef CONFIG_PM_TEST_CLK_AUTO_VOLT
+       __ATTR(clk_auto_volt, S_IRUGO | S_IWUSR, clk_auto_volt_show, clk_auto_volt_store),
+#endif
 #if 0
        __ATTR(ddr_scale_freq, S_IRUGO | S_IWUSR, ddr_scale_freq_show, ddr_scale_freq_store),
        __ATTR(pmic_delay, S_IRUGO | S_IWUSR, pmic_delay_show, pmic_delay_store),