diff options
author | Tony Lindgren <tony@atomide.com> | 2011-11-04 20:36:34 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2011-11-04 20:36:34 -0400 |
commit | 8f86f36284547fdd873769a5f190549f3ab69cca (patch) | |
tree | 06791d877fec7a0b3a6059b14ebad9e5ed77b200 /arch | |
parent | 994c0e992522c123298b4a91b72f5e67ba2d1123 (diff) | |
parent | 1194d7b82486ad967db65115559e9ad50a88ba57 (diff) |
Merge branch 'omap_clock_fixes_3.2' of git://git.pwsan.com/linux-2.6 into fixes
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/clkt_dpll.c | 51 | ||||
-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 | 32 | ||||
-rw-r--r-- | arch/arm/mach-omap2/dpll3xxx.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-omap2/dpll44xx.c | 69 |
6 files changed, 142 insertions, 28 deletions
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c index bcffee001bfa..e069a9be93df 100644 --- a/arch/arm/mach-omap2/clkt_dpll.c +++ b/arch/arm/mach-omap2/clkt_dpll.c | |||
@@ -46,10 +46,19 @@ | |||
46 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) | 46 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) |
47 | 47 | ||
48 | /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ | 48 | /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ |
49 | #define DPLL_FINT_BAND1_MIN 750000 | 49 | #define OMAP3430_DPLL_FINT_BAND1_MIN 750000 |
50 | #define DPLL_FINT_BAND1_MAX 2100000 | 50 | #define OMAP3430_DPLL_FINT_BAND1_MAX 2100000 |
51 | #define DPLL_FINT_BAND2_MIN 7500000 | 51 | #define OMAP3430_DPLL_FINT_BAND2_MIN 7500000 |
52 | #define DPLL_FINT_BAND2_MAX 21000000 | 52 | #define OMAP3430_DPLL_FINT_BAND2_MAX 21000000 |
53 | |||
54 | /* | ||
55 | * DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx. | ||
56 | * From device data manual section 4.3 "DPLL and DLL Specifications". | ||
57 | */ | ||
58 | #define OMAP3PLUS_DPLL_FINT_JTYPE_MIN 500000 | ||
59 | #define OMAP3PLUS_DPLL_FINT_JTYPE_MAX 2500000 | ||
60 | #define OMAP3PLUS_DPLL_FINT_MIN 32000 | ||
61 | #define OMAP3PLUS_DPLL_FINT_MAX 52000000 | ||
53 | 62 | ||
54 | /* _dpll_test_fint() return codes */ | 63 | /* _dpll_test_fint() return codes */ |
55 | #define DPLL_FINT_UNDERFLOW -1 | 64 | #define DPLL_FINT_UNDERFLOW -1 |
@@ -71,33 +80,43 @@ | |||
71 | static int _dpll_test_fint(struct clk *clk, u8 n) | 80 | static int _dpll_test_fint(struct clk *clk, u8 n) |
72 | { | 81 | { |
73 | struct dpll_data *dd; | 82 | struct dpll_data *dd; |
74 | long fint; | 83 | long fint, fint_min, fint_max; |
75 | int ret = 0; | 84 | int ret = 0; |
76 | 85 | ||
77 | dd = clk->dpll_data; | 86 | dd = clk->dpll_data; |
78 | 87 | ||
79 | /* DPLL divider must result in a valid jitter correction val */ | 88 | /* DPLL divider must result in a valid jitter correction val */ |
80 | fint = clk->parent->rate / n; | 89 | fint = clk->parent->rate / n; |
81 | if (fint < DPLL_FINT_BAND1_MIN) { | ||
82 | 90 | ||
91 | if (cpu_is_omap24xx()) { | ||
92 | /* Should not be called for OMAP2, so warn if it is called */ | ||
93 | WARN(1, "No fint limits available for OMAP2!\n"); | ||
94 | return DPLL_FINT_INVALID; | ||
95 | } else if (cpu_is_omap3430()) { | ||
96 | fint_min = OMAP3430_DPLL_FINT_BAND1_MIN; | ||
97 | fint_max = OMAP3430_DPLL_FINT_BAND2_MAX; | ||
98 | } else if (dd->flags & DPLL_J_TYPE) { | ||
99 | fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN; | ||
100 | fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX; | ||
101 | } else { | ||
102 | fint_min = OMAP3PLUS_DPLL_FINT_MIN; | ||
103 | fint_max = OMAP3PLUS_DPLL_FINT_MAX; | ||
104 | } | ||
105 | |||
106 | if (fint < fint_min) { | ||
83 | pr_debug("rejecting n=%d due to Fint failure, " | 107 | pr_debug("rejecting n=%d due to Fint failure, " |
84 | "lowering max_divider\n", n); | 108 | "lowering max_divider\n", n); |
85 | dd->max_divider = n; | 109 | dd->max_divider = n; |
86 | ret = DPLL_FINT_UNDERFLOW; | 110 | ret = DPLL_FINT_UNDERFLOW; |
87 | 111 | } else if (fint > fint_max) { | |
88 | } else if (fint > DPLL_FINT_BAND1_MAX && | ||
89 | fint < DPLL_FINT_BAND2_MIN) { | ||
90 | |||
91 | pr_debug("rejecting n=%d due to Fint failure\n", n); | ||
92 | ret = DPLL_FINT_INVALID; | ||
93 | |||
94 | } else if (fint > DPLL_FINT_BAND2_MAX) { | ||
95 | |||
96 | pr_debug("rejecting n=%d due to Fint failure, " | 112 | pr_debug("rejecting n=%d due to Fint failure, " |
97 | "boosting min_divider\n", n); | 113 | "boosting min_divider\n", n); |
98 | dd->min_divider = n; | 114 | dd->min_divider = n; |
99 | ret = DPLL_FINT_INVALID; | 115 | ret = DPLL_FINT_INVALID; |
100 | 116 | } else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX && | |
117 | fint < OMAP3430_DPLL_FINT_BAND2_MIN) { | ||
118 | pr_debug("rejecting n=%d due to Fint failure\n", n); | ||
119 | ret = DPLL_FINT_INVALID; | ||
101 | } | 120 | } |
102 | 121 | ||
103 | return ret; | 122 | return ret; |
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 946bf04a956d..cbf9b68d4b94 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 | ||
@@ -1195,11 +1195,25 @@ static struct clk l4_wkup_clk_mux_ck = { | |||
1195 | .recalc = &omap2_clksel_recalc, | 1195 | .recalc = &omap2_clksel_recalc, |
1196 | }; | 1196 | }; |
1197 | 1197 | ||
1198 | static const struct clksel_rate div2_2to1_rates[] = { | ||
1199 | { .div = 1, .val = 1, .flags = RATE_IN_4430 }, | ||
1200 | { .div = 2, .val = 0, .flags = RATE_IN_4430 }, | ||
1201 | { .div = 0 }, | ||
1202 | }; | ||
1203 | |||
1204 | static const struct clksel ocp_abe_iclk_div[] = { | ||
1205 | { .parent = &aess_fclk, .rates = div2_2to1_rates }, | ||
1206 | { .parent = NULL }, | ||
1207 | }; | ||
1208 | |||
1198 | static struct clk ocp_abe_iclk = { | 1209 | static struct clk ocp_abe_iclk = { |
1199 | .name = "ocp_abe_iclk", | 1210 | .name = "ocp_abe_iclk", |
1200 | .parent = &aess_fclk, | 1211 | .parent = &aess_fclk, |
1212 | .clksel = ocp_abe_iclk_div, | ||
1213 | .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL, | ||
1214 | .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK, | ||
1201 | .ops = &clkops_null, | 1215 | .ops = &clkops_null, |
1202 | .recalc = &followparent_recalc, | 1216 | .recalc = &omap2_clksel_recalc, |
1203 | }; | 1217 | }; |
1204 | 1218 | ||
1205 | static struct clk per_abe_24m_fclk = { | 1219 | static struct clk per_abe_24m_fclk = { |
@@ -1398,9 +1412,9 @@ static struct clk dss_dss_clk = { | |||
1398 | }; | 1412 | }; |
1399 | 1413 | ||
1400 | static const struct clksel_rate div3_8to32_rates[] = { | 1414 | static const struct clksel_rate div3_8to32_rates[] = { |
1401 | { .div = 8, .val = 0, .flags = RATE_IN_44XX }, | 1415 | { .div = 8, .val = 0, .flags = RATE_IN_4460 }, |
1402 | { .div = 16, .val = 1, .flags = RATE_IN_44XX }, | 1416 | { .div = 16, .val = 1, .flags = RATE_IN_4460 }, |
1403 | { .div = 32, .val = 2, .flags = RATE_IN_44XX }, | 1417 | { .div = 32, .val = 2, .flags = RATE_IN_4460 }, |
1404 | { .div = 0 }, | 1418 | { .div = 0 }, |
1405 | }; | 1419 | }; |
1406 | 1420 | ||
@@ -3403,12 +3417,12 @@ int __init omap4xxx_clk_init(void) | |||
3403 | struct omap_clk *c; | 3417 | struct omap_clk *c; |
3404 | u32 cpu_clkflg; | 3418 | u32 cpu_clkflg; |
3405 | 3419 | ||
3406 | if (cpu_is_omap44xx()) { | 3420 | if (cpu_is_omap443x()) { |
3407 | cpu_mask = RATE_IN_4430; | 3421 | cpu_mask = RATE_IN_4430; |
3408 | cpu_clkflg = CK_443X; | 3422 | cpu_clkflg = CK_443X; |
3409 | } else if (cpu_is_omap446x()) { | 3423 | } else if (cpu_is_omap446x()) { |
3410 | cpu_mask = RATE_IN_4460; | 3424 | cpu_mask = RATE_IN_4460 | RATE_IN_4430; |
3411 | cpu_clkflg = CK_446X; | 3425 | cpu_clkflg = CK_446X | CK_443X; |
3412 | } else { | 3426 | } else { |
3413 | return 0; | 3427 | return 0; |
3414 | } | 3428 | } |
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index f77022be783d..fc56745676fa 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
@@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk) | |||
390 | * propagating? | 390 | * propagating? |
391 | */ | 391 | */ |
392 | if (!r) | 392 | if (!r) |
393 | clk->rate = omap2_get_dpll_rate(clk); | 393 | clk->rate = (clk->recalc) ? clk->recalc(clk) : |
394 | omap2_get_dpll_rate(clk); | ||
394 | 395 | ||
395 | return r; | 396 | return r; |
396 | } | 397 | } |
@@ -424,6 +425,7 @@ void omap3_noncore_dpll_disable(struct clk *clk) | |||
424 | int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) | 425 | int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) |
425 | { | 426 | { |
426 | struct clk *new_parent = NULL; | 427 | struct clk *new_parent = NULL; |
428 | unsigned long hw_rate; | ||
427 | u16 freqsel = 0; | 429 | u16 freqsel = 0; |
428 | struct dpll_data *dd; | 430 | struct dpll_data *dd; |
429 | int ret; | 431 | int ret; |
@@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) | |||
435 | if (!dd) | 437 | if (!dd) |
436 | return -EINVAL; | 438 | return -EINVAL; |
437 | 439 | ||
438 | if (rate == omap2_get_dpll_rate(clk)) | 440 | hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk); |
441 | if (rate == hw_rate) | ||
439 | return 0; | 442 | return 0; |
440 | 443 | ||
441 | /* | 444 | /* |
@@ -455,7 +458,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate) | |||
455 | new_parent = dd->clk_bypass; | 458 | new_parent = dd->clk_bypass; |
456 | } else { | 459 | } else { |
457 | if (dd->last_rounded_rate != rate) | 460 | if (dd->last_rounded_rate != rate) |
458 | omap2_dpll_round_rate(clk, rate); | 461 | rate = clk->round_rate(clk, rate); |
459 | 462 | ||
460 | if (dd->last_rounded_rate == 0) | 463 | if (dd->last_rounded_rate == 0) |
461 | return -EINVAL; | 464 | return -EINVAL; |
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 | } | ||