diff options
Diffstat (limited to 'arch/arm/mach-omap2/clock36xx.c')
-rw-r--r-- | arch/arm/mach-omap2/clock36xx.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/clock36xx.c b/arch/arm/mach-omap2/clock36xx.c new file mode 100644 index 000000000000..0c5e25ed8879 --- /dev/null +++ b/arch/arm/mach-omap2/clock36xx.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * OMAP36xx-specific clkops | ||
3 | * | ||
4 | * Copyright (C) 2010 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2010 Nokia Corporation | ||
6 | * | ||
7 | * Mike Turquette | ||
8 | * Vijaykumar GN | ||
9 | * Paul Walmsley | ||
10 | * | ||
11 | * Parts of this code are based on code written by | ||
12 | * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu, | ||
13 | * Russell King | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License version 2 as | ||
17 | * published by the Free Software Foundation. | ||
18 | */ | ||
19 | #undef DEBUG | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <plat/clock.h> | ||
26 | |||
27 | #include "clock.h" | ||
28 | #include "clock36xx.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * omap36xx_pwrdn_clk_enable_with_hsdiv_restore - enable clocks suffering | ||
33 | * from HSDivider PWRDN problem Implements Errata ID: i556. | ||
34 | * @clk: DPLL output struct clk | ||
35 | * | ||
36 | * 3630 only: dpll3_m3_ck, dpll4_m2_ck, dpll4_m3_ck, dpll4_m4_ck, | ||
37 | * dpll4_m5_ck & dpll4_m6_ck dividers gets loaded with reset | ||
38 | * valueafter their respective PWRDN bits are set. Any dummy write | ||
39 | * (Any other value different from the Read value) to the | ||
40 | * corresponding CM_CLKSEL register will refresh the dividers. | ||
41 | */ | ||
42 | static int omap36xx_pwrdn_clk_enable_with_hsdiv_restore(struct clk *clk) | ||
43 | { | ||
44 | u32 dummy_v, orig_v, clksel_shift; | ||
45 | int ret; | ||
46 | |||
47 | /* Clear PWRDN bit of HSDIVIDER */ | ||
48 | ret = omap2_dflt_clk_enable(clk); | ||
49 | |||
50 | /* Restore the dividers */ | ||
51 | if (!ret) { | ||
52 | clksel_shift = __ffs(clk->parent->clksel_mask); | ||
53 | orig_v = __raw_readl(clk->parent->clksel_reg); | ||
54 | dummy_v = orig_v; | ||
55 | |||
56 | /* Write any other value different from the Read value */ | ||
57 | dummy_v ^= (1 << clksel_shift); | ||
58 | __raw_writel(dummy_v, clk->parent->clksel_reg); | ||
59 | |||
60 | /* Write the original divider */ | ||
61 | __raw_writel(orig_v, clk->parent->clksel_reg); | ||
62 | } | ||
63 | |||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | const struct clkops clkops_omap36xx_pwrdn_with_hsdiv_wait_restore = { | ||
68 | .enable = omap36xx_pwrdn_clk_enable_with_hsdiv_restore, | ||
69 | .disable = omap2_dflt_clk_disable, | ||
70 | .find_companion = omap2_clk_dflt_find_companion, | ||
71 | .find_idlest = omap2_clk_dflt_find_idlest, | ||
72 | }; | ||