Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347379
b: refs/heads/master
c: 3ff51ed
h: refs/heads/master
i:
  347377: 72114d9
  347375: bdc5d68
v: v3
  • Loading branch information
Jon Hunter authored and Paul Walmsley committed Dec 15, 2012
1 parent 244ff00 commit 860b49a
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9b4fcc86941ec0c12b27fefa39dc85e32244dc64
refs/heads/master: 3ff51ed8287d3d2c7899f18f0487348e3448afb5
2 changes: 2 additions & 0 deletions trunk/arch/arm/mach-omap2/cclock44xx_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ static struct dpll_data dpll_abe_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
.m4xen_mask = OMAP4430_DPLL_REGM4XEN_MASK,
.lpmode_mask = OMAP4430_DPLL_LPMODE_EN_MASK,
.max_multiplier = 2047,
.max_divider = 128,
.min_divider = 1,
Expand Down
10 changes: 10 additions & 0 deletions trunk/arch/arm/mach-omap2/clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ struct clksel {
* @enable_mask: mask of the DPLL mode bitfield in @control_reg
* @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
* @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
* @last_rounded_m4xen: cache of the last M4X result of
* omap4_dpll_regm4xen_round_rate()
* @last_rounded_lpmode: cache of the last lpmode result of
* omap4_dpll_lpmode_recalc()
* @max_multiplier: maximum valid non-bypass multiplier value (actual)
* @last_rounded_n: cache of the last N result of omap2_dpll_round_rate()
* @min_divider: minimum valid non-bypass divider value (actual)
Expand All @@ -205,6 +209,8 @@ struct clksel {
* @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
* @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
* @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
* @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
* @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
* @auto_recal_bit: bitshift of the driftguard enable bit in @control_reg
* @recal_en_bit: bitshift of the PRM_IRQENABLE_* bit for recalibration IRQs
* @recal_st_bit: bitshift of the PRM_IRQSTATUS_* bit for recalibration IRQs
Expand Down Expand Up @@ -233,6 +239,8 @@ struct dpll_data {
u32 enable_mask;
unsigned long last_rounded_rate;
u16 last_rounded_m;
u8 last_rounded_m4xen;
u8 last_rounded_lpmode;
u16 max_multiplier;
u8 last_rounded_n;
u8 min_divider;
Expand All @@ -245,6 +253,8 @@ struct dpll_data {
u32 idlest_mask;
u32 dco_mask;
u32 sddiv_mask;
u32 lpmode_mask;
u32 m4xen_mask;
u8 auto_recal_bit;
u8 recal_en_bit;
u8 recal_st_bit;
Expand Down
46 changes: 32 additions & 14 deletions trunk/arch/arm/mach-omap2/dpll3xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,13 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n)

/*
* _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
* @clk: struct clk * of DPLL to set
* @m: DPLL multiplier to set
* @n: DPLL divider to set
* @freqsel: FREQSEL value to set
* @clk: struct clk * of DPLL to set
* @freqsel: FREQSEL value to set
*
* Program the DPLL with the supplied M, N values, and wait for the DPLL to
* lock.. Returns -EINVAL upon error, or 0 upon success.
* Program the DPLL with the last M, N values calculated, and wait for
* the DPLL to lock. Returns -EINVAL upon error, or 0 upon success.
*/
static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
u16 freqsel)
static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
{
struct dpll_data *dd = clk->dpll_data;
u8 dco, sd_div;
Expand All @@ -323,23 +320,45 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 m, u8 n,
/* Set DPLL multiplier, divider */
v = __raw_readl(dd->mult_div1_reg);
v &= ~(dd->mult_mask | dd->div1_mask);
v |= m << __ffs(dd->mult_mask);
v |= (n - 1) << __ffs(dd->div1_mask);
v |= dd->last_rounded_m << __ffs(dd->mult_mask);
v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);

/* Configure dco and sd_div for dplls that have these fields */
if (dd->dco_mask) {
_lookup_dco(clk, &dco, m, n);
_lookup_dco(clk, &dco, dd->last_rounded_m, dd->last_rounded_n);
v &= ~(dd->dco_mask);
v |= dco << __ffs(dd->dco_mask);
}
if (dd->sddiv_mask) {
_lookup_sddiv(clk, &sd_div, m, n);
_lookup_sddiv(clk, &sd_div, dd->last_rounded_m,
dd->last_rounded_n);
v &= ~(dd->sddiv_mask);
v |= sd_div << __ffs(dd->sddiv_mask);
}

__raw_writel(v, dd->mult_div1_reg);

/* Set 4X multiplier and low-power mode */
if (dd->m4xen_mask || dd->lpmode_mask) {
v = __raw_readl(dd->control_reg);

if (dd->m4xen_mask) {
if (dd->last_rounded_m4xen)
v |= dd->m4xen_mask;
else
v &= ~dd->m4xen_mask;
}

if (dd->lpmode_mask) {
if (dd->last_rounded_lpmode)
v |= dd->lpmode_mask;
else
v &= ~dd->lpmode_mask;
}

__raw_writel(v, dd->control_reg);
}

/* We let the clock framework set the other output dividers later */

/* REVISIT: Set ramp-up delay? */
Expand Down Expand Up @@ -492,8 +511,7 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
pr_debug("%s: %s: set rate: locking rate to %lu.\n",
__func__, __clk_get_name(hw->clk), rate);

ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
dd->last_rounded_n, freqsel);
ret = omap3_noncore_dpll_program(clk, freqsel);
if (!ret)
new_parent = dd->clk_ref;
}
Expand Down
64 changes: 55 additions & 9 deletions trunk/arch/arm/mach-omap2/dpll44xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@
#include "clock44xx.h"
#include "cm-regbits-44xx.h"

/*
* Maximum DPLL input frequency (FINT) and output frequency (FOUT) that
* can supported when using the DPLL low-power mode. Frequencies are
* defined in OMAP4430/60 Public TRM section 3.6.3.3.2 "Enable Control,
* Status, and Low-Power Operation Mode".
*/
#define OMAP4_DPLL_LP_FINT_MAX 1000000
#define OMAP4_DPLL_LP_FOUT_MAX 100000000

/* Supported only on OMAP4 */
int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk)
{
Expand Down Expand Up @@ -81,6 +90,31 @@ const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
.deny_idle = omap4_dpllmx_deny_gatectrl,
};

/**
* omap4_dpll_lpmode_recalc - compute DPLL low-power setting
* @dd: pointer to the dpll data structure
*
* Calculates if low-power mode can be enabled based upon the last
* multiplier and divider values calculated. If low-power mode can be
* enabled, then the bit to enable low-power mode is stored in the
* last_rounded_lpmode variable. This implementation is based upon the
* criteria for enabling low-power mode as described in the OMAP4430/60
* Public TRM section 3.6.3.3.2 "Enable Control, Status, and Low-Power
* Operation Mode".
*/
static void omap4_dpll_lpmode_recalc(struct dpll_data *dd)
{
long fint, fout;

fint = __clk_get_rate(dd->clk_ref) / (dd->last_rounded_n + 1);
fout = fint * dd->last_rounded_m;

if ((fint < OMAP4_DPLL_LP_FINT_MAX) && (fout < OMAP4_DPLL_LP_FOUT_MAX))
dd->last_rounded_lpmode = 1;
else
dd->last_rounded_lpmode = 0;
}

/**
* omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
* @clk: struct clk * of the DPLL to compute the rate for
Expand Down Expand Up @@ -130,7 +164,6 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
unsigned long *parent_rate)
{
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
u32 v;
struct dpll_data *dd;
long r;

Expand All @@ -139,18 +172,31 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,

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;
dd->last_rounded_m4xen = 0;

/*
* First try to compute the DPLL configuration for
* target rate without using the 4X multiplier.
*/
r = omap2_dpll_round_rate(hw, target_rate, NULL);
if (r != ~0)
goto out;

/*
* If we did not find a valid DPLL configuration, try again, but
* this time see if using the 4X multiplier can help. Enabling the
* 4X multiplier is equivalent to dividing the target rate by 4.
*/
r = omap2_dpll_round_rate(hw, target_rate / OMAP4430_REGM4XEN_MULT,
NULL);
if (r == ~0)
return r;

if (v)
clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
dd->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
dd->last_rounded_m4xen = 1;

out:
omap4_dpll_lpmode_recalc(dd);

return clk->dpll_data->last_rounded_rate;
return dd->last_rounded_rate;
}

0 comments on commit 860b49a

Please sign in to comment.