ARM: tegra11: power: Add CPU EDP safety limits
[linux-3.10.git] / arch / arm / mach-tegra / edp.c
1 /*
2  * arch/arm/mach-tegra/edp.c
3  *
4  * Copyright (C) 2011-2012, 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 version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  * 02111-1307, USA
19  */
20
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <linux/seq_file.h>
24 #include <linux/slab.h>
25 #include <linux/module.h>
26 #include <linux/uaccess.h>
27 #include <mach/edp.h>
28
29 #include "fuse.h"
30 #include "dvfs.h"
31 #include "clock.h"
32 #include "cpu-tegra.h"
33
34 #define FREQ_STEP 12750000
35 #define OVERRIDE_DEFAULT 6000
36
37 static struct tegra_edp_limits *edp_limits;
38 static int edp_limits_size;
39 static unsigned int regulator_cur;
40 /* Value to subtract from regulator current limit */
41 static unsigned int edp_reg_override_mA = OVERRIDE_DEFAULT;
42
43 static const unsigned int *system_edp_limits;
44
45 /*
46  * Temperature step size cannot be less than 4C because of hysteresis
47  * delta
48  * Code assumes different temperatures for the same speedo_id /
49  * regulator_cur are adjacent in the table, and higest regulator_cur
50  * comes first
51  */
52 static char __initdata tegra_edp_vdd_cpu_map[] = {
53         0x00, 0x2f, 0x17, 0x7d, 0x73, 0x73, 0x73, 0x00,
54         0x2f, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f,
55         0x3c, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f, 0x4b,
56         0x82, 0x78, 0x78, 0x78, 0x00, 0x2f, 0x55, 0x82,
57         0x78, 0x78, 0x78, 0x00, 0x28, 0x17, 0x7d, 0x73,
58         0x73, 0x73, 0x00, 0x28, 0x2d, 0x82, 0x78, 0x78,
59         0x78, 0x00, 0x28, 0x3c, 0x82, 0x78, 0x78, 0x78,
60         0x00, 0x28, 0x4b, 0x82, 0x78, 0x78, 0x73, 0x00,
61         0x28, 0x55, 0x82, 0x78, 0x78, 0x69, 0x00, 0x23,
62         0x17, 0x7d, 0x73, 0x73, 0x73, 0x00, 0x23, 0x2d,
63         0x82, 0x78, 0x78, 0x78, 0x00, 0x23, 0x3c, 0x82,
64         0x78, 0x78, 0x6e, 0x00, 0x23, 0x4b, 0x82, 0x78,
65         0x78, 0x64, 0x00, 0x23, 0x55, 0x82, 0x78, 0x6e,
66         0x5a, 0x00, 0x1e, 0x17, 0x7d, 0x73, 0x73, 0x64,
67         0x00, 0x1e, 0x2d, 0x82, 0x78, 0x78, 0x69, 0x00,
68         0x1e, 0x3c, 0x82, 0x78, 0x78, 0x64, 0x00, 0x1e,
69         0x4b, 0x82, 0x78, 0x6e, 0x5a, 0x00, 0x1e, 0x55,
70         0x82, 0x78, 0x64, 0x50, 0x00, 0x19, 0x17, 0x7d,
71         0x73, 0x69, 0x55, 0x00, 0x19, 0x2d, 0x82, 0x78,
72         0x6e, 0x5a, 0x00, 0x19, 0x3c, 0x82, 0x78, 0x69,
73         0x55, 0x00, 0x19, 0x4b, 0x82, 0x78, 0x5f, 0x4b,
74         0x00, 0x19, 0x55, 0x82, 0x73, 0x55, 0x3c, 0x01,
75         0x2f, 0x17, 0x7d, 0x73, 0x73, 0x73, 0x01, 0x2f,
76         0x2d, 0x82, 0x78, 0x78, 0x78, 0x01, 0x2f, 0x3c,
77         0x82, 0x78, 0x78, 0x78, 0x01, 0x2f, 0x4b, 0x82,
78         0x78, 0x78, 0x78, 0x01, 0x2f, 0x55, 0x82, 0x78,
79         0x78, 0x78, 0x01, 0x28, 0x17, 0x7d, 0x73, 0x73,
80         0x73, 0x01, 0x28, 0x2d, 0x82, 0x78, 0x78, 0x78,
81         0x01, 0x28, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x01,
82         0x28, 0x4b, 0x82, 0x78, 0x78, 0x73, 0x01, 0x28,
83         0x55, 0x82, 0x78, 0x78, 0x69, 0x01, 0x23, 0x17,
84         0x7d, 0x73, 0x73, 0x73, 0x01, 0x23, 0x2d, 0x82,
85         0x78, 0x78, 0x78, 0x01, 0x23, 0x3c, 0x82, 0x78,
86         0x78, 0x6e, 0x01, 0x23, 0x4b, 0x82, 0x78, 0x78,
87         0x64, 0x01, 0x23, 0x55, 0x82, 0x78, 0x6e, 0x5a,
88         0x01, 0x1e, 0x17, 0x7d, 0x73, 0x73, 0x64, 0x01,
89         0x1e, 0x2d, 0x82, 0x78, 0x78, 0x69, 0x01, 0x1e,
90         0x3c, 0x82, 0x78, 0x78, 0x64, 0x01, 0x1e, 0x4b,
91         0x82, 0x78, 0x6e, 0x5a, 0x01, 0x1e, 0x55, 0x82,
92         0x78, 0x64, 0x50, 0x01, 0x19, 0x17, 0x7d, 0x73,
93         0x69, 0x55, 0x01, 0x19, 0x2d, 0x82, 0x78, 0x6e,
94         0x5a, 0x01, 0x19, 0x3c, 0x82, 0x78, 0x69, 0x55,
95         0x01, 0x19, 0x4b, 0x82, 0x78, 0x5f, 0x4b, 0x01,
96         0x19, 0x55, 0x82, 0x73, 0x55, 0x3c, 0x02, 0x3d,
97         0x17, 0x87, 0x7d, 0x7d, 0x7d, 0x02, 0x3d, 0x2d,
98         0x8c, 0x82, 0x82, 0x82, 0x02, 0x3d, 0x3c, 0x8c,
99         0x82, 0x82, 0x82, 0x02, 0x3d, 0x4b, 0x8c, 0x82,
100         0x82, 0x82, 0x02, 0x3d, 0x55, 0x8c, 0x82, 0x82,
101         0x82, 0x02, 0x32, 0x17, 0x87, 0x7d, 0x7d, 0x7d,
102         0x02, 0x32, 0x2d, 0x8c, 0x82, 0x82, 0x82, 0x02,
103         0x32, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x02, 0x32,
104         0x4b, 0x8c, 0x82, 0x82, 0x78, 0x02, 0x32, 0x55,
105         0x8c, 0x82, 0x82, 0x6e, 0x02, 0x28, 0x17, 0x87,
106         0x7d, 0x7d, 0x73, 0x02, 0x28, 0x2d, 0x8c, 0x82,
107         0x82, 0x78, 0x02, 0x28, 0x3c, 0x8c, 0x82, 0x82,
108         0x73, 0x02, 0x28, 0x4b, 0x8c, 0x82, 0x78, 0x69,
109         0x02, 0x28, 0x55, 0x8c, 0x82, 0x6e, 0x5a, 0x02,
110         0x23, 0x17, 0x87, 0x7d, 0x7d, 0x69, 0x02, 0x23,
111         0x2d, 0x8c, 0x82, 0x82, 0x6e, 0x02, 0x23, 0x3c,
112         0x8c, 0x82, 0x78, 0x69, 0x02, 0x23, 0x4b, 0x8c,
113         0x82, 0x6e, 0x5a, 0x02, 0x23, 0x55, 0x8c, 0x82,
114         0x64, 0x50, 0x03, 0x3d, 0x17, 0x87, 0x7d, 0x7d,
115         0x7d, 0x03, 0x3d, 0x2d, 0x8c, 0x82, 0x82, 0x82,
116         0x03, 0x3d, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x03,
117         0x3d, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x3d,
118         0x55, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x32, 0x17,
119         0x87, 0x7d, 0x7d, 0x7d, 0x03, 0x32, 0x2d, 0x8c,
120         0x82, 0x82, 0x82, 0x03, 0x32, 0x3c, 0x8c, 0x82,
121         0x82, 0x82, 0x03, 0x32, 0x4b, 0x8c, 0x82, 0x82,
122         0x78, 0x03, 0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e,
123         0x03, 0x28, 0x17, 0x87, 0x7d, 0x7d, 0x73, 0x03,
124         0x28, 0x2d, 0x8c, 0x82, 0x82, 0x78, 0x03, 0x28,
125         0x3c, 0x8c, 0x82, 0x82, 0x73, 0x03, 0x28, 0x4b,
126         0x8c, 0x82, 0x78, 0x69, 0x03, 0x28, 0x55, 0x8c,
127         0x82, 0x6e, 0x5a, 0x03, 0x23, 0x17, 0x87, 0x7d,
128         0x7d, 0x69, 0x03, 0x23, 0x2d, 0x8c, 0x82, 0x82,
129         0x6e, 0x03, 0x23, 0x3c, 0x8c, 0x82, 0x78, 0x69,
130         0x03, 0x23, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x03,
131         0x23, 0x55, 0x8c, 0x82, 0x64, 0x50, 0x04, 0x32,
132         0x17, 0x91, 0x87, 0x87, 0x87, 0x04, 0x32, 0x2d,
133         0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x32, 0x3c, 0x96,
134         0x8c, 0x8c, 0x8c, 0x04, 0x32, 0x46, 0x96, 0x8c,
135         0x8c, 0x8c, 0x04, 0x32, 0x4b, 0x82, 0x78, 0x78,
136         0x78, 0x04, 0x32, 0x55, 0x82, 0x78, 0x78, 0x78,
137         0x04, 0x2f, 0x17, 0x91, 0x87, 0x87, 0x87, 0x04,
138         0x2f, 0x2d, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x2f,
139         0x3c, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x2f, 0x46,
140         0x96, 0x8c, 0x8c, 0x82, 0x04, 0x2f, 0x4b, 0x82,
141         0x78, 0x78, 0x78, 0x04, 0x2f, 0x55, 0x82, 0x78,
142         0x78, 0x78, 0x04, 0x28, 0x17, 0x91, 0x87, 0x87,
143         0x87, 0x04, 0x28, 0x2d, 0x96, 0x8c, 0x8c, 0x82,
144         0x04, 0x28, 0x3c, 0x96, 0x8c, 0x8c, 0x82, 0x04,
145         0x28, 0x46, 0x96, 0x8c, 0x8c, 0x78, 0x04, 0x28,
146         0x4b, 0x82, 0x78, 0x78, 0x78, 0x04, 0x28, 0x55,
147         0x82, 0x78, 0x78, 0x6e, 0x04, 0x23, 0x17, 0x91,
148         0x87, 0x87, 0x73, 0x04, 0x23, 0x2d, 0x96, 0x8c,
149         0x8c, 0x78, 0x04, 0x23, 0x3c, 0x96, 0x8c, 0x82,
150         0x78, 0x04, 0x23, 0x46, 0x96, 0x8c, 0x82, 0x6e,
151         0x04, 0x23, 0x4b, 0x82, 0x78, 0x78, 0x6e, 0x04,
152         0x23, 0x55, 0x82, 0x78, 0x78, 0x64, 0x04, 0x1e,
153         0x17, 0x91, 0x87, 0x7d, 0x69, 0x04, 0x1e, 0x2d,
154         0x96, 0x8c, 0x82, 0x6e, 0x04, 0x1e, 0x3c, 0x96,
155         0x8c, 0x78, 0x64, 0x04, 0x1e, 0x46, 0x96, 0x8c,
156         0x78, 0x5a, 0x04, 0x1e, 0x4b, 0x82, 0x78, 0x78,
157         0x5a, 0x04, 0x1e, 0x55, 0x82, 0x78, 0x64, 0x50,
158         0x04, 0x19, 0x17, 0x91, 0x87, 0x69, 0x55, 0x04,
159         0x19, 0x2d, 0x96, 0x8c, 0x6e, 0x5a, 0x04, 0x19,
160         0x3c, 0x96, 0x82, 0x6e, 0x55, 0x04, 0x19, 0x46,
161         0x96, 0x82, 0x64, 0x50, 0x04, 0x19, 0x4b, 0x82,
162         0x78, 0x64, 0x50, 0x04, 0x19, 0x55, 0x82, 0x78,
163         0x55, 0x3c, 0x05, 0x64, 0x17, 0xa5, 0x9b, 0x9b,
164         0x9b, 0x05, 0x64, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0,
165         0x05, 0x64, 0x3c, 0xaa, 0xa0, 0xa0, 0xa0, 0x05,
166         0x64, 0x46, 0xaa, 0xa0, 0xa0, 0xa0, 0x05, 0x64,
167         0x4b, 0x8c, 0x82, 0x82, 0x82, 0x05, 0x64, 0x55,
168         0x8c, 0x82, 0x82, 0x82, 0x05, 0x50, 0x17, 0xa5,
169         0x9b, 0x9b, 0x9b, 0x05, 0x50, 0x2d, 0xaa, 0xa0,
170         0xa0, 0xa0, 0x05, 0x50, 0x3c, 0xaa, 0xa0, 0xa0,
171         0x96, 0x05, 0x50, 0x46, 0xaa, 0xa0, 0xa0, 0x96,
172         0x05, 0x50, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x05,
173         0x50, 0x55, 0x8c, 0x82, 0x82, 0x82, 0x05, 0x3c,
174         0x17, 0xa5, 0x9b, 0x9b, 0x87, 0x05, 0x3c, 0x2d,
175         0xaa, 0xa0, 0xa0, 0x8c, 0x05, 0x3c, 0x3c, 0xaa,
176         0xa0, 0x96, 0x82, 0x05, 0x3c, 0x46, 0xaa, 0xa0,
177         0x96, 0x78, 0x05, 0x3c, 0x4b, 0x8c, 0x82, 0x82,
178         0x78, 0x05, 0x3c, 0x55, 0x8c, 0x82, 0x82, 0x6e,
179         0x05, 0x28, 0x17, 0xa5, 0x91, 0x7d, 0x69, 0x05,
180         0x28, 0x2d, 0xaa, 0x96, 0x82, 0x6e, 0x05, 0x28,
181         0x3c, 0xaa, 0x96, 0x78, 0x64, 0x05, 0x28, 0x46,
182         0xaa, 0x8c, 0x6e, 0x5a, 0x05, 0x28, 0x4b, 0x8c,
183         0x82, 0x6e, 0x5a, 0x05, 0x28, 0x55, 0x8c, 0x82,
184         0x64, 0x50, 0x06, 0x3d, 0x17, 0xa5, 0x9b, 0x7d,
185         0x7d, 0x06, 0x3d, 0x2d, 0xaa, 0xa0, 0x82, 0x82,
186         0x06, 0x3d, 0x3c, 0xaa, 0xa0, 0x82, 0x82, 0x06,
187         0x3d, 0x46, 0xaa, 0xa0, 0x82, 0x82, 0x06, 0x3d,
188         0x4b, 0x8c, 0x82, 0x82, 0x82, 0x06, 0x3d, 0x55,
189         0x8c, 0x82, 0x82, 0x82, 0x06, 0x32, 0x17, 0xa5,
190         0x9b, 0x7d, 0x7d, 0x06, 0x32, 0x2d, 0xaa, 0xa0,
191         0x82, 0x82, 0x06, 0x32, 0x3c, 0xaa, 0xa0, 0x82,
192         0x82, 0x06, 0x32, 0x46, 0xaa, 0xa0, 0x82, 0x78,
193         0x06, 0x32, 0x4b, 0x8c, 0x82, 0x82, 0x78, 0x06,
194         0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e, 0x06, 0x28,
195         0x17, 0xa5, 0x9b, 0x7d, 0x73, 0x06, 0x28, 0x2d,
196         0xaa, 0xa0, 0x82, 0x78, 0x06, 0x28, 0x3c, 0xaa,
197         0x96, 0x82, 0x73, 0x06, 0x28, 0x46, 0xaa, 0x96,
198         0x78, 0x69, 0x06, 0x28, 0x4b, 0x8c, 0x82, 0x78,
199         0x69, 0x06, 0x28, 0x55, 0x8c, 0x82, 0x6e, 0x5a,
200         0x06, 0x23, 0x17, 0xa5, 0x91, 0x7d, 0x69, 0x06,
201         0x23, 0x2d, 0xaa, 0x96, 0x82, 0x6e, 0x06, 0x23,
202         0x3c, 0xaa, 0x96, 0x78, 0x69, 0x06, 0x23, 0x46,
203         0xaa, 0x8c, 0x6e, 0x5a, 0x06, 0x23, 0x4b, 0x8c,
204         0x82, 0x6e, 0x5a, 0x06, 0x23, 0x55, 0x8c, 0x82,
205         0x64, 0x50, 0x07, 0x3b, 0x17, 0x7d, 0x73, 0x73,
206         0x73, 0x07, 0x3b, 0x2d, 0x82, 0x78, 0x78, 0x78,
207         0x07, 0x3b, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x07,
208         0x3b, 0x4b, 0x82, 0x78, 0x78, 0x78, 0x07, 0x3b,
209         0x5a, 0x82, 0x78, 0x78, 0x78, 0x07, 0x32, 0x17,
210         0x7d, 0x73, 0x73, 0x73, 0x07, 0x32, 0x2d, 0x82,
211         0x78, 0x78, 0x78, 0x07, 0x32, 0x3c, 0x82, 0x78,
212         0x78, 0x78, 0x07, 0x32, 0x4b, 0x82, 0x78, 0x78,
213         0x78, 0x07, 0x32, 0x5a, 0x82, 0x78, 0x6e, 0x64,
214         0x07, 0x28, 0x17, 0x7d, 0x73, 0x73, 0x69, 0x07,
215         0x28, 0x2d, 0x82, 0x78, 0x78, 0x6e, 0x07, 0x28,
216         0x3c, 0x82, 0x78, 0x78, 0x64, 0x07, 0x28, 0x4b,
217         0x82, 0x78, 0x78, 0x64, 0x07, 0x28, 0x5a, 0x82,
218         0x78, 0x64, 0x50, 0x07, 0x23, 0x17, 0x7d, 0x73,
219         0x73, 0x5f, 0x07, 0x23, 0x2d, 0x82, 0x78, 0x78,
220         0x64, 0x07, 0x23, 0x3c, 0x82, 0x78, 0x78, 0x64,
221         0x07, 0x23, 0x4b, 0x82, 0x78, 0x64, 0x50, 0x07,
222         0x23, 0x5a, 0x82, 0x78, 0x5a, 0x46, 0x08, 0x3b,
223         0x17, 0x7d, 0x73, 0x73, 0x73, 0x08, 0x3b, 0x2d,
224         0x82, 0x78, 0x78, 0x78, 0x08, 0x3b, 0x3c, 0x82,
225         0x78, 0x78, 0x78, 0x08, 0x3b, 0x4b, 0x82, 0x78,
226         0x78, 0x78, 0x08, 0x3b, 0x5a, 0x82, 0x78, 0x78,
227         0x78, 0x08, 0x32, 0x17, 0x7d, 0x73, 0x73, 0x73,
228         0x08, 0x32, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x08,
229         0x32, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x08, 0x32,
230         0x4b, 0x82, 0x78, 0x78, 0x78, 0x08, 0x32, 0x5a,
231         0x82, 0x78, 0x6e, 0x64, 0x08, 0x28, 0x17, 0x7d,
232         0x73, 0x73, 0x69, 0x08, 0x28, 0x2d, 0x82, 0x78,
233         0x78, 0x6e, 0x08, 0x28, 0x3c, 0x82, 0x78, 0x78,
234         0x64, 0x08, 0x28, 0x4b, 0x82, 0x78, 0x78, 0x64,
235         0x08, 0x28, 0x5a, 0x82, 0x78, 0x64, 0x50, 0x08,
236         0x23, 0x17, 0x7d, 0x73, 0x73, 0x5f, 0x08, 0x23,
237         0x2d, 0x82, 0x78, 0x78, 0x64, 0x08, 0x23, 0x3c,
238         0x82, 0x78, 0x78, 0x64, 0x08, 0x23, 0x4b, 0x82,
239         0x78, 0x64, 0x50, 0x08, 0x23, 0x5a, 0x82, 0x78,
240         0x5a, 0x46, 0x0c, 0x52, 0x17, 0xa5, 0x9b, 0x9b,
241         0x9b, 0x0c, 0x52, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0,
242         0x0c, 0x52, 0x3c, 0xaa, 0xa0, 0xa0, 0xa0, 0x0c,
243         0x52, 0x46, 0xaa, 0xa0, 0xa0, 0xa0, 0x0c, 0x52,
244         0x4b, 0x8c, 0x82, 0x82, 0x82, 0x0c, 0x52, 0x55,
245         0x8c, 0x82, 0x82, 0x82, 0x0c, 0x42, 0x17, 0xa5,
246         0x9b, 0x9b, 0x91, 0x0c, 0x42, 0x2d, 0xaa, 0xa0,
247         0xa0, 0x96, 0x0c, 0x42, 0x3c, 0xaa, 0xa0, 0xa0,
248         0x96, 0x0c, 0x42, 0x46, 0xaa, 0xa0, 0xa0, 0x96,
249         0x0c, 0x42, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x0c,
250         0x42, 0x55, 0x8c, 0x82, 0x82, 0x82, 0x0c, 0x3d,
251         0x17, 0xa5, 0x9b, 0x9b, 0x91, 0x0c, 0x3d, 0x2d,
252         0xaa, 0xa0, 0xa0, 0x96, 0x0c, 0x3d, 0x3c, 0xaa,
253         0xa0, 0xa0, 0x8c, 0x0c, 0x3d, 0x46, 0xaa, 0xa0,
254         0x96, 0x8c, 0x0c, 0x3d, 0x4b, 0x8c, 0x82, 0x82,
255         0x82, 0x0c, 0x3d, 0x55, 0x8c, 0x82, 0x82, 0x82,
256         0x0c, 0x32, 0x17, 0xa5, 0x9b, 0x91, 0x87, 0x0c,
257         0x32, 0x2d, 0xaa, 0xa0, 0x96, 0x8c, 0x0c, 0x32,
258         0x3c, 0xaa, 0xa0, 0x96, 0x82, 0x0c, 0x32, 0x46,
259         0xaa, 0xa0, 0x8c, 0x78, 0x0c, 0x32, 0x4b, 0x8c,
260         0x82, 0x82, 0x78, 0x0c, 0x32, 0x55, 0x8c, 0x82,
261         0x82, 0x6e, 0x0c, 0x28, 0x17, 0xa5, 0x9b, 0x87,
262         0x73, 0x0c, 0x28, 0x2d, 0xaa, 0xa0, 0x8c, 0x78,
263         0x0c, 0x28, 0x3c, 0xaa, 0x96, 0x82, 0x73, 0x0c,
264         0x28, 0x46, 0xaa, 0x96, 0x78, 0x69, 0x0c, 0x28,
265         0x4b, 0x8c, 0x82, 0x78, 0x69, 0x0c, 0x28, 0x55,
266         0x8c, 0x82, 0x6e, 0x5a, 0x0c, 0x23, 0x17, 0xa5,
267         0x91, 0x7d, 0x69, 0x0c, 0x23, 0x2d, 0xaa, 0x96,
268         0x82, 0x6e, 0x0c, 0x23, 0x3c, 0xaa, 0x96, 0x78,
269         0x69, 0x0c, 0x23, 0x46, 0xaa, 0x8c, 0x6e, 0x5a,
270         0x0c, 0x23, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x0c,
271         0x23, 0x55, 0x8c, 0x82, 0x64, 0x50, 0x0d, 0x64,
272         0x17, 0xa5, 0x9b, 0x9b, 0x9b, 0x0d, 0x64, 0x2d,
273         0xaa, 0xa0, 0xa0, 0xa0, 0x0d, 0x64, 0x3c, 0xaa,
274         0xa0, 0xa0, 0xa0, 0x0d, 0x64, 0x46, 0xaa, 0xa0,
275         0xa0, 0xa0, 0x0d, 0x64, 0x4b, 0x8c, 0x82, 0x82,
276         0x82, 0x0d, 0x64, 0x55, 0x8c, 0x82, 0x82, 0x82,
277         0x0d, 0x50, 0x17, 0xa5, 0x9b, 0x9b, 0x9b, 0x0d,
278         0x50, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0, 0x0d, 0x50,
279         0x3c, 0xaa, 0xa0, 0xa0, 0x96, 0x0d, 0x50, 0x46,
280         0xaa, 0xa0, 0xa0, 0x96, 0x0d, 0x50, 0x4b, 0x8c,
281         0x82, 0x82, 0x82, 0x0d, 0x50, 0x55, 0x8c, 0x82,
282         0x82, 0x82, 0x0d, 0x3c, 0x17, 0xa5, 0x9b, 0x9b,
283         0x87, 0x0d, 0x3c, 0x2d, 0xaa, 0xa0, 0xa0, 0x8c,
284         0x0d, 0x3c, 0x3c, 0xaa, 0xa0, 0x96, 0x82, 0x0d,
285         0x3c, 0x46, 0xaa, 0xa0, 0x96, 0x78, 0x0d, 0x3c,
286         0x4b, 0x8c, 0x82, 0x82, 0x78, 0x0d, 0x3c, 0x55,
287         0x8c, 0x82, 0x82, 0x6e, 0x0d, 0x28, 0x17, 0xa5,
288         0x91, 0x7d, 0x69, 0x0d, 0x28, 0x2d, 0xaa, 0x96,
289         0x82, 0x6e, 0x0d, 0x28, 0x3c, 0xaa, 0x96, 0x78,
290         0x64, 0x0d, 0x28, 0x46, 0xaa, 0x8c, 0x6e, 0x5a,
291         0x0d, 0x28, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x0d,
292         0x28, 0x55, 0x8c, 0x82, 0x64, 0x50,
293 };
294
295
296 static struct tegra_system_edp_entry __initdata tegra_system_edp_map[] = {
297
298 /* {SKU, power-limit (in 100mW), {freq limits (in 10Mhz)} } */
299
300         {  1,  49, {130, 120, 120, 120} },
301         {  1,  44, {130, 120, 120, 110} },
302         {  1,  37, {130, 120, 110, 100} },
303         {  1,  35, {130, 120, 110,  90} },
304         {  1,  29, {130, 120, 100,  80} },
305         {  1,  27, {130, 120,  90,  80} },
306         {  1,  25, {130, 110,  80,  60} },
307         {  1,  21, {130, 100,  80,  40} },
308
309         {  4,  49, {130, 120, 120, 120} },
310         {  4,  44, {130, 120, 120, 110} },
311         {  4,  37, {130, 120, 110, 100} },
312         {  4,  35, {130, 120, 110,  90} },
313         {  4,  29, {130, 120, 100,  80} },
314         {  4,  27, {130, 120,  90,  80} },
315         {  4,  25, {130, 110,  80,  60} },
316         {  4,  21, {130, 100,  80,  40} },
317 };
318
319 /*
320  * "Safe entry" to be used when no match for speedo_id /
321  * regulator_cur is found; must be the last one
322  */
323 static struct tegra_edp_limits edp_default_limits[] = {
324         {85, {1000000, 1000000, 1000000, 1000000} },
325 };
326
327 /* Constants for EDP calculations */
328 static int temperatures[] = { 23, 40, 50, 60, 70, 75, 80, 85, 90, 95 };
329 static struct tegra_edp_cpu_leakage_params leakage_params[] = {
330         {
331                 .cpu_speedo_id      = 0, /* A01 CPU */
332                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
333                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
334                 .leakage_consts_ijk = {
335                          /* i = 0 */
336                          { {  -42746668,   -5458429,   164998,  -1711, },
337                            {  178262421,   13375684,  -411791,   4590, },
338                            { -228866784,  -10482993,   331248,  -4062, },
339                            {   94301550,    2618719,   -85983,   1193, },
340                          },
341                          /* i = 1 */
342                          { { -256611791,   49677413, -1655785,  14917, },
343                            {  584675433, -132620939,  4541560, -41812, },
344                            { -398106336,  115987156, -4102328,  38737, },
345                            {   68897184,  -33030745,  1217839, -11801, },
346                          },
347                          /* i = 2 */
348                          { {  186324676,  -36019083,  1177969, -10669, },
349                            { -439237936,   98429131, -3276444,  30301, },
350                            {  315060898,  -88635036,  3004777, -28474, },
351                            {  -60854399,   26267188,  -907121,   8844, },
352                          },
353                          /* i = 3 */
354                          { {  -35432997,    6154621,  -202200,   1830, },
355                            {   87402153,  -16908683,   565152,  -5220, },
356                            {  -67775314,   15326770,  -521221,   4927, },
357                            {   15618709,   -4576116,   158401,  -1538, },
358                          },
359                  },
360         },
361         {
362                 .cpu_speedo_id      = 1, /* A01P+ CPU */
363                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
364                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
365                 .leakage_consts_ijk = {
366                          /* i = 0 */
367                          { {  -42746668,   -5458429,   164998,  -1711, },
368                            {  178262421,   13375684,  -411791,   4590, },
369                            { -228866784,  -10482993,   331248,  -4062, },
370                            {   94301550,    2618719,   -85983,   1193, },
371                          },
372                          /* i = 1 */
373                          { { -256611791,   49677413, -1655785,  14917, },
374                            {  584675433, -132620939,  4541560, -41812, },
375                            { -398106336,  115987156, -4102328,  38737, },
376                            {   68897184,  -33030745,  1217839, -11801, },
377                          },
378                          /* i = 2 */
379                          { {  186324676,  -36019083,  1177969, -10669, },
380                            { -439237936,   98429131, -3276444,  30301, },
381                            {  315060898,  -88635036,  3004777, -28474, },
382                            {  -60854399,   26267188,  -907121,   8844, },
383                          },
384                          /* i = 3 */
385                          { {  -35432997,    6154621,  -202200,   1830, },
386                            {   87402153,  -16908683,   565152,  -5220, },
387                            {  -67775314,   15326770,  -521221,   4927, },
388                            {   15618709,   -4576116,   158401,  -1538, },
389                          },
390                  },
391                 .safety_cap = { 1810500, 1810500, 1606500, 1606500 },
392         },
393         {
394                 .cpu_speedo_id      = 2, /* A01P+ fast CPU */
395                 .dyn_consts_n       = { 1091747, 2035205, 2978661, 3922119 },
396                 .leakage_consts_n   = {  538991,  752463,  959441, 1150000 },
397                 .leakage_consts_ijk = {
398                          /* i = 0 */
399                          { {  -42746668,   -5458429,   164998,  -1711, },
400                            {  178262421,   13375684,  -411791,   4590, },
401                            { -228866784,  -10482993,   331248,  -4062, },
402                            {   94301550,    2618719,   -85983,   1193, },
403                          },
404                          /* i = 1 */
405                          { { -256611791,   49677413, -1655785,  14917, },
406                            {  584675433, -132620939,  4541560, -41812, },
407                            { -398106336,  115987156, -4102328,  38737, },
408                            {   68897184,  -33030745,  1217839, -11801, },
409                          },
410                          /* i = 2 */
411                          { {  186324676,  -36019083,  1177969, -10669, },
412                            { -439237936,   98429131, -3276444,  30301, },
413                            {  315060898,  -88635036,  3004777, -28474, },
414                            {  -60854399,   26267188,  -907121,   8844, },
415                          },
416                          /* i = 3 */
417                          { {  -35432997,    6154621,  -202200,   1830, },
418                            {   87402153,  -16908683,   565152,  -5220, },
419                            {  -67775314,   15326770,  -521221,   4927, },
420                            {   15618709,   -4576116,   158401,  -1538, },
421                          },
422                  },
423                 .safety_cap = { 1912500, 1912500, 1708500, 1708500 },
424         },
425 };
426
427 static struct tegra_edp_freq_voltage_table *freq_voltage_lut;
428 static unsigned int freq_voltage_lut_size;
429
430 static inline s64 edp_pow(s64 val, int pwr)
431 {
432         s64 retval = 1;
433
434         while (pwr) {
435                 if (pwr & 1)
436                         retval *= val;
437                 pwr >>= 1;
438                 if (pwr)
439                         val *= val;
440         }
441
442         return retval;
443 }
444
445 /*
446  * Find the maximum frequency that results in dynamic and leakage current that
447  * is less than the regulator current limit.
448  */
449 unsigned int edp_calculate_maxf(struct tegra_edp_cpu_leakage_params *params,
450                                 int temp_C,
451                                 int iddq_mA,
452                                 int n_cores_idx)
453 {
454         unsigned int voltage_mV, freq_KHz;
455         unsigned int cur_effective = regulator_cur - edp_reg_override_mA;
456         int f, i, j, k;
457         s64 leakage_mA, dyn_mA, leakage_calc_step;
458
459         for (f = freq_voltage_lut_size - 1; f >= 0; f--) {
460                 freq_KHz = freq_voltage_lut[f].freq / 1000;
461                 voltage_mV = freq_voltage_lut[f].voltage_mV;
462
463                 /* Calculate leakage current */
464                 leakage_mA = 0;
465                 for (i = 0; i <= 3; i++) {
466                         for (j = 0; j <= 3; j++) {
467                                 for (k = 0; k <= 3; k++) {
468                                         leakage_calc_step =
469                                                 params->leakage_consts_ijk
470                                                 [i][j][k] * edp_pow(iddq_mA, i);
471                                         /* Convert (mA)^i to (A)^i */
472                                         leakage_calc_step =
473                                                 div64_s64(leakage_calc_step,
474                                                           edp_pow(1000, i));
475                                         leakage_calc_step *=
476                                                 edp_pow(voltage_mV, j);
477                                         /* Convert (mV)^i to (V)^i */
478                                         leakage_calc_step =
479                                                 div64_s64(leakage_calc_step,
480                                                           edp_pow(1000, j));
481                                         leakage_calc_step *=
482                                                 edp_pow(temp_C, k);
483                                         /* leakage_consts_ijk was X 100,000 */
484                                         leakage_calc_step =
485                                                 div64_s64(leakage_calc_step,
486                                                           100000);
487                                         leakage_mA += leakage_calc_step;
488                                 }
489                         }
490                 }
491                 leakage_mA *= params->leakage_consts_n[n_cores_idx];
492                 /* leakage_const_n was pre-multiplied by 1,000,000 */
493                 leakage_mA = div64_s64(leakage_mA, 1000000);
494
495                 /* Calculate dynamic current */
496                 dyn_mA = voltage_mV * freq_KHz / 1000;
497                 /* Convert mV to V */
498                 dyn_mA = div64_s64(dyn_mA, 1000);
499                 dyn_mA *= params->dyn_consts_n[n_cores_idx];
500                 /* dyn_const_n was pre-multiplied by 1,000,000 */
501                 dyn_mA = div64_s64(dyn_mA, 1000000);
502
503                 if ((leakage_mA + dyn_mA) <= cur_effective)
504                         return freq_KHz;
505         }
506         return 0;
507 }
508
509 static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
510                                 unsigned int cpu_speedo_idx)
511 {
512         unsigned int i, j, freq;
513         int voltage_mV;
514
515         for (i = 0, j = 0, freq = 0;
516                  i < freq_voltage_lut_size;
517                  i++, freq += FREQ_STEP) {
518
519                 /* Predict voltages */
520                 voltage_mV = tegra_dvfs_predict_millivolts(clk_cpu_g, freq);
521                 if (voltage_mV < 0) {
522                         pr_err("%s: couldn't predict voltage: freq %u; err %d",
523                                __func__, freq, voltage_mV);
524                         return -EINVAL;
525                 }
526
527                 /* Cache frequency / voltage / voltage constant relationship */
528                 freq_voltage_lut[i].freq = freq;
529                 freq_voltage_lut[i].voltage_mV = voltage_mV;
530         }
531         return 0;
532 }
533
534 int edp_find_speedo_idx(int cpu_speedo_id, unsigned int *cpu_speedo_idx)
535 {
536         int i;
537
538         for (i = 0; i < ARRAY_SIZE(leakage_params); i++)
539                 if (cpu_speedo_id == leakage_params[i].cpu_speedo_id) {
540                         *cpu_speedo_idx = i;
541                         return 0;
542                 }
543
544         pr_err("%s: couldn't find cpu speedo id %d in freq/voltage LUT\n",
545                __func__, cpu_speedo_id);
546         return -EINVAL;
547 }
548
549 static int init_cpu_edp_limits_calculated(void)
550 {
551         unsigned int temp_idx, n_cores_idx;
552         unsigned int cpu_g_minf, cpu_g_maxf;
553         unsigned int iddq_mA;
554         unsigned int cpu_speedo_idx;
555         struct tegra_edp_limits *edp_calculated_limits;
556         struct tegra_edp_cpu_leakage_params *params;
557         int ret;
558         struct clk *clk_cpu_g = tegra_get_clock_by_name("cpu_g");
559         int cpu_speedo_id = tegra_cpu_speedo_id();
560
561         /* Determine all inputs to EDP formula */
562         iddq_mA = tegra_get_cpu_iddq_value();
563         ret = edp_find_speedo_idx(cpu_speedo_id, &cpu_speedo_idx);
564         if (ret)
565                 return ret;
566
567         params = &leakage_params[cpu_speedo_idx];
568
569         edp_calculated_limits = kmalloc(sizeof(struct tegra_edp_limits)
570                                         * ARRAY_SIZE(temperatures), GFP_KERNEL);
571         BUG_ON(!edp_calculated_limits);
572
573         cpu_g_minf = 0;
574         cpu_g_maxf = clk_get_max_rate(clk_cpu_g);
575         freq_voltage_lut_size = (cpu_g_maxf - cpu_g_minf) / FREQ_STEP + 1;
576         freq_voltage_lut = kmalloc(sizeof(struct tegra_edp_freq_voltage_table)
577                                    * freq_voltage_lut_size, GFP_KERNEL);
578         if (!freq_voltage_lut) {
579                 pr_err("%s: failed alloc mem for freq/voltage LUT\n", __func__);
580                 return -ENOMEM;
581         }
582
583         ret = edp_relate_freq_voltage(clk_cpu_g, cpu_speedo_idx);
584         if (ret) {
585                 kfree(freq_voltage_lut);
586                 return ret;
587         }
588
589         /* Calculate EDP table */
590         for (temp_idx = 0; temp_idx < ARRAY_SIZE(temperatures); temp_idx++) {
591                 edp_calculated_limits[temp_idx].
592                         temperature = temperatures[temp_idx];
593                 for (n_cores_idx = 0; n_cores_idx < NR_CPUS; n_cores_idx++) {
594                         unsigned int cap;
595                         unsigned int limit =
596                                 edp_calculate_maxf(params,
597                                                    temperatures[temp_idx],
598                                                    iddq_mA,
599                                                    n_cores_idx);
600                         /* apply safety cap if it is specified */
601                         if (n_cores_idx < 4) {
602                                 cap = params->safety_cap[n_cores_idx];
603                                 if (cap && cap < limit)
604                                         limit = cap;
605                         }
606                         edp_calculated_limits[temp_idx].
607                                 freq_limits[n_cores_idx] = limit;
608                 }
609         }
610
611         /*
612          * If this is an EDP table update, need to overwrite old table.
613          * The old table's address must remain valid.
614          */
615         if (edp_limits != edp_default_limits) {
616                 memcpy(edp_limits, edp_calculated_limits,
617                        sizeof(struct tegra_edp_limits)
618                        * ARRAY_SIZE(temperatures));
619                 kfree(edp_calculated_limits);
620         }
621         else {
622                 edp_limits = edp_calculated_limits;
623                 edp_limits_size = ARRAY_SIZE(temperatures);
624         }
625
626         kfree(freq_voltage_lut);
627         return 0;
628 }
629
630 static int __init init_cpu_edp_limits_lookup(void)
631 {
632         int i, j;
633         struct tegra_edp_limits *e;
634         struct tegra_edp_vdd_cpu_entry *t;
635         int tsize;
636         int cpu_speedo_id = tegra_cpu_speedo_id();
637
638         t = (struct tegra_edp_vdd_cpu_entry *)tegra_edp_vdd_cpu_map;
639         tsize = sizeof(tegra_edp_vdd_cpu_map)
640                 / sizeof(struct tegra_edp_vdd_cpu_entry);
641
642         for (i = 0; i < tsize; i++) {
643                 if (t[i].speedo_id == cpu_speedo_id &&
644                     t[i].regulator_100mA <= regulator_cur / 100)
645                         break;
646         }
647
648         /* No entry found in tegra_edp_vdd_cpu_map */
649         if (i >= tsize)
650                 return -EINVAL;
651
652         /* Find all rows for this entry */
653         for (j = i + 1; j < tsize; j++) {
654                 if (t[i].speedo_id != t[j].speedo_id ||
655                     t[i].regulator_100mA != t[j].regulator_100mA)
656                         break;
657         }
658
659         edp_limits_size = j - i;
660         e = kmalloc(sizeof(struct tegra_edp_limits) * edp_limits_size,
661                     GFP_KERNEL);
662         BUG_ON(!e);
663
664         for (j = 0; j < edp_limits_size; j++) {
665                 e[j].temperature = (int)t[i+j].temperature;
666                 e[j].freq_limits[0] = (unsigned int)t[i+j].freq_limits[0]*10000;
667                 e[j].freq_limits[1] = (unsigned int)t[i+j].freq_limits[1]*10000;
668                 e[j].freq_limits[2] = (unsigned int)t[i+j].freq_limits[2]*10000;
669                 e[j].freq_limits[3] = (unsigned int)t[i+j].freq_limits[3]*10000;
670         }
671
672         if (edp_limits != edp_default_limits)
673                 kfree(edp_limits);
674
675         edp_limits = e;
676         return 0;
677 }
678
679 void tegra_recalculate_cpu_edp_limits(void)
680 {
681         if (tegra_chip_id == TEGRA11X)
682                 init_cpu_edp_limits_calculated();
683 }
684
685 /*
686  * Specify regulator current in mA, e.g. 5000mA
687  * Use 0 for default
688  */
689 void __init tegra_init_cpu_edp_limits(unsigned int regulator_mA)
690 {
691         if (!regulator_mA) {
692                 edp_limits = edp_default_limits;
693                 edp_limits_size = ARRAY_SIZE(edp_default_limits);
694                 return;
695         }
696         regulator_cur = regulator_mA + OVERRIDE_DEFAULT;
697
698         switch (tegra_chip_id) {
699         case TEGRA30:
700                 if (init_cpu_edp_limits_lookup() == 0)
701                         return;
702                 break;
703         case TEGRA11X:
704                 if (init_cpu_edp_limits_calculated() == 0)
705                         return;
706                 break;
707         case TEGRA20:
708         default:
709                 BUG();
710                 break;
711         }
712
713         edp_limits = edp_default_limits;
714         edp_limits_size = ARRAY_SIZE(edp_default_limits);
715 }
716
717 void __init tegra_init_system_edp_limits(unsigned int power_limit_mW)
718 {
719         int cpu_speedo_id = tegra_cpu_speedo_id();
720         int i;
721         unsigned int *e;
722         struct tegra_system_edp_entry *t = tegra_system_edp_map;
723         int tsize = ARRAY_SIZE(tegra_system_edp_map);
724
725         if (!power_limit_mW) {
726                 e = NULL;
727                 goto out;
728         }
729
730         for (i = 0; i < tsize; i++)
731                 if (t[i].speedo_id == cpu_speedo_id)
732                         break;
733
734         if (i >= tsize) {
735                 e = NULL;
736                 goto out;
737         }
738
739         do {
740                 if (t[i].power_limit_100mW <= power_limit_mW / 100)
741                         break;
742                 i++;
743         } while (i < tsize && t[i].speedo_id == cpu_speedo_id);
744
745         if (i >= tsize || t[i].speedo_id != cpu_speedo_id)
746                 i--; /* No low enough entry in the table, use best possible */
747
748         e = kmalloc(sizeof(unsigned int) * 4, GFP_KERNEL);
749         BUG_ON(!e);
750
751         e[0] = (unsigned int)t[i].freq_limits[0] * 10000;
752         e[1] = (unsigned int)t[i].freq_limits[1] * 10000;
753         e[2] = (unsigned int)t[i].freq_limits[2] * 10000;
754         e[3] = (unsigned int)t[i].freq_limits[3] * 10000;
755
756 out:
757         kfree(system_edp_limits);
758
759         system_edp_limits = e;
760 }
761
762
763 void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size)
764 {
765         *limits = edp_limits;
766         *size = edp_limits_size;
767 }
768
769 void tegra_get_system_edp_limits(const unsigned int **limits)
770 {
771         *limits = system_edp_limits;
772 }
773
774 #ifdef CONFIG_DEBUG_FS
775
776 static int edp_limit_debugfs_show(struct seq_file *s, void *data)
777 {
778         seq_printf(s, "%u\n", tegra_get_edp_limit(NULL));
779         return 0;
780 }
781
782 static int edp_debugfs_show(struct seq_file *s, void *data)
783 {
784         int i, th_idx;
785
786         tegra_get_edp_limit(&th_idx);
787         seq_printf(s, "-- VDD_CPU %sEDP table (%umA = %umA - %umA) --\n",
788                    edp_limits == edp_default_limits ? "default " : "",
789                    regulator_cur - edp_reg_override_mA,
790                    regulator_cur, edp_reg_override_mA);
791         seq_printf(s, "%6s %10s %10s %10s %10s\n",
792                    " Temp.", "1-core", "2-cores", "3-cores", "4-cores");
793         for (i = 0; i < edp_limits_size; i++) {
794                 seq_printf(s, "%c%3dC: %10u %10u %10u %10u\n",
795                            i == th_idx ? '>' : ' ',
796                            edp_limits[i].temperature,
797                            edp_limits[i].freq_limits[0],
798                            edp_limits[i].freq_limits[1],
799                            edp_limits[i].freq_limits[2],
800                            edp_limits[i].freq_limits[3]);
801         }
802
803         if (system_edp_limits) {
804                 seq_printf(s, "\n-- System EDP table --\n");
805                 seq_printf(s, "%10u %10u %10u %10u\n",
806                            system_edp_limits[0],
807                            system_edp_limits[1],
808                            system_edp_limits[2],
809                            system_edp_limits[3]);
810         }
811
812         return 0;
813 }
814
815 static int edp_reg_override_show(struct seq_file *s, void *data)
816 {
817         seq_printf(s, "Limit override: %u mA. Effective limit: %u mA\n",
818                    edp_reg_override_mA, regulator_cur - edp_reg_override_mA);
819         return 0;
820 }
821
822 static int edp_reg_override_write(struct file *file,
823         const char __user *userbuf, size_t count, loff_t *ppos)
824 {
825         char buf[32], *end;
826         unsigned int edp_reg_override_mA_temp;
827         unsigned int edp_reg_override_mA_prev = edp_reg_override_mA;
828
829         if (sizeof(buf) <= count)
830                 goto override_err;
831
832         if (copy_from_user(buf, userbuf, count))
833                 goto override_err;
834
835         /* terminate buffer and trim - white spaces may be appended
836          *  at the end when invoked from shell command line */
837         buf[count]='\0';
838         strim(buf);
839
840         edp_reg_override_mA_temp = simple_strtoul(buf, &end, 10);
841         if (*end != '\0')
842                 goto override_err;
843
844         if (edp_reg_override_mA_temp >= regulator_cur)
845                 goto override_err;
846
847         if (edp_reg_override_mA == edp_reg_override_mA_temp)
848                 return count;
849
850         edp_reg_override_mA = edp_reg_override_mA_temp;
851         if (init_cpu_edp_limits_calculated()) {
852                 /* Revert to previous override value if new value fails */
853                 edp_reg_override_mA = edp_reg_override_mA_prev;
854                 goto override_err;
855         }
856
857         if (tegra_cpu_set_speed_cap(NULL)) {
858                 pr_err("FAILED: Set CPU freq cap with new VDD_CPU EDP table\n");
859                 goto override_out;
860         }
861
862         pr_info("Reinitialized VDD_CPU EDP table with regulator current limit"
863                         " %u mA\n", regulator_cur - edp_reg_override_mA);
864
865         return count;
866
867 override_err:
868         pr_err("FAILED: Reinitialize VDD_CPU EDP table with override \"%s\"",
869                buf);
870 override_out:
871         return -EINVAL;
872 }
873
874 static int edp_debugfs_open(struct inode *inode, struct file *file)
875 {
876         return single_open(file, edp_debugfs_show, inode->i_private);
877 }
878
879 static int edp_limit_debugfs_open(struct inode *inode, struct file *file)
880 {
881         return single_open(file, edp_limit_debugfs_show, inode->i_private);
882 }
883
884 static int edp_reg_override_open(struct inode *inode, struct file *file)
885 {
886         return single_open(file, edp_reg_override_show, inode->i_private);
887 }
888
889 static const struct file_operations edp_debugfs_fops = {
890         .open           = edp_debugfs_open,
891         .read           = seq_read,
892         .llseek         = seq_lseek,
893         .release        = single_release,
894 };
895
896 static const struct file_operations edp_limit_debugfs_fops = {
897         .open           = edp_limit_debugfs_open,
898         .read           = seq_read,
899         .llseek         = seq_lseek,
900         .release        = single_release,
901 };
902
903 static const struct file_operations edp_reg_override_debugfs_fops = {
904         .open           = edp_reg_override_open,
905         .read           = seq_read,
906         .write          = edp_reg_override_write,
907         .llseek         = seq_lseek,
908         .release        = single_release,
909 };
910
911 static int __init tegra_edp_debugfs_init(void)
912 {
913         struct dentry *d_edp;
914         struct dentry *d_edp_limit;
915         struct dentry *d_edp_reg_override;
916         struct dentry *edp_dir;
917         struct dentry *vdd_cpu_dir;
918
919         edp_dir = debugfs_create_dir("edp", NULL);
920
921         if (!edp_dir)
922                 goto edp_dir_err;
923
924         vdd_cpu_dir = debugfs_create_dir("vdd_cpu", edp_dir);
925
926         if (!vdd_cpu_dir)
927                 goto vdd_cpu_dir_err;
928
929         d_edp = debugfs_create_file("edp", S_IRUGO, vdd_cpu_dir, NULL,
930                                 &edp_debugfs_fops);
931
932         if (!d_edp)
933                 goto edp_err;
934
935         d_edp_limit = debugfs_create_file("edp_limit", S_IRUGO, vdd_cpu_dir,
936                                 NULL, &edp_limit_debugfs_fops);
937
938         if (!d_edp_limit)
939                 goto edp_limit_err;
940
941         d_edp_reg_override = debugfs_create_file("edp_reg_override",
942                                 S_IRUGO | S_IWUSR, vdd_cpu_dir, NULL,
943                                 &edp_reg_override_debugfs_fops);
944
945         if (!d_edp_reg_override)
946                 goto edp_reg_override_err;
947
948         if (tegra_core_edp_debugfs_init(edp_dir))
949                 goto edp_reg_override_err;
950
951         return 0;
952
953 edp_reg_override_err:
954         debugfs_remove(d_edp_limit);
955 edp_limit_err:
956         debugfs_remove(d_edp);
957 edp_err:
958         debugfs_remove(vdd_cpu_dir);
959 vdd_cpu_dir_err:
960         debugfs_remove(edp_dir);
961 edp_dir_err:
962         return -ENOMEM;
963 }
964
965 late_initcall(tegra_edp_debugfs_init);
966 #endif /* CONFIG_DEBUG_FS */