diff options
author | Alex Frid <afrid@nvidia.com> | 2013-12-04 18:23:26 -0800 |
---|---|---|
committer | Yu-Huan Hsu <yhsu@nvidia.com> | 2013-12-10 16:54:04 -0800 |
commit | ffce4910c943762ba1635f4ffa3b0448b2773a59 (patch) | |
tree | 15896b7e74e13483ddf77ce1cc4b9b437a82b7db /arch/arm/mach-tegra/tegra_simon.c | |
parent | 709aa0e4081decc502e593748bc5d127f8f5e229 (diff) |
ARM: tegra: power: Add initial SiMon support
Defined tegra Silicon Monitor (SiMon) domains: CPU, GPU, core. Added
SiMon domain grade notification chain, and debugfs entries.
Bug 1343366
Change-Id: Ieff7ca57af48e5a5a2224fd6800bcccabf8eef5e
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/338521
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sai Gurrappadi <sgurrappadi@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_simon.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra_simon.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra_simon.c b/arch/arm/mach-tegra/tegra_simon.c new file mode 100644 index 000000000000..3f45b853c42c --- /dev/null +++ b/arch/arm/mach-tegra/tegra_simon.c @@ -0,0 +1,129 @@ +/* + * arch/arm/mach-tegra/tegra_simon.c + * + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * 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. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +#include "tegra_simon.h" + +static DEFINE_MUTEX(simon_lock); +static RAW_NOTIFIER_HEAD(simon_nh); +static int simon_grades[TEGRA_SIMON_DOMAIN_NUM]; + +static const char *simon_domain_names[TEGRA_SIMON_DOMAIN_NUM] = { + [TEGRA_SIMON_DOMAIN_CPU] = "cpu", + [TEGRA_SIMON_DOMAIN_GPU] = "gpu", + [TEGRA_SIMON_DOMAIN_CORE] = "core", +}; + + +int tegra_register_simon_notifier(struct notifier_block *nb) +{ + int ret; + + mutex_lock(&simon_lock); + ret = raw_notifier_chain_register(&simon_nh, nb); + mutex_unlock(&simon_lock); + return ret; +} + +void tegra_unregister_simon_notifier(struct notifier_block *nb) +{ + mutex_lock(&simon_lock); + raw_notifier_chain_unregister(&simon_nh, nb); + mutex_unlock(&simon_lock); +} + +static int simon_grade_change_notify(int grade, enum tegra_simon_domain domain) +{ + int ret = 0; + + mutex_lock(&simon_lock); + if (simon_grades[domain] != grade) { + simon_grades[domain] = grade; + ret = raw_notifier_call_chain(&simon_nh, grade, (void *)domain); + } + mutex_unlock(&simon_lock); + return ret; +} + +#ifdef CONFIG_DEBUG_FS + +static int grade_get(void *data, u64 *val) +{ + int domain = (int)data; + + if (domain >= TEGRA_SIMON_DOMAIN_NUM) { + *val = -EINVAL; + return -EINVAL; + } + + *val = simon_grades[domain]; + return 0; +} +static int grade_set(void *data, u64 val) +{ + int domain = (int)data; + + if (domain >= TEGRA_SIMON_DOMAIN_NUM) + return -EINVAL; + + simon_grade_change_notify(val, domain); + return 0; +} +DEFINE_SIMPLE_ATTRIBUTE(grade_fops, grade_get, grade_set, "%llu\n"); + +static int __init simon_debugfs_init(void) +{ + int domain; + struct dentry *d, *dir; + + dir = debugfs_create_dir("tegra_simon", NULL); + if (!dir) + return -ENOMEM; + + for (domain = 0; domain < TEGRA_SIMON_DOMAIN_NUM; domain++) { + if (!simon_domain_names[domain]) + continue; + + d = debugfs_create_file(simon_domain_names[domain], + S_IWUSR | S_IRUGO, dir, (void *)domain, &grade_fops); + if (!d) + goto err_out; + } + + return 0; + +err_out: + debugfs_remove_recursive(dir); + return -ENOMEM; +} +#endif + +static int __init tegra_simon_init(void) +{ +#ifdef CONFIG_DEBUG_FS + simon_debugfs_init(); +#endif + return 0; + +} +late_initcall_sync(tegra_simon_init); + |