278 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 115#define CPU_PROCESS_CORNERS 616 17#define FUSE_SPEEDO_CALIB_0 0x1418#define FUSE_PACKAGE_INFO 0XFC19#define FUSE_TEST_PROG_VER 0X2820 21#define G_SPEEDO_BIT_MINUS1 5822#define G_SPEEDO_BIT_MINUS1_R 5923#define G_SPEEDO_BIT_MINUS2 6024#define G_SPEEDO_BIT_MINUS2_R 6125#define LP_SPEEDO_BIT_MINUS1 6226#define LP_SPEEDO_BIT_MINUS1_R 6327#define LP_SPEEDO_BIT_MINUS2 6428#define LP_SPEEDO_BIT_MINUS2_R 6529 30enum {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 46static 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 61static 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 76static int threshold_index __initdata;77 78static 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 111static 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 235void __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