aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/tegra2_dvfs.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/mach-tegra/tegra2_dvfs.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'arch/arm/mach-tegra/tegra2_dvfs.c')
-rw-r--r--arch/arm/mach-tegra/tegra2_dvfs.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c
new file mode 100644
index 00000000000..a53033b0099
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_dvfs.c
@@ -0,0 +1,349 @@
1/*
2 * arch/arm/mach-tegra/tegra2_dvfs.c
3 *
4 * Copyright (C) 2010 Google, Inc.
5 *
6 * Author:
7 * Colin Cross <ccross@google.com>
8 *
9 * Copyright (C) 2010-2011 NVIDIA Corporation
10 *
11 * This software is licensed under the terms of the GNU General Public
12 * License version 2, as published by the Free Software Foundation, and
13 * may be copied, distributed, and modified under those terms.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 */
21
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/string.h>
25#include <linux/module.h>
26
27#include "clock.h"
28#include "dvfs.h"
29#include "fuse.h"
30
31#ifdef CONFIG_TEGRA_CORE_DVFS
32static bool tegra_dvfs_core_disabled;
33#else
34static bool tegra_dvfs_core_disabled = true;
35#endif
36#ifdef CONFIG_TEGRA_CPU_DVFS
37static bool tegra_dvfs_cpu_disabled;
38#else
39static bool tegra_dvfs_cpu_disabled = true;
40#endif
41
42static const int core_millivolts[MAX_DVFS_FREQS] =
43 {950, 1000, 1100, 1200, 1225, 1275, 1300};
44static const int cpu_millivolts[MAX_DVFS_FREQS] =
45 {750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1100, 1125};
46
47static const int cpu_speedo_nominal_millivolts[] =
48/* spedo_id 0, 1, 2 */
49 { 1100, 1025, 1125 };
50
51static const int core_speedo_nominal_millivolts[] =
52/* spedo_id 0, 1, 2 */
53 { 1225, 1225, 1300 };
54
55#define KHZ 1000
56#define MHZ 1000000
57
58static struct dvfs_rail tegra2_dvfs_rail_vdd_cpu = {
59 .reg_id = "vdd_cpu",
60 .max_millivolts = 1125,
61 .min_millivolts = 750,
62 .nominal_millivolts = 1125,
63};
64
65static struct dvfs_rail tegra2_dvfs_rail_vdd_core = {
66 .reg_id = "vdd_core",
67 .max_millivolts = 1300,
68 .min_millivolts = 950,
69 .nominal_millivolts = 1225,
70 .step = 150, /* step vdd_core by 150 mV to allow vdd_aon to follow */
71};
72
73static struct dvfs_rail tegra2_dvfs_rail_vdd_aon = {
74 .reg_id = "vdd_aon",
75 .max_millivolts = 1300,
76 .min_millivolts = 950,
77 .nominal_millivolts = 1225,
78#ifndef CONFIG_TEGRA_CORE_DVFS
79 .disabled = true,
80#endif
81};
82
83/* vdd_core and vdd_aon must be 120 mV higher than vdd_cpu */
84static int tegra2_dvfs_rel_vdd_cpu_vdd_core(struct dvfs_rail *vdd_cpu,
85 struct dvfs_rail *vdd_core)
86{
87 if (vdd_cpu->new_millivolts > vdd_cpu->millivolts &&
88 vdd_core->new_millivolts < vdd_cpu->new_millivolts + 120)
89 return vdd_cpu->new_millivolts + 120;
90
91 if (vdd_core->new_millivolts < vdd_cpu->millivolts + 120)
92 return vdd_cpu->millivolts + 120;
93
94 return vdd_core->new_millivolts;
95}
96
97/* vdd_aon must be within 170 mV of vdd_core */
98static int tegra2_dvfs_rel_vdd_core_vdd_aon(struct dvfs_rail *vdd_core,
99 struct dvfs_rail *vdd_aon)
100{
101 BUG_ON(abs(vdd_aon->millivolts - vdd_core->millivolts) >
102 vdd_aon->step);
103 return vdd_core->millivolts;
104}
105
106static struct dvfs_relationship tegra2_dvfs_relationships[] = {
107 {
108 /* vdd_core must be 120 mV higher than vdd_cpu */
109 .from = &tegra2_dvfs_rail_vdd_cpu,
110 .to = &tegra2_dvfs_rail_vdd_core,
111 .solve = tegra2_dvfs_rel_vdd_cpu_vdd_core,
112 },
113 {
114 /* vdd_aon must be 120 mV higher than vdd_cpu */
115 .from = &tegra2_dvfs_rail_vdd_cpu,
116 .to = &tegra2_dvfs_rail_vdd_aon,
117 .solve = tegra2_dvfs_rel_vdd_cpu_vdd_core,
118 },
119 {
120 /* vdd_aon must be within 170 mV of vdd_core */
121 .from = &tegra2_dvfs_rail_vdd_core,
122 .to = &tegra2_dvfs_rail_vdd_aon,
123 .solve = tegra2_dvfs_rel_vdd_core_vdd_aon,
124 },
125};
126
127static struct dvfs_rail *tegra2_dvfs_rails[] = {
128 &tegra2_dvfs_rail_vdd_cpu,
129 &tegra2_dvfs_rail_vdd_core,
130 &tegra2_dvfs_rail_vdd_aon,
131};
132
133#define CPU_DVFS(_clk_name, _speedo_id, _process_id, _mult, _freqs...) \
134 { \
135 .clk_name = _clk_name, \
136 .speedo_id = _speedo_id, \
137 .process_id = _process_id, \
138 .freqs = {_freqs}, \
139 .freqs_mult = _mult, \
140 .millivolts = cpu_millivolts, \
141 .auto_dvfs = true, \
142 .dvfs_rail = &tegra2_dvfs_rail_vdd_cpu, \
143 }
144
145#define CORE_DVFS(_clk_name, _process_id, _auto, _mult, _freqs...) \
146 { \
147 .clk_name = _clk_name, \
148 .speedo_id = -1, \
149 .process_id = _process_id, \
150 .freqs = {_freqs}, \
151 .freqs_mult = _mult, \
152 .millivolts = core_millivolts, \
153 .auto_dvfs = _auto, \
154 .dvfs_rail = &tegra2_dvfs_rail_vdd_core, \
155 }
156
157static struct dvfs dvfs_init[] = {
158 /* Cpu voltages (mV): 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1100, 1125 */
159 CPU_DVFS("cpu", 0, 0, MHZ, 314, 314, 314, 456, 456, 456, 608, 608, 608, 760, 817, 817, 912, 1000),
160 CPU_DVFS("cpu", 0, 1, MHZ, 314, 314, 314, 456, 456, 456, 618, 618, 618, 770, 827, 827, 922, 1000),
161 CPU_DVFS("cpu", 0, 2, MHZ, 494, 494, 494, 675, 675, 817, 817, 922, 922, 1000),
162 CPU_DVFS("cpu", 0, 3, MHZ, 730, 760, 845, 845, 940, 1000),
163
164 CPU_DVFS("cpu", 1, 0, MHZ, 380, 380, 503, 503, 655, 655, 798, 798, 902, 902, 960, 1000),
165 CPU_DVFS("cpu", 1, 1, MHZ, 389, 389, 503, 503, 655, 760, 798, 798, 950, 950, 1000),
166 CPU_DVFS("cpu", 1, 2, MHZ, 598, 598, 750, 750, 893, 893, 1000),
167 CPU_DVFS("cpu", 1, 3, MHZ, 730, 760, 845, 845, 940, 1000),
168
169 CPU_DVFS("cpu", 2, 0, MHZ, 0, 0, 0, 0, 655, 655, 798, 798, 902, 902, 960, 1000, 1100, 1100, 1200),
170 CPU_DVFS("cpu", 2, 1, MHZ, 0, 0, 0, 0, 655, 760, 798, 798, 950, 950, 1015, 1015, 1100, 1200),
171 CPU_DVFS("cpu", 2, 2, MHZ, 0, 0, 0, 0, 769, 769, 902, 902, 1026, 1026, 1140, 1140, 1200),
172 CPU_DVFS("cpu", 2, 3, MHZ, 0, 0, 0, 0, 940, 1000, 1000, 1000, 1130, 1130, 1200),
173
174 /* Core voltages (mV): 950, 1000, 1100, 1200, 1225, 1275, 1300 */
175 CORE_DVFS("emc", -1, 1, KHZ, 57000, 333000, 380000, 666000, 666000, 666000, 760000),
176
177 CORE_DVFS("sdmmc1", -1, 1, KHZ, 44000, 52000, 52000, 52000, 52000, 52000, 52000),
178 CORE_DVFS("sdmmc2", -1, 1, KHZ, 44000, 52000, 52000, 52000, 52000, 52000, 52000),
179 CORE_DVFS("sdmmc3", -1, 1, KHZ, 44000, 52000, 52000, 52000, 52000, 52000, 52000),
180 CORE_DVFS("sdmmc4", -1, 1, KHZ, 44000, 52000, 52000, 52000, 52000, 52000, 52000),
181
182 CORE_DVFS("ndflash", -1, 1, KHZ, 130000, 150000, 158000, 164000, 164000, 164000, 164000),
183 CORE_DVFS("nor", -1, 1, KHZ, 0, 92000, 92000, 92000, 92000, 92000, 92000),
184 CORE_DVFS("ide", -1, 1, KHZ, 0, 0, 100000, 100000, 100000, 100000, 100000),
185 CORE_DVFS("mipi", -1, 1, KHZ, 0, 40000, 40000, 40000, 40000, 60000, 60000),
186 CORE_DVFS("usbd", -1, 1, KHZ, 0, 0, 480000, 480000, 480000, 480000, 480000),
187 CORE_DVFS("usb2", -1, 1, KHZ, 0, 0, 480000, 480000, 480000, 480000, 480000),
188 CORE_DVFS("usb3", -1, 1, KHZ, 0, 0, 480000, 480000, 480000, 480000, 480000),
189 CORE_DVFS("pcie", -1, 1, KHZ, 0, 0, 0, 250000, 250000, 250000, 250000),
190 CORE_DVFS("dsi", -1, 1, KHZ, 100000, 100000, 100000, 500000, 500000, 500000, 500000),
191 CORE_DVFS("tvo", -1, 1, KHZ, 0, 0, 0, 250000, 250000, 250000, 250000),
192
193 /*
194 * The clock rate for the display controllers that determines the
195 * necessary core voltage depends on a divider that is internal
196 * to the display block. Disable auto-dvfs on the display clocks,
197 * and let the display driver call tegra_dvfs_set_rate manually
198 */
199 CORE_DVFS("disp1", -1, 0, KHZ, 158000, 158000, 190000, 190000, 190000, 190000, 190000),
200 CORE_DVFS("disp2", -1, 0, KHZ, 158000, 158000, 190000, 190000, 190000, 190000, 190000),
201 CORE_DVFS("hdmi", -1, 0, KHZ, 0, 0, 0, 148500, 148500, 148500, 148500),
202
203 /*
204 * Clocks below depend on the core process id. Define per process_id
205 * tables for SCLK/VDE/3D clocks (maximum rate for these clocks is
206 * increased depending on tegra2 sku). Use the worst case value for
207 * other clocks for now.
208 */
209 CORE_DVFS("host1x", -1, 1, KHZ, 104500, 133000, 166000, 166000, 166000, 166000, 166000),
210 CORE_DVFS("epp", -1, 1, KHZ, 133000, 171000, 247000, 300000, 300000, 300000, 300000),
211 CORE_DVFS("2d", -1, 1, KHZ, 133000, 171000, 247000, 300000, 300000, 300000, 300000),
212
213 CORE_DVFS("3d", 0, 1, KHZ, 114000, 161500, 247000, 304000, 304000, 333500, 333500),
214 CORE_DVFS("3d", 1, 1, KHZ, 161500, 209000, 285000, 333500, 333500, 361000, 361000),
215 CORE_DVFS("3d", 2, 1, KHZ, 218500, 256500, 323000, 380000, 380000, 400000, 400000),
216 CORE_DVFS("3d", 3, 1, KHZ, 247000, 285000, 351500, 400000, 400000, 400000, 400000),
217
218 CORE_DVFS("mpe", 0, 1, KHZ, 104500, 152000, 228000, 300000, 300000, 300000, 300000),
219 CORE_DVFS("mpe", 1, 1, KHZ, 142500, 190000, 275500, 300000, 300000, 300000, 300000),
220 CORE_DVFS("mpe", 2, 1, KHZ, 190000, 237500, 300000, 300000, 300000, 300000, 300000),
221 CORE_DVFS("mpe", 3, 1, KHZ, 228000, 266000, 300000, 300000, 300000, 300000, 300000),
222
223 CORE_DVFS("vi", -1, 1, KHZ, 85000, 100000, 150000, 150000, 150000, 150000, 150000),
224
225 CORE_DVFS("sclk", 0, 1, KHZ, 95000, 133000, 190000, 222500, 240000, 247000, 262000),
226 CORE_DVFS("sclk", 1, 1, KHZ, 123500, 159500, 207000, 240000, 240000, 264000, 277500),
227 CORE_DVFS("sclk", 2, 1, KHZ, 152000, 180500, 229500, 260000, 260000, 285000, 300000),
228 CORE_DVFS("sclk", 3, 1, KHZ, 171000, 218500, 256500, 292500, 292500, 300000, 300000),
229
230 CORE_DVFS("vde", 0, 1, KHZ, 95000, 123500, 209000, 275500, 275500, 300000, 300000),
231 CORE_DVFS("vde", 1, 1, KHZ, 123500, 152000, 237500, 300000, 300000, 300000, 300000),
232 CORE_DVFS("vde", 2, 1, KHZ, 152000, 209000, 285000, 300000, 300000, 300000, 300000),
233 CORE_DVFS("vde", 3, 1, KHZ, 171000, 218500, 300000, 300000, 300000, 300000, 300000),
234 /* What is this? */
235 CORE_DVFS("NVRM_DEVID_CLK_SRC", -1, 1, MHZ, 480, 600, 800, 1067, 1067, 1067, 1067),
236};
237
238int tegra_dvfs_disable_core_set(const char *arg, const struct kernel_param *kp)
239{
240 int ret;
241
242 ret = param_set_bool(arg, kp);
243 if (ret)
244 return ret;
245
246 if (tegra_dvfs_core_disabled)
247 tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core);
248 else
249 tegra_dvfs_rail_enable(&tegra2_dvfs_rail_vdd_core);
250
251 return 0;
252}
253
254int tegra_dvfs_disable_cpu_set(const char *arg, const struct kernel_param *kp)
255{
256 int ret;
257
258 ret = param_set_bool(arg, kp);
259 if (ret)
260 return ret;
261
262 if (tegra_dvfs_cpu_disabled)
263 tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu);
264 else
265 tegra_dvfs_rail_enable(&tegra2_dvfs_rail_vdd_cpu);
266
267 return 0;
268}
269
270int tegra_dvfs_disable_get(char *buffer, const struct kernel_param *kp)
271{
272 return param_get_bool(buffer, kp);
273}
274
275static struct kernel_param_ops tegra_dvfs_disable_core_ops = {
276 .set = tegra_dvfs_disable_core_set,
277 .get = tegra_dvfs_disable_get,
278};
279
280static struct kernel_param_ops tegra_dvfs_disable_cpu_ops = {
281 .set = tegra_dvfs_disable_cpu_set,
282 .get = tegra_dvfs_disable_get,
283};
284
285module_param_cb(disable_core, &tegra_dvfs_disable_core_ops,
286 &tegra_dvfs_core_disabled, 0644);
287module_param_cb(disable_cpu, &tegra_dvfs_disable_cpu_ops,
288 &tegra_dvfs_cpu_disabled, 0644);
289
290void __init tegra_soc_init_dvfs(void)
291{
292 int i;
293 struct clk *c;
294 struct dvfs *d;
295 int process_id;
296 int ret;
297 int cpu_process_id = tegra_cpu_process_id();
298 int core_process_id = tegra_core_process_id();
299 int speedo_id = tegra_soc_speedo_id();
300
301 BUG_ON(speedo_id >= ARRAY_SIZE(cpu_speedo_nominal_millivolts));
302 tegra2_dvfs_rail_vdd_cpu.nominal_millivolts =
303 cpu_speedo_nominal_millivolts[speedo_id];
304 BUG_ON(speedo_id >= ARRAY_SIZE(core_speedo_nominal_millivolts));
305 tegra2_dvfs_rail_vdd_core.nominal_millivolts =
306 core_speedo_nominal_millivolts[speedo_id];
307 tegra2_dvfs_rail_vdd_aon.nominal_millivolts =
308 core_speedo_nominal_millivolts[speedo_id];
309
310 tegra_dvfs_init_rails(tegra2_dvfs_rails, ARRAY_SIZE(tegra2_dvfs_rails));
311 tegra_dvfs_add_relationships(tegra2_dvfs_relationships,
312 ARRAY_SIZE(tegra2_dvfs_relationships));
313 /*
314 * VDD_CORE must always be at least 50 mV higher than VDD_CPU
315 * Fill out cpu_core_millivolts based on cpu_millivolts
316 */
317 for (i = 0; i < ARRAY_SIZE(dvfs_init); i++) {
318 d = &dvfs_init[i];
319
320 process_id = strcmp(d->clk_name, "cpu") ?
321 core_process_id : cpu_process_id;
322 if ((d->process_id != -1 && d->process_id != process_id) ||
323 (d->speedo_id != -1 && d->speedo_id != speedo_id)) {
324 pr_debug("tegra_dvfs: rejected %s speedo %d,"
325 " process %d\n", d->clk_name, d->speedo_id,
326 d->process_id);
327 continue;
328 }
329
330 c = tegra_get_clock_by_name(d->clk_name);
331
332 if (!c) {
333 pr_debug("tegra_dvfs: no clock found for %s\n",
334 d->clk_name);
335 continue;
336 }
337
338 ret = tegra_enable_dvfs_on_clk(c, d);
339 if (ret)
340 pr_err("tegra_dvfs: failed to enable dvfs on %s\n",
341 c->name);
342 }
343
344 if (tegra_dvfs_core_disabled)
345 tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_core);
346
347 if (tegra_dvfs_cpu_disabled)
348 tegra_dvfs_rail_disable(&tegra2_dvfs_rail_vdd_cpu);
349}