rk: pm_tests: add auto_wakeup and clk_auto_volt tool

This commit is contained in:
chenxing
2013-03-22 16:12:25 +08:00
parent aaccf500d6
commit 1e778d3e93
7 changed files with 270 additions and 2 deletions

View File

@@ -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

View 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

View File

@@ -0,0 +1,97 @@
#include <linux/android_alarm.h>
#include <linux/mutex.h>
#include <linux/kobject.h>
#include <linux/string.h>
#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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View 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),