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