From 1e778d3e934fc8f32e19f2109c2a8787c213beea Mon Sep 17 00:00:00 2001 From: chenxing Date: Fri, 22 Mar 2013 16:12:25 +0800 Subject: [PATCH] rk: pm_tests: add auto_wakeup and clk_auto_volt tool --- arch/arm/plat-rk/rk_pm_tests/Kconfig | 11 ++ arch/arm/plat-rk/rk_pm_tests/Makefile | 3 +- arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c | 97 ++++++++++++++ arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h | 10 ++ arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c | 134 +++++++++++++++++++ arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h | 8 ++ arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c | 9 +- 7 files changed, 270 insertions(+), 2 deletions(-) create mode 100644 arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c create mode 100644 arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h create mode 100644 arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c create mode 100644 arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h diff --git a/arch/arm/plat-rk/rk_pm_tests/Kconfig b/arch/arm/plat-rk/rk_pm_tests/Kconfig index a9ad24fc655d..5247989a057c 100755 --- a/arch/arm/plat-rk/rk_pm_tests/Kconfig +++ b/arch/arm/plat-rk/rk_pm_tests/Kconfig @@ -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 diff --git a/arch/arm/plat-rk/rk_pm_tests/Makefile b/arch/arm/plat-rk/rk_pm_tests/Makefile index 1f742c866a94..6cd4eb6f5c37 100644 --- a/arch/arm/plat-rk/rk_pm_tests/Makefile +++ b/arch/arm/plat-rk/rk_pm_tests/Makefile @@ -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 index 000000000000..067dd52541c9 --- /dev/null +++ b/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +#include "rk_pm_tests.h" +#include "auto_wakeup.h" +static struct alarm alarm; +static struct timespec period; +static int alarm_status = 0; +static DEFINE_MUTEX(mutex); + +static int get_alarm_status(void) +{ + return alarm_status; +} + +static void alarm_update(struct alarm *alarm) +{ + struct timespec now_time; + struct timespec new_time; + + now_time = ktime_to_timespec(alarm_get_elapsed_realtime()); + + PM_DBG("now_time %ld\n",now_time.tv_sec); + + new_time.tv_sec = now_time.tv_sec + period.tv_sec; + new_time.tv_nsec = now_time.tv_nsec + period.tv_nsec; + + alarm_start_range(alarm, timespec_to_ktime(new_time), timespec_to_ktime(new_time)); +} + +static void stop_auto_wakeup(void) +{ + mutex_lock(&mutex); + + if(alarm_status) { + alarm_cancel(&alarm); + alarm_status = 0; + } + + mutex_unlock(&mutex); +} + +static void start_auto_wakeup(long second) +{ + stop_auto_wakeup(); + + mutex_lock(&mutex); + + period.tv_sec = second; + period.tv_nsec = 0; + + alarm_init(&alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, alarm_update); + alarm_update(&alarm); + alarm_status = 1; + + mutex_unlock(&mutex); +} + +ssize_t auto_wakeup_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *s = buf; + + if(get_alarm_status()) + s += sprintf(s, "%s\n", "on"); + else + s += sprintf(s, "%s\n", "off"); + + return (s - buf); +} + +ssize_t auto_wakeup_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + char cmd[10]; + long val; + int len; + int error = -EINVAL; + + sscanf(buf, "%s %ld", cmd, &val); + len = strlen(cmd); + + if (len == strlen("on") && !strncmp(cmd,"on",len)) { + start_auto_wakeup(val); + error = 0; + } + else if(len == strlen("off") && !strncmp(cmd,"off",len)) { + stop_auto_wakeup(); + error = 0; + } + + return error ? error : n; +} + + 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 index 000000000000..6967730777e6 --- /dev/null +++ b/arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h @@ -0,0 +1,10 @@ +#ifndef __AUTO_WAKEUP_H +#define __AUTO_WAKEUP_H + +ssize_t auto_wakeup_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); +ssize_t auto_wakeup_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); + +#endif + 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 index 000000000000..fefd4d1a22b4 --- /dev/null +++ b/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include + +#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 index 000000000000..d90cff5b39f0 --- /dev/null +++ b/arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h @@ -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 diff --git a/arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c b/arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c index 9330c450c0e1..4ef2b9d8981d 100644 --- a/arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c +++ b/arch/arm/plat-rk/rk_pm_tests/rk_pm_tests.c @@ -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), -- 2.34.1