19952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2783c8f4cSPeter De Schrijver /*
3783c8f4cSPeter De Schrijver * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
4783c8f4cSPeter De Schrijver */
5783c8f4cSPeter De Schrijver
6783c8f4cSPeter De Schrijver #include <linux/bug.h>
7783c8f4cSPeter De Schrijver #include <linux/device.h>
8783c8f4cSPeter De Schrijver #include <linux/kernel.h>
9783c8f4cSPeter De Schrijver
10783c8f4cSPeter De Schrijver #include <soc/tegra/fuse.h>
11783c8f4cSPeter De Schrijver
12783c8f4cSPeter De Schrijver #include "fuse.h"
13783c8f4cSPeter De Schrijver
1403b3f4c8SThierry Reding #define SOC_PROCESS_CORNERS 1
15783c8f4cSPeter De Schrijver #define CPU_PROCESS_CORNERS 6
16783c8f4cSPeter De Schrijver
17783c8f4cSPeter De Schrijver #define FUSE_SPEEDO_CALIB_0 0x14
18783c8f4cSPeter De Schrijver #define FUSE_PACKAGE_INFO 0XFC
19783c8f4cSPeter De Schrijver #define FUSE_TEST_PROG_VER 0X28
20783c8f4cSPeter De Schrijver
21783c8f4cSPeter De Schrijver #define G_SPEEDO_BIT_MINUS1 58
22783c8f4cSPeter De Schrijver #define G_SPEEDO_BIT_MINUS1_R 59
23783c8f4cSPeter De Schrijver #define G_SPEEDO_BIT_MINUS2 60
24783c8f4cSPeter De Schrijver #define G_SPEEDO_BIT_MINUS2_R 61
25783c8f4cSPeter De Schrijver #define LP_SPEEDO_BIT_MINUS1 62
26783c8f4cSPeter De Schrijver #define LP_SPEEDO_BIT_MINUS1_R 63
27783c8f4cSPeter De Schrijver #define LP_SPEEDO_BIT_MINUS2 64
28783c8f4cSPeter De Schrijver #define LP_SPEEDO_BIT_MINUS2_R 65
29783c8f4cSPeter De Schrijver
30783c8f4cSPeter De Schrijver enum {
31783c8f4cSPeter De Schrijver THRESHOLD_INDEX_0,
32783c8f4cSPeter De Schrijver THRESHOLD_INDEX_1,
33783c8f4cSPeter De Schrijver THRESHOLD_INDEX_2,
34783c8f4cSPeter De Schrijver THRESHOLD_INDEX_3,
35783c8f4cSPeter De Schrijver THRESHOLD_INDEX_4,
36783c8f4cSPeter De Schrijver THRESHOLD_INDEX_5,
37783c8f4cSPeter De Schrijver THRESHOLD_INDEX_6,
38783c8f4cSPeter De Schrijver THRESHOLD_INDEX_7,
39783c8f4cSPeter De Schrijver THRESHOLD_INDEX_8,
40783c8f4cSPeter De Schrijver THRESHOLD_INDEX_9,
41783c8f4cSPeter De Schrijver THRESHOLD_INDEX_10,
42783c8f4cSPeter De Schrijver THRESHOLD_INDEX_11,
43783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT,
44783c8f4cSPeter De Schrijver };
45783c8f4cSPeter De Schrijver
4603b3f4c8SThierry Reding static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
47783c8f4cSPeter De Schrijver {180},
48783c8f4cSPeter De Schrijver {170},
49783c8f4cSPeter De Schrijver {195},
50783c8f4cSPeter De Schrijver {180},
51783c8f4cSPeter De Schrijver {168},
52783c8f4cSPeter De Schrijver {192},
53783c8f4cSPeter De Schrijver {180},
54783c8f4cSPeter De Schrijver {170},
55783c8f4cSPeter De Schrijver {195},
56783c8f4cSPeter De Schrijver {180},
57783c8f4cSPeter De Schrijver {180},
58783c8f4cSPeter De Schrijver {180},
59783c8f4cSPeter De Schrijver };
60783c8f4cSPeter De Schrijver
61783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
62783c8f4cSPeter De Schrijver {306, 338, 360, 376, UINT_MAX},
63783c8f4cSPeter De Schrijver {295, 336, 358, 375, UINT_MAX},
64783c8f4cSPeter De Schrijver {325, 325, 358, 375, UINT_MAX},
65783c8f4cSPeter De Schrijver {325, 325, 358, 375, UINT_MAX},
66783c8f4cSPeter De Schrijver {292, 324, 348, 364, UINT_MAX},
67783c8f4cSPeter De Schrijver {324, 324, 348, 364, UINT_MAX},
68783c8f4cSPeter De Schrijver {324, 324, 348, 364, UINT_MAX},
69783c8f4cSPeter De Schrijver {295, 336, 358, 375, UINT_MAX},
70783c8f4cSPeter De Schrijver {358, 358, 358, 358, 397, UINT_MAX},
71783c8f4cSPeter De Schrijver {364, 364, 364, 364, 397, UINT_MAX},
72783c8f4cSPeter De Schrijver {295, 336, 358, 375, 391, UINT_MAX},
73783c8f4cSPeter De Schrijver {295, 336, 358, 375, 391, UINT_MAX},
74783c8f4cSPeter De Schrijver };
75783c8f4cSPeter De Schrijver
76783c8f4cSPeter De Schrijver static int threshold_index __initdata;
77783c8f4cSPeter De Schrijver
fuse_speedo_calib(u32 * speedo_g,u32 * speedo_lp)78783c8f4cSPeter De Schrijver static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
79783c8f4cSPeter De Schrijver {
80783c8f4cSPeter De Schrijver u32 reg;
81783c8f4cSPeter De Schrijver int ate_ver;
82783c8f4cSPeter De Schrijver int bit_minus1;
83783c8f4cSPeter De Schrijver int bit_minus2;
84783c8f4cSPeter De Schrijver
857e939de1SThierry Reding reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
86783c8f4cSPeter De Schrijver
87783c8f4cSPeter De Schrijver *speedo_lp = (reg & 0xFFFF) * 4;
88783c8f4cSPeter De Schrijver *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
89783c8f4cSPeter De Schrijver
907e939de1SThierry Reding ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
91783c8f4cSPeter De Schrijver pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
92783c8f4cSPeter De Schrijver
93783c8f4cSPeter De Schrijver if (ate_ver >= 26) {
947e939de1SThierry Reding bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
957e939de1SThierry Reding bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
967e939de1SThierry Reding bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
977e939de1SThierry Reding bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
98783c8f4cSPeter De Schrijver *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
99783c8f4cSPeter De Schrijver
1007e939de1SThierry Reding bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
1017e939de1SThierry Reding bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
1027e939de1SThierry Reding bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
1037e939de1SThierry Reding bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
104783c8f4cSPeter De Schrijver *speedo_g |= (bit_minus1 << 1) | bit_minus2;
105783c8f4cSPeter De Schrijver } else {
106783c8f4cSPeter De Schrijver *speedo_lp |= 0x3;
107783c8f4cSPeter De Schrijver *speedo_g |= 0x3;
108783c8f4cSPeter De Schrijver }
109783c8f4cSPeter De Schrijver }
110783c8f4cSPeter De Schrijver
rev_sku_to_speedo_ids(struct tegra_sku_info * sku_info)111783c8f4cSPeter De Schrijver static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
112783c8f4cSPeter De Schrijver {
1137e939de1SThierry Reding int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
114783c8f4cSPeter De Schrijver
115783c8f4cSPeter De Schrijver switch (sku_info->revision) {
116783c8f4cSPeter De Schrijver case TEGRA_REVISION_A01:
117783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0;
118783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0;
119783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_0;
120783c8f4cSPeter De Schrijver break;
121783c8f4cSPeter De Schrijver case TEGRA_REVISION_A02:
122783c8f4cSPeter De Schrijver case TEGRA_REVISION_A03:
123783c8f4cSPeter De Schrijver switch (sku_info->sku_id) {
124783c8f4cSPeter De Schrijver case 0x87:
125783c8f4cSPeter De Schrijver case 0x82:
126783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 1;
127783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
128783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_1;
129783c8f4cSPeter De Schrijver break;
130783c8f4cSPeter De Schrijver case 0x81:
131783c8f4cSPeter De Schrijver switch (package_id) {
132783c8f4cSPeter De Schrijver case 1:
133783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 2;
134783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
135783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_2;
136783c8f4cSPeter De Schrijver break;
137783c8f4cSPeter De Schrijver case 2:
138783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 4;
139783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
140783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_7;
141783c8f4cSPeter De Schrijver break;
142783c8f4cSPeter De Schrijver default:
143783c8f4cSPeter De Schrijver pr_err("Tegra Unknown pkg %d\n", package_id);
144783c8f4cSPeter De Schrijver break;
145783c8f4cSPeter De Schrijver }
146783c8f4cSPeter De Schrijver break;
147783c8f4cSPeter De Schrijver case 0x80:
148783c8f4cSPeter De Schrijver switch (package_id) {
149783c8f4cSPeter De Schrijver case 1:
150783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 5;
151783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
152783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_8;
153783c8f4cSPeter De Schrijver break;
154783c8f4cSPeter De Schrijver case 2:
155783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 6;
156783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
157783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_9;
158783c8f4cSPeter De Schrijver break;
159783c8f4cSPeter De Schrijver default:
160783c8f4cSPeter De Schrijver pr_err("Tegra Unknown pkg %d\n", package_id);
161783c8f4cSPeter De Schrijver break;
162783c8f4cSPeter De Schrijver }
163783c8f4cSPeter De Schrijver break;
164783c8f4cSPeter De Schrijver case 0x83:
165783c8f4cSPeter De Schrijver switch (package_id) {
166783c8f4cSPeter De Schrijver case 1:
167783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 7;
168783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
169783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_10;
170783c8f4cSPeter De Schrijver break;
171783c8f4cSPeter De Schrijver case 2:
172783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 3;
173783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
174783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_3;
175783c8f4cSPeter De Schrijver break;
176783c8f4cSPeter De Schrijver default:
177783c8f4cSPeter De Schrijver pr_err("Tegra Unknown pkg %d\n", package_id);
178783c8f4cSPeter De Schrijver break;
179783c8f4cSPeter De Schrijver }
180783c8f4cSPeter De Schrijver break;
181783c8f4cSPeter De Schrijver case 0x8F:
182783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 8;
183783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
184783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_11;
185783c8f4cSPeter De Schrijver break;
186783c8f4cSPeter De Schrijver case 0x08:
187783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 1;
188783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
189783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_4;
190783c8f4cSPeter De Schrijver break;
191783c8f4cSPeter De Schrijver case 0x02:
192783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 2;
193783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
194783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_5;
195783c8f4cSPeter De Schrijver break;
196783c8f4cSPeter De Schrijver case 0x04:
197783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 3;
198783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
199783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_6;
200783c8f4cSPeter De Schrijver break;
201783c8f4cSPeter De Schrijver case 0:
202783c8f4cSPeter De Schrijver switch (package_id) {
203783c8f4cSPeter De Schrijver case 1:
204783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 2;
205783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
206783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_2;
207783c8f4cSPeter De Schrijver break;
208783c8f4cSPeter De Schrijver case 2:
209783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 3;
210783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 2;
211783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_3;
212783c8f4cSPeter De Schrijver break;
213783c8f4cSPeter De Schrijver default:
214783c8f4cSPeter De Schrijver pr_err("Tegra Unknown pkg %d\n", package_id);
215783c8f4cSPeter De Schrijver break;
216783c8f4cSPeter De Schrijver }
217783c8f4cSPeter De Schrijver break;
218783c8f4cSPeter De Schrijver default:
219783c8f4cSPeter De Schrijver pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
220783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0;
221783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0;
222783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_0;
223783c8f4cSPeter De Schrijver break;
224783c8f4cSPeter De Schrijver }
225783c8f4cSPeter De Schrijver break;
226783c8f4cSPeter De Schrijver default:
227783c8f4cSPeter De Schrijver pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
228783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0;
229783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0;
230783c8f4cSPeter De Schrijver threshold_index = THRESHOLD_INDEX_0;
231783c8f4cSPeter De Schrijver break;
232783c8f4cSPeter De Schrijver }
233783c8f4cSPeter De Schrijver }
234783c8f4cSPeter De Schrijver
tegra30_init_speedo_data(struct tegra_sku_info * sku_info)235783c8f4cSPeter De Schrijver void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
236783c8f4cSPeter De Schrijver {
237783c8f4cSPeter De Schrijver u32 cpu_speedo_val;
23803b3f4c8SThierry Reding u32 soc_speedo_val;
239783c8f4cSPeter De Schrijver int i;
240783c8f4cSPeter De Schrijver
241783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
242783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT);
24303b3f4c8SThierry Reding BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
244783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT);
245783c8f4cSPeter De Schrijver
246783c8f4cSPeter De Schrijver
247783c8f4cSPeter De Schrijver rev_sku_to_speedo_ids(sku_info);
24803b3f4c8SThierry Reding fuse_speedo_calib(&cpu_speedo_val, &soc_speedo_val);
249783c8f4cSPeter De Schrijver pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
25003b3f4c8SThierry Reding pr_debug("Tegra Core speedo value %u\n", soc_speedo_val);
251783c8f4cSPeter De Schrijver
252783c8f4cSPeter De Schrijver for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
253783c8f4cSPeter De Schrijver if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
254783c8f4cSPeter De Schrijver break;
255783c8f4cSPeter De Schrijver }
256783c8f4cSPeter De Schrijver sku_info->cpu_process_id = i - 1;
257783c8f4cSPeter De Schrijver
258783c8f4cSPeter De Schrijver if (sku_info->cpu_process_id == -1) {
259783c8f4cSPeter De Schrijver pr_warn("Tegra CPU speedo value %3d out of range",
260783c8f4cSPeter De Schrijver cpu_speedo_val);
261783c8f4cSPeter De Schrijver sku_info->cpu_process_id = 0;
262783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 1;
263783c8f4cSPeter De Schrijver }
264783c8f4cSPeter De Schrijver
26503b3f4c8SThierry Reding for (i = 0; i < SOC_PROCESS_CORNERS; i++) {
26603b3f4c8SThierry Reding if (soc_speedo_val < soc_process_speedos[threshold_index][i])
267783c8f4cSPeter De Schrijver break;
268783c8f4cSPeter De Schrijver }
26903b3f4c8SThierry Reding sku_info->soc_process_id = i - 1;
270783c8f4cSPeter De Schrijver
27103b3f4c8SThierry Reding if (sku_info->soc_process_id == -1) {
27203b3f4c8SThierry Reding pr_warn("Tegra SoC speedo value %3d out of range",
27303b3f4c8SThierry Reding soc_speedo_val);
27403b3f4c8SThierry Reding sku_info->soc_process_id = 0;
275783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1;
276783c8f4cSPeter De Schrijver }
277783c8f4cSPeter De Schrijver }
278