linux/arch/arm/mach-tegra/tegra30_speedo.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012, 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/kernel.h>
  18#include <linux/bug.h>
  19
  20#include "fuse.h"
  21
  22#define CORE_PROCESS_CORNERS_NUM        1
  23#define CPU_PROCESS_CORNERS_NUM         6
  24
  25#define FUSE_SPEEDO_CALIB_0     0x114
  26#define FUSE_PACKAGE_INFO       0X1FC
  27#define FUSE_TEST_PROG_VER      0X128
  28
  29#define G_SPEEDO_BIT_MINUS1     58
  30#define G_SPEEDO_BIT_MINUS1_R   59
  31#define G_SPEEDO_BIT_MINUS2     60
  32#define G_SPEEDO_BIT_MINUS2_R   61
  33#define LP_SPEEDO_BIT_MINUS1    62
  34#define LP_SPEEDO_BIT_MINUS1_R  63
  35#define LP_SPEEDO_BIT_MINUS2    64
  36#define LP_SPEEDO_BIT_MINUS2_R  65
  37
  38enum {
  39        THRESHOLD_INDEX_0,
  40        THRESHOLD_INDEX_1,
  41        THRESHOLD_INDEX_2,
  42        THRESHOLD_INDEX_3,
  43        THRESHOLD_INDEX_4,
  44        THRESHOLD_INDEX_5,
  45        THRESHOLD_INDEX_6,
  46        THRESHOLD_INDEX_7,
  47        THRESHOLD_INDEX_8,
  48        THRESHOLD_INDEX_9,
  49        THRESHOLD_INDEX_10,
  50        THRESHOLD_INDEX_11,
  51        THRESHOLD_INDEX_COUNT,
  52};
  53
  54static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
  55        {180},
  56        {170},
  57        {195},
  58        {180},
  59        {168},
  60        {192},
  61        {180},
  62        {170},
  63        {195},
  64        {180},
  65        {180},
  66        {180},
  67};
  68
  69static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
  70        {306, 338, 360, 376, UINT_MAX},
  71        {295, 336, 358, 375, UINT_MAX},
  72        {325, 325, 358, 375, UINT_MAX},
  73        {325, 325, 358, 375, UINT_MAX},
  74        {292, 324, 348, 364, UINT_MAX},
  75        {324, 324, 348, 364, UINT_MAX},
  76        {324, 324, 348, 364, UINT_MAX},
  77        {295, 336, 358, 375, UINT_MAX},
  78        {358, 358, 358, 358, 397, UINT_MAX},
  79        {364, 364, 364, 364, 397, UINT_MAX},
  80        {295, 336, 358, 375, 391, UINT_MAX},
  81        {295, 336, 358, 375, 391, UINT_MAX},
  82};
  83
  84static int threshold_index;
  85static int package_id;
  86
  87static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
  88{
  89        u32 reg;
  90        int ate_ver;
  91        int bit_minus1;
  92        int bit_minus2;
  93
  94        reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
  95
  96        *speedo_lp = (reg & 0xFFFF) * 4;
  97        *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
  98
  99        ate_ver = tegra_fuse_readl(FUSE_TEST_PROG_VER);
 100        pr_info("%s: ATE prog ver %d.%d\n", __func__, ate_ver/10, ate_ver%10);
 101
 102        if (ate_ver >= 26) {
 103                bit_minus1 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1);
 104                bit_minus1 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
 105                bit_minus2 = tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2);
 106                bit_minus2 |= tegra_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
 107                *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
 108
 109                bit_minus1 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS1);
 110                bit_minus1 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
 111                bit_minus2 = tegra_spare_fuse(G_SPEEDO_BIT_MINUS2);
 112                bit_minus2 |= tegra_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
 113                *speedo_g |= (bit_minus1 << 1) | bit_minus2;
 114        } else {
 115                *speedo_lp |= 0x3;
 116                *speedo_g |= 0x3;
 117        }
 118}
 119
 120static void rev_sku_to_speedo_ids(int rev, int sku)
 121{
 122        switch (rev) {
 123        case TEGRA_REVISION_A01:
 124                tegra_cpu_speedo_id = 0;
 125                tegra_soc_speedo_id = 0;
 126                threshold_index = THRESHOLD_INDEX_0;
 127                break;
 128        case TEGRA_REVISION_A02:
 129        case TEGRA_REVISION_A03:
 130                switch (sku) {
 131                case 0x87:
 132                case 0x82:
 133                        tegra_cpu_speedo_id = 1;
 134                        tegra_soc_speedo_id = 1;
 135                        threshold_index = THRESHOLD_INDEX_1;
 136                        break;
 137                case 0x81:
 138                        switch (package_id) {
 139                        case 1:
 140                                tegra_cpu_speedo_id = 2;
 141                                tegra_soc_speedo_id = 2;
 142                                threshold_index = THRESHOLD_INDEX_2;
 143                                break;
 144                        case 2:
 145                                tegra_cpu_speedo_id = 4;
 146                                tegra_soc_speedo_id = 1;
 147                                threshold_index = THRESHOLD_INDEX_7;
 148                                break;
 149                        default:
 150                                pr_err("Tegra30: Unknown pkg %d\n", package_id);
 151                                BUG();
 152                                break;
 153                        }
 154                        break;
 155                case 0x80:
 156                        switch (package_id) {
 157                        case 1:
 158                                tegra_cpu_speedo_id = 5;
 159                                tegra_soc_speedo_id = 2;
 160                                threshold_index = THRESHOLD_INDEX_8;
 161                                break;
 162                        case 2:
 163                                tegra_cpu_speedo_id = 6;
 164                                tegra_soc_speedo_id = 2;
 165                                threshold_index = THRESHOLD_INDEX_9;
 166                                break;
 167                        default:
 168                                pr_err("Tegra30: Unknown pkg %d\n", package_id);
 169                                BUG();
 170                                break;
 171                        }
 172                        break;
 173                case 0x83:
 174                        switch (package_id) {
 175                        case 1:
 176                                tegra_cpu_speedo_id = 7;
 177                                tegra_soc_speedo_id = 1;
 178                                threshold_index = THRESHOLD_INDEX_10;
 179                                break;
 180                        case 2:
 181                                tegra_cpu_speedo_id = 3;
 182                                tegra_soc_speedo_id = 2;
 183                                threshold_index = THRESHOLD_INDEX_3;
 184                                break;
 185                        default:
 186                                pr_err("Tegra30: Unknown pkg %d\n", package_id);
 187                                BUG();
 188                                break;
 189                        }
 190                        break;
 191                case 0x8F:
 192                        tegra_cpu_speedo_id = 8;
 193                        tegra_soc_speedo_id = 1;
 194                        threshold_index = THRESHOLD_INDEX_11;
 195                        break;
 196                case 0x08:
 197                        tegra_cpu_speedo_id = 1;
 198                        tegra_soc_speedo_id = 1;
 199                        threshold_index = THRESHOLD_INDEX_4;
 200                        break;
 201                case 0x02:
 202                        tegra_cpu_speedo_id = 2;
 203                        tegra_soc_speedo_id = 2;
 204                        threshold_index = THRESHOLD_INDEX_5;
 205                        break;
 206                case 0x04:
 207                        tegra_cpu_speedo_id = 3;
 208                        tegra_soc_speedo_id = 2;
 209                        threshold_index = THRESHOLD_INDEX_6;
 210                        break;
 211                case 0:
 212                        switch (package_id) {
 213                        case 1:
 214                                tegra_cpu_speedo_id = 2;
 215                                tegra_soc_speedo_id = 2;
 216                                threshold_index = THRESHOLD_INDEX_2;
 217                                break;
 218                        case 2:
 219                                tegra_cpu_speedo_id = 3;
 220                                tegra_soc_speedo_id = 2;
 221                                threshold_index = THRESHOLD_INDEX_3;
 222                                break;
 223                        default:
 224                                pr_err("Tegra30: Unknown pkg %d\n", package_id);
 225                                BUG();
 226                                break;
 227                        }
 228                        break;
 229                default:
 230                        pr_warn("Tegra30: Unknown SKU %d\n", sku);
 231                        tegra_cpu_speedo_id = 0;
 232                        tegra_soc_speedo_id = 0;
 233                        threshold_index = THRESHOLD_INDEX_0;
 234                        break;
 235                }
 236                break;
 237        default:
 238                pr_warn("Tegra30: Unknown chip rev %d\n", rev);
 239                tegra_cpu_speedo_id = 0;
 240                tegra_soc_speedo_id = 0;
 241                threshold_index = THRESHOLD_INDEX_0;
 242                break;
 243        }
 244}
 245
 246void tegra30_init_speedo_data(void)
 247{
 248        u32 cpu_speedo_val;
 249        u32 core_speedo_val;
 250        int i;
 251
 252        BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
 253                        THRESHOLD_INDEX_COUNT);
 254        BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
 255                        THRESHOLD_INDEX_COUNT);
 256
 257        package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
 258
 259        rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id);
 260        fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
 261        pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
 262        pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
 263
 264        for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
 265                if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
 266                        break;
 267        }
 268        tegra_cpu_process_id = i - 1;
 269
 270        if (tegra_cpu_process_id == -1) {
 271                pr_warn("Tegra30: CPU speedo value %3d out of range",
 272                       cpu_speedo_val);
 273                tegra_cpu_process_id = 0;
 274                tegra_cpu_speedo_id = 1;
 275        }
 276
 277        for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
 278                if (core_speedo_val < core_process_speedos[threshold_index][i])
 279                        break;
 280        }
 281        tegra_core_process_id = i - 1;
 282
 283        if (tegra_core_process_id == -1) {
 284                pr_warn("Tegra30: CORE speedo value %3d out of range",
 285                       core_speedo_val);
 286                tegra_core_process_id = 0;
 287                tegra_soc_speedo_id = 1;
 288        }
 289
 290        pr_info("Tegra30: CPU Speedo ID %d, Soc Speedo ID %d",
 291                tegra_cpu_speedo_id, tegra_soc_speedo_id);
 292}
 293