From 5c3dd6a93723acabd2772114e2100b1f9d27c323 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=99=88=E4=BA=AE?= Date: Thu, 27 Mar 2014 19:44:10 -0700 Subject: [PATCH] add /sys/pm_tests/ support --- arch/arm/mach-rockchip/Kconfig | 5 + arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/rk_pm_tests/Makefile | 5 + arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c | 154 ++++++++++++++++++ arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h | 8 + arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c | 93 +++++++++++ arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h | 8 + .../arm/mach-rockchip/rk_pm_tests/cpu_usage.c | 139 ++++++++++++++++ .../arm/mach-rockchip/rk_pm_tests/cpu_usage.h | 8 + .../rk_pm_tests/dvfs_table_scan.c | 94 +++++++++++ .../rk_pm_tests/dvfs_table_scan.h | 8 + .../mach-rockchip/rk_pm_tests/rk_pm_tests.c | 105 ++++++++++++ .../mach-rockchip/rk_pm_tests/rk_pm_tests.h | 5 + 13 files changed, 633 insertions(+) create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/Makefile create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c create mode 100644 arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 38be8148c690..4f8e4e76c3e1 100755 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -54,6 +54,11 @@ config DVFS select PM_OPP select CPU_FREQ +config RK_PM_TESTS + bool "/sys/pm_tests/ support" + default n + select DVFS + config RK_VPU tristate "VPU (Video Processing Unit) service driver in kernel" depends on ARCH_ROCKCHIP diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 1d183fde52b4..e2c2c878eece 100755 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_RK_VCODEC) += vcodec_service.o obj-$(CONFIG_RK_VPU) += vpu_service.o obj-$(CONFIG_RK_PL330_DMA_TEST) += dma_memcpy_test.o obj-$(CONFIG_BLOCK_RKNAND) += rknandbase.o +obj-$(CONFIG_RK_PM_TESTS) += rk_pm_tests/ diff --git a/arch/arm/mach-rockchip/rk_pm_tests/Makefile b/arch/arm/mach-rockchip/rk_pm_tests/Makefile new file mode 100644 index 000000000000..f83d41ce34d9 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/Makefile @@ -0,0 +1,5 @@ +obj-y += rk_pm_tests.o +obj-y += clk_rate.o +obj-y += clk_volt.o +obj-y += clk_volt.o +obj-y += dvfs_table_scan.o \ No newline at end of file diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c new file mode 100644 index 000000000000..ec9aed64d36e --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "rk_pm_tests.h" +#include "clk_rate.h" +/***************************************************************************/ +#define FILE_GOV_MODE "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" +#define FILE_SETSPEED "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed" +#define FILE_CUR_FREQ "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" + +static int file_read(char *file_path, char *buf) +{ + struct file *file = NULL; + mm_segment_t old_fs; + loff_t offset = 0; + + PM_DBG("read %s\n", file_path); + file = filp_open(file_path, O_RDONLY, 0); + + if (IS_ERR(file)) { + PM_ERR("%s error open file %s\n", __func__, file_path); + return -1; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + file->f_op->read(file, (char *)buf, 32, &offset); + sscanf(buf, "%s", buf); + + set_fs(old_fs); + filp_close(file, NULL); + + file = NULL; + + return 0; + +} + +static int file_write(char *file_path, char *buf) +{ + struct file *file = NULL; + mm_segment_t old_fs; + loff_t offset = 0; + + PM_DBG("write %s %s size = %d\n", file_path, buf, strlen(buf)); + file = filp_open(file_path, O_RDWR, 0); + + if (IS_ERR(file)) { + PM_ERR("%s error open file %s\n", __func__, file_path); + return -1; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + file->f_op->write(file, (char *)buf, strlen(buf), &offset); + + set_fs(old_fs); + filp_close(file, NULL); + + file = NULL; + + return 0; + +} + +ssize_t clk_rate_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *str = buf; + str += sprintf(str, "set [clk_name] [rate(Hz)]\n" + "reset [clk_name] [rate(Hz) = 0]\n"); + if (str != buf) + *(str - 1) = '\n'; + return (str - buf); + +} + +ssize_t clk_rate_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + struct dvfs_node *clk_dvfs_node = NULL; + char cmd[20], clk_name[20], msg[50]; + int rate; + printk("%s: %s\n", __func__, buf); + sscanf(buf, "%s %s %d", cmd, clk_name, &rate); + + clk_dvfs_node = clk_get_dvfs_node(clk_name); + if (!clk_dvfs_node) { + PM_ERR("%s: clk(%s) get dvfs node error\n", __func__, clk_name); + return n; + } + + if (0 == strncmp(cmd, "set", strlen("set"))) { + PM_DBG("Get command set %s %dHz\n", clk_name, rate); + if (file_read(FILE_GOV_MODE, msg) != 0) { + PM_ERR("read current governor error\n"); + return n; + } else { + PM_DBG("current governor = %s\n", msg); + } + + strcpy(msg, "userspace"); + if (file_write(FILE_GOV_MODE, msg) != 0) { + PM_ERR("set current governor error\n"); + return n; + } + + dvfs_clk_enable_limit(clk_dvfs_node, rate, rate); + dvfs_clk_set_rate(clk_dvfs_node, rate); + + } else if (0 == strncmp(cmd, "reset", strlen("reset"))) { + PM_DBG("Get command reset %s\n", clk_name); + if (file_read(FILE_GOV_MODE, msg) != 0) { + PM_ERR("read current governor error\n"); + return n; + } else { + PM_DBG("current governor = %s\n", msg); + } + + strcpy(msg, "interactive"); + if (file_write(FILE_GOV_MODE, msg) != 0) { + PM_ERR("set current governor error\n"); + return n; + } + + dvfs_clk_disable_limit(clk_dvfs_node); + } + + return n; +} + diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h new file mode 100644 index 000000000000..bfb649d09a36 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/clk_rate.h @@ -0,0 +1,8 @@ +#ifndef _CLK_RATE_H_ +#define _CLK_RATE_H_ +ssize_t clk_rate_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); +ssize_t clk_rate_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); + +#endif diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c new file mode 100644 index 000000000000..631414519c37 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +//#include +//#include + +#include "rk_pm_tests.h" +#include "clk_volt.h" +/***************************************************************************/ +ssize_t clk_volt_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *str = buf; + str += sprintf(str, "usage:\n"); + str += sprintf(str, "get voltage:get [regulaotr_name]\n"); + str += sprintf(str, "set voltage:set [regulaotr_name] [voltage(uV)]\n"); + str += sprintf(str, "set suspend voltage:set [regulaotr_name] [voltage(uV)+1]\n"); + if (str != buf) + *(str - 1) = '\n'; + return (str - buf); + +} + +#define SET_SUSPEND_VOLT_FLAG (1<<0) + +ssize_t clk_volt_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + char cmd[20], regulator_name[20]; + unsigned int volt; + int ret = 0; + int need_put_regulator=0; + struct regulator *regulator; + + printk("%s: %s\n", __func__, buf); + sscanf(buf, "%s %s %u", cmd, regulator_name, &volt); + + regulator = dvfs_get_regulator(regulator_name); + if (IS_ERR_OR_NULL(regulator)) { + regulator = regulator_get(NULL, regulator_name); + if (IS_ERR(regulator)){ + PM_ERR("%s get dvfs_regulator %s error\n", __func__, regulator_name); + return n; + } + need_put_regulator = 1; + } + + if (0 == strncmp(cmd, "set", strlen("set"))){ + if (volt & SET_SUSPEND_VOLT_FLAG){ + volt &= ~SET_SUSPEND_VOLT_FLAG; + //ret = regulator_set_suspend_voltage(regulator, volt); + if (!ret) + printk("set %s suspend volt to %uuV ok\n", regulator_name, volt); + else + printk("regulator_set_suspend_voltage err:%d\n", ret); + }else{ + ret = regulator_set_voltage(regulator, volt, volt); + if (!ret) + printk("set %s volt to %uuV ok\n", regulator_name, regulator_get_voltage(regulator)); + else + printk("regulator_set_voltage err:%d\n", ret); + } + + } + if (0 == strncmp(cmd, "get", strlen("get"))){ + printk("%s:%duV\n", regulator_name, regulator_get_voltage(regulator)); + } + + if (need_put_regulator) + regulator_put(regulator); + +// if (0 == strncmp(cmd, "enable", strlen("enable"))) { + return n; +} + diff --git a/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h new file mode 100644 index 000000000000..346bd20bfea2 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/clk_volt.h @@ -0,0 +1,8 @@ +#ifndef _CLK_VOLT_H_ +#define _CLK_VOLT_H_ +ssize_t clk_volt_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); +ssize_t clk_volt_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); + +#endif diff --git a/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c new file mode 100644 index 000000000000..3089e3de3b12 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "rk_pm_tests.h" +#include "cpu_usage.h" +/***************************************************************************/ +static DEFINE_PER_CPU(struct work_struct, work_cpu_usage); +static DEFINE_PER_CPU(struct workqueue_struct *, workqueue_cpu_usage); + +int cpu_usage_run = 0; +int cpu_usage_percent = 0; + +struct timer_list arm_mode_timer; +#define ARM_MODE_TIMER_MSEC 100 +static void arm_mode_timer_handler(unsigned long data) +{ + int i; + PM_DBG("enter %s\n", __func__); + if (cpu_usage_run == 0) { + PM_DBG("STOP\n"); + return ; + } + + arm_mode_timer.expires = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC); + add_timer(&arm_mode_timer); + for(i = 0; i < cpu_usage_percent; i++) { + mdelay(1); + } +} + +static void handler_cpu_usage(struct work_struct *work) +{ +#if 1 + while(cpu_usage_run) { + barrier(); + } +#else + del_timer(&arm_mode_timer); + arm_mode_timer.expires = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC); + add_timer(&arm_mode_timer); +#endif +} +ssize_t cpu_usage_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *str = buf; + str += sprintf(str, "HELLO\n"); + if (str != buf) + *(str - 1) = '\n'; + return (str - buf); + +} +ssize_t cpu_usage_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + struct workqueue_struct *workqueue; + struct work_struct *work; + char cmd[20]; + int usage = 0; + int cpu; + + sscanf(buf, "%s %d", cmd, &usage); + + if((strncmp(cmd, "start", strlen("start")) == 0)) { + PM_DBG("get cmd start\n"); + cpu_usage_run = 1; + + cpu_usage_percent = (ARM_MODE_TIMER_MSEC * usage) / 100; + + + for_each_online_cpu(cpu){ + work = &per_cpu(work_cpu_usage, cpu); + workqueue = per_cpu(workqueue_cpu_usage, cpu); + if (!work || !workqueue){ + PM_ERR("work or workqueue NULL\n"); + return n; + } + queue_work_on(cpu, workqueue, work); + } +#if 0 + del_timer(&arm_mode_timer); + arm_mode_timer.expires = jiffies + msecs_to_jiffies(ARM_MODE_TIMER_MSEC); + add_timer(&arm_mode_timer); +#endif + + } else if (strncmp(cmd, "stop", strlen("stop")) == 0) { + PM_DBG("get cmd stop\n"); + cpu_usage_run = 0; + } + + return n; +} + +static int __init cpu_usage_init(void) +{ + struct workqueue_struct **workqueue; + struct work_struct *work; + int cpu; + + for_each_online_cpu(cpu){ + work = &per_cpu(work_cpu_usage, cpu); + workqueue = &per_cpu(workqueue_cpu_usage, cpu); + if (!work || !workqueue){ + PM_ERR("work or workqueue NULL\n"); + return -1; + } + + *workqueue = create_singlethread_workqueue("workqueue_cpu_usage"); + INIT_WORK(work, handler_cpu_usage); + } + + setup_timer(&arm_mode_timer, arm_mode_timer_handler, (unsigned int)NULL); + return 0; +} +late_initcall(cpu_usage_init); diff --git a/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h new file mode 100644 index 000000000000..0c45ad4f4846 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/cpu_usage.h @@ -0,0 +1,8 @@ +#ifndef _CPU_USAGE_H_ +#define _CPU_USAGE_H_ +ssize_t cpu_usage_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); +ssize_t cpu_usage_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); + +#endif diff --git a/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c new file mode 100644 index 000000000000..2f68ee56881d --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +//#include +//#include +#include + + +#include +#include +#include +#include "rk_pm_tests.h" +#include "rk_pm_tests.h" +#include "dvfs_table_scan.h" +/***************************************************************************/ +struct workqueue_struct *workqueue_dvfs_table_scan; +struct work_struct work_dvfs_table_scan; +struct timer_list dvfs_table_scan_timer; +#define DVFS_TABLE_T_MSEC 1000 +struct file *file = NULL; +mm_segment_t old_fs; +loff_t offset = 0; +static int dvfs_table_scan_run = 0; + +ssize_t dvfs_table_scan_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + char *str = buf; + str += sprintf(str, "start: \tstart scan dvfs table, send alive every 1s\n" + "stop: \tstop send alive signal\n"); + if (str != buf) + *(str - 1) = '\n'; + return (str - buf); + +} +void rk29_wdt_start(void); +void rk29_wdt_stop(void); +void rk29_wdt_keepalive(void); +int rk29_wdt_set_heartbeat(int timeout); + +#define ALIVE_INTERVAL 2 //s +#define WATCHDOG_TIMEOUT (10*ALIVE_INTERVAL) +#define RESERVE_TIME_FOR_TIMEOUT 600000 //ms + +ssize_t dvfs_table_scan_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n) +{ + char cmd[20]; + int cur_test_need_time=0; //ms + static int cur_test_timeout_cnt = 0, start_flag = 0; + + sscanf(buf, "%s %d", cmd, &cur_test_need_time); + + printk("%s: get command <%s>\n", __func__, cmd); + if (0 == strncmp(cmd, "start", strlen("start"))) { + if (cur_test_need_time == 0) + return n; + cur_test_timeout_cnt = (cur_test_need_time + RESERVE_TIME_FOR_TIMEOUT)/1000/ALIVE_INTERVAL; + rk29_wdt_start(); + rk29_wdt_set_heartbeat(WATCHDOG_TIMEOUT); + start_flag = 1; + } else if (0 == strncmp(cmd, "alive", strlen("alive"))) { + if(start_flag == 0) + return n; + printk("cur_test_timeout_cnt:%d\n", cur_test_timeout_cnt); + if (cur_test_timeout_cnt-- > 0) + rk29_wdt_keepalive(); + + } else if (0 == strncmp(cmd, "stop", strlen("stop"))) { + if(start_flag == 0) + return n; + cur_test_timeout_cnt = -1; + rk29_wdt_stop(); + start_flag = 0; + } + + return n; +} diff --git a/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h new file mode 100644 index 000000000000..bef9f7bba0e8 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/dvfs_table_scan.h @@ -0,0 +1,8 @@ +#ifndef _DVFS_TABLE_SCAN_H_ +#define _DVFS_TABLE_SCAN_H_ +ssize_t dvfs_table_scan_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); +ssize_t dvfs_table_scan_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); + +#endif diff --git a/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c new file mode 100644 index 000000000000..f9243022e406 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.c @@ -0,0 +1,105 @@ +/* arch/arm/mach-rk30/rk_pm_tests.c + * + * Copyright (C) 2010 ROCKCHIP, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + + +/*************************************************************************/ +/* COPYRIGHT (C) ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.*/ +/************************************************************************* +FILE : rk_pm_tests.c +DESC : Power management in dynning state +AUTHOR : chenxing +DATE : 2012-7-2 +NOTES : +$LOG: GPIO.C,V $ +REVISION 0.01 +#include +#include + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +//#include + +#include "rk_pm_tests.h" + +#include "clk_rate.h" +#include "clk_volt.h" +#include "cpu_usage.h" +#include "dvfs_table_scan.h" + +static struct kobject *pm_tests_kobj; +struct pm_attribute { + struct attribute attr; + ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, + char *buf); + ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t n); +}; + +static struct pm_attribute pm_attrs[] = { + /* node_name permision show_func store_func*/ + __ATTR(clk_rate, S_IRUGO | S_IWUSR | S_IWUGO, clk_rate_show, clk_rate_store), + __ATTR(clk_volt, S_IRUGO | S_IWUSR | S_IWUGO, clk_volt_show, clk_volt_store), + __ATTR(dvfs_table_scan, S_IRUGO | S_IWUSR | S_IWUGO, dvfs_table_scan_show, dvfs_table_scan_store), +/* + __ATTR(maxfreq_volt, S_IRUGO | S_IWUSR, maxfreq_show, maxfreq_store), + __ATTR(freq_limit, S_IRUGO | S_IWUSR, freq_limit_show, freq_limit_store), + __ATTR(cpu_usage, S_IRUGO | S_IWUSR, cpu_usage_show, cpu_usage_store), + __ATTR(auto_wakeup, S_IRUGO | S_IWUSR, auto_wakeup_show, auto_wakeup_store), + __ATTR(suspend_test, S_IRUGO | S_IWUSR, suspend_test_show, suspend_test_store), + __ATTR(clk_auto_volt, S_IRUGO | S_IWUSR, clk_auto_volt_show, clk_auto_volt_store), +*/ +}; + +static void __exit rk_pm_tests_exit(void) +{ + kobject_put(pm_tests_kobj); +} + +static int __init rk_pm_tests_init(void) +{ + int i, ret = 0; + pm_tests_kobj = kobject_create_and_add("pm_tests", NULL); + + if (!pm_tests_kobj) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(pm_attrs); i++) { + ret = sysfs_create_file(pm_tests_kobj, &pm_attrs[i].attr); + if (ret != 0) { + PM_ERR("create index %d error\n", i); + return ret; + } + } + + return ret; +} + +late_initcall(rk_pm_tests_init); +module_exit(rk_pm_tests_exit); diff --git a/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h new file mode 100644 index 000000000000..2d4abb517b39 --- /dev/null +++ b/arch/arm/mach-rockchip/rk_pm_tests/rk_pm_tests.h @@ -0,0 +1,5 @@ +#ifndef _RK_PM_TESTS_H_ +#define _RK_PM_TESTS_H_ +#define PM_DBG(fmt, args...) printk(KERN_INFO "PM_TESTS_DBG:\t"fmt, ##args) +#define PM_ERR(fmt, args...) printk(KERN_ERR "PM_TESTS_ERR:\t"fmt, ##args) +#endif -- 2.34.1