xref: /linux/drivers/soc/tegra/fuse/speedo-tegra30.c (revision 702648721db590b3425c31ade294000e18808345)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/bug.h>
7 #include <linux/device.h>
8 #include <linux/kernel.h>
9 
10 #include <soc/tegra/fuse.h>
11 
12 #include "fuse.h"
13 
14 #define SOC_PROCESS_CORNERS	1
15 #define CPU_PROCESS_CORNERS	6
16 
17 #define FUSE_SPEEDO_CALIB_0	0x14
18 #define FUSE_PACKAGE_INFO	0XFC
19 #define FUSE_TEST_PROG_VER	0X28
20 
21 #define G_SPEEDO_BIT_MINUS1	58
22 #define G_SPEEDO_BIT_MINUS1_R	59
23 #define G_SPEEDO_BIT_MINUS2	60
24 #define G_SPEEDO_BIT_MINUS2_R	61
25 #define LP_SPEEDO_BIT_MINUS1	62
26 #define LP_SPEEDO_BIT_MINUS1_R	63
27 #define LP_SPEEDO_BIT_MINUS2	64
28 #define LP_SPEEDO_BIT_MINUS2_R	65
29 
30 enum {
31 	THRESHOLD_INDEX_0,
32 	THRESHOLD_INDEX_1,
33 	THRESHOLD_INDEX_2,
34 	THRESHOLD_INDEX_3,
35 	THRESHOLD_INDEX_4,
36 	THRESHOLD_INDEX_5,
37 	THRESHOLD_INDEX_6,
38 	THRESHOLD_INDEX_7,
39 	THRESHOLD_INDEX_8,
40 	THRESHOLD_INDEX_9,
41 	THRESHOLD_INDEX_10,
42 	THRESHOLD_INDEX_11,
43 	THRESHOLD_INDEX_COUNT,
44 };
45 
46 static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
47 	{180},
48 	{170},
49 	{195},
50 	{180},
51 	{168},
52 	{192},
53 	{180},
54 	{170},
55 	{195},
56 	{180},
57 	{180},
58 	{180},
59 };
60 
61 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
62 	{306, 338, 360, 376, UINT_MAX},
63 	{295, 336, 358, 375, UINT_MAX},
64 	{325, 325, 358, 375, UINT_MAX},
65 	{325, 325, 358, 375, UINT_MAX},
66 	{292, 324, 348, 364, UINT_MAX},
67 	{324, 324, 348, 364, UINT_MAX},
68 	{324, 324, 348, 364, UINT_MAX},
69 	{295, 336, 358, 375, UINT_MAX},
70 	{358, 358, 358, 358, 397, UINT_MAX},
71 	{364, 364, 364, 364, 397, UINT_MAX},
72 	{295, 336, 358, 375, 391, UINT_MAX},
73 	{295, 336, 358, 375, 391, UINT_MAX},
74 };
75 
76 static int threshold_index __initdata;
77 
78 static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
79 {
80 	u32 reg;
81 	int ate_ver;
82 	int bit_minus1;
83 	int bit_minus2;
84 
85 	reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
86 
87 	*speedo_lp = (reg & 0xFFFF) * 4;
88 	*speedo_g = ((reg >> 16) & 0xFFFF) * 4;
89 
90 	ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
91 	pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
92 
93 	if (ate_ver >= 26) {
94 		bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
95 		bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
96 		bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
97 		bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
98 		*speedo_lp |= (bit_minus1 << 1) | bit_minus2;
99 
100 		bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
101 		bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
102 		bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
103 		bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
104 		*speedo_g |= (bit_minus1 << 1) | bit_minus2;
105 	} else {
106 		*speedo_lp |= 0x3;
107 		*speedo_g |= 0x3;
108 	}
109 }
110 
111 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
112 {
113 	int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
114 
115 	switch (sku_info->revision) {
116 	case TEGRA_REVISION_A01:
117 		sku_info->cpu_speedo_id = 0;
118 		sku_info->soc_speedo_id = 0;
119 		threshold_index = THRESHOLD_INDEX_0;
120 		break;
121 	case TEGRA_REVISION_A02:
122 	case TEGRA_REVISION_A03:
123 		switch (sku_info->sku_id) {
124 		case 0x87:
125 		case 0x82:
126 			sku_info->cpu_speedo_id = 1;
127 			sku_info->soc_speedo_id = 1;
128 			threshold_index = THRESHOLD_INDEX_1;
129 			break;
130 		case 0x81:
131 			switch (package_id) {
132 			case 1:
133 				sku_info->cpu_speedo_id = 2;
134 				sku_info->soc_speedo_id = 2;
135 				threshold_index = THRESHOLD_INDEX_2;
136 				break;
137 			case 2:
138 				sku_info->cpu_speedo_id = 4;
139 				sku_info->soc_speedo_id = 1;
140 				threshold_index = THRESHOLD_INDEX_7;
141 				break;
142 			default:
143 				pr_err("Tegra Unknown pkg %d\n", package_id);
144 				break;
145 			}
146 			break;
147 		case 0x80:
148 			switch (package_id) {
149 			case 1:
150 				sku_info->cpu_speedo_id = 5;
151 				sku_info->soc_speedo_id = 2;
152 				threshold_index = THRESHOLD_INDEX_8;
153 				break;
154 			case 2:
155 				sku_info->cpu_speedo_id = 6;
156 				sku_info->soc_speedo_id = 2;
157 				threshold_index = THRESHOLD_INDEX_9;
158 				break;
159 			default:
160 				pr_err("Tegra Unknown pkg %d\n", package_id);
161 				break;
162 			}
163 			break;
164 		case 0x83:
165 			switch (package_id) {
166 			case 1:
167 				sku_info->cpu_speedo_id = 7;
168 				sku_info->soc_speedo_id = 1;
169 				threshold_index = THRESHOLD_INDEX_10;
170 				break;
171 			case 2:
172 				sku_info->cpu_speedo_id = 3;
173 				sku_info->soc_speedo_id = 2;
174 				threshold_index = THRESHOLD_INDEX_3;
175 				break;
176 			default:
177 				pr_err("Tegra Unknown pkg %d\n", package_id);
178 				break;
179 			}
180 			break;
181 		case 0x8F:
182 			sku_info->cpu_speedo_id = 8;
183 			sku_info->soc_speedo_id = 1;
184 			threshold_index = THRESHOLD_INDEX_11;
185 			break;
186 		case 0x08:
187 			sku_info->cpu_speedo_id = 1;
188 			sku_info->soc_speedo_id = 1;
189 			threshold_index = THRESHOLD_INDEX_4;
190 			break;
191 		case 0x02:
192 			sku_info->cpu_speedo_id = 2;
193 			sku_info->soc_speedo_id = 2;
194 			threshold_index = THRESHOLD_INDEX_5;
195 			break;
196 		case 0x04:
197 			sku_info->cpu_speedo_id = 3;
198 			sku_info->soc_speedo_id = 2;
199 			threshold_index = THRESHOLD_INDEX_6;
200 			break;
201 		case 0:
202 			switch (package_id) {
203 			case 1:
204 				sku_info->cpu_speedo_id = 2;
205 				sku_info->soc_speedo_id = 2;
206 				threshold_index = THRESHOLD_INDEX_2;
207 				break;
208 			case 2:
209 				sku_info->cpu_speedo_id = 3;
210 				sku_info->soc_speedo_id = 2;
211 				threshold_index = THRESHOLD_INDEX_3;
212 				break;
213 			default:
214 				pr_err("Tegra Unknown pkg %d\n", package_id);
215 				break;
216 			}
217 			break;
218 		default:
219 			pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
220 			sku_info->cpu_speedo_id = 0;
221 			sku_info->soc_speedo_id = 0;
222 			threshold_index = THRESHOLD_INDEX_0;
223 			break;
224 		}
225 		break;
226 	default:
227 		pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
228 		sku_info->cpu_speedo_id = 0;
229 		sku_info->soc_speedo_id = 0;
230 		threshold_index = THRESHOLD_INDEX_0;
231 		break;
232 	}
233 }
234 
235 void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
236 {
237 	u32 cpu_speedo_val;
238 	u32 soc_speedo_val;
239 	int i;
240 
241 	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
242 			THRESHOLD_INDEX_COUNT);
243 	BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
244 			THRESHOLD_INDEX_COUNT);
245 
246 
247 	rev_sku_to_speedo_ids(sku_info);
248 	fuse_speedo_calib(&cpu_speedo_val, &soc_speedo_val);
249 	pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
250 	pr_debug("Tegra Core speedo value %u\n", soc_speedo_val);
251 
252 	for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
253 		if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
254 			break;
255 	}
256 	sku_info->cpu_process_id = i - 1;
257 
258 	if (sku_info->cpu_process_id == -1) {
259 		pr_warn("Tegra CPU speedo value %3d out of range",
260 			 cpu_speedo_val);
261 		sku_info->cpu_process_id = 0;
262 		sku_info->cpu_speedo_id = 1;
263 	}
264 
265 	for (i = 0; i < SOC_PROCESS_CORNERS; i++) {
266 		if (soc_speedo_val < soc_process_speedos[threshold_index][i])
267 			break;
268 	}
269 	sku_info->soc_process_id = i - 1;
270 
271 	if (sku_info->soc_process_id == -1) {
272 		pr_warn("Tegra SoC speedo value %3d out of range",
273 			soc_speedo_val);
274 		sku_info->soc_process_id = 0;
275 		sku_info->soc_speedo_id = 1;
276 	}
277 }
278