1*783c8f4cSPeter De Schrijver /* 2*783c8f4cSPeter De Schrijver * Copyright (c) 2012-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 CPU_SPEEDO_LSBIT 20 26*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_MSBIT 29 27*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_LSBIT 30 28*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_MSBIT 39 29*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT) 30*783c8f4cSPeter De Schrijver 31*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_LSBIT 40 32*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_MSBIT 47 33*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_LSBIT 48 34*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_MSBIT 55 35*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT) 36*783c8f4cSPeter De Schrijver 37*783c8f4cSPeter De Schrijver #define SPEEDO_MULT 4 38*783c8f4cSPeter De Schrijver 39*783c8f4cSPeter De Schrijver #define PROCESS_CORNERS_NUM 4 40*783c8f4cSPeter De Schrijver 41*783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2) 42*783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_1(sku) \ 43*783c8f4cSPeter De Schrijver (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \ 44*783c8f4cSPeter De Schrijver ((sku) != 27) && ((sku) != 28)) 45*783c8f4cSPeter De Schrijver 46*783c8f4cSPeter De Schrijver enum { 47*783c8f4cSPeter De Schrijver SPEEDO_ID_0, 48*783c8f4cSPeter De Schrijver SPEEDO_ID_1, 49*783c8f4cSPeter De Schrijver SPEEDO_ID_2, 50*783c8f4cSPeter De Schrijver SPEEDO_ID_COUNT, 51*783c8f4cSPeter De Schrijver }; 52*783c8f4cSPeter De Schrijver 53*783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = { 54*783c8f4cSPeter De Schrijver {315, 366, 420, UINT_MAX}, 55*783c8f4cSPeter De Schrijver {303, 368, 419, UINT_MAX}, 56*783c8f4cSPeter De Schrijver {316, 331, 383, UINT_MAX}, 57*783c8f4cSPeter De Schrijver }; 58*783c8f4cSPeter De Schrijver 59*783c8f4cSPeter De Schrijver static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = { 60*783c8f4cSPeter De Schrijver {165, 195, 224, UINT_MAX}, 61*783c8f4cSPeter De Schrijver {165, 195, 224, UINT_MAX}, 62*783c8f4cSPeter De Schrijver {165, 195, 224, UINT_MAX}, 63*783c8f4cSPeter De Schrijver }; 64*783c8f4cSPeter De Schrijver 65*783c8f4cSPeter De Schrijver void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info) 66*783c8f4cSPeter De Schrijver { 67*783c8f4cSPeter De Schrijver u32 reg; 68*783c8f4cSPeter De Schrijver u32 val; 69*783c8f4cSPeter De Schrijver int i; 70*783c8f4cSPeter De Schrijver 71*783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT); 72*783c8f4cSPeter De Schrijver BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT); 73*783c8f4cSPeter De Schrijver 74*783c8f4cSPeter De Schrijver if (SPEEDO_ID_SELECT_0(sku_info->revision)) 75*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = SPEEDO_ID_0; 76*783c8f4cSPeter De Schrijver else if (SPEEDO_ID_SELECT_1(sku_info->sku_id)) 77*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = SPEEDO_ID_1; 78*783c8f4cSPeter De Schrijver else 79*783c8f4cSPeter De Schrijver sku_info->soc_speedo_id = SPEEDO_ID_2; 80*783c8f4cSPeter De Schrijver 81*783c8f4cSPeter De Schrijver val = 0; 82*783c8f4cSPeter De Schrijver for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) { 83*783c8f4cSPeter De Schrijver reg = tegra20_spare_fuse_early(i) | 84*783c8f4cSPeter De Schrijver tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS); 85*783c8f4cSPeter De Schrijver val = (val << 1) | (reg & 0x1); 86*783c8f4cSPeter De Schrijver } 87*783c8f4cSPeter De Schrijver val = val * SPEEDO_MULT; 88*783c8f4cSPeter De Schrijver pr_debug("Tegra CPU speedo value %u\n", val); 89*783c8f4cSPeter De Schrijver 90*783c8f4cSPeter De Schrijver for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { 91*783c8f4cSPeter De Schrijver if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i]) 92*783c8f4cSPeter De Schrijver break; 93*783c8f4cSPeter De Schrijver } 94*783c8f4cSPeter De Schrijver sku_info->cpu_process_id = i; 95*783c8f4cSPeter De Schrijver 96*783c8f4cSPeter De Schrijver val = 0; 97*783c8f4cSPeter De Schrijver for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) { 98*783c8f4cSPeter De Schrijver reg = tegra20_spare_fuse_early(i) | 99*783c8f4cSPeter De Schrijver tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS); 100*783c8f4cSPeter De Schrijver val = (val << 1) | (reg & 0x1); 101*783c8f4cSPeter De Schrijver } 102*783c8f4cSPeter De Schrijver val = val * SPEEDO_MULT; 103*783c8f4cSPeter De Schrijver pr_debug("Core speedo value %u\n", val); 104*783c8f4cSPeter De Schrijver 105*783c8f4cSPeter De Schrijver for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { 106*783c8f4cSPeter De Schrijver if (val <= core_process_speedos[sku_info->soc_speedo_id][i]) 107*783c8f4cSPeter De Schrijver break; 108*783c8f4cSPeter De Schrijver } 109*783c8f4cSPeter De Schrijver sku_info->core_process_id = i; 110*783c8f4cSPeter De Schrijver } 111