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_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; }
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; struct clk *clk; char cmd[20], clk_name[20]; unsigned long rate=0; int ret=0; sscanf(buf, "%s %s %lu", cmd, clk_name, &rate); PM_DBG("%s: cmd(%s), clk_name(%s), rate(%lu)\n", __func__, cmd, clk_name, rate); if (!strncmp(cmd, "set", strlen("set"))) { 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 (!strncmp(clk_name, "clk_core", strlen("clk_core"))) { if (file_write(FILE_GOV_MODE, "userspace") != 0) { PM_ERR("%s: set current governor error\n", __func__); return n; } } ret = dvfs_clk_enable_limit(clk_dvfs_node, rate, rate); } else { clk = clk_get(NULL, clk_name); if (IS_ERR_OR_NULL(clk)) { PM_ERR("%s: get clk(%s) err(%ld)\n", __func__, clk_name, PTR_ERR(clk)); return n; } if (!strncmp(cmd, "rawset", strlen("rawset"))) { ret = clk_set_rate(clk, rate); } else if (!strncmp(cmd, "open", strlen("open"))) { ret = clk_prepare_enable(clk); } else if (!strncmp(cmd, "close", strlen("close"))) { clk_disable_unprepare(clk); } } if (ret) { PM_ERR("%s: set rate err(%d)", __func__, ret); } return n; }
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; }
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; }
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")))) { 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"))) {
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; }
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; }
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; }