xref: /linux/drivers/soc/tegra/fuse/speedo-tegra20.c (revision 783c8f4c84451bc444e314a71b447239c6ef6fd9)
1*783c8f4cSPeter De Schrijver /*
2*783c8f4cSPeter De Schrijver  * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
3*783c8f4cSPeter De Schrijver  *
4*783c8f4cSPeter De Schrijver  * This program is free software; you can redistribute it and/or modify it
5*783c8f4cSPeter De Schrijver  * under the terms and conditions of the GNU General Public License,
6*783c8f4cSPeter De Schrijver  * version 2, as published by the Free Software Foundation.
7*783c8f4cSPeter De Schrijver  *
8*783c8f4cSPeter De Schrijver  * This program is distributed in the hope it will be useful, but WITHOUT
9*783c8f4cSPeter De Schrijver  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10*783c8f4cSPeter De Schrijver  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11*783c8f4cSPeter De Schrijver  * more details.
12*783c8f4cSPeter De Schrijver  *
13*783c8f4cSPeter De Schrijver  * You should have received a copy of the GNU General Public License
14*783c8f4cSPeter De Schrijver  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15*783c8f4cSPeter De Schrijver  */
16*783c8f4cSPeter De Schrijver 
17*783c8f4cSPeter De Schrijver #include <linux/bug.h>
18*783c8f4cSPeter De Schrijver #include <linux/device.h>
19*783c8f4cSPeter De Schrijver #include <linux/kernel.h>
20*783c8f4cSPeter De Schrijver 
21*783c8f4cSPeter De Schrijver #include <soc/tegra/fuse.h>
22*783c8f4cSPeter De Schrijver 
23*783c8f4cSPeter De Schrijver #include "fuse.h"
24*783c8f4cSPeter De Schrijver 
25*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_LSBIT		20
26*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_MSBIT		29
27*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_LSBIT		30
28*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_MSBIT		39
29*783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_OFFS	(CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
30*783c8f4cSPeter De Schrijver 
31*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_LSBIT		40
32*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_MSBIT		47
33*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_LSBIT	48
34*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_MSBIT	55
35*783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_OFFS	(CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
36*783c8f4cSPeter De Schrijver 
37*783c8f4cSPeter De Schrijver #define SPEEDO_MULT			4
38*783c8f4cSPeter De Schrijver 
39*783c8f4cSPeter De Schrijver #define PROCESS_CORNERS_NUM		4
40*783c8f4cSPeter De Schrijver 
41*783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_0(rev)		((rev) <= 2)
42*783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_1(sku)		\
43*783c8f4cSPeter De Schrijver 	(((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
44*783c8f4cSPeter De Schrijver 	 ((sku) != 27) && ((sku) != 28))
45*783c8f4cSPeter De Schrijver 
46*783c8f4cSPeter De Schrijver enum {
47*783c8f4cSPeter De Schrijver 	SPEEDO_ID_0,
48*783c8f4cSPeter De Schrijver 	SPEEDO_ID_1,
49*783c8f4cSPeter De Schrijver 	SPEEDO_ID_2,
50*783c8f4cSPeter De Schrijver 	SPEEDO_ID_COUNT,
51*783c8f4cSPeter De Schrijver };
52*783c8f4cSPeter De Schrijver 
53*783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
54*783c8f4cSPeter De Schrijver 	{315, 366, 420, UINT_MAX},
55*783c8f4cSPeter De Schrijver 	{303, 368, 419, UINT_MAX},
56*783c8f4cSPeter De Schrijver 	{316, 331, 383, UINT_MAX},
57*783c8f4cSPeter De Schrijver };
58*783c8f4cSPeter De Schrijver 
59*783c8f4cSPeter De Schrijver static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = {
60*783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
61*783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
62*783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
63*783c8f4cSPeter De Schrijver };
64*783c8f4cSPeter De Schrijver 
65*783c8f4cSPeter De Schrijver void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
66*783c8f4cSPeter De Schrijver {
67*783c8f4cSPeter De Schrijver 	u32 reg;
68*783c8f4cSPeter De Schrijver 	u32 val;
69*783c8f4cSPeter De Schrijver 	int i;
70*783c8f4cSPeter De Schrijver 
71*783c8f4cSPeter De Schrijver 	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
72*783c8f4cSPeter De Schrijver 	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
73*783c8f4cSPeter De Schrijver 
74*783c8f4cSPeter De Schrijver 	if (SPEEDO_ID_SELECT_0(sku_info->revision))
75*783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_0;
76*783c8f4cSPeter De Schrijver 	else if (SPEEDO_ID_SELECT_1(sku_info->sku_id))
77*783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_1;
78*783c8f4cSPeter De Schrijver 	else
79*783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_2;
80*783c8f4cSPeter De Schrijver 
81*783c8f4cSPeter De Schrijver 	val = 0;
82*783c8f4cSPeter De Schrijver 	for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
83*783c8f4cSPeter De Schrijver 		reg = tegra20_spare_fuse_early(i) |
84*783c8f4cSPeter De Schrijver 			tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS);
85*783c8f4cSPeter De Schrijver 		val = (val << 1) | (reg & 0x1);
86*783c8f4cSPeter De Schrijver 	}
87*783c8f4cSPeter De Schrijver 	val = val * SPEEDO_MULT;
88*783c8f4cSPeter De Schrijver 	pr_debug("Tegra CPU speedo value %u\n", val);
89*783c8f4cSPeter De Schrijver 
90*783c8f4cSPeter De Schrijver 	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
91*783c8f4cSPeter De Schrijver 		if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i])
92*783c8f4cSPeter De Schrijver 			break;
93*783c8f4cSPeter De Schrijver 	}
94*783c8f4cSPeter De Schrijver 	sku_info->cpu_process_id = i;
95*783c8f4cSPeter De Schrijver 
96*783c8f4cSPeter De Schrijver 	val = 0;
97*783c8f4cSPeter De Schrijver 	for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
98*783c8f4cSPeter De Schrijver 		reg = tegra20_spare_fuse_early(i) |
99*783c8f4cSPeter De Schrijver 			tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS);
100*783c8f4cSPeter De Schrijver 		val = (val << 1) | (reg & 0x1);
101*783c8f4cSPeter De Schrijver 	}
102*783c8f4cSPeter De Schrijver 	val = val * SPEEDO_MULT;
103*783c8f4cSPeter De Schrijver 	pr_debug("Core speedo value %u\n", val);
104*783c8f4cSPeter De Schrijver 
105*783c8f4cSPeter De Schrijver 	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
106*783c8f4cSPeter De Schrijver 		if (val <= core_process_speedos[sku_info->soc_speedo_id][i])
107*783c8f4cSPeter De Schrijver 			break;
108*783c8f4cSPeter De Schrijver 	}
109*783c8f4cSPeter De Schrijver 	sku_info->core_process_id = i;
110*783c8f4cSPeter De Schrijver }
111