diff options
author | Peter De Schrijver <pdeschrijver@nvidia.com> | 2013-06-06 06:47:31 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2013-06-11 21:00:32 -0400 |
commit | 408a24f8227f259eea97c6b4f66d1592e2f651b6 (patch) | |
tree | 005327b8ed61bca47e149f2e4e6db91e62753117 /drivers/clk | |
parent | c09e32bb67a9fba318ae4387eaabba21e0d07a87 (diff) |
clk: tegra: Use override bits when needed
PLLM has override bits in the PMC. Use those when PLLM_OVERRIDE_ENABLE
is set.
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>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/tegra/clk-pll.c | 82 |
1 files changed, 49 insertions, 33 deletions
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 393b60c9c49d..197074a57754 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c | |||
@@ -117,10 +117,6 @@ | |||
117 | #define PLLCX_MISC2_DEFAULT 0x30211200 | 117 | #define PLLCX_MISC2_DEFAULT 0x30211200 |
118 | #define PLLCX_MISC3_DEFAULT 0x200 | 118 | #define PLLCX_MISC3_DEFAULT 0x200 |
119 | 119 | ||
120 | #define PMC_PLLM_WB0_OVERRIDE 0x1dc | ||
121 | #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 | ||
122 | #define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27) | ||
123 | |||
124 | #define PMC_SATA_PWRGT 0x1ac | 120 | #define PMC_SATA_PWRGT 0x1ac |
125 | #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) | 121 | #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) |
126 | #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) | 122 | #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) |
@@ -128,10 +124,12 @@ | |||
128 | #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) | 124 | #define pll_readl(offset, p) readl_relaxed(p->clk_base + offset) |
129 | #define pll_readl_base(p) pll_readl(p->params->base_reg, p) | 125 | #define pll_readl_base(p) pll_readl(p->params->base_reg, p) |
130 | #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) | 126 | #define pll_readl_misc(p) pll_readl(p->params->misc_reg, p) |
127 | #define pll_override_readl(offset, p) readl_relaxed(p->pmc + offset) | ||
131 | 128 | ||
132 | #define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset) | 129 | #define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset) |
133 | #define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p) | 130 | #define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p) |
134 | #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) | 131 | #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) |
132 | #define pll_override_writel(val, offset, p) writel(val, p->pmc + offset) | ||
135 | 133 | ||
136 | #define mask(w) ((1 << (w)) - 1) | 134 | #define mask(w) ((1 << (w)) - 1) |
137 | #define divm_mask(p) mask(p->params->div_nmp->divm_width) | 135 | #define divm_mask(p) mask(p->params->div_nmp->divm_width) |
@@ -413,29 +411,61 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, | |||
413 | struct tegra_clk_pll_freq_table *cfg) | 411 | struct tegra_clk_pll_freq_table *cfg) |
414 | { | 412 | { |
415 | u32 val; | 413 | u32 val; |
414 | struct tegra_clk_pll_params *params = pll->params; | ||
415 | struct div_nmp *div_nmp = params->div_nmp; | ||
416 | |||
417 | if ((pll->flags & TEGRA_PLLM) && | ||
418 | (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & | ||
419 | PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { | ||
420 | val = pll_override_readl(params->pmc_divp_reg, pll); | ||
421 | val &= ~(divp_mask(pll) << div_nmp->override_divp_shift); | ||
422 | val |= cfg->p << div_nmp->override_divp_shift; | ||
423 | pll_override_writel(val, params->pmc_divp_reg, pll); | ||
424 | |||
425 | val = pll_override_readl(params->pmc_divnm_reg, pll); | ||
426 | val &= ~(divm_mask(pll) << div_nmp->override_divm_shift) | | ||
427 | ~(divn_mask(pll) << div_nmp->override_divn_shift); | ||
428 | val |= (cfg->m << div_nmp->override_divm_shift) | | ||
429 | (cfg->n << div_nmp->override_divn_shift); | ||
430 | pll_override_writel(val, params->pmc_divnm_reg, pll); | ||
431 | } else { | ||
432 | val = pll_readl_base(pll); | ||
416 | 433 | ||
417 | val = pll_readl_base(pll); | 434 | val &= ~((divm_mask(pll) << div_nmp->divm_shift) | |
435 | (divn_mask(pll) << div_nmp->divn_shift) | | ||
436 | (divp_mask(pll) << div_nmp->divp_shift)); | ||
418 | 437 | ||
419 | val &= ~((divm_mask(pll) << pll->params->div_nmp->divm_shift) | | 438 | val |= ((cfg->m << div_nmp->divm_shift) | |
420 | (divn_mask(pll) << pll->params->div_nmp->divn_shift) | | 439 | (cfg->n << div_nmp->divn_shift) | |
421 | (divp_mask(pll) << pll->params->div_nmp->divp_shift)); | 440 | (cfg->p << div_nmp->divp_shift)); |
422 | val |= ((cfg->m << pll->params->div_nmp->divm_shift) | | ||
423 | (cfg->n << pll->params->div_nmp->divn_shift) | | ||
424 | (cfg->p << pll->params->div_nmp->divp_shift)); | ||
425 | 441 | ||
426 | pll_writel_base(val, pll); | 442 | pll_writel_base(val, pll); |
443 | } | ||
427 | } | 444 | } |
428 | 445 | ||
429 | static void _get_pll_mnp(struct tegra_clk_pll *pll, | 446 | static void _get_pll_mnp(struct tegra_clk_pll *pll, |
430 | struct tegra_clk_pll_freq_table *cfg) | 447 | struct tegra_clk_pll_freq_table *cfg) |
431 | { | 448 | { |
432 | u32 val; | 449 | u32 val; |
450 | struct tegra_clk_pll_params *params = pll->params; | ||
451 | struct div_nmp *div_nmp = params->div_nmp; | ||
452 | |||
453 | if ((pll->flags & TEGRA_PLLM) && | ||
454 | (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & | ||
455 | PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { | ||
456 | val = pll_override_readl(params->pmc_divp_reg, pll); | ||
457 | cfg->p = (val >> div_nmp->override_divp_shift) & divp_mask(pll); | ||
458 | |||
459 | val = pll_override_readl(params->pmc_divnm_reg, pll); | ||
460 | cfg->m = (val >> div_nmp->override_divm_shift) & divm_mask(pll); | ||
461 | cfg->n = (val >> div_nmp->override_divn_shift) & divn_mask(pll); | ||
462 | } else { | ||
463 | val = pll_readl_base(pll); | ||
433 | 464 | ||
434 | val = pll_readl_base(pll); | 465 | cfg->m = (val >> div_nmp->divm_shift) & divm_mask(pll); |
435 | 466 | cfg->n = (val >> div_nmp->divn_shift) & divn_mask(pll); | |
436 | cfg->m = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll)); | 467 | cfg->p = (val >> div_nmp->divp_shift) & divp_mask(pll); |
437 | cfg->n = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll)); | 468 | } |
438 | cfg->p = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll)); | ||
439 | } | 469 | } |
440 | 470 | ||
441 | static void _update_pll_cpcon(struct tegra_clk_pll *pll, | 471 | static void _update_pll_cpcon(struct tegra_clk_pll *pll, |
@@ -883,7 +913,6 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate, | |||
883 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 913 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
884 | unsigned long flags = 0; | 914 | unsigned long flags = 0; |
885 | int state, ret = 0; | 915 | int state, ret = 0; |
886 | u32 val; | ||
887 | 916 | ||
888 | if (pll->lock) | 917 | if (pll->lock) |
889 | spin_lock_irqsave(pll->lock, flags); | 918 | spin_lock_irqsave(pll->lock, flags); |
@@ -902,21 +931,7 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate, | |||
902 | if (ret < 0) | 931 | if (ret < 0) |
903 | goto out; | 932 | goto out; |
904 | 933 | ||
905 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); | 934 | _update_pll_mnp(pll, &cfg); |
906 | if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) { | ||
907 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2); | ||
908 | val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) : | ||
909 | (val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK); | ||
910 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2); | ||
911 | |||
912 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); | ||
913 | val &= ~(divn_mask(pll) | divm_mask(pll)); | ||
914 | val |= (cfg.m << pll->params->div_nmp->divm_shift) | | ||
915 | (cfg.n << pll->params->div_nmp->divn_shift); | ||
916 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE); | ||
917 | } else | ||
918 | _update_pll_mnp(pll, &cfg); | ||
919 | |||
920 | 935 | ||
921 | out: | 936 | out: |
922 | if (pll->lock) | 937 | if (pll->lock) |
@@ -1460,6 +1475,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, | |||
1460 | 1475 | ||
1461 | pll_flags |= TEGRA_PLL_BYPASS; | 1476 | pll_flags |= TEGRA_PLL_BYPASS; |
1462 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | 1477 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; |
1478 | pll_flags |= TEGRA_PLLM; | ||
1463 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | 1479 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, |
1464 | freq_table, lock); | 1480 | freq_table, lock); |
1465 | if (IS_ERR(pll)) | 1481 | if (IS_ERR(pll)) |