hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/clk/tegra/clk-tegra20.c
....@@ -1,17 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2012, 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/io.h>
....@@ -140,8 +129,6 @@
140129
141130 static void __iomem *clk_base;
142131 static void __iomem *pmc_base;
143
-
144
-static DEFINE_SPINLOCK(emc_lock);
145132
146133 #define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \
147134 _clk_num, _gate_flags, _clk_id) \
....@@ -404,6 +391,8 @@
404391 .lock_delay = 300,
405392 .freq_table = pll_x_freq_table,
406393 .flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
394
+ .pre_rate_change = tegra_cclk_pre_pllx_rate_change,
395
+ .post_rate_change = tegra_cclk_post_pllx_rate_change,
407396 };
408397
409398 static struct tegra_clk_pll_params pll_e_params = {
....@@ -471,7 +460,6 @@
471460 { .con_id = "cdev1", .dt_id = TEGRA20_CLK_CDEV1 },
472461 { .con_id = "cdev2", .dt_id = TEGRA20_CLK_CDEV2 },
473462 { .con_id = "clk_32k", .dt_id = TEGRA20_CLK_CLK_32K },
474
- { .con_id = "blink", .dt_id = TEGRA20_CLK_BLINK },
475463 { .con_id = "clk_m", .dt_id = TEGRA20_CLK_CLK_M },
476464 { .con_id = "pll_ref", .dt_id = TEGRA20_CLK_PLL_REF },
477465 { .dev_id = "tegra20-i2s.0", .dt_id = TEGRA20_CLK_I2S1 },
....@@ -550,7 +538,6 @@
550538 [tegra_clk_csi] = { .dt_id = TEGRA20_CLK_CSI, .present = true },
551539 [tegra_clk_isp] = { .dt_id = TEGRA20_CLK_ISP, .present = true },
552540 [tegra_clk_clk_32k] = { .dt_id = TEGRA20_CLK_CLK_32K, .present = true },
553
- [tegra_clk_blink] = { .dt_id = TEGRA20_CLK_BLINK, .present = true },
554541 [tegra_clk_hclk] = { .dt_id = TEGRA20_CLK_HCLK, .present = true },
555542 [tegra_clk_pclk] = { .dt_id = TEGRA20_CLK_PCLK, .present = true },
556543 [tegra_clk_pll_p_out1] = { .dt_id = TEGRA20_CLK_PLL_P_OUT1, .present = true },
....@@ -717,9 +704,10 @@
717704 struct clk *clk;
718705
719706 /* CCLK */
720
- clk = tegra_clk_register_super_mux("cclk", cclk_parents,
707
+ clk = tegra_clk_register_super_cclk("cclk", cclk_parents,
721708 ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
722
- clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
709
+ clk_base + CCLK_BURST_POLICY, TEGRA20_SUPER_CLK,
710
+ NULL);
723711 clks[TEGRA20_CLK_CCLK] = clk;
724712
725713 /* SCLK */
....@@ -771,7 +759,6 @@
771759 static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
772760 static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c",
773761 "clk_m" };
774
-static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
775762
776763 static struct tegra_periph_init_data tegra_periph_clk_list[] = {
777764 TEGRA_INIT_DATA_MUX("i2s1", i2s1_parents, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, TEGRA20_CLK_I2S1),
....@@ -798,31 +785,6 @@
798785 TEGRA_INIT_DATA_NODIV("disp2", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, TEGRA20_CLK_DISP2),
799786 };
800787
801
-static void __init tegra20_emc_clk_init(void)
802
-{
803
- struct clk *clk;
804
-
805
- clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
806
- ARRAY_SIZE(mux_pllmcp_clkm),
807
- CLK_SET_RATE_NO_REPARENT,
808
- clk_base + CLK_SOURCE_EMC,
809
- 30, 2, 0, &emc_lock);
810
-
811
- clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
812
- &emc_lock);
813
- clks[TEGRA20_CLK_MC] = clk;
814
-
815
- /*
816
- * Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
817
- * the same time due to a HW bug, this won't happen because we're
818
- * defining 'emc_mux' and 'emc' as distinct clocks.
819
- */
820
- clk = tegra_clk_register_divider("emc", "emc_mux",
821
- clk_base + CLK_SOURCE_EMC, CLK_IS_CRITICAL,
822
- TEGRA_DIVIDER_INT, 0, 8, 1, &emc_lock);
823
- clks[TEGRA20_CLK_EMC] = clk;
824
-}
825
-
826788 static void __init tegra20_periph_clk_init(void)
827789 {
828790 struct tegra_periph_init_data *data;
....@@ -836,7 +798,13 @@
836798 clks[TEGRA20_CLK_AC97] = clk;
837799
838800 /* emc */
839
- tegra20_emc_clk_init();
801
+ clk = tegra20_clk_register_emc(clk_base + CLK_SOURCE_EMC, false);
802
+
803
+ clks[TEGRA20_CLK_EMC] = clk;
804
+
805
+ clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
806
+ NULL);
807
+ clks[TEGRA20_CLK_MC] = clk;
840808
841809 /* dsi */
842810 clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
....@@ -988,6 +956,7 @@
988956 static void tegra20_cpu_clock_resume(void)
989957 {
990958 unsigned int reg, policy;
959
+ u32 misc, base;
991960
992961 /* Is CPU complex already running on PLLX? */
993962 reg = readl(clk_base + CCLK_BURST_POLICY);
....@@ -1001,15 +970,21 @@
1001970 BUG();
1002971
1003972 if (reg != CCLK_BURST_POLICY_PLLX) {
1004
- /* restore PLLX settings if CPU is on different PLL */
1005
- writel(tegra20_cpu_clk_sctx.pllx_misc,
1006
- clk_base + PLLX_MISC);
1007
- writel(tegra20_cpu_clk_sctx.pllx_base,
1008
- clk_base + PLLX_BASE);
973
+ misc = readl_relaxed(clk_base + PLLX_MISC);
974
+ base = readl_relaxed(clk_base + PLLX_BASE);
1009975
1010
- /* wait for PLL stabilization if PLLX was enabled */
1011
- if (tegra20_cpu_clk_sctx.pllx_base & (1 << 30))
1012
- udelay(300);
976
+ if (misc != tegra20_cpu_clk_sctx.pllx_misc ||
977
+ base != tegra20_cpu_clk_sctx.pllx_base) {
978
+ /* restore PLLX settings if CPU is on different PLL */
979
+ writel(tegra20_cpu_clk_sctx.pllx_misc,
980
+ clk_base + PLLX_MISC);
981
+ writel(tegra20_cpu_clk_sctx.pllx_base,
982
+ clk_base + PLLX_BASE);
983
+
984
+ /* wait for PLL stabilization if PLLX was enabled */
985
+ if (tegra20_cpu_clk_sctx.pllx_base & (1 << 30))
986
+ udelay(300);
987
+ }
1013988 }
1014989
1015990 /*
....@@ -1057,10 +1032,8 @@
10571032 { TEGRA20_CLK_UARTC, TEGRA20_CLK_PLL_P, 0, 0 },
10581033 { TEGRA20_CLK_UARTD, TEGRA20_CLK_PLL_P, 0, 0 },
10591034 { TEGRA20_CLK_UARTE, TEGRA20_CLK_PLL_P, 0, 0 },
1060
- { TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 1 },
1061
- { TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 1 },
1062
- { TEGRA20_CLK_CDEV1, TEGRA20_CLK_CLK_MAX, 0, 1 },
1063
- { TEGRA20_CLK_BLINK, TEGRA20_CLK_CLK_MAX, 32768, 1 },
1035
+ { TEGRA20_CLK_PLL_A, TEGRA20_CLK_CLK_MAX, 56448000, 0 },
1036
+ { TEGRA20_CLK_PLL_A_OUT0, TEGRA20_CLK_CLK_MAX, 11289600, 0 },
10641037 { TEGRA20_CLK_I2S1, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
10651038 { TEGRA20_CLK_I2S2, TEGRA20_CLK_PLL_A_OUT0, 11289600, 0 },
10661039 { TEGRA20_CLK_SDMMC1, TEGRA20_CLK_PLL_P, 48000000, 0 },
....@@ -1072,11 +1045,9 @@
10721045 { TEGRA20_CLK_SBC3, TEGRA20_CLK_PLL_P, 100000000, 0 },
10731046 { TEGRA20_CLK_SBC4, TEGRA20_CLK_PLL_P, 100000000, 0 },
10741047 { TEGRA20_CLK_HOST1X, TEGRA20_CLK_PLL_C, 150000000, 0 },
1075
- { TEGRA20_CLK_DISP1, TEGRA20_CLK_PLL_P, 600000000, 0 },
1076
- { TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 },
10771048 { TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
10781049 { TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
1079
- { TEGRA20_CLK_VDE, TEGRA20_CLK_CLK_MAX, 300000000, 0 },
1050
+ { TEGRA20_CLK_VDE, TEGRA20_CLK_PLL_C, 300000000, 0 },
10801051 /* must be the last entry */
10811052 { TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
10821053 };
....@@ -1116,6 +1087,8 @@
11161087 if (IS_ERR(clk))
11171088 return clk;
11181089
1090
+ hw = __clk_get_hw(clk);
1091
+
11191092 /*
11201093 * Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
11211094 * clock is created by the pinctrl driver. It is possible for clk user
....@@ -1125,10 +1098,13 @@
11251098 */
11261099 if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
11271100 clkspec->args[0] == TEGRA20_CLK_CDEV2) {
1128
- hw = __clk_get_hw(clk);
1129
-
11301101 parent_hw = clk_hw_get_parent(hw);
11311102 if (!parent_hw)
1103
+ return ERR_PTR(-EPROBE_DEFER);
1104
+ }
1105
+
1106
+ if (clkspec->args[0] == TEGRA20_CLK_EMC) {
1107
+ if (!tegra20_clk_emc_driver_available(hw))
11321108 return ERR_PTR(-EPROBE_DEFER);
11331109 }
11341110
....@@ -1152,6 +1128,7 @@
11521128 }
11531129
11541130 pmc_base = of_iomap(node, 0);
1131
+ of_node_put(node);
11551132 if (!pmc_base) {
11561133 pr_err("Can't map pmc registers\n");
11571134 BUG();
....@@ -1169,7 +1146,6 @@
11691146 tegra_super_clk_gen4_init(clk_base, pmc_base, tegra20_clks, NULL);
11701147 tegra20_periph_clk_init();
11711148 tegra20_audio_clk_init();
1172
- tegra_pmc_clk_init(pmc_base, tegra20_clks);
11731149
11741150 tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX);
11751151