clk: tegra: allow PLL m,n,p init from SoC files
The m,n,p fields don't have the same bit offset and width across all PLLs. This patch allows SoC specific files to indicate the offset and width. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Tested-by: Stephen Warren <swarren@nvidia.com> Acked-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
This commit is contained in:

committed by
Mike Turquette

parent
c388eee21a
commit
aa6fefde62
@@ -134,15 +134,24 @@
|
||||
#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
|
||||
|
||||
#define mask(w) ((1 << (w)) - 1)
|
||||
#define divm_mask(p) mask(p->divm_width)
|
||||
#define divn_mask(p) mask(p->divn_width)
|
||||
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
|
||||
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
|
||||
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
|
||||
mask(p->divp_width))
|
||||
mask(p->params->div_nmp->divp_width))
|
||||
|
||||
#define divm_max(p) (divm_mask(p))
|
||||
#define divn_max(p) (divn_mask(p))
|
||||
#define divp_max(p) (1 << (divp_mask(p)))
|
||||
|
||||
static struct div_nmp default_nmp = {
|
||||
.divn_shift = PLL_BASE_DIVN_SHIFT,
|
||||
.divn_width = PLL_BASE_DIVN_WIDTH,
|
||||
.divm_shift = PLL_BASE_DIVM_SHIFT,
|
||||
.divm_width = PLL_BASE_DIVM_WIDTH,
|
||||
.divp_shift = PLL_BASE_DIVP_SHIFT,
|
||||
.divp_width = PLL_BASE_DIVP_WIDTH,
|
||||
};
|
||||
|
||||
static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
|
||||
{
|
||||
u32 val;
|
||||
@@ -407,12 +416,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
|
||||
val &= ~((divm_mask(pll) << pll->divm_shift) |
|
||||
(divn_mask(pll) << pll->divn_shift) |
|
||||
(divp_mask(pll) << pll->divp_shift));
|
||||
val |= ((cfg->m << pll->divm_shift) |
|
||||
(cfg->n << pll->divn_shift) |
|
||||
(cfg->p << pll->divp_shift));
|
||||
val &= ~((divm_mask(pll) << pll->params->div_nmp->divm_shift) |
|
||||
(divn_mask(pll) << pll->params->div_nmp->divn_shift) |
|
||||
(divp_mask(pll) << pll->params->div_nmp->divp_shift));
|
||||
val |= ((cfg->m << pll->params->div_nmp->divm_shift) |
|
||||
(cfg->n << pll->params->div_nmp->divn_shift) |
|
||||
(cfg->p << pll->params->div_nmp->divp_shift));
|
||||
|
||||
pll_writel_base(val, pll);
|
||||
}
|
||||
@@ -424,9 +433,9 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll,
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
|
||||
cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
|
||||
cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
|
||||
cfg->p = (val >> pll->divp_shift) & (divp_mask(pll));
|
||||
cfg->m = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
|
||||
cfg->n = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
|
||||
cfg->p = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
|
||||
}
|
||||
|
||||
static void _update_pll_cpcon(struct tegra_clk_pll *pll,
|
||||
@@ -646,9 +655,9 @@ static int clk_plle_enable(struct clk_hw *hw)
|
||||
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->divm_shift;
|
||||
val |= sel.n << pll->divn_shift;
|
||||
val |= sel.p << pll->divp_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 |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
pll_writel_base(val, pll);
|
||||
}
|
||||
@@ -679,9 +688,9 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
|
||||
u32 divn = 0, divm = 0, divp = 0;
|
||||
u64 rate = parent_rate;
|
||||
|
||||
divp = (val >> pll->divp_shift) & (divp_mask(pll));
|
||||
divn = (val >> pll->divn_shift) & (divn_mask(pll));
|
||||
divm = (val >> pll->divm_shift) & (divm_mask(pll));
|
||||
divp = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
|
||||
divn = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
|
||||
divm = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
|
||||
divm *= divp;
|
||||
|
||||
rate *= divn;
|
||||
@@ -902,7 +911,8 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
|
||||
val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
|
||||
val &= ~(divn_mask(pll) | divm_mask(pll));
|
||||
val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift);
|
||||
val |= (cfg.m << pll->params->div_nmp->divm_shift) |
|
||||
(cfg.n << pll->params->div_nmp->divn_shift);
|
||||
writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
|
||||
} else
|
||||
_update_pll_mnp(pll, &cfg);
|
||||
@@ -1180,8 +1190,8 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
|
||||
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->divm_shift;
|
||||
val |= sel.n << pll->divn_shift;
|
||||
val |= sel.m << pll->params->div_nmp->divm_shift;
|
||||
val |= sel.n << pll->params->div_nmp->divn_shift;
|
||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
pll_writel_base(val, pll);
|
||||
udelay(1);
|
||||
@@ -1242,12 +1252,8 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
||||
pll->flags = pll_flags;
|
||||
pll->lock = lock;
|
||||
|
||||
pll->divp_shift = PLL_BASE_DIVP_SHIFT;
|
||||
pll->divp_width = PLL_BASE_DIVP_WIDTH;
|
||||
pll->divn_shift = PLL_BASE_DIVN_SHIFT;
|
||||
pll->divn_width = PLL_BASE_DIVN_WIDTH;
|
||||
pll->divm_shift = PLL_BASE_DIVM_SHIFT;
|
||||
pll->divm_width = PLL_BASE_DIVM_WIDTH;
|
||||
if (!pll_params->div_nmp)
|
||||
pll_params->div_nmp = &default_nmp;
|
||||
|
||||
return pll;
|
||||
}
|
||||
|
Reference in New Issue
Block a user