ARM: Tegra: power: Tegra3 AP33 SKU updated EDP table
[linux-3.10.git] / arch / arm / mach-tegra / edp.c
1 /*
2  * arch/arm/mach-tegra/edp.c
3  *
4  * Copyright (C) 2011 NVIDIA, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  * 02111-1307, USA
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/seq_file.h>
24 #include <linux/slab.h>
25 #include <mach/edp.h>
26
27 #include "fuse.h"
28
29 static const struct tegra_edp_limits *edp_limits;
30 static int edp_limits_size;
31
32
33 /*
34  * Temperature step size cannot be less than 4C because of hysteresis
35  * delta
36  * Code assumes different temperatures for the same speedo_id /
37  * regulator_cur are adjacent in the table, and higest regulator_cur
38  * comes first
39  */
40 static char __initdata tegra_edp_map[] = {
41         0x00, 0x2f, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x00,
42         0x2f, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f,
43         0x4b, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f, 0x55,
44         0x82, 0x78, 0x78, 0x78, 0x00, 0x28, 0x2d, 0x82,
45         0x78, 0x78, 0x78, 0x00, 0x28, 0x3c, 0x82, 0x78,
46         0x78, 0x78, 0x00, 0x28, 0x4b, 0x82, 0x78, 0x78,
47         0x73, 0x00, 0x28, 0x55, 0x82, 0x78, 0x73, 0x69,
48         0x00, 0x23, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x00,
49         0x23, 0x3c, 0x82, 0x78, 0x78, 0x6e, 0x00, 0x23,
50         0x4b, 0x82, 0x78, 0x78, 0x64, 0x00, 0x23, 0x55,
51         0x82, 0x78, 0x6e, 0x5a, 0x00, 0x1e, 0x2d, 0x82,
52         0x78, 0x78, 0x69, 0x00, 0x1e, 0x3c, 0x82, 0x78,
53         0x78, 0x64, 0x00, 0x1e, 0x4b, 0x82, 0x78, 0x6e,
54         0x5a, 0x00, 0x1e, 0x55, 0x82, 0x78, 0x64, 0x5a,
55         0x00, 0x19, 0x2d, 0x82, 0x78, 0x6e, 0x5a, 0x00,
56         0x19, 0x3c, 0x82, 0x78, 0x69, 0x55, 0x00, 0x19,
57         0x4b, 0x82, 0x78, 0x5f, 0x4b, 0x00, 0x19, 0x55,
58         0x82, 0x73, 0x5a, 0x3c, 0x01, 0x2f, 0x2d, 0x82,
59         0x78, 0x78, 0x78, 0x01, 0x2f, 0x3c, 0x82, 0x78,
60         0x78, 0x78, 0x01, 0x2f, 0x4b, 0x82, 0x78, 0x78,
61         0x78, 0x01, 0x2f, 0x55, 0x82, 0x78, 0x78, 0x78,
62         0x01, 0x28, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x01,
63         0x28, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x01, 0x28,
64         0x4b, 0x82, 0x78, 0x78, 0x73, 0x01, 0x28, 0x55,
65         0x82, 0x78, 0x73, 0x69, 0x01, 0x23, 0x2d, 0x82,
66         0x78, 0x78, 0x78, 0x01, 0x23, 0x3c, 0x82, 0x78,
67         0x78, 0x6e, 0x01, 0x23, 0x4b, 0x82, 0x78, 0x78,
68         0x64, 0x01, 0x23, 0x55, 0x82, 0x78, 0x6e, 0x5a,
69         0x01, 0x1e, 0x2d, 0x82, 0x78, 0x78, 0x69, 0x01,
70         0x1e, 0x3c, 0x82, 0x78, 0x78, 0x64, 0x01, 0x1e,
71         0x4b, 0x82, 0x78, 0x6e, 0x5a, 0x01, 0x1e, 0x55,
72         0x82, 0x78, 0x64, 0x5a, 0x01, 0x19, 0x2d, 0x82,
73         0x78, 0x6e, 0x5a, 0x01, 0x19, 0x3c, 0x82, 0x78,
74         0x69, 0x55, 0x01, 0x19, 0x4b, 0x82, 0x78, 0x5f,
75         0x4b, 0x01, 0x19, 0x55, 0x82, 0x73, 0x5a, 0x3c,
76         0x02, 0x3d, 0x2d, 0x8c, 0x82, 0x82, 0x82, 0x02,
77         0x3d, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x02, 0x3d,
78         0x4b, 0x8c, 0x82, 0x82, 0x82, 0x02, 0x3d, 0x55,
79         0x8c, 0x82, 0x82, 0x82, 0x02, 0x32, 0x2d, 0x8c,
80         0x82, 0x82, 0x82, 0x02, 0x32, 0x3c, 0x8c, 0x82,
81         0x82, 0x82, 0x02, 0x32, 0x4b, 0x8c, 0x82, 0x82,
82         0x78, 0x02, 0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e,
83         0x02, 0x28, 0x2d, 0x8c, 0x82, 0x82, 0x78, 0x02,
84         0x28, 0x3c, 0x8c, 0x82, 0x82, 0x73, 0x02, 0x28,
85         0x4b, 0x8c, 0x82, 0x78, 0x6e, 0x02, 0x28, 0x55,
86         0x8c, 0x82, 0x73, 0x5f, 0x02, 0x23, 0x2d, 0x8c,
87         0x82, 0x82, 0x6e, 0x02, 0x23, 0x3c, 0x8c, 0x82,
88         0x78, 0x69, 0x02, 0x23, 0x4b, 0x8c, 0x82, 0x73,
89         0x5f, 0x02, 0x23, 0x55, 0x8c, 0x82, 0x69, 0x55,
90         0x03, 0x3d, 0x2d, 0x8c, 0x82, 0x82, 0x82, 0x03,
91         0x3d, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x3d,
92         0x4b, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x3d, 0x55,
93         0x8c, 0x82, 0x82, 0x82, 0x03, 0x32, 0x2d, 0x8c,
94         0x82, 0x82, 0x82, 0x03, 0x32, 0x3c, 0x8c, 0x82,
95         0x82, 0x82, 0x03, 0x32, 0x4b, 0x8c, 0x82, 0x82,
96         0x73, 0x03, 0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e,
97         0x03, 0x28, 0x2d, 0x8c, 0x82, 0x82, 0x78, 0x03,
98         0x28, 0x3c, 0x8c, 0x82, 0x82, 0x73, 0x03, 0x28,
99         0x4b, 0x8c, 0x82, 0x7d, 0x6e, 0x03, 0x28, 0x55,
100         0x8c, 0x82, 0x73, 0x5f, 0x03, 0x23, 0x2d, 0x8c,
101         0x82, 0x82, 0x6e, 0x03, 0x23, 0x3c, 0x8c, 0x82,
102         0x78, 0x69, 0x03, 0x23, 0x4b, 0x8c, 0x82, 0x6e,
103         0x5a, 0x03, 0x23, 0x55, 0x8c, 0x82, 0x64, 0x50,
104         0x04, 0x32, 0x2d, 0x96, 0x8c, 0x8c, 0x8c, 0x04,
105         0x32, 0x3c, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x32,
106         0x46, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x32, 0x4b,
107         0x82, 0x78, 0x78, 0x78, 0x04, 0x32, 0x55, 0x82,
108         0x78, 0x78, 0x78, 0x04, 0x2f, 0x2d, 0x96, 0x8c,
109         0x8c, 0x8c, 0x04, 0x2f, 0x3c, 0x96, 0x8c, 0x8c,
110         0x8c, 0x04, 0x2f, 0x46, 0x96, 0x8c, 0x8c, 0x82,
111         0x04, 0x2f, 0x4b, 0x82, 0x78, 0x78, 0x78, 0x04,
112         0x2f, 0x55, 0x82, 0x78, 0x78, 0x78, 0x04, 0x28,
113         0x2d, 0x96, 0x8c, 0x8c, 0x82, 0x04, 0x28, 0x3c,
114         0x96, 0x8c, 0x8c, 0x82, 0x04, 0x28, 0x46, 0x96,
115         0x8c, 0x8c, 0x78, 0x04, 0x28, 0x4b, 0x82, 0x78,
116         0x78, 0x78, 0x04, 0x28, 0x55, 0x82, 0x78, 0x78,
117         0x6e, 0x04, 0x23, 0x2d, 0x96, 0x8c, 0x8c, 0x78,
118         0x04, 0x23, 0x3c, 0x96, 0x8c, 0x82, 0x78, 0x04,
119         0x23, 0x46, 0x96, 0x8c, 0x82, 0x6e, 0x04, 0x23,
120         0x4b, 0x82, 0x78, 0x78, 0x6e, 0x04, 0x23, 0x55,
121         0x82, 0x78, 0x78, 0x64, 0x04, 0x1e, 0x2d, 0x96,
122         0x8c, 0x82, 0x6e, 0x04, 0x1e, 0x3c, 0x96, 0x8c,
123         0x78, 0x64, 0x04, 0x1e, 0x46, 0x96, 0x8c, 0x78,
124         0x5a, 0x04, 0x1e, 0x4b, 0x82, 0x78, 0x78, 0x5a,
125         0x04, 0x1e, 0x55, 0x82, 0x78, 0x69, 0x50, 0x04,
126         0x19, 0x2d, 0x96, 0x8c, 0x6e, 0x5a, 0x04, 0x19,
127         0x3c, 0x96, 0x82, 0x6e, 0x55, 0x04, 0x19, 0x46,
128         0x96, 0x82, 0x64, 0x50, 0x04, 0x19, 0x4b, 0x82,
129         0x78, 0x64, 0x50, 0x04, 0x19, 0x55, 0x82, 0x78,
130         0x55, 0x3c, 0x05, 0x64, 0x3c, 0xaa, 0xa0, 0xa0,
131         0xa0, 0x05, 0x64, 0x55, 0x8c, 0x82, 0x82, 0x82,
132         0x05, 0x3c, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x05,
133         0x3c, 0x55, 0x8c, 0x82, 0x82, 0x82, 0x06, 0x64,
134         0x3c, 0xaa, 0xa0, 0xa0, 0xa0, 0x06, 0x64, 0x55,
135         0x8c, 0x82, 0x82, 0x82, 0x06, 0x3c, 0x3c, 0x8c,
136         0x82, 0x82, 0x82, 0x06, 0x3c, 0x55, 0x8c, 0x82,
137         0x82, 0x82,
138 };
139
140
141 /*
142  * "Safe entry" to be used when no match for speedo_id /
143  * regulator_cur is found; must be the last one
144  */
145 static struct tegra_edp_limits edp_default_limits[] = {
146         {85, {1000000, 1000000, 1000000, 1000000} },
147 };
148
149
150
151 /*
152  * Specify regulator current in mA, e.g. 5000mA
153  * Use 0 for default
154  */
155 void __init tegra_init_cpu_edp_limits(unsigned int regulator_mA)
156 {
157         int cpu_speedo_id = tegra_cpu_speedo_id;
158         int i, j;
159         struct tegra_edp_limits *e;
160         struct tegra_edp_entry *t = (struct tegra_edp_entry *)tegra_edp_map;
161         int tsize = sizeof(tegra_edp_map)/sizeof(struct tegra_edp_entry);
162
163         /* FIXME: Now for T33 we use 6A limit - fix this later */
164         if (cpu_speedo_id > 3)
165                 regulator_mA = 6000;
166
167         if (!regulator_mA) {
168                 edp_limits = edp_default_limits;
169                 edp_limits_size = ARRAY_SIZE(edp_default_limits);
170                 return;
171         }
172
173         for (i = 0; i < tsize; i++) {
174                 if (t[i].speedo_id == cpu_speedo_id &&
175                     t[i].regulator_100mA <= regulator_mA / 100)
176                         break;
177         }
178
179         /* No entry found in tegra_edp_map */
180         if (i >= tsize) {
181                 edp_limits = edp_default_limits;
182                 edp_limits_size = ARRAY_SIZE(edp_default_limits);
183                 return;
184         }
185
186         /* Find all rows for this entry */
187         for (j = i + 1; j < tsize; j++) {
188                 if (t[i].speedo_id != t[j].speedo_id ||
189                     t[i].regulator_100mA != t[j].regulator_100mA)
190                         break;
191         }
192
193         edp_limits_size = j - i;
194         e = kmalloc(sizeof(struct tegra_edp_limits) * edp_limits_size,
195                     GFP_KERNEL);
196         BUG_ON(!e);
197
198         for (j = 0; j < edp_limits_size; j++) {
199                 e[j].temperature = (int)t[i+j].temperature;
200                 e[j].freq_limits[0] = (unsigned int)t[i+j].freq_limits[0] * 10000;
201                 e[j].freq_limits[1] = (unsigned int)t[i+j].freq_limits[1] * 10000;
202                 e[j].freq_limits[2] = (unsigned int)t[i+j].freq_limits[2] * 10000;
203                 e[j].freq_limits[3] = (unsigned int)t[i+j].freq_limits[3] * 10000;
204         }
205
206         if (edp_limits && edp_limits != edp_default_limits)
207                 kfree(edp_limits);
208
209         edp_limits = e;
210 }
211
212 void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size)
213 {
214         *limits = edp_limits;
215         *size = edp_limits_size;
216 }
217
218 #ifdef CONFIG_DEBUG_FS
219
220 static int edp_limit_debugfs_show(struct seq_file *s, void *data)
221 {
222         seq_printf(s, "%u\n", tegra_get_edp_limit());
223         return 0;
224 }
225
226 static int edp_debugfs_show(struct seq_file *s, void *data)
227 {
228         int i;
229         const struct tegra_edp_limits *limits;
230         int size;
231
232         tegra_get_cpu_edp_limits(&limits, &size);
233
234         seq_printf(s, "-- EDP table --\n");
235         for (i = 0; i < size; i++) {
236                 seq_printf(s, "%4dC: %10d %10d %10d %10d\n",
237                            limits[i].temperature,
238                            limits[i].freq_limits[0],
239                            limits[i].freq_limits[1],
240                            limits[i].freq_limits[2],
241                            limits[i].freq_limits[3]);
242         }
243
244         return 0;
245 }
246
247
248 static int edp_debugfs_open(struct inode *inode, struct file *file)
249 {
250         return single_open(file, edp_debugfs_show, inode->i_private);
251 }
252
253 static int edp_limit_debugfs_open(struct inode *inode, struct file *file)
254 {
255         return single_open(file, edp_limit_debugfs_show, inode->i_private);
256 }
257
258
259 static const struct file_operations edp_debugfs_fops = {
260         .open           = edp_debugfs_open,
261         .read           = seq_read,
262         .llseek         = seq_lseek,
263         .release        = single_release,
264 };
265
266 static const struct file_operations edp_limit_debugfs_fops = {
267         .open           = edp_limit_debugfs_open,
268         .read           = seq_read,
269         .llseek         = seq_lseek,
270         .release        = single_release,
271 };
272
273 static int __init tegra_edp_debugfs_init(void)
274 {
275         struct dentry *d;
276
277         d = debugfs_create_file("edp", S_IRUGO, NULL, NULL,
278                                 &edp_debugfs_fops);
279         if (!d)
280                 return -ENOMEM;
281
282         d = debugfs_create_file("edp_limit", S_IRUGO, NULL, NULL,
283                                 &edp_limit_debugfs_fops);
284
285         return 0;
286 }
287
288 late_initcall(tegra_edp_debugfs_init);
289 #endif /* CONFIG_DEBUG_FS */