xref: /linux/drivers/soc/tegra/fuse/speedo-tegra124.c (revision ecb41832bd2a7a3f8ac93527cec5e51e3827daed)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2013-2014, NVIDIA CORPORATION.  All rights reserved.
4  */
5 
6 #include <linux/device.h>
7 #include <linux/kernel.h>
8 #include <linux/bug.h>
9 
10 #include <soc/tegra/fuse.h>
11 
12 #include "fuse.h"
13 
14 #define CPU_PROCESS_CORNERS	2
15 #define GPU_PROCESS_CORNERS	2
16 #define SOC_PROCESS_CORNERS	2
17 
18 #define FUSE_CPU_SPEEDO_0	0x14
19 #define FUSE_CPU_SPEEDO_1	0x2c
20 #define FUSE_CPU_SPEEDO_2	0x30
21 #define FUSE_SOC_SPEEDO_0	0x34
22 #define FUSE_SOC_SPEEDO_1	0x38
23 #define FUSE_SOC_SPEEDO_2	0x3c
24 #define FUSE_CPU_IDDQ		0x18
25 #define FUSE_SOC_IDDQ		0x40
26 #define FUSE_GPU_IDDQ		0x128
27 #define FUSE_FT_REV		0x28
28 
29 enum {
30 	THRESHOLD_INDEX_0,
31 	THRESHOLD_INDEX_1,
32 	THRESHOLD_INDEX_COUNT,
33 };
34 
35 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
36 	{2190,	UINT_MAX},
37 	{0,	UINT_MAX},
38 };
39 
40 static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
41 	{1965,	UINT_MAX},
42 	{0,	UINT_MAX},
43 };
44 
45 static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
46 	{2101,	UINT_MAX},
47 	{0,	UINT_MAX},
48 };
49 
50 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
51 					 int *threshold)
52 {
53 	int sku = sku_info->sku_id;
54 
55 	/* Assign to default */
56 	sku_info->cpu_speedo_id = 0;
57 	sku_info->soc_speedo_id = 0;
58 	sku_info->gpu_speedo_id = 0;
59 	*threshold = THRESHOLD_INDEX_0;
60 
61 	switch (sku) {
62 	case 0x00: /* Eng sku */
63 	case 0x0F:
64 	case 0x23:
65 		/* Using the default */
66 		break;
67 	case 0x83:
68 		sku_info->cpu_speedo_id = 2;
69 		break;
70 
71 	case 0x1F:
72 	case 0x87:
73 	case 0x27:
74 		sku_info->cpu_speedo_id = 2;
75 		sku_info->soc_speedo_id = 0;
76 		sku_info->gpu_speedo_id = 1;
77 		*threshold = THRESHOLD_INDEX_0;
78 		break;
79 	case 0x81:
80 	case 0x21:
81 	case 0x07:
82 		sku_info->cpu_speedo_id = 1;
83 		sku_info->soc_speedo_id = 1;
84 		sku_info->gpu_speedo_id = 1;
85 		*threshold = THRESHOLD_INDEX_1;
86 		break;
87 	case 0x49:
88 	case 0x4A:
89 	case 0x48:
90 		sku_info->cpu_speedo_id = 4;
91 		sku_info->soc_speedo_id = 2;
92 		sku_info->gpu_speedo_id = 3;
93 		*threshold = THRESHOLD_INDEX_1;
94 		break;
95 	default:
96 		pr_err("Tegra Unknown SKU %d\n", sku);
97 		/* Using the default for the error case */
98 		break;
99 	}
100 }
101 
102 void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
103 {
104 	int i, threshold, cpu_speedo_0_value, soc_speedo_0_value;
105 	int cpu_iddq_value, gpu_iddq_value, soc_iddq_value;
106 
107 	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
108 			THRESHOLD_INDEX_COUNT);
109 	BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
110 			THRESHOLD_INDEX_COUNT);
111 	BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
112 			THRESHOLD_INDEX_COUNT);
113 
114 	cpu_speedo_0_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0);
115 
116 	/* GPU Speedo is stored in CPU_SPEEDO_2 */
117 	sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
118 
119 	soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
120 
121 	cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
122 	soc_iddq_value = tegra_fuse_read_early(FUSE_SOC_IDDQ);
123 	gpu_iddq_value = tegra_fuse_read_early(FUSE_GPU_IDDQ);
124 
125 	sku_info->cpu_speedo_value = cpu_speedo_0_value;
126 
127 	if (sku_info->cpu_speedo_value == 0) {
128 		pr_warn("Tegra Warning: Speedo value not fused.\n");
129 		WARN_ON(1);
130 		return;
131 	}
132 
133 	rev_sku_to_speedo_ids(sku_info, &threshold);
134 
135 	sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
136 
137 	for (i = 0; i < GPU_PROCESS_CORNERS; i++)
138 		if (sku_info->gpu_speedo_value <
139 			gpu_process_speedos[threshold][i])
140 			break;
141 	sku_info->gpu_process_id = i;
142 
143 	for (i = 0; i < CPU_PROCESS_CORNERS; i++)
144 		if (sku_info->cpu_speedo_value <
145 			cpu_process_speedos[threshold][i])
146 				break;
147 	sku_info->cpu_process_id = i;
148 
149 	for (i = 0; i < SOC_PROCESS_CORNERS; i++)
150 		if (soc_speedo_0_value <
151 			soc_process_speedos[threshold][i])
152 			break;
153 	sku_info->soc_process_id = i;
154 
155 	pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
156 		 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
157 }
158