hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/clk/samsung/clk-exynos5420.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
34 * Authors: Thomas Abraham <thomas.ab@samsung.com>
45 * Chander Kashyap <k.chander@samsung.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 *
107 * Common Clock Framework support for Exynos5420 SoC.
118 */
....@@ -15,7 +12,7 @@
1512 #include <linux/clk-provider.h>
1613 #include <linux/of.h>
1714 #include <linux/of_address.h>
18
-#include <linux/syscore_ops.h>
15
+#include <linux/clk.h>
1916
2017 #include "clk.h"
2118 #include "clk-cpu.h"
....@@ -135,6 +132,8 @@
135132 #define SRC_CDREX 0x20200
136133 #define DIV_CDREX0 0x20500
137134 #define DIV_CDREX1 0x20504
135
+#define GATE_BUS_CDREX0 0x20700
136
+#define GATE_BUS_CDREX1 0x20704
138137 #define KPLL_LOCK 0x28000
139138 #define KPLL_CON0 0x28100
140139 #define SRC_KFC 0x28200
....@@ -155,10 +154,6 @@
155154
156155 static void __iomem *reg_base;
157156 static enum exynos5x_soc exynos5x_soc;
158
-
159
-#ifdef CONFIG_PM_SLEEP
160
-static struct samsung_clk_reg_dump *exynos5x_save;
161
-static struct samsung_clk_reg_dump *exynos5800_save;
162157
163158 /*
164159 * list of controller registers to be saved and restored during a
....@@ -261,6 +256,8 @@
261256 DIV_CDREX1,
262257 SRC_KFC,
263258 DIV_KFC0,
259
+ GATE_BUS_CDREX0,
260
+ GATE_BUS_CDREX1,
264261 };
265262
266263 static const unsigned long exynos5800_clk_regs[] __initconst = {
....@@ -291,66 +288,6 @@
291288 { .offset = GATE_IP_PERIC, .value = 0xffffffff, },
292289 { .offset = GATE_IP_PERIS, .value = 0xffffffff, },
293290 };
294
-
295
-static int exynos5420_clk_suspend(void)
296
-{
297
- samsung_clk_save(reg_base, exynos5x_save,
298
- ARRAY_SIZE(exynos5x_clk_regs));
299
-
300
- if (exynos5x_soc == EXYNOS5800)
301
- samsung_clk_save(reg_base, exynos5800_save,
302
- ARRAY_SIZE(exynos5800_clk_regs));
303
-
304
- samsung_clk_restore(reg_base, exynos5420_set_clksrc,
305
- ARRAY_SIZE(exynos5420_set_clksrc));
306
-
307
- return 0;
308
-}
309
-
310
-static void exynos5420_clk_resume(void)
311
-{
312
- samsung_clk_restore(reg_base, exynos5x_save,
313
- ARRAY_SIZE(exynos5x_clk_regs));
314
-
315
- if (exynos5x_soc == EXYNOS5800)
316
- samsung_clk_restore(reg_base, exynos5800_save,
317
- ARRAY_SIZE(exynos5800_clk_regs));
318
-}
319
-
320
-static struct syscore_ops exynos5420_clk_syscore_ops = {
321
- .suspend = exynos5420_clk_suspend,
322
- .resume = exynos5420_clk_resume,
323
-};
324
-
325
-static void __init exynos5420_clk_sleep_init(void)
326
-{
327
- exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs,
328
- ARRAY_SIZE(exynos5x_clk_regs));
329
- if (!exynos5x_save) {
330
- pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
331
- __func__);
332
- return;
333
- }
334
-
335
- if (exynos5x_soc == EXYNOS5800) {
336
- exynos5800_save =
337
- samsung_clk_alloc_reg_dump(exynos5800_clk_regs,
338
- ARRAY_SIZE(exynos5800_clk_regs));
339
- if (!exynos5800_save)
340
- goto err_soc;
341
- }
342
-
343
- register_syscore_ops(&exynos5420_clk_syscore_ops);
344
- return;
345
-err_soc:
346
- kfree(exynos5x_save);
347
- pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
348
- __func__);
349
- return;
350
-}
351
-#else
352
-static void __init exynos5420_clk_sleep_init(void) {}
353
-#endif
354291
355292 /* list of all parent clocks */
356293 PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll",
....@@ -498,6 +435,9 @@
498435 PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" };
499436 PNAME(mout_group15_5800_p) = { "dout_osc_div", "mout_sw_aclk550_cam" };
500437 PNAME(mout_group16_5800_p) = { "dout_osc_div", "mout_mau_epll_clk" };
438
+PNAME(mout_mx_mspll_ccore_phy_p) = { "sclk_bpll", "mout_sclk_dpll",
439
+ "mout_sclk_mpll", "ff_dout_spll2",
440
+ "mout_sclk_spll", "mout_sclk_epll"};
501441
502442 /* fixed rate clocks generated outside the soc */
503443 static struct samsung_fixed_rate_clock
....@@ -523,7 +463,7 @@
523463 static const struct samsung_fixed_factor_clock
524464 exynos5800_fixed_factor_clks[] __initconst = {
525465 FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0),
526
- FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
466
+ FFACTOR(CLK_FF_DOUT_SPLL2, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0),
527467 };
528468
529469 static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = {
....@@ -545,11 +485,14 @@
545485 MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2),
546486 MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2),
547487
488
+ MUX(CLK_MOUT_MX_MSPLL_CCORE_PHY, "mout_mx_mspll_ccore_phy",
489
+ mout_mx_mspll_ccore_phy_p, SRC_TOP7, 0, 3),
490
+
548491 MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
549
- mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
492
+ mout_mx_mspll_ccore_p, SRC_TOP7, 16, 3),
550493 MUX_F(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p,
551494 SRC_TOP7, 20, 2, CLK_SET_RATE_PARENT, 0),
552
- MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
495
+ MUX(CLK_SCLK_BPLL, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1),
553496 MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1),
554497
555498 MUX(0, "mout_aclk550_cam", mout_group3_5800_p, SRC_TOP8, 16, 3),
....@@ -600,8 +543,6 @@
600543 GATE_BUS_TOP, 24, CLK_IS_CRITICAL, 0),
601544 GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
602545 GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
603
- GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
604
- SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
605546 };
606547
607548 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
....@@ -643,20 +584,26 @@
643584
644585 static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = {
645586 GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0),
587
+ /* Maudio Block */
646588 GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
647589 SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
590
+ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
591
+ GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
592
+ GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
593
+ GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
648594 };
649595
650596 static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = {
651597 MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p,
652598 SRC_TOP7, 4, 1),
653
- MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
654
- MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
655
-
656
- MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
599
+ MUX(CLK_MOUT_MSPLL_KFC, "mout_mspll_kfc", mout_mspll_cpu_p,
600
+ SRC_TOP7, 8, 2),
601
+ MUX(CLK_MOUT_MSPLL_CPU, "mout_mspll_cpu", mout_mspll_cpu_p,
602
+ SRC_TOP7, 12, 2),
603
+ MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
657604 CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
658605 MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
659
- MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
606
+ MUX_F(CLK_MOUT_KPLL, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
660607 CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
661608 MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
662609
....@@ -668,7 +615,8 @@
668615 MUX(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2),
669616 MUX(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2),
670617
671
- MUX(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1),
618
+ MUX_F(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1,
619
+ CLK_SET_RATE_PARENT, 0),
672620
673621 MUX(0, "mout_user_aclk400_isp", mout_user_aclk400_isp_p,
674622 SRC_TOP3, 0, 1),
....@@ -710,8 +658,8 @@
710658 SRC_TOP5, 8, 1),
711659 MUX(0, "mout_user_aclk266_g2d", mout_user_aclk266_g2d_p,
712660 SRC_TOP5, 12, 1),
713
- MUX(CLK_MOUT_G3D, "mout_user_aclk_g3d", mout_user_aclk_g3d_p,
714
- SRC_TOP5, 16, 1),
661
+ MUX_F(CLK_MOUT_G3D, "mout_user_aclk_g3d", mout_user_aclk_g3d_p,
662
+ SRC_TOP5, 16, 1, CLK_SET_RATE_PARENT, 0),
715663 MUX(0, "mout_user_aclk300_jpeg", mout_user_aclk300_jpeg_p,
716664 SRC_TOP5, 20, 1),
717665 MUX(CLK_MOUT_USER_ACLK300_DISP1, "mout_user_aclk300_disp1",
....@@ -720,8 +668,9 @@
720668 mout_user_aclk300_gscl_p, SRC_TOP5, 28, 1),
721669
722670 MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
723
- MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
724
- MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
671
+ MUX_F(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1,
672
+ CLK_SET_RATE_PARENT, 0),
673
+ MUX(CLK_MOUT_SCLK_SPLL, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1),
725674 MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1),
726675 MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1),
727676 MUX_F(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1,
....@@ -764,7 +713,8 @@
764713 SRC_TOP12, 8, 1),
765714 MUX(0, "mout_sw_aclk266_g2d", mout_sw_aclk266_g2d_p,
766715 SRC_TOP12, 12, 1),
767
- MUX(0, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, SRC_TOP12, 16, 1),
716
+ MUX_F(CLK_MOUT_SW_ACLK_G3D, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p,
717
+ SRC_TOP12, 16, 1, CLK_SET_RATE_PARENT, 0),
768718 MUX(0, "mout_sw_aclk300_jpeg", mout_sw_aclk300_jpeg_p,
769719 SRC_TOP12, 20, 1),
770720 MUX(CLK_MOUT_SW_ACLK300, "mout_sw_aclk300_disp1",
....@@ -861,8 +811,8 @@
861811 DIV_TOP2, 8, 3),
862812 DIV(CLK_DOUT_ACLK266_G2D, "dout_aclk266_g2d", "mout_aclk266_g2d",
863813 DIV_TOP2, 12, 3),
864
- DIV(CLK_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2,
865
- 16, 3),
814
+ DIV_F(CLK_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2,
815
+ 16, 3, CLK_SET_RATE_PARENT, 0),
866816 DIV(CLK_DOUT_ACLK300_JPEG, "dout_aclk300_jpeg", "mout_aclk300_jpeg",
867817 DIV_TOP2, 20, 3),
868818 DIV(CLK_DOUT_ACLK300_DISP1, "dout_aclk300_disp1",
....@@ -879,8 +829,21 @@
879829 "mout_aclk400_disp1", DIV_TOP2, 4, 3),
880830
881831 /* CDREX Block */
882
- DIV(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1",
883
- DIV_CDREX0, 28, 3),
832
+ /*
833
+ * The three clocks below are controlled using the same register and
834
+ * bits. They are put into one because there is a need of
835
+ * synchronization between the BUS and DREXs (two external memory
836
+ * interfaces).
837
+ * They are put here to show this HW assumption and for clock
838
+ * information summary completeness.
839
+ */
840
+ DIV_F(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1",
841
+ DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
842
+ DIV_F(CLK_DOUT_PCLK_DREX0, "dout_pclk_drex0", "dout_cclk_drex0",
843
+ DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
844
+ DIV_F(CLK_DOUT_PCLK_DREX1, "dout_pclk_drex1", "dout_cclk_drex0",
845
+ DIV_CDREX0, 28, 3, CLK_GET_RATE_NOCACHE, 0),
846
+
884847 DIV_F(CLK_DOUT_SCLK_CDREX, "dout_sclk_cdrex", "mout_mclk_cdrex",
885848 DIV_CDREX0, 24, 3, CLK_SET_RATE_PARENT, 0),
886849 DIV(CLK_DOUT_ACLK_CDREX1, "dout_aclk_cdrex1", "dout_clk2x_phy0",
....@@ -942,9 +905,6 @@
942905
943906 /* GSCL Block */
944907 DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2),
945
-
946
- /* MSCL Block */
947
- DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
948908
949909 /* PSGEN */
950910 DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1),
....@@ -1069,12 +1029,6 @@
10691029 GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0),
10701030 GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
10711031 GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0),
1072
-
1073
- /* Maudio Block */
1074
- GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
1075
- GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
1076
- GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
1077
- GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
10781032
10791033 /* FSYS Block */
10801034 GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0),
....@@ -1212,21 +1166,10 @@
12121166 CLK_IS_CRITICAL, 0),
12131167 GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13,
12141168 CLK_IS_CRITICAL, 0),
1215
- GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
1169
+ GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3", "dout_gscl_blk_333",
12161170 GATE_IP_GSCL1, 16, 0, 0),
12171171 GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
12181172 GATE_IP_GSCL1, 17, 0, 0),
1219
-
1220
- /* MSCL Block */
1221
- GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
1222
- GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
1223
- GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
1224
- GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
1225
- GATE_IP_MSCL, 8, 0, 0),
1226
- GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
1227
- GATE_IP_MSCL, 9, 0, 0),
1228
- GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
1229
- GATE_IP_MSCL, 10, 0, 0),
12301173
12311174 /* ISP */
12321175 GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp",
....@@ -1244,7 +1187,31 @@
12441187 GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2",
12451188 GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0),
12461189
1247
- GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
1190
+ /* CDREX */
1191
+ GATE(CLK_CLKM_PHY0, "clkm_phy0", "dout_sclk_cdrex",
1192
+ GATE_BUS_CDREX0, 0, 0, 0),
1193
+ GATE(CLK_CLKM_PHY1, "clkm_phy1", "dout_sclk_cdrex",
1194
+ GATE_BUS_CDREX0, 1, 0, 0),
1195
+ GATE(0, "mx_mspll_ccore_phy", "mout_mx_mspll_ccore_phy",
1196
+ SRC_MASK_TOP7, 0, CLK_IGNORE_UNUSED, 0),
1197
+
1198
+ GATE(CLK_ACLK_PPMU_DREX1_1, "aclk_ppmu_drex1_1", "dout_aclk_cdrex1",
1199
+ GATE_BUS_CDREX1, 12, CLK_IGNORE_UNUSED, 0),
1200
+ GATE(CLK_ACLK_PPMU_DREX1_0, "aclk_ppmu_drex1_0", "dout_aclk_cdrex1",
1201
+ GATE_BUS_CDREX1, 13, CLK_IGNORE_UNUSED, 0),
1202
+ GATE(CLK_ACLK_PPMU_DREX0_1, "aclk_ppmu_drex0_1", "dout_aclk_cdrex1",
1203
+ GATE_BUS_CDREX1, 14, CLK_IGNORE_UNUSED, 0),
1204
+ GATE(CLK_ACLK_PPMU_DREX0_0, "aclk_ppmu_drex0_0", "dout_aclk_cdrex1",
1205
+ GATE_BUS_CDREX1, 15, CLK_IGNORE_UNUSED, 0),
1206
+
1207
+ GATE(CLK_PCLK_PPMU_DREX1_1, "pclk_ppmu_drex1_1", "dout_pclk_cdrex",
1208
+ GATE_BUS_CDREX1, 26, CLK_IGNORE_UNUSED, 0),
1209
+ GATE(CLK_PCLK_PPMU_DREX1_0, "pclk_ppmu_drex1_0", "dout_pclk_cdrex",
1210
+ GATE_BUS_CDREX1, 27, CLK_IGNORE_UNUSED, 0),
1211
+ GATE(CLK_PCLK_PPMU_DREX0_1, "pclk_ppmu_drex0_1", "dout_pclk_cdrex",
1212
+ GATE_BUS_CDREX1, 28, CLK_IGNORE_UNUSED, 0),
1213
+ GATE(CLK_PCLK_PPMU_DREX0_0, "pclk_ppmu_drex0_0", "dout_pclk_cdrex",
1214
+ GATE_BUS_CDREX1, 29, CLK_IGNORE_UNUSED, 0),
12481215 };
12491216
12501217 static const struct samsung_div_clock exynos5x_disp_div_clks[] __initconst = {
....@@ -1294,6 +1261,16 @@
12941261 { DIV2_RATIO0, 0, 0x30 }, /* DIV dout_gscl_blk_300 */
12951262 };
12961263
1264
+static const struct samsung_gate_clock exynos5x_g3d_gate_clks[] __initconst = {
1265
+ GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9,
1266
+ CLK_SET_RATE_PARENT, 0),
1267
+};
1268
+
1269
+static struct exynos5_subcmu_reg_dump exynos5x_g3d_suspend_regs[] = {
1270
+ { GATE_IP_G3D, 0x3ff, 0x3ff }, /* G3D gates */
1271
+ { SRC_TOP5, 0, BIT(16) }, /* MUX mout_user_aclk_g3d */
1272
+};
1273
+
12971274 static const struct samsung_div_clock exynos5x_mfc_div_clks[] __initconst = {
12981275 DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2),
12991276 };
....@@ -1310,32 +1287,113 @@
13101287 { DIV4_RATIO, 0, 0x3 }, /* DIV dout_mfc_blk */
13111288 };
13121289
1313
-static const struct exynos5_subcmu_info exynos5x_subcmus[] = {
1314
- {
1315
- .div_clks = exynos5x_disp_div_clks,
1316
- .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks),
1317
- .gate_clks = exynos5x_disp_gate_clks,
1318
- .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks),
1319
- .suspend_regs = exynos5x_disp_suspend_regs,
1320
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
1321
- .pd_name = "DISP",
1322
- }, {
1323
- .div_clks = exynos5x_gsc_div_clks,
1324
- .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks),
1325
- .gate_clks = exynos5x_gsc_gate_clks,
1326
- .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks),
1327
- .suspend_regs = exynos5x_gsc_suspend_regs,
1328
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
1329
- .pd_name = "GSC",
1330
- }, {
1331
- .div_clks = exynos5x_mfc_div_clks,
1332
- .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks),
1333
- .gate_clks = exynos5x_mfc_gate_clks,
1334
- .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks),
1335
- .suspend_regs = exynos5x_mfc_suspend_regs,
1336
- .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
1337
- .pd_name = "MFC",
1338
- },
1290
+static const struct samsung_gate_clock exynos5x_mscl_gate_clks[] __initconst = {
1291
+ /* MSCL Block */
1292
+ GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0),
1293
+ GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0),
1294
+ GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0),
1295
+ GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk",
1296
+ GATE_IP_MSCL, 8, 0, 0),
1297
+ GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk",
1298
+ GATE_IP_MSCL, 9, 0, 0),
1299
+ GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk",
1300
+ GATE_IP_MSCL, 10, 0, 0),
1301
+};
1302
+
1303
+static const struct samsung_div_clock exynos5x_mscl_div_clks[] __initconst = {
1304
+ DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2),
1305
+};
1306
+
1307
+static struct exynos5_subcmu_reg_dump exynos5x_mscl_suspend_regs[] = {
1308
+ { GATE_IP_MSCL, 0xffffffff, 0xffffffff }, /* MSCL gates */
1309
+ { SRC_TOP3, 0, BIT(4) }, /* MUX mout_user_aclk400_mscl */
1310
+ { DIV2_RATIO0, 0, 0x30000000 }, /* DIV dout_mscl_blk */
1311
+};
1312
+
1313
+static const struct samsung_gate_clock exynos5800_mau_gate_clks[] __initconst = {
1314
+ GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll",
1315
+ SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0),
1316
+ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0",
1317
+ GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0),
1318
+ GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0",
1319
+ GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0),
1320
+};
1321
+
1322
+static struct exynos5_subcmu_reg_dump exynos5800_mau_suspend_regs[] = {
1323
+ { SRC_TOP9, 0, BIT(8) }, /* MUX mout_user_mau_epll */
1324
+};
1325
+
1326
+static const struct exynos5_subcmu_info exynos5x_disp_subcmu = {
1327
+ .div_clks = exynos5x_disp_div_clks,
1328
+ .nr_div_clks = ARRAY_SIZE(exynos5x_disp_div_clks),
1329
+ .gate_clks = exynos5x_disp_gate_clks,
1330
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_disp_gate_clks),
1331
+ .suspend_regs = exynos5x_disp_suspend_regs,
1332
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_disp_suspend_regs),
1333
+ .pd_name = "DISP",
1334
+};
1335
+
1336
+static const struct exynos5_subcmu_info exynos5x_gsc_subcmu = {
1337
+ .div_clks = exynos5x_gsc_div_clks,
1338
+ .nr_div_clks = ARRAY_SIZE(exynos5x_gsc_div_clks),
1339
+ .gate_clks = exynos5x_gsc_gate_clks,
1340
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_gsc_gate_clks),
1341
+ .suspend_regs = exynos5x_gsc_suspend_regs,
1342
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_gsc_suspend_regs),
1343
+ .pd_name = "GSC",
1344
+};
1345
+
1346
+static const struct exynos5_subcmu_info exynos5x_g3d_subcmu = {
1347
+ .gate_clks = exynos5x_g3d_gate_clks,
1348
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_g3d_gate_clks),
1349
+ .suspend_regs = exynos5x_g3d_suspend_regs,
1350
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_g3d_suspend_regs),
1351
+ .pd_name = "G3D",
1352
+};
1353
+
1354
+static const struct exynos5_subcmu_info exynos5x_mfc_subcmu = {
1355
+ .div_clks = exynos5x_mfc_div_clks,
1356
+ .nr_div_clks = ARRAY_SIZE(exynos5x_mfc_div_clks),
1357
+ .gate_clks = exynos5x_mfc_gate_clks,
1358
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_mfc_gate_clks),
1359
+ .suspend_regs = exynos5x_mfc_suspend_regs,
1360
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_mfc_suspend_regs),
1361
+ .pd_name = "MFC",
1362
+};
1363
+
1364
+static const struct exynos5_subcmu_info exynos5x_mscl_subcmu = {
1365
+ .div_clks = exynos5x_mscl_div_clks,
1366
+ .nr_div_clks = ARRAY_SIZE(exynos5x_mscl_div_clks),
1367
+ .gate_clks = exynos5x_mscl_gate_clks,
1368
+ .nr_gate_clks = ARRAY_SIZE(exynos5x_mscl_gate_clks),
1369
+ .suspend_regs = exynos5x_mscl_suspend_regs,
1370
+ .nr_suspend_regs = ARRAY_SIZE(exynos5x_mscl_suspend_regs),
1371
+ .pd_name = "MSC",
1372
+};
1373
+
1374
+static const struct exynos5_subcmu_info exynos5800_mau_subcmu = {
1375
+ .gate_clks = exynos5800_mau_gate_clks,
1376
+ .nr_gate_clks = ARRAY_SIZE(exynos5800_mau_gate_clks),
1377
+ .suspend_regs = exynos5800_mau_suspend_regs,
1378
+ .nr_suspend_regs = ARRAY_SIZE(exynos5800_mau_suspend_regs),
1379
+ .pd_name = "MAU",
1380
+};
1381
+
1382
+static const struct exynos5_subcmu_info *exynos5x_subcmus[] = {
1383
+ &exynos5x_disp_subcmu,
1384
+ &exynos5x_gsc_subcmu,
1385
+ &exynos5x_g3d_subcmu,
1386
+ &exynos5x_mfc_subcmu,
1387
+ &exynos5x_mscl_subcmu,
1388
+};
1389
+
1390
+static const struct exynos5_subcmu_info *exynos5800_subcmus[] = {
1391
+ &exynos5x_disp_subcmu,
1392
+ &exynos5x_gsc_subcmu,
1393
+ &exynos5x_g3d_subcmu,
1394
+ &exynos5x_mfc_subcmu,
1395
+ &exynos5x_mscl_subcmu,
1396
+ &exynos5800_mau_subcmu,
13391397 };
13401398
13411399 static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __initconst = {
....@@ -1360,6 +1418,17 @@
13601418 PLL_35XX_RATE(24 * MHZ, 200000000, 200, 3, 3),
13611419 };
13621420
1421
+static const struct samsung_pll_rate_table exynos5422_bpll_rate_table[] = {
1422
+ PLL_35XX_RATE(24 * MHZ, 825000000, 275, 4, 1),
1423
+ PLL_35XX_RATE(24 * MHZ, 728000000, 182, 3, 1),
1424
+ PLL_35XX_RATE(24 * MHZ, 633000000, 211, 4, 1),
1425
+ PLL_35XX_RATE(24 * MHZ, 543000000, 181, 2, 2),
1426
+ PLL_35XX_RATE(24 * MHZ, 413000000, 413, 6, 2),
1427
+ PLL_35XX_RATE(24 * MHZ, 275000000, 275, 3, 3),
1428
+ PLL_35XX_RATE(24 * MHZ, 206000000, 206, 3, 3),
1429
+ PLL_35XX_RATE(24 * MHZ, 165000000, 110, 2, 3),
1430
+};
1431
+
13631432 static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = {
13641433 PLL_36XX_RATE(24 * MHZ, 600000000U, 100, 2, 1, 0),
13651434 PLL_36XX_RATE(24 * MHZ, 400000000U, 200, 3, 2, 0),
....@@ -1376,6 +1445,17 @@
13761445 PLL_36XX_RATE(24 * MHZ, 49152000U, 197, 3, 5, -25690),
13771446 PLL_36XX_RATE(24 * MHZ, 45158401U, 90, 3, 4, 20762),
13781447 PLL_36XX_RATE(24 * MHZ, 32768001U, 131, 3, 5, 4719),
1448
+};
1449
+
1450
+static const struct samsung_pll_rate_table exynos5420_vpll_24mhz_tbl[] = {
1451
+ PLL_35XX_RATE(24 * MHZ, 600000000U, 200, 2, 2),
1452
+ PLL_35XX_RATE(24 * MHZ, 543000000U, 181, 2, 2),
1453
+ PLL_35XX_RATE(24 * MHZ, 480000000U, 160, 2, 2),
1454
+ PLL_35XX_RATE(24 * MHZ, 420000000U, 140, 2, 2),
1455
+ PLL_35XX_RATE(24 * MHZ, 350000000U, 175, 3, 2),
1456
+ PLL_35XX_RATE(24 * MHZ, 266000000U, 266, 3, 3),
1457
+ PLL_35XX_RATE(24 * MHZ, 177000000U, 118, 2, 3),
1458
+ PLL_35XX_RATE(24 * MHZ, 100000000U, 200, 3, 4),
13791459 };
13801460
13811461 static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
....@@ -1481,6 +1561,7 @@
14811561 enum exynos5x_soc soc)
14821562 {
14831563 struct samsung_clk_provider *ctx;
1564
+ struct clk_hw **hws;
14841565
14851566 if (np) {
14861567 reg_base = of_iomap(np, 0);
....@@ -1493,6 +1574,7 @@
14931574 exynos5x_soc = soc;
14941575
14951576 ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
1577
+ hws = ctx->clk_data.hws;
14961578
14971579 samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks,
14981580 ARRAY_SIZE(exynos5x_fixed_rate_ext_clks),
....@@ -1502,8 +1584,13 @@
15021584 exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl;
15031585 exynos5x_plls[epll].rate_table = exynos5420_epll_24mhz_tbl;
15041586 exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
1505
- exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
1587
+ exynos5x_plls[vpll].rate_table = exynos5420_vpll_24mhz_tbl;
15061588 }
1589
+
1590
+ if (soc == EXYNOS5420)
1591
+ exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl;
1592
+ else
1593
+ exynos5x_plls[bpll].rate_table = exynos5422_bpll_rate_table;
15071594
15081595 samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
15091596 reg_base);
....@@ -1539,20 +1626,43 @@
15391626
15401627 if (soc == EXYNOS5420) {
15411628 exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
1542
- mout_cpu_p[0], mout_cpu_p[1], 0x200,
1629
+ hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200,
15431630 exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
15441631 } else {
15451632 exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
1546
- mout_cpu_p[0], mout_cpu_p[1], 0x200,
1633
+ hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200,
15471634 exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0);
15481635 }
15491636 exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
1550
- mout_kfc_p[0], mout_kfc_p[1], 0x28200,
1637
+ hws[CLK_MOUT_KPLL], hws[CLK_MOUT_MSPLL_KFC], 0x28200,
15511638 exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
15521639
1553
- exynos5420_clk_sleep_init();
1554
- exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
1555
- exynos5x_subcmus);
1640
+ samsung_clk_extended_sleep_init(reg_base,
1641
+ exynos5x_clk_regs, ARRAY_SIZE(exynos5x_clk_regs),
1642
+ exynos5420_set_clksrc, ARRAY_SIZE(exynos5420_set_clksrc));
1643
+
1644
+ if (soc == EXYNOS5800) {
1645
+ samsung_clk_sleep_init(reg_base, exynos5800_clk_regs,
1646
+ ARRAY_SIZE(exynos5800_clk_regs));
1647
+
1648
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5800_subcmus),
1649
+ exynos5800_subcmus);
1650
+ } else {
1651
+ exynos5_subcmus_init(ctx, ARRAY_SIZE(exynos5x_subcmus),
1652
+ exynos5x_subcmus);
1653
+ }
1654
+
1655
+ /*
1656
+ * Keep top part of G3D clock path enabled permanently to ensure
1657
+ * that the internal busses get their clock regardless of the
1658
+ * main G3D clock enablement status.
1659
+ */
1660
+ clk_prepare_enable(hws[CLK_MOUT_SW_ACLK_G3D]->clk);
1661
+ /*
1662
+ * Keep top BPLL mux enabled permanently to ensure that DRAM operates
1663
+ * properly.
1664
+ */
1665
+ clk_prepare_enable(hws[CLK_MOUT_BPLL]->clk);
15561666
15571667 samsung_clk_of_add_provider(np, ctx);
15581668 }