1 /* 2 * Copyright (c) 2013-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/device.h> 18 #include <linux/kernel.h> 19 #include <linux/bug.h> 20 21 #include <soc/tegra/fuse.h> 22 23 #include "fuse.h" 24 25 #define CPU_PROCESS_CORNERS 2 26 #define GPU_PROCESS_CORNERS 2 27 #define SOC_PROCESS_CORNERS 2 28 29 #define FUSE_CPU_SPEEDO_0 0x14 30 #define FUSE_CPU_SPEEDO_1 0x2c 31 #define FUSE_CPU_SPEEDO_2 0x30 32 #define FUSE_SOC_SPEEDO_0 0x34 33 #define FUSE_SOC_SPEEDO_1 0x38 34 #define FUSE_SOC_SPEEDO_2 0x3c 35 #define FUSE_CPU_IDDQ 0x18 36 #define FUSE_SOC_IDDQ 0x40 37 #define FUSE_GPU_IDDQ 0x128 38 #define FUSE_FT_REV 0x28 39 40 enum { 41 THRESHOLD_INDEX_0, 42 THRESHOLD_INDEX_1, 43 THRESHOLD_INDEX_COUNT, 44 }; 45 46 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = { 47 {2190, UINT_MAX}, 48 {0, UINT_MAX}, 49 }; 50 51 static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = { 52 {1965, UINT_MAX}, 53 {0, UINT_MAX}, 54 }; 55 56 static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = { 57 {2101, UINT_MAX}, 58 {0, UINT_MAX}, 59 }; 60 61 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, 62 int *threshold) 63 { 64 int sku = sku_info->sku_id; 65 66 /* Assign to default */ 67 sku_info->cpu_speedo_id = 0; 68 sku_info->soc_speedo_id = 0; 69 sku_info->gpu_speedo_id = 0; 70 *threshold = THRESHOLD_INDEX_0; 71 72 switch (sku) { 73 case 0x00: /* Eng sku */ 74 case 0x0F: 75 case 0x23: 76 /* Using the default */ 77 break; 78 case 0x83: 79 sku_info->cpu_speedo_id = 2; 80 break; 81 82 case 0x1F: 83 case 0x87: 84 case 0x27: 85 sku_info->cpu_speedo_id = 2; 86 sku_info->soc_speedo_id = 0; 87 sku_info->gpu_speedo_id = 1; 88 *threshold = THRESHOLD_INDEX_0; 89 break; 90 case 0x81: 91 case 0x21: 92 case 0x07: 93 sku_info->cpu_speedo_id = 1; 94 sku_info->soc_speedo_id = 1; 95 sku_info->gpu_speedo_id = 1; 96 *threshold = THRESHOLD_INDEX_1; 97 break; 98 case 0x49: 99 case 0x4A: 100 case 0x48: 101 sku_info->cpu_speedo_id = 4; 102 sku_info->soc_speedo_id = 2; 103 sku_info->gpu_speedo_id = 3; 104 *threshold = THRESHOLD_INDEX_1; 105 break; 106 default: 107 pr_err("Tegra Unknown SKU %d\n", sku); 108 /* Using the default for the error case */ 109 break; 110 } 111 } 112 113 void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info) 114 { 115 int i, threshold, cpu_speedo_0_value, soc_speedo_0_value; 116 int cpu_iddq_value, gpu_iddq_value, soc_iddq_value; 117 118 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 119 THRESHOLD_INDEX_COUNT); 120 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) != 121 THRESHOLD_INDEX_COUNT); 122 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != 123 THRESHOLD_INDEX_COUNT); 124 125 cpu_speedo_0_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0); 126 127 /* GPU Speedo is stored in CPU_SPEEDO_2 */ 128 sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2); 129 130 soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0); 131 132 cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ); 133 soc_iddq_value = tegra_fuse_read_early(FUSE_SOC_IDDQ); 134 gpu_iddq_value = tegra_fuse_read_early(FUSE_GPU_IDDQ); 135 136 sku_info->cpu_speedo_value = cpu_speedo_0_value; 137 138 if (sku_info->cpu_speedo_value == 0) { 139 pr_warn("Tegra Warning: Speedo value not fused.\n"); 140 WARN_ON(1); 141 return; 142 } 143 144 rev_sku_to_speedo_ids(sku_info, &threshold); 145 146 sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ); 147 148 for (i = 0; i < GPU_PROCESS_CORNERS; i++) 149 if (sku_info->gpu_speedo_value < 150 gpu_process_speedos[threshold][i]) 151 break; 152 sku_info->gpu_process_id = i; 153 154 for (i = 0; i < CPU_PROCESS_CORNERS; i++) 155 if (sku_info->cpu_speedo_value < 156 cpu_process_speedos[threshold][i]) 157 break; 158 sku_info->cpu_process_id = i; 159 160 for (i = 0; i < SOC_PROCESS_CORNERS; i++) 161 if (soc_speedo_0_value < 162 soc_process_speedos[threshold][i]) 163 break; 164 sku_info->soc_process_id = i; 165 166 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n", 167 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value); 168 } 169