ARM: tegra: fuse: Add A03 revision for Tegra3.
[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}, /* soc_speedo_id 0 */
38         {180}, /* soc_speedo_id 1 */
39         {200}, /* soc_speedo_id 2 */
40 };
41
42 /* Maximum speedo levels for each CPU process corner */
43 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
44 /* proc_id 0    1    2    3 */
45         {306, 338, 360, 376}, /* cpu_speedo_id 0 */
46         {306, 338, 360, 376}, /* cpu_speedo_id 1 */
47         {338, 338, 360, 376}, /* cpu_speedo_id 2 */
48         {338, 338, 360, 376}, /* cpu_speedo_id 3 */
49 };
50
51 static int cpu_process_id;
52 static int core_process_id;
53 static int cpu_speedo_id;
54 static int soc_speedo_id;
55 static int package_id;
56
57 static void fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
58 {
59         u32 reg;
60
61         BUG_ON(!speedo_g || !speedo_lp);
62         reg = tegra_fuse_readl(FUSE_SPEEDO_CALIB_0);
63
64         /* Speedo LP = Lower 16-bits Multiplied by 4 */
65         *speedo_lp = (reg & 0xFFFF) * 4;
66
67         /* Speedo G = Upper 16-bits Multiplied by 4 */
68         *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
69 }
70
71 static void rev_sku_to_speedo_ids(int rev, int sku)
72 {
73         switch (rev) {
74         case TEGRA_REVISION_A01:
75                 cpu_speedo_id = 0;
76                 soc_speedo_id = 0;
77                 break;
78         case TEGRA_REVISION_A02:
79         case TEGRA_REVISION_A03:
80                 switch (sku) {
81                 case 0x87: /* AP30 */
82                         cpu_speedo_id = 1;
83                         soc_speedo_id = 1;
84                         break;
85                 case 0x81: /* T30 */
86                         cpu_speedo_id = 2;
87                         soc_speedo_id = 2;
88                         break;
89                 case 0x83: /* T30S */
90                         cpu_speedo_id = 3;
91                         soc_speedo_id = 2;
92                         break;
93                 case 0:    /* ENG - check PKG_SKU */
94                         pr_info("Tegra3 ENG SKU: Checking pkg info\n");
95                         switch (package_id) {
96                         case 1: /* MID => assume T30 */
97                                 cpu_speedo_id = 2;
98                                 soc_speedo_id = 2;
99                                 break;
100                         case 2: /* DSC => assume T30S */
101                                 cpu_speedo_id = 3;
102                                 soc_speedo_id = 2;
103                                 break;
104                         default:
105                                 pr_err("Tegra3 Rev-A02: Reserved pkg info %d\n",
106                                        package_id);
107                                 BUG();
108                                 break;
109                         }
110                         break;
111                 default:
112                         /* FIXME: replace with BUG() when all SKU's valid */
113                         pr_err("Tegra3 Rev-A02: Unknown SKU %d\n", sku);
114                         cpu_speedo_id = 0;
115                         soc_speedo_id = 0;
116                         break;
117                 }
118                 break;
119         default:
120                 BUG();
121                 break;
122         }
123 }
124
125 void tegra_init_speedo_data(void)
126 {
127         u32 cpu_speedo_val, core_speedo_val;
128         int iv;
129
130         /* Package info: 4 bits - 0,3:reserved 1:MID 2:DSC */
131         package_id = tegra_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F;
132
133         rev_sku_to_speedo_ids(tegra_get_revision(), tegra_sku_id());
134         BUG_ON(cpu_speedo_id >= ARRAY_SIZE(cpu_process_speedos));
135         BUG_ON(soc_speedo_id >= ARRAY_SIZE(core_process_speedos));
136
137         fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val);
138         pr_debug("%s CPU speedo value %u\n", __func__, cpu_speedo_val);
139         pr_debug("%s Core speedo value %u\n", __func__, core_speedo_val);
140
141         for (iv = 0; iv < CPU_PROCESS_CORNERS_NUM; iv++) {
142                 if (cpu_speedo_val < cpu_process_speedos[cpu_speedo_id][iv]) {
143                         break;
144                 }
145         }
146         cpu_process_id = iv -1;
147
148         if (cpu_process_id == -1) {
149                 pr_err("****************************************************");
150                 pr_err("****************************************************");
151                 pr_err("* tegra3_speedo: CPU speedo value %3d out of range *",
152                        cpu_speedo_val);
153                 pr_err("****************************************************");
154                 pr_err("****************************************************");
155
156                 cpu_process_id = INVALID_PROCESS_ID;
157                 cpu_speedo_id = 0;
158         }
159
160         for (iv = 0; iv < CORE_PROCESS_CORNERS_NUM; iv++) {
161                 if (core_speedo_val < core_process_speedos[soc_speedo_id][iv]) {
162                         break;
163                 }
164         }
165         core_process_id = iv -1;
166
167         if (core_process_id == -1) {
168                 pr_err("*****************************************************");
169                 pr_err("*****************************************************");
170                 pr_err("* tegra3_speedo: CORE speedo value %3d out of range *",
171                        core_speedo_val);
172                 pr_err("*****************************************************");
173                 pr_err("*****************************************************");
174
175                 core_process_id = INVALID_PROCESS_ID;
176                 soc_speedo_id = 0;
177         }
178
179         pr_info("Tegra3: CPU Speedo ID %d, Soc Speedo ID %d",
180                  cpu_speedo_id, soc_speedo_id);
181 }
182
183 int tegra_cpu_process_id(void)
184 {
185         /* FIXME: remove when ready to deprecate invalid process-id boards */
186         if (cpu_process_id == INVALID_PROCESS_ID)
187                 return 0;
188         else
189                 return cpu_process_id;
190 }
191
192 int tegra_core_process_id(void)
193 {
194         /* FIXME: remove when ready to deprecate invalid process-id boards */
195         if (core_process_id == INVALID_PROCESS_ID)
196                 return 0;
197         else
198                 return core_process_id;
199 }
200
201 int tegra_cpu_speedo_id(void)
202 {
203         return cpu_speedo_id;
204 }
205
206 int tegra_soc_speedo_id(void)
207 {
208         return soc_speedo_id;
209 }
210
211 int tegra_package_id(void)
212 {
213         return package_id;
214 }