1 /* 2 * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <linux/bug.h> 18 #include <linux/device.h> 19 #include <linux/kernel.h> 20 21 #include <soc/tegra/fuse.h> 22 23 #include "fuse.h" 24 25 #define CORE_PROCESS_CORNERS 1 26 #define CPU_PROCESS_CORNERS 6 27 28 #define FUSE_SPEEDO_CALIB_0 0x14 29 #define FUSE_PACKAGE_INFO 0XFC 30 #define FUSE_TEST_PROG_VER 0X28 31 32 #define G_SPEEDO_BIT_MINUS1 58 33 #define G_SPEEDO_BIT_MINUS1_R 59 34 #define G_SPEEDO_BIT_MINUS2 60 35 #define G_SPEEDO_BIT_MINUS2_R 61 36 #define LP_SPEEDO_BIT_MINUS1 62 37 #define LP_SPEEDO_BIT_MINUS1_R 63 38 #define LP_SPEEDO_BIT_MINUS2 64 39 #define LP_SPEEDO_BIT_MINUS2_R 65 40 41 enum { 42 THRESHOLD_INDEX_0, 43 THRESHOLD_INDEX_1, 44 THRESHOLD_INDEX_2, 45 THRESHOLD_INDEX_3, 46 THRESHOLD_INDEX_4, 47 THRESHOLD_INDEX_5, 48 THRESHOLD_INDEX_6, 49 THRESHOLD_INDEX_7, 50 THRESHOLD_INDEX_8, 51 THRESHOLD_INDEX_9, 52 THRESHOLD_INDEX_10, 53 THRESHOLD_INDEX_11, 54 THRESHOLD_INDEX_COUNT, 55 }; 56 57 static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = { 58 {180}, 59 {170}, 60 {195}, 61 {180}, 62 {168}, 63 {192}, 64 {180}, 65 {170}, 66 {195}, 67 {180}, 68 {180}, 69 {180}, 70 }; 71 72 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = { 73 {306, 338, 360, 376, UINT_MAX}, 74 {295, 336, 358, 375, UINT_MAX}, 75 {325, 325, 358, 375, UINT_MAX}, 76 {325, 325, 358, 375, UINT_MAX}, 77 {292, 324, 348, 364, UINT_MAX}, 78 {324, 324, 348, 364, UINT_MAX}, 79 {324, 324, 348, 364, UINT_MAX}, 80 {295, 336, 358, 375, UINT_MAX}, 81 {358, 358, 358, 358, 397, UINT_MAX}, 82 {364, 364, 364, 364, 397, UINT_MAX}, 83 {295, 336, 358, 375, 391, UINT_MAX}, 84 {295, 336, 358, 375, 391, UINT_MAX}, 85 }; 86 87 static int threshold_index __initdata; 88 89 static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp) 90 { 91 u32 reg; 92 int ate_ver; 93 int bit_minus1; 94 int bit_minus2; 95 96 reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0); 97 98 *speedo_lp = (reg & 0xFFFF) * 4; 99 *speedo_g = ((reg >> 16) & 0xFFFF) * 4; 100 101 ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER); 102 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10); 103 104 if (ate_ver >= 26) { 105 bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1); 106 bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R); 107 bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2); 108 bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R); 109 *speedo_lp |= (bit_minus1 << 1) | bit_minus2; 110 111 bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1); 112 bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R); 113 bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2); 114 bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R); 115 *speedo_g |= (bit_minus1 << 1) | bit_minus2; 116 } else { 117 *speedo_lp |= 0x3; 118 *speedo_g |= 0x3; 119 } 120 } 121 122 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info) 123 { 124 int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F; 125 126 switch (sku_info->revision) { 127 case TEGRA_REVISION_A01: 128 sku_info->cpu_speedo_id = 0; 129 sku_info->soc_speedo_id = 0; 130 threshold_index = THRESHOLD_INDEX_0; 131 break; 132 case TEGRA_REVISION_A02: 133 case TEGRA_REVISION_A03: 134 switch (sku_info->sku_id) { 135 case 0x87: 136 case 0x82: 137 sku_info->cpu_speedo_id = 1; 138 sku_info->soc_speedo_id = 1; 139 threshold_index = THRESHOLD_INDEX_1; 140 break; 141 case 0x81: 142 switch (package_id) { 143 case 1: 144 sku_info->cpu_speedo_id = 2; 145 sku_info->soc_speedo_id = 2; 146 threshold_index = THRESHOLD_INDEX_2; 147 break; 148 case 2: 149 sku_info->cpu_speedo_id = 4; 150 sku_info->soc_speedo_id = 1; 151 threshold_index = THRESHOLD_INDEX_7; 152 break; 153 default: 154 pr_err("Tegra Unknown pkg %d\n", package_id); 155 break; 156 } 157 break; 158 case 0x80: 159 switch (package_id) { 160 case 1: 161 sku_info->cpu_speedo_id = 5; 162 sku_info->soc_speedo_id = 2; 163 threshold_index = THRESHOLD_INDEX_8; 164 break; 165 case 2: 166 sku_info->cpu_speedo_id = 6; 167 sku_info->soc_speedo_id = 2; 168 threshold_index = THRESHOLD_INDEX_9; 169 break; 170 default: 171 pr_err("Tegra Unknown pkg %d\n", package_id); 172 break; 173 } 174 break; 175 case 0x83: 176 switch (package_id) { 177 case 1: 178 sku_info->cpu_speedo_id = 7; 179 sku_info->soc_speedo_id = 1; 180 threshold_index = THRESHOLD_INDEX_10; 181 break; 182 case 2: 183 sku_info->cpu_speedo_id = 3; 184 sku_info->soc_speedo_id = 2; 185 threshold_index = THRESHOLD_INDEX_3; 186 break; 187 default: 188 pr_err("Tegra Unknown pkg %d\n", package_id); 189 break; 190 } 191 break; 192 case 0x8F: 193 sku_info->cpu_speedo_id = 8; 194 sku_info->soc_speedo_id = 1; 195 threshold_index = THRESHOLD_INDEX_11; 196 break; 197 case 0x08: 198 sku_info->cpu_speedo_id = 1; 199 sku_info->soc_speedo_id = 1; 200 threshold_index = THRESHOLD_INDEX_4; 201 break; 202 case 0x02: 203 sku_info->cpu_speedo_id = 2; 204 sku_info->soc_speedo_id = 2; 205 threshold_index = THRESHOLD_INDEX_5; 206 break; 207 case 0x04: 208 sku_info->cpu_speedo_id = 3; 209 sku_info->soc_speedo_id = 2; 210 threshold_index = THRESHOLD_INDEX_6; 211 break; 212 case 0: 213 switch (package_id) { 214 case 1: 215 sku_info->cpu_speedo_id = 2; 216 sku_info->soc_speedo_id = 2; 217 threshold_index = THRESHOLD_INDEX_2; 218 break; 219 case 2: 220 sku_info->cpu_speedo_id = 3; 221 sku_info->soc_speedo_id = 2; 222 threshold_index = THRESHOLD_INDEX_3; 223 break; 224 default: 225 pr_err("Tegra Unknown pkg %d\n", package_id); 226 break; 227 } 228 break; 229 default: 230 pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id); 231 sku_info->cpu_speedo_id = 0; 232 sku_info->soc_speedo_id = 0; 233 threshold_index = THRESHOLD_INDEX_0; 234 break; 235 } 236 break; 237 default: 238 pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision); 239 sku_info->cpu_speedo_id = 0; 240 sku_info->soc_speedo_id = 0; 241 threshold_index = THRESHOLD_INDEX_0; 242 break; 243 } 244 } 245 246 void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info) 247 { 248 u32 cpu_speedo_val; 249 u32 core_speedo_val; 250 int i; 251 252 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 253 THRESHOLD_INDEX_COUNT); 254 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 255 THRESHOLD_INDEX_COUNT); 256 257 258 rev_sku_to_speedo_ids(sku_info); 259 fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val); 260 pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val); 261 pr_debug("Tegra Core speedo value %u\n", core_speedo_val); 262 263 for (i = 0; i < CPU_PROCESS_CORNERS; i++) { 264 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i]) 265 break; 266 } 267 sku_info->cpu_process_id = i - 1; 268 269 if (sku_info->cpu_process_id == -1) { 270 pr_warn("Tegra CPU speedo value %3d out of range", 271 cpu_speedo_val); 272 sku_info->cpu_process_id = 0; 273 sku_info->cpu_speedo_id = 1; 274 } 275 276 for (i = 0; i < CORE_PROCESS_CORNERS; i++) { 277 if (core_speedo_val < core_process_speedos[threshold_index][i]) 278 break; 279 } 280 sku_info->core_process_id = i - 1; 281 282 if (sku_info->core_process_id == -1) { 283 pr_warn("Tegra CORE speedo value %3d out of range", 284 core_speedo_val); 285 sku_info->core_process_id = 0; 286 sku_info->soc_speedo_id = 1; 287 } 288 } 289