Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc/tegra: fuse: Add Tegra210 support

Add Tegra210 support to the fuses driver and add Tegra210-specific
speedo definitions.

Signed-off-by: Thierry Reding <treding@nvidia.com>

+215 -2
+1
drivers/soc/tegra/fuse/Makefile
··· 7 7 obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o 8 8 obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o 9 9 obj-$(CONFIG_ARCH_TEGRA_132_SOC) += speedo-tegra124.o 10 + obj-$(CONFIG_ARCH_TEGRA_210_SOC) += speedo-tegra210.o
+4
drivers/soc/tegra/fuse/fuse-tegra.c
··· 91 91 { .compatible = "nvidia,tegra114-car", }, 92 92 { .compatible = "nvidia,tegra124-car", }, 93 93 { .compatible = "nvidia,tegra132-car", }, 94 + { .compatible = "nvidia,tegra210-car", }, 94 95 {}, 95 96 }; 96 97 ··· 101 100 }; 102 101 103 102 static const struct of_device_id tegra_fuse_match[] = { 103 + #ifdef CONFIG_ARCH_TEGRA_210_SOC 104 + { .compatible = "nvidia,tegra210-efuse", .data = &tegra210_fuse_soc }, 105 + #endif 104 106 #ifdef CONFIG_ARCH_TEGRA_132_SOC 105 107 { .compatible = "nvidia,tegra132-efuse", .data = &tegra124_fuse_soc }, 106 108 #endif
+15 -1
drivers/soc/tegra/fuse/fuse-tegra30.c
··· 45 45 #if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \ 46 46 defined(CONFIG_ARCH_TEGRA_114_SOC) || \ 47 47 defined(CONFIG_ARCH_TEGRA_124_SOC) || \ 48 - defined(CONFIG_ARCH_TEGRA_132_SOC) 48 + defined(CONFIG_ARCH_TEGRA_132_SOC) || \ 49 + defined(CONFIG_ARCH_TEGRA_210_SOC) 49 50 static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset) 50 51 { 51 52 return readl_relaxed(fuse->base + FUSE_BEGIN + offset); ··· 140 139 .init = tegra30_fuse_init, 141 140 .speedo_init = tegra124_init_speedo_data, 142 141 .info = &tegra124_fuse_info, 142 + }; 143 + #endif 144 + 145 + #if defined(CONFIG_ARCH_TEGRA_210_SOC) 146 + static const struct tegra_fuse_info tegra210_fuse_info = { 147 + .read = tegra30_fuse_read, 148 + .size = 0x300, 149 + }; 150 + 151 + const struct tegra_fuse_soc tegra210_fuse_soc = { 152 + .init = tegra30_fuse_init, 153 + .speedo_init = tegra210_init_speedo_data, 154 + .info = &tegra210_fuse_info, 143 155 }; 144 156 #endif
+8
drivers/soc/tegra/fuse/fuse.h
··· 81 81 void tegra124_init_speedo_data(struct tegra_sku_info *sku_info); 82 82 #endif 83 83 84 + #ifdef CONFIG_ARCH_TEGRA_210_SOC 85 + void tegra210_init_speedo_data(struct tegra_sku_info *sku_info); 86 + #endif 87 + 84 88 #ifdef CONFIG_ARCH_TEGRA_2x_SOC 85 89 extern const struct tegra_fuse_soc tegra20_fuse_soc; 86 90 #endif ··· 99 95 100 96 #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) 101 97 extern const struct tegra_fuse_soc tegra124_fuse_soc; 98 + #endif 99 + 100 + #ifdef CONFIG_ARCH_TEGRA_210_SOC 101 + extern const struct tegra_fuse_soc tegra210_fuse_soc; 102 102 #endif 103 103 104 104 #endif
+184
drivers/soc/tegra/fuse/speedo-tegra210.c
··· 1 + /* 2 + * Copyright (c) 2013-2015, 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 3 28 + 29 + #define FUSE_CPU_SPEEDO_0 0x014 30 + #define FUSE_CPU_SPEEDO_1 0x02c 31 + #define FUSE_CPU_SPEEDO_2 0x030 32 + #define FUSE_SOC_SPEEDO_0 0x034 33 + #define FUSE_SOC_SPEEDO_1 0x038 34 + #define FUSE_SOC_SPEEDO_2 0x03c 35 + #define FUSE_CPU_IDDQ 0x018 36 + #define FUSE_SOC_IDDQ 0x040 37 + #define FUSE_GPU_IDDQ 0x128 38 + #define FUSE_FT_REV 0x028 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 + { 2119, UINT_MAX }, 48 + { 2119, UINT_MAX }, 49 + }; 50 + 51 + static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = { 52 + { UINT_MAX, UINT_MAX }, 53 + { UINT_MAX, UINT_MAX }, 54 + }; 55 + 56 + static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = { 57 + { 1950, 2100, UINT_MAX }, 58 + { 1950, 2100, UINT_MAX }, 59 + }; 60 + 61 + static u8 __init get_speedo_revision(void) 62 + { 63 + return tegra_fuse_read_spare(4) << 2 | 64 + tegra_fuse_read_spare(3) << 1 | 65 + tegra_fuse_read_spare(2) << 0; 66 + } 67 + 68 + static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, 69 + u8 speedo_rev, int *threshold) 70 + { 71 + int sku = sku_info->sku_id; 72 + 73 + /* Assign to default */ 74 + sku_info->cpu_speedo_id = 0; 75 + sku_info->soc_speedo_id = 0; 76 + sku_info->gpu_speedo_id = 0; 77 + *threshold = THRESHOLD_INDEX_0; 78 + 79 + switch (sku) { 80 + case 0x00: /* Engineering SKU */ 81 + case 0x01: /* Engineering SKU */ 82 + case 0x07: 83 + case 0x17: 84 + case 0x27: 85 + if (speedo_rev >= 2) 86 + sku_info->gpu_speedo_id = 1; 87 + break; 88 + 89 + case 0x13: 90 + if (speedo_rev >= 2) 91 + sku_info->gpu_speedo_id = 1; 92 + 93 + sku_info->cpu_speedo_id = 1; 94 + break; 95 + 96 + default: 97 + pr_err("Tegra210: unknown SKU %#04x\n", sku); 98 + /* Using the default for the error case */ 99 + break; 100 + } 101 + } 102 + 103 + static int get_process_id(int value, const u32 *speedos, unsigned int num) 104 + { 105 + unsigned int i; 106 + 107 + for (i = 0; i < num; i++) 108 + if (value < speedos[num]) 109 + return i; 110 + 111 + return -EINVAL; 112 + } 113 + 114 + void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info) 115 + { 116 + int cpu_speedo[3], soc_speedo[3], cpu_iddq, gpu_iddq, soc_iddq; 117 + unsigned int index; 118 + u8 speedo_revision; 119 + 120 + BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 121 + THRESHOLD_INDEX_COUNT); 122 + BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) != 123 + THRESHOLD_INDEX_COUNT); 124 + BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != 125 + THRESHOLD_INDEX_COUNT); 126 + 127 + /* Read speedo/IDDQ fuses */ 128 + cpu_speedo[0] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0); 129 + cpu_speedo[1] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_1); 130 + cpu_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2); 131 + 132 + soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0); 133 + soc_speedo[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1); 134 + soc_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2); 135 + 136 + cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4; 137 + soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4; 138 + gpu_iddq = tegra_fuse_read_early(FUSE_GPU_IDDQ) * 5; 139 + 140 + /* 141 + * Determine CPU, GPU and SoC speedo values depending on speedo fusing 142 + * revision. Note that GPU speedo value is fused in CPU_SPEEDO_2. 143 + */ 144 + speedo_revision = get_speedo_revision(); 145 + pr_info("Speedo Revision %u\n", speedo_revision); 146 + 147 + if (speedo_revision >= 3) { 148 + sku_info->cpu_speedo_value = cpu_speedo[0]; 149 + sku_info->gpu_speedo_value = cpu_speedo[2]; 150 + sku_info->soc_speedo_value = soc_speedo[0]; 151 + } else if (speedo_revision == 2) { 152 + sku_info->cpu_speedo_value = (-1938 + (1095 * cpu_speedo[0] / 100)) / 10; 153 + sku_info->gpu_speedo_value = (-1662 + (1082 * cpu_speedo[2] / 100)) / 10; 154 + sku_info->soc_speedo_value = ( -705 + (1037 * soc_speedo[0] / 100)) / 10; 155 + } else { 156 + sku_info->cpu_speedo_value = 2100; 157 + sku_info->gpu_speedo_value = cpu_speedo[2] - 75; 158 + sku_info->soc_speedo_value = 1900; 159 + } 160 + 161 + if ((sku_info->cpu_speedo_value <= 0) || 162 + (sku_info->gpu_speedo_value <= 0) || 163 + (sku_info->soc_speedo_value <= 0)) { 164 + WARN(1, "speedo value not fused\n"); 165 + return; 166 + } 167 + 168 + rev_sku_to_speedo_ids(sku_info, speedo_revision, &index); 169 + 170 + sku_info->gpu_process_id = get_process_id(sku_info->gpu_speedo_value, 171 + gpu_process_speedos[index], 172 + GPU_PROCESS_CORNERS); 173 + 174 + sku_info->cpu_process_id = get_process_id(sku_info->cpu_speedo_value, 175 + cpu_process_speedos[index], 176 + CPU_PROCESS_CORNERS); 177 + 178 + sku_info->soc_process_id = get_process_id(sku_info->soc_speedo_value, 179 + soc_process_speedos[index], 180 + SOC_PROCESS_CORNERS); 181 + 182 + pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n", 183 + sku_info->gpu_speedo_id, sku_info->gpu_speedo_value); 184 + }
+3 -1
include/soc/tegra/fuse.h
··· 22 22 #define TEGRA114 0x35 23 23 #define TEGRA124 0x40 24 24 #define TEGRA132 0x13 25 + #define TEGRA210 0x21 25 26 26 27 #define TEGRA_FUSE_SKU_CALIB_0 0xf0 27 28 #define TEGRA30_FUSE_SATA_CALIB 0x124 ··· 50 49 int cpu_iddq_value; 51 50 int core_process_id; 52 51 int soc_speedo_id; 53 - int gpu_speedo_id; 52 + int soc_speedo_value; 54 53 int gpu_process_id; 54 + int gpu_speedo_id; 55 55 int gpu_speedo_value; 56 56 enum tegra_revision revision; 57 57 };