Merge branch linux-tegra-2.6.36 into android-tegra-2.6.36
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-tegra / dvfs.c
1 /*
2  *
3  * Copyright (C) 2010 Google, Inc.
4  *
5  * Author:
6  *      Colin Cross <ccross@google.com>
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/clk.h>
21 #include <linux/list.h>
22 #include <linux/init.h>
23 #include <linux/list_sort.h>
24 #include <linux/module.h>
25 #include <linux/debugfs.h>
26 #include <linux/slab.h>
27 #include <linux/seq_file.h>
28 #include <linux/regulator/consumer.h>
29 #include <asm/clkdev.h>
30 #include <mach/clk.h>
31
32 #include "board.h"
33 #include "clock.h"
34 #include "dvfs.h"
35
36 struct dvfs_reg {
37         struct list_head node;  /* node in dvfs_reg_list */
38         struct list_head dvfs;  /* list head of attached dvfs clocks */
39         const char *reg_id;
40         struct regulator *reg;
41         int max_millivolts;
42         int millivolts;
43         struct mutex lock;
44 };
45
46 static LIST_HEAD(dvfs_debug_list);
47 static LIST_HEAD(dvfs_reg_list);
48
49 static DEFINE_MUTEX(dvfs_debug_list_lock);
50 static DEFINE_MUTEX(dvfs_reg_list_lock);
51
52 static int dvfs_reg_set_voltage(struct dvfs_reg *dvfs_reg)
53 {
54         int millivolts = 0;
55         struct dvfs *d;
56         int ret = 0;
57
58         mutex_lock(&dvfs_reg->lock);
59
60         list_for_each_entry(d, &dvfs_reg->dvfs, reg_node)
61                 millivolts = max(d->cur_millivolts, millivolts);
62
63         if (millivolts == dvfs_reg->millivolts)
64                 goto out;
65
66         dvfs_reg->millivolts = millivolts;
67
68         if (!dvfs_reg->reg) {
69                 pr_warn("dvfs set voltage on %s ignored\n", dvfs_reg->reg_id);
70                 goto out;
71         }
72
73         ret = regulator_set_voltage(dvfs_reg->reg,
74                 millivolts * 1000, dvfs_reg->max_millivolts * 1000);
75
76 out:
77         mutex_unlock(&dvfs_reg->lock);
78         return ret;
79 }
80
81 static int dvfs_reg_connect_to_regulator(struct dvfs_reg *dvfs_reg)
82 {
83         struct regulator *reg;
84
85         if (!dvfs_reg->reg) {
86                 reg = regulator_get(NULL, dvfs_reg->reg_id);
87                 if (IS_ERR(reg))
88                         return -EINVAL;
89         }
90
91         dvfs_reg->reg = reg;
92
93         return 0;
94 }
95
96 static struct dvfs_reg *get_dvfs_reg(struct dvfs *d)
97 {
98         struct dvfs_reg *dvfs_reg;
99
100         mutex_lock(&dvfs_reg_list_lock);
101
102         list_for_each_entry(dvfs_reg, &dvfs_reg_list, node)
103                 if (!strcmp(d->reg_id, dvfs_reg->reg_id))
104                         goto out;
105
106         dvfs_reg = kzalloc(sizeof(struct dvfs_reg), GFP_KERNEL);
107         if (!dvfs_reg) {
108                 pr_err("%s: Failed to allocate dvfs_reg\n", __func__);
109                 goto out;
110         }
111
112         mutex_init(&dvfs_reg->lock);
113         INIT_LIST_HEAD(&dvfs_reg->dvfs);
114         dvfs_reg->reg_id = kstrdup(d->reg_id, GFP_KERNEL);
115
116         list_add_tail(&dvfs_reg->node, &dvfs_reg_list);
117
118 out:
119         mutex_unlock(&dvfs_reg_list_lock);
120         return dvfs_reg;
121 }
122
123 static struct dvfs_reg *attach_dvfs_reg(struct dvfs *d)
124 {
125         struct dvfs_reg *dvfs_reg;
126
127         dvfs_reg = get_dvfs_reg(d);
128         if (!dvfs_reg)
129                 return NULL;
130
131         mutex_lock(&dvfs_reg->lock);
132         list_add_tail(&d->reg_node, &dvfs_reg->dvfs);
133
134         d->dvfs_reg = dvfs_reg;
135         if (d->max_millivolts > d->dvfs_reg->max_millivolts)
136                 d->dvfs_reg->max_millivolts = d->max_millivolts;
137
138         d->cur_millivolts = d->max_millivolts;
139         mutex_unlock(&dvfs_reg->lock);
140
141         return dvfs_reg;
142 }
143
144 static int
145 __tegra_dvfs_set_rate(struct clk *c, struct dvfs *d, unsigned long rate)
146 {
147         int i = 0;
148         int ret;
149
150         if (d->freqs == NULL || d->millivolts == NULL)
151                 return -ENODEV;
152
153         if (rate > d->freqs[d->num_freqs - 1]) {
154                 pr_warn("tegra_dvfs: rate %lu too high for dvfs on %s\n", rate,
155                         c->name);
156                 return -EINVAL;
157         }
158
159         if (rate == 0) {
160                 d->cur_millivolts = 0;
161         } else {
162                 while (i < d->num_freqs && rate > d->freqs[i])
163                         i++;
164
165                 d->cur_millivolts = d->millivolts[i];
166         }
167
168         d->cur_rate = rate;
169
170         if (!d->dvfs_reg)
171                 return 0;
172
173         ret = dvfs_reg_set_voltage(d->dvfs_reg);
174         if (ret)
175                 pr_err("Failed to set regulator %s for clock %s to %d mV\n",
176                         d->dvfs_reg->reg_id, c->name, d->cur_millivolts);
177
178         return ret;
179 }
180
181 int tegra_dvfs_set_rate_locked(struct clk *c, unsigned long rate)
182 {
183         struct dvfs *d;
184         int ret = 0;
185         bool freq_up;
186
187         c->dvfs_rate = rate;
188
189         freq_up = (c->refcnt == 0) || (rate > clk_get_rate_locked(c));
190
191         list_for_each_entry(d, &c->dvfs, node) {
192                 if (d->higher == freq_up)
193                         ret = __tegra_dvfs_set_rate(c, d, rate);
194                 if (ret)
195                         return ret;
196         }
197
198         list_for_each_entry(d, &c->dvfs, node) {
199                 if (d->higher != freq_up)
200                         ret = __tegra_dvfs_set_rate(c, d, rate);
201                 if (ret)
202                         return ret;
203         }
204
205         return 0;
206 }
207
208 /* May only be called during clock init, does not take any locks on clock c. */
209 int __init tegra_enable_dvfs_on_clk(struct clk *c, struct dvfs *d)
210 {
211         int i;
212         struct dvfs_reg *dvfs_reg;
213
214         dvfs_reg = attach_dvfs_reg(d);
215         if (!dvfs_reg) {
216                 pr_err("Failed to get regulator %s for clock %s\n",
217                         d->reg_id, c->name);
218                 return -EINVAL;
219         }
220
221         for (i = 0; i < MAX_DVFS_FREQS; i++) {
222                 if (d->millivolts[i] == 0)
223                         break;
224
225                 d->freqs[i] *= d->freqs_mult;
226
227                 /* If final frequencies are 0, pad with previous frequency */
228                 if (d->freqs[i] == 0 && i > 1)
229                         d->freqs[i] = d->freqs[i - 1];
230         }
231         d->num_freqs = i;
232
233         if (d->auto_dvfs) {
234                 c->auto_dvfs = true;
235                 clk_set_cansleep(c);
236         }
237
238         c->is_dvfs = true;
239
240         list_add_tail(&d->node, &c->dvfs);
241
242         mutex_lock(&dvfs_debug_list_lock);
243         list_add_tail(&d->debug_node, &dvfs_debug_list);
244         mutex_unlock(&dvfs_debug_list_lock);
245
246         return 0;
247 }
248
249 /*
250  * Iterate through all the dvfs regulators, finding the regulator exported
251  * by the regulator api for each one.  Must be called in late init, after
252  * all the regulator api's regulators are initialized.
253  */
254 int __init tegra_dvfs_late_init(void)
255 {
256         struct dvfs_reg *dvfs_reg;
257
258         mutex_lock(&dvfs_reg_list_lock);
259         list_for_each_entry(dvfs_reg, &dvfs_reg_list, node)
260                 dvfs_reg_connect_to_regulator(dvfs_reg);
261         mutex_unlock(&dvfs_reg_list_lock);
262
263         return 0;
264 }
265
266 #ifdef CONFIG_DEBUG_FS
267 static int dvfs_tree_sort_cmp(void *p, struct list_head *a, struct list_head *b)
268 {
269         struct dvfs *da = list_entry(a, struct dvfs, debug_node);
270         struct dvfs *db = list_entry(b, struct dvfs, debug_node);
271         int ret;
272
273         ret = strcmp(da->reg_id, db->reg_id);
274         if (ret != 0)
275                 return ret;
276
277         if (da->cur_millivolts < db->cur_millivolts)
278                 return 1;
279         if (da->cur_millivolts > db->cur_millivolts)
280                 return -1;
281
282         return strcmp(da->clk_name, db->clk_name);
283 }
284
285 static int dvfs_tree_show(struct seq_file *s, void *data)
286 {
287         struct dvfs *d;
288         const char *last_reg = "";
289
290         seq_printf(s, "   clock      rate       mV\n");
291         seq_printf(s, "--------------------------------\n");
292
293         mutex_lock(&dvfs_debug_list_lock);
294
295         list_sort(NULL, &dvfs_debug_list, dvfs_tree_sort_cmp);
296
297         list_for_each_entry(d, &dvfs_debug_list, debug_node) {
298                 if (strcmp(last_reg, d->dvfs_reg->reg_id) != 0) {
299                         last_reg = d->dvfs_reg->reg_id;
300                         seq_printf(s, "%s %d mV:\n", d->dvfs_reg->reg_id,
301                                 d->dvfs_reg->millivolts);
302                 }
303
304                 seq_printf(s, "   %-10s %-10lu %-4d mV\n", d->clk_name,
305                         d->cur_rate, d->cur_millivolts);
306         }
307
308         mutex_unlock(&dvfs_debug_list_lock);
309
310         return 0;
311 }
312
313 static int dvfs_tree_open(struct inode *inode, struct file *file)
314 {
315         return single_open(file, dvfs_tree_show, inode->i_private);
316 }
317
318 static const struct file_operations dvfs_tree_fops = {
319         .open           = dvfs_tree_open,
320         .read           = seq_read,
321         .llseek         = seq_lseek,
322         .release        = single_release,
323 };
324
325 int __init dvfs_debugfs_init(struct dentry *clk_debugfs_root)
326 {
327         struct dentry *d;
328
329         d = debugfs_create_file("dvfs", S_IRUGO, clk_debugfs_root, NULL,
330                 &dvfs_tree_fops);
331         if (!d)
332                 return -ENOMEM;
333
334         return 0;
335 }
336
337 #endif