18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2013-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 SOC_PROCESS_CORNERS	2
158c2ecf20Sopenharmony_ci#define CPU_PROCESS_CORNERS	2
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cienum {
188c2ecf20Sopenharmony_ci	THRESHOLD_INDEX_0,
198c2ecf20Sopenharmony_ci	THRESHOLD_INDEX_1,
208c2ecf20Sopenharmony_ci	THRESHOLD_INDEX_COUNT,
218c2ecf20Sopenharmony_ci};
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
248c2ecf20Sopenharmony_ci	{1123,     UINT_MAX},
258c2ecf20Sopenharmony_ci	{0,        UINT_MAX},
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
298c2ecf20Sopenharmony_ci	{1695,     UINT_MAX},
308c2ecf20Sopenharmony_ci	{0,        UINT_MAX},
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
348c2ecf20Sopenharmony_ci					 int *threshold)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	u32 tmp;
378c2ecf20Sopenharmony_ci	u32 sku = sku_info->sku_id;
388c2ecf20Sopenharmony_ci	enum tegra_revision rev = sku_info->revision;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	switch (sku) {
418c2ecf20Sopenharmony_ci	case 0x00:
428c2ecf20Sopenharmony_ci	case 0x10:
438c2ecf20Sopenharmony_ci	case 0x05:
448c2ecf20Sopenharmony_ci	case 0x06:
458c2ecf20Sopenharmony_ci		sku_info->cpu_speedo_id = 1;
468c2ecf20Sopenharmony_ci		sku_info->soc_speedo_id = 0;
478c2ecf20Sopenharmony_ci		*threshold = THRESHOLD_INDEX_0;
488c2ecf20Sopenharmony_ci		break;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	case 0x03:
518c2ecf20Sopenharmony_ci	case 0x04:
528c2ecf20Sopenharmony_ci		sku_info->cpu_speedo_id = 2;
538c2ecf20Sopenharmony_ci		sku_info->soc_speedo_id = 1;
548c2ecf20Sopenharmony_ci		*threshold = THRESHOLD_INDEX_1;
558c2ecf20Sopenharmony_ci		break;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	default:
588c2ecf20Sopenharmony_ci		pr_err("Tegra Unknown SKU %d\n", sku);
598c2ecf20Sopenharmony_ci		sku_info->cpu_speedo_id = 0;
608c2ecf20Sopenharmony_ci		sku_info->soc_speedo_id = 0;
618c2ecf20Sopenharmony_ci		*threshold = THRESHOLD_INDEX_0;
628c2ecf20Sopenharmony_ci		break;
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	if (rev == TEGRA_REVISION_A01) {
668c2ecf20Sopenharmony_ci		tmp = tegra_fuse_read_early(0x270) << 1;
678c2ecf20Sopenharmony_ci		tmp |= tegra_fuse_read_early(0x26c);
688c2ecf20Sopenharmony_ci		if (!tmp)
698c2ecf20Sopenharmony_ci			sku_info->cpu_speedo_id = 0;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_civoid __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	u32 cpu_speedo_val;
768c2ecf20Sopenharmony_ci	u32 soc_speedo_val;
778c2ecf20Sopenharmony_ci	int threshold;
788c2ecf20Sopenharmony_ci	int i;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
818c2ecf20Sopenharmony_ci			THRESHOLD_INDEX_COUNT);
828c2ecf20Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
838c2ecf20Sopenharmony_ci			THRESHOLD_INDEX_COUNT);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	rev_sku_to_speedo_ids(sku_info, &threshold);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	cpu_speedo_val = tegra_fuse_read_early(0x12c) + 1024;
888c2ecf20Sopenharmony_ci	soc_speedo_val = tegra_fuse_read_early(0x134);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	for (i = 0; i < CPU_PROCESS_CORNERS; i++)
918c2ecf20Sopenharmony_ci		if (cpu_speedo_val < cpu_process_speedos[threshold][i])
928c2ecf20Sopenharmony_ci			break;
938c2ecf20Sopenharmony_ci	sku_info->cpu_process_id = i;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	for (i = 0; i < SOC_PROCESS_CORNERS; i++)
968c2ecf20Sopenharmony_ci		if (soc_speedo_val < soc_process_speedos[threshold][i])
978c2ecf20Sopenharmony_ci			break;
988c2ecf20Sopenharmony_ci	sku_info->soc_process_id = i;
998c2ecf20Sopenharmony_ci}
100