Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / soc / tegra / fuse / speedo-tegra30.c
1 /*
2  * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/bug.h>
18 #include <linux/device.h>
19 #include <linux/kernel.h>
20
21 #include <soc/tegra/fuse.h>
22
23 #include "fuse.h"
24
25 #define CORE_PROCESS_CORNERS    1
26 #define CPU_PROCESS_CORNERS     6
27
28 #define FUSE_SPEEDO_CALIB_0     0x14
29 #define FUSE_PACKAGE_INFO       0XFC
30 #define FUSE_TEST_PROG_VER      0X28
31
32 #define G_SPEEDO_BIT_MINUS1     58
33 #define G_SPEEDO_BIT_MINUS1_R   59
34 #define G_SPEEDO_BIT_MINUS2     60
35 #define G_SPEEDO_BIT_MINUS2_R   61
36 #define LP_SPEEDO_BIT_MINUS1    62
37 #define LP_SPEEDO_BIT_MINUS1_R  63
38 #define LP_SPEEDO_BIT_MINUS2    64
39 #define LP_SPEEDO_BIT_MINUS2_R  65
40
41 enum {
42         THRESHOLD_INDEX_0,
43         THRESHOLD_INDEX_1,
44         THRESHOLD_INDEX_2,
45         THRESHOLD_INDEX_3,
46         THRESHOLD_INDEX_4,
47         THRESHOLD_INDEX_5,
48         THRESHOLD_INDEX_6,
49         THRESHOLD_INDEX_7,
50         THRESHOLD_INDEX_8,
51         THRESHOLD_INDEX_9,
52         THRESHOLD_INDEX_10,
53         THRESHOLD_INDEX_11,
54         THRESHOLD_INDEX_COUNT,
55 };
56
57 static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = {
58         {180},
59         {170},
60         {195},
61         {180},
62         {168},
63         {192},
64         {180},
65         {170},
66         {195},
67         {180},
68         {180},
69         {180},
70 };
71
72 static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
73         {306, 338, 360, 376, UINT_MAX},
74         {295, 336, 358, 375, UINT_MAX},
75         {325, 325, 358, 375, UINT_MAX},
76         {325, 325, 358, 375, UINT_MAX},
77         {292, 324, 348, 364, UINT_MAX},
78         {324, 324, 348, 364, UINT_MAX},
79         {324, 324, 348, 364, UINT_MAX},
80         {295, 336, 358, 375, UINT_MAX},
81         {358, 358, 358, 358, 397, UINT_MAX},
82         {364, 364, 364, 364, 397, UINT_MAX},
83         {295, 336, 358, 375, 391, UINT_MAX},
84         {295, 336, 358, 375, 391, UINT_MAX},
85 };
86
87 static int threshold_index __initdata;
88
89 static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
90 {
91         u32 reg;
92         int ate_ver;
93         int bit_minus1;
94         int bit_minus2;
95
96         reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0);
97
98         *speedo_lp = (reg & 0xFFFF) * 4;
99         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
100
101         ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER);
102         pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
103
104         if (ate_ver >= 26) {
105                 bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1);
106                 bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R);
107                 bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2);
108                 bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R);
109                 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
110
111                 bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1);
112                 bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R);
113                 bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2);
114                 bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R);
115                 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
116         } else {
117                 *speedo_lp |= 0x3;
118                 *speedo_g |= 0x3;
119         }
120 }
121
122 static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
123 {
124         int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
125
126         switch (sku_info->revision) {
127         case TEGRA_REVISION_A01:
128                 sku_info->cpu_speedo_id = 0;
129                 sku_info->soc_speedo_id = 0;
130                 threshold_index = THRESHOLD_INDEX_0;
131                 break;
132         case TEGRA_REVISION_A02:
133         case TEGRA_REVISION_A03:
134                 switch (sku_info->sku_id) {
135                 case 0x87:
136                 case 0x82:
137                         sku_info->cpu_speedo_id = 1;
138                         sku_info->soc_speedo_id = 1;
139                         threshold_index = THRESHOLD_INDEX_1;
140                         break;
141                 case 0x81:
142                         switch (package_id) {
143                         case 1:
144                                 sku_info->cpu_speedo_id = 2;
145                                 sku_info->soc_speedo_id = 2;
146                                 threshold_index = THRESHOLD_INDEX_2;
147                                 break;
148                         case 2:
149                                 sku_info->cpu_speedo_id = 4;
150                                 sku_info->soc_speedo_id = 1;
151                                 threshold_index = THRESHOLD_INDEX_7;
152                                 break;
153                         default:
154                                 pr_err("Tegra Unknown pkg %d\n", package_id);
155                                 break;
156                         }
157                         break;
158                 case 0x80:
159                         switch (package_id) {
160                         case 1:
161                                 sku_info->cpu_speedo_id = 5;
162                                 sku_info->soc_speedo_id = 2;
163                                 threshold_index = THRESHOLD_INDEX_8;
164                                 break;
165                         case 2:
166                                 sku_info->cpu_speedo_id = 6;
167                                 sku_info->soc_speedo_id = 2;
168                                 threshold_index = THRESHOLD_INDEX_9;
169                                 break;
170                         default:
171                                 pr_err("Tegra Unknown pkg %d\n", package_id);
172                                 break;
173                         }
174                         break;
175                 case 0x83:
176                         switch (package_id) {
177                         case 1:
178                                 sku_info->cpu_speedo_id = 7;
179                                 sku_info->soc_speedo_id = 1;
180                                 threshold_index = THRESHOLD_INDEX_10;
181                                 break;
182                         case 2:
183                                 sku_info->cpu_speedo_id = 3;
184                                 sku_info->soc_speedo_id = 2;
185                                 threshold_index = THRESHOLD_INDEX_3;
186                                 break;
187                         default:
188                                 pr_err("Tegra Unknown pkg %d\n", package_id);
189                                 break;
190                         }
191                         break;
192                 case 0x8F:
193                         sku_info->cpu_speedo_id = 8;
194                         sku_info->soc_speedo_id = 1;
195                         threshold_index = THRESHOLD_INDEX_11;
196                         break;
197                 case 0x08:
198                         sku_info->cpu_speedo_id = 1;
199                         sku_info->soc_speedo_id = 1;
200                         threshold_index = THRESHOLD_INDEX_4;
201                         break;
202                 case 0x02:
203                         sku_info->cpu_speedo_id = 2;
204                         sku_info->soc_speedo_id = 2;
205                         threshold_index = THRESHOLD_INDEX_5;
206                         break;
207                 case 0x04:
208                         sku_info->cpu_speedo_id = 3;
209                         sku_info->soc_speedo_id = 2;
210                         threshold_index = THRESHOLD_INDEX_6;
211                         break;
212                 case 0:
213                         switch (package_id) {
214                         case 1:
215                                 sku_info->cpu_speedo_id = 2;
216                                 sku_info->soc_speedo_id = 2;
217                                 threshold_index = THRESHOLD_INDEX_2;
218                                 break;
219                         case 2:
220                                 sku_info->cpu_speedo_id = 3;
221                                 sku_info->soc_speedo_id = 2;
222                                 threshold_index = THRESHOLD_INDEX_3;
223                                 break;
224                         default:
225                                 pr_err("Tegra Unknown pkg %d\n", package_id);
226                                 break;
227                         }
228                         break;
229                 default:
230                         pr_warn("Tegra Unknown SKU %d\n", sku_info->sku_id);
231                         sku_info->cpu_speedo_id = 0;
232                         sku_info->soc_speedo_id = 0;
233                         threshold_index = THRESHOLD_INDEX_0;
234                         break;
235                 }
236                 break;
237         default:
238                 pr_warn("Tegra Unknown chip rev %d\n", sku_info->revision);
239                 sku_info->cpu_speedo_id = 0;
240                 sku_info->soc_speedo_id = 0;
241                 threshold_index = THRESHOLD_INDEX_0;
242                 break;
243         }
244 }
245
246 void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
247 {
248         u32 cpu_speedo_val;
249         u32 core_speedo_val;
250         int i;
251
252         BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
253                         THRESHOLD_INDEX_COUNT);
254         BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
255                         THRESHOLD_INDEX_COUNT);
256
257
258         rev_sku_to_speedo_ids(sku_info);
259         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
260         pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
261         pr_debug("Tegra Core speedo value %u\n", core_speedo_val);
262
263         for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
264                 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
265                         break;
266         }
267         sku_info->cpu_process_id = i - 1;
268
269         if (sku_info->cpu_process_id == -1) {
270                 pr_warn("Tegra CPU speedo value %3d out of range",
271                          cpu_speedo_val);
272                 sku_info->cpu_process_id = 0;
273                 sku_info->cpu_speedo_id = 1;
274         }
275
276         for (i = 0; i < CORE_PROCESS_CORNERS; i++) {
277                 if (core_speedo_val < core_process_speedos[threshold_index][i])
278                         break;
279         }
280         sku_info->core_process_id = i - 1;
281
282         if (sku_info->core_process_id == -1) {
283                 pr_warn("Tegra CORE speedo value %3d out of range",
284                                  core_speedo_val);
285                 sku_info->core_process_id = 0;
286                 sku_info->soc_speedo_id = 1;
287         }
288 }