ARM: tegra12: set CPU rate to 2.2GHz for sku 0x87
[linux-3.10.git] / arch / arm / mach-tegra / tegra11_speedo.c
1 /*
2  * arch/arm/mach-tegra/tegra11_speedo.c
3  *
4  * Copyright (C) 2012-2013, NVIDIA Corporation. All rights reserved.
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; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/io.h>
23 #include <linux/err.h>
24 #include <linux/bug.h>                  /* For BUG_ON.  */
25
26 #include <linux/tegra-soc.h>
27 #include <linux/module.h>
28 #include <linux/moduleparam.h>
29 #include <linux/tegra-fuse.h>
30
31 #include "iomap.h"
32 #include "common.h"
33
34 #define CORE_PROCESS_CORNERS_NUM        2
35 #define CPU_PROCESS_CORNERS_NUM         2
36
37 #define FUSE_CPU_SPEEDO_0 0x114
38 #define FUSE_CPU_SPEEDO_1 0x12c
39 #define FUSE_CPU_IDDQ 0x118
40 #define FUSE_CORE_SPEEDO_0 0x134
41 #define FUSE_CORE_SPEEDO_1 0x138
42 #define FUSE_CORE_IDDQ 0x140
43 #define FUSE_FT_REV 0x128
44 #define FUSE_OPT_CPU23_DISABLE 0x26c
45 #define FUSE_OPT_CPU23_REENABLE 0x270
46
47 static int threshold_index;
48
49 static int cpu_process_id;
50 static int core_process_id;
51 static int cpu_speedo_id;
52 static int cpu_speedo_value;
53 static int soc_speedo_id;
54 static int core_speedo_value;
55 static int package_id;
56 static int cpu_iddq_value;
57
58 static int enable_app_profiles;
59
60 static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
61 /* proc_id  0,     1 */
62         {1123,     UINT_MAX}, /* [0]: threshold_index 0 */
63         {0,        UINT_MAX}, /* [1]: threshold_index 1 */
64 };
65
66 static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
67 /* proc_id  0,     1 */
68         {1695,     UINT_MAX}, /* [0]: threshold_index 0 */
69         {0,        UINT_MAX}, /* [1]: threshold_index 1 */
70 };
71
72 static void rev_sku_to_speedo_ids(int rev, int sku)
73 {
74         bool a01 = false;
75         cpu_speedo_id = 0;      /* For A01 rev, regardless of SKU */
76
77         if (rev == TEGRA_REVISION_A01) {
78                 u32 a01p = tegra_fuse_readl(FUSE_OPT_CPU23_REENABLE) << 1;
79                 a01p |= tegra_fuse_readl(FUSE_OPT_CPU23_DISABLE);
80                 if (a01p == 0)
81                         a01 = true;
82         }
83
84         switch (sku) {
85         case 0x00: /* Eng */
86         case 0x10: /* Eng */
87         case 0x05: /* T40S */
88         case 0x06: /* AP40 */
89         case 0x20: /* T40DC */
90                 if (!a01)
91                         cpu_speedo_id = 1;
92                 soc_speedo_id = 0;
93                 threshold_index = 0;
94                 break;
95
96         case 0x03: /* T40X */
97         case 0x04: /* T40T */
98                 if (!a01)
99                         cpu_speedo_id = 2;
100                 soc_speedo_id = 1;
101                 threshold_index = 1;
102                 break;
103
104         case 0x08: /* AP40X */
105                 if (!a01)
106                         cpu_speedo_id = 3;
107                 soc_speedo_id = 1;
108                 threshold_index = 1;
109                 break;
110
111         default:
112                 /* FIXME: replace with BUG() when all SKU's valid */
113                 pr_err("Tegra11 Unknown SKU %d\n", sku);
114                 cpu_speedo_id = 0;
115                 soc_speedo_id = 0;
116                 threshold_index = 0;
117                 break;
118         }
119 }
120
121 void tegra_init_speedo_data(void)
122 {
123         int i;
124         u32 ft_rev, ft_rev_major, ft_rev_minor;
125
126         cpu_speedo_value = 1024 + tegra_fuse_readl(FUSE_CPU_SPEEDO_1);
127         core_speedo_value = tegra_fuse_readl(FUSE_CORE_SPEEDO_0);
128
129         cpu_iddq_value = tegra_fuse_readl(FUSE_CPU_IDDQ);
130
131         ft_rev = tegra_fuse_readl(FUSE_FT_REV);
132         ft_rev_minor = ft_rev & 0x1f;
133         ft_rev_major = (ft_rev >> 5) & 0x3f;
134
135         if ((ft_rev_minor < 5) && (ft_rev_major == 0)) {
136                 /* Implement: cpu_iddq = max(1.3*fused_cpu_iddq, 2 Amps) */
137                 cpu_iddq_value *= 130;
138                 cpu_iddq_value = cpu_iddq_value > 200000 ?
139                         cpu_iddq_value : 200000;
140                 cpu_iddq_value /= 100;
141
142                 pr_warn("Tegra11: CPU IDDQ and speedo may be bogus");
143         }
144
145         rev_sku_to_speedo_ids(tegra_revision, tegra_get_sku_id());
146
147         pr_info("Tegra11: CPU Speedo ID %d, Soc Speedo ID %d",
148                 cpu_speedo_id, soc_speedo_id);
149         pr_info("Tegra11: CPU Speedo Value %d, Soc Speedo Value %d",
150                 cpu_speedo_value, core_speedo_value);
151
152         for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++) {
153                 if (cpu_speedo_value <
154                     cpu_process_speedos[threshold_index][i]) {
155                         break;
156                 }
157         }
158         cpu_process_id = i;
159
160         for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++) {
161                 if (core_speedo_value <
162                     core_process_speedos[threshold_index][i]) {
163                         break;
164                 }
165         }
166         core_process_id = i;
167 }
168
169 int tegra_cpu_process_id(void)
170 {
171         return cpu_process_id;
172 }
173
174 int tegra_core_process_id(void)
175 {
176         return core_process_id;
177 }
178
179 int tegra_cpu_speedo_id(void)
180 {
181         return cpu_speedo_id;
182 }
183
184 int tegra_soc_speedo_id(void)
185 {
186         return soc_speedo_id;
187 }
188
189 int tegra_package_id(void)
190 {
191         return package_id;
192 }
193
194 int tegra_cpu_speedo_value(void)
195 {
196         return cpu_speedo_value;
197 }
198
199 /*
200  * CPU and core nominal voltage levels as determined by chip SKU and speedo
201  * (not final - can be lowered by dvfs tables and rail dependencies; the
202  * latter is resolved by the dvfs code)
203  */
204 int tegra_cpu_speedo_mv(void)
205 {
206         /* Not applicable on Tegra11 */
207         return -ENOSYS;
208 }
209
210 int tegra_core_speedo_mv(void)
211 {
212         u32 tegra_sku_id;
213
214         tegra_sku_id = tegra_get_sku_id();
215         switch (soc_speedo_id) {
216         case 0:
217                 if (core_process_id == 1)
218                         return 1170;
219         /* fall thru if core_process_id = 0 */
220         case 1:
221                 if ((tegra_sku_id == 0x4) || (tegra_sku_id == 0x8))
222                         return 1390;
223                 return 1250;
224         default:
225                 BUG();
226         }
227 }
228
229 int tegra_get_cpu_iddq_value()
230 {
231         return cpu_iddq_value;
232 }
233
234 static int get_enable_app_profiles(char *val, const struct kernel_param *kp)
235 {
236         return param_get_uint(val, kp);
237 }
238
239 static struct kernel_param_ops tegra_profiles_ops = {
240         .get = get_enable_app_profiles,
241 };
242
243 module_param_cb(tegra_enable_app_profiles,
244         &tegra_profiles_ops, &enable_app_profiles, 0444);