diff options
| -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 | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/dpll44xx.c | 69 | 
4 files changed, 80 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 48ac568881b..2311bc21722 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);  int omap4_dpllmx_gatectrl_read(struct clk *clk);  void omap4_dpllmx_allow_gatectrl(struct clk *clk);  void omap4_dpllmx_deny_gatectrl(struct clk *clk); +long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate); +unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);  #ifdef CONFIG_OMAP_RESET_CLOCKS  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 7ceb870e7ab..287a46f78d9 100644 --- a/arch/arm/mach-omap2/clock44xx.h +++ b/arch/arm/mach-omap2/clock44xx.h @@ -8,6 +8,13 @@  #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H  #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H +/* + * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is + *    set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM + *    vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters") + */ +#define OMAP4430_REGM4XEN_MULT	4 +  int omap4xxx_clk_init(void);  #endif diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index c0b6fbda340..c98c0a22c18 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 = {  	.dpll_data	= &dpll_abe_dd,  	.init		= &omap2_init_dpll_parent,  	.ops		= &clkops_omap3_noncore_dpll_ops, -	.recalc		= &omap3_dpll_recalc, -	.round_rate	= &omap2_dpll_round_rate, +	.recalc		= &omap4_dpll_regm4xen_recalc, +	.round_rate	= &omap4_dpll_regm4xen_round_rate,  	.set_rate	= &omap3_noncore_dpll_set_rate,  }; diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 4e4da6160d0..9c6a296b3dc 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -19,6 +19,7 @@  #include <plat/clock.h>  #include "clock.h" +#include "clock44xx.h"  #include "cm-regbits-44xx.h"  /* Supported only on OMAP4 */ @@ -82,3 +83,71 @@ const struct clkops clkops_omap4_dpllmx_ops = {  	.deny_idle	= omap4_dpllmx_deny_gatectrl,  }; +/** + * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit + * @clk: struct clk * of the DPLL to compute the rate for + * + * Compute the output rate for the OMAP4 DPLL represented by @clk. + * Takes the REGM4XEN bit into consideration, which is needed for the + * OMAP4 ABE DPLL.  Returns the DPLL's output rate (before M-dividers) + * upon success, or 0 upon error. + */ +unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk) +{ +	u32 v; +	unsigned long rate; +	struct dpll_data *dd; + +	if (!clk || !clk->dpll_data) +		return 0; + +	dd = clk->dpll_data; + +	rate = omap2_get_dpll_rate(clk); + +	/* regm4xen adds a multiplier of 4 to DPLL calculations */ +	v = __raw_readl(dd->control_reg); +	if (v & OMAP4430_DPLL_REGM4XEN_MASK) +		rate *= OMAP4430_REGM4XEN_MULT; + +	return rate; +} + +/** + * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit + * @clk: struct clk * of the DPLL to round a rate for + * @target_rate: the desired rate of the DPLL + * + * Compute the rate that would be programmed into the DPLL hardware + * for @clk if set_rate() were to be provided with the rate + * @target_rate.  Takes the REGM4XEN bit into consideration, which is + * needed for the OMAP4 ABE DPLL.  Returns the rounded rate (before + * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or + * ~0 if an error occurred in omap2_dpll_round_rate(). + */ +long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate) +{ +	u32 v; +	struct dpll_data *dd; +	long r; + +	if (!clk || !clk->dpll_data) +		return -EINVAL; + +	dd = clk->dpll_data; + +	/* regm4xen adds a multiplier of 4 to DPLL calculations */ +	v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK; + +	if (v) +		target_rate = target_rate / OMAP4430_REGM4XEN_MULT; + +	r = omap2_dpll_round_rate(clk, target_rate); +	if (r == ~0) +		return r; + +	if (v) +		clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT; + +	return clk->dpll_data->last_rounded_rate; +}  |