arm: tegra: Tegra14x leakage and dynamic model parameters
[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                 .temp_scaled        = 10,
203
204                 .dyn_scaled         = 1000000,
205                 .dyn_consts_n       = {  376000,  638000,  916000, 1203000 },
206
207                 .consts_scaled      = 1000000,
208                 .leakage_consts_n   = {  489500,  730600,  867600, 1000000 },
209
210                 .ijk_scaled         = 1000,
211                 .leakage_consts_ijk = {
212                         /* i = 0 */
213                         { {    564982,  -1353469,    309283,    -20862, },
214                           {  -1866916,   4500931,  -1026666,     68669, },
215                           {   1965934,  -4869757,   1107682,    -73554, },
216                           {   -637854,   1715497,   -388916,     25621, },
217                         },
218                         /* i = 1 */
219                         { {  -7341396,   7706464,  -1729662,    114105, },
220                           {  24249928, -25178676,   5651247,   -370322, },
221                           { -26109261,  26794485,  -6018513,    392722, },
222                           {   9127986,  -9288224,   2091707,   -135487, },
223                         },
224                         /* i = 2 */
225                         { {   9830061,  -9444047,   2035950,   -132842, },
226                           { -31837469,  30412491,  -6571344,    428173, },
227                           {  33645736, -31974811,   6933186,   -452148, },
228                           { -11561204,  11000249,  -2395570,    156270, },
229                         },
230                         /* i = 3 */
231                         { {  -2848862,   2437747,   -500201,     31386, },
232                           {   9160903,  -7785587,   1605160,   -100724, },
233                           {  -9619266,   8124245,  -1686232,    106069, },
234                           {   3291191,  -2777151,    581139,    -36610, },
235                         },
236                 },
237                 .leakage_min = 30,
238                 /* .volt_temp_cap = { 70, 1240 }, - TODO for T148 */
239         },
240         {
241                 .cpu_speedo_id      = 1, /* SKU 0x3 CPU */
242
243                 .temp_scaled        = 10,
244
245                 .dyn_scaled         = 1000000,
246                 .dyn_consts_n       = {  376000,  638000,  916000, 1203000 },
247
248                 .consts_scaled      = 1000000,
249                 .leakage_consts_n   = {  489500,  730600,  867600, 1000000 },
250
251                 .ijk_scaled         = 1000,
252                 .leakage_consts_ijk = {
253                         /* i = 0 */
254                         { {    564982,  -1353469,    309283,    -20862, },
255                           {  -1866916,   4500931,  -1026666,     68669, },
256                           {   1965934,  -4869757,   1107682,    -73554, },
257                           {   -637854,   1715497,   -388916,     25621, },
258                         },
259                         /* i = 1 */
260                         { {  -7341396,   7706464,  -1729662,    114105, },
261                           {  24249928, -25178676,   5651247,   -370322, },
262                           { -26109261,  26794485,  -6018513,    392722, },
263                           {   9127986,  -9288224,   2091707,   -135487, },
264                         },
265                         /* i = 2 */
266                         { {   9830061,  -9444047,   2035950,   -132842, },
267                           { -31837469,  30412491,  -6571344,    428173, },
268                           {  33645736, -31974811,   6933186,   -452148, },
269                           { -11561204,  11000249,  -2395570,    156270, },
270                         },
271                         /* i = 3 */
272                         { {  -2848862,   2437747,   -500201,     31386, },
273                           {   9160903,  -7785587,   1605160,   -100724, },
274                           {  -9619266,   8124245,  -1686232,    106069, },
275                           {   3291191,  -2777151,    581139,    -36610, },
276                         },
277                 },
278                 .leakage_min = 30,
279                 /* .volt_temp_cap = { 70, 1240 }, - TODO for T148 */
280         },
281 };
282
283 struct tegra_edp_cpu_leakage_params *tegra14x_get_leakage_params(int index,
284                                                         unsigned int *sz)
285 {
286         BUG_ON(index >= ARRAY_SIZE(t14x_leakage_params));
287         if (sz)
288                 *sz = ARRAY_SIZE(t14x_leakage_params);
289         return &t14x_leakage_params[index];
290 }
291 #endif
292
293 static struct core_edp_entry *find_edp_entry(int sku, unsigned int regulator_mA)
294 {
295         int i;
296
297         for (i = 0; i < ARRAY_SIZE(core_edp_table); i++) {
298                 struct core_edp_entry *entry = &core_edp_table[i];
299                 if ((entry->sku == sku) && (entry->cap_mA == regulator_mA))
300                         return entry;
301         }
302         return NULL;
303 }
304
305 static unsigned long clip_cap_rate(struct clk *cap_clk, unsigned long rate)
306 {
307         unsigned long floor, ceiling;
308         struct clk *p = clk_get_parent(cap_clk);
309
310         if (!p || !p->ops || !p->ops->shared_bus_update) {
311                 WARN(1, "%s: edp cap clk %s is not a shared bus user\n",
312                         __func__, cap_clk->name);
313                 return rate;
314         }
315
316         /*
317          * Clip cap rate to shared bus possible rates (going up via shared
318          * bus * ladder since bus clocks always rounds up with resolution of
319          * at least 2kHz)
320          */
321         ceiling = clk_round_rate(p, clk_get_min_rate(p));
322         do {
323                 floor = ceiling;
324                 ceiling = clk_round_rate(p, floor + 2000);
325                 if (IS_ERR_VALUE(ceiling)) {
326                         pr_err("%s: failed to clip %lu to %s possible rates\n",
327                                __func__, rate, p->name);
328                         return rate;
329                 }
330         } while ((floor < ceiling) && (ceiling <= rate));
331
332         if (floor > rate)
333                 WARN(1, "%s: %s cap rate %lu is below %s floor %lu\n",
334                         __func__, cap_clk->name, rate, p->name, floor);
335         return floor;
336 }
337
338 int __init tegra14x_select_core_edp_table(unsigned int regulator_mA,
339                                           struct tegra_core_edp_limits *limits)
340 {
341         int i;
342         int sku = tegra_sku_id;
343         unsigned long *cap_rates;
344         struct core_edp_entry *edp_entry;
345
346         BUG_ON(ARRAY_SIZE(temperatures) != TEMPERATURE_RANGES);
347         BUG_ON(ARRAY_SIZE(cap_clks_names) != CAP_CLKS_NUM);
348
349         for (i = 0; i < CAP_CLKS_NUM; i++) {
350                 struct clk *c = tegra_get_clock_by_name(cap_clks_names[i]);
351                 if (!c) {
352                         pr_err("%s: failed to find edp cap clock %s\n",
353                                __func__, cap_clks_names[i]);
354                         return -ENODEV;
355                 }
356                 cap_clks[i] = c;
357         }
358
359         if (sku == 0x0)
360                 sku = 0x7;
361
362         if ((sku == 0x7) && (regulator_mA >= 3500)) {
363                 pr_info("%s: no core edp capping for sku %d, %d mA\n",
364                        __func__, sku, regulator_mA);
365                 return -ENODATA;
366         }
367
368         edp_entry = find_edp_entry(sku, regulator_mA);
369         if (!edp_entry) {
370                 pr_info("%s: no core edp table for sku %d, %d mA\n",
371                        __func__, sku, regulator_mA);
372                 return -ENODATA;
373         }
374
375         limits->sku = sku;
376         limits->cap_clocks = cap_clks;
377         limits->cap_clocks_num = CAP_CLKS_NUM;
378         limits->temperatures = temperatures;
379         limits->temperature_ranges = TEMPERATURE_RANGES;
380         limits->core_modules_states = CORE_MODULES_STATES;
381
382         cap_rates = &edp_entry->cap_cpu[0][0][0][0];
383         limits->cap_rates_scpu_on = cap_rates;
384         limits->cap_rates_scpu_off = cap_rates;
385         for (i = 0; i < TOTAL_CAPS; i++, cap_rates++) {
386                 unsigned long rate = *cap_rates * edp_entry->mult;
387                 *cap_rates = clip_cap_rate(cap_clks[i % CAP_CLKS_NUM], rate);
388         }
389
390         return 0;
391 }