diff options
author | Mike Turquette <mturquette@ti.com> | 2011-10-07 02:52:58 -0400 |
---|---|---|
committer | Paul Walmsley <paul@pwsan.com> | 2011-10-07 02:52:58 -0400 |
commit | a1900f2efe2d75e0fe5b871421a2f2de2fa68b4e (patch) | |
tree | ec96f1f2a34d81bc0fa561d3ff404fbd9059531d /arch/arm | |
parent | be73246058737beec52ae232bcab7776332a9e06 (diff) |
ARM: OMAP4: clock: round_rate and recalc functions for DPLL_ABE
OMAP4 DPLL_ABE can enable a 4X multipler on top of the normal MN multipler
and divider. This is achieved by setting CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN
bit in CKGEN module of CM1. From the OMAP4 TRM:
Fdpll = Fref x 2 x (4 x M/(N+1)) in case REGM4XEN bit field is set (only
applicable to DPLL_ABE).
Add new round_rate() and recalc() functions for OMAP4, that check the
setting of REGM4XEN bit and handle this appropriately. The new functions
are a simple wrapper on top of the existing omap2_dpll_round_rate() and
omap2_dpll_get_rate() functions to handle the REGM4XEN bit.
The REGM4XEN bit is only implemented for the ABE DPLL on OMAP4 and so
only dpll_abe_ck uses omap4_dpll_regm4xen_round_rate() and
omap4_dpll_regm4xen_recalc() functions.
Signed-off-by: Mike Turquette <mturquette@ti.com>
Tested-by: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
[paul@pwsan.com: fixed attempt to return a negative from a fn returning
unsigned; pass along errors from omap2_dpll_round_rate();
added documentation; added Jon's S-o-b]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx_data.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/dpll44xx.c | 69 |
4 files changed, 80 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 48ac568881bd..2311bc217226 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -66,6 +66,8 @@ void omap3_noncore_dpll_disable(struct clk *clk); | |||
66 | int omap4_dpllmx_gatectrl_read(struct clk *clk); | 66 | int omap4_dpllmx_gatectrl_read(struct clk *clk); |
67 | void omap4_dpllmx_allow_gatectrl(struct clk *clk); | 67 | void omap4_dpllmx_allow_gatectrl(struct clk *clk); |
68 | void omap4_dpllmx_deny_gatectrl(struct clk *clk); | 68 | void omap4_dpllmx_deny_gatectrl(struct clk *clk); |
69 | long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate); | ||
70 | unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk); | ||
69 | 71 | ||
70 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 72 | #ifdef CONFIG_OMAP_RESET_CLOCKS |
71 | void omap2_clk_disable_unused(struct clk *clk); | 73 | void omap2_clk_disable_unused(struct clk *clk); |
diff --git a/arch/arm/mach-omap2/clock44xx.h b/arch/arm/mach-omap2/clock44xx.h index 7ceb870e7ab8..287a46f78d97 100644 --- a/arch/arm/mach-omap2/clock44xx.h +++ b/arch/arm/mach-omap2/clock44xx.h | |||
@@ -8,6 +8,13 @@ | |||
8 | #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H | 8 | #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H |
9 | #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H | 9 | #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H |
10 | 10 | ||
11 | /* | ||
12 | * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is | ||
13 | * set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM | ||
14 | * vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters") | ||
15 | */ | ||
16 | #define OMAP4430_REGM4XEN_MULT 4 | ||
17 | |||
11 | int omap4xxx_clk_init(void); | 18 | int omap4xxx_clk_init(void); |
12 | 19 | ||
13 | #endif | 20 | #endif |
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index c0b6fbda3408..c98c0a22c188 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c | |||
@@ -270,8 +270,8 @@ static struct clk dpll_abe_ck = { | |||
270 | .dpll_data = &dpll_abe_dd, | 270 | .dpll_data = &dpll_abe_dd, |
271 | .init = &omap2_init_dpll_parent, | 271 | .init = &omap2_init_dpll_parent, |
272 | .ops = &clkops_omap3_noncore_dpll_ops, | 272 | .ops = &clkops_omap3_noncore_dpll_ops, |
273 | .recalc = &omap3_dpll_recalc, | 273 | .recalc = &omap4_dpll_regm4xen_recalc, |
274 | .round_rate = &omap2_dpll_round_rate, | 274 | .round_rate = &omap4_dpll_regm4xen_round_rate, |
275 | .set_rate = &omap3_noncore_dpll_set_rate, | 275 | .set_rate = &omap3_noncore_dpll_set_rate, |
276 | }; | 276 | }; |
277 | 277 | ||
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 4e4da6160d05..9c6a296b3dc3 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <plat/clock.h> | 19 | #include <plat/clock.h> |
20 | 20 | ||
21 | #include "clock.h" | 21 | #include "clock.h" |
22 | #include "clock44xx.h" | ||
22 | #include "cm-regbits-44xx.h" | 23 | #include "cm-regbits-44xx.h" |
23 | 24 | ||
24 | /* Supported only on OMAP4 */ | 25 | /* Supported only on OMAP4 */ |
@@ -82,3 +83,71 @@ const struct clkops clkops_omap4_dpllmx_ops = { | |||
82 | .deny_idle = omap4_dpllmx_deny_gatectrl, | 83 | .deny_idle = omap4_dpllmx_deny_gatectrl, |
83 | }; | 84 | }; |
84 | 85 | ||
86 | /** | ||
87 | * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit | ||
88 | * @clk: struct clk * of the DPLL to compute the rate for | ||
89 | * | ||
90 | * Compute the output rate for the OMAP4 DPLL represented by @clk. | ||
91 | * Takes the REGM4XEN bit into consideration, which is needed for the | ||
92 | * OMAP4 ABE DPLL. Returns the DPLL's output rate (before M-dividers) | ||
93 | * upon success, or 0 upon error. | ||
94 | */ | ||
95 | unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk) | ||
96 | { | ||
97 | u32 v; | ||
98 | unsigned long rate; | ||
99 | struct dpll_data *dd; | ||
100 | |||
101 | if (!clk || !clk->dpll_data) | ||
102 | return 0; | ||
103 | |||
104 | dd = clk->dpll_data; | ||
105 | |||
106 | rate = omap2_get_dpll_rate(clk); | ||
107 | |||
108 | /* regm4xen adds a multiplier of 4 to DPLL calculations */ | ||
109 | v = __raw_readl(dd->control_reg); | ||
110 | if (v & OMAP4430_DPLL_REGM4XEN_MASK) | ||
111 | rate *= OMAP4430_REGM4XEN_MULT; | ||
112 | |||
113 | return rate; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit | ||
118 | * @clk: struct clk * of the DPLL to round a rate for | ||
119 | * @target_rate: the desired rate of the DPLL | ||
120 | * | ||
121 | * Compute the rate that would be programmed into the DPLL hardware | ||
122 | * for @clk if set_rate() were to be provided with the rate | ||
123 | * @target_rate. Takes the REGM4XEN bit into consideration, which is | ||
124 | * needed for the OMAP4 ABE DPLL. Returns the rounded rate (before | ||
125 | * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or | ||
126 | * ~0 if an error occurred in omap2_dpll_round_rate(). | ||
127 | */ | ||
128 | long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate) | ||
129 | { | ||
130 | u32 v; | ||
131 | struct dpll_data *dd; | ||
132 | long r; | ||
133 | |||
134 | if (!clk || !clk->dpll_data) | ||
135 | return -EINVAL; | ||
136 | |||
137 | dd = clk->dpll_data; | ||
138 | |||
139 | /* regm4xen adds a multiplier of 4 to DPLL calculations */ | ||
140 | v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK; | ||
141 | |||
142 | if (v) | ||
143 | target_rate = target_rate / OMAP4430_REGM4XEN_MULT; | ||
144 | |||
145 | r = omap2_dpll_round_rate(clk, target_rate); | ||
146 | if (r == ~0) | ||
147 | return r; | ||
148 | |||
149 | if (v) | ||
150 | clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; | ||
151 | |||
152 | return clk->dpll_data->last_rounded_rate; | ||
153 | } | ||