]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/blob - drivers/platform/tegra/tegra21_speedo.c
e92140e4657f904935a38283930759cfb2adcfb9
[sojka/nv-tegra/linux-3.10.git] / drivers / platform / tegra / tegra21_speedo.c
1 /*
2  * arch/arm/mach-tegra/tegra21_speedo.c
3  *
4  * Copyright (C) 2013-2015 NVIDIA Corporation. All rights reserved.
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; version 2 of the License.
9  *
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
13  * more details.
14  *
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.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <linux/bug.h>                  /* For BUG_ON.  */
25
26 #include <linux/tegra-fuse.h>
27 #include <linux/tegra-soc.h>
28 #include <linux/module.h>
29 #include <linux/moduleparam.h>
30
31 #include "iomap.h"
32 #include <linux/platform/tegra/common.h>
33
34 #define TEGRA21_SOC_SPEEDO 1900
35 #define TEGRA21_CPU_SPEEDO 2100
36 #define TEGRA21_GPU_SPEEDO 2100
37 #define TEGRA21_GPU_SPEEDO_OFFS 75
38
39
40 #define CPU_PROCESS_CORNERS_NUM         3
41 #define GPU_PROCESS_CORNERS_NUM         2
42 #define CORE_PROCESS_CORNERS_NUM        3
43
44 #define FUSE_CPU_SPEEDO_0       0x114
45 #define FUSE_CPU_SPEEDO_1       0x12c
46 #define FUSE_CPU_SPEEDO_2       0x130
47 #define FUSE_SOC_SPEEDO_0       0x134
48 #define FUSE_SOC_SPEEDO_1       0x138
49 #define FUSE_SOC_SPEEDO_2       0x13c
50 #define FUSE_CPU_IDDQ           0x118
51 #define FUSE_SOC_IDDQ           0x140
52 #define FUSE_GPU_IDDQ           0x228
53 #define FUSE_FT_REV             0x128
54
55 static int threshold_index;
56 static int cpu_process_id;
57 static int core_process_id;
58 static int gpu_process_id;
59 static int cpu_speedo_id;
60 static int soc_speedo_id;
61 static int gpu_speedo_id;
62 static int package_id;
63
64 static int core_min_mv;
65
66 static int cpu_iddq_value;
67 static int gpu_iddq_value;
68 static int soc_iddq_value;
69
70 static int cpu_speedo_0_value;
71 static int cpu_speedo_1_value;
72 static int cpu_speedo_2_value;
73 static int soc_speedo_0_value;
74 static int soc_speedo_1_value;
75 static int soc_speedo_2_value;
76
77 static int cpu_speedo_value;
78 static int gpu_speedo_value;
79 static int soc_speedo_value;
80
81 static int speedo_rev;
82
83 static int enable_app_profiles;
84
85 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
86 /* proc_id  0,         1          2 */
87         {2119,  UINT_MAX,  UINT_MAX}, /* [0]: threshold_index 0 */
88         {2119,  UINT_MAX,  UINT_MAX}, /* [1]: threshold_index 1 */
89 };
90
91 static const u32 gpu_process_speedos[][GPU_PROCESS_CORNERS_NUM] = {
92 /* proc_id      0,        1 */
93         {UINT_MAX, UINT_MAX}, /* [0]: threshold_index 0 */
94         {UINT_MAX, UINT_MAX}, /* [1]: threshold_index 1 */
95 };
96
97 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
98 /* proc_id  0,         1,             2 */
99         {1950,      2073,      UINT_MAX}, /* [0]: threshold_index 0 */
100         {UINT_MAX,  UINT_MAX,  UINT_MAX}, /* [1]: threshold_index 1 */
101 };
102
103 static void rev_sku_to_speedo_ids(int rev, int sku, int speedo_rev)
104 {
105         bool shield_sku = false;
106         bool vcm31_sku = false;
107         bool a02 = rev == TEGRA_REVISION_A02;
108
109 #ifdef CONFIG_OF
110         shield_sku = of_property_read_bool(of_chosen,
111                                            "nvidia,tegra-shield-sku");
112         vcm31_sku = of_property_read_bool(of_chosen,
113                                                "nvidia,t210-vcm31-sku");
114 #endif
115         switch (sku) {
116         case 0x13:
117                 if (a02 && !shield_sku) {
118                         cpu_speedo_id = 5;
119                         soc_speedo_id = 0;
120                         gpu_speedo_id = 2;
121                         threshold_index = 0;
122                         core_min_mv = 800;
123                         break;
124                 }
125                 /* fall thru for a01 or shild sku */
126         case 0x00: /* Engg sku */
127         case 0x01: /* Engg sku */
128         case 0x07:
129         case 0x17:
130                 if (!vcm31_sku || (sku != 0x17)) {
131                         if (a02 && !shield_sku) {
132                                 cpu_speedo_id = 1;
133                                 soc_speedo_id = 0;
134                                 gpu_speedo_id = 2;
135                                 threshold_index = 0;
136                                 core_min_mv = 800;
137                         } else {
138                                 cpu_speedo_id = shield_sku ? 2 : 0;
139                                 soc_speedo_id = 0;
140                                 gpu_speedo_id = 1;
141                                 threshold_index = 0;
142                                 core_min_mv = 825;
143                         }
144                         break;
145                 }
146                 /* fall thru for vcm31_sku 0x17 */
147         case 0x57:
148                 cpu_speedo_id = 4;
149                 soc_speedo_id = 1;
150                 gpu_speedo_id = 4;
151                 threshold_index = 1;
152                 core_min_mv = 1100;
153                 break;
154         case 0x83:
155                 if (a02) {
156                         cpu_speedo_id = 3;
157                         soc_speedo_id = 0;
158                         gpu_speedo_id = 3;
159                         threshold_index = 0;
160                         core_min_mv = 800;
161                         break;
162                 }
163                 /* fall thru for a01 part and Darcy*/
164         case 0x87:
165                 if (a02) {
166                         cpu_speedo_id = 6;
167                         soc_speedo_id = 0;
168                         gpu_speedo_id = 1;
169                         threshold_index = 0;
170                         core_min_mv = 825;
171                         break;
172                 }
173                 /* fall thru for a01 part */
174         case 0x8F:
175                 if (a02) {
176                         cpu_speedo_id = 1;
177                         soc_speedo_id = 0;
178                         gpu_speedo_id = 2;
179                         threshold_index = 0;
180                         core_min_mv = 800;
181                         break;
182                 }
183                 /* fall thru for a01 part */
184         default:
185                 pr_warn("Tegra21: Unknown SKU %d\n", sku);
186                 cpu_speedo_id = 0;
187                 soc_speedo_id = 0;
188                 gpu_speedo_id = 0;
189                 threshold_index = 0;
190                 core_min_mv = 950;
191                 break;
192         }
193
194         /* Overwrite GPU speedo selection for speedo revision 0, 1 */
195         if (speedo_rev < 2)
196                 gpu_speedo_id = 0;
197 }
198
199 static int get_speedo_rev(void)
200 {
201         return (tegra_spare_fuse(4) << 2) |
202                 (tegra_spare_fuse(3) << 1) |
203                 (tegra_spare_fuse(2) << 0);
204 }
205
206 void tegra_init_speedo_data(void)
207 {
208         int i;
209         u32 tegra_sku_id;
210
211         if (!tegra_platform_is_silicon()) {
212                 cpu_process_id  =  0;
213                 core_process_id =  0;
214                 gpu_process_id  = 0;
215                 cpu_speedo_id   = 0;
216                 soc_speedo_id   = 0;
217                 gpu_speedo_id   = 0;
218                 package_id = -1;
219                 cpu_speedo_value = TEGRA21_CPU_SPEEDO;
220                 gpu_speedo_value = TEGRA21_GPU_SPEEDO;
221                 soc_speedo_value = TEGRA21_SOC_SPEEDO;
222                 cpu_speedo_0_value = 0;
223                 cpu_speedo_1_value = 0;
224                 soc_speedo_0_value = 0;
225                 soc_speedo_1_value = 0;
226                 soc_speedo_2_value = 0;
227                 soc_iddq_value = 0;
228                 gpu_iddq_value = 0;
229                 pr_info("Tegra21: CPU Speedo value %d, Soc Speedo value %d, Gpu Speedo value %d\n",
230                         cpu_speedo_value, soc_speedo_value, gpu_speedo_value);
231                 pr_info("Tegra21: CPU Speedo ID %d, Soc Speedo ID %d, Gpu Speedo ID %d\n",
232                         cpu_speedo_id, soc_speedo_id, gpu_speedo_id);
233                 pr_info("Tegra21: CPU Process ID %d,Soc Process ID %d,Gpu Process ID %d\n",
234                         cpu_process_id, core_process_id, gpu_process_id);
235                 return;
236         }
237
238         /* Read speedo/iddq fuses */
239         cpu_speedo_0_value = tegra_fuse_readl(FUSE_CPU_SPEEDO_0);
240         cpu_speedo_1_value = tegra_fuse_readl(FUSE_CPU_SPEEDO_1);
241         cpu_speedo_2_value = tegra_fuse_readl(FUSE_CPU_SPEEDO_2);
242
243         soc_speedo_0_value = tegra_fuse_readl(FUSE_SOC_SPEEDO_0);
244         soc_speedo_1_value = tegra_fuse_readl(FUSE_SOC_SPEEDO_1);
245         soc_speedo_2_value = tegra_fuse_readl(FUSE_SOC_SPEEDO_2);
246
247         cpu_iddq_value = tegra_fuse_readl(FUSE_CPU_IDDQ) * 4;
248         soc_iddq_value = tegra_fuse_readl(FUSE_SOC_IDDQ) * 4;
249         gpu_iddq_value = tegra_fuse_readl(FUSE_GPU_IDDQ) * 5;
250
251         /*
252          * Determine CPU, GPU, SOC speedo values depending on speedo fusing
253          * revision. Note that GPU speedo value is fused in CPU_SPEEDO_2
254          */
255         speedo_rev = get_speedo_rev();
256         if (speedo_rev >= 3) {
257                 cpu_speedo_value = cpu_speedo_0_value;
258                 gpu_speedo_value = cpu_speedo_2_value;
259                 soc_speedo_value = soc_speedo_0_value;
260         } else if (speedo_rev == 2) {
261                 cpu_speedo_value = (-1938 + (1095*cpu_speedo_0_value/100)) / 10;
262                 gpu_speedo_value = (-1662 + (1082*cpu_speedo_2_value/100)) / 10;
263                 soc_speedo_value = (-705 + (1037*soc_speedo_0_value/100)) / 10;
264         } else {
265                 /* FIXME: do we need hard-coded IDDQ here? */
266                 cpu_speedo_value = TEGRA21_CPU_SPEEDO;
267                 gpu_speedo_value = cpu_speedo_2_value - TEGRA21_GPU_SPEEDO_OFFS;
268                 soc_speedo_value = TEGRA21_SOC_SPEEDO;
269         }
270
271         if (cpu_speedo_value <= 0) {
272                 cpu_speedo_value = TEGRA21_CPU_SPEEDO;
273                 pr_warn("Tegra21: Warning: CPU Speedo value not fused. PLEASE FIX!!!!!!!!!!!\n");
274                 pr_warn("Tegra21: Warning: PLEASE USE BOARD WITH FUSED SPEEDO VALUE !!!!\n");
275         }
276
277         if (gpu_speedo_value <= 0) {
278                 gpu_speedo_value = TEGRA21_GPU_SPEEDO;
279                 pr_warn("Tegra21: Warning: GPU Speedo value not fused. PLEASE FIX!!!!!!!!!!!\n");
280                 pr_warn("Tegra21: Warning: PLEASE USE BOARD WITH FUSED SPEEDO VALUE !!!!\n");
281         }
282
283         if (soc_speedo_value <= 0) {
284                 soc_speedo_value = TEGRA21_SOC_SPEEDO;
285                 pr_warn("Tegra21: Warning: SOC Speedo value not fused. PLEASE FIX!!!!!!!!!!!\n");
286                 pr_warn("Tegra21: Warning: PLEASE USE BOARD WITH FUSED SPEEDO VALUE !!!!\n");
287         }
288
289         /* Map chip sku, rev, speedo values into speedo and process IDs */
290         tegra_sku_id = tegra_get_sku_id();
291         rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, speedo_rev);
292
293         for (i = 0; i < GPU_PROCESS_CORNERS_NUM; i++) {
294                 if (gpu_speedo_value <
295                         gpu_process_speedos[threshold_index][i]) {
296                         break;
297                 }
298         }
299         gpu_process_id = i;
300
301         for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
302                 if (cpu_speedo_value <
303                         cpu_process_speedos[threshold_index][i]) {
304                         break;
305                 }
306         }
307         cpu_process_id = i;
308
309         for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
310                 if (soc_speedo_value <
311                         core_process_speedos[threshold_index][i]) {
312                         break;
313                 }
314         }
315         core_process_id = i;
316
317         pr_info("Tegra21: Speedo/IDDQ fuse revision %d\n", speedo_rev);
318         pr_info("Tegra21: CPU Speedo ID %d, Soc Speedo ID %d, Gpu Speedo ID %d\n",
319                 cpu_speedo_id, soc_speedo_id, gpu_speedo_id);
320         pr_info("Tegra21: CPU Process ID %d, Soc Process ID %d, Gpu Process ID %d\n",
321                  cpu_process_id, core_process_id, gpu_process_id);
322         pr_info("Tegra21: CPU Speedo value %d, Soc Speedo value %d, Gpu Speedo value %d\n",
323                  cpu_speedo_value, soc_speedo_value, gpu_speedo_value);
324         pr_info("Tegra21: CPU IDDQ %d, Soc IDDQ %d, Gpu IDDQ %d\n",
325                 cpu_iddq_value, soc_iddq_value, gpu_iddq_value);
326 }
327
328 int tegra_cpu_process_id(void)
329 {
330         return cpu_process_id;
331 }
332
333 int tegra_core_process_id(void)
334 {
335         return core_process_id;
336 }
337
338 int tegra_gpu_process_id(void)
339 {
340         return gpu_process_id;
341 }
342
343 int tegra_cpu_speedo_id(void)
344 {
345         return cpu_speedo_id;
346 }
347
348 int tegra_soc_speedo_id(void)
349 {
350         return soc_speedo_id;
351 }
352
353 int tegra_gpu_speedo_id(void)
354 {
355         return gpu_speedo_id;
356 }
357
358 int tegra_package_id(void)
359 {
360         return package_id;
361 }
362
363 int tegra_cpu_speedo_value(void)
364 {
365         return cpu_speedo_value;
366 }
367
368 int tegra_cpu_speedo_0_value(void)
369 {
370         return cpu_speedo_0_value;
371 }
372
373 int tegra_cpu_speedo_1_value(void)
374 {
375         return cpu_speedo_1_value;
376 }
377
378 int tegra_gpu_speedo_value(void)
379 {
380         return gpu_speedo_value;
381 }
382
383 int tegra_soc_speedo_0_value(void)
384 {
385         return soc_speedo_value;
386 }
387 EXPORT_SYMBOL(tegra_soc_speedo_0_value);
388
389 int tegra_soc_speedo_1_value(void)
390 {
391         return soc_speedo_1_value;
392 }
393
394 int tegra_soc_speedo_2_value(void)
395 {
396         return soc_speedo_2_value;
397 }
398
399 /*
400  * Core nominal and minimum voltage levels as determined by chip SKU and speedo
401  * (not final - will be clipped to dvfs tables).
402  */
403 int tegra_cpu_speedo_mv(void)
404 {
405         /* Not applicable on Tegra21 */
406         return -ENOSYS;
407 }
408
409 int tegra_core_speedo_mv(void)
410 {
411         switch (core_process_id) {
412         case 0:
413                 if (soc_speedo_id == 1)
414                         return 1100;
415                 if (speedo_rev <= 1)
416                         return 1000;
417                 return 1125;
418         case 1:
419                 return 1075;
420         case 2:
421                 return 1000;
422         default:
423                 BUG();
424         }
425 }
426
427 int tegra_core_speedo_min_mv(void)
428 {
429         return core_min_mv;
430 }
431
432 int tegra_get_cpu_iddq_value(void)
433 {
434         return cpu_iddq_value;
435 }
436
437 int tegra_get_soc_iddq_value(void)
438 {
439         return soc_iddq_value;
440 }
441
442 int tegra_get_gpu_iddq_value(void)
443 {
444         return gpu_iddq_value;
445 }
446
447 static int get_enable_app_profiles(char *val, const struct kernel_param *kp)
448 {
449         return param_get_uint(val, kp);
450 }
451
452 static struct kernel_param_ops tegra_profiles_ops = {
453         .get = get_enable_app_profiles,
454 };
455
456 module_param_cb(tegra_enable_app_profiles,
457         &tegra_profiles_ops, &enable_app_profiles, 0444);