Commit | Line | Data |
---|---|---|
49214640 PW |
1 | /* |
2 | * OMAP2xxx APLL clock control functions | |
3 | * | |
4 | * Copyright (C) 2005-2008 Texas Instruments, Inc. | |
5 | * Copyright (C) 2004-2010 Nokia Corporation | |
6 | * | |
7 | * Contacts: | |
8 | * Richard Woodruff <r-woodruff2@ti.com> | |
9 | * Paul Walmsley | |
10 | * | |
11 | * Based on earlier work by Tuukka Tikkanen, Tony Lindgren, | |
12 | * Gordon McNutt and RidgeRun, Inc. | |
13 | * | |
14 | * This program is free software; you can redistribute it and/or modify | |
15 | * it under the terms of the GNU General Public License version 2 as | |
16 | * published by the Free Software Foundation. | |
17 | */ | |
18 | #undef DEBUG | |
19 | ||
20 | #include <linux/kernel.h> | |
21 | #include <linux/clk.h> | |
22 | #include <linux/io.h> | |
23 | ||
24 | #include <plat/clock.h> | |
25 | #include <plat/prcm.h> | |
26 | ||
27 | #include "clock.h" | |
28 | #include "clock2xxx.h" | |
29 | #include "cm.h" | |
30 | #include "cm-regbits-24xx.h" | |
31 | ||
32 | /* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ | |
33 | #define EN_APLL_STOPPED 0 | |
34 | #define EN_APLL_LOCKED 3 | |
35 | ||
36 | /* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */ | |
37 | #define APLLS_CLKIN_19_2MHZ 0 | |
38 | #define APLLS_CLKIN_13MHZ 2 | |
39 | #define APLLS_CLKIN_12MHZ 3 | |
40 | ||
81b34fbe PW |
41 | void __iomem *cm_idlest_pll; |
42 | ||
49214640 PW |
43 | /* Private functions */ |
44 | ||
45 | /* Enable an APLL if off */ | |
46 | static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask) | |
47 | { | |
48 | u32 cval, apll_mask; | |
49 | ||
50 | apll_mask = EN_APLL_LOCKED << clk->enable_bit; | |
51 | ||
52 | cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); | |
53 | ||
54 | if ((cval & apll_mask) == apll_mask) | |
55 | return 0; /* apll already enabled */ | |
56 | ||
57 | cval &= ~apll_mask; | |
58 | cval |= apll_mask; | |
59 | cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); | |
60 | ||
81b34fbe | 61 | omap2_cm_wait_idlest(cm_idlest_pll, status_mask, |
419cc97d | 62 | OMAP24XX_CM_IDLEST_VAL, clk->name); |
49214640 PW |
63 | |
64 | /* | |
65 | * REVISIT: Should we return an error code if omap2_wait_clock_ready() | |
66 | * fails? | |
67 | */ | |
68 | return 0; | |
69 | } | |
70 | ||
71 | static int omap2_clk_apll96_enable(struct clk *clk) | |
72 | { | |
73 | return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL); | |
74 | } | |
75 | ||
76 | static int omap2_clk_apll54_enable(struct clk *clk) | |
77 | { | |
78 | return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL); | |
79 | } | |
80 | ||
81 | /* Stop APLL */ | |
82 | static void omap2_clk_apll_disable(struct clk *clk) | |
83 | { | |
84 | u32 cval; | |
85 | ||
86 | cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); | |
87 | cval &= ~(EN_APLL_LOCKED << clk->enable_bit); | |
88 | cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); | |
89 | } | |
90 | ||
91 | /* Public data */ | |
92 | ||
93 | const struct clkops clkops_apll96 = { | |
94 | .enable = omap2_clk_apll96_enable, | |
95 | .disable = omap2_clk_apll_disable, | |
96 | }; | |
97 | ||
98 | const struct clkops clkops_apll54 = { | |
99 | .enable = omap2_clk_apll54_enable, | |
100 | .disable = omap2_clk_apll_disable, | |
101 | }; | |
102 | ||
103 | /* Public functions */ | |
104 | ||
105 | u32 omap2xxx_get_apll_clkin(void) | |
106 | { | |
107 | u32 aplls, srate = 0; | |
108 | ||
109 | aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); | |
110 | aplls &= OMAP24XX_APLLS_CLKIN_MASK; | |
111 | aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; | |
112 | ||
113 | if (aplls == APLLS_CLKIN_19_2MHZ) | |
114 | srate = 19200000; | |
115 | else if (aplls == APLLS_CLKIN_13MHZ) | |
116 | srate = 13000000; | |
117 | else if (aplls == APLLS_CLKIN_12MHZ) | |
118 | srate = 12000000; | |
119 | ||
120 | return srate; | |
121 | } | |
122 |