2 * arch/arm/mach-tegra/tegra21_speedo.c
4 * Copyright (C) 2013-2015 NVIDIA Corporation. All rights reserved.
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.
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
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.
21 #include <linux/kernel.h>
23 #include <linux/err.h>
24 #include <linux/bug.h> /* For BUG_ON. */
26 #include <linux/tegra-fuse.h>
27 #include <linux/tegra-soc.h>
28 #include <linux/module.h>
29 #include <linux/moduleparam.h>
32 #include <linux/platform/tegra/common.h>
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
40 #define CPU_PROCESS_CORNERS_NUM 3
41 #define GPU_PROCESS_CORNERS_NUM 2
42 #define CORE_PROCESS_CORNERS_NUM 3
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
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;
64 static int core_min_mv;
66 static int cpu_iddq_value;
67 static int gpu_iddq_value;
68 static int soc_iddq_value;
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;
77 static int cpu_speedo_value;
78 static int gpu_speedo_value;
79 static int soc_speedo_value;
81 static int speedo_rev;
83 static int enable_app_profiles;
85 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
87 {2119, UINT_MAX, UINT_MAX}, /* [0]: threshold_index 0 */
88 {2119, UINT_MAX, UINT_MAX}, /* [1]: threshold_index 1 */
91 static const u32 gpu_process_speedos[][GPU_PROCESS_CORNERS_NUM] = {
93 {UINT_MAX, UINT_MAX}, /* [0]: threshold_index 0 */
94 {UINT_MAX, UINT_MAX}, /* [1]: threshold_index 1 */
97 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
99 {1950, 2073, UINT_MAX}, /* [0]: threshold_index 0 */
100 {UINT_MAX, UINT_MAX, UINT_MAX}, /* [1]: threshold_index 1 */
103 static void rev_sku_to_speedo_ids(int rev, int sku, int speedo_rev)
105 bool shield_sku = false;
106 bool vcm31_sku = false;
107 bool a02 = rev == TEGRA_REVISION_A02;
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");
117 if (a02 && !shield_sku) {
125 /* fall thru for a01 or shild sku */
126 case 0x00: /* Engg sku */
127 case 0x01: /* Engg sku */
130 if (!vcm31_sku || (sku != 0x17)) {
131 if (a02 && !shield_sku) {
138 cpu_speedo_id = shield_sku ? 2 : 0;
146 /* fall thru for vcm31_sku 0x17 */
163 /* fall thru for a01 part and Darcy*/
173 /* fall thru for a01 part */
183 /* fall thru for a01 part */
185 pr_warn("Tegra21: Unknown SKU %d\n", sku);
194 /* Overwrite GPU speedo selection for speedo revision 0, 1 */
199 static int get_speedo_rev(void)
201 return (tegra_spare_fuse(4) << 2) |
202 (tegra_spare_fuse(3) << 1) |
203 (tegra_spare_fuse(2) << 0);
206 void tegra_init_speedo_data(void)
211 if (!tegra_platform_is_silicon()) {
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;
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);
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);
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);
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;
252 * Determine CPU, GPU, SOC speedo values depending on speedo fusing
253 * revision. Note that GPU speedo value is fused in CPU_SPEEDO_2
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;
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;
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");
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");
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");
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);
293 for (i = 0; i < GPU_PROCESS_CORNERS_NUM; i++) {
294 if (gpu_speedo_value <
295 gpu_process_speedos[threshold_index][i]) {
301 for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
302 if (cpu_speedo_value <
303 cpu_process_speedos[threshold_index][i]) {
309 for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
310 if (soc_speedo_value <
311 core_process_speedos[threshold_index][i]) {
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);
328 int tegra_cpu_process_id(void)
330 return cpu_process_id;
333 int tegra_core_process_id(void)
335 return core_process_id;
338 int tegra_gpu_process_id(void)
340 return gpu_process_id;
343 int tegra_cpu_speedo_id(void)
345 return cpu_speedo_id;
348 int tegra_soc_speedo_id(void)
350 return soc_speedo_id;
353 int tegra_gpu_speedo_id(void)
355 return gpu_speedo_id;
358 int tegra_package_id(void)
363 int tegra_cpu_speedo_value(void)
365 return cpu_speedo_value;
368 int tegra_cpu_speedo_0_value(void)
370 return cpu_speedo_0_value;
373 int tegra_cpu_speedo_1_value(void)
375 return cpu_speedo_1_value;
378 int tegra_gpu_speedo_value(void)
380 return gpu_speedo_value;
383 int tegra_soc_speedo_0_value(void)
385 return soc_speedo_value;
387 EXPORT_SYMBOL(tegra_soc_speedo_0_value);
389 int tegra_soc_speedo_1_value(void)
391 return soc_speedo_1_value;
394 int tegra_soc_speedo_2_value(void)
396 return soc_speedo_2_value;
400 * Core nominal and minimum voltage levels as determined by chip SKU and speedo
401 * (not final - will be clipped to dvfs tables).
403 int tegra_cpu_speedo_mv(void)
405 /* Not applicable on Tegra21 */
409 int tegra_core_speedo_mv(void)
411 switch (core_process_id) {
413 if (soc_speedo_id == 1)
427 int tegra_core_speedo_min_mv(void)
432 int tegra_get_cpu_iddq_value(void)
434 return cpu_iddq_value;
437 int tegra_get_soc_iddq_value(void)
439 return soc_iddq_value;
442 int tegra_get_gpu_iddq_value(void)
444 return gpu_iddq_value;
447 static int get_enable_app_profiles(char *val, const struct kernel_param *kp)
449 return param_get_uint(val, kp);
452 static struct kernel_param_ops tegra_profiles_ops = {
453 .get = get_enable_app_profiles,
456 module_param_cb(tegra_enable_app_profiles,
457 &tegra_profiles_ops, &enable_app_profiles, 0444);