ARM: tegra: dvfs: Update Tegra3 AP33 speedo thresholds
[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         {180}, /* threshold_index 1: soc_speedo_id 1: AP30 */
41         {204}, /* threshold_index 2: soc_speedo_id 2: T30  */
42         {192}, /* threshold_index 3: soc_speedo_id 2: T30S */
43
44 /* Characterization SKUs */
45         {168}, /* threshold_index 4: soc_speedo_id 1: AP30 char */
46         {192}, /* threshold_index 5: soc_speedo_id 2: T30  char */
47         {184}, /* threshold_index 6: soc_speedo_id 2: T30S char */
48
49 /* T33 family: Numbers cloned from T30 family; FIXME: adjust these later */
50         {180}, /* threshold_index 7: soc_speedo_id = 1 - AP33 */
51         {204}, /* threshold_index 8: soc_speedo_id = 2 - T33  */
52         {192}, /* 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         {304, 336, 359, 375}, /* threshold_index 1: cpu_speedo_id 1: AP30 */
62         {336, 336, 359, 375}, /* threshold_index 2: cpu_speedo_id 2: T30  */
63         {336, 336, 359, 375}, /* threshold_index 3: cpu_speedo_id 3: T30S */
64
65 /* Characterization SKUs */
66         {292, 324, 348, 364}, /* threshold_index 4: cpu_speedo_id 1: AP30char */
67         {324, 324, 348, 364}, /* threshold_index 5: cpu_speedo_id 2: T30char  */
68         {324, 324, 348, 364}, /* threshold_index 6: cpu_speedo_id 3: T30Schar */
69
70 /* T33 family */
71         {304, 336, 359, 375}, /* threshold_index 7: cpu_speedo_id = 4 - AP33 */
72         {368, 368, 368, 368}, /* threshold_index 8: cpu_speedo_id = 5 - T33  */
73         {372, 372, 372, 372}, /* threshold_index 9: cpu_speedo_id = 6 - 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                 case 0x82: /* T30V */
116                         cpu_speedo_id = 1;
117                         soc_speedo_id = 1;
118                         threshold_index = 1;
119                         break;
120
121                 case 0x81: /* T30 */
122                         switch (package_id) {
123                         case 1: /* MID => T30 */
124                                 cpu_speedo_id = 2;
125                                 soc_speedo_id = 2;
126                                 threshold_index = 2;
127                                 break;
128                         case 2: /* DSC => AP33 */
129                                 cpu_speedo_id = 4;
130                                 soc_speedo_id = 1;
131                                 threshold_index = 7;
132                                 break;
133                         default:
134                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
135                                        package_id);
136                                 BUG();
137                                 break;
138                         }
139                         break;
140
141                 case 0x80: /* T33 or T33S */
142                         switch (package_id) {
143                         case 1: /* MID => T33 */
144                                 cpu_speedo_id = 5;
145                                 soc_speedo_id = 2;
146                                 threshold_index = 8;
147                                 break;
148                         case 2: /* DSC => T33S */
149                                 cpu_speedo_id = 6;
150                                 soc_speedo_id = 2;
151                                 threshold_index = 9;
152                                 break;
153                         default:
154                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
155                                        package_id);
156                                 BUG();
157                                 break;
158                         }
159                         break;
160
161                 case 0x83: /* T30S */
162                         cpu_speedo_id = 3;
163                         soc_speedo_id = 2;
164                         threshold_index = 3;
165                         break;
166
167 /* Characterization SKUs */
168                 case 0x08: /* AP30 char */
169                         cpu_speedo_id = 1;
170                         soc_speedo_id = 1;
171                         threshold_index = 4;
172                         break;
173                 case 0x02: /* T30 char */
174                         cpu_speedo_id = 2;
175                         soc_speedo_id = 2;
176                         threshold_index = 5;
177                         break;
178                 case 0x04: /* T30S char */
179                         cpu_speedo_id = 3;
180                         soc_speedo_id = 2;
181                         threshold_index = 6;
182                         break;
183
184                 case 0:    /* ENG - check package_id */
185                         pr_info("Tegra3 ENG SKU: Checking package_id\n");
186                         switch (package_id) {
187                         case 1: /* MID => assume T30 */
188                                 cpu_speedo_id = 2;
189                                 soc_speedo_id = 2;
190                                 threshold_index = 2;
191                                 break;
192                         case 2: /* DSC => assume T30S */
193                                 cpu_speedo_id = 3;
194                                 soc_speedo_id = 2;
195                                 threshold_index = 3;
196                                 break;
197                         default:
198                                 pr_err("Tegra3 Rev-A02: Reserved pkg: %d\n",
199                                        package_id);
200                                 BUG();
201                                 break;
202                         }
203                         break;
204
205                 default:
206                         /* FIXME: replace with BUG() when all SKU's valid */
207                         pr_err("Tegra3 Rev-A02: Unknown SKU %d\n", sku);
208                         cpu_speedo_id = 0;
209                         soc_speedo_id = 0;
210                         threshold_index = 0;
211                         break;
212                 }
213                 break;
214         default:
215                 BUG();
216                 break;
217         }
218 }
219
220 void tegra_init_speedo_data(void)
221 {
222         u32 cpu_speedo_val, core_speedo_val;
223         int iv;
224
225         /* Package info: 4 bits - 0,3:reserved 1:MID 2:DSC */
226         package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
227
228         /* Arrays must be of equal size - each index corresponds to a SKU */
229         BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
230                ARRAY_SIZE(core_process_speedos));
231
232         rev_sku_to_speedo_ids(tegra_get_revision(), tegra_sku_id());
233         BUG_ON(threshold_index >= ARRAY_SIZE(cpu_process_speedos));
234
235         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
236         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
237         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
238
239         for (iv = 0; iv < CPU_PROCESS_CORNERS_NUM; iv++) {
240                 if (cpu_speedo_val <
241                     cpu_process_speedos[threshold_index][iv]) {
242                         break;
243                 }
244         }
245         cpu_process_id = iv -1;
246
247         if (cpu_process_id == -1) {
248                 pr_err("****************************************************");
249                 pr_err("****************************************************");
250                 pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
251                        cpu_speedo_val);
252                 pr_err("****************************************************");
253                 pr_err("****************************************************");
254
255                 cpu_process_id = INVALID_PROCESS_ID;
256                 cpu_speedo_id = 1;
257         }
258
259         for (iv = 0; iv < CORE_PROCESS_CORNERS_NUM; iv++) {
260                 if (core_speedo_val <
261                     core_process_speedos[threshold_index][iv]) {
262                         break;
263                 }
264         }
265         core_process_id = iv -1;
266
267         if (core_process_id == -1) {
268                 pr_err("****************************************************");
269                 pr_err("****************************************************");
270                 pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
271                        core_speedo_val);
272                 pr_err("****************************************************");
273                 pr_err("****************************************************");
274
275                 core_process_id = INVALID_PROCESS_ID;
276                 soc_speedo_id = 1;
277         }
278
279         pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
280                  cpu_speedo_id, soc_speedo_id);
281 }
282
283 int tegra_cpu_process_id(void)
284 {
285         /* FIXME: remove when ready to deprecate invalid process-id boards */
286         if (cpu_process_id == INVALID_PROCESS_ID)
287                 return 0;
288         else
289                 return cpu_process_id;
290 }
291
292 int tegra_core_process_id(void)
293 {
294         /* FIXME: remove when ready to deprecate invalid process-id boards */
295         if (core_process_id == INVALID_PROCESS_ID)
296                 return 0;
297         else
298                 return core_process_id;
299 }
300
301 int tegra_cpu_speedo_id(void)
302 {
303         return cpu_speedo_id;
304 }
305
306 int tegra_soc_speedo_id(void)
307 {
308         return soc_speedo_id;
309 }
310
311 int tegra_package_id(void)
312 {
313         return package_id;
314 }