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 | ||
41 | /* Private functions */ | |
42 | ||
43 | /* Enable an APLL if off */ | |
44 | static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask) | |
45 | { | |
46 | u32 cval, apll_mask; | |
47 | ||
48 | apll_mask = EN_APLL_LOCKED << clk->enable_bit; | |
49 | ||
50 | cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); | |
51 | ||
52 | if ((cval & apll_mask) == apll_mask) | |
53 | return 0; /* apll already enabled */ | |
54 | ||
55 | cval &= ~apll_mask; | |
56 | cval |= apll_mask; | |
57 | cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); | |
58 | ||
59 | omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), status_mask, | |
60 | clk->name); | |
61 | ||
62 | /* | |
63 | * REVISIT: Should we return an error code if omap2_wait_clock_ready() | |
64 | * fails? | |
65 | */ | |
66 | return 0; | |
67 | } | |
68 | ||
69 | static int omap2_clk_apll96_enable(struct clk *clk) | |
70 | { | |
71 | return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL); | |
72 | } | |
73 | ||
74 | static int omap2_clk_apll54_enable(struct clk *clk) | |
75 | { | |
76 | return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL); | |
77 | } | |
78 | ||
79 | /* Stop APLL */ | |
80 | static void omap2_clk_apll_disable(struct clk *clk) | |
81 | { | |
82 | u32 cval; | |
83 | ||
84 | cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN); | |
85 | cval &= ~(EN_APLL_LOCKED << clk->enable_bit); | |
86 | cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN); | |
87 | } | |
88 | ||
89 | /* Public data */ | |
90 | ||
91 | const struct clkops clkops_apll96 = { | |
92 | .enable = omap2_clk_apll96_enable, | |
93 | .disable = omap2_clk_apll_disable, | |
94 | }; | |
95 | ||
96 | const struct clkops clkops_apll54 = { | |
97 | .enable = omap2_clk_apll54_enable, | |
98 | .disable = omap2_clk_apll_disable, | |
99 | }; | |
100 | ||
101 | /* Public functions */ | |
102 | ||
103 | u32 omap2xxx_get_apll_clkin(void) | |
104 | { | |
105 | u32 aplls, srate = 0; | |
106 | ||
107 | aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); | |
108 | aplls &= OMAP24XX_APLLS_CLKIN_MASK; | |
109 | aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; | |
110 | ||
111 | if (aplls == APLLS_CLKIN_19_2MHZ) | |
112 | srate = 19200000; | |
113 | else if (aplls == APLLS_CLKIN_13MHZ) | |
114 | srate = 13000000; | |
115 | else if (aplls == APLLS_CLKIN_12MHZ) | |
116 | srate = 12000000; | |
117 | ||
118 | return srate; | |
119 | } | |
120 |