1*783c8f4cSPeter De Schrijver /* 2*783c8f4cSPeter De Schrijver * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. 3*783c8f4cSPeter De Schrijver * 4*783c8f4cSPeter De Schrijver * This program is free software; you can redistribute it and/or modify it 5*783c8f4cSPeter De Schrijver * under the terms and conditions of the GNU General Public License, 6*783c8f4cSPeter De Schrijver * version 2, as published by the Free Software Foundation. 7*783c8f4cSPeter De Schrijver * 8*783c8f4cSPeter De Schrijver * This program is distributed in the hope it will be useful, but WITHOUT 9*783c8f4cSPeter De Schrijver * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10*783c8f4cSPeter De Schrijver * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11*783c8f4cSPeter De Schrijver * more details. 12*783c8f4cSPeter De Schrijver * 13*783c8f4cSPeter De Schrijver * You should have received a copy of the GNU General Public License 14*783c8f4cSPeter De Schrijver * along with this program. If not, see <http://www.gnu.org/licenses/>. 15*783c8f4cSPeter De Schrijver */ 16*783c8f4cSPeter De Schrijver 17*783c8f4cSPeter De Schrijver #include <linux/bug.h> 18*783c8f4cSPeter De Schrijver #include <linux/device.h> 19*783c8f4cSPeter De Schrijver #include <linux/kernel.h> 20*783c8f4cSPeter De Schrijver 21*783c8f4cSPeter De Schrijver #include <soc/tegra/fuse.h> 22*783c8f4cSPeter De Schrijver 23*783c8f4cSPeter De Schrijver #include "fuse.h" 24*783c8f4cSPeter De Schrijver 25*783c8f4cSPeter De Schrijver #define CORE_PROCESS_CORNERS 2 26*783c8f4cSPeter De Schrijver #define CPU_PROCESS_CORNERS 2 27*783c8f4cSPeter De Schrijver 28*783c8f4cSPeter De Schrijver enum { 29*783c8f4cSPeter De Schrijver THRESHOLD_INDEX_0, 30*783c8f4cSPeter De Schrijver THRESHOLD_INDEX_1, 31*783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT, 32*783c8f4cSPeter De Schrijver }; 33*783c8f4cSPeter De Schrijver 34*783c8f4cSPeter De Schrijver static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = { 35*783c8f4cSPeter De Schrijver {1123, UINT_MAX}, 36*783c8f4cSPeter De Schrijver {0, UINT_MAX}, 37*783c8f4cSPeter De Schrijver }; 38*783c8f4cSPeter De Schrijver 39*783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = { 40*783c8f4cSPeter De Schrijver {1695, UINT_MAX}, 41*783c8f4cSPeter De Schrijver {0, UINT_MAX}, 42*783c8f4cSPeter De Schrijver }; 43*783c8f4cSPeter De Schrijver 44*783c8f4cSPeter De Schrijver static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info, 45*783c8f4cSPeter De Schrijver int *threshold) 46*783c8f4cSPeter De Schrijver { 47*783c8f4cSPeter De Schrijver u32 tmp; 48*783c8f4cSPeter De Schrijver u32 sku = sku_info->sku_id; 49*783c8f4cSPeter De Schrijver enum tegra_revision rev = sku_info->revision; 50*783c8f4cSPeter De Schrijver 51*783c8f4cSPeter De Schrijver switch (sku) { 52*783c8f4cSPeter De Schrijver case 0x00: 53*783c8f4cSPeter De Schrijver case 0x10: 54*783c8f4cSPeter De Schrijver case 0x05: 55*783c8f4cSPeter De Schrijver case 0x06: 56*783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 1; 57*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0; 58*783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_0; 59*783c8f4cSPeter De Schrijver break; 60*783c8f4cSPeter De Schrijver 61*783c8f4cSPeter De Schrijver case 0x03: 62*783c8f4cSPeter De Schrijver case 0x04: 63*783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 2; 64*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 1; 65*783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_1; 66*783c8f4cSPeter De Schrijver break; 67*783c8f4cSPeter De Schrijver 68*783c8f4cSPeter De Schrijver default: 69*783c8f4cSPeter De Schrijver pr_err("Tegra Unknown SKU %d\n", sku); 70*783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0; 71*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = 0; 72*783c8f4cSPeter De Schrijver *threshold = THRESHOLD_INDEX_0; 73*783c8f4cSPeter De Schrijver break; 74*783c8f4cSPeter De Schrijver } 75*783c8f4cSPeter De Schrijver 76*783c8f4cSPeter De Schrijver if (rev == TEGRA_REVISION_A01) { 77*783c8f4cSPeter De Schrijver tmp = tegra30_fuse_readl(0x270) << 1; 78*783c8f4cSPeter De Schrijver tmp |= tegra30_fuse_readl(0x26c); 79*783c8f4cSPeter De Schrijver if (!tmp) 80*783c8f4cSPeter De Schrijver sku_info->cpu_speedo_id = 0; 81*783c8f4cSPeter De Schrijver } 82*783c8f4cSPeter De Schrijver } 83*783c8f4cSPeter De Schrijver 84*783c8f4cSPeter De Schrijver void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info) 85*783c8f4cSPeter De Schrijver { 86*783c8f4cSPeter De Schrijver u32 cpu_speedo_val; 87*783c8f4cSPeter De Schrijver u32 core_speedo_val; 88*783c8f4cSPeter De Schrijver int threshold; 89*783c8f4cSPeter De Schrijver int i; 90*783c8f4cSPeter De Schrijver 91*783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 92*783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT); 93*783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 94*783c8f4cSPeter De Schrijver THRESHOLD_INDEX_COUNT); 95*783c8f4cSPeter De Schrijver 96*783c8f4cSPeter De Schrijver rev_sku_to_speedo_ids(sku_info, &threshold); 97*783c8f4cSPeter De Schrijver 98*783c8f4cSPeter De Schrijver cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024; 99*783c8f4cSPeter De Schrijver core_speedo_val = tegra30_fuse_readl(0x134); 100*783c8f4cSPeter De Schrijver 101*783c8f4cSPeter De Schrijver for (i = 0; i < CPU_PROCESS_CORNERS; i++) 102*783c8f4cSPeter De Schrijver if (cpu_speedo_val < cpu_process_speedos[threshold][i]) 103*783c8f4cSPeter De Schrijver break; 104*783c8f4cSPeter De Schrijver sku_info->cpu_process_id = i; 105*783c8f4cSPeter De Schrijver 106*783c8f4cSPeter De Schrijver for (i = 0; i < CORE_PROCESS_CORNERS; i++) 107*783c8f4cSPeter De Schrijver if (core_speedo_val < core_process_speedos[threshold][i]) 108*783c8f4cSPeter De Schrijver break; 109*783c8f4cSPeter De Schrijver sku_info->core_process_id = i; 110*783c8f4cSPeter De Schrijver } 111