summaryrefslogtreecommitdiff
path: root/drivers/clk/tegra/clk-pll.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-13 11:04:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-13 11:04:14 -0700
commitf60a2abfdbf298a4722dfef331c38447fa18c4e3 (patch)
tree1ac56db32fb1909aedefc21b1c62d0bbe5a13e68 /drivers/clk/tegra/clk-pll.c
parent561a8eb3e1d219f415597c76dae44b530b7f961a (diff)
parent73c950da6ec523136090d6d4d6907a6ea8e8b67b (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.c159
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);