0001
0002
0003
0004
0005
0006 #include <linux/bug.h>
0007 #include <linux/device.h>
0008 #include <linux/kernel.h>
0009
0010 #include <soc/tegra/fuse.h>
0011
0012 #include "fuse.h"
0013
0014 #define SOC_PROCESS_CORNERS 1
0015 #define CPU_PROCESS_CORNERS 6
0016
0017 #define FUSE_SPEEDO_CALIB_0 0x14
0018 #define FUSE_PACKAGE_INFO 0XFC
0019 #define FUSE_TEST_PROG_VER 0X28
0020
0021 #define G_SPEEDO_BIT_MINUS1 58
0022 #define G_SPEEDO_BIT_MINUS1_R 59
0023 #define G_SPEEDO_BIT_MINUS2 60
0024 #define G_SPEEDO_BIT_MINUS2_R 61
0025 #define LP_SPEEDO_BIT_MINUS1 62
0026 #define LP_SPEEDO_BIT_MINUS1_R 63
0027 #define LP_SPEEDO_BIT_MINUS2 64
0028 #define LP_SPEEDO_BIT_MINUS2_R 65
0029
0030 enum {
0031 THRESHOLD_INDEX_0,
0032 THRESHOLD_INDEX_1,
0033 THRESHOLD_INDEX_2,
0034 THRESHOLD_INDEX_3,
0035 THRESHOLD_INDEX_4,
0036 THRESHOLD_INDEX_5,
0037 THRESHOLD_INDEX_6,
0038 THRESHOLD_INDEX_7,
0039 THRESHOLD_INDEX_8,
0040 THRESHOLD_INDEX_9,
0041 THRESHOLD_INDEX_10,
0042 THRESHOLD_INDEX_11,
0043 THRESHOLD_INDEX_COUNT,
0044 };
0045
0046 static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
0047 {180},
0048 {170},
0049 {195},
0050 {180},
0051 {168},
0052 {192},
0053 {180},
0054 {170},
0055 {195},
0056 {180},
0057 {180},
0058 {180},
0059 };
0060
0061 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
0062 {306, 338, 360, 376, UINT_MAX},
0063 {295, 336, 358, 375, UINT_MAX},
0064 {325, 325, 358, 375, UINT_MAX},
0065 {325, 325, 358, 375, UINT_MAX},
0066 {292, 324, 348, 364, UINT_MAX},
0067 {324, 324, 348, 364, UINT_MAX},
0068 {324, 324, 348, 364, UINT_MAX},
0069 {295, 336, 358, 375, UINT_MAX},
0070 {358, 358, 358, 358, 397, UINT_MAX},
0071 {364, 364, 364, 364, 397, UINT_MAX},
0072 {295, 336, 358, 375, 391, UINT_MAX},
0073 {295, 336, 358, 375, 391, UINT_MAX},
0074 };
0075
0076 static int threshold_index __initdata;
0077
0078 static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
0079 {
0080 u32 reg;
0081 int ate_ver;
0082 int bit_minus1;
0083 int bit_minus2;
0084
0085 reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
0086
0087 *speedo_lp = (reg & 0xFFFF) * 4;
0088 *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
0089
0090 ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
0091 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
0092
0093 if (ate_ver >= 26) {
0094 bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
0095 bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
0096 bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
0097 bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
0098 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
0099
0100 bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
0101 bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
0102 bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
0103 bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
0104 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
0105 } else {
0106 *speedo_lp |= 0x3;
0107 *speedo_g |= 0x3;
0108 }
0109 }
0110
0111 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
0112 {
0113 int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
0114
0115 switch (sku_info->revision) {
0116 case TEGRA_REVISION_A01:
0117 sku_info->cpu_speedo_id = 0;
0118 sku_info->soc_speedo_id = 0;
0119 threshold_index = THRESHOLD_INDEX_0;
0120 break;
0121 case TEGRA_REVISION_A02:
0122 case TEGRA_REVISION_A03:
0123 switch (sku_info->sku_id) {
0124 case 0x87:
0125 case 0x82:
0126 sku_info->cpu_speedo_id = 1;
0127 sku_info->soc_speedo_id = 1;
0128 threshold_index = THRESHOLD_INDEX_1;
0129 break;
0130 case 0x81:
0131 switch (package_id) {
0132 case 1:
0133 sku_info->cpu_speedo_id = 2;
0134 sku_info->soc_speedo_id = 2;
0135 threshold_index = THRESHOLD_INDEX_2;
0136 break;
0137 case 2:
0138 sku_info->cpu_speedo_id = 4;
0139 sku_info->soc_speedo_id = 1;
0140 threshold_index = THRESHOLD_INDEX_7;
0141 break;
0142 default:
0143 pr_err("Tegra Unknown pkg %d\n", package_id);
0144 break;
0145 }
0146 break;
0147 case 0x80:
0148 switch (package_id) {
0149 case 1:
0150 sku_info->cpu_speedo_id = 5;
0151 sku_info->soc_speedo_id = 2;
0152 threshold_index = THRESHOLD_INDEX_8;
0153 break;
0154 case 2:
0155 sku_info->cpu_speedo_id = 6;
0156 sku_info->soc_speedo_id = 2;
0157 threshold_index = THRESHOLD_INDEX_9;
0158 break;
0159 default:
0160 pr_err("Tegra Unknown pkg %d\n", package_id);
0161 break;
0162 }
0163 break;
0164 case 0x83:
0165 switch (package_id) {
0166 case 1:
0167 sku_info->cpu_speedo_id = 7;
0168 sku_info->soc_speedo_id = 1;
0169 threshold_index = THRESHOLD_INDEX_10;
0170 break;
0171 case 2:
0172 sku_info->cpu_speedo_id = 3;
0173 sku_info->soc_speedo_id = 2;
0174 threshold_index = THRESHOLD_INDEX_3;
0175 break;
0176 default:
0177 pr_err("Tegra Unknown pkg %d\n", package_id);
0178 break;
0179 }
0180 break;
0181 case 0x8F:
0182 sku_info->cpu_speedo_id = 8;
0183 sku_info->soc_speedo_id = 1;
0184 threshold_index = THRESHOLD_INDEX_11;
0185 break;
0186 case 0x08:
0187 sku_info->cpu_speedo_id = 1;
0188 sku_info->soc_speedo_id = 1;
0189 threshold_index = THRESHOLD_INDEX_4;
0190 break;
0191 case 0x02:
0192 sku_info->cpu_speedo_id = 2;
0193 sku_info->soc_speedo_id = 2;
0194 threshold_index = THRESHOLD_INDEX_5;
0195 break;
0196 case 0x04:
0197 sku_info->cpu_speedo_id = 3;
0198 sku_info->soc_speedo_id = 2;
0199 threshold_index = THRESHOLD_INDEX_6;
0200 break;
0201 case 0:
0202 switch (package_id) {
0203 case 1:
0204 sku_info->cpu_speedo_id = 2;
0205 sku_info->soc_speedo_id = 2;
0206 threshold_index = THRESHOLD_INDEX_2;
0207 break;
0208 case 2:
0209 sku_info->cpu_speedo_id = 3;
0210 sku_info->soc_speedo_id = 2;
0211 threshold_index = THRESHOLD_INDEX_3;
0212 break;
0213 default:
0214 pr_err("Tegra Unknown pkg %d\n", package_id);
0215 break;
0216 }
0217 break;
0218 default:
0219 pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
0220 sku_info->cpu_speedo_id = 0;
0221 sku_info->soc_speedo_id = 0;
0222 threshold_index = THRESHOLD_INDEX_0;
0223 break;
0224 }
0225 break;
0226 default:
0227 pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
0228 sku_info->cpu_speedo_id = 0;
0229 sku_info->soc_speedo_id = 0;
0230 threshold_index = THRESHOLD_INDEX_0;
0231 break;
0232 }
0233 }
0234
0235 void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
0236 {
0237 u32 cpu_speedo_val;
0238 u32 soc_speedo_val;
0239 int i;
0240
0241 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
0242 THRESHOLD_INDEX_COUNT);
0243 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
0244 THRESHOLD_INDEX_COUNT);
0245
0246
0247 rev_sku_to_speedo_ids(sku_info);
0248 fuse_speedo_calib(&cpu_speedo_val, &soc_speedo_val);
0249 pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
0250 pr_debug("Tegra Core speedo value %u\n", soc_speedo_val);
0251
0252 for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
0253 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
0254 break;
0255 }
0256 sku_info->cpu_process_id = i - 1;
0257
0258 if (sku_info->cpu_process_id == -1) {
0259 pr_warn("Tegra CPU speedo value %3d out of range",
0260 cpu_speedo_val);
0261 sku_info->cpu_process_id = 0;
0262 sku_info->cpu_speedo_id = 1;
0263 }
0264
0265 for (i = 0; i < SOC_PROCESS_CORNERS; i++) {
0266 if (soc_speedo_val < soc_process_speedos[threshold_index][i])
0267 break;
0268 }
0269 sku_info->soc_process_id = i - 1;
0270
0271 if (sku_info->soc_process_id == -1) {
0272 pr_warn("Tegra SoC speedo value %3d out of range",
0273 soc_speedo_val);
0274 sku_info->soc_process_id = 0;
0275 sku_info->soc_speedo_id = 1;
0276 }
0277 }