From 3b6b717218968b500753f5b6b9eeeebcc4763446 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 25 Aug 2016 15:57:16 +0900 Subject: [PATCH 01/12] clk: samsung: Add clock IDs for the CMU_CDREX (DRAM Express Controller) This patch adds missing clock IDs for CMU_CDREX (DRAM Express Controller) which generates clocks for DRAM and NoC (Network on Chip) busses. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- include/dt-bindings/clock/exynos5420.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h index 17ab8394bec7..6fd21c291416 100644 --- a/include/dt-bindings/clock/exynos5420.h +++ b/include/dt-bindings/clock/exynos5420.h @@ -214,6 +214,9 @@ #define CLK_MOUT_SW_ACLK400 651 #define CLK_MOUT_USER_ACLK300_GSCL 652 #define CLK_MOUT_SW_ACLK300_GSCL 653 +#define CLK_MOUT_MCLK_CDREX 654 +#define CLK_MOUT_BPLL 655 +#define CLK_MOUT_MX_MSPLL_CCORE 656 /* divider clocks */ #define CLK_DOUT_PIXEL 768 @@ -239,8 +242,14 @@ #define CLK_DOUT_ACLK300_DISP1 788 #define CLK_DOUT_ACLK300_GSCL 789 #define CLK_DOUT_ACLK400_DISP1 790 +#define CLK_DOUT_PCLK_CDREX 791 +#define CLK_DOUT_SCLK_CDREX 792 +#define CLK_DOUT_ACLK_CDREX1 793 +#define CLK_DOUT_CCLK_DREX0 794 +#define CLK_DOUT_CLK2X_PHY0 795 +#define CLK_DOUT_PCLK_CORE_MEM 796 /* must be greater than maximal clock id */ -#define CLK_NR_CLKS 791 +#define CLK_NR_CLKS 797 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5420_H */ From 58d6506f327e3d192998ba03632f546da221b8d8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 22 Aug 2016 11:15:39 +0200 Subject: [PATCH 02/12] clk: samsung: exynos5410: Add clock IDs for PDMA and EPLL clocks The PDMA{0,1} and EPLL clock IDs are added separately in this patch so the patch can be merged to the arm-soc tree as dependency. Signed-off-by: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi --- include/dt-bindings/clock/exynos5410.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h index 85b467b3a207..6cb4e90f81fc 100644 --- a/include/dt-bindings/clock/exynos5410.h +++ b/include/dt-bindings/clock/exynos5410.h @@ -19,6 +19,7 @@ #define CLK_FOUT_MPLL 4 #define CLK_FOUT_BPLL 5 #define CLK_FOUT_KPLL 6 +#define CLK_FOUT_EPLL 7 /* gate for special clocks (sclk) */ #define CLK_SCLK_UART0 128 @@ -55,6 +56,8 @@ #define CLK_MMC0 351 #define CLK_MMC1 352 #define CLK_MMC2 353 +#define CLK_PDMA0 362 +#define CLK_PDMA1 363 #define CLK_USBH20 365 #define CLK_USBD300 366 #define CLK_USBD301 367 From 490583f0b6604a50073c3ba73fce596dc30d3282 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 18 Aug 2016 21:47:19 +0900 Subject: [PATCH 03/12] MAINTAINERS: Add myself as Samsung SoC clock drivers co-maintainer Add myself to the SAMSUNG SOC CLOCK DRIVERS entry, I'm going to review and test related patches as supporter. I can access all the datasheet of Exynos SoC series and can do tests on Exynos based boards. I have implemented the exynos4415/5433 clock drivers and co-authored the exynos3250 clock driver. While at it, add missing paths of the exynos clock driver files. Cc: Tomasz Figa Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 20bb1d00098c..442d6f5c65be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10233,9 +10233,12 @@ F: drivers/nfc/s3fwrn5 SAMSUNG SOC CLOCK DRIVERS M: Sylwester Nawrocki M: Tomasz Figa +M: Chanwoo Choi S: Supported L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers) F: drivers/clk/samsung/ +F: include/dt-bindings/clock/exynos*.h +F: Documentation/devicetree/bindings/clock/exynos*.txt SAMSUNG SXGBE DRIVERS M: Byungho An From 7a23fa0c6a9f5abf132d015cabc9d48a6eba3957 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 22 Aug 2016 11:49:44 +0900 Subject: [PATCH 04/12] clk: samsung: exynos5260: Move struct samsung_cmu_info to init section This patch moves the samsung_cmu_info struct instances to initconst section, this decreases the kernel image size by 784 bytes, which makes zImage smaller by 480 bytes. The patch increases .init.rodata section size by 780 bytes but decreases .init.text section size by 1564 bytes. Size of the drivers/clk/samsung/clk-exynos5260.o object file is 29100 bytes without the patch and 28316 after applying the patch. The section size differences are as below: 15c15 < 3 .init.text 000006b8 00000000 00000000 00000034 2**2 --- > 3 .init.text 0000009c 00000000 00000000 00000034 2**2 25c25 < 8 .init.rodata 00003f6c 00000000 00000000 00002f20 2**2 --- > 8 .init.rodata 00004278 00000000 00000000 00002904 2**2 Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5260.c | 350 +++++++++++++-------------- 1 file changed, 175 insertions(+), 175 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index a43642c36039..fd1d9bfc151b 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -131,21 +131,21 @@ static const struct samsung_gate_clock aud_gate_clks[] __initconst = { EN_IP_AUD, 4, 0, 0), }; +static const struct samsung_cmu_info aud_cmu __initconst = { + .mux_clks = aud_mux_clks, + .nr_mux_clks = ARRAY_SIZE(aud_mux_clks), + .div_clks = aud_div_clks, + .nr_div_clks = ARRAY_SIZE(aud_div_clks), + .gate_clks = aud_gate_clks, + .nr_gate_clks = ARRAY_SIZE(aud_gate_clks), + .nr_clk_ids = AUD_NR_CLK, + .clk_regs = aud_clk_regs, + .nr_clk_regs = ARRAY_SIZE(aud_clk_regs), +}; + static void __init exynos5260_clk_aud_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = aud_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); - cmu.div_clks = aud_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(aud_div_clks); - cmu.gate_clks = aud_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(aud_gate_clks); - cmu.nr_clk_ids = AUD_NR_CLK; - cmu.clk_regs = aud_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &aud_cmu); } CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", @@ -321,21 +321,21 @@ static const struct samsung_gate_clock disp_gate_clks[] __initconst = { EN_IP_DISP, 25, 0, 0), }; +static const struct samsung_cmu_info disp_cmu __initconst = { + .mux_clks = disp_mux_clks, + .nr_mux_clks = ARRAY_SIZE(disp_mux_clks), + .div_clks = disp_div_clks, + .nr_div_clks = ARRAY_SIZE(disp_div_clks), + .gate_clks = disp_gate_clks, + .nr_gate_clks = ARRAY_SIZE(disp_gate_clks), + .nr_clk_ids = DISP_NR_CLK, + .clk_regs = disp_clk_regs, + .nr_clk_regs = ARRAY_SIZE(disp_clk_regs), +}; + static void __init exynos5260_clk_disp_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = disp_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); - cmu.div_clks = disp_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(disp_div_clks); - cmu.gate_clks = disp_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(disp_gate_clks); - cmu.nr_clk_ids = DISP_NR_CLK; - cmu.clk_regs = disp_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &disp_cmu); } CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", @@ -385,21 +385,21 @@ static const struct samsung_pll_clock egl_pll_clks[] __initconst = { pll2550_24mhz_tbl), }; +static const struct samsung_cmu_info egl_cmu __initconst = { + .pll_clks = egl_pll_clks, + .nr_pll_clks = ARRAY_SIZE(egl_pll_clks), + .mux_clks = egl_mux_clks, + .nr_mux_clks = ARRAY_SIZE(egl_mux_clks), + .div_clks = egl_div_clks, + .nr_div_clks = ARRAY_SIZE(egl_div_clks), + .nr_clk_ids = EGL_NR_CLK, + .clk_regs = egl_clk_regs, + .nr_clk_regs = ARRAY_SIZE(egl_clk_regs), +}; + static void __init exynos5260_clk_egl_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.pll_clks = egl_pll_clks; - cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); - cmu.mux_clks = egl_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(egl_mux_clks); - cmu.div_clks = egl_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(egl_div_clks); - cmu.nr_clk_ids = EGL_NR_CLK; - cmu.clk_regs = egl_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &egl_cmu); } CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", @@ -487,19 +487,19 @@ static const struct samsung_gate_clock fsys_gate_clks[] __initconst = { EN_IP_FSYS_SECURE_SMMU_RTIC, 12, 0, 0), }; +static const struct samsung_cmu_info fsys_cmu __initconst = { + .mux_clks = fsys_mux_clks, + .nr_mux_clks = ARRAY_SIZE(fsys_mux_clks), + .gate_clks = fsys_gate_clks, + .nr_gate_clks = ARRAY_SIZE(fsys_gate_clks), + .nr_clk_ids = FSYS_NR_CLK, + .clk_regs = fsys_clk_regs, + .nr_clk_regs = ARRAY_SIZE(fsys_clk_regs), +}; + static void __init exynos5260_clk_fsys_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = fsys_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); - cmu.gate_clks = fsys_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(fsys_gate_clks); - cmu.nr_clk_ids = FSYS_NR_CLK; - cmu.clk_regs = fsys_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &fsys_cmu); } CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", @@ -576,21 +576,21 @@ static const struct samsung_gate_clock g2d_gate_clks[] __initconst = { EN_IP_G2D_SECURE_SMMU_G2D, 15, 0, 0), }; +static const struct samsung_cmu_info g2d_cmu __initconst = { + .mux_clks = g2d_mux_clks, + .nr_mux_clks = ARRAY_SIZE(g2d_mux_clks), + .div_clks = g2d_div_clks, + .nr_div_clks = ARRAY_SIZE(g2d_div_clks), + .gate_clks = g2d_gate_clks, + .nr_gate_clks = ARRAY_SIZE(g2d_gate_clks), + .nr_clk_ids = G2D_NR_CLK, + .clk_regs = g2d_clk_regs, + .nr_clk_regs = ARRAY_SIZE(g2d_clk_regs), +}; + static void __init exynos5260_clk_g2d_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = g2d_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); - cmu.div_clks = g2d_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(g2d_div_clks); - cmu.gate_clks = g2d_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(g2d_gate_clks); - cmu.nr_clk_ids = G2D_NR_CLK; - cmu.clk_regs = g2d_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &g2d_cmu); } CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", @@ -637,23 +637,23 @@ static const struct samsung_pll_clock g3d_pll_clks[] __initconst = { pll2550_24mhz_tbl), }; +static const struct samsung_cmu_info g3d_cmu __initconst = { + .pll_clks = g3d_pll_clks, + .nr_pll_clks = ARRAY_SIZE(g3d_pll_clks), + .mux_clks = g3d_mux_clks, + .nr_mux_clks = ARRAY_SIZE(g3d_mux_clks), + .div_clks = g3d_div_clks, + .nr_div_clks = ARRAY_SIZE(g3d_div_clks), + .gate_clks = g3d_gate_clks, + .nr_gate_clks = ARRAY_SIZE(g3d_gate_clks), + .nr_clk_ids = G3D_NR_CLK, + .clk_regs = g3d_clk_regs, + .nr_clk_regs = ARRAY_SIZE(g3d_clk_regs), +}; + static void __init exynos5260_clk_g3d_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.pll_clks = g3d_pll_clks; - cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); - cmu.mux_clks = g3d_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(g3d_mux_clks); - cmu.div_clks = g3d_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(g3d_div_clks); - cmu.gate_clks = g3d_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(g3d_gate_clks); - cmu.nr_clk_ids = G3D_NR_CLK; - cmu.clk_regs = g3d_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &g3d_cmu); } CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", @@ -772,21 +772,21 @@ static const struct samsung_gate_clock gscl_gate_clks[] __initconst = { EN_IP_GSCL_SECURE_SMMU_MSCL1, 20, 0, 0), }; +static const struct samsung_cmu_info gscl_cmu __initconst = { + .mux_clks = gscl_mux_clks, + .nr_mux_clks = ARRAY_SIZE(gscl_mux_clks), + .div_clks = gscl_div_clks, + .nr_div_clks = ARRAY_SIZE(gscl_div_clks), + .gate_clks = gscl_gate_clks, + .nr_gate_clks = ARRAY_SIZE(gscl_gate_clks), + .nr_clk_ids = GSCL_NR_CLK, + .clk_regs = gscl_clk_regs, + .nr_clk_regs = ARRAY_SIZE(gscl_clk_regs), +}; + static void __init exynos5260_clk_gscl_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = gscl_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); - cmu.div_clks = gscl_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(gscl_div_clks); - cmu.gate_clks = gscl_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(gscl_gate_clks); - cmu.nr_clk_ids = GSCL_NR_CLK; - cmu.clk_regs = gscl_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &gscl_cmu); } CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", @@ -891,21 +891,21 @@ static const struct samsung_gate_clock isp_gate_clks[] __initconst = { EN_SCLK_ISP, 9, CLK_SET_RATE_PARENT, 0), }; +static const struct samsung_cmu_info isp_cmu __initconst = { + .mux_clks = isp_mux_clks, + .nr_mux_clks = ARRAY_SIZE(isp_mux_clks), + .div_clks = isp_div_clks, + .nr_div_clks = ARRAY_SIZE(isp_div_clks), + .gate_clks = isp_gate_clks, + .nr_gate_clks = ARRAY_SIZE(isp_gate_clks), + .nr_clk_ids = ISP_NR_CLK, + .clk_regs = isp_clk_regs, + .nr_clk_regs = ARRAY_SIZE(isp_clk_regs), +}; + static void __init exynos5260_clk_isp_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = isp_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); - cmu.div_clks = isp_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(isp_div_clks); - cmu.gate_clks = isp_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(isp_gate_clks); - cmu.nr_clk_ids = ISP_NR_CLK; - cmu.clk_regs = isp_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &isp_cmu); } CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", @@ -955,21 +955,21 @@ static const struct samsung_pll_clock kfc_pll_clks[] __initconst = { pll2550_24mhz_tbl), }; +static const struct samsung_cmu_info kfc_cmu __initconst = { + .pll_clks = kfc_pll_clks, + .nr_pll_clks = ARRAY_SIZE(kfc_pll_clks), + .mux_clks = kfc_mux_clks, + .nr_mux_clks = ARRAY_SIZE(kfc_mux_clks), + .div_clks = kfc_div_clks, + .nr_div_clks = ARRAY_SIZE(kfc_div_clks), + .nr_clk_ids = KFC_NR_CLK, + .clk_regs = kfc_clk_regs, + .nr_clk_regs = ARRAY_SIZE(kfc_clk_regs), +}; + static void __init exynos5260_clk_kfc_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.pll_clks = kfc_pll_clks; - cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); - cmu.mux_clks = kfc_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(kfc_mux_clks); - cmu.div_clks = kfc_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(kfc_div_clks); - cmu.nr_clk_ids = KFC_NR_CLK; - cmu.clk_regs = kfc_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &kfc_cmu); } CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", @@ -1011,21 +1011,21 @@ static const struct samsung_gate_clock mfc_gate_clks[] __initconst = { EN_IP_MFC_SECURE_SMMU2_MFC, 7, 0, 0), }; +static const struct samsung_cmu_info mfc_cmu __initconst = { + .mux_clks = mfc_mux_clks, + .nr_mux_clks = ARRAY_SIZE(mfc_mux_clks), + .div_clks = mfc_div_clks, + .nr_div_clks = ARRAY_SIZE(mfc_div_clks), + .gate_clks = mfc_gate_clks, + .nr_gate_clks = ARRAY_SIZE(mfc_gate_clks), + .nr_clk_ids = MFC_NR_CLK, + .clk_regs = mfc_clk_regs, + .nr_clk_regs = ARRAY_SIZE(mfc_clk_regs), +}; + static void __init exynos5260_clk_mfc_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = mfc_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); - cmu.div_clks = mfc_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(mfc_div_clks); - cmu.gate_clks = mfc_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks); - cmu.nr_clk_ids = MFC_NR_CLK; - cmu.clk_regs = mfc_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &mfc_cmu); } CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", @@ -1158,23 +1158,23 @@ static const struct samsung_pll_clock mif_pll_clks[] __initconst = { pll2550_24mhz_tbl), }; +static const struct samsung_cmu_info mif_cmu __initconst = { + .pll_clks = mif_pll_clks, + .nr_pll_clks = ARRAY_SIZE(mif_pll_clks), + .mux_clks = mif_mux_clks, + .nr_mux_clks = ARRAY_SIZE(mif_mux_clks), + .div_clks = mif_div_clks, + .nr_div_clks = ARRAY_SIZE(mif_div_clks), + .gate_clks = mif_gate_clks, + .nr_gate_clks = ARRAY_SIZE(mif_gate_clks), + .nr_clk_ids = MIF_NR_CLK, + .clk_regs = mif_clk_regs, + .nr_clk_regs = ARRAY_SIZE(mif_clk_regs), +}; + static void __init exynos5260_clk_mif_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.pll_clks = mif_pll_clks; - cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); - cmu.mux_clks = mif_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(mif_mux_clks); - cmu.div_clks = mif_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(mif_div_clks); - cmu.gate_clks = mif_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(mif_gate_clks); - cmu.nr_clk_ids = MIF_NR_CLK; - cmu.clk_regs = mif_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &mif_cmu); } CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", @@ -1366,21 +1366,21 @@ static const struct samsung_gate_clock peri_gate_clks[] __initconst = { EN_IP_PERI_SECURE_TZPC, 20, 0, 0), }; +static const struct samsung_cmu_info peri_cmu __initconst = { + .mux_clks = peri_mux_clks, + .nr_mux_clks = ARRAY_SIZE(peri_mux_clks), + .div_clks = peri_div_clks, + .nr_div_clks = ARRAY_SIZE(peri_div_clks), + .gate_clks = peri_gate_clks, + .nr_gate_clks = ARRAY_SIZE(peri_gate_clks), + .nr_clk_ids = PERI_NR_CLK, + .clk_regs = peri_clk_regs, + .nr_clk_regs = ARRAY_SIZE(peri_clk_regs), +}; + static void __init exynos5260_clk_peri_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.mux_clks = peri_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); - cmu.div_clks = peri_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(peri_div_clks); - cmu.gate_clks = peri_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(peri_gate_clks); - cmu.nr_clk_ids = PERI_NR_CLK; - cmu.clk_regs = peri_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &peri_cmu); } CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", @@ -1818,25 +1818,25 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = { pll2650_24mhz_tbl), }; +static const struct samsung_cmu_info top_cmu __initconst = { + .pll_clks = top_pll_clks, + .nr_pll_clks = ARRAY_SIZE(top_pll_clks), + .mux_clks = top_mux_clks, + .nr_mux_clks = ARRAY_SIZE(top_mux_clks), + .div_clks = top_div_clks, + .nr_div_clks = ARRAY_SIZE(top_div_clks), + .gate_clks = top_gate_clks, + .nr_gate_clks = ARRAY_SIZE(top_gate_clks), + .fixed_clks = fixed_rate_clks, + .nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks), + .nr_clk_ids = TOP_NR_CLK, + .clk_regs = top_clk_regs, + .nr_clk_regs = ARRAY_SIZE(top_clk_regs), +}; + static void __init exynos5260_clk_top_init(struct device_node *np) { - struct samsung_cmu_info cmu = { NULL }; - - cmu.pll_clks = top_pll_clks; - cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); - cmu.mux_clks = top_mux_clks; - cmu.nr_mux_clks = ARRAY_SIZE(top_mux_clks); - cmu.div_clks = top_div_clks; - cmu.nr_div_clks = ARRAY_SIZE(top_div_clks); - cmu.gate_clks = top_gate_clks; - cmu.nr_gate_clks = ARRAY_SIZE(top_gate_clks); - cmu.fixed_clks = fixed_rate_clks; - cmu.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks); - cmu.nr_clk_ids = TOP_NR_CLK; - cmu.clk_regs = top_clk_regs; - cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); - - samsung_cmu_register_one(np, &cmu); + samsung_cmu_register_one(np, &top_cmu); } CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", From ba9d05d9728e229eaebc68c42215ed391f473263 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 22 Aug 2016 11:49:45 +0900 Subject: [PATCH 05/12] clk: samsung: exynos5410: Use samsung_cmu_register_one() to simplify code This patch uses the samsung_cmu_register_one() to simplify code and move the pll/mux/div/gate data to initconst section. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 33 +++++++++++----------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 54ec486a5e45..5488a4460c15 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -230,29 +230,22 @@ static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = { KPLL_CON0, NULL), }; +static const struct samsung_cmu_info cmu __initconst = { + .pll_clks = exynos5410_plls, + .nr_pll_clks = ARRAY_SIZE(exynos5410_plls), + .mux_clks = exynos5410_mux_clks, + .nr_mux_clks = ARRAY_SIZE(exynos5410_mux_clks), + .div_clks = exynos5410_div_clks, + .nr_div_clks = ARRAY_SIZE(exynos5410_div_clks), + .gate_clks = exynos5410_gate_clks, + .nr_gate_clks = ARRAY_SIZE(exynos5410_gate_clks), + .nr_clk_ids = CLK_NR_CLKS, +}; + /* register exynos5410 clocks */ static void __init exynos5410_clk_init(struct device_node *np) { - struct samsung_clk_provider *ctx; - void __iomem *reg_base; - - reg_base = of_iomap(np, 0); - if (!reg_base) - panic("%s: failed to map registers\n", __func__); - - ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); - - samsung_clk_register_pll(ctx, exynos5410_plls, - ARRAY_SIZE(exynos5410_plls), reg_base); - - samsung_clk_register_mux(ctx, exynos5410_mux_clks, - ARRAY_SIZE(exynos5410_mux_clks)); - samsung_clk_register_div(ctx, exynos5410_div_clks, - ARRAY_SIZE(exynos5410_div_clks)); - samsung_clk_register_gate(ctx, exynos5410_gate_clks, - ARRAY_SIZE(exynos5410_gate_clks)); - - samsung_clk_of_add_provider(np, ctx); + samsung_cmu_register_one(np, &cmu); pr_debug("Exynos5410: clock setup completed.\n"); } From e867e8fa825dd4fae2514883d77f5954d8d90991 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Thu, 25 Aug 2016 15:57:17 +0900 Subject: [PATCH 06/12] clk: samsung: exynos5420: Add clocks for CMU_CDREX domain This patch adds the mux/divider clocks for CMU_CDREX (DRAM Express Controller) which generates the clocks for DRAM and NoC (Network on Chip) bus. There is differnet source of MUX_MX_MSPLL_CCORE between exynos5420 and exynos5422, so each MUX_MX_MSPLL_CCORE uses the different parent source group. Signed-off-by: Chanwoo Choi Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5420.c | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index bb196ca21a77..8c8b495cbf0d 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -131,6 +131,9 @@ #define TOP_SPARE2 0x10b08 #define BPLL_LOCK 0x20010 #define BPLL_CON0 0x20110 +#define SRC_CDREX 0x20200 +#define DIV_CDREX0 0x20500 +#define DIV_CDREX1 0x20504 #define KPLL_LOCK 0x28000 #define KPLL_CON0 0x28100 #define SRC_KFC 0x28200 @@ -244,6 +247,9 @@ static const unsigned long exynos5x_clk_regs[] __initconst = { GATE_TOP_SCLK_FSYS, GATE_TOP_SCLK_PERIC, TOP_SPARE2, + SRC_CDREX, + DIV_CDREX0, + DIV_CDREX1, SRC_KFC, DIV_KFC0, }; @@ -448,6 +454,8 @@ PNAME(mout_maudio0_p) = {"fin_pll", "maudio_clk", "mout_sclk_dpll", "mout_sclk_epll", "mout_sclk_rpll"}; PNAME(mout_mau_epll_clk_p) = {"mout_sclk_epll", "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll"}; +PNAME(mout_mclk_cdrex_p) = {"mout_bpll", "mout_mx_mspll_ccore"}; + /* List of parents specific to exynos5800 */ PNAME(mout_epll2_5800_p) = { "mout_sclk_epll", "ff_dout_epll2" }; PNAME(mout_group1_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", @@ -465,6 +473,9 @@ PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll", PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll", "mout_epll2", "mout_sclk_ipll" }; +PNAME(mout_mx_mspll_ccore_p) = {"sclk_bpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2", + "mout_sclk_spll", "mout_sclk_epll"}; PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll", "mout_sclk_mpll", "ff_dout_spll2" }; @@ -523,6 +534,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2), MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2), + MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", + mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2), MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7, 20, 2), MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1), @@ -601,6 +614,8 @@ static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { MUX(0, "mout_aclk300_disp1", mout_group1_p, SRC_TOP2, 24, 2), MUX(0, "mout_aclk300_gscl", mout_group1_p, SRC_TOP2, 28, 2), + MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", + mout_group5_5800_p, SRC_TOP7, 16, 2), MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2), MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1), @@ -744,6 +759,12 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { MUX(0, "mout_fimd1_final", mout_fimd1_final_p, TOP_SPARE2, 8, 1), + /* CDREX block */ + MUX_F(CLK_MOUT_MCLK_CDREX, "mout_mclk_cdrex", mout_mclk_cdrex_p, + SRC_CDREX, 4, 1, CLK_SET_RATE_PARENT, 0), + MUX_F(CLK_MOUT_BPLL, "mout_bpll", mout_bpll_p, SRC_CDREX, 0, 1, + CLK_SET_RATE_PARENT, 0), + /* MAU Block */ MUX(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3), @@ -836,6 +857,21 @@ static const struct samsung_div_clock exynos5x_div_clks[] __initconst = { DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), + /* CDREX Block */ + DIV(CLK_DOUT_PCLK_CDREX, "dout_pclk_cdrex", "dout_aclk_cdrex1", + DIV_CDREX0, 28, 3), + DIV_F(CLK_DOUT_SCLK_CDREX, "dout_sclk_cdrex", "mout_mclk_cdrex", + DIV_CDREX0, 24, 3, CLK_SET_RATE_PARENT, 0), + DIV(CLK_DOUT_ACLK_CDREX1, "dout_aclk_cdrex1", "dout_clk2x_phy0", + DIV_CDREX0, 16, 3), + DIV(CLK_DOUT_CCLK_DREX0, "dout_cclk_drex0", "dout_clk2x_phy0", + DIV_CDREX0, 8, 3), + DIV(CLK_DOUT_CLK2X_PHY0, "dout_clk2x_phy0", "dout_sclk_cdrex", + DIV_CDREX0, 3, 5), + + DIV(CLK_DOUT_PCLK_CORE_MEM, "dout_pclk_core_mem", "mout_mclk_cdrex", + DIV_CDREX1, 8, 3), + /* Audio Block */ DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), DIV(0, "dout_maupcm0", "dout_maudio0", DIV_MAU, 24, 8), @@ -1364,6 +1400,7 @@ static void __init exynos5x_clk_init(struct device_node *np, if (_get_rate("fin_pll") == 24 * MHZ) { exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl; exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl; + exynos5x_plls[bpll].rate_table = exynos5420_pll2550x_24mhz_tbl; } samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls), From 0299042dca9689cdccfaaf00c5f64425c3ac360f Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Mon, 22 Aug 2016 11:14:49 +0200 Subject: [PATCH 07/12] clk: samsung: exynos5410: Expose the peripheral DMA gate clocks These clocks are needed in order to use the PL330 peripheral DMA controllers. Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos5410.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index 5488a4460c15..eefed92a59aa 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -176,6 +176,8 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0), GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0), GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0), + GATE(CLK_PDMA1, "pdma1", "aclk200", GATE_BUS_FSYS0, 2, 0, 0), + GATE(CLK_PDMA0, "pdma0", "aclk200", GATE_BUS_FSYS0, 1, 0, 0), GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301", GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0), From 1d9aa64c37f55d2c242f27a5788bf16a4f1578e4 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 18 Aug 2016 17:01:20 +0200 Subject: [PATCH 08/12] clk: samsung: Use common registration function for pll2550x There is no such significant differences in pll2550x PLL type to justify a separate registration function. This patch adapts exynos5440 driver to use the common function and removes samsung_clk_register_pll2550x(). Signed-off-by: Sylwester Nawrocki Reviewed-by: Krzysztof Kozlowski Reviewed-by: Chanwoo Choi --- drivers/clk/samsung/clk-exynos5440.c | 9 ++++- drivers/clk/samsung/clk-pll.c | 52 +++----------------------- drivers/clk/samsung/clk-pll.h | 1 + include/dt-bindings/clock/exynos5440.h | 2 + 4 files changed, 15 insertions(+), 49 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index a57d01b99b76..a80f3ef20801 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -112,6 +112,11 @@ static struct notifier_block exynos5440_clk_restart_handler = { .priority = 128, }; +static const struct samsung_pll_clock exynos5440_plls[] __initconst = { + PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL), + PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL), +}; + /* register exynos5440 clocks */ static void __init exynos5440_clk_init(struct device_node *np) { @@ -129,8 +134,8 @@ static void __init exynos5440_clk_init(struct device_node *np) samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10); - samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10); + samsung_clk_register_pll(ctx, exynos5440_plls, + ARRAY_SIZE(exynos5440_plls), ctx->reg_base); samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks, ARRAY_SIZE(exynos5440_fixed_rate_clks)); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 48139bd510f1..b5ab055957d2 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -890,22 +890,14 @@ static const struct clk_ops samsung_s3c2440_mpll_clk_ops = { #define PLL2550X_M_SHIFT (4) #define PLL2550X_S_SHIFT (0) -struct samsung_clk_pll2550x { - struct clk_hw hw; - const void __iomem *reg_base; - unsigned long offset; -}; - -#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw) - static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw); + struct samsung_clk_pll *pll = to_clk_pll(hw); u32 r, p, m, s, pll_stat; u64 fvco = parent_rate; - pll_stat = readl_relaxed(pll->reg_base + pll->offset * 3); + pll_stat = readl_relaxed(pll->con_reg); r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK; if (!r) return 0; @@ -923,43 +915,6 @@ static const struct clk_ops samsung_pll2550x_clk_ops = { .recalc_rate = samsung_pll2550x_recalc_rate, }; -struct clk * __init samsung_clk_register_pll2550x(const char *name, - const char *pname, const void __iomem *reg_base, - const unsigned long offset) -{ - struct samsung_clk_pll2550x *pll; - struct clk *clk; - struct clk_init_data init; - - pll = kzalloc(sizeof(*pll), GFP_KERNEL); - if (!pll) { - pr_err("%s: could not allocate pll clk %s\n", __func__, name); - return NULL; - } - - init.name = name; - init.ops = &samsung_pll2550x_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_names = &pname; - init.num_parents = 1; - - pll->hw.init = &init; - pll->reg_base = reg_base; - pll->offset = offset; - - clk = clk_register(NULL, &pll->hw); - if (IS_ERR(clk)) { - pr_err("%s: failed to register pll clock %s\n", __func__, - name); - kfree(pll); - } - - if (clk_register_clkdev(clk, name, NULL)) - pr_err("%s: failed to register lookup for %s", __func__, name); - - return clk; -} - /* * PLL2550xx Clock Type */ @@ -1263,6 +1218,9 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, else init.ops = &samsung_s3c2440_mpll_clk_ops; break; + case pll_2550x: + init.ops = &samsung_pll2550x_clk_ops; + break; case pll_2550xx: if (!pll->rate_table) init.ops = &samsung_pll2550xx_clk_min_ops; diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 213de9af8b4f..df4ad8a51050 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -31,6 +31,7 @@ enum samsung_pll_type { pll_s3c2410_mpll, pll_s3c2410_upll, pll_s3c2440_mpll, + pll_2550x, pll_2550xx, pll_2650xx, pll_1450x, diff --git a/include/dt-bindings/clock/exynos5440.h b/include/dt-bindings/clock/exynos5440.h index c66fc405a79a..842cdc0adff1 100644 --- a/include/dt-bindings/clock/exynos5440.h +++ b/include/dt-bindings/clock/exynos5440.h @@ -14,6 +14,8 @@ #define CLK_XTAL 1 #define CLK_ARM_CLK 2 +#define CLK_CPLLA 3 +#define CLK_CPLLB 4 #define CLK_SPI_BAUD 16 #define CLK_PB0_250 17 #define CLK_PR0_250 18 From 7c3ca061d4cfb25537d90a9ad936667b909133a0 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 2 Sep 2016 18:23:47 +0200 Subject: [PATCH 09/12] clk: samsung: clk-exynos-audss: controller variant handling rework Then variant handling is reworked to make the code simpler when more variants are added. Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-audss.c | 64 +++++++++++++++----------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index bdf8b971f332..7d4026b01c9a 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -14,18 +14,13 @@ #include #include #include +#include #include #include #include #include -enum exynos_audss_clk_type { - TYPE_EXYNOS4210, - TYPE_EXYNOS5250, - TYPE_EXYNOS5420, -}; - static DEFINE_SPINLOCK(lock); static struct clk **clk_table; static void __iomem *reg_base; @@ -73,14 +68,34 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = { }; #endif /* CONFIG_PM_SLEEP */ +struct exynos_audss_clk_drvdata { + unsigned int has_adma_clk:1; + unsigned int enable_epll:1; + unsigned int num_clks; +}; + +static const struct exynos_audss_clk_drvdata exynos4210_drvdata = { + .num_clks = EXYNOS_AUDSS_MAX_CLKS - 1, +}; + +static const struct exynos_audss_clk_drvdata exynos5420_drvdata = { + .num_clks = EXYNOS_AUDSS_MAX_CLKS, + .has_adma_clk = 1, + .enable_epll = 1, +}; + static const struct of_device_id exynos_audss_clk_of_match[] = { - { .compatible = "samsung,exynos4210-audss-clock", - .data = (void *)TYPE_EXYNOS4210, }, - { .compatible = "samsung,exynos5250-audss-clock", - .data = (void *)TYPE_EXYNOS5250, }, - { .compatible = "samsung,exynos5420-audss-clock", - .data = (void *)TYPE_EXYNOS5420, }, - {}, + { + .compatible = "samsung,exynos4210-audss-clock", + .data = &exynos4210_drvdata, + }, { + .compatible = "samsung,exynos5250-audss-clock", + .data = &exynos4210_drvdata, + }, { + .compatible = "samsung,exynos5420-audss-clock", + .data = &exynos5420_drvdata, + }, + { }, }; static void exynos_audss_clk_teardown(void) @@ -106,19 +121,17 @@ static void exynos_audss_clk_teardown(void) /* register exynos_audss clocks */ static int exynos_audss_clk_probe(struct platform_device *pdev) { - int i, ret = 0; - struct resource *res; const char *mout_audss_p[] = {"fin_pll", "fout_epll"}; const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"}; const char *sclk_pcm_p = "sclk_pcm0"; struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in; - const struct of_device_id *match; - enum exynos_audss_clk_type variant; + const struct exynos_audss_clk_drvdata *variant; + struct resource *res; + int i, ret = 0; - match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node); - if (!match) + variant = of_device_get_match_data(&pdev->dev); + if (!variant) return -EINVAL; - variant = (enum exynos_audss_clk_type)match->data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(&pdev->dev, res); @@ -126,7 +139,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to map audss registers\n"); return PTR_ERR(reg_base); } - /* EPLL don't have to be enabled for boards other than Exynos5420 */ + epll = ERR_PTR(-ENODEV); clk_table = devm_kzalloc(&pdev->dev, @@ -136,10 +149,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) return -ENOMEM; clk_data.clks = clk_table; - if (variant == TYPE_EXYNOS5420) - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS; - else - clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1; + clk_data.clk_num = variant->num_clks; pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); pll_in = devm_clk_get(&pdev->dev, "pll_in"); @@ -148,7 +158,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) if (!IS_ERR(pll_in)) { mout_audss_p[1] = __clk_get_name(pll_in); - if (variant == TYPE_EXYNOS5420) { + if (variant->enable_epll) { epll = pll_in; ret = clk_prepare_enable(epll); @@ -210,7 +220,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) sclk_pcm_p, CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 5, 0, &lock); - if (variant == TYPE_EXYNOS5420) { + if (variant->has_adma_clk) { clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma", "dout_srp", CLK_SET_RATE_PARENT, reg_base + ASS_CLK_GATE, 9, 0, &lock); From 2ec865b79b3852de6c663073c7a004e1fb918c3b Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 2 Sep 2016 18:47:45 +0200 Subject: [PATCH 10/12] clk: samsung: clk-exynos-audss: Add exynos5410 compatible Exynos5410 Audio Subsystem Clock Controller, comparing to the already supported IP block revisions, has additionally an I2S_MST divider so a new compatible string is added. It is not clear from the Exynos5410 User's Manual released on 2012.03.09 where in the clock tree the I2S_MST clock divider can be found exactly so this clock is left unimplemented for now. Signed-off-by: Sylwester Nawrocki --- .../devicetree/bindings/clock/clk-exynos-audss.txt | 4 +++- drivers/clk/samsung/clk-exynos-audss.c | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt index 180e8835569e..0c3d6015868d 100644 --- a/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt +++ b/Documentation/devicetree/bindings/clock/clk-exynos-audss.txt @@ -10,6 +10,8 @@ Required Properties: - "samsung,exynos4210-audss-clock" - controller compatible with all Exynos4 SoCs. - "samsung,exynos5250-audss-clock" - controller compatible with Exynos5250 SoCs. + - "samsung,exynos5410-audss-clock" - controller compatible with Exynos5410 + SoCs. - "samsung,exynos5420-audss-clock" - controller compatible with Exynos5420 SoCs. - reg: physical base address and length of the controller's register set. @@ -91,5 +93,5 @@ i2s0: i2s@03830000 { <&clock_audss EXYNOS_MOUT_AUDSS>, <&clock_audss EXYNOS_MOUT_I2S>; clock-names = "iis", "i2s_opclk0", "i2s_opclk1", - "mout_audss", "mout_i2s"; + "mout_audss", "mout_i2s"; }; diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 7d4026b01c9a..628f86b60eab 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -70,6 +70,7 @@ static struct syscore_ops exynos_audss_clk_syscore_ops = { struct exynos_audss_clk_drvdata { unsigned int has_adma_clk:1; + unsigned int has_mst_clk:1; unsigned int enable_epll:1; unsigned int num_clks; }; @@ -78,6 +79,11 @@ static const struct exynos_audss_clk_drvdata exynos4210_drvdata = { .num_clks = EXYNOS_AUDSS_MAX_CLKS - 1, }; +static const struct exynos_audss_clk_drvdata exynos5410_drvdata = { + .num_clks = EXYNOS_AUDSS_MAX_CLKS - 1, + .has_mst_clk = 1, +}; + static const struct exynos_audss_clk_drvdata exynos5420_drvdata = { .num_clks = EXYNOS_AUDSS_MAX_CLKS, .has_adma_clk = 1, @@ -91,6 +97,9 @@ static const struct of_device_id exynos_audss_clk_of_match[] = { }, { .compatible = "samsung,exynos5250-audss-clock", .data = &exynos4210_drvdata, + }, { + .compatible = "samsung,exynos5410-audss-clock", + .data = &exynos5410_drvdata, }, { .compatible = "samsung,exynos5420-audss-clock", .data = &exynos5420_drvdata, From c17a6163647a20d22fa03c00ba8714492b0311c6 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 2 Sep 2016 18:47:54 +0200 Subject: [PATCH 11/12] clk: samsung: clk-exynos-audss: Whitespace and debug trace cleanup There is no need to log probe() completion in normal conditions so the "setup completed" log is removed. Signed-off-by: Sylwester Nawrocki --- drivers/clk/samsung/clk-exynos-audss.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c index 628f86b60eab..51d152f735cc 100644 --- a/drivers/clk/samsung/clk-exynos-audss.c +++ b/drivers/clk/samsung/clk-exynos-audss.c @@ -39,9 +39,9 @@ static struct clk *epll; #ifdef CONFIG_PM_SLEEP static unsigned long reg_save[][2] = { - {ASS_CLK_SRC, 0}, - {ASS_CLK_DIV, 0}, - {ASS_CLK_GATE, 0}, + { ASS_CLK_SRC, 0 }, + { ASS_CLK_DIV, 0 }, + { ASS_CLK_GATE, 0 }, }; static int exynos_audss_clk_suspend(void) @@ -173,7 +173,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) ret = clk_prepare_enable(epll); if (ret) { dev_err(&pdev->dev, - "failed to prepare the epll clock\n"); + "failed to prepare the epll clock\n"); return ret; } } @@ -253,9 +253,6 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP register_syscore_ops(&exynos_audss_clk_syscore_ops); #endif - - dev_info(&pdev->dev, "setup completed\n"); - return 0; unregister: From be95d2c7d918b2b7b973378a1e92bdc6559c21f9 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Fri, 9 Sep 2016 10:09:05 +0200 Subject: [PATCH 12/12] clk: samsung: Add support for EPLL on exynos5410 This patch adds code instantiating the EPLL, which is used as the audio subsystem's root clock. The requirement to specify the external root clock in clocks property is documented. Having the consumer 'clocks' property ensures proper initialization order by explicitly specifying dependencies in DT. It prevents situations when the SoC's clock controller driver has initialized, the external oscillator clock is not yet registered and setting clock frequencies through assigned-clock-rates property doesn't work properly due to unknown external oscillator frequency. Signed-off-by: Sylwester Nawrocki Reviewed-by: Chanwoo Choi --- .../bindings/clock/exynos5410-clock.txt | 21 ++-- drivers/clk/samsung/clk-exynos5410.c | 30 +++++- drivers/clk/samsung/clk-pll.c | 102 ++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 1 + 4 files changed, 144 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/exynos5410-clock.txt b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt index aeab635b07b5..4527de3ea205 100644 --- a/Documentation/devicetree/bindings/clock/exynos5410-clock.txt +++ b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt @@ -12,24 +12,29 @@ Required Properties: - #clock-cells: should be 1. +- clocks: should contain an entry specifying the root clock from external + oscillator supplied through XXTI or XusbXTI pin. This clock should be + defined using standard clock bindings with "fin_pll" clock-output-name. + That clock is being passed internally to the 9 PLLs. + All available clocks are defined as preprocessor macros in dt-bindings/clock/exynos5410.h header and can be used in device tree sources. -External clock: - -There is clock that is generated outside the SoC. It -is expected that it is defined using standard clock bindings -with following clock-output-name: - - - "fin_pll" - PLL input clock from XXTI - Example 1: An example of a clock controller node is listed below. + fin_pll: xxti { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + clock-output-names = "fin_pll"; + #clock-cells = <0>; + }; + clock: clock-controller@0x10010000 { compatible = "samsung,exynos5410-clock"; reg = <0x10010000 0x30000>; #clock-cells = <1>; + clocks = <&fin_pll>; }; Example 2: UART controller node that consumes the clock generated by the clock diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index eefed92a59aa..fc471a49e8f4 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "clk.h" @@ -21,6 +22,8 @@ #define APLL_CON0 0x100 #define CPLL_LOCK 0x10020 #define CPLL_CON0 0x10120 +#define EPLL_LOCK 0x10040 +#define EPLL_CON0 0x10130 #define MPLL_LOCK 0x4000 #define MPLL_CON0 0x4100 #define BPLL_LOCK 0x20010 @@ -58,7 +61,7 @@ /* list of PLLs */ enum exynos5410_plls { - apll, cpll, mpll, + apll, cpll, epll, mpll, bpll, kpll, nr_plls /* number of PLLs */ }; @@ -67,6 +70,7 @@ enum exynos5410_plls { PNAME(apll_p) = { "fin_pll", "fout_apll", }; PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; PNAME(cpll_p) = { "fin_pll", "fout_cpll" }; +PNAME(epll_p) = { "fin_pll", "fout_epll" }; PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; @@ -95,6 +99,8 @@ static const struct samsung_mux_clock exynos5410_mux_clks[] __initconst = { MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1), + MUX(0, "sclk_epll", epll_p, SRC_TOP2, 12, 1), + MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1), MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1), @@ -219,11 +225,26 @@ static const struct samsung_gate_clock exynos5410_gate_clks[] __initconst = { GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0), }; -static const struct samsung_pll_clock exynos5410_plls[nr_plls] __initconst = { +static const struct samsung_pll_rate_table exynos5410_pll2550x_24mhz_tbl[] __initconst = { + PLL_36XX_RATE(400000000U, 200, 3, 2, 0), + PLL_36XX_RATE(333000000U, 111, 2, 2, 0), + PLL_36XX_RATE(300000000U, 100, 2, 2, 0), + PLL_36XX_RATE(266000000U, 266, 3, 3, 0), + PLL_36XX_RATE(200000000U, 200, 3, 3, 0), + PLL_36XX_RATE(192000000U, 192, 3, 3, 0), + PLL_36XX_RATE(166000000U, 166, 3, 3, 0), + PLL_36XX_RATE(133000000U, 266, 3, 4, 0), + PLL_36XX_RATE(100000000U, 200, 3, 4, 0), + PLL_36XX_RATE(66000000U, 176, 2, 5, 0), +}; + +static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = { [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, CPLL_CON0, NULL), + [epll] = PLL(pll_2650x, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK, + EPLL_CON0, NULL), [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, MPLL_CON0, NULL), [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, @@ -247,6 +268,11 @@ static const struct samsung_cmu_info cmu __initconst = { /* register exynos5410 clocks */ static void __init exynos5410_clk_init(struct device_node *np) { + struct clk *xxti = of_clk_get(np, 0); + + if (!IS_ERR(xxti) && clk_get_rate(xxti) == 24 * MHZ) + exynos5410_plls[epll].rate_table = exynos5410_pll2550x_24mhz_tbl; + samsung_cmu_register_one(np, &cmu); pr_debug("Exynos5410: clock setup completed.\n"); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index b5ab055957d2..9617825daabb 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -1017,6 +1017,102 @@ static const struct clk_ops samsung_pll2550xx_clk_min_ops = { .recalc_rate = samsung_pll2550xx_recalc_rate, }; +/* + * PLL2650x Clock Type + */ + +/* Maximum lock time can be 3000 * PDIV cycles */ +#define PLL2650X_LOCK_FACTOR 3000 + +#define PLL2650X_M_MASK 0x1ff +#define PLL2650X_P_MASK 0x3f +#define PLL2650X_S_MASK 0x7 +#define PLL2650X_K_MASK 0xffff +#define PLL2650X_LOCK_STAT_MASK 0x1 +#define PLL2650X_M_SHIFT 16 +#define PLL2650X_P_SHIFT 8 +#define PLL2650X_S_SHIFT 0 +#define PLL2650X_K_SHIFT 0 +#define PLL2650X_LOCK_STAT_SHIFT 29 +#define PLL2650X_PLL_ENABLE_SHIFT 31 + +static unsigned long samsung_pll2650x_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u64 fout = parent_rate; + u32 mdiv, pdiv, sdiv, pll_con0, pll_con1; + s16 kdiv; + + pll_con0 = readl_relaxed(pll->con_reg); + mdiv = (pll_con0 >> PLL2650X_M_SHIFT) & PLL2650X_M_MASK; + pdiv = (pll_con0 >> PLL2650X_P_SHIFT) & PLL2650X_P_MASK; + sdiv = (pll_con0 >> PLL2650X_S_SHIFT) & PLL2650X_S_MASK; + + pll_con1 = readl_relaxed(pll->con_reg + 4); + kdiv = (s16)((pll_con1 >> PLL2650X_K_SHIFT) & PLL2650X_K_MASK); + + fout *= (mdiv << 16) + kdiv; + do_div(fout, (pdiv << sdiv)); + fout >>= 16; + + return (unsigned long)fout; +} + +static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 con0, con1; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, clk_hw_get_name(hw)); + return -EINVAL; + } + + con0 = readl_relaxed(pll->con_reg); + con1 = readl_relaxed(pll->con_reg + 4); + + /* Set PLL lock time. */ + writel_relaxed(rate->pdiv * PLL2650X_LOCK_FACTOR, pll->lock_reg); + + /* Change PLL PMS values */ + con0 &= ~((PLL2650X_M_MASK << PLL2650X_M_SHIFT) | + (PLL2650X_P_MASK << PLL2650X_P_SHIFT) | + (PLL2650X_S_MASK << PLL2650X_S_SHIFT)); + con0 |= (rate->mdiv << PLL2650X_M_SHIFT) | + (rate->pdiv << PLL2650X_P_SHIFT) | + (rate->sdiv << PLL2650X_S_SHIFT); + con0 |= (1 << PLL2650X_PLL_ENABLE_SHIFT); + writel_relaxed(con0, pll->con_reg); + + con1 &= ~(PLL2650X_K_MASK << PLL2650X_K_SHIFT); + con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT); + writel_relaxed(con1, pll->con_reg + 4); + + do { + cpu_relax(); + con0 = readl_relaxed(pll->con_reg); + } while (!(con0 & (PLL2650X_LOCK_STAT_MASK + << PLL2650X_LOCK_STAT_SHIFT))); + + return 0; +} + +static const struct clk_ops samsung_pll2650x_clk_ops = { + .recalc_rate = samsung_pll2650x_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll2650x_set_rate, +}; + +static const struct clk_ops samsung_pll2650x_clk_min_ops = { + .recalc_rate = samsung_pll2650x_recalc_rate, +}; + /* * PLL2650XX Clock Type */ @@ -1227,6 +1323,12 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, else init.ops = &samsung_pll2550xx_clk_ops; break; + case pll_2650x: + if (!pll->rate_table) + init.ops = &samsung_pll2650x_clk_min_ops; + else + init.ops = &samsung_pll2650x_clk_ops; + break; case pll_2650xx: if (!pll->rate_table) init.ops = &samsung_pll2650xx_clk_min_ops; diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index df4ad8a51050..a1ca0233cb4b 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -33,6 +33,7 @@ enum samsung_pll_type { pll_s3c2440_mpll, pll_2550x, pll_2550xx, + pll_2650x, pll_2650xx, pll_1450x, pll_1451x,