/* * 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 #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 device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%d\n", query_cpu_config()); } static ssize_t store_cpuctl(struct device *dev, struct device_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 DEVICE_ATTR(cpuctl, 0600, show_cpuctl, store_cpuctl); static int __init init_scm_cpu(void) { return device_create_file(cpu_subsys.dev_root, &dev_attr_cpuctl); } module_init(init_scm_cpu);