mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
rk: pm_tests: add auto_wakeup and clk_auto_volt tool
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
97
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c
Normal file
97
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
10
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h
Normal file
10
arch/arm/plat-rk/rk_pm_tests/auto_wakeup.h
Normal 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
|
||||
|
||||
134
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c
Normal file
134
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.c
Normal 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;
|
||||
}
|
||||
|
||||
8
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h
Normal file
8
arch/arm/plat-rk/rk_pm_tests/clk_auto_volt.h
Normal 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
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user