diff options
Diffstat (limited to 'arch/arm/mach-tegra/tegra2_clocks.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 826 |
1 files changed, 655 insertions, 171 deletions
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 426163231fff..ae3b308e22a4 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,10 +104,14 @@ | |||
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 |
94 | 112 | ||
113 | #define PLLE_MISC_READY (1 << 15) | ||
114 | |||
95 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) | 115 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) |
96 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) | 116 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) |
97 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) | 117 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) |
@@ -143,30 +163,37 @@ unsigned long clk_measure_input_freq(void) | |||
143 | } | 163 | } |
144 | } | 164 | } |
145 | 165 | ||
146 | static int clk_div71_get_divider(struct clk *c, unsigned long rate) | 166 | static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate) |
147 | { | 167 | { |
148 | unsigned long divider_u71; | 168 | s64 divider_u71 = parent_rate * 2; |
169 | divider_u71 += rate - 1; | ||
170 | do_div(divider_u71, rate); | ||
149 | 171 | ||
150 | divider_u71 = DIV_ROUND_UP(c->rate * 2, rate); | 172 | if (divider_u71 - 2 < 0) |
173 | return 0; | ||
151 | 174 | ||
152 | if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0) | 175 | if (divider_u71 - 2 > 255) |
153 | return -EINVAL; | 176 | return -EINVAL; |
154 | 177 | ||
155 | return divider_u71 - 2; | 178 | return divider_u71 - 2; |
156 | } | 179 | } |
157 | 180 | ||
158 | static unsigned long tegra2_clk_recalculate_rate(struct clk *c) | 181 | static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) |
159 | { | 182 | { |
160 | unsigned long rate; | 183 | s64 divider_u16; |
161 | rate = c->parent->rate; | ||
162 | 184 | ||
163 | if (c->mul != 0 && c->div != 0) | 185 | divider_u16 = parent_rate; |
164 | c->rate = rate * c->mul / c->div; | 186 | divider_u16 += rate - 1; |
165 | else | 187 | do_div(divider_u16, rate); |
166 | c->rate = rate; | 188 | |
167 | return c->rate; | 189 | if (divider_u16 - 1 < 0) |
168 | } | 190 | return 0; |
169 | 191 | ||
192 | if (divider_u16 - 1 > 255) | ||
193 | return -EINVAL; | ||
194 | |||
195 | return divider_u16 - 1; | ||
196 | } | ||
170 | 197 | ||
171 | /* clk_m functions */ | 198 | /* clk_m functions */ |
172 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | 199 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) |
@@ -244,7 +271,6 @@ static void tegra2_super_clk_init(struct clk *c) | |||
244 | } | 271 | } |
245 | BUG_ON(sel->input == NULL); | 272 | BUG_ON(sel->input == NULL); |
246 | c->parent = sel->input; | 273 | c->parent = sel->input; |
247 | tegra2_clk_recalculate_rate(c); | ||
248 | } | 274 | } |
249 | 275 | ||
250 | static int tegra2_super_clk_enable(struct clk *c) | 276 | static int tegra2_super_clk_enable(struct clk *c) |
@@ -266,6 +292,7 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
266 | u32 val; | 292 | u32 val; |
267 | const struct clk_mux_sel *sel; | 293 | const struct clk_mux_sel *sel; |
268 | int shift; | 294 | int shift; |
295 | |||
269 | val = clk_readl(c->reg + SUPER_CLK_MUX);; | 296 | val = clk_readl(c->reg + SUPER_CLK_MUX);; |
270 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | 297 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && |
271 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | 298 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); |
@@ -273,11 +300,18 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
273 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | 300 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; |
274 | for (sel = c->inputs; sel->input != NULL; sel++) { | 301 | for (sel = c->inputs; sel->input != NULL; sel++) { |
275 | if (sel->input == p) { | 302 | if (sel->input == p) { |
276 | clk_reparent(c, p); | ||
277 | val &= ~(SUPER_SOURCE_MASK << shift); | 303 | val &= ~(SUPER_SOURCE_MASK << shift); |
278 | val |= sel->value << shift; | 304 | val |= sel->value << shift; |
305 | |||
306 | if (c->refcnt) | ||
307 | clk_enable_locked(p); | ||
308 | |||
279 | clk_writel(val, c->reg); | 309 | clk_writel(val, c->reg); |
280 | c->rate = c->parent->rate; | 310 | |
311 | if (c->refcnt && c->parent) | ||
312 | clk_disable_locked(c->parent); | ||
313 | |||
314 | clk_reparent(c, p); | ||
281 | return 0; | 315 | return 0; |
282 | } | 316 | } |
283 | } | 317 | } |
@@ -289,7 +323,61 @@ static struct clk_ops tegra_super_ops = { | |||
289 | .enable = tegra2_super_clk_enable, | 323 | .enable = tegra2_super_clk_enable, |
290 | .disable = tegra2_super_clk_disable, | 324 | .disable = tegra2_super_clk_disable, |
291 | .set_parent = tegra2_super_clk_set_parent, | 325 | .set_parent = tegra2_super_clk_set_parent, |
292 | .recalculate_rate = tegra2_clk_recalculate_rate, | 326 | }; |
327 | |||
328 | /* virtual cpu clock functions */ | ||
329 | /* some clocks can not be stopped (cpu, memory bus) while the SoC is running. | ||
330 | To change the frequency of these clocks, the parent pll may need to be | ||
331 | reprogrammed, so the clock must be moved off the pll, the pll reprogrammed, | ||
332 | and then the clock moved back to the pll. To hide this sequence, a virtual | ||
333 | clock handles it. | ||
334 | */ | ||
335 | static void tegra2_cpu_clk_init(struct clk *c) | ||
336 | { | ||
337 | } | ||
338 | |||
339 | static int tegra2_cpu_clk_enable(struct clk *c) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static void tegra2_cpu_clk_disable(struct clk *c) | ||
345 | { | ||
346 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
347 | |||
348 | /* oops - don't disable the CPU clock! */ | ||
349 | BUG(); | ||
350 | } | ||
351 | |||
352 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) | ||
353 | { | ||
354 | int ret; | ||
355 | ret = clk_set_parent_locked(c->parent, c->backup); | ||
356 | if (ret) { | ||
357 | pr_err("Failed to switch cpu to clock %s\n", c->backup->name); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | ret = clk_set_rate_locked(c->main, rate); | ||
362 | if (ret) { | ||
363 | pr_err("Failed to change cpu pll to %lu\n", rate); | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | ret = clk_set_parent_locked(c->parent, c->main); | ||
368 | if (ret) { | ||
369 | pr_err("Failed to switch cpu to clock %s\n", c->main->name); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static struct clk_ops tegra_cpu_ops = { | ||
377 | .init = tegra2_cpu_clk_init, | ||
378 | .enable = tegra2_cpu_clk_enable, | ||
379 | .disable = tegra2_cpu_clk_disable, | ||
380 | .set_rate = tegra2_cpu_clk_set_rate, | ||
293 | }; | 381 | }; |
294 | 382 | ||
295 | /* bus clock functions */ | 383 | /* bus clock functions */ |
@@ -299,7 +387,6 @@ static void tegra2_bus_clk_init(struct clk *c) | |||
299 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | 387 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; |
300 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | 388 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; |
301 | c->mul = 1; | 389 | c->mul = 1; |
302 | tegra2_clk_recalculate_rate(c); | ||
303 | } | 390 | } |
304 | 391 | ||
305 | static int tegra2_bus_clk_enable(struct clk *c) | 392 | static int tegra2_bus_clk_enable(struct clk *c) |
@@ -340,27 +427,15 @@ static struct clk_ops tegra_bus_ops = { | |||
340 | .enable = tegra2_bus_clk_enable, | 427 | .enable = tegra2_bus_clk_enable, |
341 | .disable = tegra2_bus_clk_disable, | 428 | .disable = tegra2_bus_clk_disable, |
342 | .set_rate = tegra2_bus_clk_set_rate, | 429 | .set_rate = tegra2_bus_clk_set_rate, |
343 | .recalculate_rate = tegra2_clk_recalculate_rate, | ||
344 | }; | 430 | }; |
345 | 431 | ||
346 | /* PLL Functions */ | 432 | /* 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) | 433 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) |
360 | { | 434 | { |
361 | ktime_t before; | 435 | ktime_t before; |
362 | 436 | ||
363 | before = ktime_get(); | 437 | before = ktime_get(); |
438 | |||
364 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { | 439 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { |
365 | if (ktime_us_delta(ktime_get(), before) > 5000) { | 440 | if (ktime_us_delta(ktime_get(), before) > 5000) { |
366 | pr_err("Timed out waiting for lock bit on pll %s", | 441 | pr_err("Timed out waiting for lock bit on pll %s", |
@@ -380,24 +455,19 @@ static void tegra2_pll_clk_init(struct clk *c) | |||
380 | 455 | ||
381 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { | 456 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { |
382 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); | 457 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); |
383 | c->n = 1; | 458 | c->mul = 1; |
384 | c->m = 0; | 459 | c->div = 1; |
385 | c->p = 1; | ||
386 | } else if (val & PLL_BASE_BYPASS) { | 460 | } else if (val & PLL_BASE_BYPASS) { |
387 | c->n = 1; | 461 | c->mul = 1; |
388 | c->m = 1; | 462 | c->div = 1; |
389 | c->p = 1; | ||
390 | } else { | 463 | } else { |
391 | c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; | 464 | c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT; |
392 | c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; | 465 | c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT; |
393 | c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | 466 | if (c->flags & PLLU) |
467 | c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2; | ||
468 | else | ||
469 | c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | ||
394 | } | 470 | } |
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 | } | 471 | } |
402 | 472 | ||
403 | static int tegra2_pll_clk_enable(struct clk *c) | 473 | static int tegra2_pll_clk_enable(struct clk *c) |
@@ -411,7 +481,7 @@ static int tegra2_pll_clk_enable(struct clk *c) | |||
411 | clk_writel(val, c->reg + PLL_BASE); | 481 | clk_writel(val, c->reg + PLL_BASE); |
412 | 482 | ||
413 | val = clk_readl(c->reg + PLL_MISC(c)); | 483 | val = clk_readl(c->reg + PLL_MISC(c)); |
414 | val |= PLL_MISC_LOCK_ENABLE; | 484 | val |= PLL_MISC_LOCK_ENABLE(c); |
415 | clk_writel(val, c->reg + PLL_MISC(c)); | 485 | clk_writel(val, c->reg + PLL_MISC(c)); |
416 | 486 | ||
417 | tegra2_pll_clk_wait_for_lock(c); | 487 | tegra2_pll_clk_wait_for_lock(c); |
@@ -441,33 +511,36 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | |||
441 | input_rate = c->parent->rate; | 511 | input_rate = c->parent->rate; |
442 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { | 512 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { |
443 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | 513 | if (sel->input_rate == input_rate && sel->output_rate == rate) { |
444 | c->n = sel->n; | 514 | c->mul = sel->n; |
445 | c->m = sel->m; | 515 | c->div = sel->m * sel->p; |
446 | c->p = sel->p; | ||
447 | c->cpcon = sel->cpcon; | ||
448 | 516 | ||
449 | val = clk_readl(c->reg + PLL_BASE); | 517 | val = clk_readl(c->reg + PLL_BASE); |
450 | if (c->flags & PLL_FIXED) | 518 | if (c->flags & PLL_FIXED) |
451 | val |= PLL_BASE_OVERRIDE; | 519 | val |= PLL_BASE_OVERRIDE; |
452 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | | 520 | val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK | |
453 | PLL_BASE_DIVM_MASK); | 521 | PLL_BASE_DIVM_MASK); |
454 | val |= (c->m << PLL_BASE_DIVM_SHIFT) | | 522 | val |= (sel->m << PLL_BASE_DIVM_SHIFT) | |
455 | (c->n << PLL_BASE_DIVN_SHIFT); | 523 | (sel->n << PLL_BASE_DIVN_SHIFT); |
456 | BUG_ON(c->p > 2); | 524 | BUG_ON(sel->p < 1 || sel->p > 2); |
457 | if (c->p == 2) | 525 | if (c->flags & PLLU) { |
458 | val |= 1 << PLL_BASE_DIVP_SHIFT; | 526 | if (sel->p == 1) |
527 | val |= PLLU_BASE_POST_DIV; | ||
528 | } else { | ||
529 | if (sel->p == 2) | ||
530 | val |= 1 << PLL_BASE_DIVP_SHIFT; | ||
531 | } | ||
459 | clk_writel(val, c->reg + PLL_BASE); | 532 | clk_writel(val, c->reg + PLL_BASE); |
460 | 533 | ||
461 | if (c->flags & PLL_HAS_CPCON) { | 534 | if (c->flags & PLL_HAS_CPCON) { |
462 | val = c->cpcon << PLL_MISC_CPCON_SHIFT; | 535 | val = clk_readl(c->reg + PLL_MISC(c)); |
463 | val |= PLL_MISC_LOCK_ENABLE; | 536 | val &= ~PLL_MISC_CPCON_MASK; |
537 | val |= sel->cpcon << PLL_MISC_CPCON_SHIFT; | ||
464 | clk_writel(val, c->reg + PLL_MISC(c)); | 538 | clk_writel(val, c->reg + PLL_MISC(c)); |
465 | } | 539 | } |
466 | 540 | ||
467 | if (c->state == ON) | 541 | if (c->state == ON) |
468 | tegra2_pll_clk_enable(c); | 542 | tegra2_pll_clk_enable(c); |
469 | 543 | ||
470 | c->rate = rate; | ||
471 | return 0; | 544 | return 0; |
472 | } | 545 | } |
473 | } | 546 | } |
@@ -479,7 +552,46 @@ static struct clk_ops tegra_pll_ops = { | |||
479 | .enable = tegra2_pll_clk_enable, | 552 | .enable = tegra2_pll_clk_enable, |
480 | .disable = tegra2_pll_clk_disable, | 553 | .disable = tegra2_pll_clk_disable, |
481 | .set_rate = tegra2_pll_clk_set_rate, | 554 | .set_rate = tegra2_pll_clk_set_rate, |
482 | .recalculate_rate = tegra2_pll_clk_recalculate_rate, | 555 | }; |
556 | |||
557 | static void tegra2_pllx_clk_init(struct clk *c) | ||
558 | { | ||
559 | tegra2_pll_clk_init(c); | ||
560 | |||
561 | if (tegra_sku_id() == 7) | ||
562 | c->max_rate = 750000000; | ||
563 | } | ||
564 | |||
565 | static struct clk_ops tegra_pllx_ops = { | ||
566 | .init = tegra2_pllx_clk_init, | ||
567 | .enable = tegra2_pll_clk_enable, | ||
568 | .disable = tegra2_pll_clk_disable, | ||
569 | .set_rate = tegra2_pll_clk_set_rate, | ||
570 | }; | ||
571 | |||
572 | static int tegra2_plle_clk_enable(struct clk *c) | ||
573 | { | ||
574 | u32 val; | ||
575 | |||
576 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
577 | |||
578 | mdelay(1); | ||
579 | |||
580 | val = clk_readl(c->reg + PLL_BASE); | ||
581 | if (!(val & PLLE_MISC_READY)) | ||
582 | return -EBUSY; | ||
583 | |||
584 | val = clk_readl(c->reg + PLL_BASE); | ||
585 | val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS; | ||
586 | clk_writel(val, c->reg + PLL_BASE); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static struct clk_ops tegra_plle_ops = { | ||
592 | .init = tegra2_pll_clk_init, | ||
593 | .enable = tegra2_plle_clk_enable, | ||
594 | .set_rate = tegra2_pll_clk_set_rate, | ||
483 | }; | 595 | }; |
484 | 596 | ||
485 | /* Clock divider ops */ | 597 | /* Clock divider ops */ |
@@ -503,8 +615,6 @@ static void tegra2_pll_div_clk_init(struct clk *c) | |||
503 | c->div = 1; | 615 | c->div = 1; |
504 | c->mul = 1; | 616 | c->mul = 1; |
505 | } | 617 | } |
506 | |||
507 | tegra2_clk_recalculate_rate(c); | ||
508 | } | 618 | } |
509 | 619 | ||
510 | static int tegra2_pll_div_clk_enable(struct clk *c) | 620 | static int tegra2_pll_div_clk_enable(struct clk *c) |
@@ -565,7 +675,7 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
565 | int divider_u71; | 675 | int divider_u71; |
566 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 676 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
567 | if (c->flags & DIV_U71) { | 677 | if (c->flags & DIV_U71) { |
568 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 678 | divider_u71 = clk_div71_get_divider(c->parent->rate, rate); |
569 | if (divider_u71 >= 0) { | 679 | if (divider_u71 >= 0) { |
570 | val = clk_readl(c->reg); | 680 | val = clk_readl(c->reg); |
571 | new_val = val >> c->reg_shift; | 681 | new_val = val >> c->reg_shift; |
@@ -580,25 +690,37 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
580 | clk_writel(val, c->reg); | 690 | clk_writel(val, c->reg); |
581 | c->div = divider_u71 + 2; | 691 | c->div = divider_u71 + 2; |
582 | c->mul = 2; | 692 | c->mul = 2; |
583 | tegra2_clk_recalculate_rate(c); | ||
584 | return 0; | 693 | return 0; |
585 | } | 694 | } |
586 | } else if (c->flags & DIV_2) { | 695 | } else if (c->flags & DIV_2) { |
587 | if (c->parent->rate == rate * 2) { | 696 | if (c->parent->rate == rate * 2) |
588 | c->rate = rate; | ||
589 | return 0; | 697 | return 0; |
590 | } | ||
591 | } | 698 | } |
592 | return -EINVAL; | 699 | return -EINVAL; |
593 | } | 700 | } |
594 | 701 | ||
702 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | ||
703 | { | ||
704 | int divider; | ||
705 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
706 | |||
707 | if (c->flags & DIV_U71) { | ||
708 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
709 | if (divider < 0) | ||
710 | return divider; | ||
711 | return c->parent->rate * 2 / (divider + 2); | ||
712 | } else if (c->flags & DIV_2) { | ||
713 | return c->parent->rate / 2; | ||
714 | } | ||
715 | return -EINVAL; | ||
716 | } | ||
595 | 717 | ||
596 | static struct clk_ops tegra_pll_div_ops = { | 718 | static struct clk_ops tegra_pll_div_ops = { |
597 | .init = tegra2_pll_div_clk_init, | 719 | .init = tegra2_pll_div_clk_init, |
598 | .enable = tegra2_pll_div_clk_enable, | 720 | .enable = tegra2_pll_div_clk_enable, |
599 | .disable = tegra2_pll_div_clk_disable, | 721 | .disable = tegra2_pll_div_clk_disable, |
600 | .set_rate = tegra2_pll_div_clk_set_rate, | 722 | .set_rate = tegra2_pll_div_clk_set_rate, |
601 | .recalculate_rate = tegra2_clk_recalculate_rate, | 723 | .round_rate = tegra2_pll_div_clk_round_rate, |
602 | }; | 724 | }; |
603 | 725 | ||
604 | /* Periph clk ops */ | 726 | /* Periph clk ops */ |
@@ -621,9 +743,13 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
621 | } | 743 | } |
622 | 744 | ||
623 | if (c->flags & DIV_U71) { | 745 | if (c->flags & DIV_U71) { |
624 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK; | 746 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; |
625 | c->div = divu71 + 2; | 747 | c->div = divu71 + 2; |
626 | c->mul = 2; | 748 | c->mul = 2; |
749 | } else if (c->flags & DIV_U16) { | ||
750 | u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
751 | c->div = divu16 + 1; | ||
752 | c->mul = 1; | ||
627 | } else { | 753 | } else { |
628 | c->div = 1; | 754 | c->div = 1; |
629 | c->mul = 1; | 755 | c->mul = 1; |
@@ -637,7 +763,6 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
637 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | 763 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & |
638 | PERIPH_CLK_TO_ENB_BIT(c)) | 764 | PERIPH_CLK_TO_ENB_BIT(c)) |
639 | c->state = OFF; | 765 | c->state = OFF; |
640 | tegra2_clk_recalculate_rate(c); | ||
641 | } | 766 | } |
642 | 767 | ||
643 | static int tegra2_periph_clk_enable(struct clk *c) | 768 | static int tegra2_periph_clk_enable(struct clk *c) |
@@ -692,12 +817,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); | 817 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); |
693 | for (sel = c->inputs; sel->input != NULL; sel++) { | 818 | for (sel = c->inputs; sel->input != NULL; sel++) { |
694 | if (sel->input == p) { | 819 | if (sel->input == p) { |
695 | clk_reparent(c, p); | ||
696 | val = clk_readl(c->reg); | 820 | val = clk_readl(c->reg); |
697 | val &= ~PERIPH_CLK_SOURCE_MASK; | 821 | val &= ~PERIPH_CLK_SOURCE_MASK; |
698 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; | 822 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; |
823 | |||
824 | if (c->refcnt) | ||
825 | clk_enable_locked(p); | ||
826 | |||
699 | clk_writel(val, c->reg); | 827 | clk_writel(val, c->reg); |
700 | c->rate = c->parent->rate; | 828 | |
829 | if (c->refcnt && c->parent) | ||
830 | clk_disable_locked(c->parent); | ||
831 | |||
832 | clk_reparent(c, p); | ||
701 | return 0; | 833 | return 0; |
702 | } | 834 | } |
703 | } | 835 | } |
@@ -708,20 +840,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) | 840 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) |
709 | { | 841 | { |
710 | u32 val; | 842 | u32 val; |
711 | int divider_u71; | 843 | int divider; |
712 | pr_debug("%s: %lu\n", __func__, rate); | 844 | pr_debug("%s: %lu\n", __func__, rate); |
713 | if (c->flags & DIV_U71) { | 845 | if (c->flags & DIV_U71) { |
714 | divider_u71 = clk_div71_get_divider(c->parent, rate); | 846 | divider = clk_div71_get_divider(c->parent->rate, rate); |
715 | if (divider_u71 >= 0) { | 847 | if (divider >= 0) { |
716 | val = clk_readl(c->reg); | 848 | val = clk_readl(c->reg); |
717 | val &= ~PERIPH_CLK_SOURCE_DIV_MASK; | 849 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; |
718 | val |= divider_u71; | 850 | val |= divider; |
719 | clk_writel(val, c->reg); | 851 | clk_writel(val, c->reg); |
720 | c->div = divider_u71 + 2; | 852 | c->div = divider + 2; |
721 | c->mul = 2; | 853 | c->mul = 2; |
722 | tegra2_clk_recalculate_rate(c); | ||
723 | return 0; | 854 | return 0; |
724 | } | 855 | } |
856 | } else if (c->flags & DIV_U16) { | ||
857 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
858 | if (divider >= 0) { | ||
859 | val = clk_readl(c->reg); | ||
860 | val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
861 | val |= divider; | ||
862 | clk_writel(val, c->reg); | ||
863 | c->div = divider + 1; | ||
864 | c->mul = 1; | ||
865 | return 0; | ||
866 | } | ||
867 | } else if (c->parent->rate <= rate) { | ||
868 | c->div = 1; | ||
869 | c->mul = 1; | ||
870 | return 0; | ||
871 | } | ||
872 | return -EINVAL; | ||
873 | } | ||
874 | |||
875 | static long tegra2_periph_clk_round_rate(struct clk *c, | ||
876 | unsigned long rate) | ||
877 | { | ||
878 | int divider; | ||
879 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
880 | |||
881 | if (c->flags & DIV_U71) { | ||
882 | divider = clk_div71_get_divider(c->parent->rate, rate); | ||
883 | if (divider < 0) | ||
884 | return divider; | ||
885 | |||
886 | return c->parent->rate * 2 / (divider + 2); | ||
887 | } else if (c->flags & DIV_U16) { | ||
888 | divider = clk_div16_get_divider(c->parent->rate, rate); | ||
889 | if (divider < 0) | ||
890 | return divider; | ||
891 | return c->parent->rate / (divider + 1); | ||
725 | } | 892 | } |
726 | return -EINVAL; | 893 | return -EINVAL; |
727 | } | 894 | } |
@@ -732,7 +899,7 @@ static struct clk_ops tegra_periph_clk_ops = { | |||
732 | .disable = &tegra2_periph_clk_disable, | 899 | .disable = &tegra2_periph_clk_disable, |
733 | .set_parent = &tegra2_periph_clk_set_parent, | 900 | .set_parent = &tegra2_periph_clk_set_parent, |
734 | .set_rate = &tegra2_periph_clk_set_rate, | 901 | .set_rate = &tegra2_periph_clk_set_rate, |
735 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 902 | .round_rate = &tegra2_periph_clk_round_rate, |
736 | }; | 903 | }; |
737 | 904 | ||
738 | /* Clock doubler ops */ | 905 | /* Clock doubler ops */ |
@@ -744,21 +911,108 @@ static void tegra2_clk_double_init(struct clk *c) | |||
744 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 911 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
745 | PERIPH_CLK_TO_ENB_BIT(c))) | 912 | PERIPH_CLK_TO_ENB_BIT(c))) |
746 | c->state = OFF; | 913 | c->state = OFF; |
747 | tegra2_clk_recalculate_rate(c); | ||
748 | }; | 914 | }; |
749 | 915 | ||
916 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) | ||
917 | { | ||
918 | if (rate != 2 * c->parent->rate) | ||
919 | return -EINVAL; | ||
920 | c->mul = 2; | ||
921 | c->div = 1; | ||
922 | return 0; | ||
923 | } | ||
924 | |||
750 | static struct clk_ops tegra_clk_double_ops = { | 925 | static struct clk_ops tegra_clk_double_ops = { |
751 | .init = &tegra2_clk_double_init, | 926 | .init = &tegra2_clk_double_init, |
752 | .enable = &tegra2_periph_clk_enable, | 927 | .enable = &tegra2_periph_clk_enable, |
753 | .disable = &tegra2_periph_clk_disable, | 928 | .disable = &tegra2_periph_clk_disable, |
754 | .recalculate_rate = &tegra2_clk_recalculate_rate, | 929 | .set_rate = &tegra2_clk_double_set_rate, |
930 | }; | ||
931 | |||
932 | static void tegra2_audio_sync_clk_init(struct clk *c) | ||
933 | { | ||
934 | int source; | ||
935 | const struct clk_mux_sel *sel; | ||
936 | u32 val = clk_readl(c->reg); | ||
937 | c->state = (val & (1<<4)) ? OFF : ON; | ||
938 | source = val & 0xf; | ||
939 | for (sel = c->inputs; sel->input != NULL; sel++) | ||
940 | if (sel->value == source) | ||
941 | break; | ||
942 | BUG_ON(sel->input == NULL); | ||
943 | c->parent = sel->input; | ||
944 | } | ||
945 | |||
946 | static int tegra2_audio_sync_clk_enable(struct clk *c) | ||
947 | { | ||
948 | clk_writel(0, c->reg); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static void tegra2_audio_sync_clk_disable(struct clk *c) | ||
953 | { | ||
954 | clk_writel(1, c->reg); | ||
955 | } | ||
956 | |||
957 | static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | ||
958 | { | ||
959 | u32 val; | ||
960 | const struct clk_mux_sel *sel; | ||
961 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
962 | if (sel->input == p) { | ||
963 | val = clk_readl(c->reg); | ||
964 | val &= ~0xf; | ||
965 | val |= sel->value; | ||
966 | |||
967 | if (c->refcnt) | ||
968 | clk_enable_locked(p); | ||
969 | |||
970 | clk_writel(val, c->reg); | ||
971 | |||
972 | if (c->refcnt && c->parent) | ||
973 | clk_disable_locked(c->parent); | ||
974 | |||
975 | clk_reparent(c, p); | ||
976 | return 0; | ||
977 | } | ||
978 | } | ||
979 | |||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate) | ||
984 | { | ||
985 | unsigned long parent_rate; | ||
986 | if (!c->parent) { | ||
987 | pr_err("%s: clock has no parent\n", __func__); | ||
988 | return -EINVAL; | ||
989 | } | ||
990 | parent_rate = c->parent->rate; | ||
991 | if (rate != parent_rate) { | ||
992 | pr_err("%s: %s/%ld differs from parent %s/%ld\n", | ||
993 | __func__, | ||
994 | c->name, rate, | ||
995 | c->parent->name, parent_rate); | ||
996 | return -EINVAL; | ||
997 | } | ||
998 | c->rate = parent_rate; | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | static struct clk_ops tegra_audio_sync_clk_ops = { | ||
1003 | .init = tegra2_audio_sync_clk_init, | ||
1004 | .enable = tegra2_audio_sync_clk_enable, | ||
1005 | .disable = tegra2_audio_sync_clk_disable, | ||
1006 | .set_rate = tegra2_audio_sync_clk_set_rate, | ||
1007 | .set_parent = tegra2_audio_sync_clk_set_parent, | ||
755 | }; | 1008 | }; |
756 | 1009 | ||
757 | /* Clock definitions */ | 1010 | /* Clock definitions */ |
758 | static struct clk tegra_clk_32k = { | 1011 | static struct clk tegra_clk_32k = { |
759 | .name = "clk_32k", | 1012 | .name = "clk_32k", |
760 | .rate = 32678, | 1013 | .rate = 32768, |
761 | .ops = NULL, | 1014 | .ops = NULL, |
1015 | .max_rate = 32768, | ||
762 | }; | 1016 | }; |
763 | 1017 | ||
764 | static struct clk_pll_table tegra_pll_s_table[] = { | 1018 | static struct clk_pll_table tegra_pll_s_table[] = { |
@@ -782,6 +1036,7 @@ static struct clk tegra_pll_s = { | |||
782 | .vco_min = 12000000, | 1036 | .vco_min = 12000000, |
783 | .vco_max = 26000000, | 1037 | .vco_max = 26000000, |
784 | .pll_table = tegra_pll_s_table, | 1038 | .pll_table = tegra_pll_s_table, |
1039 | .max_rate = 26000000, | ||
785 | }; | 1040 | }; |
786 | 1041 | ||
787 | static struct clk_mux_sel tegra_clk_m_sel[] = { | 1042 | static struct clk_mux_sel tegra_clk_m_sel[] = { |
@@ -797,6 +1052,7 @@ static struct clk tegra_clk_m = { | |||
797 | .reg = 0x1fc, | 1052 | .reg = 0x1fc, |
798 | .reg_mask = (1<<28), | 1053 | .reg_mask = (1<<28), |
799 | .reg_shift = 28, | 1054 | .reg_shift = 28, |
1055 | .max_rate = 26000000, | ||
800 | }; | 1056 | }; |
801 | 1057 | ||
802 | static struct clk_pll_table tegra_pll_c_table[] = { | 1058 | static struct clk_pll_table tegra_pll_c_table[] = { |
@@ -816,6 +1072,7 @@ static struct clk tegra_pll_c = { | |||
816 | .vco_min = 20000000, | 1072 | .vco_min = 20000000, |
817 | .vco_max = 1400000000, | 1073 | .vco_max = 1400000000, |
818 | .pll_table = tegra_pll_c_table, | 1074 | .pll_table = tegra_pll_c_table, |
1075 | .max_rate = 600000000, | ||
819 | }; | 1076 | }; |
820 | 1077 | ||
821 | static struct clk tegra_pll_c_out1 = { | 1078 | static struct clk tegra_pll_c_out1 = { |
@@ -825,9 +1082,18 @@ static struct clk tegra_pll_c_out1 = { | |||
825 | .parent = &tegra_pll_c, | 1082 | .parent = &tegra_pll_c, |
826 | .reg = 0x84, | 1083 | .reg = 0x84, |
827 | .reg_shift = 0, | 1084 | .reg_shift = 0, |
1085 | .max_rate = 600000000, | ||
828 | }; | 1086 | }; |
829 | 1087 | ||
830 | static struct clk_pll_table tegra_pll_m_table[] = { | 1088 | static struct clk_pll_table tegra_pll_m_table[] = { |
1089 | { 12000000, 666000000, 666, 12, 1, 8}, | ||
1090 | { 13000000, 666000000, 666, 13, 1, 8}, | ||
1091 | { 19200000, 666000000, 555, 16, 1, 8}, | ||
1092 | { 26000000, 666000000, 666, 26, 1, 8}, | ||
1093 | { 12000000, 600000000, 600, 12, 1, 8}, | ||
1094 | { 13000000, 600000000, 600, 13, 1, 8}, | ||
1095 | { 19200000, 600000000, 375, 12, 1, 6}, | ||
1096 | { 26000000, 600000000, 600, 26, 1, 8}, | ||
831 | { 0, 0, 0, 0, 0, 0 }, | 1097 | { 0, 0, 0, 0, 0, 0 }, |
832 | }; | 1098 | }; |
833 | 1099 | ||
@@ -844,6 +1110,7 @@ static struct clk tegra_pll_m = { | |||
844 | .vco_min = 20000000, | 1110 | .vco_min = 20000000, |
845 | .vco_max = 1200000000, | 1111 | .vco_max = 1200000000, |
846 | .pll_table = tegra_pll_m_table, | 1112 | .pll_table = tegra_pll_m_table, |
1113 | .max_rate = 800000000, | ||
847 | }; | 1114 | }; |
848 | 1115 | ||
849 | static struct clk tegra_pll_m_out1 = { | 1116 | static struct clk tegra_pll_m_out1 = { |
@@ -853,6 +1120,7 @@ static struct clk tegra_pll_m_out1 = { | |||
853 | .parent = &tegra_pll_m, | 1120 | .parent = &tegra_pll_m, |
854 | .reg = 0x94, | 1121 | .reg = 0x94, |
855 | .reg_shift = 0, | 1122 | .reg_shift = 0, |
1123 | .max_rate = 600000000, | ||
856 | }; | 1124 | }; |
857 | 1125 | ||
858 | static struct clk_pll_table tegra_pll_p_table[] = { | 1126 | static struct clk_pll_table tegra_pll_p_table[] = { |
@@ -880,6 +1148,7 @@ static struct clk tegra_pll_p = { | |||
880 | .vco_min = 20000000, | 1148 | .vco_min = 20000000, |
881 | .vco_max = 1400000000, | 1149 | .vco_max = 1400000000, |
882 | .pll_table = tegra_pll_p_table, | 1150 | .pll_table = tegra_pll_p_table, |
1151 | .max_rate = 432000000, | ||
883 | }; | 1152 | }; |
884 | 1153 | ||
885 | static struct clk tegra_pll_p_out1 = { | 1154 | static struct clk tegra_pll_p_out1 = { |
@@ -889,6 +1158,7 @@ static struct clk tegra_pll_p_out1 = { | |||
889 | .parent = &tegra_pll_p, | 1158 | .parent = &tegra_pll_p, |
890 | .reg = 0xa4, | 1159 | .reg = 0xa4, |
891 | .reg_shift = 0, | 1160 | .reg_shift = 0, |
1161 | .max_rate = 432000000, | ||
892 | }; | 1162 | }; |
893 | 1163 | ||
894 | static struct clk tegra_pll_p_out2 = { | 1164 | static struct clk tegra_pll_p_out2 = { |
@@ -898,6 +1168,7 @@ static struct clk tegra_pll_p_out2 = { | |||
898 | .parent = &tegra_pll_p, | 1168 | .parent = &tegra_pll_p, |
899 | .reg = 0xa4, | 1169 | .reg = 0xa4, |
900 | .reg_shift = 16, | 1170 | .reg_shift = 16, |
1171 | .max_rate = 432000000, | ||
901 | }; | 1172 | }; |
902 | 1173 | ||
903 | static struct clk tegra_pll_p_out3 = { | 1174 | static struct clk tegra_pll_p_out3 = { |
@@ -907,6 +1178,7 @@ static struct clk tegra_pll_p_out3 = { | |||
907 | .parent = &tegra_pll_p, | 1178 | .parent = &tegra_pll_p, |
908 | .reg = 0xa8, | 1179 | .reg = 0xa8, |
909 | .reg_shift = 0, | 1180 | .reg_shift = 0, |
1181 | .max_rate = 432000000, | ||
910 | }; | 1182 | }; |
911 | 1183 | ||
912 | static struct clk tegra_pll_p_out4 = { | 1184 | static struct clk tegra_pll_p_out4 = { |
@@ -916,6 +1188,7 @@ static struct clk tegra_pll_p_out4 = { | |||
916 | .parent = &tegra_pll_p, | 1188 | .parent = &tegra_pll_p, |
917 | .reg = 0xa8, | 1189 | .reg = 0xa8, |
918 | .reg_shift = 16, | 1190 | .reg_shift = 16, |
1191 | .max_rate = 432000000, | ||
919 | }; | 1192 | }; |
920 | 1193 | ||
921 | static struct clk_pll_table tegra_pll_a_table[] = { | 1194 | static struct clk_pll_table tegra_pll_a_table[] = { |
@@ -923,6 +1196,7 @@ static struct clk_pll_table tegra_pll_a_table[] = { | |||
923 | { 28800000, 73728000, 64, 25, 1, 1}, | 1196 | { 28800000, 73728000, 64, 25, 1, 1}, |
924 | { 28800000, 11289600, 49, 25, 1, 1}, | 1197 | { 28800000, 11289600, 49, 25, 1, 1}, |
925 | { 28800000, 12288000, 64, 25, 1, 1}, | 1198 | { 28800000, 12288000, 64, 25, 1, 1}, |
1199 | { 28800000, 24000000, 5, 6, 1, 1}, | ||
926 | { 0, 0, 0, 0, 0, 0 }, | 1200 | { 0, 0, 0, 0, 0, 0 }, |
927 | }; | 1201 | }; |
928 | 1202 | ||
@@ -939,6 +1213,7 @@ static struct clk tegra_pll_a = { | |||
939 | .vco_min = 20000000, | 1213 | .vco_min = 20000000, |
940 | .vco_max = 1400000000, | 1214 | .vco_max = 1400000000, |
941 | .pll_table = tegra_pll_a_table, | 1215 | .pll_table = tegra_pll_a_table, |
1216 | .max_rate = 56448000, | ||
942 | }; | 1217 | }; |
943 | 1218 | ||
944 | static struct clk tegra_pll_a_out0 = { | 1219 | static struct clk tegra_pll_a_out0 = { |
@@ -948,6 +1223,7 @@ static struct clk tegra_pll_a_out0 = { | |||
948 | .parent = &tegra_pll_a, | 1223 | .parent = &tegra_pll_a, |
949 | .reg = 0xb4, | 1224 | .reg = 0xb4, |
950 | .reg_shift = 0, | 1225 | .reg_shift = 0, |
1226 | .max_rate = 56448000, | ||
951 | }; | 1227 | }; |
952 | 1228 | ||
953 | static struct clk_pll_table tegra_pll_d_table[] = { | 1229 | static struct clk_pll_table tegra_pll_d_table[] = { |
@@ -971,6 +1247,7 @@ static struct clk tegra_pll_d = { | |||
971 | .vco_min = 40000000, | 1247 | .vco_min = 40000000, |
972 | .vco_max = 1000000000, | 1248 | .vco_max = 1000000000, |
973 | .pll_table = tegra_pll_d_table, | 1249 | .pll_table = tegra_pll_d_table, |
1250 | .max_rate = 1000000000, | ||
974 | }; | 1251 | }; |
975 | 1252 | ||
976 | static struct clk tegra_pll_d_out0 = { | 1253 | static struct clk tegra_pll_d_out0 = { |
@@ -978,19 +1255,20 @@ static struct clk tegra_pll_d_out0 = { | |||
978 | .ops = &tegra_pll_div_ops, | 1255 | .ops = &tegra_pll_div_ops, |
979 | .flags = DIV_2 | PLLD, | 1256 | .flags = DIV_2 | PLLD, |
980 | .parent = &tegra_pll_d, | 1257 | .parent = &tegra_pll_d, |
1258 | .max_rate = 500000000, | ||
981 | }; | 1259 | }; |
982 | 1260 | ||
983 | static struct clk_pll_table tegra_pll_u_table[] = { | 1261 | static struct clk_pll_table tegra_pll_u_table[] = { |
984 | { 12000000, 480000000, 960, 12, 1, 0}, | 1262 | { 12000000, 480000000, 960, 12, 2, 0}, |
985 | { 13000000, 480000000, 960, 13, 1, 0}, | 1263 | { 13000000, 480000000, 960, 13, 2, 0}, |
986 | { 19200000, 480000000, 200, 4, 1, 0}, | 1264 | { 19200000, 480000000, 200, 4, 2, 0}, |
987 | { 26000000, 480000000, 960, 26, 1, 0}, | 1265 | { 26000000, 480000000, 960, 26, 2, 0}, |
988 | { 0, 0, 0, 0, 0, 0 }, | 1266 | { 0, 0, 0, 0, 0, 0 }, |
989 | }; | 1267 | }; |
990 | 1268 | ||
991 | static struct clk tegra_pll_u = { | 1269 | static struct clk tegra_pll_u = { |
992 | .name = "pll_u", | 1270 | .name = "pll_u", |
993 | .flags = 0, | 1271 | .flags = PLLU, |
994 | .ops = &tegra_pll_ops, | 1272 | .ops = &tegra_pll_ops, |
995 | .reg = 0xc0, | 1273 | .reg = 0xc0, |
996 | .input_min = 2000000, | 1274 | .input_min = 2000000, |
@@ -1001,24 +1279,59 @@ static struct clk tegra_pll_u = { | |||
1001 | .vco_min = 480000000, | 1279 | .vco_min = 480000000, |
1002 | .vco_max = 960000000, | 1280 | .vco_max = 960000000, |
1003 | .pll_table = tegra_pll_u_table, | 1281 | .pll_table = tegra_pll_u_table, |
1282 | .max_rate = 480000000, | ||
1004 | }; | 1283 | }; |
1005 | 1284 | ||
1006 | static struct clk_pll_table tegra_pll_x_table[] = { | 1285 | static struct clk_pll_table tegra_pll_x_table[] = { |
1286 | /* 1 GHz */ | ||
1007 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 1287 | { 12000000, 1000000000, 1000, 12, 1, 12}, |
1008 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 1288 | { 13000000, 1000000000, 1000, 13, 1, 12}, |
1009 | { 19200000, 1000000000, 625, 12, 1, 8}, | 1289 | { 19200000, 1000000000, 625, 12, 1, 8}, |
1010 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 1290 | { 26000000, 1000000000, 1000, 26, 1, 12}, |
1011 | { 12000000, 750000000, 750, 12, 1, 12}, | 1291 | |
1012 | { 13000000, 750000000, 750, 13, 1, 12}, | 1292 | /* 912 MHz */ |
1013 | { 19200000, 750000000, 625, 16, 1, 8}, | 1293 | { 12000000, 912000000, 912, 12, 1, 12}, |
1014 | { 26000000, 750000000, 750, 26, 1, 12}, | 1294 | { 13000000, 912000000, 912, 13, 1, 12}, |
1295 | { 19200000, 912000000, 760, 16, 1, 8}, | ||
1296 | { 26000000, 912000000, 912, 26, 1, 12}, | ||
1297 | |||
1298 | /* 816 MHz */ | ||
1299 | { 12000000, 816000000, 816, 12, 1, 12}, | ||
1300 | { 13000000, 816000000, 816, 13, 1, 12}, | ||
1301 | { 19200000, 816000000, 680, 16, 1, 8}, | ||
1302 | { 26000000, 816000000, 816, 26, 1, 12}, | ||
1303 | |||
1304 | /* 760 MHz */ | ||
1305 | { 12000000, 760000000, 760, 12, 1, 12}, | ||
1306 | { 13000000, 760000000, 760, 13, 1, 12}, | ||
1307 | { 19200000, 760000000, 950, 24, 1, 8}, | ||
1308 | { 26000000, 760000000, 760, 26, 1, 12}, | ||
1309 | |||
1310 | /* 608 MHz */ | ||
1311 | { 12000000, 608000000, 760, 12, 1, 12}, | ||
1312 | { 13000000, 608000000, 760, 13, 1, 12}, | ||
1313 | { 19200000, 608000000, 380, 12, 1, 8}, | ||
1314 | { 26000000, 608000000, 760, 26, 1, 12}, | ||
1315 | |||
1316 | /* 456 MHz */ | ||
1317 | { 12000000, 456000000, 456, 12, 1, 12}, | ||
1318 | { 13000000, 456000000, 456, 13, 1, 12}, | ||
1319 | { 19200000, 456000000, 380, 16, 1, 8}, | ||
1320 | { 26000000, 456000000, 456, 26, 1, 12}, | ||
1321 | |||
1322 | /* 312 MHz */ | ||
1323 | { 12000000, 312000000, 312, 12, 1, 12}, | ||
1324 | { 13000000, 312000000, 312, 13, 1, 12}, | ||
1325 | { 19200000, 312000000, 260, 16, 1, 8}, | ||
1326 | { 26000000, 312000000, 312, 26, 1, 12}, | ||
1327 | |||
1015 | { 0, 0, 0, 0, 0, 0 }, | 1328 | { 0, 0, 0, 0, 0, 0 }, |
1016 | }; | 1329 | }; |
1017 | 1330 | ||
1018 | static struct clk tegra_pll_x = { | 1331 | static struct clk tegra_pll_x = { |
1019 | .name = "pll_x", | 1332 | .name = "pll_x", |
1020 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, | 1333 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, |
1021 | .ops = &tegra_pll_ops, | 1334 | .ops = &tegra_pllx_ops, |
1022 | .reg = 0xe0, | 1335 | .reg = 0xe0, |
1023 | .input_min = 2000000, | 1336 | .input_min = 2000000, |
1024 | .input_max = 31000000, | 1337 | .input_max = 31000000, |
@@ -1028,6 +1341,24 @@ static struct clk tegra_pll_x = { | |||
1028 | .vco_min = 20000000, | 1341 | .vco_min = 20000000, |
1029 | .vco_max = 1200000000, | 1342 | .vco_max = 1200000000, |
1030 | .pll_table = tegra_pll_x_table, | 1343 | .pll_table = tegra_pll_x_table, |
1344 | .max_rate = 1000000000, | ||
1345 | }; | ||
1346 | |||
1347 | static struct clk_pll_table tegra_pll_e_table[] = { | ||
1348 | { 12000000, 100000000, 200, 24, 1, 0 }, | ||
1349 | { 0, 0, 0, 0, 0, 0 }, | ||
1350 | }; | ||
1351 | |||
1352 | static struct clk tegra_pll_e = { | ||
1353 | .name = "pll_e", | ||
1354 | .flags = PLL_ALT_MISC_REG, | ||
1355 | .ops = &tegra_plle_ops, | ||
1356 | .input_min = 12000000, | ||
1357 | .input_max = 12000000, | ||
1358 | .max_rate = 100000000, | ||
1359 | .parent = &tegra_clk_m, | ||
1360 | .reg = 0xe8, | ||
1361 | .pll_table = tegra_pll_e_table, | ||
1031 | }; | 1362 | }; |
1032 | 1363 | ||
1033 | static struct clk tegra_clk_d = { | 1364 | static struct clk tegra_clk_d = { |
@@ -1038,19 +1369,77 @@ static struct clk tegra_clk_d = { | |||
1038 | .reg = 0x34, | 1369 | .reg = 0x34, |
1039 | .reg_shift = 12, | 1370 | .reg_shift = 12, |
1040 | .parent = &tegra_clk_m, | 1371 | .parent = &tegra_clk_m, |
1372 | .max_rate = 52000000, | ||
1373 | }; | ||
1374 | |||
1375 | /* initialized before peripheral clocks */ | ||
1376 | static struct clk_mux_sel mux_audio_sync_clk[8+1]; | ||
1377 | static const struct audio_sources { | ||
1378 | const char *name; | ||
1379 | int value; | ||
1380 | } mux_audio_sync_clk_sources[] = { | ||
1381 | { .name = "spdif_in", .value = 0 }, | ||
1382 | { .name = "i2s1", .value = 1 }, | ||
1383 | { .name = "i2s2", .value = 2 }, | ||
1384 | { .name = "pll_a_out0", .value = 4 }, | ||
1385 | #if 0 /* FIXME: not implemented */ | ||
1386 | { .name = "ac97", .value = 3 }, | ||
1387 | { .name = "ext_audio_clk2", .value = 5 }, | ||
1388 | { .name = "ext_audio_clk1", .value = 6 }, | ||
1389 | { .name = "ext_vimclk", .value = 7 }, | ||
1390 | #endif | ||
1391 | { 0, 0 } | ||
1392 | }; | ||
1393 | |||
1394 | static struct clk tegra_clk_audio = { | ||
1395 | .name = "audio", | ||
1396 | .inputs = mux_audio_sync_clk, | ||
1397 | .reg = 0x38, | ||
1398 | .max_rate = 24000000, | ||
1399 | .ops = &tegra_audio_sync_clk_ops | ||
1041 | }; | 1400 | }; |
1042 | 1401 | ||
1043 | /* FIXME: need tegra_audio | ||
1044 | static struct clk tegra_clk_audio_2x = { | 1402 | static struct clk tegra_clk_audio_2x = { |
1045 | .name = "clk_d", | 1403 | .name = "audio_2x", |
1046 | .flags = PERIPH_NO_RESET, | 1404 | .flags = PERIPH_NO_RESET, |
1405 | .max_rate = 48000000, | ||
1047 | .ops = &tegra_clk_double_ops, | 1406 | .ops = &tegra_clk_double_ops, |
1048 | .clk_num = 89, | 1407 | .clk_num = 89, |
1049 | .reg = 0x34, | 1408 | .reg = 0x34, |
1050 | .reg_shift = 8, | 1409 | .reg_shift = 8, |
1051 | .parent = &tegra_audio, | 1410 | .parent = &tegra_clk_audio, |
1411 | }; | ||
1412 | |||
1413 | struct clk_lookup tegra_audio_clk_lookups[] = { | ||
1414 | { .con_id = "audio", .clk = &tegra_clk_audio }, | ||
1415 | { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x } | ||
1416 | }; | ||
1417 | |||
1418 | /* This is called after peripheral clocks are initialized, as the | ||
1419 | * audio_sync clock depends on some of the peripheral clocks. | ||
1420 | */ | ||
1421 | |||
1422 | static void init_audio_sync_clock_mux(void) | ||
1423 | { | ||
1424 | int i; | ||
1425 | struct clk_mux_sel *sel = mux_audio_sync_clk; | ||
1426 | const struct audio_sources *src = mux_audio_sync_clk_sources; | ||
1427 | struct clk_lookup *lookup; | ||
1428 | |||
1429 | for (i = 0; src->name; i++, sel++, src++) { | ||
1430 | sel->input = tegra_get_clock_by_name(src->name); | ||
1431 | if (!sel->input) | ||
1432 | pr_err("%s: could not find clk %s\n", __func__, | ||
1433 | src->name); | ||
1434 | sel->value = src->value; | ||
1435 | } | ||
1436 | |||
1437 | lookup = tegra_audio_clk_lookups; | ||
1438 | for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) { | ||
1439 | clk_init(lookup->clk); | ||
1440 | clkdev_add(lookup); | ||
1441 | } | ||
1052 | } | 1442 | } |
1053 | */ | ||
1054 | 1443 | ||
1055 | static struct clk_mux_sel mux_cclk[] = { | 1444 | static struct clk_mux_sel mux_cclk[] = { |
1056 | { .input = &tegra_clk_m, .value = 0}, | 1445 | { .input = &tegra_clk_m, .value = 0}, |
@@ -1077,27 +1466,40 @@ static struct clk_mux_sel mux_sclk[] = { | |||
1077 | { 0, 0}, | 1466 | { 0, 0}, |
1078 | }; | 1467 | }; |
1079 | 1468 | ||
1080 | static struct clk tegra_clk_cpu = { | 1469 | static struct clk tegra_clk_cclk = { |
1081 | .name = "cpu", | 1470 | .name = "cclk", |
1082 | .inputs = mux_cclk, | 1471 | .inputs = mux_cclk, |
1083 | .reg = 0x20, | 1472 | .reg = 0x20, |
1084 | .ops = &tegra_super_ops, | 1473 | .ops = &tegra_super_ops, |
1474 | .max_rate = 1000000000, | ||
1085 | }; | 1475 | }; |
1086 | 1476 | ||
1087 | static struct clk tegra_clk_sys = { | 1477 | static struct clk tegra_clk_sclk = { |
1088 | .name = "sys", | 1478 | .name = "sclk", |
1089 | .inputs = mux_sclk, | 1479 | .inputs = mux_sclk, |
1090 | .reg = 0x28, | 1480 | .reg = 0x28, |
1091 | .ops = &tegra_super_ops, | 1481 | .ops = &tegra_super_ops, |
1482 | .max_rate = 600000000, | ||
1483 | }; | ||
1484 | |||
1485 | static struct clk tegra_clk_virtual_cpu = { | ||
1486 | .name = "cpu", | ||
1487 | .parent = &tegra_clk_cclk, | ||
1488 | .main = &tegra_pll_x, | ||
1489 | .backup = &tegra_clk_m, | ||
1490 | .ops = &tegra_cpu_ops, | ||
1491 | .max_rate = 1000000000, | ||
1492 | .dvfs = &tegra_dvfs_virtual_cpu_dvfs, | ||
1092 | }; | 1493 | }; |
1093 | 1494 | ||
1094 | static struct clk tegra_clk_hclk = { | 1495 | static struct clk tegra_clk_hclk = { |
1095 | .name = "hclk", | 1496 | .name = "hclk", |
1096 | .flags = DIV_BUS, | 1497 | .flags = DIV_BUS, |
1097 | .parent = &tegra_clk_sys, | 1498 | .parent = &tegra_clk_sclk, |
1098 | .reg = 0x30, | 1499 | .reg = 0x30, |
1099 | .reg_shift = 4, | 1500 | .reg_shift = 4, |
1100 | .ops = &tegra_bus_ops, | 1501 | .ops = &tegra_bus_ops, |
1502 | .max_rate = 240000000, | ||
1101 | }; | 1503 | }; |
1102 | 1504 | ||
1103 | static struct clk tegra_clk_pclk = { | 1505 | static struct clk tegra_clk_pclk = { |
@@ -1107,6 +1509,7 @@ static struct clk tegra_clk_pclk = { | |||
1107 | .reg = 0x30, | 1509 | .reg = 0x30, |
1108 | .reg_shift = 0, | 1510 | .reg_shift = 0, |
1109 | .ops = &tegra_bus_ops, | 1511 | .ops = &tegra_bus_ops, |
1512 | .max_rate = 108000000, | ||
1110 | }; | 1513 | }; |
1111 | 1514 | ||
1112 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { | 1515 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { |
@@ -1133,10 +1536,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = { | |||
1133 | { 0, 0}, | 1536 | { 0, 0}, |
1134 | }; | 1537 | }; |
1135 | 1538 | ||
1136 | static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = { | 1539 | static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = { |
1137 | {.input = &tegra_pll_a, .value = 0}, | 1540 | {.input = &tegra_pll_a_out0, .value = 0}, |
1138 | /* FIXME: no mux defined for tegra_audio | 1541 | {.input = &tegra_clk_audio_2x, .value = 1}, |
1139 | {.input = &tegra_audio, .value = 1},*/ | ||
1140 | {.input = &tegra_pll_p, .value = 2}, | 1542 | {.input = &tegra_pll_p, .value = 2}, |
1141 | {.input = &tegra_clk_m, .value = 3}, | 1543 | {.input = &tegra_clk_m, .value = 3}, |
1142 | { 0, 0}, | 1544 | { 0, 0}, |
@@ -1153,8 +1555,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = { | |||
1153 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { | 1555 | static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = { |
1154 | {.input = &tegra_pll_p, .value = 0}, | 1556 | {.input = &tegra_pll_p, .value = 0}, |
1155 | {.input = &tegra_pll_c, .value = 1}, | 1557 | {.input = &tegra_pll_c, .value = 1}, |
1156 | /* FIXME: no mux defined for tegra_audio | 1558 | {.input = &tegra_clk_audio, .value = 2}, |
1157 | {.input = &tegra_audio, .value = 2},*/ | ||
1158 | {.input = &tegra_clk_m, .value = 3}, | 1559 | {.input = &tegra_clk_m, .value = 3}, |
1159 | {.input = &tegra_clk_32k, .value = 4}, | 1560 | {.input = &tegra_clk_32k, .value = 4}, |
1160 | { 0, 0}, | 1561 | { 0, 0}, |
@@ -1187,7 +1588,7 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1187 | { 0, 0}, | 1588 | { 0, 0}, |
1188 | }; | 1589 | }; |
1189 | 1590 | ||
1190 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \ | 1591 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ |
1191 | { \ | 1592 | { \ |
1192 | .name = _name, \ | 1593 | .name = _name, \ |
1193 | .lookup = { \ | 1594 | .lookup = { \ |
@@ -1199,72 +1600,79 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1199 | .reg = _reg, \ | 1600 | .reg = _reg, \ |
1200 | .inputs = _inputs, \ | 1601 | .inputs = _inputs, \ |
1201 | .flags = _flags, \ | 1602 | .flags = _flags, \ |
1603 | .max_rate = _max, \ | ||
1202 | } | 1604 | } |
1203 | 1605 | ||
1204 | struct clk tegra_periph_clks[] = { | 1606 | struct clk tegra_periph_clks[] = { |
1205 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, mux_clk_32k, PERIPH_NO_RESET), | 1607 | 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), | 1608 | 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), | 1609 | 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), | 1610 | 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 */ | 1611 | /* 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), | 1612 | 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), | 1613 | 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), | 1614 | 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), | 1615 | 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), | 1616 | 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), | 1617 | 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), | 1618 | 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), | 1619 | 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), | 1620 | 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), | 1621 | 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), | 1622 | 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), | 1623 | 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 */ | 1624 | /* FIXME: vfir shares an enable with uartb */ |
1223 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1625 | 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), | 1626 | 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), | 1627 | 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), | 1628 | 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), | 1629 | 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), | 1630 | 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), | 1631 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ |
1230 | /* FIXME: what is la? */ | 1632 | /* FIXME: what is la? */ |
1231 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 1633 | 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), | 1634 | 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), | 1635 | 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), | 1636 | 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), | 1637 | 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), | 1638 | 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), | 1639 | 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), | 1640 | 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), | 1641 | 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), | 1642 | 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), | 1643 | 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), | 1644 | 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), | 1645 | 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), | 1646 | 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), | 1647 | 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), | 1648 | 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), | 1649 | 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), | 1650 | 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), | 1651 | 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 */ | 1652 | /* FIXME: vi and vi_sensor share an enable */ |
1251 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), | 1653 | 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), | 1654 | 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), | 1655 | 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), | 1656 | 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), | 1657 | 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 */ | 1658 | /* FIXME: cve and tvo share an enable */ |
1257 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), | 1659 | 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), | 1660 | 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), | 1661 | 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), | 1662 | 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), | 1663 | 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), | 1664 | 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), | 1665 | 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), | 1666 | 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), | 1667 | 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), | 1668 | 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), | 1669 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ |
1670 | PERIPH_CLK("csi", "csi", NULL, 52, 0, 72000000, mux_pllp_out3, 0), | ||
1671 | PERIPH_CLK("isp", "isp", NULL, 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ | ||
1672 | PERIPH_CLK("csus", "csus", NULL, 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), | ||
1673 | PERIPH_CLK("pex", NULL, "pex", 70, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1674 | PERIPH_CLK("afi", NULL, "afi", 72, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1675 | PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | ||
1268 | }; | 1676 | }; |
1269 | 1677 | ||
1270 | #define CLK_DUPLICATE(_name, _dev, _con) \ | 1678 | #define CLK_DUPLICATE(_name, _dev, _con) \ |
@@ -1286,6 +1694,9 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
1286 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), | 1694 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), |
1287 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), | 1695 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), |
1288 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), | 1696 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), |
1697 | CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"), | ||
1698 | CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"), | ||
1699 | CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), | ||
1289 | }; | 1700 | }; |
1290 | 1701 | ||
1291 | #define CLK(dev, con, ck) \ | 1702 | #define CLK(dev, con, ck) \ |
@@ -1315,11 +1726,13 @@ struct clk_lookup tegra_clk_lookups[] = { | |||
1315 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), | 1726 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), |
1316 | CLK(NULL, "pll_u", &tegra_pll_u), | 1727 | CLK(NULL, "pll_u", &tegra_pll_u), |
1317 | CLK(NULL, "pll_x", &tegra_pll_x), | 1728 | CLK(NULL, "pll_x", &tegra_pll_x), |
1318 | CLK(NULL, "cpu", &tegra_clk_cpu), | 1729 | CLK(NULL, "pll_e", &tegra_pll_e), |
1319 | CLK(NULL, "sys", &tegra_clk_sys), | 1730 | CLK(NULL, "cclk", &tegra_clk_cclk), |
1731 | CLK(NULL, "sclk", &tegra_clk_sclk), | ||
1320 | CLK(NULL, "hclk", &tegra_clk_hclk), | 1732 | CLK(NULL, "hclk", &tegra_clk_hclk), |
1321 | CLK(NULL, "pclk", &tegra_clk_pclk), | 1733 | CLK(NULL, "pclk", &tegra_clk_pclk), |
1322 | CLK(NULL, "clk_d", &tegra_clk_d), | 1734 | CLK(NULL, "clk_d", &tegra_clk_d), |
1735 | CLK(NULL, "cpu", &tegra_clk_virtual_cpu), | ||
1323 | }; | 1736 | }; |
1324 | 1737 | ||
1325 | void __init tegra2_init_clocks(void) | 1738 | void __init tegra2_init_clocks(void) |
@@ -1356,4 +1769,75 @@ void __init tegra2_init_clocks(void) | |||
1356 | cd->name); | 1769 | cd->name); |
1357 | } | 1770 | } |
1358 | } | 1771 | } |
1772 | |||
1773 | init_audio_sync_clock_mux(); | ||
1774 | } | ||
1775 | |||
1776 | #ifdef CONFIG_PM | ||
1777 | static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + | ||
1778 | PERIPH_CLK_SOURCE_NUM + 3]; | ||
1779 | |||
1780 | void tegra_clk_suspend(void) | ||
1781 | { | ||
1782 | unsigned long off, i; | ||
1783 | u32 *ctx = clk_rst_suspend; | ||
1784 | |||
1785 | *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; | ||
1786 | |||
1787 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1788 | off += 4) { | ||
1789 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1790 | continue; | ||
1791 | *ctx++ = clk_readl(off); | ||
1792 | } | ||
1793 | |||
1794 | off = RST_DEVICES; | ||
1795 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1796 | *ctx++ = clk_readl(off); | ||
1797 | |||
1798 | off = CLK_OUT_ENB; | ||
1799 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1800 | *ctx++ = clk_readl(off); | ||
1801 | |||
1802 | *ctx++ = clk_readl(MISC_CLK_ENB); | ||
1803 | *ctx++ = clk_readl(CLK_MASK_ARM); | ||
1804 | } | ||
1805 | |||
1806 | void tegra_clk_resume(void) | ||
1807 | { | ||
1808 | unsigned long off, i; | ||
1809 | const u32 *ctx = clk_rst_suspend; | ||
1810 | u32 val; | ||
1811 | |||
1812 | val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK; | ||
1813 | val |= *ctx++; | ||
1814 | clk_writel(val, OSC_CTRL); | ||
1815 | |||
1816 | /* enable all clocks before configuring clock sources */ | ||
1817 | clk_writel(0xbffffff9ul, CLK_OUT_ENB); | ||
1818 | clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); | ||
1819 | clk_writel(0x77f01bfful, CLK_OUT_ENB + 8); | ||
1820 | wmb(); | ||
1821 | |||
1822 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | ||
1823 | off += 4) { | ||
1824 | if (off == PERIPH_CLK_SOURCE_EMC) | ||
1825 | continue; | ||
1826 | clk_writel(*ctx++, off); | ||
1827 | } | ||
1828 | wmb(); | ||
1829 | |||
1830 | off = RST_DEVICES; | ||
1831 | for (i = 0; i < RST_DEVICES_NUM; i++, off += 4) | ||
1832 | clk_writel(*ctx++, off); | ||
1833 | wmb(); | ||
1834 | |||
1835 | off = CLK_OUT_ENB; | ||
1836 | for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4) | ||
1837 | clk_writel(*ctx++, off); | ||
1838 | wmb(); | ||
1839 | |||
1840 | clk_writel(*ctx++, MISC_CLK_ENB); | ||
1841 | clk_writel(*ctx++, CLK_MASK_ARM); | ||
1359 | } | 1842 | } |
1843 | #endif | ||