• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
3  *
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.
7  *
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
11  * more details.
12  *
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/>.
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/bug.h>
19 
20 #include "fuse.h"
21 
22 #define CORE_PROCESS_CORNERS_NUM	1
23 #define CPU_PROCESS_CORNERS_NUM		6
24 
25 #define FUSE_SPEEDO_CALIB_0	0x114
26 #define FUSE_PACKAGE_INFO	0X1FC
27 #define FUSE_TEST_PROG_VER	0X128
28 
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
37 
38 enum {
39 	THRESHOLD_INDEX_0,
40 	THRESHOLD_INDEX_1,
41 	THRESHOLD_INDEX_2,
42 	THRESHOLD_INDEX_3,
43 	THRESHOLD_INDEX_4,
44 	THRESHOLD_INDEX_5,
45 	THRESHOLD_INDEX_6,
46 	THRESHOLD_INDEX_7,
47 	THRESHOLD_INDEX_8,
48 	THRESHOLD_INDEX_9,
49 	THRESHOLD_INDEX_10,
50 	THRESHOLD_INDEX_11,
51 	THRESHOLD_INDEX_COUNT,
52 };
53 
54 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
55 	{180},
56 	{170},
57 	{195},
58 	{180},
59 	{168},
60 	{192},
61 	{180},
62 	{170},
63 	{195},
64 	{180},
65 	{180},
66 	{180},
67 };
68 
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},
82 };
83 
84 static int threshold_index;
85 static int package_id;
86 
fuse_speedo_calib(u32 * speedo_g,u32 * speedo_lp)87 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
88 {
89 	u32 reg;
90 	int ate_ver;
91 	int bit_minus1;
92 	int bit_minus2;
93 
94 	reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
95 
96 	*speedo_lp = (reg & 0xFFFF) * 4;
97 	*speedo_g = ((reg >> 16) & 0xFFFF) * 4;
98 
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);
101 
102 	if (ate_ver >= 26) {
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;
108 
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;
114 	} else {
115 		*speedo_lp |= 0x3;
116 		*speedo_g |= 0x3;
117 	}
118 }
119 
rev_sku_to_speedo_ids(int rev,int sku)120 static void rev_sku_to_speedo_ids(int rev, int sku)
121 {
122 	switch (rev) {
123 	case TEGRA_REVISION_A01:
124 		tegra_cpu_speedo_id = 0;
125 		tegra_soc_speedo_id = 0;
126 		threshold_index = THRESHOLD_INDEX_0;
127 		break;
128 	case TEGRA_REVISION_A02:
129 	case TEGRA_REVISION_A03:
130 		switch (sku) {
131 		case 0x87:
132 		case 0x82:
133 			tegra_cpu_speedo_id = 1;
134 			tegra_soc_speedo_id = 1;
135 			threshold_index = THRESHOLD_INDEX_1;
136 			break;
137 		case 0x81:
138 			switch (package_id) {
139 			case 1:
140 				tegra_cpu_speedo_id = 2;
141 				tegra_soc_speedo_id = 2;
142 				threshold_index = THRESHOLD_INDEX_2;
143 				break;
144 			case 2:
145 				tegra_cpu_speedo_id = 4;
146 				tegra_soc_speedo_id = 1;
147 				threshold_index = THRESHOLD_INDEX_7;
148 				break;
149 			default:
150 				pr_err("Tegra30: Unknown pkg %d\n", package_id);
151 				BUG();
152 				break;
153 			}
154 			break;
155 		case 0x80:
156 			switch (package_id) {
157 			case 1:
158 				tegra_cpu_speedo_id = 5;
159 				tegra_soc_speedo_id = 2;
160 				threshold_index = THRESHOLD_INDEX_8;
161 				break;
162 			case 2:
163 				tegra_cpu_speedo_id = 6;
164 				tegra_soc_speedo_id = 2;
165 				threshold_index = THRESHOLD_INDEX_9;
166 				break;
167 			default:
168 				pr_err("Tegra30: Unknown pkg %d\n", package_id);
169 				BUG();
170 				break;
171 			}
172 			break;
173 		case 0x83:
174 			switch (package_id) {
175 			case 1:
176 				tegra_cpu_speedo_id = 7;
177 				tegra_soc_speedo_id = 1;
178 				threshold_index = THRESHOLD_INDEX_10;
179 				break;
180 			case 2:
181 				tegra_cpu_speedo_id = 3;
182 				tegra_soc_speedo_id = 2;
183 				threshold_index = THRESHOLD_INDEX_3;
184 				break;
185 			default:
186 				pr_err("Tegra30: Unknown pkg %d\n", package_id);
187 				BUG();
188 				break;
189 			}
190 			break;
191 		case 0x8F:
192 			tegra_cpu_speedo_id = 8;
193 			tegra_soc_speedo_id = 1;
194 			threshold_index = THRESHOLD_INDEX_11;
195 			break;
196 		case 0x08:
197 			tegra_cpu_speedo_id = 1;
198 			tegra_soc_speedo_id = 1;
199 			threshold_index = THRESHOLD_INDEX_4;
200 			break;
201 		case 0x02:
202 			tegra_cpu_speedo_id = 2;
203 			tegra_soc_speedo_id = 2;
204 			threshold_index = THRESHOLD_INDEX_5;
205 			break;
206 		case 0x04:
207 			tegra_cpu_speedo_id = 3;
208 			tegra_soc_speedo_id = 2;
209 			threshold_index = THRESHOLD_INDEX_6;
210 			break;
211 		case 0:
212 			switch (package_id) {
213 			case 1:
214 				tegra_cpu_speedo_id = 2;
215 				tegra_soc_speedo_id = 2;
216 				threshold_index = THRESHOLD_INDEX_2;
217 				break;
218 			case 2:
219 				tegra_cpu_speedo_id = 3;
220 				tegra_soc_speedo_id = 2;
221 				threshold_index = THRESHOLD_INDEX_3;
222 				break;
223 			default:
224 				pr_err("Tegra30: Unknown pkg %d\n", package_id);
225 				BUG();
226 				break;
227 			}
228 			break;
229 		default:
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;
234 			break;
235 		}
236 		break;
237 	default:
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;
242 		break;
243 	}
244 }
245 
tegra30_init_speedo_data(void)246 void tegra30_init_speedo_data(void)
247 {
248 	u32 cpu_speedo_val;
249 	u32 core_speedo_val;
250 	int i;
251 
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);
256 
257 	package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
258 
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);
263 
264 	for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
265 		if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
266 			break;
267 	}
268 	tegra_cpu_process_id = i - 1;
269 
270 	if (tegra_cpu_process_id == -1) {
271 		pr_warn("Tegra30: CPU speedo value %3d out of range",
272 		       cpu_speedo_val);
273 		tegra_cpu_process_id = 0;
274 		tegra_cpu_speedo_id = 1;
275 	}
276 
277 	for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
278 		if (core_speedo_val < core_process_speedos[threshold_index][i])
279 			break;
280 	}
281 	tegra_core_process_id = i - 1;
282 
283 	if (tegra_core_process_id == -1) {
284 		pr_warn("Tegra30: CORE speedo value %3d out of range",
285 		       core_speedo_val);
286 		tegra_core_process_id = 0;
287 		tegra_soc_speedo_id = 1;
288 	}
289 
290 	pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
291 		tegra_cpu_speedo_id, tegra_soc_speedo_id);
292 }
293