1783c8f4cSPeter De Schrijver /* 2783c8f4cSPeter De Schrijver * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. 3783c8f4cSPeter De Schrijver * 4783c8f4cSPeter De Schrijver * This program is free software; you can redistribute it and/or modify it 5783c8f4cSPeter De Schrijver * under the terms and conditions of the GNU General Public License, 6783c8f4cSPeter De Schrijver * version 2, as published by the Free Software Foundation. 7783c8f4cSPeter De Schrijver * 8783c8f4cSPeter De Schrijver * This program is distributed in the hope it will be useful, but WITHOUT 9783c8f4cSPeter De Schrijver * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10783c8f4cSPeter De Schrijver * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11783c8f4cSPeter De Schrijver * more details. 12783c8f4cSPeter De Schrijver * 13783c8f4cSPeter De Schrijver * You should have received a copy of the GNU General Public License 14783c8f4cSPeter De Schrijver * along with this program. If not, see <http://www.gnu.org/licenses/>. 15783c8f4cSPeter De Schrijver */ 16783c8f4cSPeter De Schrijver 17783c8f4cSPeter De Schrijver #include <linux/bug.h> 18783c8f4cSPeter De Schrijver #include <linux/device.h> 19783c8f4cSPeter De Schrijver #include <linux/kernel.h> 20783c8f4cSPeter De Schrijver 21783c8f4cSPeter De Schrijver #include <soc/tegra/fuse.h> 22783c8f4cSPeter De Schrijver 23783c8f4cSPeter De Schrijver #include "fuse.h" 24783c8f4cSPeter De Schrijver 25*03b3f4c8SThierry Reding #define SOC_PROCESS_CORNERS 2 26783c8f4cSPeter De Schrijver #define CPU_PROCESS_CORNERS 2 27783c8f4cSPeter De Schrijver 28783c8f4cSPeter De Schrijver enum { 29783c8f4cSPeter De Schrijver THRESHOLD_INDEX_0, 30783c8f4cSPeter De Schrijver THRESHOLD_INDEX_1, 31783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT, 32783c8f4cSPeter De Schrijver }; 33783c8f4cSPeter De Schrijver 34*03b3f4c8SThierry Reding static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = { 35783c8f4cSPeter De Schrijver {1123, UINT_MAX}, 36783c8f4cSPeter De Schrijver {0, UINT_MAX}, 37783c8f4cSPeter De Schrijver }; 38783c8f4cSPeter De Schrijver 39783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = { 40783c8f4cSPeter De Schrijver {1695, UINT_MAX}, 41783c8f4cSPeter De Schrijver {0, UINT_MAX}, 42783c8f4cSPeter De Schrijver }; 43783c8f4cSPeter De Schrijver 44783c8f4cSPeter De Schrijver static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, 45783c8f4cSPeter De Schrijver int *threshold) 46783c8f4cSPeter De Schrijver { 47783c8f4cSPeter De Schrijver u32 tmp; 48783c8f4cSPeter De Schrijver u32 sku = sku_info->sku_id; 49783c8f4cSPeter De Schrijver enum tegra_revision rev = sku_info->revision; 50783c8f4cSPeter De Schrijver 51783c8f4cSPeter De Schrijver switch (sku) { 52783c8f4cSPeter De Schrijver case 0x00: 53783c8f4cSPeter De Schrijver case 0x10: 54783c8f4cSPeter De Schrijver case 0x05: 55783c8f4cSPeter De Schrijver case 0x06: 56783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 1; 57783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0; 58783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_0; 59783c8f4cSPeter De Schrijver break; 60783c8f4cSPeter De Schrijver 61783c8f4cSPeter De Schrijver case 0x03: 62783c8f4cSPeter De Schrijver case 0x04: 63783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 2; 64783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1; 65783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_1; 66783c8f4cSPeter De Schrijver break; 67783c8f4cSPeter De Schrijver 68783c8f4cSPeter De Schrijver default: 69783c8f4cSPeter De Schrijver pr_err("Tegra Unknown SKU %d\n", sku); 70783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0; 71783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0; 72783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_0; 73783c8f4cSPeter De Schrijver break; 74783c8f4cSPeter De Schrijver } 75783c8f4cSPeter De Schrijver 76783c8f4cSPeter De Schrijver if (rev == TEGRA_REVISION_A01) { 777e939de1SThierry Reding tmp = tegra_fuse_read_early(0x270) << 1; 787e939de1SThierry Reding tmp |= tegra_fuse_read_early(0x26c); 79783c8f4cSPeter De Schrijver if (!tmp) 80783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0; 81783c8f4cSPeter De Schrijver } 82783c8f4cSPeter De Schrijver } 83783c8f4cSPeter De Schrijver 84783c8f4cSPeter De Schrijver void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info) 85783c8f4cSPeter De Schrijver { 86783c8f4cSPeter De Schrijver u32 cpu_speedo_val; 87*03b3f4c8SThierry Reding u32 soc_speedo_val; 88783c8f4cSPeter De Schrijver int threshold; 89783c8f4cSPeter De Schrijver int i; 90783c8f4cSPeter De Schrijver 91783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 92783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT); 93*03b3f4c8SThierry Reding BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != 94783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT); 95783c8f4cSPeter De Schrijver 96783c8f4cSPeter De Schrijver rev_sku_to_speedo_ids(sku_info, &threshold); 97783c8f4cSPeter De Schrijver 987e939de1SThierry Reding cpu_speedo_val = tegra_fuse_read_early(0x12c) + 1024; 99*03b3f4c8SThierry Reding soc_speedo_val = tegra_fuse_read_early(0x134); 100783c8f4cSPeter De Schrijver 101783c8f4cSPeter De Schrijver for (i = 0; i < CPU_PROCESS_CORNERS; i++) 102783c8f4cSPeter De Schrijver if (cpu_speedo_val < cpu_process_speedos[threshold][i]) 103783c8f4cSPeter De Schrijver break; 104783c8f4cSPeter De Schrijver sku_info->cpu_process_id = i; 105783c8f4cSPeter De Schrijver 106*03b3f4c8SThierry Reding for (i = 0; i < SOC_PROCESS_CORNERS; i++) 107*03b3f4c8SThierry Reding if (soc_speedo_val < soc_process_speedos[threshold][i]) 108783c8f4cSPeter De Schrijver break; 109*03b3f4c8SThierry Reding sku_info->soc_process_id = i; 110783c8f4cSPeter De Schrijver } 111