2 * arch/arm/mach-tegra/edp.c
4 * Copyright (C) 2011 NVIDIA, Inc.
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.
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.
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
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>
32 #define FREQ_STEP 10000000
33 #define A_TEMP_LUT_MAX 7
34 #define A_VOLTAGE_LUT_MAX 49
36 static const struct tegra_edp_limits *edp_limits;
37 static int edp_limits_size;
38 static unsigned int regulator_cur;
40 static const unsigned int *system_edp_limits;
43 * Temperature step size cannot be less than 4C because of hysteresis
45 * Code assumes different temperatures for the same speedo_id /
46 * regulator_cur are adjacent in the table, and higest regulator_cur
49 static char __initdata tegra_edp_map[] = {
50 0x00, 0x2f, 0x17, 0x7d, 0x73, 0x73, 0x73, 0x00,
51 0x2f, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f,
52 0x3c, 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f, 0x4b,
53 0x82, 0x78, 0x78, 0x78, 0x00, 0x2f, 0x55, 0x82,
54 0x78, 0x78, 0x78, 0x00, 0x28, 0x17, 0x7d, 0x73,
55 0x73, 0x73, 0x00, 0x28, 0x2d, 0x82, 0x78, 0x78,
56 0x78, 0x00, 0x28, 0x3c, 0x82, 0x78, 0x78, 0x78,
57 0x00, 0x28, 0x4b, 0x82, 0x78, 0x78, 0x73, 0x00,
58 0x28, 0x55, 0x82, 0x78, 0x78, 0x69, 0x00, 0x23,
59 0x17, 0x7d, 0x73, 0x73, 0x73, 0x00, 0x23, 0x2d,
60 0x82, 0x78, 0x78, 0x78, 0x00, 0x23, 0x3c, 0x82,
61 0x78, 0x78, 0x6e, 0x00, 0x23, 0x4b, 0x82, 0x78,
62 0x78, 0x64, 0x00, 0x23, 0x55, 0x82, 0x78, 0x6e,
63 0x5a, 0x00, 0x1e, 0x17, 0x7d, 0x73, 0x73, 0x64,
64 0x00, 0x1e, 0x2d, 0x82, 0x78, 0x78, 0x69, 0x00,
65 0x1e, 0x3c, 0x82, 0x78, 0x78, 0x64, 0x00, 0x1e,
66 0x4b, 0x82, 0x78, 0x6e, 0x5a, 0x00, 0x1e, 0x55,
67 0x82, 0x78, 0x64, 0x50, 0x00, 0x19, 0x17, 0x7d,
68 0x73, 0x69, 0x55, 0x00, 0x19, 0x2d, 0x82, 0x78,
69 0x6e, 0x5a, 0x00, 0x19, 0x3c, 0x82, 0x78, 0x69,
70 0x55, 0x00, 0x19, 0x4b, 0x82, 0x78, 0x5f, 0x4b,
71 0x00, 0x19, 0x55, 0x82, 0x73, 0x55, 0x3c, 0x01,
72 0x2f, 0x17, 0x7d, 0x73, 0x73, 0x73, 0x01, 0x2f,
73 0x2d, 0x82, 0x78, 0x78, 0x78, 0x01, 0x2f, 0x3c,
74 0x82, 0x78, 0x78, 0x78, 0x01, 0x2f, 0x4b, 0x82,
75 0x78, 0x78, 0x78, 0x01, 0x2f, 0x55, 0x82, 0x78,
76 0x78, 0x78, 0x01, 0x28, 0x17, 0x7d, 0x73, 0x73,
77 0x73, 0x01, 0x28, 0x2d, 0x82, 0x78, 0x78, 0x78,
78 0x01, 0x28, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x01,
79 0x28, 0x4b, 0x82, 0x78, 0x78, 0x73, 0x01, 0x28,
80 0x55, 0x82, 0x78, 0x78, 0x69, 0x01, 0x23, 0x17,
81 0x7d, 0x73, 0x73, 0x73, 0x01, 0x23, 0x2d, 0x82,
82 0x78, 0x78, 0x78, 0x01, 0x23, 0x3c, 0x82, 0x78,
83 0x78, 0x6e, 0x01, 0x23, 0x4b, 0x82, 0x78, 0x78,
84 0x64, 0x01, 0x23, 0x55, 0x82, 0x78, 0x6e, 0x5a,
85 0x01, 0x1e, 0x17, 0x7d, 0x73, 0x73, 0x64, 0x01,
86 0x1e, 0x2d, 0x82, 0x78, 0x78, 0x69, 0x01, 0x1e,
87 0x3c, 0x82, 0x78, 0x78, 0x64, 0x01, 0x1e, 0x4b,
88 0x82, 0x78, 0x6e, 0x5a, 0x01, 0x1e, 0x55, 0x82,
89 0x78, 0x64, 0x50, 0x01, 0x19, 0x17, 0x7d, 0x73,
90 0x69, 0x55, 0x01, 0x19, 0x2d, 0x82, 0x78, 0x6e,
91 0x5a, 0x01, 0x19, 0x3c, 0x82, 0x78, 0x69, 0x55,
92 0x01, 0x19, 0x4b, 0x82, 0x78, 0x5f, 0x4b, 0x01,
93 0x19, 0x55, 0x82, 0x73, 0x55, 0x3c, 0x02, 0x3d,
94 0x17, 0x87, 0x7d, 0x7d, 0x7d, 0x02, 0x3d, 0x2d,
95 0x8c, 0x82, 0x82, 0x82, 0x02, 0x3d, 0x3c, 0x8c,
96 0x82, 0x82, 0x82, 0x02, 0x3d, 0x4b, 0x8c, 0x82,
97 0x82, 0x82, 0x02, 0x3d, 0x55, 0x8c, 0x82, 0x82,
98 0x82, 0x02, 0x32, 0x17, 0x87, 0x7d, 0x7d, 0x7d,
99 0x02, 0x32, 0x2d, 0x8c, 0x82, 0x82, 0x82, 0x02,
100 0x32, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x02, 0x32,
101 0x4b, 0x8c, 0x82, 0x82, 0x78, 0x02, 0x32, 0x55,
102 0x8c, 0x82, 0x82, 0x6e, 0x02, 0x28, 0x17, 0x87,
103 0x7d, 0x7d, 0x73, 0x02, 0x28, 0x2d, 0x8c, 0x82,
104 0x82, 0x78, 0x02, 0x28, 0x3c, 0x8c, 0x82, 0x82,
105 0x73, 0x02, 0x28, 0x4b, 0x8c, 0x82, 0x78, 0x69,
106 0x02, 0x28, 0x55, 0x8c, 0x82, 0x6e, 0x5a, 0x02,
107 0x23, 0x17, 0x87, 0x7d, 0x7d, 0x69, 0x02, 0x23,
108 0x2d, 0x8c, 0x82, 0x82, 0x6e, 0x02, 0x23, 0x3c,
109 0x8c, 0x82, 0x78, 0x69, 0x02, 0x23, 0x4b, 0x8c,
110 0x82, 0x6e, 0x5a, 0x02, 0x23, 0x55, 0x8c, 0x82,
111 0x64, 0x50, 0x03, 0x3d, 0x17, 0x87, 0x7d, 0x7d,
112 0x7d, 0x03, 0x3d, 0x2d, 0x8c, 0x82, 0x82, 0x82,
113 0x03, 0x3d, 0x3c, 0x8c, 0x82, 0x82, 0x82, 0x03,
114 0x3d, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x3d,
115 0x55, 0x8c, 0x82, 0x82, 0x82, 0x03, 0x32, 0x17,
116 0x87, 0x7d, 0x7d, 0x7d, 0x03, 0x32, 0x2d, 0x8c,
117 0x82, 0x82, 0x82, 0x03, 0x32, 0x3c, 0x8c, 0x82,
118 0x82, 0x82, 0x03, 0x32, 0x4b, 0x8c, 0x82, 0x82,
119 0x78, 0x03, 0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e,
120 0x03, 0x28, 0x17, 0x87, 0x7d, 0x7d, 0x73, 0x03,
121 0x28, 0x2d, 0x8c, 0x82, 0x82, 0x78, 0x03, 0x28,
122 0x3c, 0x8c, 0x82, 0x82, 0x73, 0x03, 0x28, 0x4b,
123 0x8c, 0x82, 0x78, 0x69, 0x03, 0x28, 0x55, 0x8c,
124 0x82, 0x6e, 0x5a, 0x03, 0x23, 0x17, 0x87, 0x7d,
125 0x7d, 0x69, 0x03, 0x23, 0x2d, 0x8c, 0x82, 0x82,
126 0x6e, 0x03, 0x23, 0x3c, 0x8c, 0x82, 0x78, 0x69,
127 0x03, 0x23, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x03,
128 0x23, 0x55, 0x8c, 0x82, 0x64, 0x50, 0x04, 0x32,
129 0x17, 0x91, 0x87, 0x87, 0x87, 0x04, 0x32, 0x2d,
130 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x32, 0x3c, 0x96,
131 0x8c, 0x8c, 0x8c, 0x04, 0x32, 0x46, 0x96, 0x8c,
132 0x8c, 0x8c, 0x04, 0x32, 0x4b, 0x82, 0x78, 0x78,
133 0x78, 0x04, 0x32, 0x55, 0x82, 0x78, 0x78, 0x78,
134 0x04, 0x2f, 0x17, 0x91, 0x87, 0x87, 0x87, 0x04,
135 0x2f, 0x2d, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x2f,
136 0x3c, 0x96, 0x8c, 0x8c, 0x8c, 0x04, 0x2f, 0x46,
137 0x96, 0x8c, 0x8c, 0x82, 0x04, 0x2f, 0x4b, 0x82,
138 0x78, 0x78, 0x78, 0x04, 0x2f, 0x55, 0x82, 0x78,
139 0x78, 0x78, 0x04, 0x28, 0x17, 0x91, 0x87, 0x87,
140 0x87, 0x04, 0x28, 0x2d, 0x96, 0x8c, 0x8c, 0x82,
141 0x04, 0x28, 0x3c, 0x96, 0x8c, 0x8c, 0x82, 0x04,
142 0x28, 0x46, 0x96, 0x8c, 0x8c, 0x78, 0x04, 0x28,
143 0x4b, 0x82, 0x78, 0x78, 0x78, 0x04, 0x28, 0x55,
144 0x82, 0x78, 0x78, 0x6e, 0x04, 0x23, 0x17, 0x91,
145 0x87, 0x87, 0x73, 0x04, 0x23, 0x2d, 0x96, 0x8c,
146 0x8c, 0x78, 0x04, 0x23, 0x3c, 0x96, 0x8c, 0x82,
147 0x78, 0x04, 0x23, 0x46, 0x96, 0x8c, 0x82, 0x6e,
148 0x04, 0x23, 0x4b, 0x82, 0x78, 0x78, 0x6e, 0x04,
149 0x23, 0x55, 0x82, 0x78, 0x78, 0x64, 0x04, 0x1e,
150 0x17, 0x91, 0x87, 0x7d, 0x69, 0x04, 0x1e, 0x2d,
151 0x96, 0x8c, 0x82, 0x6e, 0x04, 0x1e, 0x3c, 0x96,
152 0x8c, 0x78, 0x64, 0x04, 0x1e, 0x46, 0x96, 0x8c,
153 0x78, 0x5a, 0x04, 0x1e, 0x4b, 0x82, 0x78, 0x78,
154 0x5a, 0x04, 0x1e, 0x55, 0x82, 0x78, 0x64, 0x50,
155 0x04, 0x19, 0x17, 0x91, 0x87, 0x69, 0x55, 0x04,
156 0x19, 0x2d, 0x96, 0x8c, 0x6e, 0x5a, 0x04, 0x19,
157 0x3c, 0x96, 0x82, 0x6e, 0x55, 0x04, 0x19, 0x46,
158 0x96, 0x82, 0x64, 0x50, 0x04, 0x19, 0x4b, 0x82,
159 0x78, 0x64, 0x50, 0x04, 0x19, 0x55, 0x82, 0x78,
160 0x55, 0x3c, 0x05, 0x64, 0x17, 0xa5, 0x9b, 0x9b,
161 0x9b, 0x05, 0x64, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0,
162 0x05, 0x64, 0x3c, 0xaa, 0xa0, 0xa0, 0xa0, 0x05,
163 0x64, 0x46, 0xaa, 0xa0, 0xa0, 0xa0, 0x05, 0x64,
164 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x05, 0x64, 0x55,
165 0x8c, 0x82, 0x82, 0x82, 0x05, 0x50, 0x17, 0xa5,
166 0x9b, 0x9b, 0x9b, 0x05, 0x50, 0x2d, 0xaa, 0xa0,
167 0xa0, 0xa0, 0x05, 0x50, 0x3c, 0xaa, 0xa0, 0xa0,
168 0x96, 0x05, 0x50, 0x46, 0xaa, 0xa0, 0xa0, 0x96,
169 0x05, 0x50, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x05,
170 0x50, 0x55, 0x8c, 0x82, 0x82, 0x82, 0x05, 0x3c,
171 0x17, 0xa5, 0x9b, 0x9b, 0x87, 0x05, 0x3c, 0x2d,
172 0xaa, 0xa0, 0xa0, 0x8c, 0x05, 0x3c, 0x3c, 0xaa,
173 0xa0, 0x96, 0x82, 0x05, 0x3c, 0x46, 0xaa, 0xa0,
174 0x96, 0x78, 0x05, 0x3c, 0x4b, 0x8c, 0x82, 0x82,
175 0x78, 0x05, 0x3c, 0x55, 0x8c, 0x82, 0x82, 0x6e,
176 0x05, 0x28, 0x17, 0xa5, 0x91, 0x7d, 0x69, 0x05,
177 0x28, 0x2d, 0xaa, 0x96, 0x82, 0x6e, 0x05, 0x28,
178 0x3c, 0xaa, 0x96, 0x78, 0x64, 0x05, 0x28, 0x46,
179 0xaa, 0x8c, 0x6e, 0x5a, 0x05, 0x28, 0x4b, 0x8c,
180 0x82, 0x6e, 0x5a, 0x05, 0x28, 0x55, 0x8c, 0x82,
181 0x64, 0x50, 0x06, 0x3d, 0x17, 0xa5, 0x9b, 0x7d,
182 0x7d, 0x06, 0x3d, 0x2d, 0xaa, 0xa0, 0x82, 0x82,
183 0x06, 0x3d, 0x3c, 0xaa, 0xa0, 0x82, 0x82, 0x06,
184 0x3d, 0x46, 0xaa, 0xa0, 0x82, 0x82, 0x06, 0x3d,
185 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x06, 0x3d, 0x55,
186 0x8c, 0x82, 0x82, 0x82, 0x06, 0x32, 0x17, 0xa5,
187 0x9b, 0x7d, 0x7d, 0x06, 0x32, 0x2d, 0xaa, 0xa0,
188 0x82, 0x82, 0x06, 0x32, 0x3c, 0xaa, 0xa0, 0x82,
189 0x82, 0x06, 0x32, 0x46, 0xaa, 0xa0, 0x82, 0x78,
190 0x06, 0x32, 0x4b, 0x8c, 0x82, 0x82, 0x78, 0x06,
191 0x32, 0x55, 0x8c, 0x82, 0x82, 0x6e, 0x06, 0x28,
192 0x17, 0xa5, 0x9b, 0x7d, 0x73, 0x06, 0x28, 0x2d,
193 0xaa, 0xa0, 0x82, 0x78, 0x06, 0x28, 0x3c, 0xaa,
194 0x96, 0x82, 0x73, 0x06, 0x28, 0x46, 0xaa, 0x96,
195 0x78, 0x69, 0x06, 0x28, 0x4b, 0x8c, 0x82, 0x78,
196 0x69, 0x06, 0x28, 0x55, 0x8c, 0x82, 0x6e, 0x5a,
197 0x06, 0x23, 0x17, 0xa5, 0x91, 0x7d, 0x69, 0x06,
198 0x23, 0x2d, 0xaa, 0x96, 0x82, 0x6e, 0x06, 0x23,
199 0x3c, 0xaa, 0x96, 0x78, 0x69, 0x06, 0x23, 0x46,
200 0xaa, 0x8c, 0x6e, 0x5a, 0x06, 0x23, 0x4b, 0x8c,
201 0x82, 0x6e, 0x5a, 0x06, 0x23, 0x55, 0x8c, 0x82,
202 0x64, 0x50, 0x07, 0x3b, 0x17, 0x7d, 0x73, 0x73,
203 0x73, 0x07, 0x3b, 0x2d, 0x82, 0x78, 0x78, 0x78,
204 0x07, 0x3b, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x07,
205 0x3b, 0x4b, 0x82, 0x78, 0x78, 0x78, 0x07, 0x3b,
206 0x5a, 0x82, 0x78, 0x78, 0x78, 0x07, 0x32, 0x17,
207 0x7d, 0x73, 0x73, 0x73, 0x07, 0x32, 0x2d, 0x82,
208 0x78, 0x78, 0x78, 0x07, 0x32, 0x3c, 0x82, 0x78,
209 0x78, 0x78, 0x07, 0x32, 0x4b, 0x82, 0x78, 0x78,
210 0x78, 0x07, 0x32, 0x5a, 0x82, 0x78, 0x6e, 0x64,
211 0x07, 0x28, 0x17, 0x7d, 0x73, 0x73, 0x69, 0x07,
212 0x28, 0x2d, 0x82, 0x78, 0x78, 0x6e, 0x07, 0x28,
213 0x3c, 0x82, 0x78, 0x78, 0x64, 0x07, 0x28, 0x4b,
214 0x82, 0x78, 0x78, 0x64, 0x07, 0x28, 0x5a, 0x82,
215 0x78, 0x64, 0x50, 0x07, 0x23, 0x17, 0x7d, 0x73,
216 0x73, 0x5f, 0x07, 0x23, 0x2d, 0x82, 0x78, 0x78,
217 0x64, 0x07, 0x23, 0x3c, 0x82, 0x78, 0x78, 0x64,
218 0x07, 0x23, 0x4b, 0x82, 0x78, 0x64, 0x50, 0x07,
219 0x23, 0x5a, 0x82, 0x78, 0x5a, 0x46, 0x08, 0x3b,
220 0x17, 0x7d, 0x73, 0x73, 0x73, 0x08, 0x3b, 0x2d,
221 0x82, 0x78, 0x78, 0x78, 0x08, 0x3b, 0x3c, 0x82,
222 0x78, 0x78, 0x78, 0x08, 0x3b, 0x4b, 0x82, 0x78,
223 0x78, 0x78, 0x08, 0x3b, 0x5a, 0x82, 0x78, 0x78,
224 0x78, 0x08, 0x32, 0x17, 0x7d, 0x73, 0x73, 0x73,
225 0x08, 0x32, 0x2d, 0x82, 0x78, 0x78, 0x78, 0x08,
226 0x32, 0x3c, 0x82, 0x78, 0x78, 0x78, 0x08, 0x32,
227 0x4b, 0x82, 0x78, 0x78, 0x78, 0x08, 0x32, 0x5a,
228 0x82, 0x78, 0x6e, 0x64, 0x08, 0x28, 0x17, 0x7d,
229 0x73, 0x73, 0x69, 0x08, 0x28, 0x2d, 0x82, 0x78,
230 0x78, 0x6e, 0x08, 0x28, 0x3c, 0x82, 0x78, 0x78,
231 0x64, 0x08, 0x28, 0x4b, 0x82, 0x78, 0x78, 0x64,
232 0x08, 0x28, 0x5a, 0x82, 0x78, 0x64, 0x50, 0x08,
233 0x23, 0x17, 0x7d, 0x73, 0x73, 0x5f, 0x08, 0x23,
234 0x2d, 0x82, 0x78, 0x78, 0x64, 0x08, 0x23, 0x3c,
235 0x82, 0x78, 0x78, 0x64, 0x08, 0x23, 0x4b, 0x82,
236 0x78, 0x64, 0x50, 0x08, 0x23, 0x5a, 0x82, 0x78,
237 0x5a, 0x46, 0x0c, 0x52, 0x17, 0xa5, 0x9b, 0x9b,
238 0x9b, 0x0c, 0x52, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0,
239 0x0c, 0x52, 0x3c, 0xaa, 0xa0, 0xa0, 0xa0, 0x0c,
240 0x52, 0x46, 0xaa, 0xa0, 0xa0, 0xa0, 0x0c, 0x52,
241 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x0c, 0x52, 0x55,
242 0x8c, 0x82, 0x82, 0x82, 0x0c, 0x42, 0x17, 0xa5,
243 0x9b, 0x9b, 0x91, 0x0c, 0x42, 0x2d, 0xaa, 0xa0,
244 0xa0, 0x96, 0x0c, 0x42, 0x3c, 0xaa, 0xa0, 0xa0,
245 0x96, 0x0c, 0x42, 0x46, 0xaa, 0xa0, 0xa0, 0x96,
246 0x0c, 0x42, 0x4b, 0x8c, 0x82, 0x82, 0x82, 0x0c,
247 0x42, 0x55, 0x8c, 0x82, 0x82, 0x82, 0x0c, 0x3d,
248 0x17, 0xa5, 0x9b, 0x9b, 0x91, 0x0c, 0x3d, 0x2d,
249 0xaa, 0xa0, 0xa0, 0x96, 0x0c, 0x3d, 0x3c, 0xaa,
250 0xa0, 0xa0, 0x8c, 0x0c, 0x3d, 0x46, 0xaa, 0xa0,
251 0x96, 0x8c, 0x0c, 0x3d, 0x4b, 0x8c, 0x82, 0x82,
252 0x82, 0x0c, 0x3d, 0x55, 0x8c, 0x82, 0x82, 0x82,
253 0x0c, 0x32, 0x17, 0xa5, 0x9b, 0x91, 0x87, 0x0c,
254 0x32, 0x2d, 0xaa, 0xa0, 0x96, 0x8c, 0x0c, 0x32,
255 0x3c, 0xaa, 0xa0, 0x96, 0x82, 0x0c, 0x32, 0x46,
256 0xaa, 0xa0, 0x8c, 0x78, 0x0c, 0x32, 0x4b, 0x8c,
257 0x82, 0x82, 0x78, 0x0c, 0x32, 0x55, 0x8c, 0x82,
258 0x82, 0x6e, 0x0c, 0x28, 0x17, 0xa5, 0x9b, 0x87,
259 0x73, 0x0c, 0x28, 0x2d, 0xaa, 0xa0, 0x8c, 0x78,
260 0x0c, 0x28, 0x3c, 0xaa, 0x96, 0x82, 0x73, 0x0c,
261 0x28, 0x46, 0xaa, 0x96, 0x78, 0x69, 0x0c, 0x28,
262 0x4b, 0x8c, 0x82, 0x78, 0x69, 0x0c, 0x28, 0x55,
263 0x8c, 0x82, 0x6e, 0x5a, 0x0c, 0x23, 0x17, 0xa5,
264 0x91, 0x7d, 0x69, 0x0c, 0x23, 0x2d, 0xaa, 0x96,
265 0x82, 0x6e, 0x0c, 0x23, 0x3c, 0xaa, 0x96, 0x78,
266 0x69, 0x0c, 0x23, 0x46, 0xaa, 0x8c, 0x6e, 0x5a,
267 0x0c, 0x23, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x0c,
268 0x23, 0x55, 0x8c, 0x82, 0x64, 0x50, 0x0d, 0x64,
269 0x17, 0xa5, 0x9b, 0x9b, 0x9b, 0x0d, 0x64, 0x2d,
270 0xaa, 0xa0, 0xa0, 0xa0, 0x0d, 0x64, 0x3c, 0xaa,
271 0xa0, 0xa0, 0xa0, 0x0d, 0x64, 0x46, 0xaa, 0xa0,
272 0xa0, 0xa0, 0x0d, 0x64, 0x4b, 0x8c, 0x82, 0x82,
273 0x82, 0x0d, 0x64, 0x55, 0x8c, 0x82, 0x82, 0x82,
274 0x0d, 0x50, 0x17, 0xa5, 0x9b, 0x9b, 0x9b, 0x0d,
275 0x50, 0x2d, 0xaa, 0xa0, 0xa0, 0xa0, 0x0d, 0x50,
276 0x3c, 0xaa, 0xa0, 0xa0, 0x96, 0x0d, 0x50, 0x46,
277 0xaa, 0xa0, 0xa0, 0x96, 0x0d, 0x50, 0x4b, 0x8c,
278 0x82, 0x82, 0x82, 0x0d, 0x50, 0x55, 0x8c, 0x82,
279 0x82, 0x82, 0x0d, 0x3c, 0x17, 0xa5, 0x9b, 0x9b,
280 0x87, 0x0d, 0x3c, 0x2d, 0xaa, 0xa0, 0xa0, 0x8c,
281 0x0d, 0x3c, 0x3c, 0xaa, 0xa0, 0x96, 0x82, 0x0d,
282 0x3c, 0x46, 0xaa, 0xa0, 0x96, 0x78, 0x0d, 0x3c,
283 0x4b, 0x8c, 0x82, 0x82, 0x78, 0x0d, 0x3c, 0x55,
284 0x8c, 0x82, 0x82, 0x6e, 0x0d, 0x28, 0x17, 0xa5,
285 0x91, 0x7d, 0x69, 0x0d, 0x28, 0x2d, 0xaa, 0x96,
286 0x82, 0x6e, 0x0d, 0x28, 0x3c, 0xaa, 0x96, 0x78,
287 0x64, 0x0d, 0x28, 0x46, 0xaa, 0x8c, 0x6e, 0x5a,
288 0x0d, 0x28, 0x4b, 0x8c, 0x82, 0x6e, 0x5a, 0x0d,
289 0x28, 0x55, 0x8c, 0x82, 0x64, 0x50,
293 static struct system_edp_entry __initdata tegra_system_edp_map[] = {
295 /* {SKU, power-limit (in 100mW), {freq limits (in 10Mhz)} } */
297 { 1, 49, {130, 120, 120, 120} },
298 { 1, 44, {130, 120, 120, 110} },
299 { 1, 37, {130, 120, 110, 100} },
300 { 1, 35, {130, 120, 110, 90} },
301 { 1, 29, {130, 120, 100, 80} },
302 { 1, 27, {130, 120, 90, 80} },
303 { 1, 25, {130, 110, 80, 60} },
304 { 1, 21, {130, 100, 80, 40} },
306 { 4, 49, {130, 120, 120, 120} },
307 { 4, 44, {130, 120, 120, 110} },
308 { 4, 37, {130, 120, 110, 100} },
309 { 4, 35, {130, 120, 110, 90} },
310 { 4, 29, {130, 120, 100, 80} },
311 { 4, 27, {130, 120, 90, 80} },
312 { 4, 25, {130, 110, 80, 60} },
313 { 4, 21, {130, 100, 80, 40} },
317 * "Safe entry" to be used when no match for speedo_id /
318 * regulator_cur is found; must be the last one
320 static struct tegra_edp_limits edp_default_limits[] = {
321 {85, {1000000, 1000000, 1000000, 1000000} },
325 * Constants for EDP calculations
328 struct a_voltage_lut_t {
329 unsigned int voltage;
330 unsigned int a_voltage;
333 struct a_temp_lut_t {
338 /* TODO: This struct will get large for 13 speedo IDs... relocate. */
339 struct edp_constants_lut_t {
342 struct a_temp_lut_t a_temp_lut [A_TEMP_LUT_MAX];
343 unsigned int a_temp_lut_size;
345 struct a_voltage_lut_t a_voltage_lut [A_VOLTAGE_LUT_MAX];
346 unsigned int a_voltage_lut_size;
348 unsigned int a_cores_lut[NR_CPUS];
349 } edp_constants_lut[] = {
361 .a_temp_lut_size = 7,
413 .a_voltage_lut_size = 49,
423 struct freq_voltage_lut_t {
425 struct a_voltage_lut_t *a_voltage_lut;
426 } *freq_voltage_lut = 0;
427 unsigned int freq_voltage_lut_size;
430 * Find the maximum frequency that results in dynamic and leakage current that
431 * is less than the regulator current limit.
433 unsigned int edp_calculate_maxf(unsigned int a_temp,
434 unsigned int a_cores,
435 unsigned int n_cores,
436 unsigned int iddq_mA)
438 unsigned int voltage_mV, a_voltage, leakage_mA, op_mA, freq_MHz;
441 for (i = freq_voltage_lut_size - 1; i >= 0; i--) {
442 freq_MHz = freq_voltage_lut[i].freq / 1000000;
444 voltage_mV = freq_voltage_lut[i].a_voltage_lut->voltage;
445 a_voltage = freq_voltage_lut[i].a_voltage_lut->a_voltage;
447 leakage_mA = a_temp * a_voltage;
448 /* a_voltage was pre-multiplied by 1000 */
450 leakage_mA *= a_cores;
451 /* a_temp was pre-multiplied by 100,000 */
452 leakage_mA /= 100000;
453 leakage_mA *= iddq_mA;
454 /* a_cores was pre-multiplied by 10,000 */
457 op_mA = 55 * voltage_mV * freq_MHz * n_cores;
458 /* 55 was pre-multiplied by 100000 */
461 /* TODO: Apply additional margin to total current calculated? */
462 if ((leakage_mA + op_mA) <= regulator_cur)
463 return freq_MHz * 1000;
468 static int edp_relate_freq_voltage(struct clk *clk_cpu_g,
469 unsigned int cpu_speedo_idx)
471 unsigned int i, j, freq, voltage_mV, a_voltage_lut_size;
472 struct a_voltage_lut_t *a_voltage_lut;
474 a_voltage_lut = edp_constants_lut[cpu_speedo_idx].a_voltage_lut;
475 a_voltage_lut_size = edp_constants_lut[cpu_speedo_idx].a_voltage_lut_size;
477 for (i = 0, j = 0, freq = clk_get_min_rate(clk_cpu_g);
478 i < freq_voltage_lut_size;
479 i++, freq += FREQ_STEP) {
481 /* Predict voltages */
482 voltage_mV = tegra_dvfs_predict_millivolts(clk_cpu_g, freq);
483 if (voltage_mV < 0) {
484 pr_err("%s: could not predict voltage for freqency %u, err %d\n",
485 __func__, freq, voltage_mV);
489 /* Look up voltage constant */
490 for (;j < a_voltage_lut_size; j++) {
491 if (voltage_mV <= a_voltage_lut[j].voltage) {
495 if (j == a_voltage_lut_size) {
496 pr_err("%s: couldn't find voltage const for predicted voltage %d\n",
497 __func__, voltage_mV);
501 /* Cache frequency / voltage / voltage constant relationship */
502 freq_voltage_lut[i].freq = freq;
503 freq_voltage_lut[i].a_voltage_lut = &a_voltage_lut[j];
509 int edp_find_speedo_idx(int cpu_speedo_id, unsigned int *cpu_speedo_idx)
513 for (i = 0; i < ARRAY_SIZE(edp_constants_lut); i++)
514 if (cpu_speedo_id == edp_constants_lut[i].cpu_speedo_id) {
519 pr_err("%s: couldn't find cpu speedo id in freq/voltage LUT\n", __func__);
523 int init_cpu_edp_limits_calculated(int cpu_speedo_id)
525 unsigned int temp_idx, n_cores_idx, cpu_speedo_idx;
526 unsigned int cpu_g_minf, cpu_g_maxf;
527 unsigned int *a_cores_lut, a_temp_lut_size, iddq_mA;
528 struct a_temp_lut_t *a_temp_lut;
529 struct tegra_edp_limits *edp_calculated_limits;
530 int ret, edp_calculated_limits_size;
531 struct clk *clk_cpu_g = tegra_get_clock_by_name("cpu_g");
533 /* Determine all inputs to EDP formula */
534 tegra_fuse_get_cpu_iddq_mA(&iddq_mA);
536 ret = edp_find_speedo_idx(cpu_speedo_id, &cpu_speedo_idx);
540 a_temp_lut = edp_constants_lut[cpu_speedo_idx].a_temp_lut;
541 a_temp_lut_size = edp_constants_lut[cpu_speedo_idx].a_temp_lut_size;
543 a_cores_lut = edp_constants_lut[cpu_speedo_idx].a_cores_lut;
545 edp_calculated_limits =
546 kmalloc(sizeof(struct tegra_edp_limits) * a_temp_lut_size, GFP_KERNEL);
547 BUG_ON(!edp_calculated_limits);
548 edp_calculated_limits_size = a_temp_lut_size;
550 cpu_g_minf = clk_get_min_rate(clk_cpu_g);
551 cpu_g_maxf = clk_get_max_rate(clk_cpu_g);
552 freq_voltage_lut_size = (cpu_g_maxf - cpu_g_minf) / FREQ_STEP + 1;
554 kmalloc(sizeof(struct freq_voltage_lut_t) * freq_voltage_lut_size,
556 if (!freq_voltage_lut) {
557 pr_err("%s: failed to allocate mem for freq/voltage LUT\n", __func__);
561 ret = edp_relate_freq_voltage(clk_cpu_g, cpu_speedo_idx);
563 kfree(freq_voltage_lut);
567 /* Calculate EDP table */
568 for (temp_idx = 0; temp_idx < a_temp_lut_size; temp_idx++) {
569 edp_calculated_limits[temp_idx].temperature = a_temp_lut[temp_idx].temp;
571 for (n_cores_idx = 0; n_cores_idx < NR_CPUS; n_cores_idx++)
572 edp_calculated_limits[temp_idx].freq_limits[n_cores_idx] =
573 edp_calculate_maxf(a_temp_lut[temp_idx].a_temp,
574 a_cores_lut[n_cores_idx],
579 edp_limits = edp_calculated_limits;
580 edp_limits_size = edp_calculated_limits_size;
582 kfree(freq_voltage_lut);
586 int init_cpu_edp_limits_lookup(int cpu_speedo_id)
589 struct tegra_edp_limits *e;
590 struct tegra_edp_entry *t = (struct tegra_edp_entry *)tegra_edp_map;
591 int tsize = sizeof(tegra_edp_map)/sizeof(struct tegra_edp_entry);
593 for (i = 0; i < tsize; i++) {
594 if (t[i].speedo_id == cpu_speedo_id &&
595 t[i].regulator_100mA <= regulator_cur / 100)
599 /* No entry found in tegra_edp_map */
603 /* Find all rows for this entry */
604 for (j = i + 1; j < tsize; j++) {
605 if (t[i].speedo_id != t[j].speedo_id ||
606 t[i].regulator_100mA != t[j].regulator_100mA)
610 edp_limits_size = j - i;
611 e = kmalloc(sizeof(struct tegra_edp_limits) * edp_limits_size,
615 for (j = 0; j < edp_limits_size; j++) {
616 e[j].temperature = (int)t[i+j].temperature;
617 e[j].freq_limits[0] = (unsigned int)t[i+j].freq_limits[0] * 10000;
618 e[j].freq_limits[1] = (unsigned int)t[i+j].freq_limits[1] * 10000;
619 e[j].freq_limits[2] = (unsigned int)t[i+j].freq_limits[2] * 10000;
620 e[j].freq_limits[3] = (unsigned int)t[i+j].freq_limits[3] * 10000;
623 if (edp_limits != edp_default_limits)
631 * Specify regulator current in mA, e.g. 5000mA
634 void __init tegra_init_cpu_edp_limits(unsigned int regulator_mA)
636 int cpu_speedo_id = tegra_cpu_speedo_id();
638 edp_limits = edp_default_limits;
639 edp_limits_size = ARRAY_SIZE(edp_default_limits);
642 regulator_cur = regulator_mA;
644 if (!init_cpu_edp_limits_lookup(cpu_speedo_id))
647 if (!init_cpu_edp_limits_calculated(cpu_speedo_id))
650 edp_limits = edp_default_limits;
651 edp_limits_size = ARRAY_SIZE(edp_default_limits);
654 void __init tegra_init_system_edp_limits(unsigned int power_limit_mW)
656 int cpu_speedo_id = tegra_cpu_speedo_id();
659 struct system_edp_entry *t =
660 (struct system_edp_entry *)tegra_system_edp_map;
661 int tsize = sizeof(tegra_system_edp_map) /
662 sizeof(struct system_edp_entry);
664 if (!power_limit_mW) {
669 for (i = 0; i < tsize; i++)
670 if (t[i].speedo_id == cpu_speedo_id)
679 if (t[i].power_limit_100mW <= power_limit_mW / 100)
682 } while (i < tsize && t[i].speedo_id == cpu_speedo_id);
684 if (i >= tsize || t[i].speedo_id != cpu_speedo_id)
685 i--; /* No low enough entry in the table, use best possible */
687 e = kmalloc(sizeof(unsigned int) * 4, GFP_KERNEL);
690 e[0] = (unsigned int)t[i].freq_limits[0] * 10000;
691 e[1] = (unsigned int)t[i].freq_limits[1] * 10000;
692 e[2] = (unsigned int)t[i].freq_limits[2] * 10000;
693 e[3] = (unsigned int)t[i].freq_limits[3] * 10000;
696 kfree(system_edp_limits);
698 system_edp_limits = e;
702 void tegra_get_cpu_edp_limits(const struct tegra_edp_limits **limits, int *size)
704 *limits = edp_limits;
705 *size = edp_limits_size;
708 void tegra_get_system_edp_limits(const unsigned int **limits)
710 *limits = system_edp_limits;
713 #ifdef CONFIG_DEBUG_FS
715 static int edp_limit_debugfs_show(struct seq_file *s, void *data)
717 seq_printf(s, "%u\n", tegra_get_edp_limit());
721 static int edp_debugfs_show(struct seq_file *s, void *data)
725 seq_printf(s, "-- CPU %sEDP table (%umA) --\n",
726 edp_limits == edp_default_limits ? "default " : "",
728 for (i = 0; i < edp_limits_size; i++) {
729 seq_printf(s, "%4dC: %10u %10u %10u %10u\n",
730 edp_limits[i].temperature,
731 edp_limits[i].freq_limits[0],
732 edp_limits[i].freq_limits[1],
733 edp_limits[i].freq_limits[2],
734 edp_limits[i].freq_limits[3]);
737 if (system_edp_limits) {
738 seq_printf(s, "\n-- System EDP table --\n");
739 seq_printf(s, "%10u %10u %10u %10u\n",
740 system_edp_limits[0],
741 system_edp_limits[1],
742 system_edp_limits[2],
743 system_edp_limits[3]);
750 static int edp_debugfs_open(struct inode *inode, struct file *file)
752 return single_open(file, edp_debugfs_show, inode->i_private);
755 static int edp_limit_debugfs_open(struct inode *inode, struct file *file)
757 return single_open(file, edp_limit_debugfs_show, inode->i_private);
761 static const struct file_operations edp_debugfs_fops = {
762 .open = edp_debugfs_open,
765 .release = single_release,
768 static const struct file_operations edp_limit_debugfs_fops = {
769 .open = edp_limit_debugfs_open,
772 .release = single_release,
775 static int __init tegra_edp_debugfs_init(void)
779 d = debugfs_create_file("edp", S_IRUGO, NULL, NULL,
784 d = debugfs_create_file("edp_limit", S_IRUGO, NULL, NULL,
785 &edp_limit_debugfs_fops);
790 late_initcall(tegra_edp_debugfs_init);
791 #endif /* CONFIG_DEBUG_FS */