/* * Copyright (c) 2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * 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. */ #include #include #include #include #include #include #include #include #define CPU_CONFIG_CMD 5 #define CPU_CONFIG_QUERY_CMD 6 static int query_cpu_config(void) { struct cpu_config_query_req_resp { u32 id; u32 arg0; u32 arg1; u32 arg2; } request; struct cpu_config_query_resp { u32 ret0; u32 ret1; u32 ret2; u32 ret3; } response = {0}; int ret; request.id = 1; ret = scm_call(SCM_SVC_BOOT, CPU_CONFIG_QUERY_CMD, &request, sizeof(request), &response, sizeof(response)); return ret ? : response.ret0; } static void set_cpu_config(int enable) { struct cpu_config_req { u32 id; u32 arg0; u32 arg1; u32 arg2; } request; request.id = 1; request.arg0 = enable; scm_call(SCM_SVC_BOOT, CPU_CONFIG_CMD, &request, sizeof(request), NULL, 0); } void enable_cpu_config(struct work_struct *work) { set_cpu_config(1); } void disable_cpu_config(struct work_struct *work) { set_cpu_config(0); } int cpu_config_on_each_cpu(bool enable) { work_func_t func = enable ? enable_cpu_config : disable_cpu_config; return schedule_on_each_cpu(func); } static ssize_t show_cpuctl(struct sysdev_class *class, struct sysdev_class_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", query_cpu_config()); } static ssize_t store_cpuctl(struct sysdev_class *class, struct sysdev_class_attribute *attr, const char *buf, size_t count) { unsigned val; int ret; ret = kstrtouint(buf, 10, &val); if (ret < 0) return ret; ret = cpu_config_on_each_cpu(val); if (ret < 0) return ret; return count; } static SYSDEV_CLASS_ATTR(cpuctl, 0600, show_cpuctl, store_cpuctl); static int __init init_scm_cpu(void) { return sysfs_create_file(&cpu_subsys.dev_root->kobj, &attr_cpuctl.attr); } module_init(init_scm_cpu);