mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
add suppport common clock framework for exynos
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRYuw1AAoJEA0Cl+kVi2xq53MP/Rimo8kL9e/dMrgxqvtQ198N csKzsAvOFSI69x0VupVOGfMSMDmltIaimyljJO3YrUvy+UOS3irWTHqu1JKq8+HX oaym2KirVFpGjcll4E2nyeZ18vL8Czt0bNPh2QVuHinwbETtAuq0CBfeAQLWA1Xs I/bbVKryocLwMNd5iqttSwGVwNZz14ceheliSHkneDeTaZJYQ0nSCLL7qmXncRFl Z1Xe4aZRTdiU8JZiRN6G3Q2UdhcKRwZPSZrftbVpDRBegnaZp6htUszD2GFX3SJH lV4ifgh9XVawRPE8Op00lX9fEjGe3EDP5kqqFRqht+mvr15vs2eFNiIIYOyjvBDU GfCK2Ij2QaUCiIweJOcO5SGkLKYqyVg+G5k7Z5M5FGwwBhEdZRPkZE++9cWG8K/m ziuJxAl9fK47NwUk4oz15e6JD6gFbEwqYf1f7RdvdRBiclarIuk2rha9BsoeOFM3 LBpGhWW4rcwEH87e0MjkvoopYl4ZHLtiZYk6cEg0rmAxKLvQjdZCZM+A707RG6DC CZiY6Iu5pSOIz4FweY42mXaANkdBlzn4r7/cPJj7S4umQlkEjYtwXEEziK50lc+g b7aZEvztQhFDw3lHhFeR44FCy7a1r5NjAZASshHJ72h3xNXrp+9bbugpbkdQVUKj tpL2eMZQn/lK6T1h8SwE =JEIy -----END PGP SIGNATURE----- Merge tag 'clk-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers From Kukjin Kim <[email protected]>: add suppport common clock framework for exynos * tag 'clk-exynos-for-v3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: (73 commits) ARM: EXYNOS: fix compilation error introduced due to common clock migration clk: exynos5250: Fix divider values for sclk_mmc{0,1,2,3} clk: exynos4: export clocks required for fimc-is clk: samsung: Fix compilation error clk: exynos5250: register display block gate clocks to common clock framework clk: exynos4: Add support for SoC-specific register save list clk: exynos4: Add missing registers to suspend save list clk: exynos4: Remove E4X12 prefix from SRC_DMC register clk: exynos4: Add E4210 prefix to GATE_IP_PERIR register clk: exynos4: Add E4210 prefix to LCD1 clock registers clk: exynos4: Remove SoC-specific registers from save list clk: exynos4: Use SRC_MASK_PERIL{0,1} definitions clk: exynos4: Define {E,V}PLL registers clk: exynos4: Add missing mout_sata on Exynos4210 clk: exynos4: Add missing CMU_TOP and ISP clocks clk: exynos4: Add G3D clocks clk: exynos4: Add camera related clock definitions clk: exynos4: Export mout_core clock of Exynos4210 clk: samsung: Remove unimplemented ops for pll clk: exynos4: Export clocks used by exynos cpufreq drivers ... [arnd: add missing #address-cells property in mshc DT node] Signed-off-by: Arnd Bergmann <[email protected]>
This commit is contained in:
commit
19ce4f4a03
53 changed files with 4655 additions and 4117 deletions
|
|
@ -29,6 +29,7 @@ obj-$(CONFIG_ARCH_U8500) += ux500/
|
|||
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
||||
obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||
obj-$(CONFIG_PLAT_SAMSUNG) += samsung/
|
||||
|
||||
obj-$(CONFIG_X86) += x86/
|
||||
|
||||
|
|
|
|||
8
drivers/clk/samsung/Makefile
Normal file
8
drivers/clk/samsung/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# Samsung Clock specific Makefile
|
||||
#
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o
|
||||
obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
|
||||
1091
drivers/clk/samsung/clk-exynos4.c
Normal file
1091
drivers/clk/samsung/clk-exynos4.c
Normal file
File diff suppressed because it is too large
Load diff
523
drivers/clk/samsung/clk-exynos5250.c
Normal file
523
drivers/clk/samsung/clk-exynos5250.c
Normal file
|
|
@ -0,0 +1,523 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Copyright (c) 2013 Linaro Ltd.
|
||||
* Author: Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for Exynos5250 SoC.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
#define SRC_CPU 0x200
|
||||
#define DIV_CPU0 0x500
|
||||
#define SRC_CORE1 0x4204
|
||||
#define SRC_TOP0 0x10210
|
||||
#define SRC_TOP2 0x10218
|
||||
#define SRC_GSCL 0x10220
|
||||
#define SRC_DISP1_0 0x1022c
|
||||
#define SRC_MAU 0x10240
|
||||
#define SRC_FSYS 0x10244
|
||||
#define SRC_GEN 0x10248
|
||||
#define SRC_PERIC0 0x10250
|
||||
#define SRC_PERIC1 0x10254
|
||||
#define SRC_MASK_GSCL 0x10320
|
||||
#define SRC_MASK_DISP1_0 0x1032c
|
||||
#define SRC_MASK_MAU 0x10334
|
||||
#define SRC_MASK_FSYS 0x10340
|
||||
#define SRC_MASK_GEN 0x10344
|
||||
#define SRC_MASK_PERIC0 0x10350
|
||||
#define SRC_MASK_PERIC1 0x10354
|
||||
#define DIV_TOP0 0x10510
|
||||
#define DIV_TOP1 0x10514
|
||||
#define DIV_GSCL 0x10520
|
||||
#define DIV_DISP1_0 0x1052c
|
||||
#define DIV_GEN 0x1053c
|
||||
#define DIV_MAU 0x10544
|
||||
#define DIV_FSYS0 0x10548
|
||||
#define DIV_FSYS1 0x1054c
|
||||
#define DIV_FSYS2 0x10550
|
||||
#define DIV_PERIC0 0x10558
|
||||
#define DIV_PERIC1 0x1055c
|
||||
#define DIV_PERIC2 0x10560
|
||||
#define DIV_PERIC3 0x10564
|
||||
#define DIV_PERIC4 0x10568
|
||||
#define DIV_PERIC5 0x1056c
|
||||
#define GATE_IP_GSCL 0x10920
|
||||
#define GATE_IP_MFC 0x1092c
|
||||
#define GATE_IP_GEN 0x10934
|
||||
#define GATE_IP_FSYS 0x10944
|
||||
#define GATE_IP_PERIC 0x10950
|
||||
#define GATE_IP_PERIS 0x10960
|
||||
#define SRC_CDREX 0x20200
|
||||
#define PLL_DIV2_SEL 0x20a24
|
||||
#define GATE_IP_DISP1 0x10928
|
||||
|
||||
/*
|
||||
* Let each supported clock get a unique id. This id is used to lookup the clock
|
||||
* for device tree based platforms. The clocks are categorized into three
|
||||
* sections: core, sclk gate and bus interface gate clocks.
|
||||
*
|
||||
* When adding a new clock to this list, it is advised to choose a clock
|
||||
* category and add it to the end of that category. That is because the the
|
||||
* device tree source file is referring to these ids and any change in the
|
||||
* sequence number of existing clocks will require corresponding change in the
|
||||
* device tree files. This limitation would go away when pre-processor support
|
||||
* for dtc would be available.
|
||||
*/
|
||||
enum exynos5250_clks {
|
||||
none,
|
||||
|
||||
/* core clocks */
|
||||
fin_pll,
|
||||
|
||||
/* gate for special clocks (sclk) */
|
||||
sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
|
||||
sclk_fimd1, sclk_mipi1, sclk_dp, sclk_hdmi, sclk_pixel, sclk_audio0,
|
||||
sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
|
||||
sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
|
||||
sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
|
||||
|
||||
/* gate clocks */
|
||||
gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
|
||||
smmu_gscl1, smmu_gscl2, smmu_gscl3, mfc, smmu_mfcl, smmu_mfcr, rotator,
|
||||
jpeg, mdma1, smmu_rotator, smmu_jpeg, smmu_mdma1, pdma0, pdma1, sata,
|
||||
usbotg, mipi_hsi, sdmmc0, sdmmc1, sdmmc2, sdmmc3, sromc, usb2, usb3,
|
||||
sata_phyctrl, sata_phyi2c, uart0, uart1, uart2, uart3, uart4, i2c0,
|
||||
i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, adc, spi0, spi1,
|
||||
spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
|
||||
hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
|
||||
tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
|
||||
wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
|
||||
|
||||
nr_clks,
|
||||
};
|
||||
|
||||
/*
|
||||
* list of controller registers to be saved and restored during a
|
||||
* suspend/resume cycle.
|
||||
*/
|
||||
static __initdata unsigned long exynos5250_clk_regs[] = {
|
||||
SRC_CPU,
|
||||
DIV_CPU0,
|
||||
SRC_CORE1,
|
||||
SRC_TOP0,
|
||||
SRC_TOP2,
|
||||
SRC_GSCL,
|
||||
SRC_DISP1_0,
|
||||
SRC_MAU,
|
||||
SRC_FSYS,
|
||||
SRC_GEN,
|
||||
SRC_PERIC0,
|
||||
SRC_PERIC1,
|
||||
SRC_MASK_GSCL,
|
||||
SRC_MASK_DISP1_0,
|
||||
SRC_MASK_MAU,
|
||||
SRC_MASK_FSYS,
|
||||
SRC_MASK_GEN,
|
||||
SRC_MASK_PERIC0,
|
||||
SRC_MASK_PERIC1,
|
||||
DIV_TOP0,
|
||||
DIV_TOP1,
|
||||
DIV_GSCL,
|
||||
DIV_DISP1_0,
|
||||
DIV_GEN,
|
||||
DIV_MAU,
|
||||
DIV_FSYS0,
|
||||
DIV_FSYS1,
|
||||
DIV_FSYS2,
|
||||
DIV_PERIC0,
|
||||
DIV_PERIC1,
|
||||
DIV_PERIC2,
|
||||
DIV_PERIC3,
|
||||
DIV_PERIC4,
|
||||
DIV_PERIC5,
|
||||
GATE_IP_GSCL,
|
||||
GATE_IP_MFC,
|
||||
GATE_IP_GEN,
|
||||
GATE_IP_FSYS,
|
||||
GATE_IP_PERIC,
|
||||
GATE_IP_PERIS,
|
||||
SRC_CDREX,
|
||||
PLL_DIV2_SEL,
|
||||
GATE_IP_DISP1,
|
||||
};
|
||||
|
||||
/* list of all parent clock list */
|
||||
PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
|
||||
PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", };
|
||||
PNAME(mout_mpll_fout_p) = { "fout_mplldiv2", "fout_mpll" };
|
||||
PNAME(mout_mpll_p) = { "fin_pll", "mout_mpll_fout" };
|
||||
PNAME(mout_bpll_fout_p) = { "fout_bplldiv2", "fout_bpll" };
|
||||
PNAME(mout_bpll_p) = { "fin_pll", "mout_bpll_fout" };
|
||||
PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" };
|
||||
PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" };
|
||||
PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" };
|
||||
PNAME(mout_epll_p) = { "fin_pll", "fout_epll" };
|
||||
PNAME(mout_mpll_user_p) = { "fin_pll", "sclk_mpll" };
|
||||
PNAME(mout_bpll_user_p) = { "fin_pll", "sclk_bpll" };
|
||||
PNAME(mout_aclk166_p) = { "sclk_cpll", "sclk_mpll_user" };
|
||||
PNAME(mout_aclk200_p) = { "sclk_mpll_user", "sclk_bpll_user" };
|
||||
PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
|
||||
PNAME(mout_usb3_p) = { "sclk_mpll_user", "sclk_cpll" };
|
||||
PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
|
||||
"sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy",
|
||||
"sclk_mpll_user", "sclk_epll", "sclk_vpll",
|
||||
"sclk_cpll" };
|
||||
PNAME(mout_audio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
|
||||
"sclk_uhostphy", "sclk_hdmiphy",
|
||||
"sclk_mpll_user", "sclk_epll", "sclk_vpll",
|
||||
"sclk_cpll" };
|
||||
PNAME(mout_audio1_p) = { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
|
||||
"sclk_uhostphy", "sclk_hdmiphy",
|
||||
"sclk_mpll_user", "sclk_epll", "sclk_vpll",
|
||||
"sclk_cpll" };
|
||||
PNAME(mout_audio2_p) = { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
|
||||
"sclk_uhostphy", "sclk_hdmiphy",
|
||||
"sclk_mpll_user", "sclk_epll", "sclk_vpll",
|
||||
"sclk_cpll" };
|
||||
PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
|
||||
"spdif_extclk" };
|
||||
|
||||
/* fixed rate clocks generated outside the soc */
|
||||
struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
|
||||
FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
|
||||
};
|
||||
|
||||
/* fixed rate clocks generated inside the soc */
|
||||
struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
|
||||
FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
|
||||
FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
|
||||
FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
|
||||
FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
|
||||
};
|
||||
|
||||
struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
|
||||
FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
|
||||
FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
|
||||
};
|
||||
|
||||
struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
|
||||
MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
|
||||
MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
|
||||
MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
|
||||
MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
|
||||
MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
|
||||
MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
|
||||
MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
|
||||
MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
|
||||
MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
|
||||
MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
|
||||
MUX(none, "sclk_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
|
||||
MUX(none, "sclk_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
|
||||
MUX(none, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
|
||||
MUX(none, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
|
||||
MUX(none, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
|
||||
MUX(none, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
|
||||
MUX(none, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
|
||||
MUX(none, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
|
||||
MUX(none, "mout_gscl_wa", mout_group1_p, SRC_GSCL, 24, 4),
|
||||
MUX(none, "mout_gscl_wb", mout_group1_p, SRC_GSCL, 28, 4),
|
||||
MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
|
||||
MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
|
||||
MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
|
||||
MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
|
||||
MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
|
||||
MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
|
||||
MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
|
||||
MUX(none, "mout_mmc2", mout_group1_p, SRC_FSYS, 8, 4),
|
||||
MUX(none, "mout_mmc3", mout_group1_p, SRC_FSYS, 12, 4),
|
||||
MUX(none, "mout_sata", mout_aclk200_p, SRC_FSYS, 24, 1),
|
||||
MUX(none, "mout_usb3", mout_usb3_p, SRC_FSYS, 28, 1),
|
||||
MUX(none, "mout_jpeg", mout_group1_p, SRC_GEN, 0, 4),
|
||||
MUX(none, "mout_uart0", mout_group1_p, SRC_PERIC0, 0, 4),
|
||||
MUX(none, "mout_uart1", mout_group1_p, SRC_PERIC0, 4, 4),
|
||||
MUX(none, "mout_uart2", mout_group1_p, SRC_PERIC0, 8, 4),
|
||||
MUX(none, "mout_uart3", mout_group1_p, SRC_PERIC0, 12, 4),
|
||||
MUX(none, "mout_pwm", mout_group1_p, SRC_PERIC0, 24, 4),
|
||||
MUX(none, "mout_audio1", mout_audio1_p, SRC_PERIC1, 0, 4),
|
||||
MUX(none, "mout_audio2", mout_audio2_p, SRC_PERIC1, 4, 4),
|
||||
MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIC1, 8, 2),
|
||||
MUX(none, "mout_spi0", mout_group1_p, SRC_PERIC1, 16, 4),
|
||||
MUX(none, "mout_spi1", mout_group1_p, SRC_PERIC1, 20, 4),
|
||||
MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
|
||||
};
|
||||
|
||||
struct samsung_div_clock exynos5250_div_clks[] __initdata = {
|
||||
DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
|
||||
DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
|
||||
DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
|
||||
DIV(none, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
|
||||
DIV(none, "aclk266", "sclk_mpll_user", DIV_TOP0, 16, 3),
|
||||
DIV(none, "aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
|
||||
DIV(none, "aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
|
||||
DIV(none, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
|
||||
DIV(none, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
|
||||
DIV(none, "div_cam0", "mout_cam0", DIV_GSCL, 16, 4),
|
||||
DIV(none, "div_cam1", "mout_cam1", DIV_GSCL, 20, 4),
|
||||
DIV(none, "div_gscl_wa", "mout_gscl_wa", DIV_GSCL, 24, 4),
|
||||
DIV(none, "div_gscl_wb", "mout_gscl_wb", DIV_GSCL, 28, 4),
|
||||
DIV(none, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4),
|
||||
DIV(none, "div_mipi1", "mout_mipi1", DIV_DISP1_0, 16, 4),
|
||||
DIV(none, "div_dp", "mout_dp", DIV_DISP1_0, 24, 4),
|
||||
DIV(none, "div_jpeg", "mout_jpeg", DIV_GEN, 4, 4),
|
||||
DIV(none, "div_audio0", "mout_audio0", DIV_MAU, 0, 4),
|
||||
DIV(none, "div_pcm0", "sclk_audio0", DIV_MAU, 4, 8),
|
||||
DIV(none, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
|
||||
DIV(none, "div_usb3", "mout_usb3", DIV_FSYS0, 24, 4),
|
||||
DIV(none, "div_mmc0", "mout_mmc0", DIV_FSYS1, 8, 8),
|
||||
DIV(none, "div_mmc1", "mout_mmc1", DIV_FSYS1, 24, 8),
|
||||
DIV(none, "div_mmc2", "mout_mmc2", DIV_FSYS2, 8, 8),
|
||||
DIV(none, "div_mmc3", "mout_mmc3", DIV_FSYS2, 24, 8),
|
||||
DIV(none, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
|
||||
DIV(none, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
|
||||
DIV(none, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
|
||||
DIV(none, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
|
||||
DIV(none, "div_spi0", "mout_spi0", DIV_PERIC1, 0, 4),
|
||||
DIV(none, "div_spi1", "mout_spi1", DIV_PERIC1, 16, 4),
|
||||
DIV(none, "div_spi2", "mout_spi2", DIV_PERIC2, 0, 4),
|
||||
DIV(none, "div_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
|
||||
DIV(none, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4),
|
||||
DIV(none, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8),
|
||||
DIV(none, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4),
|
||||
DIV(none, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8),
|
||||
DIV(none, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6),
|
||||
DIV(none, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
|
||||
DIV(sclk_pixel, "div_hdmi_pixel", "sclk_vpll", DIV_DISP1_0, 28, 4),
|
||||
DIV_A(none, "armclk", "div_arm", DIV_CPU0, 28, 3, "armclk"),
|
||||
DIV_F(none, "div_mipi1_pre", "div_mipi1",
|
||||
DIV_DISP1_0, 20, 4, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_mmc_pre0", "div_mmc0",
|
||||
DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_mmc_pre1", "div_mmc1",
|
||||
DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_mmc_pre2", "div_mmc2",
|
||||
DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_mmc_pre3", "div_mmc3",
|
||||
DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_spi_pre0", "div_spi0",
|
||||
DIV_PERIC1, 8, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_spi_pre1", "div_spi1",
|
||||
DIV_PERIC1, 24, 8, CLK_SET_RATE_PARENT, 0),
|
||||
DIV_F(none, "div_spi_pre2", "div_spi2",
|
||||
DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
|
||||
};
|
||||
|
||||
struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
|
||||
GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
|
||||
GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
|
||||
GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
|
||||
GATE(gscl3, "gscl3", "aclk266", GATE_IP_GSCL, 3, 0, 0),
|
||||
GATE(gscl_wa, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
|
||||
GATE(gscl_wb, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
|
||||
GATE(smmu_gscl0, "smmu_gscl0", "aclk266", GATE_IP_GSCL, 7, 0, 0),
|
||||
GATE(smmu_gscl1, "smmu_gscl1", "aclk266", GATE_IP_GSCL, 8, 0, 0),
|
||||
GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
|
||||
GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
|
||||
GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
|
||||
GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
|
||||
GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
|
||||
GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
|
||||
GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
|
||||
GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
|
||||
GATE(smmu_rotator, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0),
|
||||
GATE(smmu_jpeg, "smmu_jpeg", "aclk166", GATE_IP_GEN, 7, 0, 0),
|
||||
GATE(smmu_mdma1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0),
|
||||
GATE(pdma0, "pdma0", "aclk200", GATE_IP_FSYS, 1, 0, 0),
|
||||
GATE(pdma1, "pdma1", "aclk200", GATE_IP_FSYS, 2, 0, 0),
|
||||
GATE(sata, "sata", "aclk200", GATE_IP_FSYS, 6, 0, 0),
|
||||
GATE(usbotg, "usbotg", "aclk200", GATE_IP_FSYS, 7, 0, 0),
|
||||
GATE(mipi_hsi, "mipi_hsi", "aclk200", GATE_IP_FSYS, 8, 0, 0),
|
||||
GATE(sdmmc0, "sdmmc0", "aclk200", GATE_IP_FSYS, 12, 0, 0),
|
||||
GATE(sdmmc1, "sdmmc1", "aclk200", GATE_IP_FSYS, 13, 0, 0),
|
||||
GATE(sdmmc2, "sdmmc2", "aclk200", GATE_IP_FSYS, 14, 0, 0),
|
||||
GATE(sdmmc3, "sdmmc3", "aclk200", GATE_IP_FSYS, 15, 0, 0),
|
||||
GATE(sromc, "sromc", "aclk200", GATE_IP_FSYS, 17, 0, 0),
|
||||
GATE(usb2, "usb2", "aclk200", GATE_IP_FSYS, 18, 0, 0),
|
||||
GATE(usb3, "usb3", "aclk200", GATE_IP_FSYS, 19, 0, 0),
|
||||
GATE(sata_phyctrl, "sata_phyctrl", "aclk200", GATE_IP_FSYS, 24, 0, 0),
|
||||
GATE(sata_phyi2c, "sata_phyi2c", "aclk200", GATE_IP_FSYS, 25, 0, 0),
|
||||
GATE(uart0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
|
||||
GATE(uart1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
|
||||
GATE(uart2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
|
||||
GATE(uart3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
|
||||
GATE(uart4, "uart4", "aclk66", GATE_IP_PERIC, 4, 0, 0),
|
||||
GATE(i2c0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
|
||||
GATE(i2c1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
|
||||
GATE(i2c2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
|
||||
GATE(i2c3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
|
||||
GATE(i2c4, "i2c4", "aclk66", GATE_IP_PERIC, 10, 0, 0),
|
||||
GATE(i2c5, "i2c5", "aclk66", GATE_IP_PERIC, 11, 0, 0),
|
||||
GATE(i2c6, "i2c6", "aclk66", GATE_IP_PERIC, 12, 0, 0),
|
||||
GATE(i2c7, "i2c7", "aclk66", GATE_IP_PERIC, 13, 0, 0),
|
||||
GATE(i2c_hdmi, "i2c_hdmi", "aclk66", GATE_IP_PERIC, 14, 0, 0),
|
||||
GATE(adc, "adc", "aclk66", GATE_IP_PERIC, 15, 0, 0),
|
||||
GATE(spi0, "spi0", "aclk66", GATE_IP_PERIC, 16, 0, 0),
|
||||
GATE(spi1, "spi1", "aclk66", GATE_IP_PERIC, 17, 0, 0),
|
||||
GATE(spi2, "spi2", "aclk66", GATE_IP_PERIC, 18, 0, 0),
|
||||
GATE(i2s1, "i2s1", "aclk66", GATE_IP_PERIC, 20, 0, 0),
|
||||
GATE(i2s2, "i2s2", "aclk66", GATE_IP_PERIC, 21, 0, 0),
|
||||
GATE(pcm1, "pcm1", "aclk66", GATE_IP_PERIC, 22, 0, 0),
|
||||
GATE(pcm2, "pcm2", "aclk66", GATE_IP_PERIC, 23, 0, 0),
|
||||
GATE(pwm, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
|
||||
GATE(spdif, "spdif", "aclk66", GATE_IP_PERIC, 26, 0, 0),
|
||||
GATE(ac97, "ac97", "aclk66", GATE_IP_PERIC, 27, 0, 0),
|
||||
GATE(hsi2c0, "hsi2c0", "aclk66", GATE_IP_PERIC, 28, 0, 0),
|
||||
GATE(hsi2c1, "hsi2c1", "aclk66", GATE_IP_PERIC, 29, 0, 0),
|
||||
GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
|
||||
GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
|
||||
GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
|
||||
GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
|
||||
GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, 0, 0),
|
||||
GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
|
||||
GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
|
||||
GATE(tzpc2, "tzpc2", "aclk66", GATE_IP_PERIS, 8, 0, 0),
|
||||
GATE(tzpc3, "tzpc3", "aclk66", GATE_IP_PERIS, 9, 0, 0),
|
||||
GATE(tzpc4, "tzpc4", "aclk66", GATE_IP_PERIS, 10, 0, 0),
|
||||
GATE(tzpc5, "tzpc5", "aclk66", GATE_IP_PERIS, 11, 0, 0),
|
||||
GATE(tzpc6, "tzpc6", "aclk66", GATE_IP_PERIS, 12, 0, 0),
|
||||
GATE(tzpc7, "tzpc7", "aclk66", GATE_IP_PERIS, 13, 0, 0),
|
||||
GATE(tzpc8, "tzpc8", "aclk66", GATE_IP_PERIS, 14, 0, 0),
|
||||
GATE(tzpc9, "tzpc9", "aclk66", GATE_IP_PERIS, 15, 0, 0),
|
||||
GATE(hdmi_cec, "hdmi_cec", "aclk66", GATE_IP_PERIS, 16, 0, 0),
|
||||
GATE(mct, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
|
||||
GATE(wdt, "wdt", "aclk66", GATE_IP_PERIS, 19, 0, 0),
|
||||
GATE(rtc, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
|
||||
GATE(tmu, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
|
||||
GATE(cmu_top, "cmu_top", "aclk66",
|
||||
GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(cmu_core, "cmu_core", "aclk66",
|
||||
GATE_IP_PERIS, 4, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(cmu_mem, "cmu_mem", "aclk66",
|
||||
GATE_IP_PERIS, 5, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(sclk_cam_bayer, "sclk_cam_bayer", "div_cam_bayer",
|
||||
SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_cam0, "sclk_cam0", "div_cam0",
|
||||
SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_cam1, "sclk_cam1", "div_cam1",
|
||||
SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_gscl_wa, "sclk_gscl_wa", "div_gscl_wa",
|
||||
SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_gscl_wb, "sclk_gscl_wb", "div_gscl_wb",
|
||||
SRC_MASK_GSCL, 28, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_fimd1, "sclk_fimd1", "div_fimd1",
|
||||
SRC_MASK_DISP1_0, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_mipi1, "sclk_mipi1", "div_mipi1",
|
||||
SRC_MASK_DISP1_0, 12, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_dp, "sclk_dp", "div_dp",
|
||||
SRC_MASK_DISP1_0, 16, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi",
|
||||
SRC_MASK_DISP1_0, 20, 0, 0),
|
||||
GATE(sclk_audio0, "sclk_audio0", "div_audio0",
|
||||
SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_mmc0, "sclk_mmc0", "div_mmc0",
|
||||
SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_mmc1, "sclk_mmc1", "div_mmc1",
|
||||
SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_mmc2, "sclk_mmc2", "div_mmc2",
|
||||
SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_mmc3, "sclk_mmc3", "div_mmc3",
|
||||
SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_sata, "sclk_sata", "div_sata",
|
||||
SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_usb3, "sclk_usb3", "div_usb3",
|
||||
SRC_MASK_FSYS, 28, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_jpeg, "sclk_jpeg", "div_jpeg",
|
||||
SRC_MASK_GEN, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_uart0, "sclk_uart0", "div_uart0",
|
||||
SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_uart1, "sclk_uart1", "div_uart1",
|
||||
SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_uart2, "sclk_uart2", "div_uart2",
|
||||
SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_uart3, "sclk_uart3", "div_uart3",
|
||||
SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_pwm, "sclk_pwm", "div_pwm",
|
||||
SRC_MASK_PERIC0, 24, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_audio1, "sclk_audio1", "div_audio1",
|
||||
SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_audio2, "sclk_audio2", "div_audio2",
|
||||
SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_spdif, "sclk_spdif", "mout_spdif",
|
||||
SRC_MASK_PERIC1, 4, 0, 0),
|
||||
GATE(sclk_spi0, "sclk_spi0", "div_spi_pre0",
|
||||
SRC_MASK_PERIC1, 16, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_spi1, "sclk_spi1", "div_spi_pre1",
|
||||
SRC_MASK_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(sclk_spi2, "sclk_spi2", "div_spi_pre2",
|
||||
SRC_MASK_PERIC1, 24, CLK_SET_RATE_PARENT, 0),
|
||||
GATE(fimd1, "fimd1", "aclk200", GATE_IP_DISP1, 0, 0, 0),
|
||||
GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0),
|
||||
GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0),
|
||||
GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
|
||||
GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
|
||||
GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
|
||||
};
|
||||
|
||||
static __initdata struct of_device_id ext_clk_match[] = {
|
||||
{ .compatible = "samsung,clock-xxti", .data = (void *)0, },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* register exynox5250 clocks */
|
||||
void __init exynos5250_clk_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
|
||||
|
||||
if (np) {
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base)
|
||||
panic("%s: failed to map registers\n", __func__);
|
||||
} else {
|
||||
panic("%s: unable to determine soc\n", __func__);
|
||||
}
|
||||
|
||||
samsung_clk_init(np, reg_base, nr_clks,
|
||||
exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
|
||||
NULL, 0);
|
||||
samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
|
||||
ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
|
||||
ext_clk_match);
|
||||
|
||||
apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
|
||||
reg_base + 0x100);
|
||||
mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
|
||||
reg_base + 0x4100);
|
||||
bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
|
||||
reg_base + 0x20110);
|
||||
gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
|
||||
reg_base + 0x10150);
|
||||
cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
|
||||
reg_base + 0x10120);
|
||||
epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
|
||||
reg_base + 0x10130);
|
||||
vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
|
||||
reg_base + 0x10140);
|
||||
|
||||
samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos5250_fixed_rate_clks));
|
||||
samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos5250_fixed_factor_clks));
|
||||
samsung_clk_register_mux(exynos5250_mux_clks,
|
||||
ARRAY_SIZE(exynos5250_mux_clks));
|
||||
samsung_clk_register_div(exynos5250_div_clks,
|
||||
ARRAY_SIZE(exynos5250_div_clks));
|
||||
samsung_clk_register_gate(exynos5250_gate_clks,
|
||||
ARRAY_SIZE(exynos5250_gate_clks));
|
||||
|
||||
pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
|
||||
_get_rate("armclk"));
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
|
||||
139
drivers/clk/samsung/clk-exynos5440.c
Normal file
139
drivers/clk/samsung/clk-exynos5440.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Author: Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for Exynos5440 SoC.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
#define CLKEN_OV_VAL 0xf8
|
||||
#define CPU_CLK_STATUS 0xfc
|
||||
#define MISC_DOUT1 0x558
|
||||
|
||||
/*
|
||||
* Let each supported clock get a unique id. This id is used to lookup the clock
|
||||
* for device tree based platforms.
|
||||
*/
|
||||
enum exynos5440_clks {
|
||||
none, xtal, arm_clk,
|
||||
|
||||
spi_baud = 16, pb0_250, pr0_250, pr1_250, b_250, b_125, b_200, sata,
|
||||
usb, gmac0, cs250, pb0_250_o, pr0_250_o, pr1_250_o, b_250_o, b_125_o,
|
||||
b_200_o, sata_o, usb_o, gmac0_o, cs250_o,
|
||||
|
||||
nr_clks,
|
||||
};
|
||||
|
||||
/* parent clock name list */
|
||||
PNAME(mout_armclk_p) = { "cplla", "cpllb" };
|
||||
PNAME(mout_spi_p) = { "div125", "div200" };
|
||||
|
||||
/* fixed rate clocks generated outside the soc */
|
||||
struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
|
||||
FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
|
||||
};
|
||||
|
||||
/* fixed rate clocks */
|
||||
struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
|
||||
FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
|
||||
FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
|
||||
FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
|
||||
FRATE(none, "usb_ohci12", NULL, CLK_IS_ROOT, 12000000),
|
||||
FRATE(none, "usb_ohci48", NULL, CLK_IS_ROOT, 48000000),
|
||||
};
|
||||
|
||||
/* fixed factor clocks */
|
||||
struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
|
||||
FFACTOR(none, "div250", "ppll", 1, 4, 0),
|
||||
FFACTOR(none, "div200", "ppll", 1, 5, 0),
|
||||
FFACTOR(none, "div125", "div250", 1, 2, 0),
|
||||
};
|
||||
|
||||
/* mux clocks */
|
||||
struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
|
||||
MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
|
||||
MUX_A(arm_clk, "arm_clk", mout_armclk_p,
|
||||
CPU_CLK_STATUS, 0, 1, "armclk"),
|
||||
};
|
||||
|
||||
/* divider clocks */
|
||||
struct samsung_div_clock exynos5440_div_clks[] __initdata = {
|
||||
DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
|
||||
};
|
||||
|
||||
/* gate clocks */
|
||||
struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
|
||||
GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
|
||||
GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
|
||||
GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
|
||||
GATE(b_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
|
||||
GATE(b_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
|
||||
GATE(b_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
|
||||
GATE(sata, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
|
||||
GATE(usb, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
|
||||
GATE(gmac0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
|
||||
GATE(cs250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
|
||||
GATE(pb0_250_o, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
|
||||
GATE(pr0_250_o, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
|
||||
GATE(pr1_250_o, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
|
||||
GATE(b_250_o, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
|
||||
GATE(b_125_o, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
|
||||
GATE(b_200_o, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
|
||||
GATE(sata_o, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
|
||||
GATE(usb_o, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
|
||||
GATE(gmac0_o, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
|
||||
GATE(cs250_o, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
|
||||
};
|
||||
|
||||
static __initdata struct of_device_id ext_clk_match[] = {
|
||||
{ .compatible = "samsung,clock-xtal", .data = (void *)0, },
|
||||
{},
|
||||
};
|
||||
|
||||
/* register exynos5440 clocks */
|
||||
void __init exynos5440_clk_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: failed to map clock controller registers,"
|
||||
" aborting clock initialization\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0);
|
||||
samsung_clk_of_register_fixed_ext(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_fixed_rate(exynos5440_fixed_rate_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_rate_clks));
|
||||
samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
|
||||
ARRAY_SIZE(exynos5440_fixed_factor_clks));
|
||||
samsung_clk_register_mux(exynos5440_mux_clks,
|
||||
ARRAY_SIZE(exynos5440_mux_clks));
|
||||
samsung_clk_register_div(exynos5440_div_clks,
|
||||
ARRAY_SIZE(exynos5440_div_clks));
|
||||
samsung_clk_register_gate(exynos5440_gate_clks,
|
||||
ARRAY_SIZE(exynos5440_gate_clks));
|
||||
|
||||
pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk"));
|
||||
pr_info("exynos5440 clock initialization complete\n");
|
||||
}
|
||||
CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
|
||||
419
drivers/clk/samsung/clk-pll.c
Normal file
419
drivers/clk/samsung/clk-pll.c
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Copyright (c) 2013 Linaro Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This file contains the utility functions to register the pll clocks.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include "clk.h"
|
||||
#include "clk-pll.h"
|
||||
|
||||
/*
|
||||
* PLL35xx Clock Type
|
||||
*/
|
||||
|
||||
#define PLL35XX_MDIV_MASK (0x3FF)
|
||||
#define PLL35XX_PDIV_MASK (0x3F)
|
||||
#define PLL35XX_SDIV_MASK (0x7)
|
||||
#define PLL35XX_MDIV_SHIFT (16)
|
||||
#define PLL35XX_PDIV_SHIFT (8)
|
||||
#define PLL35XX_SDIV_SHIFT (0)
|
||||
|
||||
struct samsung_clk_pll35xx {
|
||||
struct clk_hw hw;
|
||||
const void __iomem *con_reg;
|
||||
};
|
||||
|
||||
#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
|
||||
|
||||
static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
|
||||
u32 mdiv, pdiv, sdiv, pll_con;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
|
||||
|
||||
fvco *= mdiv;
|
||||
do_div(fvco, (pdiv << sdiv));
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll35xx_clk_ops = {
|
||||
.recalc_rate = samsung_pll35xx_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk * __init samsung_clk_register_pll35xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg)
|
||||
{
|
||||
struct samsung_clk_pll35xx *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_pll35xx_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = &pname;
|
||||
init.num_parents = 1;
|
||||
|
||||
pll->hw.init = &init;
|
||||
pll->con_reg = con_reg;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL36xx Clock Type
|
||||
*/
|
||||
|
||||
#define PLL36XX_KDIV_MASK (0xFFFF)
|
||||
#define PLL36XX_MDIV_MASK (0x1FF)
|
||||
#define PLL36XX_PDIV_MASK (0x3F)
|
||||
#define PLL36XX_SDIV_MASK (0x7)
|
||||
#define PLL36XX_MDIV_SHIFT (16)
|
||||
#define PLL36XX_PDIV_SHIFT (8)
|
||||
#define PLL36XX_SDIV_SHIFT (0)
|
||||
|
||||
struct samsung_clk_pll36xx {
|
||||
struct clk_hw hw;
|
||||
const void __iomem *con_reg;
|
||||
};
|
||||
|
||||
#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
|
||||
|
||||
static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
|
||||
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con0 = __raw_readl(pll->con_reg);
|
||||
pll_con1 = __raw_readl(pll->con_reg + 4);
|
||||
mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
|
||||
pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
|
||||
sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
|
||||
kdiv = pll_con1 & PLL36XX_KDIV_MASK;
|
||||
|
||||
fvco *= (mdiv << 16) + kdiv;
|
||||
do_div(fvco, (pdiv << sdiv));
|
||||
fvco >>= 16;
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll36xx_clk_ops = {
|
||||
.recalc_rate = samsung_pll36xx_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk * __init samsung_clk_register_pll36xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg)
|
||||
{
|
||||
struct samsung_clk_pll36xx *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_pll36xx_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = &pname;
|
||||
init.num_parents = 1;
|
||||
|
||||
pll->hw.init = &init;
|
||||
pll->con_reg = con_reg;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL45xx Clock Type
|
||||
*/
|
||||
|
||||
#define PLL45XX_MDIV_MASK (0x3FF)
|
||||
#define PLL45XX_PDIV_MASK (0x3F)
|
||||
#define PLL45XX_SDIV_MASK (0x7)
|
||||
#define PLL45XX_MDIV_SHIFT (16)
|
||||
#define PLL45XX_PDIV_SHIFT (8)
|
||||
#define PLL45XX_SDIV_SHIFT (0)
|
||||
|
||||
struct samsung_clk_pll45xx {
|
||||
struct clk_hw hw;
|
||||
enum pll45xx_type type;
|
||||
const void __iomem *con_reg;
|
||||
};
|
||||
|
||||
#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
|
||||
|
||||
static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
|
||||
u32 mdiv, pdiv, sdiv, pll_con;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con = __raw_readl(pll->con_reg);
|
||||
mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
|
||||
pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
|
||||
sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
|
||||
|
||||
if (pll->type == pll_4508)
|
||||
sdiv = sdiv - 1;
|
||||
|
||||
fvco *= mdiv;
|
||||
do_div(fvco, (pdiv << sdiv));
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll45xx_clk_ops = {
|
||||
.recalc_rate = samsung_pll45xx_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk * __init samsung_clk_register_pll45xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg,
|
||||
enum pll45xx_type type)
|
||||
{
|
||||
struct samsung_clk_pll45xx *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_pll45xx_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = &pname;
|
||||
init.num_parents = 1;
|
||||
|
||||
pll->hw.init = &init;
|
||||
pll->con_reg = con_reg;
|
||||
pll->type = type;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL46xx Clock Type
|
||||
*/
|
||||
|
||||
#define PLL46XX_MDIV_MASK (0x1FF)
|
||||
#define PLL46XX_PDIV_MASK (0x3F)
|
||||
#define PLL46XX_SDIV_MASK (0x7)
|
||||
#define PLL46XX_MDIV_SHIFT (16)
|
||||
#define PLL46XX_PDIV_SHIFT (8)
|
||||
#define PLL46XX_SDIV_SHIFT (0)
|
||||
|
||||
#define PLL46XX_KDIV_MASK (0xFFFF)
|
||||
#define PLL4650C_KDIV_MASK (0xFFF)
|
||||
#define PLL46XX_KDIV_SHIFT (0)
|
||||
|
||||
struct samsung_clk_pll46xx {
|
||||
struct clk_hw hw;
|
||||
enum pll46xx_type type;
|
||||
const void __iomem *con_reg;
|
||||
};
|
||||
|
||||
#define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
|
||||
|
||||
static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw);
|
||||
u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_con0 = __raw_readl(pll->con_reg);
|
||||
pll_con1 = __raw_readl(pll->con_reg + 4);
|
||||
mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
|
||||
pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
|
||||
sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
|
||||
kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
|
||||
pll_con1 & PLL46XX_KDIV_MASK;
|
||||
|
||||
shift = pll->type == pll_4600 ? 16 : 10;
|
||||
fvco *= (mdiv << shift) + kdiv;
|
||||
do_div(fvco, (pdiv << sdiv));
|
||||
fvco >>= shift;
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
static const struct clk_ops samsung_pll46xx_clk_ops = {
|
||||
.recalc_rate = samsung_pll46xx_recalc_rate,
|
||||
};
|
||||
|
||||
struct clk * __init samsung_clk_register_pll46xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg,
|
||||
enum pll46xx_type type)
|
||||
{
|
||||
struct samsung_clk_pll46xx *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_pll46xx_clk_ops;
|
||||
init.flags = CLK_GET_RATE_NOCACHE;
|
||||
init.parent_names = &pname;
|
||||
init.num_parents = 1;
|
||||
|
||||
pll->hw.init = &init;
|
||||
pll->con_reg = con_reg;
|
||||
pll->type = type;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* PLL2550x Clock Type
|
||||
*/
|
||||
|
||||
#define PLL2550X_R_MASK (0x1)
|
||||
#define PLL2550X_P_MASK (0x3F)
|
||||
#define PLL2550X_M_MASK (0x3FF)
|
||||
#define PLL2550X_S_MASK (0x7)
|
||||
#define PLL2550X_R_SHIFT (20)
|
||||
#define PLL2550X_P_SHIFT (14)
|
||||
#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);
|
||||
u32 r, p, m, s, pll_stat;
|
||||
u64 fvco = parent_rate;
|
||||
|
||||
pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
|
||||
r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
|
||||
if (!r)
|
||||
return 0;
|
||||
p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
|
||||
m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
|
||||
s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
|
||||
|
||||
fvco *= m;
|
||||
do_div(fvco, (p << s));
|
||||
|
||||
return (unsigned long)fvco;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
41
drivers/clk/samsung/clk-pll.h
Normal file
41
drivers/clk/samsung/clk-pll.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Copyright (c) 2013 Linaro Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for all PLL's in Samsung platforms
|
||||
*/
|
||||
|
||||
#ifndef __SAMSUNG_CLK_PLL_H
|
||||
#define __SAMSUNG_CLK_PLL_H
|
||||
|
||||
enum pll45xx_type {
|
||||
pll_4500,
|
||||
pll_4502,
|
||||
pll_4508
|
||||
};
|
||||
|
||||
enum pll46xx_type {
|
||||
pll_4600,
|
||||
pll_4650,
|
||||
pll_4650c,
|
||||
};
|
||||
|
||||
extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg);
|
||||
extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg);
|
||||
extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg,
|
||||
enum pll45xx_type type);
|
||||
extern struct clk * __init samsung_clk_register_pll46xx(const char *name,
|
||||
const char *pname, const void __iomem *con_reg,
|
||||
enum pll46xx_type type);
|
||||
extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
|
||||
const char *pname, const void __iomem *reg_base,
|
||||
const unsigned long offset);
|
||||
|
||||
#endif /* __SAMSUNG_CLK_PLL_H */
|
||||
320
drivers/clk/samsung/clk.c
Normal file
320
drivers/clk/samsung/clk.c
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Copyright (c) 2013 Linaro Ltd.
|
||||
* Author: Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This file includes utility functions to register clocks to common
|
||||
* clock framework for Samsung platforms.
|
||||
*/
|
||||
|
||||
#include <linux/syscore_ops.h>
|
||||
#include "clk.h"
|
||||
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
static struct clk **clk_table;
|
||||
static void __iomem *reg_base;
|
||||
#ifdef CONFIG_OF
|
||||
static struct clk_onecell_data clk_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static struct samsung_clk_reg_dump *reg_dump;
|
||||
static unsigned long nr_reg_dump;
|
||||
|
||||
static int samsung_clk_suspend(void)
|
||||
{
|
||||
struct samsung_clk_reg_dump *rd = reg_dump;
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < nr_reg_dump; i++, rd++)
|
||||
rd->value = __raw_readl(reg_base + rd->offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void samsung_clk_resume(void)
|
||||
{
|
||||
struct samsung_clk_reg_dump *rd = reg_dump;
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < nr_reg_dump; i++, rd++)
|
||||
__raw_writel(rd->value, reg_base + rd->offset);
|
||||
}
|
||||
|
||||
static struct syscore_ops samsung_clk_syscore_ops = {
|
||||
.suspend = samsung_clk_suspend,
|
||||
.resume = samsung_clk_resume,
|
||||
};
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
/* setup the essentials required to support clock lookup using ccf */
|
||||
void __init samsung_clk_init(struct device_node *np, void __iomem *base,
|
||||
unsigned long nr_clks, unsigned long *rdump,
|
||||
unsigned long nr_rdump, unsigned long *soc_rdump,
|
||||
unsigned long nr_soc_rdump)
|
||||
{
|
||||
reg_base = base;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (rdump && nr_rdump) {
|
||||
unsigned int idx;
|
||||
reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
|
||||
* (nr_rdump + nr_soc_rdump), GFP_KERNEL);
|
||||
if (!reg_dump) {
|
||||
pr_err("%s: memory alloc for register dump failed\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < nr_rdump; idx++)
|
||||
reg_dump[idx].offset = rdump[idx];
|
||||
for (idx = 0; idx < nr_soc_rdump; idx++)
|
||||
reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
|
||||
nr_reg_dump = nr_rdump + nr_soc_rdump;
|
||||
register_syscore_ops(&samsung_clk_syscore_ops);
|
||||
}
|
||||
#endif
|
||||
|
||||
clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
|
||||
if (!clk_table)
|
||||
panic("could not allocate clock lookup table\n");
|
||||
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
clk_data.clks = clk_table;
|
||||
clk_data.clk_num = nr_clks;
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* add a clock instance to the clock lookup table used for dt based lookup */
|
||||
void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
|
||||
{
|
||||
if (clk_table && id)
|
||||
clk_table[id] = clk;
|
||||
}
|
||||
|
||||
/* register a list of aliases */
|
||||
void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
|
||||
if (!clk_table) {
|
||||
pr_err("%s: clock table missing\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
if (!list->id) {
|
||||
pr_err("%s: clock id missing for index %d\n", __func__,
|
||||
idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
clk = clk_table[list->id];
|
||||
if (!clk) {
|
||||
pr_err("%s: failed to find clock %d\n", __func__,
|
||||
list->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = clk_register_clkdev(clk, list->alias, list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
}
|
||||
|
||||
/* register a list of fixed clocks */
|
||||
void __init samsung_clk_register_fixed_rate(
|
||||
struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_fixed_rate(NULL, list->name,
|
||||
list->parent_name, list->flags, list->fixed_rate);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(clk, list->id);
|
||||
|
||||
/*
|
||||
* Unconditionally add a clock lookup for the fixed rate clocks.
|
||||
* There are not many of these on any of Samsung platforms.
|
||||
*/
|
||||
ret = clk_register_clkdev(clk, list->name, NULL);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register clock lookup for %s",
|
||||
__func__, list->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* register a list of fixed factor clocks */
|
||||
void __init samsung_clk_register_fixed_factor(
|
||||
struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_fixed_factor(NULL, list->name,
|
||||
list->parent_name, list->flags, list->mult, list->div);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(clk, list->id);
|
||||
}
|
||||
}
|
||||
|
||||
/* register a list of mux clocks */
|
||||
void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_mux(NULL, list->name, list->parent_names,
|
||||
list->num_parents, list->flags, reg_base + list->offset,
|
||||
list->shift, list->width, list->mux_flags, &lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(clk, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* register a list of div clocks */
|
||||
void __init samsung_clk_register_div(struct samsung_div_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
if (list->table)
|
||||
clk = clk_register_divider_table(NULL, list->name,
|
||||
list->parent_name, list->flags,
|
||||
reg_base + list->offset, list->shift,
|
||||
list->width, list->div_flags,
|
||||
list->table, &lock);
|
||||
else
|
||||
clk = clk_register_divider(NULL, list->name,
|
||||
list->parent_name, list->flags,
|
||||
reg_base + list->offset, list->shift,
|
||||
list->width, list->div_flags, &lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(clk, list->id);
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* register a list of gate clocks */
|
||||
void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
|
||||
unsigned int nr_clk)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned int idx, ret;
|
||||
|
||||
for (idx = 0; idx < nr_clk; idx++, list++) {
|
||||
clk = clk_register_gate(NULL, list->name, list->parent_name,
|
||||
list->flags, reg_base + list->offset,
|
||||
list->bit_idx, list->gate_flags, &lock);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register clock %s\n", __func__,
|
||||
list->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* register a clock lookup only if a clock alias is specified */
|
||||
if (list->alias) {
|
||||
ret = clk_register_clkdev(clk, list->alias,
|
||||
list->dev_name);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register lookup %s\n",
|
||||
__func__, list->alias);
|
||||
}
|
||||
|
||||
samsung_clk_add_lookup(clk, list->id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* obtain the clock speed of all external fixed clock sources from device
|
||||
* tree and register it
|
||||
*/
|
||||
#ifdef CONFIG_OF
|
||||
void __init samsung_clk_of_register_fixed_ext(
|
||||
struct samsung_fixed_rate_clock *fixed_rate_clk,
|
||||
unsigned int nr_fixed_rate_clk,
|
||||
struct of_device_id *clk_matches)
|
||||
{
|
||||
const struct of_device_id *match;
|
||||
struct device_node *np;
|
||||
u32 freq;
|
||||
|
||||
for_each_matching_node_and_match(np, clk_matches, &match) {
|
||||
if (of_property_read_u32(np, "clock-frequency", &freq))
|
||||
continue;
|
||||
fixed_rate_clk[(u32)match->data].fixed_rate = freq;
|
||||
}
|
||||
samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* utility function to get the rate of a specified clock */
|
||||
unsigned long _get_rate(const char *clk_name)
|
||||
{
|
||||
struct clk *clk;
|
||||
unsigned long rate;
|
||||
|
||||
clk = clk_get(NULL, clk_name);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: could not find clock %s\n", __func__, clk_name);
|
||||
return 0;
|
||||
}
|
||||
rate = clk_get_rate(clk);
|
||||
clk_put(clk);
|
||||
return rate;
|
||||
}
|
||||
289
drivers/clk/samsung/clk.h
Normal file
289
drivers/clk/samsung/clk.h
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
|
||||
* Copyright (c) 2013 Linaro Ltd.
|
||||
* Author: Thomas Abraham <thomas.ab@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Common Clock Framework support for all Samsung platforms
|
||||
*/
|
||||
|
||||
#ifndef __SAMSUNG_CLK_H
|
||||
#define __SAMSUNG_CLK_H
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
|
||||
/**
|
||||
* struct samsung_clock_alias: information about mux clock
|
||||
* @id: platform specific id of the clock.
|
||||
* @dev_name: name of the device to which this clock belongs.
|
||||
* @alias: optional clock alias name to be assigned to this clock.
|
||||
*/
|
||||
struct samsung_clock_alias {
|
||||
unsigned int id;
|
||||
const char *dev_name;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
#define ALIAS(_id, dname, a) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.alias = a, \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct samsung_fixed_rate_clock: information about fixed-rate clock
|
||||
* @id: platform specific id of the clock.
|
||||
* @name: name of this fixed-rate clock.
|
||||
* @parent_name: optional parent clock name.
|
||||
* @flags: optional fixed-rate clock flags.
|
||||
* @fixed-rate: fixed clock rate of this clock.
|
||||
*/
|
||||
struct samsung_fixed_rate_clock {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long fixed_rate;
|
||||
};
|
||||
|
||||
#define FRATE(_id, cname, pname, f, frate) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.name = cname, \
|
||||
.parent_name = pname, \
|
||||
.flags = f, \
|
||||
.fixed_rate = frate, \
|
||||
}
|
||||
|
||||
/*
|
||||
* struct samsung_fixed_factor_clock: information about fixed-factor clock
|
||||
* @id: platform specific id of the clock.
|
||||
* @name: name of this fixed-factor clock.
|
||||
* @parent_name: parent clock name.
|
||||
* @mult: fixed multiplication factor.
|
||||
* @div: fixed division factor.
|
||||
* @flags: optional fixed-factor clock flags.
|
||||
*/
|
||||
struct samsung_fixed_factor_clock {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
const char *parent_name;
|
||||
unsigned long mult;
|
||||
unsigned long div;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
#define FFACTOR(_id, cname, pname, m, d, f) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.name = cname, \
|
||||
.parent_name = pname, \
|
||||
.mult = m, \
|
||||
.div = d, \
|
||||
.flags = f, \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct samsung_mux_clock: information about mux clock
|
||||
* @id: platform specific id of the clock.
|
||||
* @dev_name: name of the device to which this clock belongs.
|
||||
* @name: name of this mux clock.
|
||||
* @parent_names: array of pointer to parent clock names.
|
||||
* @num_parents: number of parents listed in @parent_names.
|
||||
* @flags: optional flags for basic clock.
|
||||
* @offset: offset of the register for configuring the mux.
|
||||
* @shift: starting bit location of the mux control bit-field in @reg.
|
||||
* @width: width of the mux control bit-field in @reg.
|
||||
* @mux_flags: flags for mux-type clock.
|
||||
* @alias: optional clock alias name to be assigned to this clock.
|
||||
*/
|
||||
struct samsung_mux_clock {
|
||||
unsigned int id;
|
||||
const char *dev_name;
|
||||
const char *name;
|
||||
const char **parent_names;
|
||||
u8 num_parents;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u8 mux_flags;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.name = cname, \
|
||||
.parent_names = pnames, \
|
||||
.num_parents = ARRAY_SIZE(pnames), \
|
||||
.flags = f, \
|
||||
.offset = o, \
|
||||
.shift = s, \
|
||||
.width = w, \
|
||||
.mux_flags = mf, \
|
||||
.alias = a, \
|
||||
}
|
||||
|
||||
#define MUX(_id, cname, pnames, o, s, w) \
|
||||
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
|
||||
|
||||
#define MUX_A(_id, cname, pnames, o, s, w, a) \
|
||||
__MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
|
||||
|
||||
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
|
||||
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
|
||||
|
||||
/**
|
||||
* @id: platform specific id of the clock.
|
||||
* struct samsung_div_clock: information about div clock
|
||||
* @dev_name: name of the device to which this clock belongs.
|
||||
* @name: name of this div clock.
|
||||
* @parent_name: name of the parent clock.
|
||||
* @flags: optional flags for basic clock.
|
||||
* @offset: offset of the register for configuring the div.
|
||||
* @shift: starting bit location of the div control bit-field in @reg.
|
||||
* @div_flags: flags for div-type clock.
|
||||
* @alias: optional clock alias name to be assigned to this clock.
|
||||
*/
|
||||
struct samsung_div_clock {
|
||||
unsigned int id;
|
||||
const char *dev_name;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 shift;
|
||||
u8 width;
|
||||
u8 div_flags;
|
||||
const char *alias;
|
||||
struct clk_div_table *table;
|
||||
};
|
||||
|
||||
#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.name = cname, \
|
||||
.parent_name = pname, \
|
||||
.flags = f, \
|
||||
.offset = o, \
|
||||
.shift = s, \
|
||||
.width = w, \
|
||||
.div_flags = df, \
|
||||
.alias = a, \
|
||||
.table = t, \
|
||||
}
|
||||
|
||||
#define DIV(_id, cname, pname, o, s, w) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
|
||||
|
||||
#define DIV_A(_id, cname, pname, o, s, w, a) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
|
||||
|
||||
#define DIV_F(_id, cname, pname, o, s, w, f, df) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
|
||||
|
||||
#define DIV_T(_id, cname, pname, o, s, w, t) \
|
||||
__DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
|
||||
|
||||
/**
|
||||
* struct samsung_gate_clock: information about gate clock
|
||||
* @id: platform specific id of the clock.
|
||||
* @dev_name: name of the device to which this clock belongs.
|
||||
* @name: name of this gate clock.
|
||||
* @parent_name: name of the parent clock.
|
||||
* @flags: optional flags for basic clock.
|
||||
* @offset: offset of the register for configuring the gate.
|
||||
* @bit_idx: bit index of the gate control bit-field in @reg.
|
||||
* @gate_flags: flags for gate-type clock.
|
||||
* @alias: optional clock alias name to be assigned to this clock.
|
||||
*/
|
||||
struct samsung_gate_clock {
|
||||
unsigned int id;
|
||||
const char *dev_name;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
unsigned long offset;
|
||||
u8 bit_idx;
|
||||
u8 gate_flags;
|
||||
const char *alias;
|
||||
};
|
||||
|
||||
#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.dev_name = dname, \
|
||||
.name = cname, \
|
||||
.parent_name = pname, \
|
||||
.flags = f, \
|
||||
.offset = o, \
|
||||
.bit_idx = b, \
|
||||
.gate_flags = gf, \
|
||||
.alias = a, \
|
||||
}
|
||||
|
||||
#define GATE(_id, cname, pname, o, b, f, gf) \
|
||||
__GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
|
||||
|
||||
#define GATE_A(_id, cname, pname, o, b, f, gf, a) \
|
||||
__GATE(_id, NULL, cname, pname, o, b, f, gf, a)
|
||||
|
||||
#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \
|
||||
__GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
|
||||
|
||||
#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \
|
||||
__GATE(_id, dname, cname, pname, o, b, f, gf, a)
|
||||
|
||||
#define PNAME(x) static const char *x[] __initdata
|
||||
|
||||
/**
|
||||
* struct samsung_clk_reg_dump: register dump of clock controller registers.
|
||||
* @offset: clock register offset from the controller base address.
|
||||
* @value: the value to be register at offset.
|
||||
*/
|
||||
struct samsung_clk_reg_dump {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
|
||||
unsigned long nr_clks, unsigned long *rdump,
|
||||
unsigned long nr_rdump, unsigned long *soc_rdump,
|
||||
unsigned long nr_soc_rdump);
|
||||
extern void __init samsung_clk_of_register_fixed_ext(
|
||||
struct samsung_fixed_rate_clock *fixed_rate_clk,
|
||||
unsigned int nr_fixed_rate_clk,
|
||||
struct of_device_id *clk_matches);
|
||||
|
||||
extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
|
||||
|
||||
extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_fixed_rate(
|
||||
struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_fixed_factor(
|
||||
struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
|
||||
unsigned int nr_clk);
|
||||
extern void __init samsung_clk_register_gate(
|
||||
struct samsung_gate_clock *clk_list, unsigned int nr_clk);
|
||||
|
||||
extern unsigned long _get_rate(const char *clk_name);
|
||||
|
||||
#endif /* __SAMSUNG_CLK_H */
|
||||
Loading…
Reference in a new issue