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