aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/samsung/clk-exynos3250.c
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-09-02 09:21:15 -0400
committerTomasz Figa <tomasz.figa@gmail.com>2014-09-22 08:28:49 -0400
commite3c3f19bc6185e0a24454e7b439e11635e6db960 (patch)
tree8f6212dd1706bb388ca9fd86057a97267acfcc88 /drivers/clk/samsung/clk-exynos3250.c
parent22842d244af353a66fa4e6d1978d3f4c39ee4d20 (diff)
clk: samsung: exynos3250: Register DMC clk provider
Add clock provider for clocks in DMC domain including EPLL and BPLL. The DMC clocks are necessary for Exynos3 devfreq driver. The DMC clock domain uses different address space (0x105C0000) than standard clock domain (0x10030000 - 0x10050000). The difference is huge enough to add new DT node for the clock provider, rather than extending existing address space. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Diffstat (limited to 'drivers/clk/samsung/clk-exynos3250.c')
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 5e2d86e2cede..6e6cca392082 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -110,7 +110,14 @@ enum exynos3250_plls {
110 nr_plls 110 nr_plls
111}; 111};
112 112
113/* list of PLLs in DMC block to be registered */
114enum exynos3250_dmc_plls {
115 bpll, epll,
116 nr_dmc_plls
117};
118
113static void __iomem *reg_base; 119static void __iomem *reg_base;
120static void __iomem *dmc_reg_base;
114 121
115/* 122/*
116 * Support for CMU save/restore across system suspends 123 * Support for CMU save/restore across system suspends
@@ -725,6 +732,25 @@ static struct samsung_pll_rate_table exynos3250_pll_rates[] = {
725 { /* sentinel */ } 732 { /* sentinel */ }
726}; 733};
727 734
735/* EPLL */
736static struct samsung_pll_rate_table exynos3250_epll_rates[] = {
737 PLL_36XX_RATE(800000000, 200, 3, 1, 0),
738 PLL_36XX_RATE(288000000, 96, 2, 2, 0),
739 PLL_36XX_RATE(192000000, 128, 2, 3, 0),
740 PLL_36XX_RATE(144000000, 96, 2, 3, 0),
741 PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
742 PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
743 PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
744 PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
745 PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
746 PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
747 PLL_36XX_RATE( 50000000, 200, 3, 5, 0),
748 PLL_36XX_RATE( 49152002, 131, 2, 5, 4719),
749 PLL_36XX_RATE( 48000000, 128, 2, 5, 0),
750 PLL_36XX_RATE( 45158401, 180, 3, 5, 41524),
751 { /* sentinel */ }
752};
753
728/* VPLL */ 754/* VPLL */
729static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { 755static struct samsung_pll_rate_table exynos3250_vpll_rates[] = {
730 PLL_36XX_RATE(600000000, 100, 2, 1, 0), 756 PLL_36XX_RATE(600000000, 100, 2, 1, 0),
@@ -822,3 +848,172 @@ static void __init exynos3250_cmu_init(struct device_node *np)
822 samsung_clk_of_add_provider(np, ctx); 848 samsung_clk_of_add_provider(np, ctx);
823} 849}
824CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); 850CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init);
851
852/*
853 * CMU DMC
854 */
855
856#define BPLL_LOCK 0x0118
857#define BPLL_CON0 0x0218
858#define BPLL_CON1 0x021c
859#define BPLL_CON2 0x0220
860#define SRC_DMC 0x0300
861#define DIV_DMC1 0x0504
862#define GATE_BUS_DMC0 0x0700
863#define GATE_BUS_DMC1 0x0704
864#define GATE_BUS_DMC2 0x0708
865#define GATE_BUS_DMC3 0x070c
866#define GATE_SCLK_DMC 0x0800
867#define GATE_IP_DMC0 0x0900
868#define GATE_IP_DMC1 0x0904
869#define EPLL_LOCK 0x1110
870#define EPLL_CON0 0x1114
871#define EPLL_CON1 0x1118
872#define EPLL_CON2 0x111c
873#define SRC_EPLL 0x1120
874
875/*
876 * Support for CMU save/restore across system suspends
877 */
878#ifdef CONFIG_PM_SLEEP
879static struct samsung_clk_reg_dump *exynos3250_dmc_clk_regs;
880
881static unsigned long exynos3250_cmu_dmc_clk_regs[] __initdata = {
882 BPLL_LOCK,
883 BPLL_CON0,
884 BPLL_CON1,
885 BPLL_CON2,
886 SRC_DMC,
887 DIV_DMC1,
888 GATE_BUS_DMC0,
889 GATE_BUS_DMC1,
890 GATE_BUS_DMC2,
891 GATE_BUS_DMC3,
892 GATE_SCLK_DMC,
893 GATE_IP_DMC0,
894 GATE_IP_DMC1,
895 EPLL_LOCK,
896 EPLL_CON0,
897 EPLL_CON1,
898 EPLL_CON2,
899 SRC_EPLL,
900};
901
902static int exynos3250_dmc_clk_suspend(void)
903{
904 samsung_clk_save(dmc_reg_base, exynos3250_dmc_clk_regs,
905 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
906 return 0;
907}
908
909static void exynos3250_dmc_clk_resume(void)
910{
911 samsung_clk_restore(dmc_reg_base, exynos3250_dmc_clk_regs,
912 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
913}
914
915static struct syscore_ops exynos3250_dmc_clk_syscore_ops = {
916 .suspend = exynos3250_dmc_clk_suspend,
917 .resume = exynos3250_dmc_clk_resume,
918};
919
920static void exynos3250_dmc_clk_sleep_init(void)
921{
922 exynos3250_dmc_clk_regs =
923 samsung_clk_alloc_reg_dump(exynos3250_cmu_dmc_clk_regs,
924 ARRAY_SIZE(exynos3250_cmu_dmc_clk_regs));
925 if (!exynos3250_dmc_clk_regs) {
926 pr_warn("%s: Failed to allocate sleep save data\n", __func__);
927 goto err;
928 }
929
930 register_syscore_ops(&exynos3250_dmc_clk_syscore_ops);
931 return;
932err:
933 kfree(exynos3250_dmc_clk_regs);
934}
935#else
936static inline void exynos3250_dmc_clk_sleep_init(void) { }
937#endif
938
939PNAME(mout_epll_p) = { "fin_pll", "fout_epll", };
940PNAME(mout_bpll_p) = { "fin_pll", "fout_bpll", };
941PNAME(mout_mpll_mif_p) = { "fin_pll", "sclk_mpll_mif", };
942PNAME(mout_dphy_p) = { "mout_mpll_mif", "mout_bpll", };
943
944static struct samsung_mux_clock dmc_mux_clks[] __initdata = {
945 /*
946 * NOTE: Following table is sorted by register address in ascending
947 * order and then bitfield shift in descending order, as it is done
948 * in the User's Manual. When adding new entries, please make sure
949 * that the order is preserved, to avoid merge conflicts and make
950 * further work with defined data easier.
951 */
952
953 /* SRC_DMC */
954 MUX(CLK_MOUT_MPLL_MIF, "mout_mpll_mif", mout_mpll_mif_p, SRC_DMC, 12, 1),
955 MUX(CLK_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_DMC, 10, 1),
956 MUX(CLK_MOUT_DPHY, "mout_dphy", mout_dphy_p, SRC_DMC, 8, 1),
957 MUX(CLK_MOUT_DMC_BUS, "mout_dmc_bus", mout_dphy_p, SRC_DMC, 4, 1),
958
959 /* SRC_EPLL */
960 MUX(CLK_MOUT_EPLL, "mout_epll", mout_epll_p, SRC_EPLL, 4, 1),
961};
962
963static struct samsung_div_clock dmc_div_clks[] __initdata = {
964 /*
965 * NOTE: Following table is sorted by register address in ascending
966 * order and then bitfield shift in descending order, as it is done
967 * in the User's Manual. When adding new entries, please make sure
968 * that the order is preserved, to avoid merge conflicts and make
969 * further work with defined data easier.
970 */
971
972 /* DIV_DMC1 */
973 DIV(CLK_DIV_DMC, "div_dmc", "div_dmc_pre", DIV_DMC1, 27, 3),
974 DIV(CLK_DIV_DPHY, "div_dphy", "mout_dphy", DIV_DMC1, 23, 3),
975 DIV(CLK_DIV_DMC_PRE, "div_dmc_pre", "mout_dmc_bus", DIV_DMC1, 19, 2),
976 DIV(CLK_DIV_DMCP, "div_dmcp", "div_dmcd", DIV_DMC1, 15, 3),
977 DIV(CLK_DIV_DMCD, "div_dmcd", "div_dmc", DIV_DMC1, 11, 3),
978};
979
980static struct samsung_pll_clock exynos3250_dmc_plls[nr_dmc_plls] __initdata = {
981 [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll",
982 BPLL_LOCK, BPLL_CON0, NULL),
983 [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
984 EPLL_LOCK, EPLL_CON0, NULL),
985};
986
987static void __init exynos3250_cmu_dmc_init(struct device_node *np)
988{
989 struct samsung_clk_provider *ctx;
990
991 dmc_reg_base = of_iomap(np, 0);
992 if (!dmc_reg_base)
993 panic("%s: failed to map registers\n", __func__);
994
995 ctx = samsung_clk_init(np, dmc_reg_base, NR_CLKS_DMC);
996 if (!ctx)
997 panic("%s: unable to allocate context.\n", __func__);
998
999 exynos3250_dmc_plls[bpll].rate_table = exynos3250_pll_rates;
1000 exynos3250_dmc_plls[epll].rate_table = exynos3250_epll_rates;
1001
1002 pr_err("CLK registering epll bpll: %d, %d, %d, %d\n",
1003 exynos3250_dmc_plls[bpll].rate_table[0].rate,
1004 exynos3250_dmc_plls[bpll].rate_table[0].mdiv,
1005 exynos3250_dmc_plls[bpll].rate_table[0].pdiv,
1006 exynos3250_dmc_plls[bpll].rate_table[0].sdiv
1007 );
1008 samsung_clk_register_pll(ctx, exynos3250_dmc_plls,
1009 ARRAY_SIZE(exynos3250_dmc_plls), dmc_reg_base);
1010
1011 samsung_clk_register_mux(ctx, dmc_mux_clks, ARRAY_SIZE(dmc_mux_clks));
1012 samsung_clk_register_div(ctx, dmc_div_clks, ARRAY_SIZE(dmc_div_clks));
1013
1014 exynos3250_dmc_clk_sleep_init();
1015
1016 samsung_clk_of_add_provider(np, ctx);
1017}
1018CLK_OF_DECLARE(exynos3250_cmu_dmc, "samsung,exynos3250-cmu-dmc",
1019 exynos3250_cmu_dmc_init);