Commit 15a7b60e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of git://git.linaro.org/people/mike.turquette/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
parents f2159d1e 51784380
...@@ -147,7 +147,7 @@ static bool _is_valid_div(struct clk_divider *divider, unsigned int div) ...@@ -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) static int _round_up_table(const struct clk_div_table *table, int div)
{ {
const struct clk_div_table *clkt; const struct clk_div_table *clkt;
int up = _get_table_maxdiv(table); int up = INT_MAX;
for (clkt = table; clkt->div; clkt++) { for (clkt = table; clkt->div; clkt++) {
if (clkt->div == div) if (clkt->div == div)
......
...@@ -521,8 +521,10 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, ...@@ -521,8 +521,10 @@ static struct clk * __init clkgen_odf_register(const char *parent_name,
gate->lock = odf_lock; gate->lock = odf_lock;
div = kzalloc(sizeof(*div), GFP_KERNEL); div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div) if (!div) {
kfree(gate);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO; div->flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO;
div->reg = reg + pll_data->odf[odf].offset; div->reg = reg + pll_data->odf[odf].offset;
......
...@@ -58,9 +58,9 @@ ...@@ -58,9 +58,9 @@
#define PLLDU_LFCON_SET_DIVN 600 #define PLLDU_LFCON_SET_DIVN 600
#define PLLE_BASE_DIVCML_SHIFT 24 #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_SHIFT 16
#define PLLE_BASE_DIVP_WIDTH 7 #define PLLE_BASE_DIVP_WIDTH 6
#define PLLE_BASE_DIVN_SHIFT 8 #define PLLE_BASE_DIVN_SHIFT 8
#define PLLE_BASE_DIVN_WIDTH 8 #define PLLE_BASE_DIVN_WIDTH 8
#define PLLE_BASE_DIVM_SHIFT 0 #define PLLE_BASE_DIVM_SHIFT 0
...@@ -183,6 +183,14 @@ ...@@ -183,6 +183,14 @@
#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\ #define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
mask(p->params->div_nmp->divp_width)) 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 divm_max(p) (divm_mask(p))
#define divn_max(p) (divn_mask(p)) #define divn_max(p) (divn_mask(p))
#define divp_max(p) (1 << (divp_mask(p))) #define divp_max(p) (1 << (divp_mask(p)))
...@@ -476,13 +484,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, ...@@ -476,13 +484,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
} else { } else {
val = pll_readl_base(pll); val = pll_readl_base(pll);
val &= ~((divm_mask(pll) << div_nmp->divm_shift) | val &= ~(divm_mask_shifted(pll) | divn_mask_shifted(pll) |
(divn_mask(pll) << div_nmp->divn_shift) | divp_mask_shifted(pll));
(divp_mask(pll) << div_nmp->divp_shift));
val |= ((cfg->m << div_nmp->divm_shift) | val |= (cfg->m << divm_shift(pll)) |
(cfg->n << div_nmp->divn_shift) | (cfg->n << divn_shift(pll)) |
(cfg->p << div_nmp->divp_shift)); (cfg->p << divp_shift(pll));
pll_writel_base(val, pll); pll_writel_base(val, pll);
} }
...@@ -730,11 +737,12 @@ static int clk_plle_enable(struct clk_hw *hw) ...@@ -730,11 +737,12 @@ static int clk_plle_enable(struct clk_hw *hw)
if (pll->params->flags & TEGRA_PLLE_CONFIGURE) { if (pll->params->flags & TEGRA_PLLE_CONFIGURE) {
/* configure dividers */ /* configure dividers */
val = pll_readl_base(pll); val = pll_readl_base(pll);
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); divm_mask_shifted(pll));
val |= sel.m << pll->params->div_nmp->divm_shift; val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
val |= sel.n << pll->params->div_nmp->divn_shift; val |= sel.m << divm_shift(pll);
val |= sel.p << pll->params->div_nmp->divp_shift; val |= sel.n << divn_shift(pll);
val |= sel.p << divp_shift(pll);
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
pll_writel_base(val, pll); pll_writel_base(val, pll);
} }
...@@ -745,10 +753,11 @@ static int clk_plle_enable(struct clk_hw *hw) ...@@ -745,10 +753,11 @@ static int clk_plle_enable(struct clk_hw *hw)
pll_writel_misc(val, pll); pll_writel_misc(val, pll);
val = readl(pll->clk_base + PLLE_SS_CTRL); val = readl(pll->clk_base + PLLE_SS_CTRL);
val &= ~PLLE_SS_COEFFICIENTS_MASK;
val |= PLLE_SS_DISABLE; val |= PLLE_SS_DISABLE;
writel(val, pll->clk_base + PLLE_SS_CTRL); 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); val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
pll_writel_base(val, pll); pll_writel_base(val, pll);
...@@ -1292,10 +1301,11 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) ...@@ -1292,10 +1301,11 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
pll_writel(val, PLLE_SS_CTRL, pll); pll_writel(val, PLLE_SS_CTRL, pll);
val = pll_readl_base(pll); val = pll_readl_base(pll);
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); val &= ~(divp_mask_shifted(pll) | divn_mask_shifted(pll) |
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); divm_mask_shifted(pll));
val |= sel.m << pll->params->div_nmp->divm_shift; val &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
val |= sel.n << pll->params->div_nmp->divn_shift; val |= sel.m << divm_shift(pll);
val |= sel.n << divn_shift(pll);
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
pll_writel_base(val, pll); pll_writel_base(val, pll);
udelay(1); udelay(1);
...@@ -1410,6 +1420,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, ...@@ -1410,6 +1420,15 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
return clk; 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, struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc, void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, struct tegra_clk_pll_params *pll_params, unsigned long flags, struct tegra_clk_pll_params *pll_params,
...@@ -1420,6 +1439,10 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, ...@@ -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_LOCK_MISC | TEGRA_PLL_BYPASS;
pll_params->flags |= TEGRA_PLL_HAS_LOCK_ENABLE; 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); pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll)) if (IS_ERR(pll))
return ERR_CAST(pll); return ERR_CAST(pll);
...@@ -1557,9 +1580,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, ...@@ -1557,9 +1580,8 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
int m; int m;
m = _pll_fixed_mdiv(pll_params, parent_rate); m = _pll_fixed_mdiv(pll_params, parent_rate);
val = m << PLL_BASE_DIVM_SHIFT; val = m << divm_shift(pll);
val |= (pll_params->vco_min / parent_rate) val |= (pll_params->vco_min / parent_rate) << divn_shift(pll);
<< PLL_BASE_DIVN_SHIFT;
pll_writel_base(val, pll); pll_writel_base(val, pll);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment