forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/clk/tegra/clk-pll.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms and conditions of the GNU General Public License,
6
- * version 2, as published by the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
12
- *
13
- * You should have received a copy of the GNU General Public License
14
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
154 */
165
176 #include <linux/slab.h>
....@@ -338,16 +327,26 @@
338327 return clk_pll_wait_for_lock(pll);
339328 }
340329
330
+static bool pllm_clk_is_gated_by_pmc(struct tegra_clk_pll *pll)
331
+{
332
+ u32 val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
333
+
334
+ return (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) &&
335
+ !(val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE);
336
+}
337
+
341338 static int clk_pll_is_enabled(struct clk_hw *hw)
342339 {
343340 struct tegra_clk_pll *pll = to_clk_pll(hw);
344341 u32 val;
345342
346
- if (pll->params->flags & TEGRA_PLLM) {
347
- val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
348
- if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
349
- return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
350
- }
343
+ /*
344
+ * Power Management Controller (PMC) can override the PLLM clock
345
+ * settings, including the enable-state. The PLLM is enabled when
346
+ * PLLM's CaR state is ON and when PLLM isn't gated by PMC.
347
+ */
348
+ if ((pll->params->flags & TEGRA_PLLM) && pllm_clk_is_gated_by_pmc(pll))
349
+ return 0;
351350
352351 val = pll_readl_base(pll);
353352
....@@ -443,6 +442,9 @@
443442 struct tegra_clk_pll *pll = to_clk_pll(hw);
444443 unsigned long flags = 0;
445444 int ret;
445
+
446
+ if (clk_pll_is_enabled(hw))
447
+ return 0;
446448
447449 if (pll->lock)
448450 spin_lock_irqsave(pll->lock, flags);
....@@ -590,12 +592,13 @@
590592 cfg->n = cfg->output_rate / cfreq;
591593 cfg->cpcon = OUT_OF_TABLE_CPCON;
592594
593
- if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
594
- (1 << p_div) > divp_max(pll)
595
- || cfg->output_rate > pll->params->vco_max) {
595
+ if (cfg->m == 0 || cfg->m > divm_max(pll) ||
596
+ cfg->n > divn_max(pll) || (1 << p_div) > divp_max(pll) ||
597
+ cfg->output_rate > pll->params->vco_max) {
596598 return -EINVAL;
597599 }
598600
601
+ cfg->output_rate = cfg->n * DIV_ROUND_UP(parent_rate, cfg->m);
599602 cfg->output_rate >>= p_div;
600603
601604 if (pll->params->pdiv_tohw) {
....@@ -751,13 +754,19 @@
751754
752755 state = clk_pll_is_enabled(hw);
753756
757
+ if (state && pll->params->pre_rate_change) {
758
+ ret = pll->params->pre_rate_change();
759
+ if (WARN_ON(ret))
760
+ return ret;
761
+ }
762
+
754763 _get_pll_mnp(pll, &old_cfg);
755764
756765 if (state && pll->params->defaults_set && pll->params->dyn_ramp &&
757766 (cfg->m == old_cfg.m) && (cfg->p == old_cfg.p)) {
758767 ret = pll->params->dyn_ramp(pll, cfg);
759768 if (!ret)
760
- return 0;
769
+ goto done;
761770 }
762771
763772 if (state) {
....@@ -778,6 +787,10 @@
778787 ret = clk_pll_wait_for_lock(pll);
779788 pll_clk_start_ss(pll);
780789 }
790
+
791
+done:
792
+ if (state && pll->params->post_rate_change)
793
+ pll->params->post_rate_change();
781794
782795 return ret;
783796 }
....@@ -939,10 +952,15 @@
939952 static int clk_plle_enable(struct clk_hw *hw)
940953 {
941954 struct tegra_clk_pll *pll = to_clk_pll(hw);
942
- unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
943955 struct tegra_clk_pll_freq_table sel;
956
+ unsigned long input_rate;
944957 u32 val;
945958 int err;
959
+
960
+ if (clk_pll_is_enabled(hw))
961
+ return 0;
962
+
963
+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
946964
947965 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
948966 return -EINVAL;
....@@ -1010,6 +1028,27 @@
10101028 return rate;
10111029 }
10121030
1031
+static void tegra_clk_pll_restore_context(struct clk_hw *hw)
1032
+{
1033
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
1034
+ struct clk_hw *parent = clk_hw_get_parent(hw);
1035
+ unsigned long parent_rate = clk_hw_get_rate(parent);
1036
+ unsigned long rate = clk_hw_get_rate(hw);
1037
+
1038
+ if (clk_pll_is_enabled(hw))
1039
+ return;
1040
+
1041
+ if (pll->params->set_defaults)
1042
+ pll->params->set_defaults(pll);
1043
+
1044
+ clk_pll_set_rate(hw, rate, parent_rate);
1045
+
1046
+ if (!__clk_get_enable_count(hw->clk))
1047
+ clk_pll_disable(hw);
1048
+ else
1049
+ clk_pll_enable(hw);
1050
+}
1051
+
10131052 const struct clk_ops tegra_clk_pll_ops = {
10141053 .is_enabled = clk_pll_is_enabled,
10151054 .enable = clk_pll_enable,
....@@ -1017,6 +1056,7 @@
10171056 .recalc_rate = clk_pll_recalc_rate,
10181057 .round_rate = clk_pll_round_rate,
10191058 .set_rate = clk_pll_set_rate,
1059
+ .restore_context = tegra_clk_pll_restore_context,
10201060 };
10211061
10221062 const struct clk_ops tegra_clk_plle_ops = {
....@@ -1355,6 +1395,9 @@
13551395 int ret;
13561396 unsigned long flags = 0;
13571397
1398
+ if (clk_pll_is_enabled(hw))
1399
+ return 0;
1400
+
13581401 if (pll->lock)
13591402 spin_lock_irqsave(pll->lock, flags);
13601403
....@@ -1567,7 +1610,9 @@
15671610 u32 val;
15681611 int ret;
15691612 unsigned long flags = 0;
1570
- unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
1613
+ unsigned long input_rate;
1614
+
1615
+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
15711616
15721617 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
15731618 return -EINVAL;
....@@ -1626,7 +1671,7 @@
16261671 pll_writel(val, PLLE_SS_CTRL, pll);
16271672 udelay(1);
16281673
1629
- /* Enable hw control of xusb brick pll */
1674
+ /* Enable HW control of XUSB brick PLL */
16301675 val = pll_readl_misc(pll);
16311676 val &= ~PLLE_MISC_IDDQ_SW_CTRL;
16321677 pll_writel_misc(val, pll);
....@@ -1649,7 +1694,7 @@
16491694 val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
16501695 pll_writel(val, XUSBIO_PLL_CFG0, pll);
16511696
1652
- /* Enable hw control of SATA pll */
1697
+ /* Enable HW control of SATA PLL */
16531698 val = pll_readl(SATA_PLL_CFG0, pll);
16541699 val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
16551700 val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET;
....@@ -1795,6 +1840,27 @@
17951840
17961841 return ret;
17971842 }
1843
+
1844
+static void _clk_plle_tegra_init_parent(struct tegra_clk_pll *pll)
1845
+{
1846
+ u32 val, val_aux;
1847
+
1848
+ /* ensure parent is set to pll_ref */
1849
+ val = pll_readl_base(pll);
1850
+ val_aux = pll_readl(pll->params->aux_reg, pll);
1851
+
1852
+ if (val & PLL_BASE_ENABLE) {
1853
+ if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
1854
+ (val_aux & PLLE_AUX_PLLP_SEL))
1855
+ WARN(1, "pll_e enabled with unsupported parent %s\n",
1856
+ (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
1857
+ "pll_re_vco");
1858
+ } else {
1859
+ val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
1860
+ pll_writel(val_aux, pll->params->aux_reg, pll);
1861
+ fence_udelay(1, pll->clk_base);
1862
+ }
1863
+}
17981864 #endif
17991865
18001866 static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
....@@ -1823,7 +1889,7 @@
18231889 const char *name, const char *parent_name, unsigned long flags,
18241890 const struct clk_ops *ops)
18251891 {
1826
- struct clk_init_data init = {};
1892
+ struct clk_init_data init;
18271893
18281894 init.name = name;
18291895 init.ops = ops;
....@@ -2207,27 +2273,12 @@
22072273 {
22082274 struct tegra_clk_pll *pll;
22092275 struct clk *clk;
2210
- u32 val, val_aux;
22112276
22122277 pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
22132278 if (IS_ERR(pll))
22142279 return ERR_CAST(pll);
22152280
2216
- /* ensure parent is set to pll_re_vco */
2217
-
2218
- val = pll_readl_base(pll);
2219
- val_aux = pll_readl(pll_params->aux_reg, pll);
2220
-
2221
- if (val & PLL_BASE_ENABLE) {
2222
- if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
2223
- (val_aux & PLLE_AUX_PLLP_SEL))
2224
- WARN(1, "pll_e enabled with unsupported parent %s\n",
2225
- (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
2226
- "pll_re_vco");
2227
- } else {
2228
- val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
2229
- pll_writel(val_aux, pll_params->aux_reg, pll);
2230
- }
2281
+ _clk_plle_tegra_init_parent(pll);
22312282
22322283 clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
22332284 &tegra_clk_plle_tegra114_ops);
....@@ -2269,6 +2320,7 @@
22692320 .recalc_rate = clk_pll_recalc_rate,
22702321 .round_rate = clk_pll_ramp_round_rate,
22712322 .set_rate = clk_pllxc_set_rate,
2323
+ .restore_context = tegra_clk_pll_restore_context,
22722324 };
22732325
22742326 struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
....@@ -2380,6 +2432,16 @@
23802432 return clk;
23812433 }
23822434
2435
+static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
2436
+{
2437
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
2438
+ u32 val;
2439
+
2440
+ val = pll_readl_base(pll);
2441
+
2442
+ return val & PLLE_BASE_ENABLE ? 1 : 0;
2443
+}
2444
+
23832445 static int clk_plle_tegra210_enable(struct clk_hw *hw)
23842446 {
23852447 struct tegra_clk_pll *pll = to_clk_pll(hw);
....@@ -2387,7 +2449,12 @@
23872449 u32 val;
23882450 int ret = 0;
23892451 unsigned long flags = 0;
2390
- unsigned long input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
2452
+ unsigned long input_rate;
2453
+
2454
+ if (clk_plle_tegra210_is_enabled(hw))
2455
+ return 0;
2456
+
2457
+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
23912458
23922459 if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
23932460 return -EINVAL;
....@@ -2498,14 +2565,11 @@
24982565 spin_unlock_irqrestore(pll->lock, flags);
24992566 }
25002567
2501
-static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
2568
+static void tegra_clk_plle_t210_restore_context(struct clk_hw *hw)
25022569 {
25032570 struct tegra_clk_pll *pll = to_clk_pll(hw);
2504
- u32 val;
25052571
2506
- val = pll_readl_base(pll);
2507
-
2508
- return val & PLLE_BASE_ENABLE ? 1 : 0;
2572
+ _clk_plle_tegra_init_parent(pll);
25092573 }
25102574
25112575 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
....@@ -2513,6 +2577,7 @@
25132577 .enable = clk_plle_tegra210_enable,
25142578 .disable = clk_plle_tegra210_disable,
25152579 .recalc_rate = clk_pll_recalc_rate,
2580
+ .restore_context = tegra_clk_plle_t210_restore_context,
25162581 };
25172582
25182583 struct clk *tegra_clk_register_plle_tegra210(const char *name,
....@@ -2523,27 +2588,12 @@
25232588 {
25242589 struct tegra_clk_pll *pll;
25252590 struct clk *clk;
2526
- u32 val, val_aux;
25272591
25282592 pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
25292593 if (IS_ERR(pll))
25302594 return ERR_CAST(pll);
25312595
2532
- /* ensure parent is set to pll_re_vco */
2533
-
2534
- val = pll_readl_base(pll);
2535
- val_aux = pll_readl(pll_params->aux_reg, pll);
2536
-
2537
- if (val & PLLE_BASE_ENABLE) {
2538
- if ((val_aux & PLLE_AUX_PLLRE_SEL) ||
2539
- (val_aux & PLLE_AUX_PLLP_SEL))
2540
- WARN(1, "pll_e enabled with unsupported parent %s\n",
2541
- (val_aux & PLLE_AUX_PLLP_SEL) ? "pllp_out0" :
2542
- "pll_re_vco");
2543
- } else {
2544
- val_aux &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
2545
- pll_writel(val_aux, pll_params->aux_reg, pll);
2546
- }
2596
+ _clk_plle_tegra_init_parent(pll);
25472597
25482598 clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
25492599 &tegra_clk_plle_tegra210_ops);