1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved.
7 #include <linux/device.h>
8 #include <linux/kernel.h>
10 #include <soc/tegra/fuse.h>
14 #define SOC_PROCESS_CORNERS 1
15 #define CPU_PROCESS_CORNERS 6
17 #define FUSE_SPEEDO_CALIB_0 0x14
18 #define FUSE_PACKAGE_INFO 0XFC
19 #define FUSE_TEST_PROG_VER 0X28
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
43 THRESHOLD_INDEX_COUNT
,
46 static const u32 __initconst soc_process_speedos
[][SOC_PROCESS_CORNERS
] = {
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
},
76 static int threshold_index __initdata
;
78 static void __init
fuse_speedo_calib(u32
*speedo_g
, u32
*speedo_lp
)
85 reg
= tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0
);
87 *speedo_lp
= (reg
& 0xFFFF) * 4;
88 *speedo_g
= ((reg
>> 16) & 0xFFFF) * 4;
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);
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
;
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
;
111 static void __init
rev_sku_to_speedo_ids(struct tegra_sku_info
*sku_info
)
113 int package_id
= tegra_fuse_read_early(FUSE_PACKAGE_INFO
) & 0x0F;
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
;
121 case TEGRA_REVISION_A02
:
122 case TEGRA_REVISION_A03
:
123 switch (sku_info
->sku_id
) {
126 sku_info
->cpu_speedo_id
= 1;
127 sku_info
->soc_speedo_id
= 1;
128 threshold_index
= THRESHOLD_INDEX_1
;
131 switch (package_id
) {
133 sku_info
->cpu_speedo_id
= 2;
134 sku_info
->soc_speedo_id
= 2;
135 threshold_index
= THRESHOLD_INDEX_2
;
138 sku_info
->cpu_speedo_id
= 4;
139 sku_info
->soc_speedo_id
= 1;
140 threshold_index
= THRESHOLD_INDEX_7
;
143 pr_err("Tegra Unknown pkg %d\n", package_id
);
148 switch (package_id
) {
150 sku_info
->cpu_speedo_id
= 5;
151 sku_info
->soc_speedo_id
= 2;
152 threshold_index
= THRESHOLD_INDEX_8
;
155 sku_info
->cpu_speedo_id
= 6;
156 sku_info
->soc_speedo_id
= 2;
157 threshold_index
= THRESHOLD_INDEX_9
;
160 pr_err("Tegra Unknown pkg %d\n", package_id
);
165 switch (package_id
) {
167 sku_info
->cpu_speedo_id
= 7;
168 sku_info
->soc_speedo_id
= 1;
169 threshold_index
= THRESHOLD_INDEX_10
;
172 sku_info
->cpu_speedo_id
= 3;
173 sku_info
->soc_speedo_id
= 2;
174 threshold_index
= THRESHOLD_INDEX_3
;
177 pr_err("Tegra Unknown pkg %d\n", package_id
);
182 sku_info
->cpu_speedo_id
= 8;
183 sku_info
->soc_speedo_id
= 1;
184 threshold_index
= THRESHOLD_INDEX_11
;
187 sku_info
->cpu_speedo_id
= 1;
188 sku_info
->soc_speedo_id
= 1;
189 threshold_index
= THRESHOLD_INDEX_4
;
192 sku_info
->cpu_speedo_id
= 2;
193 sku_info
->soc_speedo_id
= 2;
194 threshold_index
= THRESHOLD_INDEX_5
;
197 sku_info
->cpu_speedo_id
= 3;
198 sku_info
->soc_speedo_id
= 2;
199 threshold_index
= THRESHOLD_INDEX_6
;
202 switch (package_id
) {
204 sku_info
->cpu_speedo_id
= 2;
205 sku_info
->soc_speedo_id
= 2;
206 threshold_index
= THRESHOLD_INDEX_2
;
209 sku_info
->cpu_speedo_id
= 3;
210 sku_info
->soc_speedo_id
= 2;
211 threshold_index
= THRESHOLD_INDEX_3
;
214 pr_err("Tegra Unknown pkg %d\n", package_id
);
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
;
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
;
235 void __init
tegra30_init_speedo_data(struct tegra_sku_info
*sku_info
)
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
);
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
);
252 for (i
= 0; i
< CPU_PROCESS_CORNERS
; i
++) {
253 if (cpu_speedo_val
< cpu_process_speedos
[threshold_index
][i
])
256 sku_info
->cpu_process_id
= i
- 1;
258 if (sku_info
->cpu_process_id
== -1) {
259 pr_warn("Tegra CPU speedo value %3d out of range",
261 sku_info
->cpu_process_id
= 0;
262 sku_info
->cpu_speedo_id
= 1;
265 for (i
= 0; i
< SOC_PROCESS_CORNERS
; i
++) {
266 if (soc_speedo_val
< soc_process_speedos
[threshold_index
][i
])
269 sku_info
->soc_process_id
= i
- 1;
271 if (sku_info
->soc_process_id
== -1) {
272 pr_warn("Tegra SoC speedo value %3d out of range",
274 sku_info
->soc_process_id
= 0;
275 sku_info
->soc_speedo_id
= 1;