1f5c79efc486aca40364632463d271cd6a2df9e7
[linux-2.6.git] / arch / arm / mach-tegra / tegra3_speedo.c
1 /*
2  * arch/arm/mach-tegra/tegra3_speedo.c
3  *
4  * Copyright (c) 2011, NVIDIA Corporation.
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 as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <mach/iomap.h>
25
26 #include "fuse.h"
27
28 #define CORE_PROCESS_CORNERS_NUM        1
29 #define CPU_PROCESS_CORNERS_NUM 7
30
31 #define FUSE_SPEEDO_CALIB_0     0x114
32 #define FUSE_PACKAGE_INFO       0X1FC
33
34 /* Maximum speedo levels for each core process corner */
35 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
36 /* proc_id 0 */
37         {180}, /* [0]: soc_speedo_id 0: any A01 */
38
39 /* T30 family */
40         {180}, /* [1]: soc_speedo_id 1: AP30 */
41         {204}, /* [2]: soc_speedo_id 2: T30  */
42         {192}, /* [3]: soc_speedo_id 2: T30S */
43
44 /* Characterization SKUs */
45         {168}, /* [4]: soc_speedo_id 1: AP30 char */
46         {192}, /* [5]: soc_speedo_id 2: T30  char */
47         {184}, /* [6]: soc_speedo_id 2: T30S char */
48
49 /* T33 family */
50         {180}, /* [7]: soc_speedo_id = 1 - AP33 */
51         {208}, /* [8]: soc_speedo_id = 2 - T33  */
52         {192}, /* [9]: soc_speedo_id = 2 - T33S */
53
54 /* T30 'L' family */
55         {192}, /* [10]: soc_speedo_id 1: T30L */
56         {192}, /* [11]: soc_speedo_id 1: T30SL */
57
58 /* T30 Automotives */
59         {185}, /* [12]: soc_speedo_id = 3 - Automotives */
60         {185}, /* [13]: soc_speedo_id = 3 - Automotives */
61 };
62
63 /* Maximum speedo levels for each CPU process corner */
64 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
65 /* proc_id 0    1    2    3    4*/
66         {306, 338, 360, 376, UINT_MAX}, /* [0]: cpu_speedo_id 0: any A01 */
67
68 /* T30 family */
69         {304, 336, 359, 375, UINT_MAX}, /* [1]: cpu_speedo_id 1: AP30 */
70         {336, 336, 359, 375, UINT_MAX}, /* [2]: cpu_speedo_id 2: T30  */
71         {336, 336, 359, 375, UINT_MAX}, /* [3]: cpu_speedo_id 3: T30S */
72
73 /* Characterization SKUs */
74         {292, 324, 348, 364, UINT_MAX}, /* [4]: cpu_speedo_id 1: AP30char */
75         {324, 324, 348, 364, UINT_MAX}, /* [5]: cpu_speedo_id 2: T30char  */
76         {324, 324, 348, 364, UINT_MAX}, /* [6]: cpu_speedo_id 3: T30Schar */
77
78 /* T33 family */
79         {305, 337, 359, 376, UINT_MAX}, /* [7]: cpu_speedo_id = 4 - AP33 */
80         {368, 368, 368, 368, 392, UINT_MAX}, /* [8]: cpu_speedo_id = 5 - T33  */
81         {376, 376, 376, 376, 392, UINT_MAX}, /* [9]: cpu_speedo_id = 6 - T33S */
82
83 /* T30 'L' family */
84         {305, 337, 359, 376, 392, UINT_MAX}, /* [10]: cpu_speedo_id 7: T30L  */
85         {305, 337, 359, 376, 392, UINT_MAX}, /* [11]: cpu_speedo_id 8: T30SL */
86
87 /* T30 Automotives */
88         /* threshold_index 12: cpu_speedo_id 9 & 10
89          * 0,1,2 values correspond to speedo_id  9
90          * 3,4,5 values correspond to speedo_id 10
91          */
92         {300, 311, 360, 371, 381, 415, 431},
93         {300, 311, 410, 431, UINT_MAX}, /* threshold_index 13: cpu_speedo_id = 11 */
94 };
95
96 /*
97  * Common speedo_value array threshold index for both core_process_speedos and
98  * cpu_process_speedos arrays. Make sure these two arrays are always in synch.
99  */
100 static int threshold_index;
101
102 static int cpu_process_id;
103 static int core_process_id;
104 static int cpu_speedo_id;
105 static int soc_speedo_id;
106 static int package_id;
107
108 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
109 {
110         u32 reg;
111
112         BUG_ON(!speedo_g || !speedo_lp);
113         reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
114
115         /* Speedo LP = Lower 16-bits Multiplied by 4 */
116         *speedo_lp = (reg & 0xFFFF) * 4;
117
118         /* Speedo G = Upper 16-bits Multiplied by 4 */
119         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
120 }
121
122 static void rev_sku_to_speedo_ids(int rev, int sku)
123 {
124         switch (rev) {
125         case TEGRA_REVISION_A01: /* any A01 */
126                 cpu_speedo_id = 0;
127                 soc_speedo_id = 0;
128                 threshold_index = 0;
129                 break;
130
131         case TEGRA_REVISION_A02:
132         case TEGRA_REVISION_A03:
133                 switch (sku) {
134                 case 0x87: /* AP30 */
135                 case 0x82: /* T30V */
136                         cpu_speedo_id = 1;
137                         soc_speedo_id = 1;
138                         threshold_index = 1;
139                         break;
140
141                 case 0x81: /* T30 */
142                         switch (package_id) {
143                         case 1: /* MID => T30 */
144                                 cpu_speedo_id = 2;
145                                 soc_speedo_id = 2;
146                                 threshold_index = 2;
147                                 break;
148                         case 2: /* DSC => AP33 */
149                                 cpu_speedo_id = 4;
150                                 soc_speedo_id = 1;
151                                 threshold_index = 7;
152                                 break;
153                         default:
154                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
155                                        package_id);
156                                 BUG();
157                                 break;
158                         }
159                         break;
160
161                 case 0x80: /* T33 or T33S */
162                         switch (package_id) {
163                         case 1: /* MID => T33 */
164                                 cpu_speedo_id = 5;
165                                 soc_speedo_id = 2;
166                                 threshold_index = 8;
167                                 break;
168                         case 2: /* DSC => T33S */
169                                 cpu_speedo_id = 6;
170                                 soc_speedo_id = 2;
171                                 threshold_index = 9;
172                                 break;
173                         default:
174                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
175                                        package_id);
176                                 BUG();
177                                 break;
178                         }
179                         break;
180
181                 case 0x83: /* T30L or T30S */
182                         switch (package_id) {
183                         case 1: /* MID => T30L */
184                                 cpu_speedo_id = 7;
185                                 soc_speedo_id = 1;
186                                 threshold_index = 10;
187                                 break;
188                         case 2: /* DSC => T30S */
189                                 cpu_speedo_id = 3;
190                                 soc_speedo_id = 2;
191                                 threshold_index = 3;
192                                 break;
193                         default:
194                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
195                                        package_id);
196                                 BUG();
197                                 break;
198                         }
199                         break;
200
201                 case 0x8F: /* T30SL */
202                         cpu_speedo_id = 8;
203                         soc_speedo_id = 1;
204                         threshold_index = 11;
205                         break;
206
207 /* Characterization SKUs */
208                 case 0x08: /* AP30 char */
209                         cpu_speedo_id = 1;
210                         soc_speedo_id = 1;
211                         threshold_index = 4;
212                         break;
213                 case 0x02: /* T30 char */
214                         cpu_speedo_id = 2;
215                         soc_speedo_id = 2;
216                         threshold_index = 5;
217                         break;
218                 case 0x04: /* T30S char */
219                         cpu_speedo_id = 3;
220                         soc_speedo_id = 2;
221                         threshold_index = 6;
222                         break;
223
224                 case 0x91: /* T30AGS-Ax */
225                 case 0xb0: /* T30IQS-Ax */
226                 case 0xb1: /* T30MQS-Ax */
227                 case 0x90: /* T30AQS-Ax */
228                         soc_speedo_id = 3;
229                         threshold_index = 12;
230                         break;
231                 case 0x93: /* T30AG-Ax */
232                         cpu_speedo_id = 11;
233                         soc_speedo_id = 3;
234                         threshold_index = 13;
235                         break;
236                 case 0:    /* ENG - check package_id */
237                         pr_info("Tegra3 ENG SKU: Checking package_id\n");
238                         switch (package_id) {
239                         case 1: /* MID => assume T30 */
240                                 cpu_speedo_id = 2;
241                                 soc_speedo_id = 2;
242                                 threshold_index = 2;
243                                 break;
244                         case 2: /* DSC => assume T30S */
245                                 cpu_speedo_id = 3;
246                                 soc_speedo_id = 2;
247                                 threshold_index = 3;
248                                 break;
249                         default:
250                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
251                                        package_id);
252                                 BUG();
253                                 break;
254                         }
255                         break;
256
257                 default:
258                         /* FIXME: replace with BUG() when all SKU's valid */
259                         pr_err("Tegra3 Rev-A02: Unknown SKU %d\n", sku);
260                         cpu_speedo_id = 0;
261                         soc_speedo_id = 0;
262                         threshold_index = 0;
263                         break;
264                 }
265                 break;
266         default:
267                 BUG();
268                 break;
269         }
270 }
271
272 void tegra_init_speedo_data(void)
273 {
274         u32 cpu_speedo_val, core_speedo_val;
275         int iv;
276
277         /* Package info: 4 bits - 0,3:reserved 1:MID 2:DSC */
278         package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
279
280         /* Arrays must be of equal size - each index corresponds to a SKU */
281         BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
282                ARRAY_SIZE(core_process_speedos));
283
284         rev_sku_to_speedo_ids(tegra_get_revision(), tegra_sku_id());
285         BUG_ON(threshold_index >= ARRAY_SIZE(cpu_process_speedos));
286
287         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
288         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
289         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
290
291         for (iv = 0; iv < CPU_PROCESS_CORNERS_NUM; iv++) {
292                 if (cpu_speedo_val <
293                     cpu_process_speedos[threshold_index][iv]) {
294                         break;
295                 }
296         }
297         cpu_process_id = iv -1;
298
299         if (cpu_process_id == -1) {
300                 pr_err("****************************************************");
301                 pr_err("****************************************************");
302                 pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
303                        cpu_speedo_val);
304                 pr_err("****************************************************");
305                 pr_err("****************************************************");
306
307                 cpu_process_id = INVALID_PROCESS_ID;
308                 cpu_speedo_id = 1;
309         }
310
311         for (iv = 0; iv < CORE_PROCESS_CORNERS_NUM; iv++) {
312                 if (core_speedo_val <
313                     core_process_speedos[threshold_index][iv]) {
314                         break;
315                 }
316         }
317         core_process_id = iv -1;
318
319         if (core_process_id == -1) {
320                 pr_err("****************************************************");
321                 pr_err("****************************************************");
322                 pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
323                        core_speedo_val);
324                 pr_err("****************************************************");
325                 pr_err("****************************************************");
326
327                 core_process_id = INVALID_PROCESS_ID;
328                 soc_speedo_id = 1;
329         }
330         if (threshold_index == 12 && cpu_process_id != INVALID_PROCESS_ID) {
331                 if (cpu_process_id <= 2)
332                         cpu_speedo_id = 9;
333                 else if (cpu_process_id >= 3 && cpu_process_id < 6)
334                         cpu_speedo_id = 10;
335         }
336         pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
337                  cpu_speedo_id, soc_speedo_id);
338 }
339
340 int tegra_cpu_process_id(void)
341 {
342         /* FIXME: remove when ready to deprecate invalid process-id boards */
343         if (cpu_process_id == INVALID_PROCESS_ID)
344                 return 0;
345         else
346                 return cpu_process_id;
347 }
348
349 int tegra_core_process_id(void)
350 {
351         /* FIXME: remove when ready to deprecate invalid process-id boards */
352         if (core_process_id == INVALID_PROCESS_ID)
353                 return 0;
354         else
355                 return core_process_id;
356 }
357
358 int tegra_cpu_speedo_id(void)
359 {
360         return cpu_speedo_id;
361 }
362
363 int tegra_soc_speedo_id(void)
364 {
365         return soc_speedo_id;
366 }
367
368 int tegra_package_id(void)
369 {
370         return package_id;
371 }
372
373 /*
374  * CPU and core nominal voltage levels as determined by chip SKU and speedo
375  * (not final - can be lowered by dvfs tables and rail dependencies; the
376  * latter is resolved by the dvfs code)
377  */
378 static const int cpu_speedo_nominal_millivolts[] =
379 /* speedo_id 0,    1,    2,    3,    4,    5,    6,    7,    8,   9,  10,  11 */
380         { 1125, 1150, 1150, 1150, 1237, 1237, 1237, 1150, 1150, 912, 850, 850};
381
382 int tegra_cpu_speedo_mv(void)
383 {
384         BUG_ON(cpu_speedo_id >= ARRAY_SIZE(cpu_speedo_nominal_millivolts));
385         return cpu_speedo_nominal_millivolts[cpu_speedo_id];
386 }
387
388 int tegra_core_speedo_mv(void)
389 {
390         switch (soc_speedo_id) {
391         case 0:
392                 return 1200;
393         case 1:
394                 if ((cpu_speedo_id != 7) && (cpu_speedo_id != 8))
395                         return 1200;
396                 /* fall thru for T30L or T30SL */
397         case 2:
398                 return 1300;
399         case 3:
400                 return 1250;
401         default:
402                 BUG();
403         }
404 }