diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-13 11:04:14 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-13 11:04:14 -0700 |
commit | f60a2abfdbf298a4722dfef331c38447fa18c4e3 (patch) | |
tree | 1ac56db32fb1909aedefc21b1c62d0bbe5a13e68 /drivers/clk/tegra/clk-pll.c | |
parent | 561a8eb3e1d219f415597c76dae44b530b7f961a (diff) | |
parent | 73c950da6ec523136090d6d4d6907a6ea8e8b67b (diff) |
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd:
"The diff is dominated by the Allwinner A10/A20 SoCs getting converted
to the sunxi-ng framework. Otherwise, the heavy hitters are various
drivers for SoCs like AT91, Amlogic, Renesas, and Rockchip. There are
some other new clk drivers in here too but overall this is just a
bunch of clk drivers for various different pieces of hardware and a
collection of non-critical fixes for clk drivers.
New Drivers:
- Allwinner R40 SoCs
- Renesas R-Car Gen3 USB 2.0 clock selector PHY
- Atmel AT91 audio PLL
- Uniphier PXs3 SoCs
- ARC HSDK Board PLLs
- AXS10X Board PLLs
- STMicroelectronics STM32H743 SoCs
Removed Drivers:
- Non-compiling mb86s7x support
Updates:
- Allwinner A10/A20 SoCs converted to sunxi-ng framework
- Allwinner H3 CPU clk fixes
- Renesas R-Car D3 SoC
- Renesas V2H and M3-W modules
- Samsung Exynos5420/5422/5800 audio fixes
- Rockchip fractional clk approximation fixes
- Rockchip rk3126 SoC support within the rk3128 driver
- Amlogic gxbb CEC32 and sd_emmc clks
- Amlogic meson8b reset controller support
- IDT VersaClock 5P49V5925/5P49V6901 support
- Qualcomm MSM8996 SMMU clks
- Various 'const' applications for struct clk_ops
- si5351 PLL reset bugfix
- Uniphier audio on LD11/LD20 and ethernet support on LD11/LD20/Pro4/PXs2
- Assorted Tegra clk driver fixes"
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (120 commits)
clk: si5351: fix PLL reset
ASoC: atmel-classd: remove aclk clock
ASoC: atmel-classd: remove aclk clock from DT binding
clk: at91: clk-generated: make gclk determine audio_pll rate
clk: at91: clk-generated: create function to find best_diff
clk: at91: add audio pll clock drivers
dt-bindings: clk: at91: add audio plls to the compatible list
clk: at91: clk-generated: remove useless divisor loop
clk: mb86s7x: Drop non-building driver
clk: ti: check for null return in strrchr to avoid null dereferencing
clk: Don't write error code into divider register
clk: uniphier: add video input subsystem clock
clk: uniphier: add audio system clock
clk: stm32h7: Add stm32h743 clock driver
clk: gate: expose clk_gate_ops::is_enabled
clk: nxp: clk-lpc32xx: rename clk_gate_is_enabled()
clk: uniphier: add PXs3 clock data
clk: hi6220: change watchdog clock source
clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808
clk: cs2000: Add cs2000_set_saved_rate
...
Diffstat (limited to 'drivers/clk/tegra/clk-pll.c')
-rw-r--r-- | drivers/clk/tegra/clk-pll.c | 159 |
1 files changed, 38 insertions, 121 deletions
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 159a854779e6..7c369e21c91c 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -363,7 +363,7 @@ static void _clk_pll_enable(struct clk_hw *hw) val = pll_readl(pll->params->iddq_reg, pll); val &= ~BIT(pll->params->iddq_bit_idx); pll_writel(val, pll->params->iddq_reg, pll); - udelay(2); + udelay(5); } if (pll->params->reset_reg) { @@ -418,6 +418,26 @@ static void _clk_pll_disable(struct clk_hw *hw) } } +static void pll_clk_start_ss(struct tegra_clk_pll *pll) +{ + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); + + val |= pll->params->ssc_ctrl_en_mask; + pll_writel(val, pll->params->ssc_ctrl_reg, pll); + } +} + +static void pll_clk_stop_ss(struct tegra_clk_pll *pll) +{ + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); + + val &= ~pll->params->ssc_ctrl_en_mask; + pll_writel(val, pll->params->ssc_ctrl_reg, pll); + } +} + static int clk_pll_enable(struct clk_hw *hw) { struct tegra_clk_pll *pll = to_clk_pll(hw); @@ -431,6 +451,8 @@ static int clk_pll_enable(struct clk_hw *hw) ret = clk_pll_wait_for_lock(pll); + pll_clk_start_ss(pll); + if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); @@ -445,6 +467,8 @@ static void clk_pll_disable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); + pll_clk_stop_ss(pll); + _clk_pll_disable(hw); if (pll->lock) @@ -666,6 +690,8 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, struct tegra_clk_pll_params *params = pll->params; struct div_nmp *div_nmp = params->div_nmp; + *cfg = (struct tegra_clk_pll_freq_table) { }; + if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { @@ -716,26 +742,6 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll, pll_writel_misc(val, pll); } -static void pll_clk_start_ss(struct tegra_clk_pll *pll) -{ - if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { - u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); - - val |= pll->params->ssc_ctrl_en_mask; - pll_writel(val, pll->params->ssc_ctrl_reg, pll); - } -} - -static void pll_clk_stop_ss(struct tegra_clk_pll *pll) -{ - if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { - u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); - - val &= ~pll->params->ssc_ctrl_en_mask; - pll_writel(val, pll->params->ssc_ctrl_reg, pll); - } -} - static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, unsigned long rate) { @@ -2251,7 +2257,7 @@ tegra_clk_register_pllu_tegra114(const char *name, const char *parent_name, } #endif -#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) +#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) || defined(CONFIG_ARCH_TEGRA_210_SOC) static const struct clk_ops tegra_clk_pllss_ops = { .is_enabled = clk_pll_is_enabled, .enable = clk_pll_enable, @@ -2349,7 +2355,6 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, struct tegra_clk_pll_params *pll_params, spinlock_t *lock, unsigned long parent_rate) { - u32 val; struct tegra_clk_pll *pll; struct clk *clk; @@ -2363,26 +2368,8 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, if (IS_ERR(pll)) return ERR_CAST(pll); - /* program minimum rate by default */ - - val = pll_readl_base(pll); - if (val & PLL_BASE_ENABLE) - WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & - BIT(pll_params->iddq_bit_idx)); - else { - val = 0x4 << divm_shift(pll); - val |= 0x41 << divn_shift(pll); - pll_writel_base(val, pll); - } - - /* disable lock override */ - - val = pll_readl_misc(pll); - val &= ~BIT(29); - pll_writel_misc(val, pll); - clk = _tegra_clk_register_pll(pll, name, parent_name, flags, - &tegra_clk_pllre_ops); + &tegra_clk_pll_ops); if (IS_ERR(clk)) kfree(pll); @@ -2604,46 +2591,6 @@ struct clk *tegra_clk_register_pllc_tegra210(const char *name, return clk; } -struct clk *tegra_clk_register_pllxc_tegra210(const char *name, - const char *parent_name, void __iomem *clk_base, - void __iomem *pmc, unsigned long flags, - struct tegra_clk_pll_params *pll_params, - spinlock_t *lock) -{ - struct tegra_clk_pll *pll; - struct clk *clk, *parent; - unsigned long parent_rate; - - parent = __clk_lookup(parent_name); - if (!parent) { - WARN(1, "parent clk %s of %s must be registered first\n", - name, parent_name); - return ERR_PTR(-EINVAL); - } - - if (!pll_params->pdiv_tohw) - return ERR_PTR(-EINVAL); - - parent_rate = clk_get_rate(parent); - - pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); - - if (pll_params->adjust_vco) - pll_params->vco_min = pll_params->adjust_vco(pll_params, - parent_rate); - - pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); - if (IS_ERR(pll)) - return ERR_CAST(pll); - - clk = _tegra_clk_register_pll(pll, name, parent_name, flags, - &tegra_clk_pll_ops); - if (IS_ERR(clk)) - kfree(pll); - - return clk; -} - struct clk *tegra_clk_register_pllss_tegra210(const char *name, const char *parent_name, void __iomem *clk_base, unsigned long flags, @@ -2652,10 +2599,8 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, { struct tegra_clk_pll *pll; struct clk *clk, *parent; - struct tegra_clk_pll_freq_table cfg; unsigned long parent_rate; u32 val; - int i; if (!pll_params->div_nmp) return ERR_PTR(-EINVAL); @@ -2667,13 +2612,11 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, return ERR_PTR(-EINVAL); } - pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); - if (IS_ERR(pll)) - return ERR_CAST(pll); - - val = pll_readl_base(pll); - val &= ~PLLSS_REF_SRC_SEL_MASK; - pll_writel_base(val, pll); + val = readl_relaxed(clk_base + pll_params->base_reg); + if (val & PLLSS_REF_SRC_SEL_MASK) { + WARN(1, "not supported reference clock for %s\n", name); + return ERR_PTR(-EINVAL); + } parent_rate = clk_get_rate(parent); @@ -2683,36 +2626,10 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, pll_params->vco_min = pll_params->adjust_vco(pll_params, parent_rate); - /* initialize PLL to minimum rate */ - - cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); - cfg.n = cfg.m * pll_params->vco_min / parent_rate; - - for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++) - ; - if (!i) { - kfree(pll); - return ERR_PTR(-EINVAL); - } - - cfg.p = pll_params->pdiv_tohw[i-1].hw_val; - - _update_pll_mnp(pll, &cfg); - - pll_writel_misc(PLLSS_MISC_DEFAULT, pll); - - val = pll_readl_base(pll); - if (val & PLL_BASE_ENABLE) { - if (val & BIT(pll_params->iddq_bit_idx)) { - WARN(1, "%s is on but IDDQ set\n", name); - kfree(pll); - return ERR_PTR(-EINVAL); - } - } else - val |= BIT(pll_params->iddq_bit_idx); - - val &= ~PLLSS_LOCK_OVERRIDE; - pll_writel_base(val, pll); + pll_params->flags |= TEGRA_PLL_BYPASS; + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); + if (IS_ERR(pll)) + return ERR_CAST(pll); clk = _tegra_clk_register_pll(pll, name, parent_name, flags, &tegra_clk_pll_ops); |