Skip to content

Commit

Permalink
Merge tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mike.t…
Browse files Browse the repository at this point in the history
…urquette/linux

Pull clock fixes from Mike Turquette:
 "Small number of user-visible regression fixes for clock drivers.

  There is a memory leak fix for an ST platform, an infinite Loop Of
  Doom fix for the recent changes to the basic clock divider (hopefully
  the last fix for those recent changes) and some Tegra PLL changes
  which keep PCI from being hosed on that platform"

* tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mike.turquette/linux:
  clk: st: Fix memory leak
  clk: divider: Fix table round up function
  clk: tegra: Fix enabling of PLLE
  clk: tegra: Introduce divider mask and shift helpers
  clk: tegra: Fix PLLE programming
  • Loading branch information
Linus Torvalds committed May 29, 2014
2 parents f2159d1 + 5178438 commit 15a7b60
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 23 deletions.
2 changes: 1 addition & 1 deletion drivers/clk/clk-divider.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
static int _round_up_table(const struct clk_div_table *table, int div)
{
const struct clk_div_table *clkt;
int up = _get_table_maxdiv(table);
int up = INT_MAX;

for (clkt = table; clkt->div; clkt++) {
if (clkt->div == div)
Expand Down
4 changes: 3 additions & 1 deletion drivers/clk/st/clkgen-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,10 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
gate->lock = odf_lock;

div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
if (!div) {
kfree(gate);
return ERR_PTR(-ENOMEM);
}

div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
div->reg = reg + pll_data->odf[odf].offset;
Expand Down
64 changes: 43 additions & 21 deletions drivers/clk/tegra/clk-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
#define PLLDU_LFCON_SET_DIVN 600

#define PLLE_BASE_DIVCML_SHIFT 24
#define PLLE_BASE_DIVCML_WIDTH 4
#define PLLE_BASE_DIVCML_MASK 0xf
#define PLLE_BASE_DIVP_SHIFT 16
#define PLLE_BASE_DIVP_WIDTH 7
#define PLLE_BASE_DIVP_WIDTH 6
#define PLLE_BASE_DIVN_SHIFT 8
#define PLLE_BASE_DIVN_WIDTH 8
#define PLLE_BASE_DIVM_SHIFT 0
Expand Down Expand Up @@ -183,6 +183,14 @@
#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
mask(p->params->div_nmp->divp_width))

#define divm_shift(p) (p)->params->div_nmp->divm_shift
#define divn_shift(p) (p)->params->div_nmp->divn_shift
#define divp_shift(p) (p)->params->div_nmp->divp_shift

#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p))
#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p))
#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p))

#define divm_max(p) (divm_mask(p))
#define divn_max(p) (divn_mask(p))
#define divp_max(p) (1 << (divp_mask(p)))
Expand Down Expand Up @@ -476,13 +484,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
} else {
val = pll_readl_base(pll);

val &= ~((divm_mask(pll) << div_nmp->divm_shift) |
(divn_mask(pll) << div_nmp->divn_shift) |
(divp_mask(pll) << div_nmp->divp_shift));
val &= ~(divm_mask_shifted(pll) | divn_mask_shifted(pll) |
divp_mask_shifted(pll));

val |= ((cfg->m << div_nmp->divm_shift) |
(cfg->n << div_nmp->divn_shift) |
(cfg->p << div_nmp->divp_shift));
val |= (cfg->m << divm_shift(pll)) |
(cfg->n << divn_shift(pll)) |
(cfg->p << divp_shift(pll));

pll_writel_base(val, pll);
}
Expand Down Expand Up @@ -730,11 +737,12 @@ static int clk_plle_enable(struct clk_hw *hw)
if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
/* configure dividers */
val = pll_readl_base(pll);
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
val |= sel.m << pll->params->div_nmp->divm_shift;
val |= sel.n << pll->params->div_nmp->divn_shift;
val |= sel.p << pll->params->div_nmp->divp_shift;
val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
divm_mask_shifted(pll));
val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
val |= sel.m << divm_shift(pll);
val |= sel.n << divn_shift(pll);
val |= sel.p << divp_shift(pll);
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
pll_writel_base(val, pll);
}
Expand All @@ -745,10 +753,11 @@ static int clk_plle_enable(struct clk_hw *hw)
pll_writel_misc(val, pll);

val = readl(pll->clk_base + PLLE_SS_CTRL);
val &= ~PLLE_SS_COEFFICIENTS_MASK;
val |= PLLE_SS_DISABLE;
writel(val, pll->clk_base + PLLE_SS_CTRL);

val |= pll_readl_base(pll);
val = pll_readl_base(pll);
val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
pll_writel_base(val, pll);

Expand Down Expand Up @@ -1292,10 +1301,11 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
pll_writel(val, PLLE_SS_CTRL, pll);

val = pll_readl_base(pll);
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
val |= sel.m << pll->params->div_nmp->divm_shift;
val |= sel.n << pll->params->div_nmp->divn_shift;
val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
divm_mask_shifted(pll));
val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
val |= sel.m << divm_shift(pll);
val |= sel.n << divn_shift(pll);
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
pll_writel_base(val, pll);
udelay(1);
Expand Down Expand Up @@ -1410,6 +1420,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
return clk;
}

static struct div_nmp pll_e_nmp = {
.divn_shift = PLLE_BASE_DIVN_SHIFT,
.divn_width = PLLE_BASE_DIVN_WIDTH,
.divm_shift = PLLE_BASE_DIVM_SHIFT,
.divm_width = PLLE_BASE_DIVM_WIDTH,
.divp_shift = PLLE_BASE_DIVP_SHIFT,
.divp_width = PLLE_BASE_DIVP_WIDTH,
};

struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, struct tegra_clk_pll_params *pll_params,
Expand All @@ -1420,6 +1439,10 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,

pll_params->flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE;

if (!pll_params->div_nmp)
pll_params->div_nmp = &pll_e_nmp;

pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
Expand Down Expand Up @@ -1557,9 +1580,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
int m;

m = _pll_fixed_mdiv(pll_params, parent_rate);
val = m << PLL_BASE_DIVM_SHIFT;
val |= (pll_params->vco_min / parent_rate)
<< PLL_BASE_DIVN_SHIFT;
val = m << divm_shift(pll);
val |= (pll_params->vco_min / parent_rate) << divn_shift(pll);
pll_writel_base(val, pll);
}

Expand Down

0 comments on commit 15a7b60

Please sign in to comment.