arm: tegra: refactor Tegra14x leakage and dynamic model
[linux-3.10.git] / arch / arm / mach-tegra / tegra11_edp.c
1 /*
2  * arch/arm/mach-tegra/tegra11_edp.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 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 4
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_scpu_on[CORE_EDP_PROFILES_NUM][
43                 CORE_MODULES_STATES][TEMPERATURE_RANGES][CAP_CLKS_NUM];
44         unsigned long cap_scpu_off[CORE_EDP_PROFILES_NUM][
45                 CORE_MODULES_STATES][TEMPERATURE_RANGES][CAP_CLKS_NUM];
46 };
47
48 static int temperatures[] = { 50, 70, 90, 105 };
49
50 #ifdef CONFIG_TEGRA_DUAL_CBUS
51 static char *cap_clks_names[] = { "edp.emc", "edp.c2bus" };
52 #else
53 static char *cap_clks_names[] = { "edp.emc", "edp.cbus" };
54 #endif
55 static struct clk *cap_clks[CAP_CLKS_NUM];
56
57 static struct core_edp_entry core_edp_table[] = {
58         {
59                 .sku            = 0x3,          /* SKU = 4 - T40X */
60                 .cap_mA         = 6000,         /* 6A cap */
61                 .mult           = 1000000,      /* MHZ */
62                 .cap_scpu_on    = {
63                         /* favor emc */
64                         {       /* core modules power state 0 (all ON) */
65                                 {{ 924, 636 },
66                                  { 924, 612 },
67                                  { 924, 564 },
68                                  { 924, 480 },
69                                 },
70                         },
71                         /* balanced profile */
72                         {       /* core modules power state 0 (all ON) */
73                                 {{ 792, 636 },
74                                  { 792, 636 },
75                                  { 792, 636 },
76                                  { 792, 552 },
77                                 },
78                         },
79                         /* favor gpu */
80                         {       /* core modules power state 0 (all ON) */
81                                 {{ 624, 672 },
82                                  { 624, 672 },
83                                  { 528, 672 },
84                                  { 408, 672 },
85                                 }
86                         },
87                 },
88                 .cap_scpu_off   = {
89                         /* favor emc */
90                         {       /* core modules power state 0 (all ON) */
91                                 {{1066, 700 },
92                                  { 924, 648 },
93                                  { 924, 636 },
94                                  { 924, 588 },
95                                 },
96                         },
97                         /* balanced profile */
98                         {       /* core modules power state 0 (all ON) */
99                                 {{1066, 700 },
100                                  { 792, 672 },
101                                  { 792, 672 },
102                                  { 792, 624 },
103                                 },
104                         },
105                         /* favor gpu */
106                         {       /* core modules power state 0 (all ON) */
107                                 {{1066, 700 },
108                                  { 792, 672 },
109                                  { 792, 672 },
110                                  { 624, 672 },
111                                 }
112                         },
113                 },
114         },
115 };
116
117 #ifdef CONFIG_TEGRA_EDP_LIMITS
118 static struct tegra_edp_cpu_leakage_params t11x_leakage_params[] = {
119         {
120                 .cpu_speedo_id      = 0, /* A01 CPU */
121
122                 .dyn_scaled         = 1000000,
123                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
124
125                 .consts_scaled      = 1000000,
126                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
127
128                 .ijk_scaled         = 100000,
129                 .leakage_consts_ijk = {
130                         /* i = 0 */
131                         { {  -42746668,   -5458429,   164998,  -1711, },
132                           {  178262421,   13375684,  -411791,   4590, },
133                           { -228866784,  -10482993,   331248,  -4062, },
134                           {   94301550,    2618719,   -85983,   1193, },
135                         },
136                         /* i = 1 */
137                         { { -256611791,   49677413, -1655785,  14917, },
138                           {  584675433, -132620939,  4541560, -41812, },
139                           { -398106336,  115987156, -4102328,  38737, },
140                           {   68897184,  -33030745,  1217839, -11801, },
141                         },
142                         /* i = 2 */
143                         { {  186324676,  -36019083,  1177969, -10669, },
144                           { -439237936,   98429131, -3276444,  30301, },
145                           {  315060898,  -88635036,  3004777, -28474, },
146                           {  -60854399,   26267188,  -907121,   8844, },
147                         },
148                         /* i = 3 */
149                         { {  -35432997,    6154621,  -202200,   1830, },
150                           {   87402153,  -16908683,   565152,  -5220, },
151                           {  -67775314,   15326770,  -521221,   4927, },
152                           {   15618709,   -4576116,   158401,  -1538, },
153                         },
154                 },
155                 .volt_temp_cap = { 70, 1300 },
156         },
157         {
158                 .cpu_speedo_id      = 1, /* A01P+ CPU */
159
160                 .dyn_scaled         = 1000000,
161                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
162
163                 .consts_scaled      = 1000000,
164                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
165
166                 .ijk_scaled         = 100000,
167                 .leakage_consts_ijk = {
168                         /* i = 0 */
169                         { {  -42746668,   -5458429,   164998,  -1711, },
170                           {  178262421,   13375684,  -411791,   4590, },
171                           { -228866784,  -10482993,   331248,  -4062, },
172                           {   94301550,    2618719,   -85983,   1193, },
173                         },
174                         /* i = 1 */
175                         { { -256611791,   49677413, -1655785,  14917, },
176                           {  584675433, -132620939,  4541560, -41812, },
177                           { -398106336,  115987156, -4102328,  38737, },
178                           {   68897184,  -33030745,  1217839, -11801, },
179                         },
180                         /* i = 2 */
181                         { {  186324676,  -36019083,  1177969, -10669, },
182                           { -439237936,   98429131, -3276444,  30301, },
183                           {  315060898,  -88635036,  3004777, -28474, },
184                           {  -60854399,   26267188,  -907121,   8844, },
185                         },
186                         /* i = 3 */
187                         { {  -35432997,    6154621,  -202200,   1830, },
188                           {   87402153,  -16908683,   565152,  -5220, },
189                           {  -67775314,   15326770,  -521221,   4927, },
190                           {   15618709,   -4576116,   158401,  -1538, },
191                         },
192                 },
193                 .safety_cap = { 1810500, 1810500, 1606500, 1606500 },
194                 .volt_temp_cap = { 70, 1300 },
195         },
196         {
197                 .cpu_speedo_id      = 2, /* A01P+ fast CPU */
198
199                 .dyn_scaled         = 1000000,
200                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
201
202                 .consts_scaled      = 1000000,
203                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
204
205                 .ijk_scaled         = 100000,
206                 .leakage_consts_ijk = {
207                         /* i = 0 */
208                         { {  -42746668,   -5458429,   164998,  -1711, },
209                           {  178262421,   13375684,  -411791,   4590, },
210                           { -228866784,  -10482993,   331248,  -4062, },
211                           {   94301550,    2618719,   -85983,   1193, },
212                         },
213                         /* i = 1 */
214                         { { -256611791,   49677413, -1655785,  14917, },
215                           {  584675433, -132620939,  4541560, -41812, },
216                           { -398106336,  115987156, -4102328,  38737, },
217                           {   68897184,  -33030745,  1217839, -11801, },
218                         },
219                         /* i = 2 */
220                         { {  186324676,  -36019083,  1177969, -10669, },
221                           { -439237936,   98429131, -3276444,  30301, },
222                           {  315060898,  -88635036,  3004777, -28474, },
223                           {  -60854399,   26267188,  -907121,   8844, },
224                         },
225                         /* i = 3 */
226                         { {  -35432997,    6154621,  -202200,   1830, },
227                           {   87402153,  -16908683,   565152,  -5220, },
228                           {  -67775314,   15326770,  -521221,   4927, },
229                           {   15618709,   -4576116,   158401,  -1538, },
230                         },
231                 },
232                 .safety_cap = { 1912500, 1912500, 1912500, 1912500 },
233                 .volt_temp_cap = { 70, 1300 },
234         },
235 };
236
237 struct tegra_edp_cpu_leakage_params *tegra11x_get_leakage_params(int index,
238                                                         unsigned int *sz)
239 {
240         BUG_ON(index >= ARRAY_SIZE(t11x_leakage_params));
241         if (sz)
242                 *sz = ARRAY_SIZE(t11x_leakage_params);
243         return &t11x_leakage_params[index];
244 }
245 #endif
246
247 static struct core_edp_entry *find_edp_entry(int sku, unsigned int regulator_mA)
248 {
249         int i;
250
251         for (i = 0; i < ARRAY_SIZE(core_edp_table); i++) {
252                 struct core_edp_entry *entry = &core_edp_table[i];
253                 if ((entry->sku == sku) && (entry->cap_mA == regulator_mA))
254                         return entry;
255         }
256         return NULL;
257 }
258
259 static unsigned long clip_cap_rate(struct clk *cap_clk, unsigned long rate)
260 {
261         unsigned long floor, ceiling;
262         struct clk *p = clk_get_parent(cap_clk);
263
264         if (!p || !p->ops || !p->ops->shared_bus_update) {
265                 WARN(1, "%s: edp cap clk %s is not a shared bus user\n",
266                         __func__, cap_clk->name);
267                 return rate;
268         }
269
270         /*
271          * Clip cap rate to shared bus possible rates (going up via shared
272          * bus * ladder since bus clocks always rounds up with resolution of
273          * at least 2kHz)
274          */
275         ceiling = clk_round_rate(p, clk_get_min_rate(p));
276         do {
277                 floor = ceiling;
278                 ceiling = clk_round_rate(p, floor + 2000);
279                 if (IS_ERR_VALUE(ceiling)) {
280                         pr_err("%s: failed to clip %lu to %s possible rates\n",
281                                __func__, rate, p->name);
282                         return rate;
283                 }
284         } while ((floor < ceiling) && (ceiling <= rate));
285
286         if (floor > rate)
287                 WARN(1, "%s: %s cap rate %lu is below %s floor %lu\n",
288                         __func__, cap_clk->name, rate, p->name, floor);
289         return floor;
290 }
291
292 int __init tegra11x_select_core_edp_table(unsigned int regulator_mA,
293                                           struct tegra_core_edp_limits *limits)
294 {
295         int i;
296         int sku = tegra_sku_id;
297         unsigned long *cap_rates;
298         struct core_edp_entry *edp_entry;
299
300         BUG_ON(ARRAY_SIZE(temperatures) != TEMPERATURE_RANGES);
301         BUG_ON(ARRAY_SIZE(cap_clks_names) != CAP_CLKS_NUM);
302         for (i = 0; i < CAP_CLKS_NUM; i++) {
303                 struct clk *c = tegra_get_clock_by_name(cap_clks_names[i]);
304                 if (!c) {
305                         pr_err("%s: failed to find edp cap clock %s\n",
306                                __func__, cap_clks_names[i]);
307                         return -ENODEV;
308                 }
309                 cap_clks[i] = c;
310         }
311
312         edp_entry = find_edp_entry(sku, regulator_mA);
313         if (!edp_entry) {
314                 pr_info("%s: no core edp table for sku %d, %d mA\n",
315                        __func__, sku, regulator_mA);
316                 return -ENODATA;
317         }
318
319         limits->sku = sku;
320         limits->cap_clocks = cap_clks;
321         limits->cap_clocks_num = CAP_CLKS_NUM;
322         limits->temperatures = temperatures;
323         limits->temperature_ranges = TEMPERATURE_RANGES;
324         limits->core_modules_states = CORE_MODULES_STATES;
325
326         cap_rates = &edp_entry->cap_scpu_on[0][0][0][0];
327         limits->cap_rates_scpu_on = cap_rates;
328         for (i = 0; i < TOTAL_CAPS; i++, cap_rates++) {
329                 unsigned long rate = *cap_rates * edp_entry->mult;
330                 *cap_rates = clip_cap_rate(cap_clks[i % CAP_CLKS_NUM], rate);
331         }
332
333         cap_rates = &edp_entry->cap_scpu_off[0][0][0][0];
334         limits->cap_rates_scpu_off = cap_rates;
335         for (i = 0; i < TOTAL_CAPS; i++, cap_rates++) {
336                 unsigned long rate = *cap_rates * edp_entry->mult;
337                 *cap_rates = clip_cap_rate(cap_clks[i % CAP_CLKS_NUM], rate);
338         }
339
340         return 0;
341 }