Commit a1900f2efe2d75e0fe5b871421a2f2de2fa68b4e
Committed by
Paul Walmsley
1 parent
be73246058
Exists in
master
and in
6 other branches
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>
Showing 4 changed files with 80 additions and 2 deletions Side-by-side Diff
arch/arm/mach-omap2/clock.h
... | ... | @@ -66,6 +66,8 @@ |
66 | 66 | int omap4_dpllmx_gatectrl_read(struct clk *clk); |
67 | 67 | void omap4_dpllmx_allow_gatectrl(struct clk *clk); |
68 | 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 | 72 | #ifdef CONFIG_OMAP_RESET_CLOCKS |
71 | 73 | void omap2_clk_disable_unused(struct clk *clk); |
arch/arm/mach-omap2/clock44xx.h
... | ... | @@ -8,6 +8,13 @@ |
8 | 8 | #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H |
9 | 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 | 18 | int omap4xxx_clk_init(void); |
12 | 19 | |
13 | 20 | #endif |
arch/arm/mach-omap2/clock44xx_data.c
... | ... | @@ -270,8 +270,8 @@ |
270 | 270 | .dpll_data = &dpll_abe_dd, |
271 | 271 | .init = &omap2_init_dpll_parent, |
272 | 272 | .ops = &clkops_omap3_noncore_dpll_ops, |
273 | - .recalc = &omap3_dpll_recalc, | |
274 | - .round_rate = &omap2_dpll_round_rate, | |
273 | + .recalc = &omap4_dpll_regm4xen_recalc, | |
274 | + .round_rate = &omap4_dpll_regm4xen_round_rate, | |
275 | 275 | .set_rate = &omap3_noncore_dpll_set_rate, |
276 | 276 | }; |
277 | 277 |
arch/arm/mach-omap2/dpll44xx.c
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | #include <plat/clock.h> |
20 | 20 | |
21 | 21 | #include "clock.h" |
22 | +#include "clock44xx.h" | |
22 | 23 | #include "cm-regbits-44xx.h" |
23 | 24 | |
24 | 25 | /* Supported only on OMAP4 */ |
... | ... | @@ -81,4 +82,73 @@ |
81 | 82 | .allow_idle = omap4_dpllmx_allow_gatectrl, |
82 | 83 | .deny_idle = omap4_dpllmx_deny_gatectrl, |
83 | 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 | +} |