forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
....@@ -1,17 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
3
- *
4
- * This software is licensed under the terms of the GNU General Public
5
- * License version 2, as published by the Free Software Foundation, and
6
- * may be copied, distributed, and modified under those terms.
7
- *
8
- * This program is distributed in the hope that it will be useful,
9
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- * GNU General Public License for more details.
124 */
135
146 #include <linux/clk-provider.h>
7
+#include <linux/io.h>
158 #include <linux/platform_device.h>
169 #include <linux/regmap.h>
1710
....@@ -52,32 +45,43 @@
5245 * the base (2x, 4x and 8x), and one variable divider (the one true
5346 * pll audio).
5447 *
55
- * We don't have any need for the variable divider for now, so we just
56
- * hardcode it to match with the clock names
48
+ * With sigma-delta modulation for fractional-N on the audio PLL,
49
+ * we have to use specific dividers. This means the variable divider
50
+ * can no longer be used, as the audio codec requests the exact clock
51
+ * rates we support through this mechanism. So we now hard code the
52
+ * variable divider to 1. This means the clock rates will no longer
53
+ * match the clock names.
5754 */
5855 #define SUN8I_R40_PLL_AUDIO_REG 0x008
5956
60
-static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
61
- "osc24M", 0x008,
62
- 8, 7, /* N */
63
- 0, 5, /* M */
64
- BIT(31), /* gate */
65
- BIT(28), /* lock */
66
- CLK_SET_RATE_UNGATE);
57
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
58
+ { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 },
59
+ { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 },
60
+};
6761
68
-/* TODO: The result of N/M is required to be in [8, 25] range. */
69
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video0_clk, "pll-video0",
70
- "osc24M", 0x0010,
71
- 192000000, /* Minimum rate */
72
- 8, 7, /* N */
73
- 0, 4, /* M */
74
- BIT(24), /* frac enable */
75
- BIT(25), /* frac select */
76
- 270000000, /* frac rate 0 */
77
- 297000000, /* frac rate 1 */
78
- BIT(31), /* gate */
79
- BIT(28), /* lock */
80
- CLK_SET_RATE_UNGATE);
62
+static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
63
+ "osc24M", 0x008,
64
+ 8, 7, /* N */
65
+ 0, 5, /* M */
66
+ pll_audio_sdm_table, BIT(24),
67
+ 0x284, BIT(31),
68
+ BIT(31), /* gate */
69
+ BIT(28), /* lock */
70
+ CLK_SET_RATE_UNGATE);
71
+
72
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
73
+ "osc24M", 0x0010,
74
+ 192000000, /* Minimum rate */
75
+ 1008000000, /* Maximum rate */
76
+ 8, 7, /* N */
77
+ 0, 4, /* M */
78
+ BIT(24), /* frac enable */
79
+ BIT(25), /* frac select */
80
+ 270000000, /* frac rate 0 */
81
+ 297000000, /* frac rate 1 */
82
+ BIT(31), /* gate */
83
+ BIT(28), /* lock */
84
+ CLK_SET_RATE_UNGATE);
8185
8286 /* TODO: The result of N/M is required to be in [8, 25] range. */
8387 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
....@@ -152,19 +156,19 @@
152156 },
153157 };
154158
155
-/* TODO: The result of N/M is required to be in [8, 25] range. */
156
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN(pll_video1_clk, "pll-video1",
157
- "osc24M", 0x030,
158
- 192000000, /* Minimum rate */
159
- 8, 7, /* N */
160
- 0, 4, /* M */
161
- BIT(24), /* frac enable */
162
- BIT(25), /* frac select */
163
- 270000000, /* frac rate 0 */
164
- 297000000, /* frac rate 1 */
165
- BIT(31), /* gate */
166
- BIT(28), /* lock */
167
- CLK_SET_RATE_UNGATE);
159
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video1_clk, "pll-video1",
160
+ "osc24M", 0x030,
161
+ 192000000, /* Minimum rate */
162
+ 1008000000, /* Maximum rate */
163
+ 8, 7, /* N */
164
+ 0, 4, /* M */
165
+ BIT(24), /* frac enable */
166
+ BIT(25), /* frac select */
167
+ 270000000, /* frac rate 0 */
168
+ 297000000, /* frac rate 1 */
169
+ BIT(31), /* gate */
170
+ BIT(28), /* lock */
171
+ CLK_SET_RATE_UNGATE);
168172
169173 static struct ccu_nkm pll_sata_clk = {
170174 .enable = BIT(31),
....@@ -768,7 +772,8 @@
768772 .reg = 0x1f0,
769773 .features = CCU_FEATURE_FIXED_PREDIV,
770774 .hw.init = CLK_HW_INIT_PARENTS("outa", out_parents,
771
- &ccu_mp_ops, 0),
775
+ &ccu_mp_ops,
776
+ CLK_SET_RATE_PARENT),
772777 }
773778 };
774779
....@@ -786,7 +791,8 @@
786791 .reg = 0x1f4,
787792 .features = CCU_FEATURE_FIXED_PREDIV,
788793 .hw.init = CLK_HW_INIT_PARENTS("outb", out_parents,
789
- &ccu_mp_ops, 0),
794
+ &ccu_mp_ops,
795
+ CLK_SET_RATE_PARENT),
790796 }
791797 };
792798
....@@ -951,25 +957,37 @@
951957 };
952958
953959 /* Fixed Factor clocks */
954
-static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
960
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
955961
956
-/* We hardcode the divider to 4 for now */
957
-static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
958
- "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
959
-static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
960
- "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
961
-static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
962
- "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
963
-static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
964
- "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
965
-static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
966
- "pll-periph0", 1, 2, 0);
967
-static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
968
- "pll-periph1", 1, 2, 0);
969
-static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
970
- "pll-video0", 1, 2, 0);
971
-static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
972
- "pll-video1", 1, 2, 0);
962
+static const struct clk_hw *clk_parent_pll_audio[] = {
963
+ &pll_audio_base_clk.common.hw
964
+};
965
+
966
+/* We hardcode the divider to 1 for now */
967
+static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
968
+ clk_parent_pll_audio,
969
+ 1, 1, CLK_SET_RATE_PARENT);
970
+static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
971
+ clk_parent_pll_audio,
972
+ 2, 1, CLK_SET_RATE_PARENT);
973
+static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
974
+ clk_parent_pll_audio,
975
+ 1, 1, CLK_SET_RATE_PARENT);
976
+static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
977
+ clk_parent_pll_audio,
978
+ 1, 2, CLK_SET_RATE_PARENT);
979
+static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
980
+ &pll_periph0_clk.common.hw,
981
+ 1, 2, 0);
982
+static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x",
983
+ &pll_periph1_clk.common.hw,
984
+ 1, 2, 0);
985
+static CLK_FIXED_FACTOR_HW(pll_video0_2x_clk, "pll-video0-2x",
986
+ &pll_video0_clk.common.hw,
987
+ 1, 2, 0);
988
+static CLK_FIXED_FACTOR_HW(pll_video1_2x_clk, "pll-video1-2x",
989
+ &pll_video1_clk.common.hw,
990
+ 1, 2, 0);
973991
974992 static struct clk_hw_onecell_data sun8i_r40_hw_clks = {
975993 .hws = {
....@@ -1284,6 +1302,9 @@
12841302 .writeable_reg = sun8i_r40_ccu_regmap_accessible_reg,
12851303 };
12861304
1305
+#define SUN8I_R40_SYS_32K_CLK_REG 0x310
1306
+#define SUN8I_R40_SYS_32K_CLK_KEY (0x16AA << 16)
1307
+
12871308 static int sun8i_r40_ccu_probe(struct platform_device *pdev)
12881309 {
12891310 struct resource *res;
....@@ -1297,10 +1318,10 @@
12971318 if (IS_ERR(reg))
12981319 return PTR_ERR(reg);
12991320
1300
- /* Force the PLL-Audio-1x divider to 4 */
1321
+ /* Force the PLL-Audio-1x divider to 1 */
13011322 val = readl(reg + SUN8I_R40_PLL_AUDIO_REG);
13021323 val &= ~GENMASK(19, 16);
1303
- writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG);
1324
+ writel(val | (0 << 16), reg + SUN8I_R40_PLL_AUDIO_REG);
13041325
13051326 /* Force PLL-MIPI to MIPI mode */
13061327 val = readl(reg + SUN8I_R40_PLL_MIPI_REG);
....@@ -1312,6 +1333,14 @@
13121333 val &= ~GENMASK(25, 20);
13131334 writel(val, reg + SUN8I_R40_USB_CLK_REG);
13141335
1336
+ /*
1337
+ * Force SYS 32k (otherwise known as LOSC throughout the CCU)
1338
+ * clock parent to LOSC output from RTC module instead of the
1339
+ * CCU's internal RC oscillator divided output.
1340
+ */
1341
+ writel(SUN8I_R40_SYS_32K_CLK_KEY | BIT(8),
1342
+ reg + SUN8I_R40_SYS_32K_CLK_REG);
1343
+
13151344 regmap = devm_regmap_init_mmio(&pdev->dev, reg,
13161345 &sun8i_r40_ccu_regmap_config);
13171346 if (IS_ERR(regmap))