diff options
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.h | 5 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/clock.h | 1 |
4 files changed, 72 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 76e20bcc4e8a..752e34787f21 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -58,12 +58,68 @@ | |||
58 | #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ | 58 | #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ |
59 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) | 59 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) |
60 | 60 | ||
61 | /* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */ | ||
62 | #define DPLL_FINT_BAND1_MIN 750000 | ||
63 | #define DPLL_FINT_BAND1_MAX 2100000 | ||
64 | #define DPLL_FINT_BAND2_MIN 7500000 | ||
65 | #define DPLL_FINT_BAND2_MAX 21000000 | ||
66 | |||
67 | /* _dpll_test_fint() return codes */ | ||
68 | #define DPLL_FINT_UNDERFLOW -1 | ||
69 | #define DPLL_FINT_INVALID -2 | ||
70 | |||
61 | u8 cpu_mask; | 71 | u8 cpu_mask; |
62 | 72 | ||
63 | /*------------------------------------------------------------------------- | 73 | /*------------------------------------------------------------------------- |
64 | * OMAP2/3 specific clock functions | 74 | * OMAP2/3 specific clock functions |
65 | *-------------------------------------------------------------------------*/ | 75 | *-------------------------------------------------------------------------*/ |
66 | 76 | ||
77 | /* | ||
78 | * _dpll_test_fint - test whether an Fint value is valid for the DPLL | ||
79 | * @clk: DPLL struct clk to test | ||
80 | * @n: divider value (N) to test | ||
81 | * | ||
82 | * Tests whether a particular divider @n will result in a valid DPLL | ||
83 | * internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter | ||
84 | * Correction". Returns 0 if OK, -1 if the enclosing loop can terminate | ||
85 | * (assuming that it is counting N upwards), or -2 if the enclosing loop | ||
86 | * should skip to the next iteration (again assuming N is increasing). | ||
87 | */ | ||
88 | static int _dpll_test_fint(struct clk *clk, u8 n) | ||
89 | { | ||
90 | struct dpll_data *dd; | ||
91 | long fint; | ||
92 | int ret = 0; | ||
93 | |||
94 | dd = clk->dpll_data; | ||
95 | |||
96 | /* DPLL divider must result in a valid jitter correction val */ | ||
97 | fint = clk->parent->rate / (n + 1); | ||
98 | if (fint < DPLL_FINT_BAND1_MIN) { | ||
99 | |||
100 | pr_debug("rejecting n=%d due to Fint failure, " | ||
101 | "lowering max_divider\n", n); | ||
102 | dd->max_divider = n; | ||
103 | ret = DPLL_FINT_UNDERFLOW; | ||
104 | |||
105 | } else if (fint > DPLL_FINT_BAND1_MAX && | ||
106 | fint < DPLL_FINT_BAND2_MIN) { | ||
107 | |||
108 | pr_debug("rejecting n=%d due to Fint failure\n", n); | ||
109 | ret = DPLL_FINT_INVALID; | ||
110 | |||
111 | } else if (fint > DPLL_FINT_BAND2_MAX) { | ||
112 | |||
113 | pr_debug("rejecting n=%d due to Fint failure, " | ||
114 | "boosting min_divider\n", n); | ||
115 | dd->min_divider = n; | ||
116 | ret = DPLL_FINT_INVALID; | ||
117 | |||
118 | } | ||
119 | |||
120 | return ret; | ||
121 | } | ||
122 | |||
67 | /** | 123 | /** |
68 | * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk | 124 | * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk |
69 | * @clk: OMAP clock struct ptr to use | 125 | * @clk: OMAP clock struct ptr to use |
@@ -892,7 +948,14 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
892 | 948 | ||
893 | dd->last_rounded_rate = 0; | 949 | dd->last_rounded_rate = 0; |
894 | 950 | ||
895 | for (n = DPLL_MIN_DIVIDER; n <= dd->max_divider; n++) { | 951 | for (n = dd->min_divider; n <= dd->max_divider; n++) { |
952 | |||
953 | /* Is the (input clk, divider) pair valid for the DPLL? */ | ||
954 | r = _dpll_test_fint(clk, n); | ||
955 | if (r == DPLL_FINT_UNDERFLOW) | ||
956 | break; | ||
957 | else if (r == DPLL_FINT_INVALID) | ||
958 | continue; | ||
896 | 959 | ||
897 | /* Compute the scaled DPLL multiplier, based on the divider */ | 960 | /* Compute the scaled DPLL multiplier, based on the divider */ |
898 | m = scaled_rt_rp * n; | 961 | m = scaled_rt_rp * n; |
@@ -926,7 +989,7 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | |||
926 | pr_debug("clock: found new least error %d\n", min_e); | 989 | pr_debug("clock: found new least error %d\n", min_e); |
927 | 990 | ||
928 | /* We found good settings -- bail out now */ | 991 | /* We found good settings -- bail out now */ |
929 | if (min_e <= clk->dpll_data->rate_tolerance) | 992 | if (min_e <= dd->rate_tolerance) |
930 | break; | 993 | break; |
931 | } | 994 | } |
932 | } | 995 | } |
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 32dd8573e56b..7731ab6acd18 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h | |||
@@ -666,6 +666,7 @@ static struct dpll_data dpll_dd = { | |||
666 | .mult_mask = OMAP24XX_DPLL_MULT_MASK, | 666 | .mult_mask = OMAP24XX_DPLL_MULT_MASK, |
667 | .div1_mask = OMAP24XX_DPLL_DIV_MASK, | 667 | .div1_mask = OMAP24XX_DPLL_DIV_MASK, |
668 | .max_multiplier = 1024, | 668 | .max_multiplier = 1024, |
669 | .min_divider = 1, | ||
669 | .max_divider = 16, | 670 | .max_divider = 16, |
670 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 671 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
671 | }; | 672 | }; |
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 7ee131202625..aadd296c05a2 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h | |||
@@ -268,6 +268,7 @@ static struct dpll_data dpll1_dd = { | |||
268 | .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), | 268 | .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), |
269 | .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, | 269 | .idlest_mask = OMAP3430_ST_MPU_CLK_MASK, |
270 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | 270 | .max_multiplier = OMAP3_MAX_DPLL_MULT, |
271 | .min_divider = 1, | ||
271 | .max_divider = OMAP3_MAX_DPLL_DIV, | 272 | .max_divider = OMAP3_MAX_DPLL_DIV, |
272 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 273 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
273 | }; | 274 | }; |
@@ -341,6 +342,7 @@ static struct dpll_data dpll2_dd = { | |||
341 | .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), | 342 | .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), |
342 | .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, | 343 | .idlest_mask = OMAP3430_ST_IVA2_CLK_MASK, |
343 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | 344 | .max_multiplier = OMAP3_MAX_DPLL_MULT, |
345 | .min_divider = 1, | ||
344 | .max_divider = OMAP3_MAX_DPLL_DIV, | 346 | .max_divider = OMAP3_MAX_DPLL_DIV, |
345 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 347 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
346 | }; | 348 | }; |
@@ -400,6 +402,7 @@ static struct dpll_data dpll3_dd = { | |||
400 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), | 402 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), |
401 | .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, | 403 | .idlest_mask = OMAP3430_ST_CORE_CLK_MASK, |
402 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | 404 | .max_multiplier = OMAP3_MAX_DPLL_MULT, |
405 | .min_divider = 1, | ||
403 | .max_divider = OMAP3_MAX_DPLL_DIV, | 406 | .max_divider = OMAP3_MAX_DPLL_DIV, |
404 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 407 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
405 | }; | 408 | }; |
@@ -591,6 +594,7 @@ static struct dpll_data dpll4_dd = { | |||
591 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), | 594 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), |
592 | .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, | 595 | .idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK, |
593 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | 596 | .max_multiplier = OMAP3_MAX_DPLL_MULT, |
597 | .min_divider = 1, | ||
594 | .max_divider = OMAP3_MAX_DPLL_DIV, | 598 | .max_divider = OMAP3_MAX_DPLL_DIV, |
595 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 599 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
596 | }; | 600 | }; |
@@ -930,6 +934,7 @@ static struct dpll_data dpll5_dd = { | |||
930 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), | 934 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), |
931 | .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, | 935 | .idlest_mask = OMAP3430ES2_ST_PERIPH2_CLK_MASK, |
932 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | 936 | .max_multiplier = OMAP3_MAX_DPLL_MULT, |
937 | .min_divider = 1, | ||
933 | .max_divider = OMAP3_MAX_DPLL_DIV, | 938 | .max_divider = OMAP3_MAX_DPLL_DIV, |
934 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | 939 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE |
935 | }; | 940 | }; |
diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 611df52a3242..cd69111cd33f 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h | |||
@@ -43,6 +43,7 @@ struct dpll_data { | |||
43 | unsigned long last_rounded_rate; | 43 | unsigned long last_rounded_rate; |
44 | u16 last_rounded_m; | 44 | u16 last_rounded_m; |
45 | u8 last_rounded_n; | 45 | u8 last_rounded_n; |
46 | u8 min_divider; | ||
46 | u8 max_divider; | 47 | u8 max_divider; |
47 | u32 max_tolerance; | 48 | u32 max_tolerance; |
48 | u16 max_multiplier; | 49 | u16 max_multiplier; |