2 * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
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.
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
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/>.
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>
24 #define CORE_PROCESS_CORNERS_NUM 1
25 #define CPU_PROCESS_CORNERS_NUM 7
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
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
57 THRESHOLD_INDEX_COUNT,
60 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
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},
96 static int threshold_index;
97 static int cpu_iddq_value;
100 * Only AP37 supports App Profile
101 * This informs user space of support without exposing cpu id's
103 static int enable_app_profiles;
105 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
112 reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
114 *speedo_lp = (reg & 0xFFFF) * 4;
115 *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
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);
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;
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;
138 static void rev_sku_to_speedo_ids(int rev, int sku)
141 case TEGRA_REVISION_A01:
142 tegra_cpu_speedo_id = 0;
143 tegra_soc_speedo_id = 0;
144 threshold_index = THRESHOLD_INDEX_0;
146 case TEGRA_REVISION_A02:
147 case TEGRA_REVISION_A03:
151 tegra_cpu_speedo_id = 1;
152 tegra_soc_speedo_id = 1;
153 threshold_index = THRESHOLD_INDEX_1;
156 switch (tegra_package_id) {
158 tegra_cpu_speedo_id = 2;
159 tegra_soc_speedo_id = 2;
160 threshold_index = THRESHOLD_INDEX_2;
163 tegra_cpu_speedo_id = 4;
164 tegra_soc_speedo_id = 1;
165 threshold_index = THRESHOLD_INDEX_7;
168 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
174 switch (tegra_package_id) {
176 tegra_cpu_speedo_id = 5;
177 tegra_soc_speedo_id = 2;
178 threshold_index = THRESHOLD_INDEX_8;
181 tegra_cpu_speedo_id = 6;
182 tegra_soc_speedo_id = 2;
183 threshold_index = THRESHOLD_INDEX_9;
186 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
192 switch (tegra_package_id) {
194 tegra_cpu_speedo_id = 7;
195 tegra_soc_speedo_id = 1;
196 threshold_index = THRESHOLD_INDEX_10;
199 tegra_cpu_speedo_id = 3;
200 tegra_soc_speedo_id = 2;
201 threshold_index = THRESHOLD_INDEX_3;
204 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
210 tegra_cpu_speedo_id = 8;
211 tegra_soc_speedo_id = 1;
212 threshold_index = THRESHOLD_INDEX_11;
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;
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;
228 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
235 tegra_cpu_speedo_id = 1;
236 tegra_soc_speedo_id = 1;
237 threshold_index = THRESHOLD_INDEX_4;
240 tegra_cpu_speedo_id = 2;
241 tegra_soc_speedo_id = 2;
242 threshold_index = THRESHOLD_INDEX_5;
245 tegra_cpu_speedo_id = 3;
246 tegra_soc_speedo_id = 2;
247 threshold_index = THRESHOLD_INDEX_6;
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;
256 case 0x93: /* T30AG-Ax */
257 tegra_cpu_speedo_id = 11;
258 tegra_soc_speedo_id = 3;
259 threshold_index = THRESHOLD_INDEX_13;
262 switch (tegra_package_id) {
264 tegra_cpu_speedo_id = 2;
265 tegra_soc_speedo_id = 2;
266 threshold_index = THRESHOLD_INDEX_2;
269 tegra_cpu_speedo_id = 3;
270 tegra_soc_speedo_id = 2;
271 threshold_index = THRESHOLD_INDEX_3;
274 pr_err("Tegra30: Unknown pkg %d\n", tegra_package_id);
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;
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;
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)
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};
305 void tegra30_init_speedo_data(void)
310 int fuse_sku, new_sku;
312 fuse_sku = tegra_get_sku_id();
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);
320 tegra_package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
322 cpu_iddq_value = tegra_fuse_readl(FUSE_IDDQ_CALIB_0);
323 cpu_iddq_value = ((cpu_iddq_value >> 5) & 0x3ff) * 8;
327 * T33S => T30S, T30SL
332 switch (tegra_sku_override) {
334 /* Base sku override */
335 if (fuse_sku == 0x80) {
336 if (tegra_package_id == 1) {
338 pr_info("%s: SKU OR: T33->T30\n", __func__);
340 } else if (tegra_package_id == 2) {
342 pr_info("%s: SKU OR: T33S->T30S\n", __func__);
345 } else if (fuse_sku == 0x81) {
346 if (tegra_package_id == 2) {
348 pr_info("%s: SKU OR: AP33->AP30\n", __func__);
355 if (fuse_sku == 0x80) {
356 if (tegra_package_id == 1) {
358 pr_info("%s: SKU OR: T33->T30L\n", __func__);
360 } else if (tegra_package_id == 2) {
362 pr_info("%s: SKU OR: T33S->T30SL\n", __func__);
365 } else if (fuse_sku == 0x81) {
366 if (tegra_package_id == 1) {
367 pr_info("%s: SKU OR: T30->T30L\n", __func__);
371 } else if (fuse_sku == 0x83) {
372 if (tegra_package_id == 2) {
373 pr_info("%s: SKU OR: T30S->T30SL\n", __func__);
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);
389 for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
390 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
393 tegra_cpu_process_id = i - 1;
395 if (tegra_cpu_process_id == -1) {
396 pr_warn("Tegra30: CPU speedo value %3d out of range",
398 tegra_cpu_process_id = 0;
399 tegra_cpu_speedo_id = 1;
401 if (threshold_index == 12) {
402 if (tegra_cpu_process_id <= 2) {
406 tegra_cpu_speedo_id = 9;
410 tegra_cpu_speedo_id = 14;
414 } else if (tegra_cpu_process_id >= 3 && tegra_cpu_process_id < 6) {
418 tegra_cpu_speedo_id = 10;
422 tegra_cpu_speedo_id = 15;
430 for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
431 if (core_speedo_val < core_process_speedos[threshold_index][i])
434 tegra_core_process_id = i - 1;
436 if (tegra_core_process_id == -1) {
437 pr_warn("Tegra30: CORE speedo value %3d out of range",
439 tegra_core_process_id = 0;
440 tegra_soc_speedo_id = 1;
443 pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
444 tegra_cpu_speedo_id, tegra_soc_speedo_id);
446 tegra_cpu_speedo_mv =
447 cpu_speedo_nominal_millivolts[tegra_cpu_speedo_id];
449 switch (tegra_soc_speedo_id) {
451 tegra_core_speedo_mv = 1200;
454 if ((tegra_cpu_speedo_id != 7) &&
455 (tegra_cpu_speedo_id != 8)) {
456 tegra_core_speedo_mv = 1200;
459 /* fall thru for T30L or T30SL */
461 if (tegra_cpu_speedo_id != 13)
462 tegra_core_speedo_mv = 1300;
464 tegra_core_speedo_mv = 1350;
467 tegra_core_speedo_mv = 1250;
474 int tegra_get_cpu_iddq_value()
476 return cpu_iddq_value;
479 static int get_enable_app_profiles(char *val, const struct kernel_param *kp)
481 return param_get_uint(val, kp);
484 static struct kernel_param_ops tegra_profiles_ops = {
485 .get = get_enable_app_profiles,
488 module_param_cb(tegra_enable_app_profiles,
489 &tegra_profiles_ops, &enable_app_profiles, 0444);