2 * Copyright (c) 2012, 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>
22 #define CORE_PROCESS_CORNERS_NUM 1
23 #define CPU_PROCESS_CORNERS_NUM 6
25 #define FUSE_SPEEDO_CALIB_0 0x114
26 #define FUSE_PACKAGE_INFO 0X1FC
27 #define FUSE_TEST_PROG_VER 0X128
29 #define G_SPEEDO_BIT_MINUS1 58
30 #define G_SPEEDO_BIT_MINUS1_R 59
31 #define G_SPEEDO_BIT_MINUS2 60
32 #define G_SPEEDO_BIT_MINUS2_R 61
33 #define LP_SPEEDO_BIT_MINUS1 62
34 #define LP_SPEEDO_BIT_MINUS1_R 63
35 #define LP_SPEEDO_BIT_MINUS2 64
36 #define LP_SPEEDO_BIT_MINUS2_R 65
51 THRESHOLD_INDEX_COUNT
,
54 static const u32 core_process_speedos
[][CORE_PROCESS_CORNERS_NUM
] = {
69 static const u32 cpu_process_speedos
[][CPU_PROCESS_CORNERS_NUM
] = {
70 {306, 338, 360, 376, UINT_MAX
},
71 {295, 336, 358, 375, UINT_MAX
},
72 {325, 325, 358, 375, UINT_MAX
},
73 {325, 325, 358, 375, UINT_MAX
},
74 {292, 324, 348, 364, UINT_MAX
},
75 {324, 324, 348, 364, UINT_MAX
},
76 {324, 324, 348, 364, UINT_MAX
},
77 {295, 336, 358, 375, UINT_MAX
},
78 {358, 358, 358, 358, 397, UINT_MAX
},
79 {364, 364, 364, 364, 397, UINT_MAX
},
80 {295, 336, 358, 375, 391, UINT_MAX
},
81 {295, 336, 358, 375, 391, UINT_MAX
},
84 static int threshold_index
;
85 static int package_id
;
87 static void fuse_speedo_calib(u32
*speedo_g
, u32
*speedo_lp
)
94 reg
= tegra_fuse_readl(FUSE_SPEEDO_CALIB_0
);
96 *speedo_lp
= (reg
& 0xFFFF) * 4;
97 *speedo_g
= ((reg
>> 16) & 0xFFFF) * 4;
99 ate_ver
= tegra_fuse_readl(FUSE_TEST_PROG_VER
);
100 pr_info("%s: ATE prog ver %d.%d\n", __func__
, ate_ver
/10, ate_ver
%10);
103 bit_minus1
= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1
);
104 bit_minus1
|= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R
);
105 bit_minus2
= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2
);
106 bit_minus2
|= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R
);
107 *speedo_lp
|= (bit_minus1
<< 1) | bit_minus2
;
109 bit_minus1
= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1
);
110 bit_minus1
|= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R
);
111 bit_minus2
= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2
);
112 bit_minus2
|= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R
);
113 *speedo_g
|= (bit_minus1
<< 1) | bit_minus2
;
120 static void rev_sku_to_speedo_ids(int rev
, int sku
)
123 case TEGRA_REVISION_A01
:
124 tegra_cpu_speedo_id
= 0;
125 tegra_soc_speedo_id
= 0;
126 threshold_index
= THRESHOLD_INDEX_0
;
128 case TEGRA_REVISION_A02
:
129 case TEGRA_REVISION_A03
:
133 tegra_cpu_speedo_id
= 1;
134 tegra_soc_speedo_id
= 1;
135 threshold_index
= THRESHOLD_INDEX_1
;
138 switch (package_id
) {
140 tegra_cpu_speedo_id
= 2;
141 tegra_soc_speedo_id
= 2;
142 threshold_index
= THRESHOLD_INDEX_2
;
145 tegra_cpu_speedo_id
= 4;
146 tegra_soc_speedo_id
= 1;
147 threshold_index
= THRESHOLD_INDEX_7
;
150 pr_err("Tegra30: Unknown pkg %d\n", package_id
);
156 switch (package_id
) {
158 tegra_cpu_speedo_id
= 5;
159 tegra_soc_speedo_id
= 2;
160 threshold_index
= THRESHOLD_INDEX_8
;
163 tegra_cpu_speedo_id
= 6;
164 tegra_soc_speedo_id
= 2;
165 threshold_index
= THRESHOLD_INDEX_9
;
168 pr_err("Tegra30: Unknown pkg %d\n", package_id
);
174 switch (package_id
) {
176 tegra_cpu_speedo_id
= 7;
177 tegra_soc_speedo_id
= 1;
178 threshold_index
= THRESHOLD_INDEX_10
;
181 tegra_cpu_speedo_id
= 3;
182 tegra_soc_speedo_id
= 2;
183 threshold_index
= THRESHOLD_INDEX_3
;
186 pr_err("Tegra30: Unknown pkg %d\n", package_id
);
192 tegra_cpu_speedo_id
= 8;
193 tegra_soc_speedo_id
= 1;
194 threshold_index
= THRESHOLD_INDEX_11
;
197 tegra_cpu_speedo_id
= 1;
198 tegra_soc_speedo_id
= 1;
199 threshold_index
= THRESHOLD_INDEX_4
;
202 tegra_cpu_speedo_id
= 2;
203 tegra_soc_speedo_id
= 2;
204 threshold_index
= THRESHOLD_INDEX_5
;
207 tegra_cpu_speedo_id
= 3;
208 tegra_soc_speedo_id
= 2;
209 threshold_index
= THRESHOLD_INDEX_6
;
212 switch (package_id
) {
214 tegra_cpu_speedo_id
= 2;
215 tegra_soc_speedo_id
= 2;
216 threshold_index
= THRESHOLD_INDEX_2
;
219 tegra_cpu_speedo_id
= 3;
220 tegra_soc_speedo_id
= 2;
221 threshold_index
= THRESHOLD_INDEX_3
;
224 pr_err("Tegra30: Unknown pkg %d\n", package_id
);
230 pr_warn("Tegra30: Unknown SKU %d\n", sku
);
231 tegra_cpu_speedo_id
= 0;
232 tegra_soc_speedo_id
= 0;
233 threshold_index
= THRESHOLD_INDEX_0
;
238 pr_warn("Tegra30: Unknown chip rev %d\n", rev
);
239 tegra_cpu_speedo_id
= 0;
240 tegra_soc_speedo_id
= 0;
241 threshold_index
= THRESHOLD_INDEX_0
;
246 void tegra30_init_speedo_data(void)
252 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos
) !=
253 THRESHOLD_INDEX_COUNT
);
254 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos
) !=
255 THRESHOLD_INDEX_COUNT
);
257 package_id
= tegra_fuse_readl(FUSE_PACKAGE_INFO
) & 0x0F;
259 rev_sku_to_speedo_ids(tegra_revision
, tegra_sku_id
);
260 fuse_speedo_calib(&cpu_speedo_val
, &core_speedo_val
);
261 pr_debug("%s CPU speedo value %u\n", __func__
, cpu_speedo_val
);
262 pr_debug("%s Core speedo value %u\n", __func__
, core_speedo_val
);
264 for (i
= 0; i
< CPU_PROCESS_CORNERS_NUM
; i
++) {
265 if (cpu_speedo_val
< cpu_process_speedos
[threshold_index
][i
])
268 tegra_cpu_process_id
= i
- 1;
270 if (tegra_cpu_process_id
== -1) {
271 pr_warn("Tegra30: CPU speedo value %3d out of range",
273 tegra_cpu_process_id
= 0;
274 tegra_cpu_speedo_id
= 1;
277 for (i
= 0; i
< CORE_PROCESS_CORNERS_NUM
; i
++) {
278 if (core_speedo_val
< core_process_speedos
[threshold_index
][i
])
281 tegra_core_process_id
= i
- 1;
283 if (tegra_core_process_id
== -1) {
284 pr_warn("Tegra30: CORE speedo value %3d out of range",
286 tegra_core_process_id
= 0;
287 tegra_soc_speedo_id
= 1;
290 pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
291 tegra_cpu_speedo_id
, tegra_soc_speedo_id
);