diff options
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.c | 267 | ||||
-rw-r--r-- | arch/arm/mach-tegra/clock.h | 58 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/mach/clk.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 778 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_dvfs.c | 86 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_dvfs.h | 20 |
7 files changed, 1005 insertions, 210 deletions
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 620347525272..3642e58e5073 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -8,6 +8,7 @@ obj-y += pinmux.o | |||
8 | obj-y += fuse.o | 8 | obj-y += fuse.o |
9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o | 9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o |
10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o | 10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o |
11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o | ||
11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o | 12 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o |
12 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o | 13 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o |
13 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 14 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 03ad578349b9..ae19f95585be 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -24,13 +24,80 @@ | |||
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/regulator/consumer.h> | ||
27 | #include <asm/clkdev.h> | 28 | #include <asm/clkdev.h> |
28 | 29 | ||
29 | #include "clock.h" | 30 | #include "clock.h" |
31 | #include "board.h" | ||
32 | #include "fuse.h" | ||
30 | 33 | ||
31 | static LIST_HEAD(clocks); | 34 | static LIST_HEAD(clocks); |
32 | 35 | ||
33 | static DEFINE_SPINLOCK(clock_lock); | 36 | static DEFINE_SPINLOCK(clock_lock); |
37 | static DEFINE_MUTEX(dvfs_lock); | ||
38 | |||
39 | static int clk_is_dvfs(struct clk *c) | ||
40 | { | ||
41 | return (c->dvfs != NULL); | ||
42 | }; | ||
43 | |||
44 | static int dvfs_set_rate(struct dvfs *d, unsigned long rate) | ||
45 | { | ||
46 | struct dvfs_table *t; | ||
47 | |||
48 | if (d->table == NULL) | ||
49 | return -ENODEV; | ||
50 | |||
51 | for (t = d->table; t->rate != 0; t++) { | ||
52 | if (rate <= t->rate) { | ||
53 | if (!d->reg) | ||
54 | return 0; | ||
55 | |||
56 | return regulator_set_voltage(d->reg, | ||
57 | t->millivolts * 1000, | ||
58 | d->max_millivolts * 1000); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | static void dvfs_init(struct clk *c) | ||
66 | { | ||
67 | int process_id; | ||
68 | int i; | ||
69 | struct dvfs_table *table; | ||
70 | |||
71 | process_id = c->dvfs->cpu ? tegra_core_process_id() : | ||
72 | tegra_cpu_process_id(); | ||
73 | |||
74 | for (i = 0; i < c->dvfs->process_id_table_length; i++) | ||
75 | if (process_id == c->dvfs->process_id_table[i].process_id) | ||
76 | c->dvfs->table = c->dvfs->process_id_table[i].table; | ||
77 | |||
78 | if (c->dvfs->table == NULL) { | ||
79 | pr_err("Failed to find dvfs table for clock %s process %d\n", | ||
80 | c->name, process_id); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | c->dvfs->max_millivolts = 0; | ||
85 | for (table = c->dvfs->table; table->rate != 0; table++) | ||
86 | if (c->dvfs->max_millivolts < table->millivolts) | ||
87 | c->dvfs->max_millivolts = table->millivolts; | ||
88 | |||
89 | c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id); | ||
90 | |||
91 | if (IS_ERR(c->dvfs->reg)) { | ||
92 | pr_err("Failed to get regulator %s for clock %s\n", | ||
93 | c->dvfs->reg_id, c->name); | ||
94 | c->dvfs->reg = NULL; | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | if (c->refcnt > 0) | ||
99 | dvfs_set_rate(c->dvfs, c->rate); | ||
100 | } | ||
34 | 101 | ||
35 | struct clk *tegra_get_clock_by_name(const char *name) | 102 | struct clk *tegra_get_clock_by_name(const char *name) |
36 | { | 103 | { |
@@ -48,14 +115,31 @@ struct clk *tegra_get_clock_by_name(const char *name) | |||
48 | return ret; | 115 | return ret; |
49 | } | 116 | } |
50 | 117 | ||
118 | static void clk_recalculate_rate(struct clk *c) | ||
119 | { | ||
120 | u64 rate; | ||
121 | |||
122 | if (!c->parent) | ||
123 | return; | ||
124 | |||
125 | rate = c->parent->rate; | ||
126 | |||
127 | if (c->mul != 0 && c->div != 0) { | ||
128 | rate = rate * c->mul; | ||
129 | do_div(rate, c->div); | ||
130 | } | ||
131 | |||
132 | if (rate > c->max_rate) | ||
133 | pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n", | ||
134 | c->name, rate, c->max_rate); | ||
135 | |||
136 | c->rate = rate; | ||
137 | } | ||
138 | |||
51 | int clk_reparent(struct clk *c, struct clk *parent) | 139 | int clk_reparent(struct clk *c, struct clk *parent) |
52 | { | 140 | { |
53 | pr_debug("%s: %s\n", __func__, c->name); | 141 | pr_debug("%s: %s\n", __func__, c->name); |
54 | if (c->refcnt && c->parent) | ||
55 | clk_disable_locked(c->parent); | ||
56 | c->parent = parent; | 142 | c->parent = parent; |
57 | if (c->refcnt && c->parent) | ||
58 | clk_enable_locked(c->parent); | ||
59 | list_del(&c->sibling); | 143 | list_del(&c->sibling); |
60 | list_add_tail(&c->sibling, &parent->children); | 144 | list_add_tail(&c->sibling, &parent->children); |
61 | return 0; | 145 | return 0; |
@@ -67,8 +151,7 @@ static void propagate_rate(struct clk *c) | |||
67 | pr_debug("%s: %s\n", __func__, c->name); | 151 | pr_debug("%s: %s\n", __func__, c->name); |
68 | list_for_each_entry(clkp, &c->children, sibling) { | 152 | list_for_each_entry(clkp, &c->children, sibling) { |
69 | pr_debug(" %s\n", clkp->name); | 153 | pr_debug(" %s\n", clkp->name); |
70 | if (clkp->ops->recalculate_rate) | 154 | clk_recalculate_rate(clkp); |
71 | clkp->ops->recalculate_rate(clkp); | ||
72 | propagate_rate(clkp); | 155 | propagate_rate(clkp); |
73 | } | 156 | } |
74 | } | 157 | } |
@@ -77,6 +160,8 @@ void clk_init(struct clk *c) | |||
77 | { | 160 | { |
78 | unsigned long flags; | 161 | unsigned long flags; |
79 | 162 | ||
163 | pr_debug("%s: %s\n", __func__, c->name); | ||
164 | |||
80 | spin_lock_irqsave(&clock_lock, flags); | 165 | spin_lock_irqsave(&clock_lock, flags); |
81 | 166 | ||
82 | INIT_LIST_HEAD(&c->children); | 167 | INIT_LIST_HEAD(&c->children); |
@@ -85,6 +170,8 @@ void clk_init(struct clk *c) | |||
85 | if (c->ops && c->ops->init) | 170 | if (c->ops && c->ops->init) |
86 | c->ops->init(c); | 171 | c->ops->init(c); |
87 | 172 | ||
173 | clk_recalculate_rate(c); | ||
174 | |||
88 | list_add(&c->node, &clocks); | 175 | list_add(&c->node, &clocks); |
89 | 176 | ||
90 | if (c->parent) | 177 | if (c->parent) |
@@ -122,13 +209,38 @@ int clk_enable_locked(struct clk *c) | |||
122 | return 0; | 209 | return 0; |
123 | } | 210 | } |
124 | 211 | ||
212 | int clk_enable_cansleep(struct clk *c) | ||
213 | { | ||
214 | int ret; | ||
215 | unsigned long flags; | ||
216 | |||
217 | mutex_lock(&dvfs_lock); | ||
218 | |||
219 | if (clk_is_dvfs(c) && c->refcnt > 0) | ||
220 | dvfs_set_rate(c->dvfs, c->rate); | ||
221 | |||
222 | spin_lock_irqsave(&clock_lock, flags); | ||
223 | ret = clk_enable_locked(c); | ||
224 | spin_unlock_irqrestore(&clock_lock, flags); | ||
225 | |||
226 | mutex_unlock(&dvfs_lock); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | EXPORT_SYMBOL(clk_enable_cansleep); | ||
231 | |||
125 | int clk_enable(struct clk *c) | 232 | int clk_enable(struct clk *c) |
126 | { | 233 | { |
127 | int ret; | 234 | int ret; |
128 | unsigned long flags; | 235 | unsigned long flags; |
236 | |||
237 | if (clk_is_dvfs(c)) | ||
238 | BUG(); | ||
239 | |||
129 | spin_lock_irqsave(&clock_lock, flags); | 240 | spin_lock_irqsave(&clock_lock, flags); |
130 | ret = clk_enable_locked(c); | 241 | ret = clk_enable_locked(c); |
131 | spin_unlock_irqrestore(&clock_lock, flags); | 242 | spin_unlock_irqrestore(&clock_lock, flags); |
243 | |||
132 | return ret; | 244 | return ret; |
133 | } | 245 | } |
134 | EXPORT_SYMBOL(clk_enable); | 246 | EXPORT_SYMBOL(clk_enable); |
@@ -152,9 +264,30 @@ void clk_disable_locked(struct clk *c) | |||
152 | c->refcnt--; | 264 | c->refcnt--; |
153 | } | 265 | } |
154 | 266 | ||
267 | void clk_disable_cansleep(struct clk *c) | ||
268 | { | ||
269 | unsigned long flags; | ||
270 | |||
271 | mutex_lock(&dvfs_lock); | ||
272 | |||
273 | spin_lock_irqsave(&clock_lock, flags); | ||
274 | clk_disable_locked(c); | ||
275 | spin_unlock_irqrestore(&clock_lock, flags); | ||
276 | |||
277 | if (clk_is_dvfs(c) && c->refcnt == 0) | ||
278 | dvfs_set_rate(c->dvfs, c->rate); | ||
279 | |||
280 | mutex_unlock(&dvfs_lock); | ||
281 | } | ||
282 | EXPORT_SYMBOL(clk_disable_cansleep); | ||
283 | |||
155 | void clk_disable(struct clk *c) | 284 | void clk_disable(struct clk *c) |
156 | { | 285 | { |
157 | unsigned long flags; | 286 | unsigned long flags; |
287 | |||
288 | if (clk_is_dvfs(c)) | ||
289 | BUG(); | ||
290 | |||
158 | spin_lock_irqsave(&clock_lock, flags); | 291 | spin_lock_irqsave(&clock_lock, flags); |
159 | clk_disable_locked(c); | 292 | clk_disable_locked(c); |
160 | spin_unlock_irqrestore(&clock_lock, flags); | 293 | spin_unlock_irqrestore(&clock_lock, flags); |
@@ -175,6 +308,8 @@ int clk_set_parent_locked(struct clk *c, struct clk *parent) | |||
175 | if (ret) | 308 | if (ret) |
176 | return ret; | 309 | return ret; |
177 | 310 | ||
311 | clk_recalculate_rate(c); | ||
312 | |||
178 | propagate_rate(c); | 313 | propagate_rate(c); |
179 | 314 | ||
180 | return 0; | 315 | return 0; |
@@ -197,22 +332,69 @@ struct clk *clk_get_parent(struct clk *c) | |||
197 | } | 332 | } |
198 | EXPORT_SYMBOL(clk_get_parent); | 333 | EXPORT_SYMBOL(clk_get_parent); |
199 | 334 | ||
200 | int clk_set_rate(struct clk *c, unsigned long rate) | 335 | int clk_set_rate_locked(struct clk *c, unsigned long rate) |
336 | { | ||
337 | int ret; | ||
338 | |||
339 | if (rate > c->max_rate) | ||
340 | rate = c->max_rate; | ||
341 | |||
342 | if (!c->ops || !c->ops->set_rate) | ||
343 | return -ENOSYS; | ||
344 | |||
345 | ret = c->ops->set_rate(c, rate); | ||
346 | |||
347 | if (ret) | ||
348 | return ret; | ||
349 | |||
350 | clk_recalculate_rate(c); | ||
351 | |||
352 | propagate_rate(c); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | int clk_set_rate_cansleep(struct clk *c, unsigned long rate) | ||
201 | { | 358 | { |
202 | int ret = 0; | 359 | int ret = 0; |
203 | unsigned long flags; | 360 | unsigned long flags; |
204 | 361 | ||
362 | pr_debug("%s: %s\n", __func__, c->name); | ||
363 | |||
364 | mutex_lock(&dvfs_lock); | ||
365 | |||
366 | if (rate > c->rate) | ||
367 | ret = dvfs_set_rate(c->dvfs, rate); | ||
368 | if (ret) | ||
369 | goto out; | ||
370 | |||
205 | spin_lock_irqsave(&clock_lock, flags); | 371 | spin_lock_irqsave(&clock_lock, flags); |
372 | ret = clk_set_rate_locked(c, rate); | ||
373 | spin_unlock_irqrestore(&clock_lock, flags); | ||
206 | 374 | ||
207 | pr_debug("%s: %s\n", __func__, c->name); | 375 | if (ret) |
376 | goto out; | ||
208 | 377 | ||
209 | if (c->ops && c->ops->set_rate) | 378 | ret = dvfs_set_rate(c->dvfs, rate); |
210 | ret = c->ops->set_rate(c, rate); | ||
211 | else | ||
212 | ret = -ENOSYS; | ||
213 | 379 | ||
214 | propagate_rate(c); | 380 | out: |
381 | mutex_unlock(&dvfs_lock); | ||
382 | return ret; | ||
383 | } | ||
384 | EXPORT_SYMBOL(clk_set_rate_cansleep); | ||
385 | |||
386 | int clk_set_rate(struct clk *c, unsigned long rate) | ||
387 | { | ||
388 | int ret = 0; | ||
389 | unsigned long flags; | ||
390 | |||
391 | pr_debug("%s: %s\n", __func__, c->name); | ||
392 | |||
393 | if (clk_is_dvfs(c)) | ||
394 | BUG(); | ||
215 | 395 | ||
396 | spin_lock_irqsave(&clock_lock, flags); | ||
397 | ret = clk_set_rate_locked(c, rate); | ||
216 | spin_unlock_irqrestore(&clock_lock, flags); | 398 | spin_unlock_irqrestore(&clock_lock, flags); |
217 | 399 | ||
218 | return ret; | 400 | return ret; |
@@ -235,6 +417,20 @@ unsigned long clk_get_rate(struct clk *c) | |||
235 | } | 417 | } |
236 | EXPORT_SYMBOL(clk_get_rate); | 418 | EXPORT_SYMBOL(clk_get_rate); |
237 | 419 | ||
420 | long clk_round_rate(struct clk *c, unsigned long rate) | ||
421 | { | ||
422 | pr_debug("%s: %s\n", __func__, c->name); | ||
423 | |||
424 | if (!c->ops || !c->ops->round_rate) | ||
425 | return -ENOSYS; | ||
426 | |||
427 | if (rate > c->max_rate) | ||
428 | rate = c->max_rate; | ||
429 | |||
430 | return c->ops->round_rate(c, rate); | ||
431 | } | ||
432 | EXPORT_SYMBOL(clk_round_rate); | ||
433 | |||
238 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) | 434 | static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) |
239 | { | 435 | { |
240 | struct clk *c; | 436 | struct clk *c; |
@@ -308,13 +504,28 @@ void tegra_periph_reset_assert(struct clk *c) | |||
308 | } | 504 | } |
309 | EXPORT_SYMBOL(tegra_periph_reset_assert); | 505 | EXPORT_SYMBOL(tegra_periph_reset_assert); |
310 | 506 | ||
311 | int __init tegra_init_clock(void) | 507 | void __init tegra_init_clock(void) |
312 | { | 508 | { |
313 | tegra2_init_clocks(); | 509 | tegra2_init_clocks(); |
510 | } | ||
511 | |||
512 | int __init tegra_init_dvfs(void) | ||
513 | { | ||
514 | struct clk *c, *safe; | ||
515 | |||
516 | mutex_lock(&dvfs_lock); | ||
517 | |||
518 | list_for_each_entry_safe(c, safe, &clocks, node) | ||
519 | if (c->dvfs) | ||
520 | dvfs_init(c); | ||
521 | |||
522 | mutex_unlock(&dvfs_lock); | ||
314 | 523 | ||
315 | return 0; | 524 | return 0; |
316 | } | 525 | } |
317 | 526 | ||
527 | late_initcall(tegra_init_dvfs); | ||
528 | |||
318 | #ifdef CONFIG_DEBUG_FS | 529 | #ifdef CONFIG_DEBUG_FS |
319 | static struct dentry *clk_debugfs_root; | 530 | static struct dentry *clk_debugfs_root; |
320 | 531 | ||
@@ -324,7 +535,7 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
324 | struct clk *child; | 535 | struct clk *child; |
325 | struct clk *safe; | 536 | struct clk *safe; |
326 | const char *state = "uninit"; | 537 | const char *state = "uninit"; |
327 | char div[5] = {0}; | 538 | char div[8] = {0}; |
328 | 539 | ||
329 | if (c->state == ON) | 540 | if (c->state == ON) |
330 | state = "on"; | 541 | state = "on"; |
@@ -332,16 +543,26 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
332 | state = "off"; | 543 | state = "off"; |
333 | 544 | ||
334 | if (c->mul != 0 && c->div != 0) { | 545 | if (c->mul != 0 && c->div != 0) { |
335 | BUG_ON(c->mul > 2); | 546 | if (c->mul > c->div) { |
336 | if (c->mul > c->div) | 547 | int mul = c->mul / c->div; |
337 | snprintf(div, sizeof(div), "x%d", c->mul / c->div); | 548 | int mul2 = (c->mul * 10 / c->div) % 10; |
338 | else | 549 | int mul3 = (c->mul * 10) % c->div; |
550 | if (mul2 == 0 && mul3 == 0) | ||
551 | snprintf(div, sizeof(div), "x%d", mul); | ||
552 | else if (mul3 == 0) | ||
553 | snprintf(div, sizeof(div), "x%d.%d", mul, mul2); | ||
554 | else | ||
555 | snprintf(div, sizeof(div), "x%d.%d..", mul, mul2); | ||
556 | } else { | ||
339 | snprintf(div, sizeof(div), "%d%s", c->div / c->mul, | 557 | snprintf(div, sizeof(div), "%d%s", c->div / c->mul, |
340 | (c->div % c->mul) ? ".5" : ""); | 558 | (c->div % c->mul) ? ".5" : ""); |
559 | } | ||
341 | } | 560 | } |
342 | 561 | ||
343 | seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n", | 562 | seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n", |
344 | level * 3 + 1, c->set ? "" : "*", | 563 | level * 3 + 1, "", |
564 | c->rate > c->max_rate ? '!' : ' ', | ||
565 | !c->set ? '*' : ' ', | ||
345 | 30 - level * 3, c->name, | 566 | 30 - level * 3, c->name, |
346 | state, c->refcnt, div, c->rate); | 567 | state, c->refcnt, div, c->rate); |
347 | list_for_each_entry_safe(child, safe, &c->children, sibling) { | 568 | list_for_each_entry_safe(child, safe, &c->children, sibling) { |
@@ -353,8 +574,8 @@ static int clock_tree_show(struct seq_file *s, void *data) | |||
353 | { | 574 | { |
354 | struct clk *c; | 575 | struct clk *c; |
355 | unsigned long flags; | 576 | unsigned long flags; |
356 | seq_printf(s, " clock state ref div rate \n"); | 577 | seq_printf(s, " clock state ref div rate\n"); |
357 | seq_printf(s, "-----------------------------------------------------------\n"); | 578 | seq_printf(s, "--------------------------------------------------------------\n"); |
358 | spin_lock_irqsave(&clock_lock, flags); | 579 | spin_lock_irqsave(&clock_lock, flags); |
359 | list_for_each_entry(c, &clocks, node) | 580 | list_for_each_entry(c, &clocks, node) |
360 | if (c->parent == NULL) | 581 | if (c->parent == NULL) |
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index af7c70e2a3ba..94fd859770f1 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h | |||
@@ -27,18 +27,43 @@ | |||
27 | #define DIV_U71 (1 << 1) | 27 | #define DIV_U71 (1 << 1) |
28 | #define DIV_U71_FIXED (1 << 2) | 28 | #define DIV_U71_FIXED (1 << 2) |
29 | #define DIV_2 (1 << 3) | 29 | #define DIV_2 (1 << 3) |
30 | #define PLL_FIXED (1 << 4) | 30 | #define DIV_U16 (1 << 4) |
31 | #define PLL_HAS_CPCON (1 << 5) | 31 | #define PLL_FIXED (1 << 5) |
32 | #define MUX (1 << 6) | 32 | #define PLL_HAS_CPCON (1 << 6) |
33 | #define PLLD (1 << 7) | 33 | #define MUX (1 << 7) |
34 | #define PERIPH_NO_RESET (1 << 8) | 34 | #define PLLD (1 << 8) |
35 | #define PERIPH_NO_ENB (1 << 9) | 35 | #define PERIPH_NO_RESET (1 << 9) |
36 | #define PERIPH_EMC_ENB (1 << 10) | 36 | #define PERIPH_NO_ENB (1 << 10) |
37 | #define PERIPH_MANUAL_RESET (1 << 11) | 37 | #define PERIPH_EMC_ENB (1 << 11) |
38 | #define PLL_ALT_MISC_REG (1 << 12) | 38 | #define PERIPH_MANUAL_RESET (1 << 12) |
39 | #define PLL_ALT_MISC_REG (1 << 13) | ||
40 | #define PLLU (1 << 14) | ||
39 | #define ENABLE_ON_INIT (1 << 28) | 41 | #define ENABLE_ON_INIT (1 << 28) |
40 | 42 | ||
41 | struct clk; | 43 | struct clk; |
44 | struct regulator; | ||
45 | |||
46 | struct dvfs_table { | ||
47 | unsigned long rate; | ||
48 | int millivolts; | ||
49 | }; | ||
50 | |||
51 | struct dvfs_process_id_table { | ||
52 | int process_id; | ||
53 | struct dvfs_table *table; | ||
54 | }; | ||
55 | |||
56 | |||
57 | struct dvfs { | ||
58 | struct regulator *reg; | ||
59 | struct dvfs_table *table; | ||
60 | int max_millivolts; | ||
61 | |||
62 | int process_id_table_length; | ||
63 | const char *reg_id; | ||
64 | bool cpu; | ||
65 | struct dvfs_process_id_table process_id_table[]; | ||
66 | }; | ||
42 | 67 | ||
43 | struct clk_mux_sel { | 68 | struct clk_mux_sel { |
44 | struct clk *input; | 69 | struct clk *input; |
@@ -58,12 +83,9 @@ struct clk_ops { | |||
58 | void (*init)(struct clk *); | 83 | void (*init)(struct clk *); |
59 | int (*enable)(struct clk *); | 84 | int (*enable)(struct clk *); |
60 | void (*disable)(struct clk *); | 85 | void (*disable)(struct clk *); |
61 | void (*recalc)(struct clk *); | ||
62 | int (*set_parent)(struct clk *, struct clk *); | 86 | int (*set_parent)(struct clk *, struct clk *); |
63 | int (*set_rate)(struct clk *, unsigned long); | 87 | int (*set_rate)(struct clk *, unsigned long); |
64 | unsigned long (*get_rate)(struct clk *); | ||
65 | long (*round_rate)(struct clk *, unsigned long); | 88 | long (*round_rate)(struct clk *, unsigned long); |
66 | unsigned long (*recalculate_rate)(struct clk *); | ||
67 | }; | 89 | }; |
68 | 90 | ||
69 | enum clk_state { | 91 | enum clk_state { |
@@ -85,6 +107,7 @@ struct clk { | |||
85 | struct clk *parent; | 107 | struct clk *parent; |
86 | struct clk_lookup lookup; | 108 | struct clk_lookup lookup; |
87 | unsigned long rate; | 109 | unsigned long rate; |
110 | unsigned long max_rate; | ||
88 | u32 flags; | 111 | u32 flags; |
89 | u32 refcnt; | 112 | u32 refcnt; |
90 | const char *name; | 113 | const char *name; |
@@ -103,10 +126,6 @@ struct clk { | |||
103 | unsigned long cf_max; | 126 | unsigned long cf_max; |
104 | unsigned long vco_min; | 127 | unsigned long vco_min; |
105 | unsigned long vco_max; | 128 | unsigned long vco_max; |
106 | u32 m; | ||
107 | u32 n; | ||
108 | u32 p; | ||
109 | u32 cpcon; | ||
110 | const struct clk_pll_table *pll_table; | 129 | const struct clk_pll_table *pll_table; |
111 | 130 | ||
112 | /* DIV */ | 131 | /* DIV */ |
@@ -117,6 +136,12 @@ struct clk { | |||
117 | const struct clk_mux_sel *inputs; | 136 | const struct clk_mux_sel *inputs; |
118 | u32 sel; | 137 | u32 sel; |
119 | u32 reg_mask; | 138 | u32 reg_mask; |
139 | |||
140 | /* Virtual cpu clock */ | ||
141 | struct clk *main; | ||
142 | struct clk *backup; | ||
143 | |||
144 | struct dvfs *dvfs; | ||
120 | }; | 145 | }; |
121 | 146 | ||
122 | 147 | ||
@@ -141,6 +166,7 @@ unsigned long clk_measure_input_freq(void); | |||
141 | void clk_disable_locked(struct clk *c); | 166 | void clk_disable_locked(struct clk *c); |
142 | int clk_enable_locked(struct clk *c); | 167 | int clk_enable_locked(struct clk *c); |
143 | int clk_set_parent_locked(struct clk *c, struct clk *parent); | 168 | int clk_set_parent_locked(struct clk *c, struct clk *parent); |
169 | int clk_set_rate_locked(struct clk *c, unsigned long rate); | ||
144 | int clk_reparent(struct clk *c, struct clk *parent); | 170 | int clk_reparent(struct clk *c, struct clk *parent); |
145 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); | 171 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); |
146 | 172 | ||
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index 2896f25ebfb5..d7723955dac7 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h | |||
@@ -23,4 +23,9 @@ | |||
23 | void tegra_periph_reset_deassert(struct clk *c); | 23 | void tegra_periph_reset_deassert(struct clk *c); |
24 | void tegra_periph_reset_assert(struct clk *c); | 24 | void tegra_periph_reset_assert(struct clk *c); |
25 | 25 | ||
26 | int clk_enable_cansleep(struct clk *clk); | ||
27 | void clk_disable_cansleep(struct clk *clk); | ||
28 | int clk_set_rate_cansleep(struct clk *clk, unsigned long rate); | ||
29 | int clk_set_parent_cansleep(struct clk *clk, struct clk *parent); | ||
30 | |||
26 | #endif | 31 | #endif |
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 426163231fff..cf1c9d0ef7e1 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -30,14 +30,21 @@ | |||
30 | #include <mach/iomap.h> | 30 | #include <mach/iomap.h> |
31 | 31 | ||
32 | #include "clock.h" | 32 | #include "clock.h" |
33 | #include "fuse.h" | ||
34 | #include "tegra2_dvfs.h" | ||
33 | 35 | ||
34 | #define RST_DEVICES 0x004 | 36 | #define RST_DEVICES 0x004 |
35 | #define RST_DEVICES_SET 0x300 | 37 | #define RST_DEVICES_SET 0x300 |
36 | #define RST_DEVICES_CLR 0x304 | 38 | #define RST_DEVICES_CLR 0x304 |
39 | #define RST_DEVICES_NUM 3 | ||
37 | 40 | ||
38 | #define CLK_OUT_ENB 0x010 | 41 | #define CLK_OUT_ENB 0x010 |
39 | #define CLK_OUT_ENB_SET 0x320 | 42 | #define CLK_OUT_ENB_SET 0x320 |
40 | #define CLK_OUT_ENB_CLR 0x324 | 43 | #define CLK_OUT_ENB_CLR 0x324 |
44 | #define CLK_OUT_ENB_NUM 3 | ||
45 | |||
46 | #define CLK_MASK_ARM 0x44 | ||
47 | #define MISC_CLK_ENB 0x48 | ||
41 | 48 | ||
42 | #define OSC_CTRL 0x50 | 49 | #define OSC_CTRL 0x50 |
43 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) | 50 | #define OSC_CTRL_OSC_FREQ_MASK (3<<30) |
@@ -45,6 +52,7 @@ | |||
45 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) | 52 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) |
46 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) | 53 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) |
47 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) | 54 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) |
55 | #define OSC_CTRL_MASK 0x3f2 | ||
48 | 56 | ||
49 | #define OSC_FREQ_DET 0x58 | 57 | #define OSC_FREQ_DET 0x58 |
50 | #define OSC_FREQ_DET_TRIG (1<<31) | 58 | #define OSC_FREQ_DET_TRIG (1<<31) |
@@ -53,10 +61,17 @@ | |||
53 | #define OSC_FREQ_DET_BUSY (1<<31) | 61 | #define OSC_FREQ_DET_BUSY (1<<31) |
54 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF | 62 | #define OSC_FREQ_DET_CNT_MASK 0xFFFF |
55 | 63 | ||
64 | #define PERIPH_CLK_SOURCE_I2S1 0x100 | ||
65 | #define PERIPH_CLK_SOURCE_EMC 0x19c | ||
66 | #define PERIPH_CLK_SOURCE_OSC 0x1fc | ||
67 | #define PERIPH_CLK_SOURCE_NUM \ | ||
68 | ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4) | ||
69 | |||
56 | #define PERIPH_CLK_SOURCE_MASK (3<<30) | 70 | #define PERIPH_CLK_SOURCE_MASK (3<<30) |
57 | #define PERIPH_CLK_SOURCE_SHIFT 30 | 71 | #define PERIPH_CLK_SOURCE_SHIFT 30 |
58 | #define PERIPH_CLK_SOURCE_ENABLE (1<<28) | 72 | #define PERIPH_CLK_SOURCE_ENABLE (1<<28) |
59 | #define PERIPH_CLK_SOURCE_DIV_MASK 0xFF | 73 | #define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF |
74 | #define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF | ||
60 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 | 75 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 |
61 | 76 | ||
62 | #define PLL_BASE 0x0 | 77 | #define PLL_BASE 0x0 |
@@ -79,8 +94,9 @@ | |||
79 | #define PLL_OUT_RESET_DISABLE (1<<0) | 94 | #define PLL_OUT_RESET_DISABLE (1<<0) |
80 | 95 | ||
81 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) | 96 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) |
97 | #define PLL_MISC_LOCK_ENABLE(c) (((c)->flags & PLLU) ? (1<<22) : (1<<18)) | ||
98 | |||
82 | #define PLL_MISC_DCCON_SHIFT 20 | 99 | #define PLL_MISC_DCCON_SHIFT 20 |
83 | #define PLL_MISC_LOCK_ENABLE (1<<18) | ||
84 | #define PLL_MISC_CPCON_SHIFT 8 | 100 | #define PLL_MISC_CPCON_SHIFT 8 |
85 | #define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) | 101 | #define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT) |
86 | #define PLL_MISC_LFCON_SHIFT 4 | 102 | #define PLL_MISC_LFCON_SHIFT 4 |
@@ -88,6 +104,8 @@ | |||
88 | #define PLL_MISC_VCOCON_SHIFT 0 | 104 | #define PLL_MISC_VCOCON_SHIFT 0 |
89 | #define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) | 105 | #define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT) |
90 | 106 | ||
107 | #define PLLU_BASE_POST_DIV (1<<20) | ||
108 | |||
91 | #define PLLD_MISC_CLKENABLE (1<<30) | 109 | #define PLLD_MISC_CLKENABLE (1<<30) |
92 | #define PLLD_MISC_DIV_RST (1<<23) | 110 | #define PLLD_MISC_DIV_RST (1<<23) |
93 | #define PLLD_MISC_DCCON_SHIFT 12 | 111 | #define PLLD_MISC_DCCON_SHIFT 12 |
@@ -143,30 +161,37 @@ unsigned long clk_measure_input_freq(void) | |||
143 | } | 161 | } |
144 | } | 162 | } |
145 | 163 | ||
146 | static int clk_div71_get_divider(struct clk *c, unsigned long rate) | 164 | static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate) |
147 | { | 165 | { |
148 | unsigned long divider_u71; | 166 | s64 divider_u71 = parent_rate * 2; |
167 | divider_u71 += rate - 1; | ||
168 | do_div(divider_u71, rate); | ||
149 | 169 | ||
150 | divider_u71 = DIV_ROUND_UP(c->rate * 2, rate); | 170 | if (divider_u71 - 2 < 0) |
171 | return 0; | ||
151 | 172 | ||
152 | if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0) | 173 | if (divider_u71 - 2 > 255) |
153 | return -EINVAL; | 174 | return -EINVAL; |
154 | 175 | ||
155 | return divider_u71 - 2; | 176 | return divider_u71 - 2; |
156 | } | 177 | } |
157 | 178 | ||
158 | static unsigned long tegra2_clk_recalculate_rate(struct clk *c) | 179 | static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) |
159 | { | 180 | { |
160 | unsigned long rate; | 181 | s64 divider_u16; |
161 | rate = c->parent->rate; | ||
162 | 182 | ||
163 | if (c->mul != 0 && c->div != 0) | 183 | divider_u16 = parent_rate; |
164 | c->rate = rate * c->mul / c->div; | 184 | divider_u16 += rate - 1; |
165 | else | 185 | do_div(divider_u16, rate); |
166 | c->rate = rate; | ||
167 | return c->rate; | ||
168 | } | ||
169 | 186 | ||
187 | if (divider_u16 - 1 < 0) | ||
188 | return 0; | ||
189 | |||
190 | if (divider_u16 - 1 > 255) | ||
191 | return -EINVAL; | ||
192 | |||
193 | return divider_u16 - 1; | ||
194 | } | ||
170 | 195 | ||
171 | /* clk_m functions */ | 196 | /* clk_m functions */ |
172 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | 197 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) |
@@ -244,7 +269,6 @@ static void tegra2_super_clk_init(struct clk *c) | |||
244 | } | 269 | } |
245 | BUG_ON(sel->input == NULL); | 270 | BUG_ON(sel->input == NULL); |
246 | c->parent = sel->input; | 271 | c->parent = sel->input; |
247 | tegra2_clk_recalculate_rate(c); | ||
248 | } | 272 | } |
249 | 273 | ||
250 | static int tegra2_super_clk_enable(struct clk *c) | 274 | static int tegra2_super_clk_enable(struct clk *c) |
@@ -266,6 +290,7 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
266 | u32 val; | 290 | u32 val; |
267 | const struct clk_mux_sel *sel; | 291 | const struct clk_mux_sel *sel; |
268 | int shift; | 292 | int shift; |
293 | |||
269 | val = clk_readl(c->reg + SUPER_CLK_MUX);; | 294 | val = clk_readl(c->reg + SUPER_CLK_MUX);; |
270 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | 295 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && |
271 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | 296 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); |
@@ -273,11 +298,18 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
273 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | 298 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; |
274 | for (sel = c->inputs; sel->input != NULL; sel++) { | 299 | for (sel = c->inputs; sel->input != NULL; sel++) { |
275 | if (sel->input == p) { | 300 | if (sel->input == p) { |
276 | clk_reparent(c, p); | ||
277 | val &= ~(SUPER_SOURCE_MASK << shift); | 301 | val &= ~(SUPER_SOURCE_MASK << shift); |
278 | val |= sel->value << shift; | 302 | val |= sel->value << shift; |
303 | |||
304 | if (c->refcnt) | ||
305 | clk_enable_locked(p); | ||
306 | |||
279 | clk_writel(val, c->reg); | 307 | clk_writel(val, c->reg); |
280 | c->rate = c->parent->rate; | 308 | |
309 | if (c->refcnt && c->parent) | ||
310 | clk_disable_locked(c->parent); | ||
311 | |||
312 | clk_reparent(c, p); | ||
281 | return 0; | 313 | return 0; |
282 | } | 314 | } |
283 | } | 315 | } |
@@ -289,7 +321,61 @@ static struct clk_ops tegra_super_ops = { | |||
289 | .enable = tegra2_super_clk_enable, | 321 | .enable = tegra2_super_clk_enable, |
290 | .disable = tegra2_super_clk_disable, | 322 | .disable = tegra2_super_clk_disable, |
291 | .set_parent = tegra2_super_clk_set_parent, | 323 | .set_parent = tegra2_super_clk_set_parent, |
292 | .recalculate_rate = tegra2_clk_recalculate_rate, | 324 | }; |
325 | |||
326 | /* virtual cpu clock functions */ | ||
327 | /* some clocks can not be stopped (cpu, memory bus) while the SoC is running. | ||
328 | To change the frequency of these clocks, the parent pll may need to be | ||
329 | reprogrammed, so the clock must be moved off the pll, the pll reprogrammed, | ||
330 | and then the clock moved back to the pll. To hide this sequence, a virtual | ||
331 | clock handles it. | ||
332 | */ | ||
333 | static void tegra2_cpu_clk_init(struct clk *c) | ||
334 | { | ||
335 | } | ||
336 | |||
337 | static int tegra2_cpu_clk_enable(struct clk *c) | ||
338 | { | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static void tegra2_cpu_clk_disable(struct clk *c) | ||
343 | { | ||
344 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
345 | |||
346 | /* oops - don't disable the CPU clock! */ | ||
347 | BUG(); | ||
348 | } | ||
349 | |||
350 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) | ||
351 | { | ||
352 | int ret; | ||
353 | ret = clk_set_parent_locked(c->parent, c->backup); | ||
354 | if (ret) { | ||
355 | pr_err("Failed to switch cpu to clock %s\n", c->backup->name); | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | ret = clk_set_rate_locked(c->main, rate); | ||
360 | if (ret) { | ||
361 | pr_err("Failed to change cpu pll to %lu\n", rate); | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | ret = clk_set_parent_locked(c->parent, c->main); | ||
366 | if (ret) { | ||
367 | pr_err("Failed to switch cpu to clock %s\n", c->main->name); | ||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | static struct clk_ops tegra_cpu_ops = { | ||
375 | .init = tegra2_cpu_clk_init, | ||
376 | .enable = tegra2_cpu_clk_enable, | ||
377 | .disable = tegra2_cpu_clk_disable, | ||
378 | .set_rate = tegra2_cpu_clk_set_rate, | ||
293 | }; | 379 | }; |
294 | 380 | ||
295 | /* bus clock functions */ | 381 | /* bus clock functions */ |
@@ -299,7 +385,6 @@ static void tegra2_bus_clk_init(struct clk *c) | |||
299 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | 385 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; |
300 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | 386 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; |
301 | c->mul = 1; | 387 | c->mul = 1; |
302 | tegra2_clk_recalculate_rate(c); | ||
303 | } | 388 | } |
304 | 389 | ||
305 | static int tegra2_bus_clk_enable(struct clk *c) | 390 | static int tegra2_bus_clk_enable(struct clk *c) |
@@ -340,27 +425,15 @@ static struct clk_ops tegra_bus_ops = { | |||
340 | .enable = tegra2_bus_clk_enable, | 425 | .enable = tegra2_bus_clk_enable, |
341 | .disable = tegra2_bus_clk_disable, | 426 | .disable = tegra2_bus_clk_disable, |
342 | .set_rate = tegra2_bus_clk_set_rate, | 427 | .set_rate = tegra2_bus_clk_set_rate, |
343 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
344 | }; | 428 | }; |
345 | 429 | ||
346 | /* PLL Functions */ | 430 | /* PLL Functions */ |
347 | static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c) | ||
348 | { | ||
349 | u64 rate; | ||
350 | rate = c->parent->rate; | ||
351 | rate *= c->n; | ||
352 | do_div(rate, c->m); | ||
353 | if (c->p == 2) | ||
354 | rate >>= 1; | ||
355 | c->rate = rate; | ||
356 | return c->rate; | ||
357 | } | ||
358 | |||
359 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | 431 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) |
360 | { | 432 | { |
361 | ktime_t before; | 433 | ktime_t before; |
362 | 434 | ||
363 | before = ktime_get(); | 435 | before = ktime_get(); |
436 | |||
364 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { | 437 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { |
365 | if (ktime_us_delta(ktime_get(), before) > 5000) { | 438 | if (ktime_us_delta(ktime_get(), before) > 5000) { |
366 | pr_err("Timed out waiting for lock bit on pll %s", | 439 | pr_err("Timed out waiting for lock bit on pll %s", |
@@ -380,24 +453,19 @@ static void tegra2_pll_clk_init(struct clk *c) | |||
380 | 453 | ||
381 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { | 454 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { |
382 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); | 455 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); |
383 | c->n = 1; | 456 | c->mul = 1; |
384 | c->m = 0; | 457 | c->div = 1; |
385 | c->p = 1; | ||
386 | } else if (val & PLL_BASE_BYPASS) { | 458 | } else if (val & PLL_BASE_BYPASS) { |
387 | c->n = 1; | 459 | c->mul = 1; |
388 | c->m = 1; | 460 | c->div = 1; |
389 | c->p = 1; | ||
390 | } else { | 461 | } else { |
391 | c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; | 462 | c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; |
392 | c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; | 463 | c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; |
393 | c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | 464 | if (c->flags & PLLU) |
465 | c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2; | ||
466 | else | ||
467 | c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | ||
394 | } | 468 | } |
395 | |||
396 | val = clk_readl(c->reg + PLL_MISC(c)); | ||
397 | if (c->flags & PLL_HAS_CPCON) | ||
398 | c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT; | ||
399 | |||
400 | tegra2_pll_clk_recalculate_rate(c); | ||
401 | } | 469 | } |
402 | 470 | ||
403 | static int tegra2_pll_clk_enable(struct clk *c) | 471 | static int tegra2_pll_clk_enable(struct clk *c) |
@@ -411,7 +479,7 @@ static int tegra2_pll_clk_enable(struct clk *c) | |||
411 | clk_writel(val, c->reg + PLL_BASE); | 479 | clk_writel(val, c->reg + PLL_BASE); |
412 | 480 | ||
413 | val = clk_readl(c->reg + PLL_MISC(c)); | 481 | val = clk_readl(c->reg + PLL_MISC(c)); |
414 | val |= PLL_MISC_LOCK_ENABLE; | 482 | val |= PLL_MISC_LOCK_ENABLE(c); |
415 | clk_writel(val, c->reg + PLL_MISC(c)); | 483 | clk_writel(val, c->reg + PLL_MISC(c)); |
416 | 484 | ||
417 | tegra2_pll_clk_wait_for_lock(c); | 485 | tegra2_pll_clk_wait_for_lock(c); |
@@ -441,33 +509,36 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | |||
441 | input_rate = c->parent->rate; | 509 | input_rate = c->parent->rate; |
442 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { | 510 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { |
443 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | 511 | if (sel->input_rate == input_rate && sel->output_rate == rate) { |
444 | c->n = sel->n; | 512 | c->mul = sel->n; |
445 | c->m = sel->m; | 513 | c->div = sel->m * sel->p; |
446 | c->p = sel->p; | ||
447 | c->cpcon = sel->cpcon; | ||
448 | 514 | ||
449 | val = clk_readl(c->reg + PLL_BASE); | 515 | val = clk_readl(c->reg + PLL_BASE); |
450 | if (c->flags & PLL_FIXED) | 516 | if (c->flags & PLL_FIXED) |
451 | val |= PLL_BASE_OVERRIDE; | 517 | val |= PLL_BASE_OVERRIDE; |
452 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | | 518 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | |
453 | PLL_BASE_DIVM_MASK); | 519 | PLL_BASE_DIVM_MASK); |
454 | val |= (c->m << PLL_BASE_DIVM_SHIFT) | | 520 | val |= (sel->m << PLL_BASE_DIVM_SHIFT) | |
455 | (c->n << PLL_BASE_DIVN_SHIFT); | 521 | (sel->n << PLL_BASE_DIVN_SHIFT); |
456 | BUG_ON(c->p > 2); | 522 | BUG_ON(sel->p < 1 || sel->p > 2); |
457 | if (c->p == 2) | 523 | if (c->flags & PLLU) { |
458 | val |= 1 << PLL_BASE_DIVP_SHIFT; | 524 | if (sel->p == 1) |
525 | val |= PLLU_BASE_POST_DIV; | ||
526 | } else { | ||
527 | if (sel->p == 2) | ||
528 | val |= 1 << PLL_BASE_DIVP_SHIFT; | ||
529 | } | ||
459 | clk_writel(val, c->reg + PLL_BASE); | 530 | clk_writel(val, c->reg + PLL_BASE); |
460 | 531 | ||
461 | if (c->flags & PLL_HAS_CPCON) { | 532 | if (c->flags & PLL_HAS_CPCON) { |
462 | val = c->cpcon << PLL_MISC_CPCON_SHIFT; | 533 | val = clk_readl(c->reg + PLL_MISC(c)); |
463 | val |= PLL_MISC_LOCK_ENABLE; | 534 | val &= ~PLL_MISC_CPCON_MASK; |
535 | val |= sel->cpcon << PLL_MISC_CPCON_SHIFT; | ||
464 | clk_writel(val, c->reg + PLL_MISC(c)); | 536 | clk_writel(val, c->reg + PLL_MISC(c)); |
465 | } | 537 | } |
466 | 538 | ||
467 | if (c->state == ON) | 539 | if (c->state == ON) |
468 | tegra2_pll_clk_enable(c); | 540 | tegra2_pll_clk_enable(c); |
469 | 541 | ||
470 | c->rate = rate; | ||
471 | return 0; | 542 | return 0; |
472 | } | 543 | } |
473 | } | 544 | } |
@@ -479,7 +550,21 @@ static struct clk_ops tegra_pll_ops = { | |||
479 | .enable = tegra2_pll_clk_enable, | 550 | .enable = tegra2_pll_clk_enable, |
480 | .disable = tegra2_pll_clk_disable, | 551 | .disable = tegra2_pll_clk_disable, |
481 | .set_rate = tegra2_pll_clk_set_rate, | 552 | .set_rate = tegra2_pll_clk_set_rate, |
482 | .recalculate_rate = tegra2_pll_clk_recalculate_rate, | 553 | }; |
554 | |||
555 | static void tegra2_pllx_clk_init(struct clk *c) | ||
556 | { | ||
557 | tegra2_pll_clk_init(c); | ||
558 | |||
559 | if (tegra_sku_id() == 7) | ||
560 | c->max_rate = 750000000; | ||
561 | } | ||
562 | |||
563 | static struct clk_ops tegra_pllx_ops = { | ||
564 | .init = tegra2_pllx_clk_init, | ||
565 | .enable = tegra2_pll_clk_enable, | ||
566 | .disable = tegra2_pll_clk_disable, | ||
567 | .set_rate = tegra2_pll_clk_set_rate, | ||
483 | }; | 568 | }; |
484 | 569 | ||
485 | /* Clock divider ops */ | 570 | /* Clock divider ops */ |
@@ -503,8 +588,6 @@ static void tegra2_pll_div_clk_init(struct clk *c) | |||
503 | c->div = 1; | 588 | c->div = 1; |
504 | c->mul = 1; | 589 | c->mul = 1; |
505 | } | 590 | } |
506 | |||
507 | tegra2_clk_recalculate_rate(c); | ||
508 | } | 591 | } |
509 | 592 | ||
510 | static int tegra2_pll_div_clk_enable(struct clk *c) | 593 | static int tegra2_pll_div_clk_enable(struct clk *c) |
@@ -565,7 +648,7 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
565 | int divider_u71; | 648 | int divider_u71; |
566 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 649 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
567 | if (c->flags & DIV_U71) { | 650 | if (c->flags & DIV_U71) { |
568 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 651 | divider_u71 = clk_div71_get_divider(c->parent->rate, rate); |
569 | if (divider_u71 >= 0) { | 652 | if (divider_u71 >= 0) { |
570 | val = clk_readl(c->reg); | 653 | val = clk_readl(c->reg); |
571 | new_val = val >> c->reg_shift; | 654 | new_val = val >> c->reg_shift; |
@@ -580,25 +663,37 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
580 | clk_writel(val, c->reg); | 663 | clk_writel(val, c->reg); |
581 | c->div = divider_u71 + 2; | 664 | c->div = divider_u71 + 2; |
582 | c->mul = 2; | 665 | c->mul = 2; |
583 | tegra2_clk_recalculate_rate(c); | ||
584 | return 0; | 666 | return 0; |
585 | } | 667 | } |
586 | } else if (c->flags & DIV_2) { | 668 | } else if (c->flags & DIV_2) { |
587 | if (c->parent->rate == rate * 2) { | 669 | if (c->parent->rate == rate * 2) |
588 | c->rate = rate; | ||
589 | return 0; | 670 | return 0; |
590 | } | ||
591 | } | 671 | } |
592 | return -EINVAL; | 672 | return -EINVAL; |
593 | } | 673 | } |
594 | 674 | ||
675 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | ||
676 | { | ||
677 | int divider; | ||
678 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
679 | |||
680 | if (c->flags & DIV_U71) { | ||
681 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
682 | if (divider < 0) | ||
683 | return divider; | ||
684 | return c->parent->rate * 2 / (divider + 2); | ||
685 | } else if (c->flags & DIV_2) { | ||
686 | return c->parent->rate / 2; | ||
687 | } | ||
688 | return -EINVAL; | ||
689 | } | ||
595 | 690 | ||
596 | static struct clk_ops tegra_pll_div_ops = { | 691 | static struct clk_ops tegra_pll_div_ops = { |
597 | .init = tegra2_pll_div_clk_init, | 692 | .init = tegra2_pll_div_clk_init, |
598 | .enable = tegra2_pll_div_clk_enable, | 693 | .enable = tegra2_pll_div_clk_enable, |
599 | .disable = tegra2_pll_div_clk_disable, | 694 | .disable = tegra2_pll_div_clk_disable, |
600 | .set_rate = tegra2_pll_div_clk_set_rate, | 695 | .set_rate = tegra2_pll_div_clk_set_rate, |
601 | .recalculate_rate = tegra2_clk_recalculate_rate, | 696 | .round_rate = tegra2_pll_div_clk_round_rate, |
602 | }; | 697 | }; |
603 | 698 | ||
604 | /* Periph clk ops */ | 699 | /* Periph clk ops */ |
@@ -621,9 +716,13 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
621 | } | 716 | } |
622 | 717 | ||
623 | if (c->flags & DIV_U71) { | 718 | if (c->flags & DIV_U71) { |
624 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK; | 719 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; |
625 | c->div = divu71 + 2; | 720 | c->div = divu71 + 2; |
626 | c->mul = 2; | 721 | c->mul = 2; |
722 | } else if (c->flags & DIV_U16) { | ||
723 | u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
724 | c->div = divu16 + 1; | ||
725 | c->mul = 1; | ||
627 | } else { | 726 | } else { |
628 | c->div = 1; | 727 | c->div = 1; |
629 | c->mul = 1; | 728 | c->mul = 1; |
@@ -637,7 +736,6 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
637 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | 736 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & |
638 | PERIPH_CLK_TO_ENB_BIT(c)) | 737 | PERIPH_CLK_TO_ENB_BIT(c)) |
639 | c->state = OFF; | 738 | c->state = OFF; |
640 | tegra2_clk_recalculate_rate(c); | ||
641 | } | 739 | } |
642 | 740 | ||
643 | static int tegra2_periph_clk_enable(struct clk *c) | 741 | static int tegra2_periph_clk_enable(struct clk *c) |
@@ -692,12 +790,19 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
692 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); | 790 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); |
693 | for (sel = c->inputs; sel->input != NULL; sel++) { | 791 | for (sel = c->inputs; sel->input != NULL; sel++) { |
694 | if (sel->input == p) { | 792 | if (sel->input == p) { |
695 | clk_reparent(c, p); | ||
696 | val = clk_readl(c->reg); | 793 | val = clk_readl(c->reg); |
697 | val &= ~PERIPH_CLK_SOURCE_MASK; | 794 | val &= ~PERIPH_CLK_SOURCE_MASK; |
698 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; | 795 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; |
796 | |||
797 | if (c->refcnt) | ||
798 | clk_enable_locked(p); | ||
799 | |||
699 | clk_writel(val, c->reg); | 800 | clk_writel(val, c->reg); |
700 | c->rate = c->parent->rate; | 801 | |
802 | if (c->refcnt && c->parent) | ||
803 | clk_disable_locked(c->parent); | ||
804 | |||
805 | clk_reparent(c, p); | ||
701 | return 0; | 806 | return 0; |
702 | } | 807 | } |
703 | } | 808 | } |
@@ -708,20 +813,55 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
708 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | 813 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) |
709 | { | 814 | { |
710 | u32 val; | 815 | u32 val; |
711 | int divider_u71; | 816 | int divider; |
712 | pr_debug("%s: %lu\n", __func__, rate); | 817 | pr_debug("%s: %lu\n", __func__, rate); |
713 | if (c->flags & DIV_U71) { | 818 | if (c->flags & DIV_U71) { |
714 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 819 | divider = clk_div71_get_divider(c->parent->rate, rate); |
715 | if (divider_u71 >= 0) { | 820 | if (divider >= 0) { |
716 | val = clk_readl(c->reg); | 821 | val = clk_readl(c->reg); |
717 | val &= ~PERIPH_CLK_SOURCE_DIV_MASK; | 822 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; |
718 | val |= divider_u71; | 823 | val |= divider; |
719 | clk_writel(val, c->reg); | 824 | clk_writel(val, c->reg); |
720 | c->div = divider_u71 + 2; | 825 | c->div = divider + 2; |
721 | c->mul = 2; | 826 | c->mul = 2; |
722 | tegra2_clk_recalculate_rate(c); | ||
723 | return 0; | 827 | return 0; |
724 | } | 828 | } |
829 | } else if (c->flags & DIV_U16) { | ||
830 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
831 | if (divider >= 0) { | ||
832 | val = clk_readl(c->reg); | ||
833 | val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
834 | val |= divider; | ||
835 | clk_writel(val, c->reg); | ||
836 | c->div = divider + 1; | ||
837 | c->mul = 1; | ||
838 | return 0; | ||
839 | } | ||
840 | } else if (c->parent->rate <= rate) { | ||
841 | c->div = 1; | ||
842 | c->mul = 1; | ||
843 | return 0; | ||
844 | } | ||
845 | return -EINVAL; | ||
846 | } | ||
847 | |||
848 | static long tegra2_periph_clk_round_rate(struct clk *c, | ||
849 | unsigned long rate) | ||
850 | { | ||
851 | int divider; | ||
852 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
853 | |||
854 | if (c->flags & DIV_U71) { | ||
855 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
856 | if (divider < 0) | ||
857 | return divider; | ||
858 | |||
859 | return c->parent->rate * 2 / (divider + 2); | ||
860 | } else if (c->flags & DIV_U16) { | ||
861 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
862 | if (divider < 0) | ||
863 | return divider; | ||
864 | return c->parent->rate / (divider + 1); | ||
725 | } | 865 | } |
726 | return -EINVAL; | 866 | return -EINVAL; |
727 | } | 867 | } |
@@ -732,7 +872,7 @@ static struct clk_ops tegra_periph_clk_ops = { | |||
732 | .disable = &tegra2_periph_clk_disable, | 872 | .disable = &tegra2_periph_clk_disable, |
733 | .set_parent = &tegra2_periph_clk_set_parent, | 873 | .set_parent = &tegra2_periph_clk_set_parent, |
734 | .set_rate = &tegra2_periph_clk_set_rate, | 874 | .set_rate = &tegra2_periph_clk_set_rate, |
735 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 875 | .round_rate = &tegra2_periph_clk_round_rate, |
736 | }; | 876 | }; |
737 | 877 | ||
738 | /* Clock doubler ops */ | 878 | /* Clock doubler ops */ |
@@ -744,21 +884,108 @@ static void tegra2_clk_double_init(struct clk *c) | |||
744 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 884 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
745 | PERIPH_CLK_TO_ENB_BIT(c))) | 885 | PERIPH_CLK_TO_ENB_BIT(c))) |
746 | c->state = OFF; | 886 | c->state = OFF; |
747 | tegra2_clk_recalculate_rate(c); | ||
748 | }; | 887 | }; |
749 | 888 | ||
889 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) | ||
890 | { | ||
891 | if (rate != 2 * c->parent->rate) | ||
892 | return -EINVAL; | ||
893 | c->mul = 2; | ||
894 | c->div = 1; | ||
895 | return 0; | ||
896 | } | ||
897 | |||
750 | static struct clk_ops tegra_clk_double_ops = { | 898 | static struct clk_ops tegra_clk_double_ops = { |
751 | .init = &tegra2_clk_double_init, | 899 | .init = &tegra2_clk_double_init, |
752 | .enable = &tegra2_periph_clk_enable, | 900 | .enable = &tegra2_periph_clk_enable, |
753 | .disable = &tegra2_periph_clk_disable, | 901 | .disable = &tegra2_periph_clk_disable, |
754 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 902 | .set_rate = &tegra2_clk_double_set_rate, |
903 | }; | ||
904 | |||
905 | static void tegra2_audio_sync_clk_init(struct clk *c) | ||
906 | { | ||
907 | int source; | ||
908 | const struct clk_mux_sel *sel; | ||
909 | u32 val = clk_readl(c->reg); | ||
910 | c->state = (val & (1<<4)) ? OFF : ON; | ||
911 | source = val & 0xf; | ||
912 | for (sel = c->inputs; sel->input != NULL; sel++) | ||
913 | if (sel->value == source) | ||
914 | break; | ||
915 | BUG_ON(sel->input == NULL); | ||
916 | c->parent = sel->input; | ||
917 | } | ||
918 | |||
919 | static int tegra2_audio_sync_clk_enable(struct clk *c) | ||
920 | { | ||
921 | clk_writel(0, c->reg); | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | static void tegra2_audio_sync_clk_disable(struct clk *c) | ||
926 | { | ||
927 | clk_writel(1, c->reg); | ||
928 | } | ||
929 | |||
930 | static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | ||
931 | { | ||
932 | u32 val; | ||
933 | const struct clk_mux_sel *sel; | ||
934 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
935 | if (sel->input == p) { | ||
936 | val = clk_readl(c->reg); | ||
937 | val &= ~0xf; | ||
938 | val |= sel->value; | ||
939 | |||
940 | if (c->refcnt) | ||
941 | clk_enable_locked(p); | ||
942 | |||
943 | clk_writel(val, c->reg); | ||
944 | |||
945 | if (c->refcnt && c->parent) | ||
946 | clk_disable_locked(c->parent); | ||
947 | |||
948 | clk_reparent(c, p); | ||
949 | return 0; | ||
950 | } | ||
951 | } | ||
952 | |||
953 | return -EINVAL; | ||
954 | } | ||
955 | |||
956 | static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate) | ||
957 | { | ||
958 | unsigned long parent_rate; | ||
959 | if (!c->parent) { | ||
960 | pr_err("%s: clock has no parent\n", __func__); | ||
961 | return -EINVAL; | ||
962 | } | ||
963 | parent_rate = c->parent->rate; | ||
964 | if (rate != parent_rate) { | ||
965 | pr_err("%s: %s/%ld differs from parent %s/%ld\n", | ||
966 | __func__, | ||
967 | c->name, rate, | ||
968 | c->parent->name, parent_rate); | ||
969 | return -EINVAL; | ||
970 | } | ||
971 | c->rate = parent_rate; | ||
972 | return 0; | ||
973 | } | ||
974 | |||
975 | static struct clk_ops tegra_audio_sync_clk_ops = { | ||
976 | .init = tegra2_audio_sync_clk_init, | ||
977 | .enable = tegra2_audio_sync_clk_enable, | ||
978 | .disable = tegra2_audio_sync_clk_disable, | ||
979 | .set_rate = tegra2_audio_sync_clk_set_rate, | ||
980 | .set_parent = tegra2_audio_sync_clk_set_parent, | ||
755 | }; | 981 | }; |
756 | 982 | ||
757 | /* Clock definitions */ | 983 | /* Clock definitions */ |
758 | static struct clk tegra_clk_32k = { | 984 | static struct clk tegra_clk_32k = { |
759 | .name = "clk_32k", | 985 | .name = "clk_32k", |
760 | .rate = 32678, | 986 | .rate = 32768, |
761 | .ops = NULL, | 987 | .ops = NULL, |
988 | .max_rate = 32768, | ||
762 | }; | 989 | }; |
763 | 990 | ||
764 | static struct clk_pll_table tegra_pll_s_table[] = { | 991 | static struct clk_pll_table tegra_pll_s_table[] = { |
@@ -782,6 +1009,7 @@ static struct clk tegra_pll_s = { | |||
782 | .vco_min = 12000000, | 1009 | .vco_min = 12000000, |
783 | .vco_max = 26000000, | 1010 | .vco_max = 26000000, |
784 | .pll_table = tegra_pll_s_table, | 1011 | .pll_table = tegra_pll_s_table, |
1012 | .max_rate = 26000000, | ||
785 | }; | 1013 | }; |
786 | 1014 | ||
787 | static struct clk_mux_sel tegra_clk_m_sel[] = { | 1015 | static struct clk_mux_sel tegra_clk_m_sel[] = { |
@@ -797,6 +1025,7 @@ static struct clk tegra_clk_m = { | |||
797 | .reg = 0x1fc, | 1025 | .reg = 0x1fc, |
798 | .reg_mask = (1<<28), | 1026 | .reg_mask = (1<<28), |
799 | .reg_shift = 28, | 1027 | .reg_shift = 28, |
1028 | .max_rate = 26000000, | ||
800 | }; | 1029 | }; |
801 | 1030 | ||
802 | static struct clk_pll_table tegra_pll_c_table[] = { | 1031 | static struct clk_pll_table tegra_pll_c_table[] = { |
@@ -816,6 +1045,7 @@ static struct clk tegra_pll_c = { | |||
816 | .vco_min = 20000000, | 1045 | .vco_min = 20000000, |
817 | .vco_max = 1400000000, | 1046 | .vco_max = 1400000000, |
818 | .pll_table = tegra_pll_c_table, | 1047 | .pll_table = tegra_pll_c_table, |
1048 | .max_rate = 600000000, | ||
819 | }; | 1049 | }; |
820 | 1050 | ||
821 | static struct clk tegra_pll_c_out1 = { | 1051 | static struct clk tegra_pll_c_out1 = { |
@@ -825,9 +1055,18 @@ static struct clk tegra_pll_c_out1 = { | |||
825 | .parent = &tegra_pll_c, | 1055 | .parent = &tegra_pll_c, |
826 | .reg = 0x84, | 1056 | .reg = 0x84, |
827 | .reg_shift = 0, | 1057 | .reg_shift = 0, |
1058 | .max_rate = 600000000, | ||
828 | }; | 1059 | }; |
829 | 1060 | ||
830 | static struct clk_pll_table tegra_pll_m_table[] = { | 1061 | static struct clk_pll_table tegra_pll_m_table[] = { |
1062 | { 12000000, 666000000, 666, 12, 1, 8}, | ||
1063 | { 13000000, 666000000, 666, 13, 1, 8}, | ||
1064 | { 19200000, 666000000, 555, 16, 1, 8}, | ||
1065 | { 26000000, 666000000, 666, 26, 1, 8}, | ||
1066 | { 12000000, 600000000, 600, 12, 1, 8}, | ||
1067 | { 13000000, 600000000, 600, 13, 1, 8}, | ||
1068 | { 19200000, 600000000, 375, 12, 1, 6}, | ||
1069 | { 26000000, 600000000, 600, 26, 1, 8}, | ||
831 | { 0, 0, 0, 0, 0, 0 }, | 1070 | { 0, 0, 0, 0, 0, 0 }, |
832 | }; | 1071 | }; |
833 | 1072 | ||
@@ -844,6 +1083,7 @@ static struct clk tegra_pll_m = { | |||
844 | .vco_min = 20000000, | 1083 | .vco_min = 20000000, |
845 | .vco_max = 1200000000, | 1084 | .vco_max = 1200000000, |
846 | .pll_table = tegra_pll_m_table, | 1085 | .pll_table = tegra_pll_m_table, |
1086 | .max_rate = 800000000, | ||
847 | }; | 1087 | }; |
848 | 1088 | ||
849 | static struct clk tegra_pll_m_out1 = { | 1089 | static struct clk tegra_pll_m_out1 = { |
@@ -853,6 +1093,7 @@ static struct clk tegra_pll_m_out1 = { | |||
853 | .parent = &tegra_pll_m, | 1093 | .parent = &tegra_pll_m, |
854 | .reg = 0x94, | 1094 | .reg = 0x94, |
855 | .reg_shift = 0, | 1095 | .reg_shift = 0, |
1096 | .max_rate = 600000000, | ||
856 | }; | 1097 | }; |
857 | 1098 | ||
858 | static struct clk_pll_table tegra_pll_p_table[] = { | 1099 | static struct clk_pll_table tegra_pll_p_table[] = { |
@@ -880,6 +1121,7 @@ static struct clk tegra_pll_p = { | |||
880 | .vco_min = 20000000, | 1121 | .vco_min = 20000000, |
881 | .vco_max = 1400000000, | 1122 | .vco_max = 1400000000, |
882 | .pll_table = tegra_pll_p_table, | 1123 | .pll_table = tegra_pll_p_table, |
1124 | .max_rate = 432000000, | ||
883 | }; | 1125 | }; |
884 | 1126 | ||
885 | static struct clk tegra_pll_p_out1 = { | 1127 | static struct clk tegra_pll_p_out1 = { |
@@ -889,6 +1131,7 @@ static struct clk tegra_pll_p_out1 = { | |||
889 | .parent = &tegra_pll_p, | 1131 | .parent = &tegra_pll_p, |
890 | .reg = 0xa4, | 1132 | .reg = 0xa4, |
891 | .reg_shift = 0, | 1133 | .reg_shift = 0, |
1134 | .max_rate = 432000000, | ||
892 | }; | 1135 | }; |
893 | 1136 | ||
894 | static struct clk tegra_pll_p_out2 = { | 1137 | static struct clk tegra_pll_p_out2 = { |
@@ -898,6 +1141,7 @@ static struct clk tegra_pll_p_out2 = { | |||
898 | .parent = &tegra_pll_p, | 1141 | .parent = &tegra_pll_p, |
899 | .reg = 0xa4, | 1142 | .reg = 0xa4, |
900 | .reg_shift = 16, | 1143 | .reg_shift = 16, |
1144 | .max_rate = 432000000, | ||
901 | }; | 1145 | }; |
902 | 1146 | ||
903 | static struct clk tegra_pll_p_out3 = { | 1147 | static struct clk tegra_pll_p_out3 = { |
@@ -907,6 +1151,7 @@ static struct clk tegra_pll_p_out3 = { | |||
907 | .parent = &tegra_pll_p, | 1151 | .parent = &tegra_pll_p, |
908 | .reg = 0xa8, | 1152 | .reg = 0xa8, |
909 | .reg_shift = 0, | 1153 | .reg_shift = 0, |
1154 | .max_rate = 432000000, | ||
910 | }; | 1155 | }; |
911 | 1156 | ||
912 | static struct clk tegra_pll_p_out4 = { | 1157 | static struct clk tegra_pll_p_out4 = { |
@@ -916,6 +1161,7 @@ static struct clk tegra_pll_p_out4 = { | |||
916 | .parent = &tegra_pll_p, | 1161 | .parent = &tegra_pll_p, |
917 | .reg = 0xa8, | 1162 | .reg = 0xa8, |
918 | .reg_shift = 16, | 1163 | .reg_shift = 16, |
1164 | .max_rate = 432000000, | ||
919 | }; | 1165 | }; |
920 | 1166 | ||
921 | static struct clk_pll_table tegra_pll_a_table[] = { | 1167 | static struct clk_pll_table tegra_pll_a_table[] = { |
@@ -923,6 +1169,7 @@ static struct clk_pll_table tegra_pll_a_table[] = { | |||
923 | { 28800000, 73728000, 64, 25, 1, 1}, | 1169 | { 28800000, 73728000, 64, 25, 1, 1}, |
924 | { 28800000, 11289600, 49, 25, 1, 1}, | 1170 | { 28800000, 11289600, 49, 25, 1, 1}, |
925 | { 28800000, 12288000, 64, 25, 1, 1}, | 1171 | { 28800000, 12288000, 64, 25, 1, 1}, |
1172 | { 28800000, 24000000, 5, 6, 1, 1}, | ||
926 | { 0, 0, 0, 0, 0, 0 }, | 1173 | { 0, 0, 0, 0, 0, 0 }, |
927 | }; | 1174 | }; |
928 | 1175 | ||
@@ -939,6 +1186,7 @@ static struct clk tegra_pll_a = { | |||
939 | .vco_min = 20000000, | 1186 | .vco_min = 20000000, |
940 | .vco_max = 1400000000, | 1187 | .vco_max = 1400000000, |
941 | .pll_table = tegra_pll_a_table, | 1188 | .pll_table = tegra_pll_a_table, |
1189 | .max_rate = 56448000, | ||
942 | }; | 1190 | }; |
943 | 1191 | ||
944 | static struct clk tegra_pll_a_out0 = { | 1192 | static struct clk tegra_pll_a_out0 = { |
@@ -948,6 +1196,7 @@ static struct clk tegra_pll_a_out0 = { | |||
948 | .parent = &tegra_pll_a, | 1196 | .parent = &tegra_pll_a, |
949 | .reg = 0xb4, | 1197 | .reg = 0xb4, |
950 | .reg_shift = 0, | 1198 | .reg_shift = 0, |
1199 | .max_rate = 56448000, | ||
951 | }; | 1200 | }; |
952 | 1201 | ||
953 | static struct clk_pll_table tegra_pll_d_table[] = { | 1202 | static struct clk_pll_table tegra_pll_d_table[] = { |
@@ -971,6 +1220,7 @@ static struct clk tegra_pll_d = { | |||
971 | .vco_min = 40000000, | 1220 | .vco_min = 40000000, |
972 | .vco_max = 1000000000, | 1221 | .vco_max = 1000000000, |
973 | .pll_table = tegra_pll_d_table, | 1222 | .pll_table = tegra_pll_d_table, |
1223 | .max_rate = 1000000000, | ||
974 | }; | 1224 | }; |
975 | 1225 | ||
976 | static struct clk tegra_pll_d_out0 = { | 1226 | static struct clk tegra_pll_d_out0 = { |
@@ -978,19 +1228,20 @@ static struct clk tegra_pll_d_out0 = { | |||
978 | .ops = &tegra_pll_div_ops, | 1228 | .ops = &tegra_pll_div_ops, |
979 | .flags = DIV_2 | PLLD, | 1229 | .flags = DIV_2 | PLLD, |
980 | .parent = &tegra_pll_d, | 1230 | .parent = &tegra_pll_d, |
1231 | .max_rate = 500000000, | ||
981 | }; | 1232 | }; |
982 | 1233 | ||
983 | static struct clk_pll_table tegra_pll_u_table[] = { | 1234 | static struct clk_pll_table tegra_pll_u_table[] = { |
984 | { 12000000, 480000000, 960, 12, 1, 0}, | 1235 | { 12000000, 480000000, 960, 12, 2, 0}, |
985 | { 13000000, 480000000, 960, 13, 1, 0}, | 1236 | { 13000000, 480000000, 960, 13, 2, 0}, |
986 | { 19200000, 480000000, 200, 4, 1, 0}, | 1237 | { 19200000, 480000000, 200, 4, 2, 0}, |
987 | { 26000000, 480000000, 960, 26, 1, 0}, | 1238 | { 26000000, 480000000, 960, 26, 2, 0}, |
988 | { 0, 0, 0, 0, 0, 0 }, | 1239 | { 0, 0, 0, 0, 0, 0 }, |
989 | }; | 1240 | }; |
990 | 1241 | ||
991 | static struct clk tegra_pll_u = { | 1242 | static struct clk tegra_pll_u = { |
992 | .name = "pll_u", | 1243 | .name = "pll_u", |
993 | .flags = 0, | 1244 | .flags = PLLU, |
994 | .ops = &tegra_pll_ops, | 1245 | .ops = &tegra_pll_ops, |
995 | .reg = 0xc0, | 1246 | .reg = 0xc0, |
996 | .input_min = 2000000, | 1247 | .input_min = 2000000, |
@@ -1001,24 +1252,59 @@ static struct clk tegra_pll_u = { | |||
1001 | .vco_min = 480000000, | 1252 | .vco_min = 480000000, |
1002 | .vco_max = 960000000, | 1253 | .vco_max = 960000000, |
1003 | .pll_table = tegra_pll_u_table, | 1254 | .pll_table = tegra_pll_u_table, |
1255 | .max_rate = 480000000, | ||
1004 | }; | 1256 | }; |
1005 | 1257 | ||
1006 | static struct clk_pll_table tegra_pll_x_table[] = { | 1258 | static struct clk_pll_table tegra_pll_x_table[] = { |
1259 | /* 1 GHz */ | ||
1007 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 1260 | { 12000000, 1000000000, 1000, 12, 1, 12}, |
1008 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 1261 | { 13000000, 1000000000, 1000, 13, 1, 12}, |
1009 | { 19200000, 1000000000, 625, 12, 1, 8}, | 1262 | { 19200000, 1000000000, 625, 12, 1, 8}, |
1010 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 1263 | { 26000000, 1000000000, 1000, 26, 1, 12}, |
1011 | { 12000000, 750000000, 750, 12, 1, 12}, | 1264 | |
1012 | { 13000000, 750000000, 750, 13, 1, 12}, | 1265 | /* 912 MHz */ |
1013 | { 19200000, 750000000, 625, 16, 1, 8}, | 1266 | { 12000000, 912000000, 912, 12, 1, 12}, |
1014 | { 26000000, 750000000, 750, 26, 1, 12}, | 1267 | { 13000000, 912000000, 912, 13, 1, 12}, |
1268 | { 19200000, 912000000, 760, 16, 1, 8}, | ||
1269 | { 26000000, 912000000, 912, 26, 1, 12}, | ||
1270 | |||
1271 | /* 816 MHz */ | ||
1272 | { 12000000, 816000000, 816, 12, 1, 12}, | ||
1273 | { 13000000, 816000000, 816, 13, 1, 12}, | ||
1274 | { 19200000, 816000000, 680, 16, 1, 8}, | ||
1275 | { 26000000, 816000000, 816, 26, 1, 12}, | ||
1276 | |||
1277 | /* 760 MHz */ | ||
1278 | { 12000000, 760000000, 760, 12, 1, 12}, | ||
1279 | { 13000000, 760000000, 760, 13, 1, 12}, | ||
1280 | { 19200000, 760000000, 950, 24, 1, 8}, | ||
1281 | { 26000000, 760000000, 760, 26, 1, 12}, | ||
1282 | |||
1283 | /* 608 MHz */ | ||
1284 | { 12000000, 608000000, 760, 12, 1, 12}, | ||
1285 | { 13000000, 608000000, 760, 13, 1, 12}, | ||
1286 | { 19200000, 608000000, 380, 12, 1, 8}, | ||
1287 | { 26000000, 608000000, 760, 26, 1, 12}, | ||
1288 | |||
1289 | /* 456 MHz */ | ||
1290 | { 12000000, 456000000, 456, 12, 1, 12}, | ||
1291 | { 13000000, 456000000, 456, 13, 1, 12}, | ||
1292 | { 19200000, 456000000, 380, 16, 1, 8}, | ||
1293 | { 26000000, 456000000, 456, 26, 1, 12}, | ||
1294 | |||
1295 | /* 312 MHz */ | ||
1296 | { 12000000, 312000000, 312, 12, 1, 12}, | ||
1297 | { 13000000, 312000000, 312, 13, 1, 12}, | ||
1298 | { 19200000, 312000000, 260, 16, 1, 8}, | ||
1299 | { 26000000, 312000000, 312, 26, 1, 12}, | ||
1300 | |||
1015 | { 0, 0, 0, 0, 0, 0 }, | 1301 | { 0, 0, 0, 0, 0, 0 }, |
1016 | }; | 1302 | }; |
1017 | 1303 | ||
1018 | static struct clk tegra_pll_x = { | 1304 | static struct clk tegra_pll_x = { |
1019 | .name = "pll_x", | 1305 | .name = "pll_x", |
1020 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, | 1306 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, |
1021 | .ops = &tegra_pll_ops, | 1307 | .ops = &tegra_pllx_ops, |
1022 | .reg = 0xe0, | 1308 | .reg = 0xe0, |
1023 | .input_min = 2000000, | 1309 | .input_min = 2000000, |
1024 | .input_max = 31000000, | 1310 | .input_max = 31000000, |
@@ -1028,6 +1314,7 @@ static struct clk tegra_pll_x = { | |||
1028 | .vco_min = 20000000, | 1314 | .vco_min = 20000000, |
1029 | .vco_max = 1200000000, | 1315 | .vco_max = 1200000000, |
1030 | .pll_table = tegra_pll_x_table, | 1316 | .pll_table = tegra_pll_x_table, |
1317 | .max_rate = 1000000000, | ||
1031 | }; | 1318 | }; |
1032 | 1319 | ||
1033 | static struct clk tegra_clk_d = { | 1320 | static struct clk tegra_clk_d = { |
@@ -1038,19 +1325,77 @@ static struct clk tegra_clk_d = { | |||
1038 | .reg = 0x34, | 1325 | .reg = 0x34, |
1039 | .reg_shift = 12, | 1326 | .reg_shift = 12, |
1040 | .parent = &tegra_clk_m, | 1327 | .parent = &tegra_clk_m, |
1328 | .max_rate = 52000000, | ||
1329 | }; | ||
1330 | |||
1331 | /* initialized before peripheral clocks */ | ||
1332 | static struct clk_mux_sel mux_audio_sync_clk[8+1]; | ||
1333 | static const struct audio_sources { | ||
1334 | const char *name; | ||
1335 | int value; | ||
1336 | } mux_audio_sync_clk_sources[] = { | ||
1337 | { .name = "spdif_in", .value = 0 }, | ||
1338 | { .name = "i2s1", .value = 1 }, | ||
1339 | { .name = "i2s2", .value = 2 }, | ||
1340 | { .name = "pll_a_out0", .value = 4 }, | ||
1341 | #if 0 /* FIXME: not implemented */ | ||
1342 | { .name = "ac97", .value = 3 }, | ||
1343 | { .name = "ext_audio_clk2", .value = 5 }, | ||
1344 | { .name = "ext_audio_clk1", .value = 6 }, | ||
1345 | { .name = "ext_vimclk", .value = 7 }, | ||
1346 | #endif | ||
1347 | { 0, 0 } | ||
1348 | }; | ||
1349 | |||
1350 | static struct clk tegra_clk_audio = { | ||
1351 | .name = "audio", | ||
1352 | .inputs = mux_audio_sync_clk, | ||
1353 | .reg = 0x38, | ||
1354 | .max_rate = 24000000, | ||
1355 | .ops = &tegra_audio_sync_clk_ops | ||
1041 | }; | 1356 | }; |
1042 | 1357 | ||
1043 | /* FIXME: need tegra_audio | ||
1044 | static struct clk tegra_clk_audio_2x = { | 1358 | static struct clk tegra_clk_audio_2x = { |
1045 | .name = "clk_d", | 1359 | .name = "audio_2x", |
1046 | .flags = PERIPH_NO_RESET, | 1360 | .flags = PERIPH_NO_RESET, |
1361 | .max_rate = 48000000, | ||
1047 | .ops = &tegra_clk_double_ops, | 1362 | .ops = &tegra_clk_double_ops, |
1048 | .clk_num = 89, | 1363 | .clk_num = 89, |
1049 | .reg = 0x34, | 1364 | .reg = 0x34, |
1050 | .reg_shift = 8, | 1365 | .reg_shift = 8, |
1051 | .parent = &tegra_audio, | 1366 | .parent = &tegra_clk_audio, |
1367 | }; | ||
1368 | |||
1369 | struct clk_lookup tegra_audio_clk_lookups[] = { | ||
1370 | { .con_id = "audio", .clk = &tegra_clk_audio }, | ||
1371 | { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x } | ||
1372 | }; | ||
1373 | |||
1374 | /* This is called after peripheral clocks are initialized, as the | ||
1375 | * audio_sync clock depends on some of the peripheral clocks. | ||
1376 | */ | ||
1377 | |||
1378 | static void init_audio_sync_clock_mux(void) | ||
1379 | { | ||
1380 | int i; | ||
1381 | struct clk_mux_sel *sel = mux_audio_sync_clk; | ||
1382 | const struct audio_sources *src = mux_audio_sync_clk_sources; | ||
1383 | struct clk_lookup *lookup; | ||
1384 | |||
1385 | for (i = 0; src->name; i++, sel++, src++) { | ||
1386 | sel->input = tegra_get_clock_by_name(src->name); | ||
1387 | if (!sel->input) | ||
1388 | pr_err("%s: could not find clk %s\n", __func__, | ||
1389 | src->name); | ||
1390 | sel->value = src->value; | ||
1391 | } | ||
1392 | |||
1393 | lookup = tegra_audio_clk_lookups; | ||
1394 | for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) { | ||
1395 | clk_init(lookup->clk); | ||
1396 | clkdev_add(lookup); | ||
1397 | } | ||
1052 | } | 1398 | } |
1053 | */ | ||
1054 | 1399 | ||
1055 | static struct clk_mux_sel mux_cclk[] = { | 1400 | static struct clk_mux_sel mux_cclk[] = { |
1056 | { .input = &tegra_clk_m, .value = 0}, | 1401 | { .input = &tegra_clk_m, .value = 0}, |
@@ -1077,27 +1422,40 @@ static struct clk_mux_sel mux_sclk[] = { | |||
1077 | { 0, 0}, | 1422 | { 0, 0}, |
1078 | }; | 1423 | }; |
1079 | 1424 | ||
1080 | static struct clk tegra_clk_cpu = { | 1425 | static struct clk tegra_clk_cclk = { |
1081 | .name = "cpu", | 1426 | .name = "cclk", |
1082 | .inputs = mux_cclk, | 1427 | .inputs = mux_cclk, |
1083 | .reg = 0x20, | 1428 | .reg = 0x20, |
1084 | .ops = &tegra_super_ops, | 1429 | .ops = &tegra_super_ops, |
1430 | .max_rate = 1000000000, | ||
1085 | }; | 1431 | }; |
1086 | 1432 | ||
1087 | static struct clk tegra_clk_sys = { | 1433 | static struct clk tegra_clk_sclk = { |
1088 | .name = "sys", | 1434 | .name = "sclk", |
1089 | .inputs = mux_sclk, | 1435 | .inputs = mux_sclk, |
1090 | .reg = 0x28, | 1436 | .reg = 0x28, |
1091 | .ops = &tegra_super_ops, | 1437 | .ops = &tegra_super_ops, |
1438 | .max_rate = 600000000, | ||
1439 | }; | ||
1440 | |||
1441 | static struct clk tegra_clk_virtual_cpu = { | ||
1442 | .name = "cpu", | ||
1443 | .parent = &tegra_clk_cclk, | ||
1444 | .main = &tegra_pll_x, | ||
1445 | .backup = &tegra_clk_m, | ||
1446 | .ops = &tegra_cpu_ops, | ||
1447 | .max_rate = 1000000000, | ||
1448 | .dvfs = &tegra_dvfs_virtual_cpu_dvfs, | ||
1092 | }; | 1449 | }; |
1093 | 1450 | ||
1094 | static struct clk tegra_clk_hclk = { | 1451 | static struct clk tegra_clk_hclk = { |
1095 | .name = "hclk", | 1452 | .name = "hclk", |
1096 | .flags = DIV_BUS, | 1453 | .flags = DIV_BUS, |
1097 | .parent = &tegra_clk_sys, | 1454 | .parent = &tegra_clk_sclk, |
1098 | .reg = 0x30, | 1455 | .reg = 0x30, |
1099 | .reg_shift = 4, | 1456 | .reg_shift = 4, |
1100 | .ops = &tegra_bus_ops, | 1457 | .ops = &tegra_bus_ops, |
1458 | .max_rate = 240000000, | ||
1101 | }; | 1459 | }; |
1102 | 1460 | ||
1103 | static struct clk tegra_clk_pclk = { | 1461 | static struct clk tegra_clk_pclk = { |
@@ -1107,6 +1465,7 @@ static struct clk tegra_clk_pclk = { | |||
1107 | .reg = 0x30, | 1465 | .reg = 0x30, |
1108 | .reg_shift = 0, | 1466 | .reg_shift = 0, |
1109 | .ops = &tegra_bus_ops, | 1467 | .ops = &tegra_bus_ops, |
1468 | .max_rate = 108000000, | ||
1110 | }; | 1469 | }; |
1111 | 1470 | ||
1112 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { | 1471 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { |
@@ -1133,10 +1492,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = { | |||
1133 | { 0, 0}, | 1492 | { 0, 0}, |
1134 | }; | 1493 | }; |
1135 | 1494 | ||
1136 | static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = { | 1495 | static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = { |
1137 | {.input = &tegra_pll_a, .value = 0}, | 1496 | {.input = &tegra_pll_a_out0, .value = 0}, |
1138 | /* FIXME: no mux defined for tegra_audio | 1497 | {.input = &tegra_clk_audio_2x, .value = 1}, |
1139 | {.input = &tegra_audio, .value = 1},*/ | ||
1140 | {.input = &tegra_pll_p, .value = 2}, | 1498 | {.input = &tegra_pll_p, .value = 2}, |
1141 | {.input = &tegra_clk_m, .value = 3}, | 1499 | {.input = &tegra_clk_m, .value = 3}, |
1142 | { 0, 0}, | 1500 | { 0, 0}, |
@@ -1153,8 +1511,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = { | |||
1153 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { | 1511 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { |
1154 | {.input = &tegra_pll_p, .value = 0}, | 1512 | {.input = &tegra_pll_p, .value = 0}, |
1155 | {.input = &tegra_pll_c, .value = 1}, | 1513 | {.input = &tegra_pll_c, .value = 1}, |
1156 | /* FIXME: no mux defined for tegra_audio | 1514 | {.input = &tegra_clk_audio, .value = 2}, |
1157 | {.input = &tegra_audio, .value = 2},*/ | ||
1158 | {.input = &tegra_clk_m, .value = 3}, | 1515 | {.input = &tegra_clk_m, .value = 3}, |
1159 | {.input = &tegra_clk_32k, .value = 4}, | 1516 | {.input = &tegra_clk_32k, .value = 4}, |
1160 | { 0, 0}, | 1517 | { 0, 0}, |
@@ -1187,7 +1544,7 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1187 | { 0, 0}, | 1544 | { 0, 0}, |
1188 | }; | 1545 | }; |
1189 | 1546 | ||
1190 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \ | 1547 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ |
1191 | { \ | 1548 | { \ |
1192 | .name = _name, \ | 1549 | .name = _name, \ |
1193 | .lookup = { \ | 1550 | .lookup = { \ |
@@ -1199,72 +1556,76 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1199 | .reg = _reg, \ | 1556 | .reg = _reg, \ |
1200 | .inputs = _inputs, \ | 1557 | .inputs = _inputs, \ |
1201 | .flags = _flags, \ | 1558 | .flags = _flags, \ |
1559 | .max_rate = _max, \ | ||
1202 | } | 1560 | } |
1203 | 1561 | ||
1204 | struct clk tegra_periph_clks[] = { | 1562 | struct clk tegra_periph_clks[] = { |
1205 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, mux_clk_32k, PERIPH_NO_RESET), | 1563 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET), |
1206 | PERIPH_CLK("timer", "timer", NULL, 5, 0, mux_clk_m, 0), | 1564 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), |
1207 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1565 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1208 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1566 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1209 | /* FIXME: spdif has 2 clocks but 1 enable */ | 1567 | /* FIXME: spdif has 2 clocks but 1 enable */ |
1210 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, mux_plla_audio_pllp_clkm, MUX | DIV_U71), | 1568 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1211 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, mux_pllp_pllc_pllm, MUX | DIV_U71), | 1569 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), |
1212 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), | 1570 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), |
1213 | PERIPH_CLK("spi", "spi", NULL, 43, 0x114, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1571 | PERIPH_CLK("spi", "spi", NULL, 43, 0x114, 40000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1214 | PERIPH_CLK("xio", "xio", NULL, 45, 0x120, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1572 | PERIPH_CLK("xio", "xio", NULL, 45, 0x120, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1215 | PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1573 | PERIPH_CLK("twc", "twc", NULL, 16, 0x12c, 150000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1216 | PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1574 | PERIPH_CLK("sbc1", "spi_tegra.0", NULL, 41, 0x134, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1217 | PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1575 | PERIPH_CLK("sbc2", "spi_tegra.1", NULL, 44, 0x118, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1218 | PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1576 | PERIPH_CLK("sbc3", "spi_tegra.2", NULL, 46, 0x11c, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1219 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1577 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1220 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1578 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
1221 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1579 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1222 | /* FIXME: vfir shares an enable with uartb */ | 1580 | /* FIXME: vfir shares an enable with uartb */ |
1223 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1581 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1224 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1582 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1225 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1583 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1226 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1584 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1227 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1585 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1228 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1586 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, 250000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1229 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1587 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ |
1230 | /* FIXME: what is la? */ | 1588 | /* FIXME: what is la? */ |
1231 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1589 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1232 | PERIPH_CLK("owr", "owr", NULL, 71, 0x1cc, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1590 | PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1233 | PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1591 | PERIPH_CLK("nor", "nor", NULL, 42, 0x1d0, 92000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
1234 | PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1592 | PERIPH_CLK("mipi", "mipi", NULL, 50, 0x174, 60000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1235 | PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1593 | PERIPH_CLK("i2c1", "tegra-i2c.0", NULL, 12, 0x124, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1236 | PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1594 | PERIPH_CLK("i2c2", "tegra-i2c.1", NULL, 54, 0x198, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1237 | PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1595 | PERIPH_CLK("i2c3", "tegra-i2c.2", NULL, 67, 0x1b8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1238 | PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1596 | PERIPH_CLK("dvc", "tegra-i2c.3", NULL, 47, 0x128, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16), |
1239 | PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, mux_pllp_out3, 0), | 1597 | PERIPH_CLK("i2c1_i2c", "tegra-i2c.0", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1240 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, mux_pllp_out3, 0), | 1598 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1241 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, mux_pllp_out3, 0), | 1599 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1242 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, mux_pllp_out3, 0), | 1600 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1243 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1601 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1244 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1602 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1245 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1603 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1246 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1604 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1247 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1605 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 216000000, mux_pllp_pllc_pllm_clkm, MUX), |
1248 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), | 1606 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ |
1249 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1607 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1250 | /* FIXME: vi and vi_sensor share an enable */ | 1608 | /* FIXME: vi and vi_sensor share an enable */ |
1251 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1609 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1252 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1610 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ |
1253 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1611 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1254 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1612 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1255 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1613 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1256 | /* FIXME: cve and tvo share an enable */ | 1614 | /* FIXME: cve and tvo share an enable */ |
1257 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1615 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1258 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1616 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1259 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1617 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 148500000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1260 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1618 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1261 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1619 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1262 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1620 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1263 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, mux_clk_m, 0), | 1621 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1264 | PERIPH_CLK("usb2", "usb.1", NULL, 58, 0, mux_clk_m, 0), | 1622 | PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1265 | PERIPH_CLK("usb3", "usb.2", NULL, 59, 0, mux_clk_m, 0), | 1623 | PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1266 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), | 1624 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, 800000000, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), |
1267 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, mux_plld, 0), | 1625 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ |
1626 | PERIPH_CLK("csi", "csi", NULL, 52, 0, 72000000, mux_pllp_out3, 0), | ||
1627 | PERIPH_CLK("isp", "isp", NULL, 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ | ||
1628 | PERIPH_CLK("csus", "csus", NULL, 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), | ||
1268 | }; | 1629 | }; |
1269 | 1630 | ||
1270 | #define CLK_DUPLICATE(_name, _dev, _con) \ | 1631 | #define CLK_DUPLICATE(_name, _dev, _con) \ |
@@ -1286,6 +1647,9 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
1286 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), | 1647 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), |
1287 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), | 1648 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), |
1288 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), | 1649 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), |
1650 | CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"), | ||
1651 | CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"), | ||
1652 | CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), | ||
1289 | }; | 1653 | }; |
1290 | 1654 | ||
1291 | #define CLK(dev, con, ck) \ | 1655 | #define CLK(dev, con, ck) \ |
@@ -1315,11 +1679,12 @@ struct clk_lookup tegra_clk_lookups[] = { | |||
1315 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), | 1679 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), |
1316 | CLK(NULL, "pll_u", &tegra_pll_u), | 1680 | CLK(NULL, "pll_u", &tegra_pll_u), |
1317 | CLK(NULL, "pll_x", &tegra_pll_x), | 1681 | CLK(NULL, "pll_x", &tegra_pll_x), |
1318 | CLK(NULL, "cpu", &tegra_clk_cpu), | 1682 | CLK(NULL, "cclk", &tegra_clk_cclk), |
1319 | CLK(NULL, "sys", &tegra_clk_sys), | 1683 | CLK(NULL, "sclk", &tegra_clk_sclk), |
1320 | CLK(NULL, "hclk", &tegra_clk_hclk), | 1684 | CLK(NULL, "hclk", &tegra_clk_hclk), |
1321 | CLK(NULL, "pclk", &tegra_clk_pclk), | 1685 | CLK(NULL, "pclk", &tegra_clk_pclk), |
1322 | CLK(NULL, "clk_d", &tegra_clk_d), | 1686 | CLK(NULL, "clk_d", &tegra_clk_d), |
1687 | CLK(NULL, "cpu", &tegra_clk_virtual_cpu), | ||
1323 | }; | 1688 | }; |
1324 | 1689 | ||
1325 | void __init tegra2_init_clocks(void) | 1690 | void __init tegra2_init_clocks(void) |
@@ -1356,4 +1721,75 @@ void __init tegra2_init_clocks(void) | |||
1356 | cd->name); | 1721 | cd->name); |
1357 | } | 1722 | } |
1358 | } | 1723 | } |
1724 | |||
1725 | init_audio_sync_clock_mux(); | ||
1726 | } | ||
1727 | |||
1728 | #ifdef CONFIG_PM | ||
1729 | static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + | ||
1730 | PERIPH_CLK_SOURCE_NUM + 3]; | ||
1731 | |||
1732 | void tegra_clk_suspend(void) | ||
1733 | { | ||
1734 | unsigned long off, i; | ||
1735 | u32 *ctx = clk_rst_suspend; | ||
1736 | |||
1737 | *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; | ||
1738 | |||
1739 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1740 | off += 4) { | ||
1741 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1742 | continue; | ||
1743 | *ctx++ = clk_readl(off); | ||
1744 | } | ||
1745 | |||
1746 | off = RST_DEVICES; | ||
1747 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1748 | *ctx++ = clk_readl(off); | ||
1749 | |||
1750 | off = CLK_OUT_ENB; | ||
1751 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1752 | *ctx++ = clk_readl(off); | ||
1753 | |||
1754 | *ctx++ = clk_readl(MISC_CLK_ENB); | ||
1755 | *ctx++ = clk_readl(CLK_MASK_ARM); | ||
1756 | } | ||
1757 | |||
1758 | void tegra_clk_resume(void) | ||
1759 | { | ||
1760 | unsigned long off, i; | ||
1761 | const u32 *ctx = clk_rst_suspend; | ||
1762 | u32 val; | ||
1763 | |||
1764 | val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK; | ||
1765 | val |= *ctx++; | ||
1766 | clk_writel(val, OSC_CTRL); | ||
1767 | |||
1768 | /* enable all clocks before configuring clock sources */ | ||
1769 | clk_writel(0xbffffff9ul, CLK_OUT_ENB); | ||
1770 | clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); | ||
1771 | clk_writel(0x77f01bfful, CLK_OUT_ENB + 8); | ||
1772 | wmb(); | ||
1773 | |||
1774 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1775 | off += 4) { | ||
1776 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1777 | continue; | ||
1778 | clk_writel(*ctx++, off); | ||
1779 | } | ||
1780 | wmb(); | ||
1781 | |||
1782 | off = RST_DEVICES; | ||
1783 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1784 | clk_writel(*ctx++, off); | ||
1785 | wmb(); | ||
1786 | |||
1787 | off = CLK_OUT_ENB; | ||
1788 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1789 | clk_writel(*ctx++, off); | ||
1790 | wmb(); | ||
1791 | |||
1792 | clk_writel(*ctx++, MISC_CLK_ENB); | ||
1793 | clk_writel(*ctx++, CLK_MASK_ARM); | ||
1359 | } | 1794 | } |
1795 | #endif | ||
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c new file mode 100644 index 000000000000..5529c238dd77 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_dvfs.c | |||
@@ -0,0 +1,86 @@ | |||
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 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #include "clock.h" | ||
23 | #include "tegra2_dvfs.h" | ||
24 | |||
25 | static struct dvfs_table virtual_cpu_process_0[] = { | ||
26 | {314000000, 750}, | ||
27 | {456000000, 825}, | ||
28 | {608000000, 900}, | ||
29 | {760000000, 975}, | ||
30 | {817000000, 1000}, | ||
31 | {912000000, 1050}, | ||
32 | {1000000000, 1100}, | ||
33 | {0, 0}, | ||
34 | }; | ||
35 | |||
36 | static struct dvfs_table virtual_cpu_process_1[] = { | ||
37 | {314000000, 750}, | ||
38 | {456000000, 825}, | ||
39 | {618000000, 900}, | ||
40 | {770000000, 975}, | ||
41 | {827000000, 1000}, | ||
42 | {922000000, 1050}, | ||
43 | {1000000000, 1100}, | ||
44 | {0, 0}, | ||
45 | }; | ||
46 | |||
47 | static struct dvfs_table virtual_cpu_process_2[] = { | ||
48 | {494000000, 750}, | ||
49 | {675000000, 825}, | ||
50 | {817000000, 875}, | ||
51 | {922000000, 925}, | ||
52 | {1000000000, 975}, | ||
53 | {0, 0}, | ||
54 | }; | ||
55 | |||
56 | static struct dvfs_table virtual_cpu_process_3[] = { | ||
57 | {730000000, 750}, | ||
58 | {760000000, 775}, | ||
59 | {845000000, 800}, | ||
60 | {1000000000, 875}, | ||
61 | {0, 0}, | ||
62 | }; | ||
63 | |||
64 | struct dvfs tegra_dvfs_virtual_cpu_dvfs = { | ||
65 | .reg_id = "vdd_cpu", | ||
66 | .process_id_table = { | ||
67 | { | ||
68 | .process_id = 0, | ||
69 | .table = virtual_cpu_process_0, | ||
70 | }, | ||
71 | { | ||
72 | .process_id = 1, | ||
73 | .table = virtual_cpu_process_1, | ||
74 | }, | ||
75 | { | ||
76 | .process_id = 2, | ||
77 | .table = virtual_cpu_process_2, | ||
78 | }, | ||
79 | { | ||
80 | .process_id = 3, | ||
81 | .table = virtual_cpu_process_3, | ||
82 | }, | ||
83 | }, | ||
84 | .process_id_table_length = 4, | ||
85 | .cpu = 1, | ||
86 | }; | ||
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h new file mode 100644 index 000000000000..f8c1adba96a6 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_dvfs.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/tegra2_dvfs.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | extern struct dvfs tegra_dvfs_virtual_cpu_dvfs; | ||