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
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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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
#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"
#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),