ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / tegra30_speedo.c
1 /*
2  * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/bug.h>
19 #include <linux/module.h>
20 #include <linux/moduleparam.h>
21 #include <linux/tegra-fuse.h>
22
23
24 #define CORE_PROCESS_CORNERS_NUM        1
25 #define CPU_PROCESS_CORNERS_NUM         7
26
27 #define FUSE_SPEEDO_CALIB_0     0x114
28 #define FUSE_IDDQ_CALIB_0       0x118
29 #define FUSE_PACKAGE_INFO       0X1FC
30 #define FUSE_TEST_PROG_VER      0X128
31
32 #define G_SPEEDO_BIT_MINUS1     58
33 #define G_SPEEDO_BIT_MINUS1_R   59
34 #define G_SPEEDO_BIT_MINUS2     60
35 #define G_SPEEDO_BIT_MINUS2_R   61
36 #define LP_SPEEDO_BIT_MINUS1    62
37 #define LP_SPEEDO_BIT_MINUS1_R  63
38 #define LP_SPEEDO_BIT_MINUS2    64
39 #define LP_SPEEDO_BIT_MINUS2_R  65
40
41 enum {
42         THRESHOLD_INDEX_0,
43         THRESHOLD_INDEX_1,
44         THRESHOLD_INDEX_2,
45         THRESHOLD_INDEX_3,
46         THRESHOLD_INDEX_4,
47         THRESHOLD_INDEX_5,
48         THRESHOLD_INDEX_6,
49         THRESHOLD_INDEX_7,
50         THRESHOLD_INDEX_8,
51         THRESHOLD_INDEX_9,
52         THRESHOLD_INDEX_10,
53         THRESHOLD_INDEX_11,
54         THRESHOLD_INDEX_12,
55         THRESHOLD_INDEX_13,
56         THRESHOLD_INDEX_14,
57         THRESHOLD_INDEX_COUNT,
58 };
59
60 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
61         {180},
62         {170},
63         {195},
64         {180},
65         {168},
66         {192},
67         {180},
68         {170},
69         {195},
70         {180},
71         {180},
72         {180},
73         {185},
74         {185},
75         {210},
76 };
77
78 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
79         {306, 338, 360, 376, UINT_MAX},
80         {295, 336, 358, 375, UINT_MAX},
81         {325, 325, 358, 375, UINT_MAX},
82         {325, 325, 358, 375, UINT_MAX},
83         {292, 324, 348, 364, UINT_MAX},
84         {324, 324, 348, 364, UINT_MAX},
85         {324, 324, 348, 364, UINT_MAX},
86         {295, 336, 358, 375, UINT_MAX},
87         {358, 358, 358, 358, 397, UINT_MAX},
88         {364, 364, 364, 364, 397, UINT_MAX},
89         {295, 336, 358, 375, 391, UINT_MAX},
90         {295, 336, 358, 375, 391, UINT_MAX},
91         {300, 311, 360, 371, 381, 415, 431},
92         {300, 311, 410, 431, UINT_MAX},
93         {358, 358, 358, 358, 397, UINT_MAX},
94 };
95
96 static int threshold_index;
97 static int cpu_iddq_value;
98
99 /*
100  * Only AP37 supports App Profile
101  * This informs user space of support without exposing cpu id's
102  */
103 static int enable_app_profiles;
104
105 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
106 {
107         u32 reg;
108         int ate_ver;
109         int bit_minus1;
110         int bit_minus2;
111
112         reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
113
114         *speedo_lp = (reg & 0xFFFF) * 4;
115         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
116
117         ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
118         pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
119
120         if (ate_ver >= 26) {
121                 bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
122                 bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
123                 bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
124                 bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
125                 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
126
127                 bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
128                 bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
129                 bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
130                 bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
131                 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
132         } else {
133                 *speedo_lp |= 0x3;
134                 *speedo_g |= 0x3;
135         }
136 }
137
138 static void rev_sku_to_speedo_ids(int rev, int sku)
139 {
140         switch (rev) {
141         case TEGRA_REVISION_A01:
142                 tegra_cpu_speedo_id = 0;
143                 tegra_soc_speedo_id = 0;
144                 threshold_index = THRESHOLD_INDEX_0;
145                 break;
146         case TEGRA_REVISION_A02:
147         case TEGRA_REVISION_A03:
148                 switch (sku) {
149                 case 0x87:
150                 case 0x82:
151                         tegra_cpu_speedo_id = 1;
152                         tegra_soc_speedo_id = 1;
153                         threshold_index = THRESHOLD_INDEX_1;
154                         break;
155                 case 0x81:
156                         switch (tegra_package_id) {
157                         case 1:
158                                 tegra_cpu_speedo_id = 2;
159                                 tegra_soc_speedo_id = 2;
160                                 threshold_index = THRESHOLD_INDEX_2;
161                                 break;
162                         case 2:
163                                 tegra_cpu_speedo_id = 4;
164                                 tegra_soc_speedo_id = 1;
165                                 threshold_index = THRESHOLD_INDEX_7;
166                                 break;
167                         default:
168                                 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
169                                 BUG();
170                                 break;
171                         }
172                         break;
173                 case 0x80:
174                         switch (tegra_package_id) {
175                         case 1:
176                                 tegra_cpu_speedo_id = 5;
177                                 tegra_soc_speedo_id = 2;
178                                 threshold_index = THRESHOLD_INDEX_8;
179                                 break;
180                         case 2:
181                                 tegra_cpu_speedo_id = 6;
182                                 tegra_soc_speedo_id = 2;
183                                 threshold_index = THRESHOLD_INDEX_9;
184                                 break;
185                         default:
186                                 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
187                                 BUG();
188                                 break;
189                         }
190                         break;
191                 case 0x83:
192                         switch (tegra_package_id) {
193                         case 1:
194                                 tegra_cpu_speedo_id = 7;
195                                 tegra_soc_speedo_id = 1;
196                                 threshold_index = THRESHOLD_INDEX_10;
197                                 break;
198                         case 2:
199                                 tegra_cpu_speedo_id = 3;
200                                 tegra_soc_speedo_id = 2;
201                                 threshold_index = THRESHOLD_INDEX_3;
202                                 break;
203                         default:
204                                 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
205                                 BUG();
206                                 break;
207                         }
208                         break;
209                 case 0x8F:
210                         tegra_cpu_speedo_id = 8;
211                         tegra_soc_speedo_id = 1;
212                         threshold_index = THRESHOLD_INDEX_11;
213                         break;
214                 case 0xA0: /* T37 or A37 */
215                         switch (tegra_package_id) {
216                         case 1: /* MID => T37 */
217                                 tegra_cpu_speedo_id = 13;
218                                 tegra_soc_speedo_id = 2;
219                                 threshold_index = THRESHOLD_INDEX_14;
220                                 break;
221                         case 2: /* DSC => AP37 */
222                                 tegra_cpu_speedo_id = 12;
223                                 tegra_soc_speedo_id = 2;
224                                 threshold_index = THRESHOLD_INDEX_9;
225                                 enable_app_profiles = 1;
226                                 break;
227                         default:
228                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
229                                                 tegra_package_id);
230                                 BUG();
231                                 break;
232                         }
233                         break;
234                 case 0x08:
235                         tegra_cpu_speedo_id = 1;
236                         tegra_soc_speedo_id = 1;
237                         threshold_index = THRESHOLD_INDEX_4;
238                         break;
239                 case 0x02:
240                         tegra_cpu_speedo_id = 2;
241                         tegra_soc_speedo_id = 2;
242                         threshold_index = THRESHOLD_INDEX_5;
243                         break;
244                 case 0x04:
245                         tegra_cpu_speedo_id = 3;
246                         tegra_soc_speedo_id = 2;
247                         threshold_index = THRESHOLD_INDEX_6;
248                         break;
249                 case 0x91: /* T30AGS-Ax */
250                 case 0xb0: /* T30IQS-Ax */
251                 case 0xb1: /* T30MQS-Ax */
252                 case 0x90: /* T30AQS-Ax */
253                         tegra_soc_speedo_id = 3;
254                         threshold_index = THRESHOLD_INDEX_12;
255                         break;
256                 case 0x93: /* T30AG-Ax */
257                         tegra_cpu_speedo_id = 11;
258                         tegra_soc_speedo_id = 3;
259                         threshold_index = THRESHOLD_INDEX_13;
260                         break;
261                 case 0:
262                         switch (tegra_package_id) {
263                         case 1:
264                                 tegra_cpu_speedo_id = 2;
265                                 tegra_soc_speedo_id = 2;
266                                 threshold_index = THRESHOLD_INDEX_2;
267                                 break;
268                         case 2:
269                                 tegra_cpu_speedo_id = 3;
270                                 tegra_soc_speedo_id = 2;
271                                 threshold_index = THRESHOLD_INDEX_3;
272                                 break;
273                         default:
274                                 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
275                                 BUG();
276                                 break;
277                         }
278                         break;
279                 default:
280                         pr_warn("Tegra30: Unknown SKU %d\n", sku);
281                         tegra_cpu_speedo_id = 0;
282                         tegra_soc_speedo_id = 0;
283                         threshold_index = THRESHOLD_INDEX_0;
284                         break;
285                 }
286                 break;
287         default:
288                 pr_warn("Tegra30: Unknown chip rev %d\n", rev);
289                 tegra_cpu_speedo_id = 0;
290                 tegra_soc_speedo_id = 0;
291                 threshold_index = THRESHOLD_INDEX_0;
292                 break;
293         }
294 }
295
296 /*
297  * CPU and core nominal voltage levels as determined by chip SKU and speedo
298  * (not final - can be lowered by dvfs tables and rail dependencies; the
299  * latter is resolved by the dvfs code)
300  */
301 static const int cpu_speedo_nominal_millivolts[] =
302 /* speedo_id 0,    1,    2,    3,    4,    5,    6,    7,    8,   9,  10,  11,   12,    13,  14,  15 */
303         { 1125, 1150, 1150, 1150, 1237, 1237, 1237, 1150, 1150, 1007, 916, 850, 1237, 1237, 950, 900};
304
305 void tegra30_init_speedo_data(void)
306 {
307         u32 cpu_speedo_val;
308         u32 core_speedo_val;
309         int i;
310         int fuse_sku, new_sku;
311
312         fuse_sku = tegra_get_sku_id();
313         new_sku = fuse_sku;
314
315         BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
316                         THRESHOLD_INDEX_COUNT);
317         BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
318                         THRESHOLD_INDEX_COUNT);
319
320         tegra_package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
321
322         cpu_iddq_value = tegra_fuse_readl(FUSE_IDDQ_CALIB_0);
323         cpu_iddq_value = ((cpu_iddq_value >> 5) & 0x3ff) * 8;
324
325         /* SKU Overrides
326         * T33   => T30, T30L
327         * T33S  => T30S, T30SL
328         * T30   => T30L
329         * T30S  => T30SL
330         * AP33  => AP30
331         */
332         switch (tegra_sku_override) {
333         case 1:
334                 /* Base sku override */
335                 if (fuse_sku == 0x80) {
336                         if (tegra_package_id == 1) {
337                                 /* T33 to T30 */
338                                 pr_info("%s: SKU OR: T33->T30\n", __func__);
339                                 new_sku = 0x81;
340                         } else if (tegra_package_id == 2) {
341                                 /* T33S->T30S */
342                                 pr_info("%s: SKU OR: T33S->T30S\n", __func__);
343                                 new_sku = 0x83;
344                         }
345                 } else if (fuse_sku == 0x81) {
346                         if (tegra_package_id == 2) {
347                                 /* AP33->AP30 */
348                                 pr_info("%s: SKU OR: AP33->AP30\n", __func__);
349                                 new_sku = 0x87;
350                         }
351                 }
352                 break;
353         case 2:
354                 /* L sku override */
355                 if (fuse_sku == 0x80) {
356                         if (tegra_package_id == 1) {
357                                 /* T33->T30L */
358                                 pr_info("%s: SKU OR: T33->T30L\n", __func__);
359                                 new_sku = 0x83;
360                         } else if (tegra_package_id == 2) {
361                                 /* T33S->T33SL */
362                                 pr_info("%s: SKU OR: T33S->T30SL\n", __func__);
363                                 new_sku = 0x8f;
364                         }
365                 } else if (fuse_sku == 0x81) {
366                         if (tegra_package_id == 1) {
367                                 pr_info("%s: SKU OR: T30->T30L\n", __func__);
368                                 /* T30->T30L */
369                                 new_sku = 0x83;
370                         }
371                 } else if (fuse_sku == 0x83) {
372                         if (tegra_package_id == 2) {
373                                 pr_info("%s: SKU OR: T30S->T30SL\n", __func__);
374                                 /* T30S to T30SL */
375                                 new_sku = 0x8f;
376                         }
377                 }
378                 break;
379         default:
380                 /* no override */
381                 break;
382         }
383
384         rev_sku_to_speedo_ids(tegra_revision, new_sku);
385         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
386         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
387         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
388
389         for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
390                 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
391                         break;
392         }
393         tegra_cpu_process_id = i - 1;
394
395         if (tegra_cpu_process_id == -1) {
396                 pr_warn("Tegra30: CPU speedo value %3d out of range",
397                        cpu_speedo_val);
398                 tegra_cpu_process_id = 0;
399                 tegra_cpu_speedo_id = 1;
400         } else {
401                 if (threshold_index == 12) {
402                         if (tegra_cpu_process_id <= 2) {
403                                 switch(fuse_sku) {
404                                 case 0xb0:
405                                 case 0xb1:
406                                         tegra_cpu_speedo_id = 9;
407                                         break;
408                                 case 0x90:
409                                 case 0x91:
410                                         tegra_cpu_speedo_id = 14;
411                                 default:
412                                         break;
413                                 }
414                         } else if (tegra_cpu_process_id >= 3 && tegra_cpu_process_id < 6) {
415                                 switch(fuse_sku) {
416                                 case 0xb0:
417                                 case 0xb1:
418                                         tegra_cpu_speedo_id = 10;
419                                         break;
420                                 case 0x90:
421                                 case 0x91:
422                                         tegra_cpu_speedo_id = 15;
423                                 default:
424                                         break;
425                                 }
426                         }
427                 }
428         }
429
430         for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
431                 if (core_speedo_val < core_process_speedos[threshold_index][i])
432                         break;
433         }
434         tegra_core_process_id = i - 1;
435
436         if (tegra_core_process_id == -1) {
437                 pr_warn("Tegra30: CORE speedo value %3d out of range",
438                        core_speedo_val);
439                 tegra_core_process_id = 0;
440                 tegra_soc_speedo_id = 1;
441         }
442
443         pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
444                 tegra_cpu_speedo_id, tegra_soc_speedo_id);
445
446         tegra_cpu_speedo_mv =
447                 cpu_speedo_nominal_millivolts[tegra_cpu_speedo_id];
448         
449         switch (tegra_soc_speedo_id) {
450         case 0:
451                 tegra_core_speedo_mv = 1200;
452                 break;
453         case 1:
454                 if ((tegra_cpu_speedo_id != 7) &&
455                     (tegra_cpu_speedo_id != 8)) {
456                         tegra_core_speedo_mv = 1200;
457                         break;
458                 }
459                 /* fall thru for T30L or T30SL */
460         case 2:
461                 if (tegra_cpu_speedo_id != 13)
462                         tegra_core_speedo_mv = 1300;
463                 else /* T37 */
464                         tegra_core_speedo_mv = 1350;
465                 break;
466         case 3:
467                 tegra_core_speedo_mv = 1250;
468                 break;
469         default:
470                 BUG();
471         }
472 }
473
474 int tegra_get_cpu_iddq_value()
475 {
476         return cpu_iddq_value;
477 }
478
479 static int get_enable_app_profiles(char *val, const struct kernel_param *kp)
480 {
481         return param_get_uint(val, kp);
482 }
483
484 static struct kernel_param_ops tegra_profiles_ops = {
485         .get = get_enable_app_profiles,
486 };
487
488 module_param_cb(tegra_enable_app_profiles,
489         &tegra_profiles_ops, &enable_app_profiles, 0444);