18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/bug.h> 78c2ecf20Sopenharmony_ci#include <linux/device.h> 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <soc/tegra/fuse.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include "fuse.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define CPU_SPEEDO_LSBIT 20 158c2ecf20Sopenharmony_ci#define CPU_SPEEDO_MSBIT 29 168c2ecf20Sopenharmony_ci#define CPU_SPEEDO_REDUND_LSBIT 30 178c2ecf20Sopenharmony_ci#define CPU_SPEEDO_REDUND_MSBIT 39 188c2ecf20Sopenharmony_ci#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT) 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define SOC_SPEEDO_LSBIT 40 218c2ecf20Sopenharmony_ci#define SOC_SPEEDO_MSBIT 47 228c2ecf20Sopenharmony_ci#define SOC_SPEEDO_REDUND_LSBIT 48 238c2ecf20Sopenharmony_ci#define SOC_SPEEDO_REDUND_MSBIT 55 248c2ecf20Sopenharmony_ci#define SOC_SPEEDO_REDUND_OFFS (SOC_SPEEDO_REDUND_MSBIT - SOC_SPEEDO_MSBIT) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define SPEEDO_MULT 4 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define PROCESS_CORNERS_NUM 4 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2) 318c2ecf20Sopenharmony_ci#define SPEEDO_ID_SELECT_1(sku) \ 328c2ecf20Sopenharmony_ci (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \ 338c2ecf20Sopenharmony_ci ((sku) != 27) && ((sku) != 28)) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cienum { 368c2ecf20Sopenharmony_ci SPEEDO_ID_0, 378c2ecf20Sopenharmony_ci SPEEDO_ID_1, 388c2ecf20Sopenharmony_ci SPEEDO_ID_2, 398c2ecf20Sopenharmony_ci SPEEDO_ID_COUNT, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = { 438c2ecf20Sopenharmony_ci {315, 366, 420, UINT_MAX}, 448c2ecf20Sopenharmony_ci {303, 368, 419, UINT_MAX}, 458c2ecf20Sopenharmony_ci {316, 331, 383, UINT_MAX}, 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic const u32 __initconst soc_process_speedos[][PROCESS_CORNERS_NUM] = { 498c2ecf20Sopenharmony_ci {165, 195, 224, UINT_MAX}, 508c2ecf20Sopenharmony_ci {165, 195, 224, UINT_MAX}, 518c2ecf20Sopenharmony_ci {165, 195, 224, UINT_MAX}, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_civoid __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci u32 reg; 578c2ecf20Sopenharmony_ci u32 val; 588c2ecf20Sopenharmony_ci int i; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT); 618c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != SPEEDO_ID_COUNT); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (SPEEDO_ID_SELECT_0(sku_info->revision)) 648c2ecf20Sopenharmony_ci sku_info->soc_speedo_id = SPEEDO_ID_0; 658c2ecf20Sopenharmony_ci else if (SPEEDO_ID_SELECT_1(sku_info->sku_id)) 668c2ecf20Sopenharmony_ci sku_info->soc_speedo_id = SPEEDO_ID_1; 678c2ecf20Sopenharmony_ci else 688c2ecf20Sopenharmony_ci sku_info->soc_speedo_id = SPEEDO_ID_2; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci val = 0; 718c2ecf20Sopenharmony_ci for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) { 728c2ecf20Sopenharmony_ci reg = tegra_fuse_read_spare(i) | 738c2ecf20Sopenharmony_ci tegra_fuse_read_spare(i + CPU_SPEEDO_REDUND_OFFS); 748c2ecf20Sopenharmony_ci val = (val << 1) | (reg & 0x1); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci val = val * SPEEDO_MULT; 778c2ecf20Sopenharmony_ci pr_debug("Tegra CPU speedo value %u\n", val); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { 808c2ecf20Sopenharmony_ci if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i]) 818c2ecf20Sopenharmony_ci break; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci sku_info->cpu_process_id = i; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci val = 0; 868c2ecf20Sopenharmony_ci for (i = SOC_SPEEDO_MSBIT; i >= SOC_SPEEDO_LSBIT; i--) { 878c2ecf20Sopenharmony_ci reg = tegra_fuse_read_spare(i) | 888c2ecf20Sopenharmony_ci tegra_fuse_read_spare(i + SOC_SPEEDO_REDUND_OFFS); 898c2ecf20Sopenharmony_ci val = (val << 1) | (reg & 0x1); 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci val = val * SPEEDO_MULT; 928c2ecf20Sopenharmony_ci pr_debug("Core speedo value %u\n", val); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { 958c2ecf20Sopenharmony_ci if (val <= soc_process_speedos[sku_info->soc_speedo_id][i]) 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci sku_info->soc_process_id = i; 998c2ecf20Sopenharmony_ci} 100