ARM: Tegra: dvfs: Fix speedo value thresholds for T30S, T30
[linux-2.6.git] / arch / arm / mach-tegra / tegra3_speedo.c
1 /*
2  * arch/arm/mach-tegra/tegra3_speedo.c
3  *
4  * Copyright (c) 2011, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <mach/iomap.h>
25
26 #include "fuse.h"
27
28 #define CORE_PROCESS_CORNERS_NUM        1
29 #define CPU_PROCESS_CORNERS_NUM         4
30
31 #define FUSE_SPEEDO_CALIB_0     0x114
32 #define FUSE_PACKAGE_INFO       0X1FC
33
34 /* Maximum speedo levels for each core process corner */
35 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
36 /* proc_id 0 */
37         {180}, /* threshold_index 0: soc_speedo_id 0: any A01 */
38
39 /* T30 family */
40         {183}, /* threshold_index 1: soc_speedo_id 1: AP30 */
41         {197}, /* threshold_index 2: soc_speedo_id 2: T30  */
42         {197}, /* threshold_index 3: soc_speedo_id 2: T30S */
43
44 /* Characterization SKUs */
45         {170}, /* threshold_index 4: soc_speedo_id 1: AP30 char */
46         {195}, /* threshold_index 5: soc_speedo_id 2: T30  char */
47         {185}, /* threshold_index 6: soc_speedo_id 2: T30S char */
48
49 /* T33 family: Numbers cloned from T30 family; FIXME: adjust these later */
50         {183}, /* threshold_index 7: soc_speedo_id = 1 - AP33 */
51         {197}, /* threshold_index 8: soc_speedo_id = 2 - T33  */
52         {197}, /* threshold_index 9: soc_speedo_id = 2 - T33S */
53 };
54
55 /* Maximum speedo levels for each CPU process corner */
56 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
57 /* proc_id 0    1    2    3 */
58         {306, 338, 360, 376}, /* threshold_index 0: cpu_speedo_id 0: any A01 */
59
60 /* T30 family */
61         {305, 336, 358, 375}, /* threshold_index 1: cpu_speedo_id 1: AP30 */
62         {336, 336, 358, 375}, /* threshold_index 2: cpu_speedo_id 2: T30  */
63         {336, 336, 358, 375}, /* threshold_index 3: cpu_speedo_id 3: T30S */
64
65 /* Characterization SKUs */
66         {295, 326, 348, 364}, /* threshold_index 4: cpu_speedo_id 1: AP30char */
67         {326, 326, 348, 364}, /* threshold_index 5: cpu_speedo_id 2: T30char  */
68         {326, 326, 348, 364}, /* threshold_index 6: cpu_speedo_id 3: T30Schar */
69
70 /* T33 family: Numbers cloned from T30 family; FIXME: adjust these later */
71         {376, 376, 376, 376}, /* threshold_FIXME 7: cpu_speedo_id = 1 - AP33 */
72         {376, 376, 376, 376}, /* threshold_index 8: cpu_speedo_id = 2 - T33  */
73         {376, 376, 376, 376}, /* threshold_index 9: cpu_speedo_id = 3 - T33S */
74 };
75
76 /*
77  * Common speedo_value array threshold index for both core_process_speedos and
78  * cpu_process_speedos arrays. Make sure these two arrays are always in synch.
79  */
80 static int threshold_index;
81
82 static int cpu_process_id;
83 static int core_process_id;
84 static int cpu_speedo_id;
85 static int soc_speedo_id;
86 static int package_id;
87
88 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
89 {
90         u32 reg;
91
92         BUG_ON(!speedo_g || !speedo_lp);
93         reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
94
95         /* Speedo LP = Lower 16-bits Multiplied by 4 */
96         *speedo_lp = (reg & 0xFFFF) * 4;
97
98         /* Speedo G = Upper 16-bits Multiplied by 4 */
99         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
100 }
101
102 static void rev_sku_to_speedo_ids(int rev, int sku)
103 {
104         switch (rev) {
105         case TEGRA_REVISION_A01: /* any A01 */
106                 cpu_speedo_id = 0;
107                 soc_speedo_id = 0;
108                 threshold_index = 0;
109                 break;
110
111         case TEGRA_REVISION_A02:
112         case TEGRA_REVISION_A03:
113                 switch (sku) {
114                 case 0x87: /* AP30 */
115                         cpu_speedo_id = 1;
116                         soc_speedo_id = 1;
117                         threshold_index = 1;
118                         break;
119
120                 case 0x81: /* T30 */
121                         switch (package_id) {
122                         case 1: /* MID => T30 */
123                                 cpu_speedo_id = 2;
124                                 soc_speedo_id = 2;
125                                 threshold_index = 2;
126                                 break;
127                         case 2: /* DSC => AP33 */
128                                 cpu_speedo_id = 1;
129                                 soc_speedo_id = 1;
130                                 threshold_index = 7;
131                                 break;
132                         default:
133                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
134                                        package_id);
135                                 BUG();
136                                 break;
137                         }
138                         break;
139
140                 case 0x80: /* T33 or T33S */
141                         switch (package_id) {
142                         case 1: /* MID => T33 */
143                                 cpu_speedo_id = 2;
144                                 soc_speedo_id = 2;
145                                 threshold_index = 8;
146                                 break;
147                         case 2: /* DSC => T33S */
148                                 cpu_speedo_id = 3;
149                                 soc_speedo_id = 2;
150                                 threshold_index = 9;
151                                 break;
152                         default:
153                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
154                                        package_id);
155                                 BUG();
156                                 break;
157                         }
158                         break;
159
160                 case 0x83: /* T30S */
161                         cpu_speedo_id = 3;
162                         soc_speedo_id = 2;
163                         threshold_index = 3;
164                         break;
165
166 /* Characterization SKUs */
167                 case 0x08: /* AP30 char */
168                         cpu_speedo_id = 1;
169                         soc_speedo_id = 1;
170                         threshold_index = 4;
171                         break;
172                 case 0x02: /* T30 char */
173                         cpu_speedo_id = 2;
174                         soc_speedo_id = 2;
175                         threshold_index = 5;
176                         break;
177                 case 0x04: /* T30S char */
178                         cpu_speedo_id = 3;
179                         soc_speedo_id = 2;
180                         threshold_index = 6;
181                         break;
182
183                 case 0:    /* ENG - check package_id */
184                         pr_info("Tegra3 ENG SKU: Checking package_id\n");
185                         switch (package_id) {
186                         case 1: /* MID => assume T30 */
187                                 cpu_speedo_id = 2;
188                                 soc_speedo_id = 2;
189                                 threshold_index = 2;
190                                 break;
191                         case 2: /* DSC => assume T30S */
192                                 cpu_speedo_id = 3;
193                                 soc_speedo_id = 2;
194                                 threshold_index = 3;
195                                 break;
196                         default:
197                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
198                                        package_id);
199                                 BUG();
200                                 break;
201                         }
202                         break;
203
204                 default:
205                         /* FIXME: replace with BUG() when all SKU's valid */
206                         pr_err("Tegra3 Rev-A02: Unknown SKU %d\n", sku);
207                         cpu_speedo_id = 0;
208                         soc_speedo_id = 0;
209                         threshold_index = 0;
210                         break;
211                 }
212                 break;
213         default:
214                 BUG();
215                 break;
216         }
217 }
218
219 void tegra_init_speedo_data(void)
220 {
221         u32 cpu_speedo_val, core_speedo_val;
222         int iv;
223
224         /* Package info: 4 bits - 0,3:reserved 1:MID 2:DSC */
225         package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
226
227         /* Arrays must be of equal size - each index corresponds to a SKU */
228         BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
229                ARRAY_SIZE(core_process_speedos));
230
231         rev_sku_to_speedo_ids(tegra_get_revision(), tegra_sku_id());
232         BUG_ON(threshold_index >= ARRAY_SIZE(cpu_process_speedos));
233
234         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
235         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
236         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
237
238         for (iv = 0; iv < CPU_PROCESS_CORNERS_NUM; iv++) {
239                 if (cpu_speedo_val <
240                     cpu_process_speedos[threshold_index][iv]) {
241                         break;
242                 }
243         }
244         cpu_process_id = iv -1;
245
246         if (cpu_process_id == -1) {
247                 pr_err("****************************************************");
248                 pr_err("****************************************************");
249                 pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
250                        cpu_speedo_val);
251                 pr_err("****************************************************");
252                 pr_err("****************************************************");
253
254                 cpu_process_id = INVALID_PROCESS_ID;
255                 cpu_speedo_id = 0;
256         }
257
258         for (iv = 0; iv < CORE_PROCESS_CORNERS_NUM; iv++) {
259                 if (core_speedo_val <
260                     core_process_speedos[threshold_index][iv]) {
261                         break;
262                 }
263         }
264         core_process_id = iv -1;
265
266         if (core_process_id == -1) {
267                 pr_err("****************************************************");
268                 pr_err("****************************************************");
269                 pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
270                        core_speedo_val);
271                 pr_err("****************************************************");
272                 pr_err("****************************************************");
273
274                 core_process_id = INVALID_PROCESS_ID;
275                 soc_speedo_id = 0;
276         }
277
278         pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
279                  cpu_speedo_id, soc_speedo_id);
280 }
281
282 int tegra_cpu_process_id(void)
283 {
284         /* FIXME: remove when ready to deprecate invalid process-id boards */
285         if (cpu_process_id == INVALID_PROCESS_ID)
286                 return 0;
287         else
288                 return cpu_process_id;
289 }
290
291 int tegra_core_process_id(void)
292 {
293         /* FIXME: remove when ready to deprecate invalid process-id boards */
294         if (core_process_id == INVALID_PROCESS_ID)
295                 return 0;
296         else
297                 return core_process_id;
298 }
299
300 int tegra_cpu_speedo_id(void)
301 {
302         return cpu_speedo_id;
303 }
304
305 int tegra_soc_speedo_id(void)
306 {
307         return soc_speedo_id;
308 }
309
310 int tegra_package_id(void)
311 {
312         return package_id;
313 }