2 * arch/arm/mach-tegra/tegra3_throttle.c
4 * Copyright (c) 2011-2012, NVIDIA Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include <linux/kernel.h>
21 #include <linux/cpufreq.h>
22 #include <linux/delay.h>
23 #include <linux/init.h>
24 #include <linux/err.h>
25 #include <linux/clk.h>
26 #include <linux/debugfs.h>
27 #include <linux/seq_file.h>
28 #include <linux/uaccess.h>
29 #include <linux/thermal.h>
30 #include <linux/module.h>
31 #include <mach/thermal.h>
34 #include "cpu-tegra.h"
37 static struct mutex *cpu_throttle_lock;
38 static DEFINE_MUTEX(bthrot_list_lock);
39 static LIST_HEAD(bthrot_list);
41 static unsigned int clip_to_table(unsigned int cpu_freq)
44 struct cpufreq_frequency_table *cpu_freq_table;
45 struct tegra_cpufreq_table_data *table_data =
46 tegra_cpufreq_table_get();
48 if (IS_ERR_OR_NULL(table_data))
51 cpu_freq_table = table_data->freq_table;
53 for (i = 0; cpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
54 if (cpu_freq_table[i].frequency > cpu_freq)
57 i = (i == 0) ? 0 : i-1;
58 return cpu_freq_table[i].frequency;
61 unsigned int tegra_throttle_governor_speed(unsigned int requested_speed)
63 struct balanced_throttle *bthrot;
64 unsigned int throttle_speed = requested_speed;
66 unsigned int bthrot_speed;
67 unsigned int lowest_speed;
68 struct cpufreq_frequency_table *cpu_freq_table;
69 struct tegra_cpufreq_table_data *table_data =
70 tegra_cpufreq_table_get();
73 return requested_speed;
76 cpu_freq_table = table_data->freq_table;
77 lowest_speed = cpu_freq_table[table_data->throttle_lowest_index].frequency;
79 mutex_lock(&bthrot_list_lock);
81 list_for_each_entry(bthrot, &bthrot_list, node) {
82 if (bthrot->is_throttling) {
83 index = bthrot->throttle_index;
84 bthrot_speed = bthrot->throt_tab[index].cpu_freq;
86 if (bthrot_speed == 0)
87 bthrot_speed = lowest_speed;
89 bthrot_speed = clip_to_table(bthrot_speed);
91 throttle_speed = min(throttle_speed, bthrot_speed);
94 mutex_unlock(&bthrot_list_lock);
96 return throttle_speed;
99 bool tegra_is_throttling(void)
101 struct balanced_throttle *bthrot;
102 bool is_throttling = false;
104 mutex_lock(&bthrot_list_lock);
105 list_for_each_entry(bthrot, &bthrot_list, node) {
106 if (bthrot->is_throttling) {
107 is_throttling = true;
111 mutex_unlock(&bthrot_list_lock);
113 return is_throttling;
117 tegra_throttle_get_max_state(struct thermal_cooling_device *cdev,
118 unsigned long *max_state)
120 struct balanced_throttle *bthrot = cdev->devdata;
122 *max_state = bthrot->throt_tab_size;
128 tegra_throttle_get_cur_state(struct thermal_cooling_device *cdev,
129 unsigned long *cur_state)
131 struct balanced_throttle *bthrot = cdev->devdata;
133 mutex_lock(cpu_throttle_lock);
134 *cur_state = bthrot->is_throttling ?
135 (bthrot->throt_tab_size - bthrot->throttle_index) :
137 mutex_unlock(cpu_throttle_lock);
143 tegra_throttle_set_cur_state(struct thermal_cooling_device *cdev,
144 unsigned long cur_state)
146 struct balanced_throttle *bthrot = cdev->devdata;
150 mutex_lock(cpu_throttle_lock);
151 if (cur_state == 0) {
152 /* restore speed requested by governor */
153 if (bthrot->is_throttling) {
154 tegra_dvfs_core_cap_enable(false);
155 bthrot->is_throttling = false;
158 tegra_cpu_set_speed_cap(NULL);
160 if (!bthrot->is_throttling) {
161 tegra_dvfs_core_cap_enable(true);
162 bthrot->is_throttling = true;
165 bthrot->throttle_index = bthrot->throt_tab_size - cur_state;
166 index = bthrot->throttle_index;
167 core_level = bthrot->throt_tab[index].core_cap_level;
168 tegra_dvfs_core_cap_level_set(core_level);
170 tegra_cpu_set_speed_cap(NULL);
173 mutex_unlock(cpu_throttle_lock);
178 static struct thermal_cooling_device_ops tegra_throttle_cooling_ops = {
179 .get_max_state = tegra_throttle_get_max_state,
180 .get_cur_state = tegra_throttle_get_cur_state,
181 .set_cur_state = tegra_throttle_set_cur_state,
184 #ifdef CONFIG_DEBUG_FS
185 static int table_show(struct seq_file *s, void *data)
187 struct balanced_throttle *bthrot = s->private;
190 for (i = 0; i < bthrot->throt_tab_size; i++)
191 seq_printf(s, "[%d] = %7u %4d\n",
192 i, bthrot->throt_tab[i].cpu_freq,
193 bthrot->throt_tab[i].core_cap_level);
198 static int table_open(struct inode *inode, struct file *file)
200 return single_open(file, table_show, inode->i_private);
203 static ssize_t table_write(struct file *file,
204 const char __user *userbuf, size_t count, loff_t *ppos)
206 struct balanced_throttle *bthrot = file->private_data;
209 unsigned int cpu_freq;
212 if (sizeof(buf) <= count)
215 if (copy_from_user(buf, userbuf, count))
218 /* terminate buffer and trim - white spaces may be appended
219 * at the end when invoked from shell command line */
223 if (sscanf(buf, "[%d] = %u %d",
224 &table_idx, &cpu_freq, &core_cap_level) != 3)
227 if ((table_idx < 0) || (table_idx >= bthrot->throt_tab_size))
230 /* round new settings before updating table */
231 bthrot->throt_tab[table_idx].cpu_freq = clip_to_table(cpu_freq);
232 bthrot->throt_tab[table_idx].core_cap_level = (core_cap_level / 50) * 50;
237 static const struct file_operations table_fops = {
240 .write = table_write,
242 .release = single_release,
245 static struct dentry *throttle_debugfs_root;
246 #endif /* CONFIG_DEBUG_FS */
249 int balanced_throttle_register(struct balanced_throttle *bthrot)
251 #ifdef CONFIG_DEBUG_FS
254 struct balanced_throttle *dev;
256 mutex_lock(&bthrot_list_lock);
257 list_for_each_entry(dev, &bthrot_list, node) {
258 if (dev->tegra_cdev.id == bthrot->tegra_cdev.id) {
259 mutex_unlock(&bthrot_list_lock);
265 list_add(&bthrot->node, &bthrot_list);
266 mutex_unlock(&bthrot_list_lock);
268 bthrot->cdev = thermal_cooling_device_register(
271 &tegra_throttle_cooling_ops);
273 if (IS_ERR(bthrot->cdev)) {
278 #ifdef CONFIG_DEBUG_FS
279 sprintf(name, "throttle_table%d", bthrot->tegra_cdev.id);
280 debugfs_create_file(name,0644, throttle_debugfs_root,
281 bthrot, &table_fops);
287 int __init tegra_throttle_init(struct mutex *cpu_lock)
289 cpu_throttle_lock = cpu_lock;
290 #ifdef CONFIG_DEBUG_FS
291 throttle_debugfs_root = debugfs_create_dir("tegra_throttle", 0);
296 void tegra_throttle_exit(void)
298 #ifdef CONFIG_DEBUG_FS
299 debugfs_remove_recursive(throttle_debugfs_root);