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; |
