arm: tegra: refactor Tegra14x leakage and dynamic model
[linux-3.10.git] / arch / arm / mach-tegra / tegra14_edp.c
1 /*
2  * arch/arm/mach-tegra/tegra14_edp.c
3  *
4  * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope 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
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/string.h>
22 #include <linux/module.h>
23 #include <linux/clk.h>
24 #include <linux/kobject.h>
25 #include <linux/err.h>
26
27 #include <mach/edp.h>
28
29 #include "clock.h"
30 #include "fuse.h"
31
32 #define CORE_MODULES_STATES 1
33 #define TEMPERATURE_RANGES 5
34 #define CAP_CLKS_NUM 2
35 #define TOTAL_CAPS (CORE_EDP_PROFILES_NUM * CORE_MODULES_STATES *\
36                         TEMPERATURE_RANGES * CAP_CLKS_NUM)
37
38 struct core_edp_entry {
39         int sku;
40         unsigned int cap_mA;
41         int mult;
42         unsigned long cap_cpu[CORE_EDP_PROFILES_NUM][
43                 CORE_MODULES_STATES][TEMPERATURE_RANGES][CAP_CLKS_NUM];
44 };
45
46 static int temperatures[] = { 50, 70, 80, 90, 100 };
47
48 #ifdef CONFIG_TEGRA_DUAL_CBUS
49 static char *cap_clks_names[] = { "edp.emc", "edp.c2bus" };
50 #else
51 static char *cap_clks_names[] = { "edp.emc", "edp.cbus" };
52 #endif
53 static struct clk *cap_clks[CAP_CLKS_NUM];
54
55 /* FIXME: Populate with correct values as per final EDP tables.
56  * Currently contains *safe* values
57  */
58 static struct core_edp_entry core_edp_table[] = {
59         {
60                 .sku            = 0x7,          /* SL440 */
61                 .cap_mA         = 3000,         /* 3A cap */
62                 .mult           = 1000000,      /* MHZ */
63                 .cap_cpu        = {
64                         /* favor emc */
65                         {       /* core modules power state 0 (all ON) */
66                                 {{ 921, 655 },
67                                  { 921, 596 },
68                                  { 921, 596 },
69                                  { 921, 596 },
70                                  { 921, 557 },
71                                 },
72                         },
73                         /* balanced profile */
74                         {       /* core modules power state 0 (all ON) */
75                                 {{ 921, 655 },
76                                  { 921, 596 },
77                                  { 921, 596 },
78                                  { 921, 596 },
79                                  { 788, 596 },
80                                 },
81                         },
82                         /* favor gpu */
83                         {       /* core modules power state 0 (all ON) */
84                                 {{ 921, 655 },
85                                  { 788, 655 },
86                                  { 921, 596 },
87                                  { 921, 596 },
88                                  { 788, 596 },
89                                 }
90                         },
91                 },
92         },
93         {
94                 .sku            = 0x3,          /* SL460 */
95                 .cap_mA         = 3000,         /* 3A cap */
96                 .mult           = 1000000,      /* MHZ */
97                 .cap_cpu        = {
98                         /* favor emc */
99                         {       /* core modules power state 0 (all ON) */
100                                 {{ 921, 672 },
101                                  { 921, 596 },
102                                  { 921, 596 },
103                                  { 921, 596 },
104                                  { 921, 557 },
105                                 },
106                         },
107                         /* balanced profile */
108                         {       /* core modules power state 0 (all ON) */
109                                 {{ 921, 672 },
110                                  { 788, 672 },
111                                  { 921, 596 },
112                                  { 921, 596 },
113                                  { 788, 596 },
114                                 },
115                         },
116                         /* favor gpu */
117                         {       /* core modules power state 0 (all ON) */
118                                 {{ 921, 672 },
119                                  { 788, 672 },
120                                  { 921, 596 },
121                                  { 921, 596 },
122                                  { 788, 596 },
123                                 }
124                         },
125                 },
126         },
127         {
128                 .sku            = 0x3,          /* SL460 */
129                 .cap_mA         = 3500,         /* 3.5A cap */
130                 .mult           = 1000000,      /* MHZ */
131                 .cap_cpu        = {
132                         /* favor emc */
133                         {       /* core modules power state 0 (all ON) */
134                                 {{ 921, 711 },
135                                  { 921, 711 },
136                                  { 921, 711 },
137                                  { 921, 672 },
138                                  { 921, 672 },
139                                 },
140                         },
141                         /* balanced profile */
142                         {       /* core modules power state 0 (all ON) */
143                                 {{ 788, 749 },
144                                  { 921, 711 },
145                                  { 921, 711 },
146                                  { 921, 672 },
147                                  { 921, 672 },
148                                 },
149                         },
150                         /* favor gpu */
151                         {       /* core modules power state 0 (all ON) */
152                                 {{ 788, 749 },
153                                  { 921, 711 },
154                                  { 921, 711 },
155                                  { 921, 672 },
156                                  { 921, 672 },
157                                 }
158                         },
159                 },
160         },
161         {
162                 .sku            = 0x3,          /* SL460 */
163                 .cap_mA         = 4000,         /* 4A cap */
164                 .mult           = 1000000,      /* MHZ */
165                 .cap_cpu        = {
166                         /* favor emc */
167                         {       /* core modules power state 0 (all ON) */
168                                 {{ 921, 749 },
169                                  { 921, 749 },
170                                  { 921, 711 },
171                                  { 921, 672 },
172                                  { 921, 672 },
173                                 },
174                         },
175                         /* balanced profile */
176                         {       /* core modules power state 0 (all ON) */
177                                 {{ 921, 749 },
178                                  { 921, 749 },
179                                  { 921, 711 },
180                                  { 921, 672 },
181                                  { 921, 672 },
182                                 },
183                         },
184                         /* favor gpu */
185                         {       /* core modules power state 0 (all ON) */
186                                 {{ 921, 749 },
187                                  { 921, 749 },
188                                  { 921, 711 },
189                                  { 921, 672 },
190                                  { 921, 672 },
191                                 }
192                         },
193                 },
194         }
195 };
196
197 #ifdef CONFIG_TEGRA_EDP_LIMITS
198 static struct tegra_edp_cpu_leakage_params t14x_leakage_params[] = {
199         {
200                 .cpu_speedo_id      = 0, /* A01 CPU */
201
202                 .dyn_scaled         = 1000000,
203                 .dyn_consts_n       = {  643724,  908655, 1173586, 1438517 },
204
205                 .consts_scaled      = 1000000,
206                 .leakage_consts_n   = {  524409,  699606,  874803, 1050000 },
207
208                 .ijk_scaled         = 100000,
209                 .leakage_consts_ijk = {
210                         /* i = 0 */
211                         { {   0,   -5346808,   97234,   -464, },
212                           {   0,   16803984, -307162,   1481, },
213                           {   0,  -17730060,  322460,  -1546, },
214                           {   0,    6489900, -118190,    564, },
215                         },
216                         /* i = 1 */
217                         { {   0,   -7166070,   16144,  -2495, },
218                           {   0,   22733881,  -62339,   7849, },
219                           {   0,  -22851718,   17626,  -7211, },
220                           {   0,    8845764,   -3232,   2668, },
221                         },
222                         /* i = 2 */
223                         { {   0,  -13755297,   88228,    194, },
224                           {   0,   43058825, -281494,   -604, },
225                           {   0,  -45854189,  328873,    337, },
226                           {   0,   17332703, -123100,   -128, },
227                         },
228                         /* i = 3 */
229                         { {   0,    1950888,   -8210,    -62, },
230                           {   0,   -6086732,   26052,    197, },
231                           {   0,    6462190,  -32222,   -161, },
232                           {   0,   -2416618,   11593,     62, },
233                         },
234                 },
235                 .leakage_min = 30,
236                 /* .volt_temp_cap = { 70, 1240 }, - TODO for T148 */
237         },
238         {
239                 .cpu_speedo_id      = 1, /* SKU 0x3 CPU */
240
241                 .dyn_scaled         = 1000000,
242                 .dyn_consts_n       = {  376000,  638000,  916000, 1203000 },
243
244                 .consts_scaled      = 1000000,
245                 .leakage_consts_n   = {  489500,  730600,  867600, 1000000 },
246
247                 .ijk_scaled         = 1000,
248                 .leakage_consts_ijk = {
249                         /* i = 0 */
250                         { {    564982,  -135347,    3093,    -21, },
251                           {  -1866916,   450093,  -10267,     69, },
252                           {   1965934,  -486976,   11077,    -74, },
253                           {   -637854,   171550,   -3889,     26, },
254                         },
255                         /* i = 1 */
256                         { {  -7341396,   770646,  -17297,    114, },
257                           {  24249928, -2517868,   56512,   -370, },
258                           { -26109261,  2679448,  -60185,    392, },
259                           {   9127986,  -928822,   20917,   -135, },
260                         },
261                         /* i = 2 */
262                         { {   9830061,  -944405,   20359,   -133, },
263                           { -31837469,  3041249, -655713,    428, },
264                           {  33645736, -3197481,   69332,   -452, },
265                           { -11561204,  1100025,  -23956,    156, },
266                         },
267                         /* i = 3 */
268                         { {  -2848862,   243774,   -5002,     31, },
269                           {   9160903,  -778559,   16052,   -101, },
270                           {  -9619266,   812425,  -16862,    106, },
271                           {   3291191,  -277715,    5811,    -37, },
272                         },
273                 },
274                 .leakage_min = 30,
275                 /* .volt_temp_cap = { 70, 1240 }, - TODO for T148 */
276         },
277 };
278
279 struct tegra_edp_cpu_leakage_params *tegra14x_get_leakage_params(int index,
280                                                         unsigned int *sz)
281 {
282         BUG_ON(index >= ARRAY_SIZE(t14x_leakage_params));
283         if (sz)
284                 *sz = ARRAY_SIZE(t14x_leakage_params);
285         return &t14x_leakage_params[index];
286 }
287 #endif
288
289 static struct core_edp_entry *find_edp_entry(int sku, unsigned int regulator_mA)
290 {
291         int i;
292
293         for (i = 0; i < ARRAY_SIZE(core_edp_table); i++) {
294                 struct core_edp_entry *entry = &core_edp_table[i];
295                 if ((entry->sku == sku) && (entry->cap_mA == regulator_mA))
296                         return entry;
297         }
298         return NULL;
299 }
300
301 static unsigned long clip_cap_rate(struct clk *cap_clk, unsigned long rate)
302 {
303         unsigned long floor, ceiling;
304         struct clk *p = clk_get_parent(cap_clk);
305
306         if (!p || !p->ops || !p->ops->shared_bus_update) {
307                 WARN(1, "%s: edp cap clk %s is not a shared bus user\n",
308                         __func__, cap_clk->name);
309                 return rate;
310         }
311
312         /*
313          * Clip cap rate to shared bus possible rates (going up via shared
314          * bus * ladder since bus clocks always rounds up with resolution of
315          * at least 2kHz)
316          */
317         ceiling = clk_round_rate(p, clk_get_min_rate(p));
318         do {
319                 floor = ceiling;
320                 ceiling = clk_round_rate(p, floor + 2000);
321                 if (IS_ERR_VALUE(ceiling)) {
322                         pr_err("%s: failed to clip %lu to %s possible rates\n",
323                                __func__, rate, p->name);
324                         return rate;
325                 }
326         } while ((floor < ceiling) && (ceiling <= rate));
327
328         if (floor > rate)
329                 WARN(1, "%s: %s cap rate %lu is below %s floor %lu\n",
330                         __func__, cap_clk->name, rate, p->name, floor);
331         return floor;
332 }
333
334 int __init tegra14x_select_core_edp_table(unsigned int regulator_mA,
335                                           struct tegra_core_edp_limits *limits)
336 {
337         int i;
338         int sku = tegra_sku_id;
339         unsigned long *cap_rates;
340         struct core_edp_entry *edp_entry;
341
342         BUG_ON(ARRAY_SIZE(temperatures) != TEMPERATURE_RANGES);
343         BUG_ON(ARRAY_SIZE(cap_clks_names) != CAP_CLKS_NUM);
344
345         for (i = 0; i < CAP_CLKS_NUM; i++) {
346                 struct clk *c = tegra_get_clock_by_name(cap_clks_names[i]);
347                 if (!c) {
348                         pr_err("%s: failed to find edp cap clock %s\n",
349                                __func__, cap_clks_names[i]);
350                         return -ENODEV;
351                 }
352                 cap_clks[i] = c;
353         }
354
355         if (sku == 0x0)
356                 sku = 0x7;
357
358         if ((sku == 0x7) && (regulator_mA >= 3500)) {
359                 pr_info("%s: no core edp capping for sku %d, %d mA\n",
360                        __func__, sku, regulator_mA);
361                 return -ENODATA;
362         }
363
364         edp_entry = find_edp_entry(sku, regulator_mA);
365         if (!edp_entry) {
366                 pr_info("%s: no core edp table for sku %d, %d mA\n",
367                        __func__, sku, regulator_mA);
368                 return -ENODATA;
369         }
370
371         limits->sku = sku;
372         limits->cap_clocks = cap_clks;
373         limits->cap_clocks_num = CAP_CLKS_NUM;
374         limits->temperatures = temperatures;
375         limits->temperature_ranges = TEMPERATURE_RANGES;
376         limits->core_modules_states = CORE_MODULES_STATES;
377
378         cap_rates = &edp_entry->cap_cpu[0][0][0][0];
379         limits->cap_rates_scpu_on = cap_rates;
380         limits->cap_rates_scpu_off = cap_rates;
381         for (i = 0; i < TOTAL_CAPS; i++, cap_rates++) {
382                 unsigned long rate = *cap_rates * edp_entry->mult;
383                 *cap_rates = clip_cap_rate(cap_clks[i % CAP_CLKS_NUM], rate);
384         }
385
386         return 0;
387 }