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>
33 #include "cpu-tegra.h"
36 static struct mutex *cpu_throttle_lock;
37 static DEFINE_MUTEX(bthrot_list_lock);
38 static LIST_HEAD(bthrot_list);
41 #ifndef CONFIG_TEGRA_THERMAL_THROTTLE_EXACT_FREQ
42 static unsigned int clip_to_table(unsigned int cpu_freq)
45 struct cpufreq_frequency_table *cpu_freq_table;
46 struct tegra_cpufreq_table_data *table_data =
47 tegra_cpufreq_table_get();
49 if (IS_ERR_OR_NULL(table_data))
52 cpu_freq_table = table_data->freq_table;
54 for (i = 0; cpu_freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
55 if (cpu_freq_table[i].frequency > cpu_freq)
58 i = (i == 0) ? 0 : i-1;
59 return cpu_freq_table[i].frequency;
62 static unsigned int clip_to_table(unsigned int cpu_freq)
66 #endif /* CONFIG_TEGRA_THERMAL_THROTTLE_EXACT_FREQ */
68 unsigned int tegra_throttle_governor_speed(unsigned int requested_speed)
70 struct balanced_throttle *bthrot;
71 unsigned int throttle_speed = requested_speed;
73 unsigned int bthrot_speed;
74 unsigned int lowest_speed;
75 struct cpufreq_frequency_table *cpu_freq_table;
76 struct tegra_cpufreq_table_data *table_data =
77 tegra_cpufreq_table_get();
80 return requested_speed;
83 cpu_freq_table = table_data->freq_table;
84 lowest_speed = cpu_freq_table[table_data->throttle_lowest_index].frequency;
86 mutex_lock(&bthrot_list_lock);
88 list_for_each_entry(bthrot, &bthrot_list, node) {
89 if (bthrot->is_throttling) {
90 index = bthrot->throttle_index;
91 bthrot_speed = bthrot->throt_tab[index].cpu_freq;
93 if (bthrot_speed == 0)
94 bthrot_speed = lowest_speed;
96 bthrot_speed = clip_to_table(bthrot_speed);
98 throttle_speed = min(throttle_speed, bthrot_speed);
101 mutex_unlock(&bthrot_list_lock);
103 return throttle_speed;
106 static void tegra_throttle_set_core_level(void)
108 struct balanced_throttle *bthrot;
109 int core_level = INT_MAX;
111 mutex_lock(&bthrot_list_lock);
112 list_for_each_entry(bthrot, &bthrot_list, node) {
113 if (bthrot->is_throttling) {
114 int idx = bthrot->throttle_index;
115 core_level = min(core_level,
116 bthrot->throt_tab[idx].core_cap_level);
119 mutex_unlock(&bthrot_list_lock);
121 tegra_dvfs_core_cap_level_set(core_level);
124 bool tegra_is_throttling(int *count)
126 struct balanced_throttle *bthrot;
127 bool is_throttling = false;
130 mutex_lock(&bthrot_list_lock);
131 list_for_each_entry(bthrot, &bthrot_list, node) {
132 if (bthrot->is_throttling)
133 is_throttling = true;
134 lcount += bthrot->throttle_count;
136 mutex_unlock(&bthrot_list_lock);
140 return is_throttling;
144 tegra_throttle_get_max_state(struct thermal_cooling_device *cdev,
145 unsigned long *max_state)
147 struct balanced_throttle *bthrot = cdev->devdata;
149 *max_state = bthrot->throt_tab_size;
155 tegra_throttle_get_cur_state(struct thermal_cooling_device *cdev,
156 unsigned long *cur_state)
158 struct balanced_throttle *bthrot = cdev->devdata;
160 mutex_lock(cpu_throttle_lock);
161 *cur_state = bthrot->is_throttling ?
162 (bthrot->throt_tab_size - bthrot->throttle_index) :
164 mutex_unlock(cpu_throttle_lock);
170 tegra_throttle_set_cur_state(struct thermal_cooling_device *cdev,
171 unsigned long cur_state)
173 struct balanced_throttle *bthrot = cdev->devdata;
175 mutex_lock(cpu_throttle_lock);
176 if (cur_state == 0) {
177 /* restore speed requested by governor */
178 if (bthrot->is_throttling) {
179 tegra_dvfs_core_cap_enable(false);
180 bthrot->is_throttling = false;
183 if (!bthrot->is_throttling) {
184 tegra_dvfs_core_cap_enable(true);
185 bthrot->is_throttling = true;
186 bthrot->throttle_count++;
189 bthrot->throttle_index = bthrot->throt_tab_size - cur_state;
190 tegra_throttle_set_core_level();
193 tegra_cpu_set_speed_cap(NULL);
195 mutex_unlock(cpu_throttle_lock);
200 static struct thermal_cooling_device_ops tegra_throttle_cooling_ops = {
201 .get_max_state = tegra_throttle_get_max_state,
202 .get_cur_state = tegra_throttle_get_cur_state,
203 .set_cur_state = tegra_throttle_set_cur_state,
206 #ifdef CONFIG_DEBUG_FS
207 static int table_show(struct seq_file *s, void *data)
209 struct balanced_throttle *bthrot = s->private;
212 for (i = 0; i < bthrot->throt_tab_size; i++)
213 seq_printf(s, "[%d] = %7u %4d\n",
214 i, bthrot->throt_tab[i].cpu_freq,
215 bthrot->throt_tab[i].core_cap_level);
220 static int table_open(struct inode *inode, struct file *file)
222 return single_open(file, table_show, inode->i_private);
225 static ssize_t table_write(struct file *file,
226 const char __user *userbuf, size_t count, loff_t *ppos)
228 struct balanced_throttle *bthrot = file->private_data;
231 unsigned int cpu_freq;
234 if (sizeof(buf) <= count)
237 if (copy_from_user(buf, userbuf, count))
240 /* terminate buffer and trim - white spaces may be appended
241 * at the end when invoked from shell command line */
245 if (sscanf(buf, "[%d] = %u %d",
246 &table_idx, &cpu_freq, &core_cap_level) != 3)
249 if ((table_idx < 0) || (table_idx >= bthrot->throt_tab_size))
252 /* round new settings before updating table */
253 bthrot->throt_tab[table_idx].cpu_freq = clip_to_table(cpu_freq);
254 bthrot->throt_tab[table_idx].core_cap_level = (core_cap_level / 50) * 50;
259 static const struct file_operations table_fops = {
262 .write = table_write,
264 .release = single_release,
267 static struct dentry *throttle_debugfs_root;
268 #endif /* CONFIG_DEBUG_FS */
271 struct thermal_cooling_device *balanced_throttle_register(
272 struct balanced_throttle *bthrot,
275 #ifdef CONFIG_DEBUG_FS
278 mutex_lock(&bthrot_list_lock);
280 list_add(&bthrot->node, &bthrot_list);
281 mutex_unlock(&bthrot_list_lock);
283 bthrot->cdev = thermal_cooling_device_register(
286 &tegra_throttle_cooling_ops);
288 if (IS_ERR(bthrot->cdev)) {
290 return ERR_PTR(-ENODEV);
293 #ifdef CONFIG_DEBUG_FS
294 sprintf(name, "throttle_table%d", num_throt);
295 debugfs_create_file(name,0644, throttle_debugfs_root,
296 bthrot, &table_fops);
302 int __init tegra_throttle_init(struct mutex *cpu_lock)
304 cpu_throttle_lock = cpu_lock;
305 #ifdef CONFIG_DEBUG_FS
306 throttle_debugfs_root = debugfs_create_dir("tegra_throttle", 0);
311 void tegra_throttle_exit(void)
313 #ifdef CONFIG_DEBUG_FS
314 debugfs_remove_recursive(throttle_debugfs_root);