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