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);