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;