cc119c7e913ccc77124dbe01c4fe68e028c63af2
[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         },
392 };
393
394 static struct tegra_edp_freq_voltage_table *freq_voltage_lut;
395 static unsigned int freq_voltage_lut_size;
396
397 static inline s64 edp_pow(s64 val, int pwr)
398 {
399         s64 retval = 1;
400
401         while (pwr) {
402                 if (pwr & 1)
403                         retval *= val;
404                 pwr >>= 1;
405                 if (pwr)
406                         val *= val;
407         }
408
409         return retval;
410 }
411
412 /*
413  * Find the maximum frequency that results in dynamic and leakage current that
414  * is less than the regulator current limit.
415  */
416 unsigned int edp_calculate_maxf(struct tegra_edp_cpu_leakage_params *params,
417                                 int temp_C,
418                                 int iddq_mA,
419                                 int n_cores_idx)
420 {
421         unsigned int voltage_mV, freq_MHz;
422         unsigned int cur_effective = regulator_cur - edp_reg_override_mA;
423         int f, i, j, k;
424         s64 leakage_mA, dyn_mA, leakage_calc_step;
425
426         for (f = freq_voltage_lut_size - 1; f >= 0; f--) {
427                 freq_MHz = freq_voltage_lut[f].freq / 1000000;
428                 voltage_mV = freq_voltage_lut[f].voltage_mV;
429
430                 /* Calculate leakage current */
431                 leakage_mA = 0;
432                 for (i = 0; i <= 3; i++) {
433                         for (j = 0; j <= 3; j++) {
434                                 for (k = 0; k <= 3; k++) {
435                                         leakage_calc_step =
436                                                 params->leakage_consts_ijk
437                                                 [i][j][k] * edp_pow(iddq_mA, i);
438                                         /* Convert (mA)^i to (A)^i */
439                                         leakage_calc_step =
440                                                 div64_s64(leakage_calc_step,
441                                                           edp_pow(1000, i));
442                                         leakage_calc_step *=
443                                                 edp_pow(voltage_mV, j);
444                                         /* Convert (mV)^i to (V)^i */
445                                         leakage_calc_step =
446                                                 div64_s64(leakage_calc_step,
447                                                           edp_pow(1000, j));
448                                         leakage_calc_step *=
449                                                 edp_pow(temp_C, k);
450                                         /* leakage_consts_ijk was X 100,000 */
451                                         leakage_calc_step =
452                                                 div64_s64(leakage_calc_step,
453                                                           100000);
454                                         leakage_mA += leakage_calc_step;
455                                 }
456                         }
457                 }
458                 leakage_mA *= params->leakage_consts_n[n_cores_idx];
459                 /* leakage_const_n was pre-multiplied by 1,000,000 */
460                 leakage_mA = div64_s64(leakage_mA, 1000000);
461
462                 /* Calculate dynamic current */
463                 dyn_mA = voltage_mV * freq_MHz;
464                 /* Convert mV to V */
465                 dyn_mA = div64_s64(dyn_mA, 1000);
466                 dyn_mA *= params->dyn_consts_n[n_cores_idx];
467                 /* dyn_const_n was pre-multiplied by 1,000,000 */
468                 dyn_mA = div64_s64(dyn_mA, 1000000);
469
470                 if ((leakage_mA + dyn_mA) <= cur_effective)
471                         return freq_MHz * 1000;
472         }
473         return 0;
474 }
475
476 static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
477                                 unsigned int cpu_speedo_idx)
478 {
479         unsigned int i, j, freq;
480         int voltage_mV;
481
482         for (i = 0, j = 0, freq = 0;
483                  i < freq_voltage_lut_size;
484                  i++, freq += FREQ_STEP) {
485
486                 /* Predict voltages */
487                 voltage_mV = tegra_dvfs_predict_millivolts(clk_cpu_g, freq);
488                 if (voltage_mV < 0) {
489                         pr_err("%s: couldn't predict voltage: freq %u; err %d",
490                                __func__, freq, voltage_mV);
491                         return -EINVAL;
492                 }
493
494                 /* Cache frequency / voltage / voltage constant relationship */
495                 freq_voltage_lut[i].freq = freq;
496                 freq_voltage_lut[i].voltage_mV = voltage_mV;
497         }
498         return 0;
499 }
500
501 int edp_find_speedo_idx(int cpu_speedo_id, unsigned int *cpu_speedo_idx)
502 {
503         int i;
504
505         for (i = 0; i < ARRAY_SIZE(leakage_params); i++)
506                 if (cpu_speedo_id == leakage_params[i].cpu_speedo_id) {
507                         *cpu_speedo_idx = i;
508                         return 0;
509                 }
510
511         pr_err("%s: couldn't find cpu speedo id %d in freq/voltage LUT\n",
512                __func__, cpu_speedo_id);
513         return -EINVAL;
514 }
515
516 static int init_cpu_edp_limits_calculated(void)
517 {
518         unsigned int temp_idx, n_cores_idx;
519         unsigned int cpu_g_minf, cpu_g_maxf;
520         unsigned int iddq_mA;
521         unsigned int cpu_speedo_idx;
522         struct tegra_edp_limits *edp_calculated_limits;
523         struct tegra_edp_cpu_leakage_params *params;
524         int ret;
525         struct clk *clk_cpu_g = tegra_get_clock_by_name("cpu_g");
526         int cpu_speedo_id = tegra_cpu_speedo_id();
527
528         /* Determine all inputs to EDP formula */
529         iddq_mA = tegra_get_cpu_iddq_value();
530         ret = edp_find_speedo_idx(cpu_speedo_id, &cpu_speedo_idx);
531         if (ret)
532                 return ret;
533
534         params = &leakage_params[cpu_speedo_idx];
535
536         edp_calculated_limits = kmalloc(sizeof(struct tegra_edp_limits)
537                                         * ARRAY_SIZE(temperatures), GFP_KERNEL);
538         BUG_ON(!edp_calculated_limits);
539
540         cpu_g_minf = 0;
541         cpu_g_maxf = clk_get_max_rate(clk_cpu_g);
542         freq_voltage_lut_size = (cpu_g_maxf - cpu_g_minf) / FREQ_STEP + 1;
543         freq_voltage_lut = kmalloc(sizeof(struct tegra_edp_freq_voltage_table)
544                                    * freq_voltage_lut_size, GFP_KERNEL);
545         if (!freq_voltage_lut) {
546                 pr_err("%s: failed alloc mem for freq/voltage LUT\n", __func__);
547                 return -ENOMEM;
548         }
549
550         ret = edp_relate_freq_voltage(clk_cpu_g, cpu_speedo_idx);
551         if (ret) {
552                 kfree(freq_voltage_lut);
553                 return ret;
554         }
555
556         /* Calculate EDP table */
557         for (temp_idx = 0; temp_idx < ARRAY_SIZE(temperatures); temp_idx++) {
558                 edp_calculated_limits[temp_idx].
559                         temperature = temperatures[temp_idx];
560                 for (n_cores_idx = 0; n_cores_idx < NR_CPUS; n_cores_idx++)
561                         edp_calculated_limits[temp_idx].
562                                 freq_limits[n_cores_idx] =
563                                 edp_calculate_maxf(params,
564                                                    temperatures[temp_idx],
565                                                    iddq_mA,
566                                                    n_cores_idx);
567         }
568
569         /*
570          * If this is an EDP table update, need to overwrite old table.
571          * The old table's address must remain valid.
572          */
573         if (edp_limits != edp_default_limits) {
574                 memcpy(edp_limits, edp_calculated_limits,
575                        sizeof(struct tegra_edp_limits)
576                        * ARRAY_SIZE(temperatures));
577                 kfree(edp_calculated_limits);
578         }
579         else {
580                 edp_limits = edp_calculated_limits;
581                 edp_limits_size = ARRAY_SIZE(temperatures);
582         }
583
584         kfree(freq_voltage_lut);
585         return 0;
586 }
587
588 static int __init init_cpu_edp_limits_lookup(void)
589 {
590         int i, j;
591         struct tegra_edp_limits *e;
592         struct tegra_edp_vdd_cpu_entry *t;
593         int tsize;
594         int cpu_speedo_id = tegra_cpu_speedo_id();
595
596         t = (struct tegra_edp_vdd_cpu_entry *)tegra_edp_vdd_cpu_map;
597         tsize = sizeof(tegra_edp_vdd_cpu_map)
598                 / sizeof(struct tegra_edp_vdd_cpu_entry);
599
600         for (i = 0; i < tsize; i++) {
601                 if (t[i].speedo_id == cpu_speedo_id &&
602                     t[i].regulator_100mA <= regulator_cur / 100)
603                         break;
604         }
605
606         /* No entry found in tegra_edp_vdd_cpu_map */
607         if (i >= tsize)
608                 return -EINVAL;
609
610         /* Find all rows for this entry */
611         for (j = i + 1; j < tsize; j++) {
612                 if (t[i].speedo_id != t[j].speedo_id ||
613                     t[i].regulator_100mA != t[j].regulator_100mA)
614                         break;
615         }
616
617         edp_limits_size = j - i;
618         e = kmalloc(sizeof(struct tegra_edp_limits) * edp_limits_size,
619                     GFP_KERNEL);
620         BUG_ON(!e);
621
622         for (j = 0; j < edp_limits_size; j++) {
623                 e[j].temperature = (int)t[i+j].temperature;
624                 e[j].freq_limits[0] = (unsigned int)t[i+j].freq_limits[0]*10000;
625                 e[j].freq_limits[1] = (unsigned int)t[i+j].freq_limits[1]*10000;
626                 e[j].freq_limits[2] = (unsigned int)t[i+j].freq_limits[2]*10000;
627                 e[j].freq_limits[3] = (unsigned int)t[i+j].freq_limits[3]*10000;
628         }
629
630         if (edp_limits != edp_default_limits)
631                 kfree(edp_limits);
632
633         edp_limits = e;
634         return 0;
635 }
636
637 void tegra_recalculate_cpu_edp_limits(void)
638 {
639         if (tegra_chip_id == TEGRA11X)
640                 init_cpu_edp_limits_calculated();
641 }
642
643 /*
644  * Specify regulator current in mA, e.g. 5000mA
645  * Use 0 for default
646  */
647 void __init tegra_init_cpu_edp_limits(unsigned int regulator_mA)
648 {
649         if (!regulator_mA) {
650                 edp_limits = edp_default_limits;
651                 edp_limits_size = ARRAY_SIZE(edp_default_limits);
652                 return;
653         }
654         regulator_cur = regulator_mA + OVERRIDE_DEFAULT;
655
656         switch (tegra_chip_id) {
657         case TEGRA30:
658                 if (init_cpu_edp_limits_lookup() == 0)
659                         return;
660                 break;
661         case TEGRA11X:
662                 if (init_cpu_edp_limits_calculated() == 0)
663                         return;
664                 break;
665         case TEGRA20:
666         default:
667                 BUG();
668                 break;
669         }
670
671         edp_limits = edp_default_limits;
672         edp_limits_size = ARRAY_SIZE(edp_default_limits);
673 }
674
675 void __init tegra_init_system_edp_limits(unsigned int power_limit_mW)
676 {
677         int cpu_speedo_id = tegra_cpu_speedo_id();
678         int i;
679         unsigned int *e;
680         struct tegra_system_edp_entry *t = tegra_system_edp_map;
681         int tsize = ARRAY_SIZE(tegra_system_edp_map);
682
683         if (!power_limit_mW) {
684                 e = NULL;
685                 goto out;
686         }
687
688         for (i = 0; i < tsize; i++)
689                 if (t[i].speedo_id == cpu_speedo_id)
690                         break;
691
692         if (i >= tsize) {
693                 e = NULL;
694                 goto out;
695         }
696
697         do {
698                 if (t[i].power_limit_100mW <= power_limit_mW / 100)
699                         break;
700                 i++;
701         } while (i < tsize && t[i].speedo_id == cpu_speedo_id);
702
703         if (i >= tsize || t[i].speedo_id != cpu_speedo_id)
704                 i--; /* No low enough entry in the table, use best possible */
705
706         e = kmalloc(sizeof(unsigned int) * 4, GFP_KERNEL);
707         BUG_ON(!e);
708
709         e[0] = (unsigned int)t[i].freq_limits[0] * 10000;
710         e[1] = (unsigned int)t[i].freq_limits[1] * 10000;
711         e[2] = (unsigned int)t[i].freq_limits[2] * 10000;
712         e[3] = (unsigned int)t[i].freq_limits[3] * 10000;
713
714 out:
715         kfree(system_edp_limits);
716
717         system_edp_limits = e;
718 }
719
720
721 void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size)
722 {
723         *limits = edp_limits;
724         *size = edp_limits_size;
725 }
726
727 void tegra_get_system_edp_limits(const unsigned int **limits)
728 {
729         *limits = system_edp_limits;
730 }
731
732 #ifdef CONFIG_DEBUG_FS
733
734 static int edp_limit_debugfs_show(struct seq_file *s, void *data)
735 {
736         seq_printf(s, "%u\n", tegra_get_edp_limit(NULL));
737         return 0;
738 }
739
740 static int edp_debugfs_show(struct seq_file *s, void *data)
741 {
742         int i, th_idx;
743
744         tegra_get_edp_limit(&th_idx);
745         seq_printf(s, "-- VDD_CPU %sEDP table (%umA = %umA - %umA) --\n",
746                    edp_limits == edp_default_limits ? "default " : "",
747                    regulator_cur - edp_reg_override_mA,
748                    regulator_cur, edp_reg_override_mA);
749         seq_printf(s, "%6s %10s %10s %10s %10s\n",
750                    " Temp.", "1-core", "2-cores", "3-cores", "4-cores");
751         for (i = 0; i < edp_limits_size; i++) {
752                 seq_printf(s, "%c%3dC: %10u %10u %10u %10u\n",
753                            i == th_idx ? '>' : ' ',
754                            edp_limits[i].temperature,
755                            edp_limits[i].freq_limits[0],
756                            edp_limits[i].freq_limits[1],
757                            edp_limits[i].freq_limits[2],
758                            edp_limits[i].freq_limits[3]);
759         }
760
761         if (system_edp_limits) {
762                 seq_printf(s, "\n-- System EDP table --\n");
763                 seq_printf(s, "%10u %10u %10u %10u\n",
764                            system_edp_limits[0],
765                            system_edp_limits[1],
766                            system_edp_limits[2],
767                            system_edp_limits[3]);
768         }
769
770         return 0;
771 }
772
773 static int edp_reg_override_show(struct seq_file *s, void *data)
774 {
775         seq_printf(s, "Limit override: %u mA. Effective limit: %u mA\n",
776                    edp_reg_override_mA, regulator_cur - edp_reg_override_mA);
777         return 0;
778 }
779
780 static int edp_reg_override_write(struct file *file,
781         const char __user *userbuf, size_t count, loff_t *ppos)
782 {
783         char buf[32], *end;
784         unsigned int edp_reg_override_mA_temp;
785         unsigned int edp_reg_override_mA_prev = edp_reg_override_mA;
786
787         if (sizeof(buf) <= count)
788                 goto override_err;
789
790         if (copy_from_user(buf, userbuf, count))
791                 goto override_err;
792
793         /* terminate buffer and trim - white spaces may be appended
794          *  at the end when invoked from shell command line */
795         buf[count]='\0';
796         strim(buf);
797
798         edp_reg_override_mA_temp = simple_strtoul(buf, &end, 10);
799         if (*end != '\0')
800                 goto override_err;
801
802         if (edp_reg_override_mA_temp >= regulator_cur)
803                 goto override_err;
804
805         if (edp_reg_override_mA == edp_reg_override_mA_temp)
806                 return count;
807
808         edp_reg_override_mA = edp_reg_override_mA_temp;
809         if (init_cpu_edp_limits_calculated()) {
810                 /* Revert to previous override value if new value fails */
811                 edp_reg_override_mA = edp_reg_override_mA_prev;
812                 goto override_err;
813         }
814
815         if (tegra_cpu_set_speed_cap(NULL)) {
816                 pr_err("FAILED: Set CPU freq cap with new VDD_CPU EDP table\n");
817                 goto override_out;
818         }
819
820         pr_info("Reinitialized VDD_CPU EDP table with regulator current limit"
821                         " %u mA\n", regulator_cur - edp_reg_override_mA);
822
823         return count;
824
825 override_err:
826         pr_err("FAILED: Reinitialize VDD_CPU EDP table with override \"%s\"",
827                buf);
828 override_out:
829         return -EINVAL;
830 }
831
832 static int edp_debugfs_open(struct inode *inode, struct file *file)
833 {
834         return single_open(file, edp_debugfs_show, inode->i_private);
835 }
836
837 static int edp_limit_debugfs_open(struct inode *inode, struct file *file)
838 {
839         return single_open(file, edp_limit_debugfs_show, inode->i_private);
840 }
841
842 static int edp_reg_override_open(struct inode *inode, struct file *file)
843 {
844         return single_open(file, edp_reg_override_show, inode->i_private);
845 }
846
847 static const struct file_operations edp_debugfs_fops = {
848         .open           = edp_debugfs_open,
849         .read           = seq_read,
850         .llseek         = seq_lseek,
851         .release        = single_release,
852 };
853
854 static const struct file_operations edp_limit_debugfs_fops = {
855         .open           = edp_limit_debugfs_open,
856         .read           = seq_read,
857         .llseek         = seq_lseek,
858         .release        = single_release,
859 };
860
861 static const struct file_operations edp_reg_override_debugfs_fops = {
862         .open           = edp_reg_override_open,
863         .read           = seq_read,
864         .write          = edp_reg_override_write,
865         .llseek         = seq_lseek,
866         .release        = single_release,
867 };
868
869 static int __init tegra_edp_debugfs_init(void)
870 {
871         struct dentry *d_edp;
872         struct dentry *d_edp_limit;
873         struct dentry *d_edp_reg_override;
874         struct dentry *edp_dir;
875         struct dentry *vdd_cpu_dir;
876
877         edp_dir = debugfs_create_dir("edp", NULL);
878
879         if (!edp_dir)
880                 goto edp_dir_err;
881
882         vdd_cpu_dir = debugfs_create_dir("vdd_cpu", edp_dir);
883
884         if (!vdd_cpu_dir)
885                 goto vdd_cpu_dir_err;
886
887         d_edp = debugfs_create_file("edp", S_IRUGO, vdd_cpu_dir, NULL,
888                                 &edp_debugfs_fops);
889
890         if (!d_edp)
891                 goto edp_err;
892
893         d_edp_limit = debugfs_create_file("edp_limit", S_IRUGO, vdd_cpu_dir,
894                                 NULL, &edp_limit_debugfs_fops);
895
896         if (!d_edp_limit)
897                 goto edp_limit_err;
898
899         d_edp_reg_override = debugfs_create_file("edp_reg_override",
900                                 S_IRUGO | S_IWUSR, vdd_cpu_dir, NULL,
901                                 &edp_reg_override_debugfs_fops);
902
903         if (!d_edp_reg_override)
904                 goto edp_reg_override_err;
905
906         if (tegra_core_edp_debugfs_init(edp_dir))
907                 goto edp_reg_override_err;
908
909         return 0;
910
911 edp_reg_override_err:
912         debugfs_remove(d_edp_limit);
913 edp_limit_err:
914         debugfs_remove(d_edp);
915 edp_err:
916         debugfs_remove(vdd_cpu_dir);
917 vdd_cpu_dir_err:
918         debugfs_remove(edp_dir);
919 edp_dir_err:
920         return -ENOMEM;
921 }
922
923 late_initcall(tegra_edp_debugfs_init);
924 #endif /* CONFIG_DEBUG_FS */