Merge branch 'omap_clock_fixes_3.2' of git://git.pwsan.com/linux-2.6 into fixes
This commit is contained in:
commit
8f86f36284
|
@ -46,10 +46,19 @@
|
||||||
(DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
|
(DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
|
||||||
|
|
||||||
/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
|
/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
|
||||||
#define DPLL_FINT_BAND1_MIN 750000
|
#define OMAP3430_DPLL_FINT_BAND1_MIN 750000
|
||||||
#define DPLL_FINT_BAND1_MAX 2100000
|
#define OMAP3430_DPLL_FINT_BAND1_MAX 2100000
|
||||||
#define DPLL_FINT_BAND2_MIN 7500000
|
#define OMAP3430_DPLL_FINT_BAND2_MIN 7500000
|
||||||
#define DPLL_FINT_BAND2_MAX 21000000
|
#define OMAP3430_DPLL_FINT_BAND2_MAX 21000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DPLL valid Fint frequency range for OMAP36xx and OMAP4xxx.
|
||||||
|
* From device data manual section 4.3 "DPLL and DLL Specifications".
|
||||||
|
*/
|
||||||
|
#define OMAP3PLUS_DPLL_FINT_JTYPE_MIN 500000
|
||||||
|
#define OMAP3PLUS_DPLL_FINT_JTYPE_MAX 2500000
|
||||||
|
#define OMAP3PLUS_DPLL_FINT_MIN 32000
|
||||||
|
#define OMAP3PLUS_DPLL_FINT_MAX 52000000
|
||||||
|
|
||||||
/* _dpll_test_fint() return codes */
|
/* _dpll_test_fint() return codes */
|
||||||
#define DPLL_FINT_UNDERFLOW -1
|
#define DPLL_FINT_UNDERFLOW -1
|
||||||
|
@ -71,33 +80,43 @@
|
||||||
static int _dpll_test_fint(struct clk *clk, u8 n)
|
static int _dpll_test_fint(struct clk *clk, u8 n)
|
||||||
{
|
{
|
||||||
struct dpll_data *dd;
|
struct dpll_data *dd;
|
||||||
long fint;
|
long fint, fint_min, fint_max;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
dd = clk->dpll_data;
|
dd = clk->dpll_data;
|
||||||
|
|
||||||
/* DPLL divider must result in a valid jitter correction val */
|
/* DPLL divider must result in a valid jitter correction val */
|
||||||
fint = clk->parent->rate / n;
|
fint = clk->parent->rate / n;
|
||||||
if (fint < DPLL_FINT_BAND1_MIN) {
|
|
||||||
|
|
||||||
|
if (cpu_is_omap24xx()) {
|
||||||
|
/* Should not be called for OMAP2, so warn if it is called */
|
||||||
|
WARN(1, "No fint limits available for OMAP2!\n");
|
||||||
|
return DPLL_FINT_INVALID;
|
||||||
|
} else if (cpu_is_omap3430()) {
|
||||||
|
fint_min = OMAP3430_DPLL_FINT_BAND1_MIN;
|
||||||
|
fint_max = OMAP3430_DPLL_FINT_BAND2_MAX;
|
||||||
|
} else if (dd->flags & DPLL_J_TYPE) {
|
||||||
|
fint_min = OMAP3PLUS_DPLL_FINT_JTYPE_MIN;
|
||||||
|
fint_max = OMAP3PLUS_DPLL_FINT_JTYPE_MAX;
|
||||||
|
} else {
|
||||||
|
fint_min = OMAP3PLUS_DPLL_FINT_MIN;
|
||||||
|
fint_max = OMAP3PLUS_DPLL_FINT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fint < fint_min) {
|
||||||
pr_debug("rejecting n=%d due to Fint failure, "
|
pr_debug("rejecting n=%d due to Fint failure, "
|
||||||
"lowering max_divider\n", n);
|
"lowering max_divider\n", n);
|
||||||
dd->max_divider = n;
|
dd->max_divider = n;
|
||||||
ret = DPLL_FINT_UNDERFLOW;
|
ret = DPLL_FINT_UNDERFLOW;
|
||||||
|
} else if (fint > fint_max) {
|
||||||
} else if (fint > DPLL_FINT_BAND1_MAX &&
|
|
||||||
fint < DPLL_FINT_BAND2_MIN) {
|
|
||||||
|
|
||||||
pr_debug("rejecting n=%d due to Fint failure\n", n);
|
|
||||||
ret = DPLL_FINT_INVALID;
|
|
||||||
|
|
||||||
} else if (fint > DPLL_FINT_BAND2_MAX) {
|
|
||||||
|
|
||||||
pr_debug("rejecting n=%d due to Fint failure, "
|
pr_debug("rejecting n=%d due to Fint failure, "
|
||||||
"boosting min_divider\n", n);
|
"boosting min_divider\n", n);
|
||||||
dd->min_divider = n;
|
dd->min_divider = n;
|
||||||
ret = DPLL_FINT_INVALID;
|
ret = DPLL_FINT_INVALID;
|
||||||
|
} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
|
||||||
|
fint < OMAP3430_DPLL_FINT_BAND2_MIN) {
|
||||||
|
pr_debug("rejecting n=%d due to Fint failure\n", n);
|
||||||
|
ret = DPLL_FINT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -66,6 +66,8 @@ void omap3_noncore_dpll_disable(struct clk *clk);
|
||||||
int omap4_dpllmx_gatectrl_read(struct clk *clk);
|
int omap4_dpllmx_gatectrl_read(struct clk *clk);
|
||||||
void omap4_dpllmx_allow_gatectrl(struct clk *clk);
|
void omap4_dpllmx_allow_gatectrl(struct clk *clk);
|
||||||
void omap4_dpllmx_deny_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
|
#ifdef CONFIG_OMAP_RESET_CLOCKS
|
||||||
void omap2_clk_disable_unused(struct clk *clk);
|
void omap2_clk_disable_unused(struct clk *clk);
|
||||||
|
|
|
@ -8,6 +8,13 @@
|
||||||
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
|
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
|
||||||
#define __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);
|
int omap4xxx_clk_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -270,8 +270,8 @@ static struct clk dpll_abe_ck = {
|
||||||
.dpll_data = &dpll_abe_dd,
|
.dpll_data = &dpll_abe_dd,
|
||||||
.init = &omap2_init_dpll_parent,
|
.init = &omap2_init_dpll_parent,
|
||||||
.ops = &clkops_omap3_noncore_dpll_ops,
|
.ops = &clkops_omap3_noncore_dpll_ops,
|
||||||
.recalc = &omap3_dpll_recalc,
|
.recalc = &omap4_dpll_regm4xen_recalc,
|
||||||
.round_rate = &omap2_dpll_round_rate,
|
.round_rate = &omap4_dpll_regm4xen_round_rate,
|
||||||
.set_rate = &omap3_noncore_dpll_set_rate,
|
.set_rate = &omap3_noncore_dpll_set_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1195,11 +1195,25 @@ static struct clk l4_wkup_clk_mux_ck = {
|
||||||
.recalc = &omap2_clksel_recalc,
|
.recalc = &omap2_clksel_recalc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct clksel_rate div2_2to1_rates[] = {
|
||||||
|
{ .div = 1, .val = 1, .flags = RATE_IN_4430 },
|
||||||
|
{ .div = 2, .val = 0, .flags = RATE_IN_4430 },
|
||||||
|
{ .div = 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct clksel ocp_abe_iclk_div[] = {
|
||||||
|
{ .parent = &aess_fclk, .rates = div2_2to1_rates },
|
||||||
|
{ .parent = NULL },
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk ocp_abe_iclk = {
|
static struct clk ocp_abe_iclk = {
|
||||||
.name = "ocp_abe_iclk",
|
.name = "ocp_abe_iclk",
|
||||||
.parent = &aess_fclk,
|
.parent = &aess_fclk,
|
||||||
|
.clksel = ocp_abe_iclk_div,
|
||||||
|
.clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
|
||||||
|
.clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
|
||||||
.ops = &clkops_null,
|
.ops = &clkops_null,
|
||||||
.recalc = &followparent_recalc,
|
.recalc = &omap2_clksel_recalc,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct clk per_abe_24m_fclk = {
|
static struct clk per_abe_24m_fclk = {
|
||||||
|
@ -1398,9 +1412,9 @@ static struct clk dss_dss_clk = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clksel_rate div3_8to32_rates[] = {
|
static const struct clksel_rate div3_8to32_rates[] = {
|
||||||
{ .div = 8, .val = 0, .flags = RATE_IN_44XX },
|
{ .div = 8, .val = 0, .flags = RATE_IN_4460 },
|
||||||
{ .div = 16, .val = 1, .flags = RATE_IN_44XX },
|
{ .div = 16, .val = 1, .flags = RATE_IN_4460 },
|
||||||
{ .div = 32, .val = 2, .flags = RATE_IN_44XX },
|
{ .div = 32, .val = 2, .flags = RATE_IN_4460 },
|
||||||
{ .div = 0 },
|
{ .div = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3403,12 +3417,12 @@ int __init omap4xxx_clk_init(void)
|
||||||
struct omap_clk *c;
|
struct omap_clk *c;
|
||||||
u32 cpu_clkflg;
|
u32 cpu_clkflg;
|
||||||
|
|
||||||
if (cpu_is_omap44xx()) {
|
if (cpu_is_omap443x()) {
|
||||||
cpu_mask = RATE_IN_4430;
|
cpu_mask = RATE_IN_4430;
|
||||||
cpu_clkflg = CK_443X;
|
cpu_clkflg = CK_443X;
|
||||||
} else if (cpu_is_omap446x()) {
|
} else if (cpu_is_omap446x()) {
|
||||||
cpu_mask = RATE_IN_4460;
|
cpu_mask = RATE_IN_4460 | RATE_IN_4430;
|
||||||
cpu_clkflg = CK_446X;
|
cpu_clkflg = CK_446X | CK_443X;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk)
|
||||||
* propagating?
|
* propagating?
|
||||||
*/
|
*/
|
||||||
if (!r)
|
if (!r)
|
||||||
clk->rate = omap2_get_dpll_rate(clk);
|
clk->rate = (clk->recalc) ? clk->recalc(clk) :
|
||||||
|
omap2_get_dpll_rate(clk);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -424,6 +425,7 @@ void omap3_noncore_dpll_disable(struct clk *clk)
|
||||||
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
||||||
{
|
{
|
||||||
struct clk *new_parent = NULL;
|
struct clk *new_parent = NULL;
|
||||||
|
unsigned long hw_rate;
|
||||||
u16 freqsel = 0;
|
u16 freqsel = 0;
|
||||||
struct dpll_data *dd;
|
struct dpll_data *dd;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
||||||
if (!dd)
|
if (!dd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (rate == omap2_get_dpll_rate(clk))
|
hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
|
||||||
|
if (rate == hw_rate)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -455,7 +458,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
|
||||||
new_parent = dd->clk_bypass;
|
new_parent = dd->clk_bypass;
|
||||||
} else {
|
} else {
|
||||||
if (dd->last_rounded_rate != rate)
|
if (dd->last_rounded_rate != rate)
|
||||||
omap2_dpll_round_rate(clk, rate);
|
rate = clk->round_rate(clk, rate);
|
||||||
|
|
||||||
if (dd->last_rounded_rate == 0)
|
if (dd->last_rounded_rate == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <plat/clock.h>
|
#include <plat/clock.h>
|
||||||
|
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
#include "clock44xx.h"
|
||||||
#include "cm-regbits-44xx.h"
|
#include "cm-regbits-44xx.h"
|
||||||
|
|
||||||
/* Supported only on OMAP4 */
|
/* Supported only on OMAP4 */
|
||||||
|
@ -82,3 +83,71 @@ const struct clkops clkops_omap4_dpllmx_ops = {
|
||||||
.deny_idle = omap4_dpllmx_deny_gatectrl,
|
.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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue