forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-09 244b2c5ca8b14627e4a17755e5922221e121c771
kernel/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
....@@ -4,6 +4,7 @@
44 */
55
66 #include <linux/clk-provider.h>
7
+#include <linux/io.h>
78 #include <linux/of_address.h>
89 #include <linux/platform_device.h>
910
....@@ -120,6 +121,8 @@
120121 .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
121122 .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
122123 .fixed_post_div = 4,
124
+ .min_rate = 288000000,
125
+ .max_rate = 2400000000UL,
123126 .common = {
124127 .reg = 0x040,
125128 .features = CCU_FEATURE_FIXED_POSTDIV,
....@@ -136,6 +139,8 @@
136139 .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
137140 .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
138141 .fixed_post_div = 4,
142
+ .min_rate = 288000000,
143
+ .max_rate = 2400000000UL,
139144 .common = {
140145 .reg = 0x048,
141146 .features = CCU_FEATURE_FIXED_POSTDIV,
....@@ -198,12 +203,21 @@
198203 * hardcode it to match with the clock names.
199204 */
200205 #define SUN50I_H6_PLL_AUDIO_REG 0x078
206
+
207
+static struct ccu_sdm_setting pll_audio_sdm_table[] = {
208
+ { .rate = 541900800, .pattern = 0xc001288d, .m = 1, .n = 22 },
209
+ { .rate = 589824000, .pattern = 0xc00126e9, .m = 1, .n = 24 },
210
+};
211
+
201212 static struct ccu_nm pll_audio_base_clk = {
202213 .enable = BIT(31),
203214 .lock = BIT(28),
204215 .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
205216 .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
217
+ .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table,
218
+ BIT(24), 0x178, BIT(31)),
206219 .common = {
220
+ .features = CCU_FEATURE_SIGMA_DELTA_MOD,
207221 .reg = 0x078,
208222 .hw.init = CLK_HW_INIT("pll-audio-base", "osc24M",
209223 &ccu_nm_ops,
....@@ -262,7 +276,7 @@
262276 0, 4, /* M */
263277 24, 1, /* mux */
264278 BIT(31), /* gate */
265
- 0);
279
+ CLK_SET_RATE_PARENT);
266280
267281 static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
268282 0x60c, BIT(0), 0);
....@@ -285,7 +299,7 @@
285299 0, 3, /* M */
286300 24, 1, /* mux */
287301 BIT(31), /* gate */
288
- 0);
302
+ CLK_SET_RATE_PARENT);
289303
290304 static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
291305 0x67c, BIT(0), 0);
....@@ -307,7 +321,7 @@
307321 0, 3, /* M */
308322 24, 1, /* mux */
309323 BIT(31), /* gate */
310
- 0);
324
+ CLK_SET_RATE_PARENT);
311325
312326 static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
313327 0x69c, BIT(0), 0);
....@@ -408,26 +422,29 @@
408422
409423 static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
410424 "pll-periph1-2x" };
411
-static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830,
412
- 0, 4, /* M */
413
- 8, 2, /* N */
414
- 24, 3, /* mux */
415
- BIT(31),/* gate */
416
- 0);
425
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
426
+ 0, 4, /* M */
427
+ 8, 2, /* N */
428
+ 24, 2, /* mux */
429
+ BIT(31), /* gate */
430
+ 2, /* post-div */
431
+ 0);
417432
418
-static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834,
419
- 0, 4, /* M */
420
- 8, 2, /* N */
421
- 24, 3, /* mux */
422
- BIT(31),/* gate */
423
- 0);
433
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
434
+ 0, 4, /* M */
435
+ 8, 2, /* N */
436
+ 24, 2, /* mux */
437
+ BIT(31), /* gate */
438
+ 2, /* post-div */
439
+ 0);
424440
425
-static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838,
426
- 0, 4, /* M */
427
- 8, 2, /* N */
428
- 24, 3, /* mux */
429
- BIT(31),/* gate */
430
- 0);
441
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
442
+ 0, 4, /* M */
443
+ 8, 2, /* N */
444
+ 24, 2, /* mux */
445
+ BIT(31), /* gate */
446
+ 2, /* post-div */
447
+ 0);
431448
432449 static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
433450 static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
....@@ -497,7 +514,7 @@
497514 .hw.init = CLK_HW_INIT_PARENTS("i2s3",
498515 audio_parents,
499516 &ccu_div_ops,
500
- 0),
517
+ CLK_SET_RATE_PARENT),
501518 },
502519 };
503520
....@@ -510,7 +527,7 @@
510527 .hw.init = CLK_HW_INIT_PARENTS("i2s0",
511528 audio_parents,
512529 &ccu_div_ops,
513
- 0),
530
+ CLK_SET_RATE_PARENT),
514531 },
515532 };
516533
....@@ -523,7 +540,7 @@
523540 .hw.init = CLK_HW_INIT_PARENTS("i2s1",
524541 audio_parents,
525542 &ccu_div_ops,
526
- 0),
543
+ CLK_SET_RATE_PARENT),
527544 },
528545 };
529546
....@@ -536,7 +553,7 @@
536553 .hw.init = CLK_HW_INIT_PARENTS("i2s2",
537554 audio_parents,
538555 &ccu_div_ops,
539
- 0),
556
+ CLK_SET_RATE_PARENT),
540557 },
541558 };
542559
....@@ -614,8 +631,9 @@
614631 static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
615632 static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
616633
617
-static CLK_FIXED_FACTOR(pcie_ref_100m_clk, "pcie-ref-100M",
618
- "pll-periph0-4x", 24, 1, 0);
634
+static struct clk_fixed_factor pll_periph0_4x_clk;
635
+static CLK_FIXED_FACTOR_HW(pcie_ref_100m_clk, "pcie-ref-100M",
636
+ &pll_periph0_4x_clk.hw, 24, 1, 0);
619637 static SUNXI_CCU_GATE(pcie_ref_clk, "pcie-ref", "pcie-ref-100M",
620638 0xab0, BIT(31), 0);
621639 static SUNXI_CCU_GATE(pcie_ref_out_clk, "pcie-ref-out", "pcie-ref",
....@@ -649,6 +667,8 @@
649667 static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
650668 { .index = 1, .div = 36621 },
651669 };
670
+
671
+#define SUN50I_H6_HDMI_CEC_CLK_REG 0xb10
652672 static struct ccu_mux hdmi_cec_clk = {
653673 .enable = BIT(31),
654674
....@@ -682,7 +702,7 @@
682702 tcon_lcd0_parents, 0xb60,
683703 24, 3, /* mux */
684704 BIT(31), /* gate */
685
- 0);
705
+ CLK_SET_RATE_PARENT);
686706
687707 static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
688708 0xb7c, BIT(0), 0);
....@@ -697,7 +717,7 @@
697717 8, 2, /* P */
698718 24, 3, /* mux */
699719 BIT(31), /* gate */
700
- 0);
720
+ CLK_SET_RATE_PARENT);
701721
702722 static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
703723 0xb9c, BIT(0), 0);
....@@ -735,34 +755,52 @@
735755 static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
736756
737757 /* Fixed factor clocks */
738
-static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0);
758
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
759
+
760
+static const struct clk_hw *clk_parent_pll_audio[] = {
761
+ &pll_audio_base_clk.common.hw
762
+};
739763
740764 /*
741
- * The divider of pll-audio is fixed to 8 now, as pll-audio-4x has a
742
- * fixed post-divider 2.
765
+ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
766
+ * rates can be set exactly in conjunction with sigma-delta modulation.
743767 */
744
-static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
745
- "pll-audio-base", 8, 1, CLK_SET_RATE_PARENT);
746
-static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
747
- "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
748
-static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
749
- "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
768
+static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
769
+ clk_parent_pll_audio,
770
+ 24, 1, CLK_SET_RATE_PARENT);
771
+static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
772
+ clk_parent_pll_audio,
773
+ 4, 1, CLK_SET_RATE_PARENT);
774
+static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
775
+ clk_parent_pll_audio,
776
+ 2, 1, CLK_SET_RATE_PARENT);
750777
751
-static CLK_FIXED_FACTOR(pll_periph0_4x_clk, "pll-periph0-4x",
752
- "pll-periph0", 1, 4, 0);
753
-static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
754
- "pll-periph0", 1, 2, 0);
778
+static const struct clk_hw *pll_periph0_parents[] = {
779
+ &pll_periph0_clk.common.hw
780
+};
781
+static CLK_FIXED_FACTOR_HWS(pll_periph0_4x_clk, "pll-periph0-4x",
782
+ pll_periph0_parents,
783
+ 1, 4, 0);
784
+static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
785
+ pll_periph0_parents,
786
+ 1, 2, 0);
755787
756
-static CLK_FIXED_FACTOR(pll_periph1_4x_clk, "pll-periph1-4x",
757
- "pll-periph1", 1, 4, 0);
758
-static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
759
- "pll-periph1", 1, 2, 0);
788
+static const struct clk_hw *pll_periph1_parents[] = {
789
+ &pll_periph1_clk.common.hw
790
+};
791
+static CLK_FIXED_FACTOR_HWS(pll_periph1_4x_clk, "pll-periph1-4x",
792
+ pll_periph1_parents,
793
+ 1, 4, 0);
794
+static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
795
+ pll_periph1_parents,
796
+ 1, 2, 0);
760797
761
-static CLK_FIXED_FACTOR(pll_video0_4x_clk, "pll-video0-4x",
762
- "pll-video0", 1, 4, CLK_SET_RATE_PARENT);
763
-
764
-static CLK_FIXED_FACTOR(pll_video1_4x_clk, "pll-video1-4x",
765
- "pll-video1", 1, 4, CLK_SET_RATE_PARENT);
798
+static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
799
+ &pll_video0_clk.common.hw,
800
+ 1, 4, CLK_SET_RATE_PARENT);
801
+static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
802
+ &pll_video1_clk.common.hw,
803
+ 1, 4, CLK_SET_RATE_PARENT);
766804
767805 static struct ccu_common *sun50i_h6_ccu_clks[] = {
768806 &pll_cpux_clk.common,
....@@ -1186,12 +1224,21 @@
11861224 }
11871225
11881226 /*
1189
- * Force the post-divider of pll-audio to 8 and the output divider
1190
- * of it to 1, to make the clock name represents the real frequency.
1227
+ * Force the post-divider of pll-audio to 12 and the output divider
1228
+ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
11911229 */
11921230 val = readl(reg + SUN50I_H6_PLL_AUDIO_REG);
11931231 val &= ~(GENMASK(21, 16) | BIT(0));
1194
- writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG);
1232
+ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H6_PLL_AUDIO_REG);
1233
+
1234
+ /*
1235
+ * First clock parent (osc32K) is unusable for CEC. But since there
1236
+ * is no good way to force parent switch (both run with same frequency),
1237
+ * just set second clock parent here.
1238
+ */
1239
+ val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG);
1240
+ val |= BIT(24);
1241
+ writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
11951242
11961243 return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
11971244 }