aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorMike Turquette <mturquette@ti.com>2011-10-07 02:52:58 -0400
committerPaul Walmsley <paul@pwsan.com>2011-10-07 02:52:58 -0400
commita1900f2efe2d75e0fe5b871421a2f2de2fa68b4e (patch)
treeec96f1f2a34d81bc0fa561d3ff404fbd9059531d /arch/arm
parentbe73246058737beec52ae232bcab7776332a9e06 (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.h2
-rw-r--r--arch/arm/mach-omap2/clock44xx.h7
-rw-r--r--arch/arm/mach-omap2/clock44xx_data.c4
-rw-r--r--arch/arm/mach-omap2/dpll44xx.c69
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);
66int omap4_dpllmx_gatectrl_read(struct clk *clk); 66int omap4_dpllmx_gatectrl_read(struct clk *clk);
67void omap4_dpllmx_allow_gatectrl(struct clk *clk); 67void omap4_dpllmx_allow_gatectrl(struct clk *clk);
68void omap4_dpllmx_deny_gatectrl(struct clk *clk); 68void omap4_dpllmx_deny_gatectrl(struct clk *clk);
69long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
70unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
69 71
70#ifdef CONFIG_OMAP_RESET_CLOCKS 72#ifdef CONFIG_OMAP_RESET_CLOCKS
71void omap2_clk_disable_unused(struct clk *clk); 73void 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
11int omap4xxx_clk_init(void); 18int 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 */
95unsigned 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 */
128long 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}