diff options
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 198 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock24xx.h | 17 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock34xx.h | 36 | ||||
-rw-r--r-- | include/asm-arm/arch-omap/clock.h | 9 |
6 files changed, 258 insertions, 19 deletions
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 0243480e8bfe..15675bce8012 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -41,6 +41,24 @@ | |||
41 | 41 | ||
42 | #define MAX_CLOCK_ENABLE_WAIT 100000 | 42 | #define MAX_CLOCK_ENABLE_WAIT 100000 |
43 | 43 | ||
44 | /* DPLL rate rounding: minimum DPLL multiplier, divider values */ | ||
45 | #define DPLL_MIN_MULTIPLIER 1 | ||
46 | #define DPLL_MIN_DIVIDER 1 | ||
47 | |||
48 | /* Possible error results from _dpll_test_mult */ | ||
49 | #define DPLL_MULT_UNDERFLOW (1 << 0) | ||
50 | |||
51 | /* | ||
52 | * Scale factor to mitigate roundoff errors in DPLL rate rounding. | ||
53 | * The higher the scale factor, the greater the risk of arithmetic overflow, | ||
54 | * but the closer the rounded rate to the target rate. DPLL_SCALE_FACTOR | ||
55 | * must be a power of DPLL_SCALE_BASE. | ||
56 | */ | ||
57 | #define DPLL_SCALE_FACTOR 64 | ||
58 | #define DPLL_SCALE_BASE 2 | ||
59 | #define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \ | ||
60 | (DPLL_SCALE_FACTOR / DPLL_SCALE_BASE)) | ||
61 | |||
44 | u8 cpu_mask; | 62 | u8 cpu_mask; |
45 | 63 | ||
46 | /*------------------------------------------------------------------------- | 64 | /*------------------------------------------------------------------------- |
@@ -95,7 +113,7 @@ u32 omap2_get_dpll_rate(struct clk *clk) | |||
95 | { | 113 | { |
96 | long long dpll_clk; | 114 | long long dpll_clk; |
97 | u32 dpll_mult, dpll_div, dpll; | 115 | u32 dpll_mult, dpll_div, dpll; |
98 | const struct dpll_data *dd; | 116 | struct dpll_data *dd; |
99 | 117 | ||
100 | dd = clk->dpll_data; | 118 | dd = clk->dpll_data; |
101 | /* REVISIT: What do we return on error? */ | 119 | /* REVISIT: What do we return on error? */ |
@@ -724,6 +742,184 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) | |||
724 | return 0; | 742 | return 0; |
725 | } | 743 | } |
726 | 744 | ||
745 | /* DPLL rate rounding code */ | ||
746 | |||
747 | /** | ||
748 | * omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding | ||
749 | * @clk: struct clk * of the DPLL | ||
750 | * @tolerance: maximum rate error tolerance | ||
751 | * | ||
752 | * Set the maximum DPLL rate error tolerance for the rate rounding | ||
753 | * algorithm. The rate tolerance is an attempt to balance DPLL power | ||
754 | * saving (the least divider value "n") vs. rate fidelity (the least | ||
755 | * difference between the desired DPLL target rate and the rounded | ||
756 | * rate out of the algorithm). So, increasing the tolerance is likely | ||
757 | * to decrease DPLL power consumption and increase DPLL rate error. | ||
758 | * Returns -EINVAL if provided a null clock ptr or a clk that is not a | ||
759 | * DPLL; or 0 upon success. | ||
760 | */ | ||
761 | int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance) | ||
762 | { | ||
763 | if (!clk || !clk->dpll_data) | ||
764 | return -EINVAL; | ||
765 | |||
766 | clk->dpll_data->rate_tolerance = tolerance; | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static unsigned long _dpll_compute_new_rate(unsigned long parent_rate, unsigned int m, unsigned int n) | ||
772 | { | ||
773 | unsigned long long num; | ||
774 | |||
775 | num = (unsigned long long)parent_rate * m; | ||
776 | do_div(num, n); | ||
777 | return num; | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * _dpll_test_mult - test a DPLL multiplier value | ||
782 | * @m: pointer to the DPLL m (multiplier) value under test | ||
783 | * @n: current DPLL n (divider) value under test | ||
784 | * @new_rate: pointer to storage for the resulting rounded rate | ||
785 | * @target_rate: the desired DPLL rate | ||
786 | * @parent_rate: the DPLL's parent clock rate | ||
787 | * | ||
788 | * This code tests a DPLL multiplier value, ensuring that the | ||
789 | * resulting rate will not be higher than the target_rate, and that | ||
790 | * the multiplier value itself is valid for the DPLL. Initially, the | ||
791 | * integer pointed to by the m argument should be prescaled by | ||
792 | * multiplying by DPLL_SCALE_FACTOR. The code will replace this with | ||
793 | * a non-scaled m upon return. This non-scaled m will result in a | ||
794 | * new_rate as close as possible to target_rate (but not greater than | ||
795 | * target_rate) given the current (parent_rate, n, prescaled m) | ||
796 | * triple. Returns DPLL_MULT_UNDERFLOW in the event that the | ||
797 | * non-scaled m attempted to underflow, which can allow the calling | ||
798 | * function to bail out early; or 0 upon success. | ||
799 | */ | ||
800 | static int _dpll_test_mult(int *m, int n, unsigned long *new_rate, | ||
801 | unsigned long target_rate, | ||
802 | unsigned long parent_rate) | ||
803 | { | ||
804 | int flags = 0, carry = 0; | ||
805 | |||
806 | /* Unscale m and round if necessary */ | ||
807 | if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL) | ||
808 | carry = 1; | ||
809 | *m = (*m / DPLL_SCALE_FACTOR) + carry; | ||
810 | |||
811 | /* | ||
812 | * The new rate must be <= the target rate to avoid programming | ||
813 | * a rate that is impossible for the hardware to handle | ||
814 | */ | ||
815 | *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); | ||
816 | if (*new_rate > target_rate) { | ||
817 | (*m)--; | ||
818 | *new_rate = 0; | ||
819 | } | ||
820 | |||
821 | /* Guard against m underflow */ | ||
822 | if (*m < DPLL_MIN_MULTIPLIER) { | ||
823 | *m = DPLL_MIN_MULTIPLIER; | ||
824 | *new_rate = 0; | ||
825 | flags = DPLL_MULT_UNDERFLOW; | ||
826 | } | ||
827 | |||
828 | if (*new_rate == 0) | ||
829 | *new_rate = _dpll_compute_new_rate(parent_rate, *m, n); | ||
830 | |||
831 | return flags; | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * omap2_dpll_round_rate - round a target rate for an OMAP DPLL | ||
836 | * @clk: struct clk * for a DPLL | ||
837 | * @target_rate: desired DPLL clock rate | ||
838 | * | ||
839 | * Given a DPLL, a desired target rate, and a rate tolerance, round | ||
840 | * the target rate to a possible, programmable rate for this DPLL. | ||
841 | * Rate tolerance is assumed to be set by the caller before this | ||
842 | * function is called. Attempts to select the minimum possible n | ||
843 | * within the tolerance to reduce power consumption. Stores the | ||
844 | * computed (m, n) in the DPLL's dpll_data structure so set_rate() | ||
845 | * will not need to call this (expensive) function again. Returns ~0 | ||
846 | * if the target rate cannot be rounded, either because the rate is | ||
847 | * too low or because the rate tolerance is set too tightly; or the | ||
848 | * rounded rate upon success. | ||
849 | */ | ||
850 | long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate) | ||
851 | { | ||
852 | int m, n, r, e, scaled_max_m; | ||
853 | unsigned long scaled_rt_rp, new_rate; | ||
854 | int min_e = -1, min_e_m = -1, min_e_n = -1; | ||
855 | |||
856 | if (!clk || !clk->dpll_data) | ||
857 | return ~0; | ||
858 | |||
859 | pr_debug("clock: starting DPLL round_rate for clock %s, target rate " | ||
860 | "%ld\n", clk->name, target_rate); | ||
861 | |||
862 | scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR); | ||
863 | scaled_max_m = clk->dpll_data->max_multiplier * DPLL_SCALE_FACTOR; | ||
864 | |||
865 | clk->dpll_data->last_rounded_rate = 0; | ||
866 | |||
867 | for (n = clk->dpll_data->max_divider; n >= DPLL_MIN_DIVIDER; n--) { | ||
868 | |||
869 | /* Compute the scaled DPLL multiplier, based on the divider */ | ||
870 | m = scaled_rt_rp * n; | ||
871 | |||
872 | /* | ||
873 | * Since we're counting n down, a m overflow means we can | ||
874 | * can immediately skip to the next n | ||
875 | */ | ||
876 | if (m > scaled_max_m) | ||
877 | continue; | ||
878 | |||
879 | r = _dpll_test_mult(&m, n, &new_rate, target_rate, | ||
880 | clk->parent->rate); | ||
881 | |||
882 | e = target_rate - new_rate; | ||
883 | pr_debug("clock: n = %d: m = %d: rate error is %d " | ||
884 | "(new_rate = %ld)\n", n, m, e, new_rate); | ||
885 | |||
886 | if (min_e == -1 || | ||
887 | min_e >= (int)(abs(e) - clk->dpll_data->rate_tolerance)) { | ||
888 | min_e = e; | ||
889 | min_e_m = m; | ||
890 | min_e_n = n; | ||
891 | |||
892 | pr_debug("clock: found new least error %d\n", min_e); | ||
893 | } | ||
894 | |||
895 | /* | ||
896 | * Since we're counting n down, a m underflow means we | ||
897 | * can bail out completely (since as n decreases in | ||
898 | * the next iteration, there's no way that m can | ||
899 | * increase beyond the current m) | ||
900 | */ | ||
901 | if (r & DPLL_MULT_UNDERFLOW) | ||
902 | break; | ||
903 | } | ||
904 | |||
905 | if (min_e < 0) { | ||
906 | pr_debug("clock: error: target rate or tolerance too low\n"); | ||
907 | return ~0; | ||
908 | } | ||
909 | |||
910 | clk->dpll_data->last_rounded_m = min_e_m; | ||
911 | clk->dpll_data->last_rounded_n = min_e_n; | ||
912 | clk->dpll_data->last_rounded_rate = | ||
913 | _dpll_compute_new_rate(clk->parent->rate, min_e_m, min_e_n); | ||
914 | |||
915 | pr_debug("clock: final least error: e = %d, m = %d, n = %d\n", | ||
916 | min_e, min_e_m, min_e_n); | ||
917 | pr_debug("clock: final rate: %ld (target rate: %ld)\n", | ||
918 | clk->dpll_data->last_rounded_rate, target_rate); | ||
919 | |||
920 | return clk->dpll_data->last_rounded_rate; | ||
921 | } | ||
922 | |||
727 | /*------------------------------------------------------------------------- | 923 | /*------------------------------------------------------------------------- |
728 | * Omap2 clock reset and init functions | 924 | * Omap2 clock reset and init functions |
729 | *-------------------------------------------------------------------------*/ | 925 | *-------------------------------------------------------------------------*/ |
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index f97948548f29..3cd37cb57c5a 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -18,11 +18,16 @@ | |||
18 | 18 | ||
19 | #include <asm/arch/clock.h> | 19 | #include <asm/arch/clock.h> |
20 | 20 | ||
21 | /* The maximum error between a target DPLL rate and the rounded rate in Hz */ | ||
22 | #define DEFAULT_DPLL_RATE_TOLERANCE 50000 | ||
23 | |||
21 | int omap2_clk_enable(struct clk *clk); | 24 | int omap2_clk_enable(struct clk *clk); |
22 | void omap2_clk_disable(struct clk *clk); | 25 | void omap2_clk_disable(struct clk *clk); |
23 | long omap2_clk_round_rate(struct clk *clk, unsigned long rate); | 26 | long omap2_clk_round_rate(struct clk *clk, unsigned long rate); |
24 | int omap2_clk_set_rate(struct clk *clk, unsigned long rate); | 27 | int omap2_clk_set_rate(struct clk *clk, unsigned long rate); |
25 | int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); | 28 | int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent); |
29 | int omap2_dpll_rate_tolerance_set(struct clk *clk, unsigned int tolerance); | ||
30 | long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate); | ||
26 | 31 | ||
27 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 32 | #ifdef CONFIG_OMAP_RESET_CLOCKS |
28 | void omap2_clk_disable_unused(struct clk *clk); | 33 | void omap2_clk_disable_unused(struct clk *clk); |
diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index ece32d8acba4..aa567876651d 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c | |||
@@ -154,7 +154,7 @@ static void omap2_clk_fixed_disable(struct clk *clk) | |||
154 | * Uses the current prcm set to tell if a rate is valid. | 154 | * Uses the current prcm set to tell if a rate is valid. |
155 | * You can go slower, but not faster within a given rate set. | 155 | * You can go slower, but not faster within a given rate set. |
156 | */ | 156 | */ |
157 | static u32 omap2_dpll_round_rate(unsigned long target_rate) | 157 | long omap2_dpllcore_round_rate(unsigned long target_rate) |
158 | { | 158 | { |
159 | u32 high, low, core_clk_src; | 159 | u32 high, low, core_clk_src; |
160 | 160 | ||
@@ -183,14 +183,14 @@ static u32 omap2_dpll_round_rate(unsigned long target_rate) | |||
183 | 183 | ||
184 | } | 184 | } |
185 | 185 | ||
186 | static void omap2_dpll_recalc(struct clk *clk) | 186 | static void omap2_dpllcore_recalc(struct clk *clk) |
187 | { | 187 | { |
188 | clk->rate = omap2_get_dpll_rate_24xx(clk); | 188 | clk->rate = omap2_get_dpll_rate_24xx(clk); |
189 | 189 | ||
190 | propagate_rate(clk); | 190 | propagate_rate(clk); |
191 | } | 191 | } |
192 | 192 | ||
193 | static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate) | 193 | static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate) |
194 | { | 194 | { |
195 | u32 cur_rate, low, mult, div, valid_rate, done_rate; | 195 | u32 cur_rate, low, mult, div, valid_rate, done_rate; |
196 | u32 bypass = 0; | 196 | u32 bypass = 0; |
@@ -209,7 +209,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate) | |||
209 | } else if ((rate == (cur_rate * 2)) && (mult == 1)) { | 209 | } else if ((rate == (cur_rate * 2)) && (mult == 1)) { |
210 | omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); | 210 | omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1); |
211 | } else if (rate != cur_rate) { | 211 | } else if (rate != cur_rate) { |
212 | valid_rate = omap2_dpll_round_rate(rate); | 212 | valid_rate = omap2_dpllcore_round_rate(rate); |
213 | if (valid_rate != rate) | 213 | if (valid_rate != rate) |
214 | goto dpll_exit; | 214 | goto dpll_exit; |
215 | 215 | ||
@@ -256,7 +256,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate) | |||
256 | omap2_init_memory_params(omap2_dll_force_needed()); | 256 | omap2_init_memory_params(omap2_dll_force_needed()); |
257 | omap2_reprogram_sdrc(done_rate, 0); | 257 | omap2_reprogram_sdrc(done_rate, 0); |
258 | } | 258 | } |
259 | omap2_dpll_recalc(&dpll_ck); | 259 | omap2_dpllcore_recalc(&dpll_ck); |
260 | ret = 0; | 260 | ret = 0; |
261 | 261 | ||
262 | dpll_exit: | 262 | dpll_exit: |
@@ -383,7 +383,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate) | |||
383 | 383 | ||
384 | local_irq_restore(flags); | 384 | local_irq_restore(flags); |
385 | } | 385 | } |
386 | omap2_dpll_recalc(&dpll_ck); | 386 | omap2_dpllcore_recalc(&dpll_ck); |
387 | 387 | ||
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 06e1118ddba2..be4e25554e05 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h | |||
@@ -30,12 +30,12 @@ static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate); | |||
30 | static void omap2_sys_clk_recalc(struct clk *clk); | 30 | static void omap2_sys_clk_recalc(struct clk *clk); |
31 | static void omap2_osc_clk_recalc(struct clk *clk); | 31 | static void omap2_osc_clk_recalc(struct clk *clk); |
32 | static void omap2_sys_clk_recalc(struct clk *clk); | 32 | static void omap2_sys_clk_recalc(struct clk *clk); |
33 | static void omap2_dpll_recalc(struct clk *clk); | 33 | static void omap2_dpllcore_recalc(struct clk *clk); |
34 | static int omap2_clk_fixed_enable(struct clk *clk); | 34 | static int omap2_clk_fixed_enable(struct clk *clk); |
35 | static void omap2_clk_fixed_disable(struct clk *clk); | 35 | static void omap2_clk_fixed_disable(struct clk *clk); |
36 | static int omap2_enable_osc_ck(struct clk *clk); | 36 | static int omap2_enable_osc_ck(struct clk *clk); |
37 | static void omap2_disable_osc_ck(struct clk *clk); | 37 | static void omap2_disable_osc_ck(struct clk *clk); |
38 | static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate); | 38 | static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate); |
39 | 39 | ||
40 | /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. | 40 | /* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated. |
41 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP | 41 | * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP |
@@ -665,20 +665,27 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */ | |||
665 | * deal with this | 665 | * deal with this |
666 | */ | 666 | */ |
667 | 667 | ||
668 | static const struct dpll_data dpll_dd = { | 668 | static struct dpll_data dpll_dd = { |
669 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), | 669 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), |
670 | .mult_mask = OMAP24XX_DPLL_MULT_MASK, | 670 | .mult_mask = OMAP24XX_DPLL_MULT_MASK, |
671 | .div1_mask = OMAP24XX_DPLL_DIV_MASK, | 671 | .div1_mask = OMAP24XX_DPLL_DIV_MASK, |
672 | .max_multiplier = 1024, | ||
673 | .max_divider = 16, | ||
674 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
672 | }; | 675 | }; |
673 | 676 | ||
677 | /* | ||
678 | * XXX Cannot add round_rate here yet, as this is still a composite clock, | ||
679 | * not just a DPLL | ||
680 | */ | ||
674 | static struct clk dpll_ck = { | 681 | static struct clk dpll_ck = { |
675 | .name = "dpll_ck", | 682 | .name = "dpll_ck", |
676 | .parent = &sys_ck, /* Can be func_32k also */ | 683 | .parent = &sys_ck, /* Can be func_32k also */ |
677 | .dpll_data = &dpll_dd, | 684 | .dpll_data = &dpll_dd, |
678 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | 685 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | |
679 | RATE_PROPAGATES | ALWAYS_ENABLED, | 686 | RATE_PROPAGATES | ALWAYS_ENABLED, |
680 | .recalc = &omap2_dpll_recalc, | 687 | .recalc = &omap2_dpllcore_recalc, |
681 | .set_rate = &omap2_reprogram_dpll, | 688 | .set_rate = &omap2_reprogram_dpllcore, |
682 | }; | 689 | }; |
683 | 690 | ||
684 | static struct clk apll96_ck = { | 691 | static struct clk apll96_ck = { |
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index e349d48ee807..05757eb032bc 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h | |||
@@ -35,6 +35,10 @@ static u32 omap3_dpll_autoidle_read(struct clk *clk); | |||
35 | static int omap3_noncore_dpll_enable(struct clk *clk); | 35 | static int omap3_noncore_dpll_enable(struct clk *clk); |
36 | static void omap3_noncore_dpll_disable(struct clk *clk); | 36 | static void omap3_noncore_dpll_disable(struct clk *clk); |
37 | 37 | ||
38 | /* Maximum DPLL multiplier, divider values for OMAP3 */ | ||
39 | #define OMAP3_MAX_DPLL_MULT 2048 | ||
40 | #define OMAP3_MAX_DPLL_DIV 128 | ||
41 | |||
38 | /* | 42 | /* |
39 | * DPLL1 supplies clock to the MPU. | 43 | * DPLL1 supplies clock to the MPU. |
40 | * DPLL2 supplies clock to the IVA2. | 44 | * DPLL2 supplies clock to the IVA2. |
@@ -255,7 +259,7 @@ static const struct clksel_rate div16_dpll_rates[] = { | |||
255 | /* DPLL1 */ | 259 | /* DPLL1 */ |
256 | /* MPU clock source */ | 260 | /* MPU clock source */ |
257 | /* Type: DPLL */ | 261 | /* Type: DPLL */ |
258 | static const struct dpll_data dpll1_dd = { | 262 | static struct dpll_data dpll1_dd = { |
259 | .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), | 263 | .mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL), |
260 | .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, | 264 | .mult_mask = OMAP3430_MPU_DPLL_MULT_MASK, |
261 | .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, | 265 | .div1_mask = OMAP3430_MPU_DPLL_DIV_MASK, |
@@ -269,6 +273,9 @@ static const struct dpll_data dpll1_dd = { | |||
269 | .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, | 273 | .autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK, |
270 | .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), | 274 | .idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL), |
271 | .idlest_bit = OMAP3430_ST_MPU_CLK_SHIFT, | 275 | .idlest_bit = OMAP3430_ST_MPU_CLK_SHIFT, |
276 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | ||
277 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
278 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
272 | }; | 279 | }; |
273 | 280 | ||
274 | static struct clk dpll1_ck = { | 281 | static struct clk dpll1_ck = { |
@@ -276,6 +283,7 @@ static struct clk dpll1_ck = { | |||
276 | .parent = &sys_ck, | 283 | .parent = &sys_ck, |
277 | .dpll_data = &dpll1_dd, | 284 | .dpll_data = &dpll1_dd, |
278 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, | 285 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, |
286 | .round_rate = &omap2_dpll_round_rate, | ||
279 | .recalc = &omap3_dpll_recalc, | 287 | .recalc = &omap3_dpll_recalc, |
280 | }; | 288 | }; |
281 | 289 | ||
@@ -317,7 +325,7 @@ static struct clk dpll1_x2m2_ck = { | |||
317 | /* IVA2 clock source */ | 325 | /* IVA2 clock source */ |
318 | /* Type: DPLL */ | 326 | /* Type: DPLL */ |
319 | 327 | ||
320 | static const struct dpll_data dpll2_dd = { | 328 | static struct dpll_data dpll2_dd = { |
321 | .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), | 329 | .mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL), |
322 | .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK, | 330 | .mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK, |
323 | .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK, | 331 | .div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK, |
@@ -331,7 +339,10 @@ static const struct dpll_data dpll2_dd = { | |||
331 | .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL), | 339 | .autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL), |
332 | .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK, | 340 | .autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK, |
333 | .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), | 341 | .idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL), |
334 | .idlest_bit = OMAP3430_ST_IVA2_CLK_SHIFT | 342 | .idlest_bit = OMAP3430_ST_IVA2_CLK_SHIFT, |
343 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | ||
344 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
345 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
335 | }; | 346 | }; |
336 | 347 | ||
337 | static struct clk dpll2_ck = { | 348 | static struct clk dpll2_ck = { |
@@ -341,6 +352,7 @@ static struct clk dpll2_ck = { | |||
341 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, | 352 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, |
342 | .enable = &omap3_noncore_dpll_enable, | 353 | .enable = &omap3_noncore_dpll_enable, |
343 | .disable = &omap3_noncore_dpll_disable, | 354 | .disable = &omap3_noncore_dpll_disable, |
355 | .round_rate = &omap2_dpll_round_rate, | ||
344 | .recalc = &omap3_dpll_recalc, | 356 | .recalc = &omap3_dpll_recalc, |
345 | }; | 357 | }; |
346 | 358 | ||
@@ -371,7 +383,7 @@ static struct clk dpll2_m2_ck = { | |||
371 | * Source clock for all interfaces and for some device fclks | 383 | * Source clock for all interfaces and for some device fclks |
372 | * REVISIT: Also supports fast relock bypass - not included below | 384 | * REVISIT: Also supports fast relock bypass - not included below |
373 | */ | 385 | */ |
374 | static const struct dpll_data dpll3_dd = { | 386 | static struct dpll_data dpll3_dd = { |
375 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), | 387 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1), |
376 | .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, | 388 | .mult_mask = OMAP3430_CORE_DPLL_MULT_MASK, |
377 | .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, | 389 | .div1_mask = OMAP3430_CORE_DPLL_DIV_MASK, |
@@ -382,6 +394,9 @@ static const struct dpll_data dpll3_dd = { | |||
382 | .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, | 394 | .recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT, |
383 | .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), | 395 | .autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE), |
384 | .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, | 396 | .autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK, |
397 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | ||
398 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
399 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
385 | }; | 400 | }; |
386 | 401 | ||
387 | static struct clk dpll3_ck = { | 402 | static struct clk dpll3_ck = { |
@@ -389,6 +404,7 @@ static struct clk dpll3_ck = { | |||
389 | .parent = &sys_ck, | 404 | .parent = &sys_ck, |
390 | .dpll_data = &dpll3_dd, | 405 | .dpll_data = &dpll3_dd, |
391 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, | 406 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED, |
407 | .round_rate = &omap2_dpll_round_rate, | ||
392 | .recalc = &omap3_dpll_recalc, | 408 | .recalc = &omap3_dpll_recalc, |
393 | }; | 409 | }; |
394 | 410 | ||
@@ -545,7 +561,7 @@ static struct clk emu_core_alwon_ck = { | |||
545 | /* DPLL4 */ | 561 | /* DPLL4 */ |
546 | /* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ | 562 | /* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */ |
547 | /* Type: DPLL */ | 563 | /* Type: DPLL */ |
548 | static const struct dpll_data dpll4_dd = { | 564 | static struct dpll_data dpll4_dd = { |
549 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), | 565 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2), |
550 | .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, | 566 | .mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK, |
551 | .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, | 567 | .div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK, |
@@ -559,6 +575,9 @@ static const struct dpll_data dpll4_dd = { | |||
559 | .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, | 575 | .autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK, |
560 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), | 576 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), |
561 | .idlest_bit = OMAP3430_ST_PERIPH_CLK_SHIFT, | 577 | .idlest_bit = OMAP3430_ST_PERIPH_CLK_SHIFT, |
578 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | ||
579 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
580 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
562 | }; | 581 | }; |
563 | 582 | ||
564 | static struct clk dpll4_ck = { | 583 | static struct clk dpll4_ck = { |
@@ -568,6 +587,7 @@ static struct clk dpll4_ck = { | |||
568 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, | 587 | .flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES, |
569 | .enable = &omap3_noncore_dpll_enable, | 588 | .enable = &omap3_noncore_dpll_enable, |
570 | .disable = &omap3_noncore_dpll_disable, | 589 | .disable = &omap3_noncore_dpll_disable, |
590 | .round_rate = &omap2_dpll_round_rate, | ||
571 | .recalc = &omap3_dpll_recalc, | 591 | .recalc = &omap3_dpll_recalc, |
572 | }; | 592 | }; |
573 | 593 | ||
@@ -843,7 +863,7 @@ static struct clk emu_per_alwon_ck = { | |||
843 | /* Supplies 120MHz clock, USIM source clock */ | 863 | /* Supplies 120MHz clock, USIM source clock */ |
844 | /* Type: DPLL */ | 864 | /* Type: DPLL */ |
845 | /* 3430ES2 only */ | 865 | /* 3430ES2 only */ |
846 | static const struct dpll_data dpll5_dd = { | 866 | static struct dpll_data dpll5_dd = { |
847 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4), | 867 | .mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4), |
848 | .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK, | 868 | .mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK, |
849 | .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK, | 869 | .div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK, |
@@ -857,6 +877,9 @@ static const struct dpll_data dpll5_dd = { | |||
857 | .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK, | 877 | .autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK, |
858 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), | 878 | .idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2), |
859 | .idlest_bit = OMAP3430ES2_ST_PERIPH2_CLK_SHIFT, | 879 | .idlest_bit = OMAP3430ES2_ST_PERIPH2_CLK_SHIFT, |
880 | .max_multiplier = OMAP3_MAX_DPLL_MULT, | ||
881 | .max_divider = OMAP3_MAX_DPLL_DIV, | ||
882 | .rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE | ||
860 | }; | 883 | }; |
861 | 884 | ||
862 | static struct clk dpll5_ck = { | 885 | static struct clk dpll5_ck = { |
@@ -866,6 +889,7 @@ static struct clk dpll5_ck = { | |||
866 | .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, | 889 | .flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES, |
867 | .enable = &omap3_noncore_dpll_enable, | 890 | .enable = &omap3_noncore_dpll_enable, |
868 | .disable = &omap3_noncore_dpll_disable, | 891 | .disable = &omap3_noncore_dpll_disable, |
892 | .round_rate = &omap2_dpll_round_rate, | ||
869 | .recalc = &omap3_dpll_recalc, | 893 | .recalc = &omap3_dpll_recalc, |
870 | }; | 894 | }; |
871 | 895 | ||
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index 22daa5d64d35..4c7b3514f71a 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h | |||
@@ -33,6 +33,13 @@ struct dpll_data { | |||
33 | void __iomem *mult_div1_reg; | 33 | void __iomem *mult_div1_reg; |
34 | u32 mult_mask; | 34 | u32 mult_mask; |
35 | u32 div1_mask; | 35 | u32 div1_mask; |
36 | u16 last_rounded_m; | ||
37 | u8 last_rounded_n; | ||
38 | unsigned long last_rounded_rate; | ||
39 | unsigned int rate_tolerance; | ||
40 | u16 max_multiplier; | ||
41 | u8 max_divider; | ||
42 | u32 max_tolerance; | ||
36 | # if defined(CONFIG_ARCH_OMAP3) | 43 | # if defined(CONFIG_ARCH_OMAP3) |
37 | u8 modes; | 44 | u8 modes; |
38 | void __iomem *control_reg; | 45 | void __iomem *control_reg; |
@@ -71,7 +78,7 @@ struct clk { | |||
71 | void __iomem *clksel_reg; | 78 | void __iomem *clksel_reg; |
72 | u32 clksel_mask; | 79 | u32 clksel_mask; |
73 | const struct clksel *clksel; | 80 | const struct clksel *clksel; |
74 | const struct dpll_data *dpll_data; | 81 | struct dpll_data *dpll_data; |
75 | #else | 82 | #else |
76 | __u8 rate_offset; | 83 | __u8 rate_offset; |
77 | __u8 src_offset; | 84 | __u8 src_offset; |