0001
0002
0003
0004
0005
0006 #include <linux/device.h>
0007 #include <linux/kernel.h>
0008 #include <linux/bug.h>
0009
0010 #include <soc/tegra/fuse.h>
0011
0012 #include "fuse.h"
0013
0014 #define CPU_PROCESS_CORNERS 2
0015 #define GPU_PROCESS_CORNERS 2
0016 #define SOC_PROCESS_CORNERS 2
0017
0018 #define FUSE_CPU_SPEEDO_0 0x14
0019 #define FUSE_CPU_SPEEDO_1 0x2c
0020 #define FUSE_CPU_SPEEDO_2 0x30
0021 #define FUSE_SOC_SPEEDO_0 0x34
0022 #define FUSE_SOC_SPEEDO_1 0x38
0023 #define FUSE_SOC_SPEEDO_2 0x3c
0024 #define FUSE_CPU_IDDQ 0x18
0025 #define FUSE_SOC_IDDQ 0x40
0026 #define FUSE_GPU_IDDQ 0x128
0027 #define FUSE_FT_REV 0x28
0028
0029 enum {
0030 THRESHOLD_INDEX_0,
0031 THRESHOLD_INDEX_1,
0032 THRESHOLD_INDEX_COUNT,
0033 };
0034
0035 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
0036 {2190, UINT_MAX},
0037 {0, UINT_MAX},
0038 };
0039
0040 static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
0041 {1965, UINT_MAX},
0042 {0, UINT_MAX},
0043 };
0044
0045 static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
0046 {2101, UINT_MAX},
0047 {0, UINT_MAX},
0048 };
0049
0050 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
0051 int *threshold)
0052 {
0053 int sku = sku_info->sku_id;
0054
0055
0056 sku_info->cpu_speedo_id = 0;
0057 sku_info->soc_speedo_id = 0;
0058 sku_info->gpu_speedo_id = 0;
0059 *threshold = THRESHOLD_INDEX_0;
0060
0061 switch (sku) {
0062 case 0x00:
0063 case 0x0F:
0064 case 0x23:
0065
0066 break;
0067 case 0x83:
0068 sku_info->cpu_speedo_id = 2;
0069 break;
0070
0071 case 0x1F:
0072 case 0x87:
0073 case 0x27:
0074 sku_info->cpu_speedo_id = 2;
0075 sku_info->soc_speedo_id = 0;
0076 sku_info->gpu_speedo_id = 1;
0077 *threshold = THRESHOLD_INDEX_0;
0078 break;
0079 case 0x81:
0080 case 0x21:
0081 case 0x07:
0082 sku_info->cpu_speedo_id = 1;
0083 sku_info->soc_speedo_id = 1;
0084 sku_info->gpu_speedo_id = 1;
0085 *threshold = THRESHOLD_INDEX_1;
0086 break;
0087 case 0x49:
0088 case 0x4A:
0089 case 0x48:
0090 sku_info->cpu_speedo_id = 4;
0091 sku_info->soc_speedo_id = 2;
0092 sku_info->gpu_speedo_id = 3;
0093 *threshold = THRESHOLD_INDEX_1;
0094 break;
0095 default:
0096 pr_err("Tegra Unknown SKU %d\n", sku);
0097
0098 break;
0099 }
0100 }
0101
0102 void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
0103 {
0104 int i, threshold, soc_speedo_0_value;
0105
0106 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
0107 THRESHOLD_INDEX_COUNT);
0108 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
0109 THRESHOLD_INDEX_COUNT);
0110 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
0111 THRESHOLD_INDEX_COUNT);
0112
0113 sku_info->cpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0);
0114 if (sku_info->cpu_speedo_value == 0) {
0115 pr_warn("Tegra Warning: Speedo value not fused.\n");
0116 WARN_ON(1);
0117 return;
0118 }
0119
0120
0121 sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
0122 soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
0123
0124 rev_sku_to_speedo_ids(sku_info, &threshold);
0125
0126 sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
0127
0128 for (i = 0; i < GPU_PROCESS_CORNERS; i++)
0129 if (sku_info->gpu_speedo_value <
0130 gpu_process_speedos[threshold][i])
0131 break;
0132 sku_info->gpu_process_id = i;
0133
0134 for (i = 0; i < CPU_PROCESS_CORNERS; i++)
0135 if (sku_info->cpu_speedo_value <
0136 cpu_process_speedos[threshold][i])
0137 break;
0138 sku_info->cpu_process_id = i;
0139
0140 for (i = 0; i < SOC_PROCESS_CORNERS; i++)
0141 if (soc_speedo_0_value <
0142 soc_process_speedos[threshold][i])
0143 break;
0144 sku_info->soc_process_id = i;
0145
0146 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
0147 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
0148 }