xref: /linux/drivers/soc/tegra/fuse/speedo-tegra20.c (revision 7e939de1b2bb26496e4967e5346619700245e7c0)
1783c8f4cSPeter De Schrijver /*
2783c8f4cSPeter De Schrijver  * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
3783c8f4cSPeter De Schrijver  *
4783c8f4cSPeter De Schrijver  * This program is free software; you can redistribute it and/or modify it
5783c8f4cSPeter De Schrijver  * under the terms and conditions of the GNU General Public License,
6783c8f4cSPeter De Schrijver  * version 2, as published by the Free Software Foundation.
7783c8f4cSPeter De Schrijver  *
8783c8f4cSPeter De Schrijver  * This program is distributed in the hope it will be useful, but WITHOUT
9783c8f4cSPeter De Schrijver  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10783c8f4cSPeter De Schrijver  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11783c8f4cSPeter De Schrijver  * more details.
12783c8f4cSPeter De Schrijver  *
13783c8f4cSPeter De Schrijver  * You should have received a copy of the GNU General Public License
14783c8f4cSPeter De Schrijver  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15783c8f4cSPeter De Schrijver  */
16783c8f4cSPeter De Schrijver 
17783c8f4cSPeter De Schrijver #include <linux/bug.h>
18783c8f4cSPeter De Schrijver #include <linux/device.h>
19783c8f4cSPeter De Schrijver #include <linux/kernel.h>
20783c8f4cSPeter De Schrijver 
21783c8f4cSPeter De Schrijver #include <soc/tegra/fuse.h>
22783c8f4cSPeter De Schrijver 
23783c8f4cSPeter De Schrijver #include "fuse.h"
24783c8f4cSPeter De Schrijver 
25783c8f4cSPeter De Schrijver #define CPU_SPEEDO_LSBIT		20
26783c8f4cSPeter De Schrijver #define CPU_SPEEDO_MSBIT		29
27783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_LSBIT		30
28783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_MSBIT		39
29783c8f4cSPeter De Schrijver #define CPU_SPEEDO_REDUND_OFFS	(CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
30783c8f4cSPeter De Schrijver 
31783c8f4cSPeter De Schrijver #define CORE_SPEEDO_LSBIT		40
32783c8f4cSPeter De Schrijver #define CORE_SPEEDO_MSBIT		47
33783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_LSBIT	48
34783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_MSBIT	55
35783c8f4cSPeter De Schrijver #define CORE_SPEEDO_REDUND_OFFS	(CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT)
36783c8f4cSPeter De Schrijver 
37783c8f4cSPeter De Schrijver #define SPEEDO_MULT			4
38783c8f4cSPeter De Schrijver 
39783c8f4cSPeter De Schrijver #define PROCESS_CORNERS_NUM		4
40783c8f4cSPeter De Schrijver 
41783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_0(rev)		((rev) <= 2)
42783c8f4cSPeter De Schrijver #define SPEEDO_ID_SELECT_1(sku)		\
43783c8f4cSPeter De Schrijver 	(((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
44783c8f4cSPeter De Schrijver 	 ((sku) != 27) && ((sku) != 28))
45783c8f4cSPeter De Schrijver 
46783c8f4cSPeter De Schrijver enum {
47783c8f4cSPeter De Schrijver 	SPEEDO_ID_0,
48783c8f4cSPeter De Schrijver 	SPEEDO_ID_1,
49783c8f4cSPeter De Schrijver 	SPEEDO_ID_2,
50783c8f4cSPeter De Schrijver 	SPEEDO_ID_COUNT,
51783c8f4cSPeter De Schrijver };
52783c8f4cSPeter De Schrijver 
53783c8f4cSPeter De Schrijver static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
54783c8f4cSPeter De Schrijver 	{315, 366, 420, UINT_MAX},
55783c8f4cSPeter De Schrijver 	{303, 368, 419, UINT_MAX},
56783c8f4cSPeter De Schrijver 	{316, 331, 383, UINT_MAX},
57783c8f4cSPeter De Schrijver };
58783c8f4cSPeter De Schrijver 
59783c8f4cSPeter De Schrijver static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = {
60783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
61783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
62783c8f4cSPeter De Schrijver 	{165, 195, 224, UINT_MAX},
63783c8f4cSPeter De Schrijver };
64783c8f4cSPeter De Schrijver 
65783c8f4cSPeter De Schrijver void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
66783c8f4cSPeter De Schrijver {
67783c8f4cSPeter De Schrijver 	u32 reg;
68783c8f4cSPeter De Schrijver 	u32 val;
69783c8f4cSPeter De Schrijver 	int i;
70783c8f4cSPeter De Schrijver 
71783c8f4cSPeter De Schrijver 	BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
72783c8f4cSPeter De Schrijver 	BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT);
73783c8f4cSPeter De Schrijver 
74783c8f4cSPeter De Schrijver 	if (SPEEDO_ID_SELECT_0(sku_info->revision))
75783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_0;
76783c8f4cSPeter De Schrijver 	else if (SPEEDO_ID_SELECT_1(sku_info->sku_id))
77783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_1;
78783c8f4cSPeter De Schrijver 	else
79783c8f4cSPeter De Schrijver 		sku_info->soc_speedo_id = SPEEDO_ID_2;
80783c8f4cSPeter De Schrijver 
81783c8f4cSPeter De Schrijver 	val = 0;
82783c8f4cSPeter De Schrijver 	for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
83*7e939de1SThierry Reding 		reg = tegra_fuse_read_spare(i) |
84*7e939de1SThierry Reding 			tegra_fuse_read_spare(i + CPU_SPEEDO_REDUND_OFFS);
85783c8f4cSPeter De Schrijver 		val = (val << 1) | (reg & 0x1);
86783c8f4cSPeter De Schrijver 	}
87783c8f4cSPeter De Schrijver 	val = val * SPEEDO_MULT;
88783c8f4cSPeter De Schrijver 	pr_debug("Tegra CPU speedo value %u\n", val);
89783c8f4cSPeter De Schrijver 
90783c8f4cSPeter De Schrijver 	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
91783c8f4cSPeter De Schrijver 		if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i])
92783c8f4cSPeter De Schrijver 			break;
93783c8f4cSPeter De Schrijver 	}
94783c8f4cSPeter De Schrijver 	sku_info->cpu_process_id = i;
95783c8f4cSPeter De Schrijver 
96783c8f4cSPeter De Schrijver 	val = 0;
97783c8f4cSPeter De Schrijver 	for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) {
98*7e939de1SThierry Reding 		reg = tegra_fuse_read_spare(i) |
99*7e939de1SThierry Reding 			tegra_fuse_read_spare(i + CORE_SPEEDO_REDUND_OFFS);
100783c8f4cSPeter De Schrijver 		val = (val << 1) | (reg & 0x1);
101783c8f4cSPeter De Schrijver 	}
102783c8f4cSPeter De Schrijver 	val = val * SPEEDO_MULT;
103783c8f4cSPeter De Schrijver 	pr_debug("Core speedo value %u\n", val);
104783c8f4cSPeter De Schrijver 
105783c8f4cSPeter De Schrijver 	for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
106783c8f4cSPeter De Schrijver 		if (val <= core_process_speedos[sku_info->soc_speedo_id][i])
107783c8f4cSPeter De Schrijver 			break;
108783c8f4cSPeter De Schrijver 	}
109783c8f4cSPeter De Schrijver 	sku_info->core_process_id = i;
110783c8f4cSPeter De Schrijver }
111