diff options
author | Olof Johansson <olof@lixom.net> | 2014-05-29 18:21:13 (GMT) |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2014-05-29 18:21:13 (GMT) |
commit | 182434f748885e169554fba410aebfef6bdf21ed (patch) | |
tree | ce4b68f3c184229100dacb5825f185e6aa900382 /drivers | |
parent | 535cee422778acaf701b9243cc6df24408856e8f (diff) | |
parent | cd245f59aae5d6ef265f46aa6cea78354d61b629 (diff) | |
download | linux-182434f748885e169554fba410aebfef6bdf21ed.tar.xz |
Merge tag 'exynos-cpuidle' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/drivers
Merge "Samsung exynos-cpuidle updates for v3.16" from Kukjin Kim:
- From Daniel Lezcano:
This patchset relies on the cpm_pm notifier to initiate the
powerdown sequence operations from pm.c instead cpuidle.c.
Thus the cpuidle driver is no longer dependent from arch
specific code as everything is called from the pm.c file.
* tag 'exynos-cpuidle' of http://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: (94 commits)
ARM: EXYNOS: Fix kernel panic when unplugging CPU1 on exynos
ARM: EXYNOS: Move the driver to drivers/cpuidle directory
ARM: EXYNOS: Cleanup all unneeded headers from cpuidle.c
ARM: EXYNOS: Pass the AFTR callback to the platform_data
ARM: EXYNOS: Move S5P_CHECK_SLEEP into pm.c
ARM: EXYNOS: Move the power sequence call in the cpu_pm notifier
ARM: EXYNOS: Move the AFTR state function into pm.c
ARM: EXYNOS: Encapsulate the AFTR code into a function
ARM: EXYNOS: Disable cpuidle for exynos5440
ARM: EXYNOS: Encapsulate boot vector code into a function for cpuidle
ARM: EXYNOS: Pass wakeup mask parameter to function for cpuidle
ARM: EXYNOS: Remove ifdef for scu_enable in pm
ARM: EXYNOS: Move scu_enable in the cpu_pm notifier
ARM: EXYNOS: Use the cpu_pm notifier for pm
ARM: EXYNOS: Fix S5P_WAKEUP_STAT call for cpuidle
ARM: EXYNOS: Move some code inside the idle_finisher for cpuidle
ARM: EXYNOS: Encapsulate register access inside a function for pm
ARM: EXYNOS: Change function name prefix for cpuidle
ARM: EXYNOS: Use cpuidle_register
ARM: EXYNOS: Prevent forward declaration for cpuidle
...
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers')
24 files changed, 6544 insertions, 495 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6f56d3a..ba24366 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -115,3 +115,5 @@ endmenu source "drivers/clk/bcm/Kconfig" source "drivers/clk/mvebu/Kconfig" + +source "drivers/clk/samsung/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f8a287..17d7f13 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ -obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ +obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig new file mode 100644 index 0000000..84196ec --- /dev/null +++ b/drivers/clk/samsung/Kconfig @@ -0,0 +1,26 @@ +config COMMON_CLK_SAMSUNG + bool + select COMMON_CLK + +config S3C2410_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + help + Build the s3c2410 clock driver based on the common clock framework. + +config S3C2410_COMMON_DCLK + bool + select COMMON_CLK_SAMSUNG + select REGMAP_MMIO + help + Temporary symbol to build the dclk driver based on the common clock + framework. + +config S3C2412_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + +config S3C2443_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 8eb4799..25646c6 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -3,9 +3,15 @@ # obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o +obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o +obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o +obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o +obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o +obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o +obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c new file mode 100644 index 0000000..7a17bd4 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., 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 Exynos3250 SoC. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clock/exynos3250.h> + +#include "clk.h" +#include "clk-pll.h" + +#define SRC_LEFTBUS 0x4200 +#define DIV_LEFTBUS 0x4500 +#define GATE_IP_LEFTBUS 0x4800 +#define SRC_RIGHTBUS 0x8200 +#define DIV_RIGHTBUS 0x8500 +#define GATE_IP_RIGHTBUS 0x8800 +#define GATE_IP_PERIR 0x8960 +#define MPLL_LOCK 0xc010 +#define MPLL_CON0 0xc110 +#define VPLL_LOCK 0xc020 +#define VPLL_CON0 0xc120 +#define UPLL_LOCK 0xc030 +#define UPLL_CON0 0xc130 +#define SRC_TOP0 0xc210 +#define SRC_TOP1 0xc214 +#define SRC_CAM 0xc220 +#define SRC_MFC 0xc228 +#define SRC_G3D 0xc22c +#define SRC_LCD 0xc234 +#define SRC_ISP 0xc238 +#define SRC_FSYS 0xc240 +#define SRC_PERIL0 0xc250 +#define SRC_PERIL1 0xc254 +#define SRC_MASK_TOP 0xc310 +#define SRC_MASK_CAM 0xc320 +#define SRC_MASK_LCD 0xc334 +#define SRC_MASK_ISP 0xc338 +#define SRC_MASK_FSYS 0xc340 +#define SRC_MASK_PERIL0 0xc350 +#define SRC_MASK_PERIL1 0xc354 +#define DIV_TOP 0xc510 +#define DIV_CAM 0xc520 +#define DIV_MFC 0xc528 +#define DIV_G3D 0xc52c +#define DIV_LCD 0xc534 +#define DIV_ISP 0xc538 +#define DIV_FSYS0 0xc540 +#define DIV_FSYS1 0xc544 +#define DIV_FSYS2 0xc548 +#define DIV_PERIL0 0xc550 +#define DIV_PERIL1 0xc554 +#define DIV_PERIL3 0xc55c +#define DIV_PERIL4 0xc560 +#define DIV_PERIL5 0xc564 +#define DIV_CAM1 0xc568 +#define CLKDIV2_RATIO 0xc580 +#define GATE_SCLK_CAM 0xc820 +#define GATE_SCLK_MFC 0xc828 +#define GATE_SCLK_G3D 0xc82c +#define GATE_SCLK_LCD 0xc834 +#define GATE_SCLK_ISP_TOP 0xc838 +#define GATE_SCLK_FSYS 0xc840 +#define GATE_SCLK_PERIL 0xc850 +#define GATE_IP_CAM 0xc920 +#define GATE_IP_MFC 0xc928 +#define GATE_IP_G3D 0xc92c +#define GATE_IP_LCD 0xc934 +#define GATE_IP_ISP 0xc938 +#define GATE_IP_FSYS 0xc940 +#define GATE_IP_PERIL 0xc950 +#define GATE_BLOCK 0xc970 +#define APLL_LOCK 0x14000 +#define APLL_CON0 0x14100 +#define SRC_CPU 0x14200 +#define DIV_CPU0 0x14500 +#define DIV_CPU1 0x14504 + +/* list of PLLs to be registered */ +enum exynos3250_plls { + apll, mpll, vpll, upll, + nr_plls +}; + +static void __iomem *reg_base; + +/* + * Support for CMU save/restore across system suspends + */ +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *exynos3250_clk_regs; + +static unsigned long exynos3250_cmu_clk_regs[] __initdata = { + SRC_LEFTBUS, + DIV_LEFTBUS, + GATE_IP_LEFTBUS, + SRC_RIGHTBUS, + DIV_RIGHTBUS, + GATE_IP_RIGHTBUS, + GATE_IP_PERIR, + MPLL_LOCK, + MPLL_CON0, + VPLL_LOCK, + VPLL_CON0, + UPLL_LOCK, + UPLL_CON0, + SRC_TOP0, + SRC_TOP1, + SRC_CAM, + SRC_MFC, + SRC_G3D, + SRC_LCD, + SRC_ISP, + SRC_FSYS, + SRC_PERIL0, + SRC_PERIL1, + SRC_MASK_TOP, + SRC_MASK_CAM, + SRC_MASK_LCD, + SRC_MASK_ISP, + SRC_MASK_FSYS, + SRC_MASK_PERIL0, + SRC_MASK_PERIL1, + DIV_TOP, + DIV_CAM, + DIV_MFC, + DIV_G3D, + DIV_LCD, + DIV_ISP, + DIV_FSYS0, + DIV_FSYS1, + DIV_FSYS2, + DIV_PERIL0, + DIV_PERIL1, + DIV_PERIL3, + DIV_PERIL4, + DIV_PERIL5, + DIV_CAM1, + CLKDIV2_RATIO, + GATE_SCLK_CAM, + GATE_SCLK_MFC, + GATE_SCLK_G3D, + GATE_SCLK_LCD, + GATE_SCLK_ISP_TOP, + GATE_SCLK_FSYS, + GATE_SCLK_PERIL, + GATE_IP_CAM, + GATE_IP_MFC, + GATE_IP_G3D, + GATE_IP_LCD, + GATE_IP_ISP, + GATE_IP_FSYS, + GATE_IP_PERIL, + GATE_BLOCK, + APLL_LOCK, + SRC_CPU, + DIV_CPU0, + DIV_CPU1, +}; + +static int exynos3250_clk_suspend(void) +{ + samsung_clk_save(reg_base, exynos3250_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); + return 0; +} + +static void exynos3250_clk_resume(void) +{ + samsung_clk_restore(reg_base, exynos3250_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); +} + +static struct syscore_ops exynos3250_clk_syscore_ops = { + .suspend = exynos3250_clk_suspend, + .resume = exynos3250_clk_resume, +}; + +static void exynos3250_clk_sleep_init(void) +{ + exynos3250_clk_regs = + samsung_clk_alloc_reg_dump(exynos3250_cmu_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); + if (!exynos3250_clk_regs) { + pr_warn("%s: Failed to allocate sleep save data\n", __func__); + goto err; + } + + register_syscore_ops(&exynos3250_clk_syscore_ops); + return; +err: + kfree(exynos3250_clk_regs); +} +#else +static inline void exynos3250_clk_sleep_init(void) { } +#endif + +/* list of all parent clock list */ +PNAME(mout_vpllsrc_p) = { "fin_pll", }; + +PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; +PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; +PNAME(mout_vpll_p) = { "fin_pll", "fout_vpll", }; +PNAME(mout_upll_p) = { "fin_pll", "fout_upll", }; + +PNAME(mout_mpll_user_p) = { "fin_pll", "div_mpll_pre", }; +PNAME(mout_epll_user_p) = { "fin_pll", "mout_epll", }; +PNAME(mout_core_p) = { "mout_apll", "mout_mpll_user_c", }; +PNAME(mout_hpm_p) = { "mout_apll", "mout_mpll_user_c", }; + +PNAME(mout_ebi_p) = { "div_aclk_200", "div_aclk_160", }; +PNAME(mout_ebi_1_p) = { "mout_ebi", "mout_vpll", }; + +PNAME(mout_gdl_p) = { "mout_mpll_user_l", }; +PNAME(mout_gdr_p) = { "mout_mpll_user_r", }; + +PNAME(mout_aclk_400_mcuisp_sub_p) + = { "fin_pll", "div_aclk_400_mcuisp", }; +PNAME(mout_aclk_266_0_p) = { "div_mpll_pre", "mout_vpll", }; +PNAME(mout_aclk_266_1_p) = { "mout_epll_user", }; +PNAME(mout_aclk_266_p) = { "mout_aclk_266_0", "mout_aclk_266_1", }; +PNAME(mout_aclk_266_sub_p) = { "fin_pll", "div_aclk_266", }; + +PNAME(group_div_mpll_pre_p) = { "div_mpll_pre", }; +PNAME(group_epll_vpll_p) = { "mout_epll_user", "mout_vpll" }; +PNAME(group_sclk_p) = { "xxti", "xusbxti", + "none", "none", + "none", "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", }; +PNAME(group_sclk_audio_p) = { "audiocdclk", "none", + "none", "none", + "xxti", "xusbxti", + "div_mpll_pre", "mout_epll_user", + "mout_vpll", }; +PNAME(group_sclk_cam_blk_p) = { "xxti", "xusbxti", + "none", "none", "none", + "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", + "div_cam_blk_320", }; +PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", + "m_bitclkhsdiv4_2l", "none", + "none", "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", + "none", "none", "none", + "div_lcd_blk_145", }; + +PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" }; +PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" }; + +static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = { + FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0), + FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0), + FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0), + FFACTOR(0, "div_cam_blk_320", "sclk_mpll_1600", 1, 5, 0), + FFACTOR(0, "div_lcd_blk_145", "sclk_mpll_1600", 1, 11, 0), + + /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */ + FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0), +}; + +static struct samsung_mux_clock mux_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* SRC_LEFTBUS */ + MUX(CLK_MOUT_MPLL_USER_L, "mout_mpll_user_l", mout_mpll_user_p, + SRC_LEFTBUS, 4, 1), + MUX(CLK_MOUT_GDL, "mout_gdl", mout_gdl_p, SRC_LEFTBUS, 0, 1), + + /* SRC_RIGHTBUS */ + MUX(CLK_MOUT_MPLL_USER_R, "mout_mpll_user_r", mout_mpll_user_p, + SRC_RIGHTBUS, 4, 1), + MUX(CLK_MOUT_GDR, "mout_gdr", mout_gdr_p, SRC_RIGHTBUS, 0, 1), + + /* SRC_TOP0 */ + MUX(CLK_MOUT_EBI, "mout_ebi", mout_ebi_p, SRC_TOP0, 28, 1), + MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_div_mpll_pre_p,SRC_TOP0, 24, 1), + MUX(CLK_MOUT_ACLK_160, "mout_aclk_160", group_div_mpll_pre_p, SRC_TOP0, 20, 1), + MUX(CLK_MOUT_ACLK_100, "mout_aclk_100", group_div_mpll_pre_p, SRC_TOP0, 16, 1), + MUX(CLK_MOUT_ACLK_266_1, "mout_aclk_266_1", mout_aclk_266_1_p, SRC_TOP0, 14, 1), + MUX(CLK_MOUT_ACLK_266_0, "mout_aclk_266_0", mout_aclk_266_0_p, SRC_TOP0, 13, 1), + MUX(CLK_MOUT_ACLK_266, "mout_aclk_266", mout_aclk_266_p, SRC_TOP0, 12, 1), + MUX(CLK_MOUT_VPLL, "mout_vpll", mout_vpll_p, SRC_TOP0, 8, 1), + MUX(CLK_MOUT_EPLL_USER, "mout_epll_user", mout_epll_user_p, SRC_TOP0, 4, 1), + MUX(CLK_MOUT_EBI_1, "mout_ebi_1", mout_ebi_1_p, SRC_TOP0, 0, 1), + + /* SRC_TOP1 */ + MUX(CLK_MOUT_UPLL, "mout_upll", mout_upll_p, SRC_TOP1, 28, 1), + MUX(CLK_MOUT_ACLK_400_MCUISP_SUB, "mout_aclk_400_mcuisp_sub", mout_aclk_400_mcuisp_sub_p, + SRC_TOP1, 24, 1), + MUX(CLK_MOUT_ACLK_266_SUB, "mout_aclk_266_sub", mout_aclk_266_sub_p, SRC_TOP1, 20, 1), + MUX(CLK_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_TOP1, 12, 1), + MUX(CLK_MOUT_ACLK_400_MCUISP, "mout_aclk_400_mcuisp", group_div_mpll_pre_p, SRC_TOP1, 8, 1), + MUX(CLK_MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1), + + /* SRC_CAM */ + MUX(CLK_MOUT_CAM1, "mout_cam1", group_sclk_p, SRC_CAM, 20, 4), + MUX(CLK_MOUT_CAM_BLK, "mout_cam_blk", group_sclk_cam_blk_p, SRC_CAM, 0, 4), + + /* SRC_MFC */ + MUX(CLK_MOUT_MFC, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), + MUX(CLK_MOUT_MFC_1, "mout_mfc_1", group_epll_vpll_p, SRC_MFC, 4, 1), + MUX(CLK_MOUT_MFC_0, "mout_mfc_0", group_div_mpll_pre_p, SRC_MFC, 0, 1), + + /* SRC_G3D */ + MUX(CLK_MOUT_G3D, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1), + MUX(CLK_MOUT_G3D_1, "mout_g3d_1", group_epll_vpll_p, SRC_G3D, 4, 1), + MUX(CLK_MOUT_G3D_0, "mout_g3d_0", group_div_mpll_pre_p, SRC_G3D, 0, 1), + + /* SRC_LCD */ + MUX(CLK_MOUT_MIPI0, "mout_mipi0", group_sclk_p, SRC_LCD, 12, 4), + MUX(CLK_MOUT_FIMD0, "mout_fimd0", group_sclk_fimd0_p, SRC_LCD, 0, 4), + + /* SRC_ISP */ + MUX(CLK_MOUT_UART_ISP, "mout_uart_isp", group_sclk_p, SRC_ISP, 12, 4), + MUX(CLK_MOUT_SPI1_ISP, "mout_spi1_isp", group_sclk_p, SRC_ISP, 8, 4), + MUX(CLK_MOUT_SPI0_ISP, "mout_spi0_isp", group_sclk_p, SRC_ISP, 4, 4), + + /* SRC_FSYS */ + MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), + MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 3), + MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 3), + + /* SRC_PERIL0 */ + MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), + MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4), + + /* SRC_PERIL1 */ + MUX(CLK_MOUT_SPI1, "mout_spi1", group_sclk_p, SRC_PERIL1, 20, 4), + MUX(CLK_MOUT_SPI0, "mout_spi0", group_sclk_p, SRC_PERIL1, 16, 4), + MUX(CLK_MOUT_AUDIO, "mout_audio", group_sclk_audio_p, SRC_PERIL1, 4, 4), + + /* SRC_CPU */ + MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p, + SRC_CPU, 24, 1), + MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1), + MUX(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1), + MUX(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1), +}; + +static struct samsung_div_clock div_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* DIV_LEFTBUS */ + DIV(CLK_DIV_GPL, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3), + DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 4), + + /* DIV_RIGHTBUS */ + DIV(CLK_DIV_GPR, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3), + DIV(CLK_DIV_GDR, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 4), + + /* DIV_TOP */ + DIV(CLK_DIV_MPLL_PRE, "div_mpll_pre", "sclk_mpll_mif", DIV_TOP, 28, 2), + DIV(CLK_DIV_ACLK_400_MCUISP, "div_aclk_400_mcuisp", + "mout_aclk_400_mcuisp", DIV_TOP, 24, 3), + DIV(CLK_DIV_EBI, "div_ebi", "mout_ebi_1", DIV_TOP, 16, 3), + DIV(CLK_DIV_ACLK_200, "div_aclk_200", "mout_aclk_200", DIV_TOP, 12, 3), + DIV(CLK_DIV_ACLK_160, "div_aclk_160", "mout_aclk_160", DIV_TOP, 8, 3), + DIV(CLK_DIV_ACLK_100, "div_aclk_100", "mout_aclk_100", DIV_TOP, 4, 4), + DIV(CLK_DIV_ACLK_266, "div_aclk_266", "mout_aclk_266", DIV_TOP, 0, 3), + + /* DIV_CAM */ + DIV(CLK_DIV_CAM1, "div_cam1", "mout_cam1", DIV_CAM, 20, 4), + DIV(CLK_DIV_CAM_BLK, "div_cam_blk", "mout_cam_blk", DIV_CAM, 0, 4), + + /* DIV_MFC */ + DIV(CLK_DIV_MFC, "div_mfc", "mout_mfc", DIV_MFC, 0, 4), + + /* DIV_G3D */ + DIV(CLK_DIV_G3D, "div_g3d", "mout_g3d", DIV_G3D, 0, 4), + + /* DIV_LCD */ + DIV_F(CLK_DIV_MIPI0_PRE, "div_mipi0_pre", "div_mipi0", DIV_LCD, 20, 4, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MIPI0, "div_mipi0", "mout_mipi0", DIV_LCD, 16, 4), + DIV(CLK_DIV_FIMD0, "div_fimd0", "mout_fimd0", DIV_LCD, 0, 4), + + /* DIV_ISP */ + DIV(CLK_DIV_UART_ISP, "div_uart_isp", "mout_uart_isp", DIV_ISP, 28, 4), + DIV_F(CLK_DIV_SPI1_ISP_PRE, "div_spi1_isp_pre", "div_spi1_isp", + DIV_ISP, 20, 8, CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4), + DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp", + DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 0, 4), + + /* DIV_FSYS0 */ + DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_TSADC, "div_tsadc", "mout_tsadc", DIV_FSYS0, 0, 4), + + /* DIV_FSYS1 */ + DIV_F(CLK_DIV_MMC1_PRE, "div_mmc1_pre", "div_mmc1", DIV_FSYS1, 24, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MMC1, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), + DIV_F(CLK_DIV_MMC0_PRE, "div_mmc0_pre", "div_mmc0", DIV_FSYS1, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), + + /* DIV_PERIL0 */ + DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4), + DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4), + + /* DIV_PERIL1 */ + DIV_F(CLK_DIV_SPI1_PRE, "div_spi1_pre", "div_spi1", DIV_PERIL1, 24, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI1, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4), + DIV_F(CLK_DIV_SPI0_PRE, "div_spi0_pre", "div_spi0", DIV_PERIL1, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI0, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4), + + /* DIV_PERIL4 */ + DIV(CLK_DIV_PCM, "div_pcm", "div_audio", DIV_PERIL4, 20, 8), + DIV(CLK_DIV_AUDIO, "div_audio", "mout_audio", DIV_PERIL4, 16, 4), + + /* DIV_PERIL5 */ + DIV(CLK_DIV_I2S, "div_i2s", "div_audio", DIV_PERIL5, 8, 6), + + /* DIV_CPU0 */ + DIV(CLK_DIV_CORE2, "div_core2", "div_core", DIV_CPU0, 28, 3), + DIV(CLK_DIV_APLL, "div_apll", "mout_apll", DIV_CPU0, 24, 3), + DIV(CLK_DIV_PCLK_DBG, "div_pclk_dbg", "div_core2", DIV_CPU0, 20, 3), + DIV(CLK_DIV_ATB, "div_atb", "div_core2", DIV_CPU0, 16, 3), + DIV(CLK_DIV_COREM, "div_corem", "div_core2", DIV_CPU0, 4, 3), + DIV(CLK_DIV_CORE, "div_core", "mout_core", DIV_CPU0, 0, 3), + + /* DIV_CPU1 */ + DIV(CLK_DIV_HPM, "div_hpm", "div_copy", DIV_CPU1, 4, 3), + DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), +}; + +static struct samsung_gate_clock gate_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* GATE_IP_LEFTBUS */ + GATE(CLK_ASYNC_G3D, "async_g3d", "div_aclk_100", GATE_IP_LEFTBUS, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_MFCL, "async_mfcl", "div_aclk_100", GATE_IP_LEFTBUS, 4, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMULEFT, "ppmuleft", "div_aclk_100", GATE_IP_LEFTBUS, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GPIO_LEFT, "gpio_left", "div_aclk_100", GATE_IP_LEFTBUS, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_IP_RIGHTBUS */ + GATE(CLK_ASYNC_ISPMX, "async_ispmx", "div_aclk_100", + GATE_IP_RIGHTBUS, 9, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_FSYSD, "async_fsysd", "div_aclk_100", + GATE_IP_RIGHTBUS, 5, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_LCD0X, "async_lcd0x", "div_aclk_100", + GATE_IP_RIGHTBUS, 3, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_CAMX, "async_camx", "div_aclk_100", GATE_IP_RIGHTBUS, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMURIGHT, "ppmuright", "div_aclk_100", GATE_IP_RIGHTBUS, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GPIO_RIGHT, "gpio_right", "div_aclk_100", GATE_IP_RIGHTBUS, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_IP_PERIR */ + GATE(CLK_MONOCNT, "monocnt", "div_aclk_100", GATE_IP_PERIR, 22, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC6, "tzpc6", "div_aclk_100", GATE_IP_PERIR, 21, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PROVISIONKEY1, "provisionkey1", "div_aclk_100", + GATE_IP_PERIR, 20, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PROVISIONKEY0, "provisionkey0", "div_aclk_100", + GATE_IP_PERIR, 19, CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_ISPPART, "cmu_isppart", "div_aclk_100", GATE_IP_PERIR, 18, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk_100", + GATE_IP_PERIR, 17, 0, 0), + GATE(CLK_KEYIF, "keyif", "div_aclk_100", GATE_IP_PERIR, 16, 0, 0), + GATE(CLK_RTC, "rtc", "div_aclk_100", GATE_IP_PERIR, 15, 0, 0), + GATE(CLK_WDT, "wdt", "div_aclk_100", GATE_IP_PERIR, 14, 0, 0), + GATE(CLK_MCT, "mct", "div_aclk_100", GATE_IP_PERIR, 13, 0, 0), + GATE(CLK_SECKEY, "seckey", "div_aclk_100", GATE_IP_PERIR, 12, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC5, "tzpc5", "div_aclk_100", GATE_IP_PERIR, 10, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC4, "tzpc4", "div_aclk_100", GATE_IP_PERIR, 9, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC3, "tzpc3", "div_aclk_100", GATE_IP_PERIR, 8, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC2, "tzpc2", "div_aclk_100", GATE_IP_PERIR, 7, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC1, "tzpc1", "div_aclk_100", GATE_IP_PERIR, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC0, "tzpc0", "div_aclk_100", GATE_IP_PERIR, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_COREPART, "cmu_corepart", "div_aclk_100", GATE_IP_PERIR, 4, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_TOPPART, "cmu_toppart", "div_aclk_100", GATE_IP_PERIR, 3, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PMU_APBIF, "pmu_apbif", "div_aclk_100", GATE_IP_PERIR, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SYSREG, "sysreg", "div_aclk_100", GATE_IP_PERIR, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CHIP_ID, "chip_id", "div_aclk_100", GATE_IP_PERIR, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_SCLK_CAM */ + GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_cam_blk", + GATE_SCLK_CAM, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_M2MSCALER, "sclk_m2mscaler", "div_cam_blk", + GATE_SCLK_CAM, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_GSCALER1, "sclk_gscaler1", "div_cam_blk", + GATE_SCLK_CAM, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_GSCALER0, "sclk_gscaler0", "div_cam_blk", + GATE_SCLK_CAM, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_MFC */ + GATE(CLK_SCLK_MFC, "sclk_mfc", "div_mfc", + GATE_SCLK_MFC, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_G3D */ + GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", + GATE_SCLK_G3D, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_LCD */ + GATE(CLK_SCLK_MIPIDPHY2L, "sclk_mipidphy2l", "div_mipi0", + GATE_SCLK_LCD, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MIPI0, "sclk_mipi0", "div_mipi0_pre", + GATE_SCLK_LCD, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_FIMD0, "sclk_fimd0", "div_fimd0", + GATE_SCLK_LCD, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_ISP_TOP */ + GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1", + GATE_SCLK_ISP_TOP, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "div_uart_isp", + GATE_SCLK_ISP_TOP, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "div_spi1_isp", + GATE_SCLK_ISP_TOP, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "div_spi0_isp", + GATE_SCLK_ISP_TOP, 1, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_FSYS */ + GATE(CLK_SCLK_UPLL, "sclk_upll", "mout_upll", GATE_SCLK_FSYS, 10, 0, 0), + GATE(CLK_SCLK_TSADC, "sclk_tsadc", "div_tsadc_pre", + GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi", + GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre", + GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre", + GATE_SCLK_FSYS, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_PERIL */ + GATE(CLK_SCLK_I2S, "sclk_i2s", "div_i2s", + GATE_SCLK_PERIL, 18, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_PCM, "sclk_pcm", "div_pcm", + GATE_SCLK_PERIL, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi1_pre", + GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre", + GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1", + GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", + GATE_SCLK_PERIL, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_IP_CAM */ + GATE(CLK_QEJPEG, "qejpeg", "div_cam_blk_320", GATE_IP_CAM, 19, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PIXELASYNCM1, "pixelasyncm1", "div_cam_blk_320", + GATE_IP_CAM, 18, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PIXELASYNCM0, "pixelasyncm0", "div_cam_blk_320", + GATE_IP_CAM, 17, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUCAMIF, "ppmucamif", "div_cam_blk_320", + GATE_IP_CAM, 16, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEM2MSCALER, "qem2mscaler", "div_cam_blk_320", + GATE_IP_CAM, 14, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEGSCALER1, "qegscaler1", "div_cam_blk_320", + GATE_IP_CAM, 13, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEGSCALER0, "qegscaler0", "div_cam_blk_320", + GATE_IP_CAM, 12, CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUJPEG, "smmujpeg", "div_cam_blk_320", + GATE_IP_CAM, 11, 0, 0), + GATE(CLK_SMMUM2M2SCALER, "smmum2m2scaler", "div_cam_blk_320", + GATE_IP_CAM, 9, 0, 0), + GATE(CLK_SMMUGSCALER1, "smmugscaler1", "div_cam_blk_320", + GATE_IP_CAM, 8, 0, 0), + GATE(CLK_SMMUGSCALER0, "smmugscaler0", "div_cam_blk_320", + GATE_IP_CAM, 7, 0, 0), + GATE(CLK_JPEG, "jpeg", "div_cam_blk_320", GATE_IP_CAM, 6, 0, 0), + GATE(CLK_M2MSCALER, "m2mscaler", "div_cam_blk_320", + GATE_IP_CAM, 2, 0, 0), + GATE(CLK_GSCALER1, "gscaler1", "div_cam_blk_320", GATE_IP_CAM, 1, 0, 0), + GATE(CLK_GSCALER0, "gscaler0", "div_cam_blk_320", GATE_IP_CAM, 0, 0, 0), + + /* GATE_IP_MFC */ + GATE(CLK_QEMFC, "qemfc", "div_aclk_200", GATE_IP_MFC, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUMFC_L, "ppmumfc_l", "div_aclk_200", GATE_IP_MFC, 3, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUMFC_L, "smmumfc_l", "div_aclk_200", GATE_IP_MFC, 1, 0, 0), + GATE(CLK_MFC, "mfc", "div_aclk_200", GATE_IP_MFC, 0, 0, 0), + + /* GATE_IP_G3D */ + GATE(CLK_SMMUG3D, "smmug3d", "div_aclk_200", GATE_IP_G3D, 3, 0, 0), + GATE(CLK_QEG3D, "qeg3d", "div_aclk_200", GATE_IP_G3D, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUG3D, "ppmug3d", "div_aclk_200", GATE_IP_G3D, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_G3D, "g3d", "div_aclk_200", GATE_IP_G3D, 0, 0, 0), + + /* GATE_IP_LCD */ + GATE(CLK_QE_CH1_LCD, "qe_ch1_lcd", "div_aclk_160", GATE_IP_LCD, 7, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_QE_CH0_LCD, "qe_ch0_lcd", "div_aclk_160", GATE_IP_LCD, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMULCD0, "ppmulcd0", "div_aclk_160", GATE_IP_LCD, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUFIMD0, "smmufimd0", "div_aclk_160", GATE_IP_LCD, 4, 0, 0), + GATE(CLK_DSIM0, "dsim0", "div_aclk_160", GATE_IP_LCD, 3, 0, 0), + GATE(CLK_SMIES, "smies", "div_aclk_160", GATE_IP_LCD, 2, 0, 0), + GATE(CLK_FIMD0, "fimd0", "div_aclk_160", GATE_IP_LCD, 0, 0, 0), + + /* GATE_IP_ISP */ + GATE(CLK_CAM1, "cam1", "mout_aclk_266_sub", GATE_IP_ISP, 5, 0, 0), + GATE(CLK_UART_ISP_TOP, "uart_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 3, 0, 0), + GATE(CLK_SPI1_ISP_TOP, "spi1_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 2, 0, 0), + GATE(CLK_SPI0_ISP_TOP, "spi0_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 1, 0, 0), + + /* GATE_IP_FSYS */ + GATE(CLK_TSADC, "tsadc", "div_aclk_200", GATE_IP_FSYS, 20, 0, 0), + GATE(CLK_PPMUFILE, "ppmufile", "div_aclk_200", GATE_IP_FSYS, 17, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_USBOTG, "usbotg", "div_aclk_200", GATE_IP_FSYS, 13, 0, 0), + GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0), + GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0), + GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0), + GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0), + GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0), + GATE(CLK_PDMA0, "pdma0", "div_aclk_200", GATE_IP_FSYS, 0, 0, 0), + + /* GATE_IP_PERIL */ + GATE(CLK_PWM, "pwm", "div_aclk_100", GATE_IP_PERIL, 24, 0, 0), + GATE(CLK_PCM, "pcm", "div_aclk_100", GATE_IP_PERIL, 23, 0, 0), + GATE(CLK_I2S, "i2s", "div_aclk_100", GATE_IP_PERIL, 21, 0, 0), + GATE(CLK_SPI1, "spi1", "div_aclk_100", GATE_IP_PERIL, 17, 0, 0), + GATE(CLK_SPI0, "spi0", "div_aclk_100", GATE_IP_PERIL, 16, 0, 0), + GATE(CLK_I2C7, "i2c7", "div_aclk_100", GATE_IP_PERIL, 13, 0, 0), + GATE(CLK_I2C6, "i2c6", "div_aclk_100", GATE_IP_PERIL, 12, 0, 0), + GATE(CLK_I2C5, "i2c5", "div_aclk_100", GATE_IP_PERIL, 11, 0, 0), + GATE(CLK_I2C4, "i2c4", "div_aclk_100", GATE_IP_PERIL, 10, 0, 0), + GATE(CLK_I2C3, "i2c3", "div_aclk_100", GATE_IP_PERIL, 9, 0, 0), + GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0), + GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0), + GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0), + GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0), + GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0), +}; + +/* APLL & MPLL & BPLL & UPLL */ +static struct samsung_pll_rate_table exynos3250_pll_rates[] = { + PLL_35XX_RATE(1200000000, 400, 4, 1), + PLL_35XX_RATE(1100000000, 275, 3, 1), + PLL_35XX_RATE(1066000000, 533, 6, 1), + PLL_35XX_RATE(1000000000, 250, 3, 1), + PLL_35XX_RATE( 960000000, 320, 4, 1), + PLL_35XX_RATE( 900000000, 300, 4, 1), + PLL_35XX_RATE( 850000000, 425, 6, 1), + PLL_35XX_RATE( 800000000, 200, 3, 1), + PLL_35XX_RATE( 700000000, 175, 3, 1), + PLL_35XX_RATE( 667000000, 667, 12, 1), + PLL_35XX_RATE( 600000000, 400, 4, 2), + PLL_35XX_RATE( 533000000, 533, 6, 2), + PLL_35XX_RATE( 520000000, 260, 3, 2), + PLL_35XX_RATE( 500000000, 250, 3, 2), + PLL_35XX_RATE( 400000000, 200, 3, 2), + PLL_35XX_RATE( 200000000, 200, 3, 3), + PLL_35XX_RATE( 100000000, 200, 3, 4), + { /* sentinel */ } +}; + +/* VPLL */ +static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { + PLL_36XX_RATE(600000000, 100, 2, 1, 0), + PLL_36XX_RATE(533000000, 266, 3, 2, 32768), + PLL_36XX_RATE(519230987, 173, 2, 2, 5046), + PLL_36XX_RATE(500000000, 250, 3, 2, 0), + PLL_36XX_RATE(445500000, 148, 2, 2, 32768), + PLL_36XX_RATE(445055007, 148, 2, 2, 23047), + PLL_36XX_RATE(400000000, 200, 3, 2, 0), + PLL_36XX_RATE(371250000, 123, 2, 2, 49152), + PLL_36XX_RATE(370878997, 185, 3, 2, 28803), + PLL_36XX_RATE(340000000, 170, 3, 2, 0), + PLL_36XX_RATE(335000015, 111, 2, 2, 43691), + PLL_36XX_RATE(333000000, 111, 2, 2, 0), + PLL_36XX_RATE(330000000, 110, 2, 2, 0), + PLL_36XX_RATE(320000015, 106, 2, 2, 43691), + PLL_36XX_RATE(300000000, 100, 2, 2, 0), + PLL_36XX_RATE(275000000, 275, 3, 3, 0), + PLL_36XX_RATE(222750000, 148, 2, 3, 32768), + PLL_36XX_RATE(222528007, 148, 2, 3, 23069), + PLL_36XX_RATE(160000000, 160, 3, 3, 0), + PLL_36XX_RATE(148500000, 99, 2, 3, 0), + PLL_36XX_RATE(148352005, 98, 2, 3, 59070), + PLL_36XX_RATE(108000000, 144, 2, 4, 0), + PLL_36XX_RATE( 74250000, 99, 2, 4, 0), + PLL_36XX_RATE( 74176002, 98, 3, 4, 59070), + PLL_36XX_RATE( 54054000, 216, 3, 5, 14156), + PLL_36XX_RATE( 54000000, 144, 2, 5, 0), + { /* sentinel */ } +}; + +static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = { + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON0, NULL), + [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll", + VPLL_LOCK, VPLL_CON0, NULL), + [upll] = PLL(pll_35xx, CLK_FOUT_UPLL, "fout_upll", "fin_pll", + UPLL_LOCK, UPLL_CON0, NULL), +}; + +static void __init exynos3250_cmu_init(struct device_node *np) +{ + struct samsung_clk_provider *ctx; + + 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); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_register_fixed_factor(ctx, fixed_factor_clks, + ARRAY_SIZE(fixed_factor_clks)); + + exynos3250_plls[apll].rate_table = exynos3250_pll_rates; + exynos3250_plls[mpll].rate_table = exynos3250_pll_rates; + exynos3250_plls[vpll].rate_table = exynos3250_vpll_rates; + exynos3250_plls[upll].rate_table = exynos3250_pll_rates; + + samsung_clk_register_pll(ctx, exynos3250_plls, + ARRAY_SIZE(exynos3250_plls), reg_base); + + samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks)); + samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks)); + samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks)); + + exynos3250_clk_sleep_init(); +} +CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index b4f9672..c4df294 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -428,7 +428,7 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata /* fixed rate clocks generated inside the soc */ static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), - FRATE(0, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), + FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), }; @@ -903,7 +903,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0), GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0), GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0), - GATE(CLK_MDMA2, "mdma2", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0), + GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0), GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 0), GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0), @@ -1043,7 +1043,7 @@ static unsigned long exynos4_get_xom(void) return xom; } -static void __init exynos4_clk_register_finpll(void) +static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx) { struct samsung_fixed_rate_clock fclk; struct clk *clk; @@ -1066,7 +1066,7 @@ static void __init exynos4_clk_register_finpll(void) fclk.parent_name = NULL; fclk.flags = CLK_IS_ROOT; fclk.fixed_rate = finpll_f; - samsung_clk_register_fixed_rate(&fclk, 1); + samsung_clk_register_fixed_rate(ctx, &fclk, 1); } @@ -1176,22 +1176,25 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc soc) { + struct samsung_clk_provider *ctx; exynos4_soc = soc; reg_base = of_iomap(np, 0); if (!reg_base) panic("%s: failed to map registers\n", __func__); - samsung_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); - samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ext_clk_match); - exynos4_clk_register_finpll(); + exynos4_clk_register_finpll(ctx); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_mux(exynos4210_mux_early, + samsung_clk_register_mux(ctx, exynos4210_mux_early, ARRAY_SIZE(exynos4210_mux_early)); if (_get_rate("fin_pll") == 24000000) { @@ -1205,7 +1208,7 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4210_plls[vpll].rate_table = exynos4210_vpll_rates; - samsung_clk_register_pll(exynos4210_plls, + samsung_clk_register_pll(ctx, exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { if (_get_rate("fin_pll") == 24000000) { @@ -1217,42 +1220,42 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4x12_vpll_rates; } - samsung_clk_register_pll(exynos4x12_plls, + samsung_clk_register_pll(ctx, exynos4x12_plls, ARRAY_SIZE(exynos4x12_plls), reg_base); } - samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks, ARRAY_SIZE(exynos4_fixed_rate_clks)); - samsung_clk_register_mux(exynos4_mux_clks, + samsung_clk_register_mux(ctx, exynos4_mux_clks, ARRAY_SIZE(exynos4_mux_clks)); - samsung_clk_register_div(exynos4_div_clks, + samsung_clk_register_div(ctx, exynos4_div_clks, ARRAY_SIZE(exynos4_div_clks)); - samsung_clk_register_gate(exynos4_gate_clks, + samsung_clk_register_gate(ctx, exynos4_gate_clks, ARRAY_SIZE(exynos4_gate_clks)); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks, ARRAY_SIZE(exynos4210_fixed_rate_clks)); - samsung_clk_register_mux(exynos4210_mux_clks, + samsung_clk_register_mux(ctx, exynos4210_mux_clks, ARRAY_SIZE(exynos4210_mux_clks)); - samsung_clk_register_div(exynos4210_div_clks, + samsung_clk_register_div(ctx, exynos4210_div_clks, ARRAY_SIZE(exynos4210_div_clks)); - samsung_clk_register_gate(exynos4210_gate_clks, + samsung_clk_register_gate(ctx, exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); - samsung_clk_register_alias(exynos4210_aliases, + samsung_clk_register_alias(ctx, exynos4210_aliases, ARRAY_SIZE(exynos4210_aliases)); } else { - samsung_clk_register_mux(exynos4x12_mux_clks, + samsung_clk_register_mux(ctx, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); - samsung_clk_register_div(exynos4x12_div_clks, + samsung_clk_register_div(ctx, exynos4x12_div_clks, ARRAY_SIZE(exynos4x12_div_clks)); - samsung_clk_register_gate(exynos4x12_gate_clks, + samsung_clk_register_gate(ctx, exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); - samsung_clk_register_alias(exynos4x12_aliases, + samsung_clk_register_alias(ctx, exynos4x12_aliases, ARRAY_SIZE(exynos4x12_aliases)); } - samsung_clk_register_alias(exynos4_aliases, + samsung_clk_register_alias(ctx, exynos4_aliases, ARRAY_SIZE(exynos4_aliases)); exynos4_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index e7ee442..1416c97 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -24,6 +24,8 @@ #define APLL_CON0 0x100 #define SRC_CPU 0x200 #define DIV_CPU0 0x500 +#define PWR_CTRL1 0x1020 +#define PWR_CTRL2 0x1024 #define MPLL_LOCK 0x4000 #define MPLL_CON0 0x4100 #define SRC_CORE1 0x4204 @@ -37,6 +39,7 @@ #define VPLL_CON0 0x10140 #define GPLL_CON0 0x10150 #define SRC_TOP0 0x10210 +#define SRC_TOP1 0x10214 #define SRC_TOP2 0x10218 #define SRC_TOP3 0x1021c #define SRC_GSCL 0x10220 @@ -71,6 +74,7 @@ #define GATE_IP_GSCL 0x10920 #define GATE_IP_DISP1 0x10928 #define GATE_IP_MFC 0x1092c +#define GATE_IP_G3D 0x10930 #define GATE_IP_GEN 0x10934 #define GATE_IP_FSYS 0x10944 #define GATE_IP_PERIC 0x10950 @@ -80,6 +84,23 @@ #define SRC_CDREX 0x20200 #define PLL_DIV2_SEL 0x20a24 +/*Below definitions are used for PWR_CTRL settings*/ +#define PWR_CTRL1_CORE2_DOWN_RATIO (7 << 28) +#define PWR_CTRL1_CORE1_DOWN_RATIO (7 << 16) +#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9) +#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8) +#define PWR_CTRL1_USE_CORE1_WFE (1 << 5) +#define PWR_CTRL1_USE_CORE0_WFE (1 << 4) +#define PWR_CTRL1_USE_CORE1_WFI (1 << 1) +#define PWR_CTRL1_USE_CORE0_WFI (1 << 0) + +#define PWR_CTRL2_DIV2_UP_EN (1 << 25) +#define PWR_CTRL2_DIV1_UP_EN (1 << 24) +#define PWR_CTRL2_DUR_STANDBY2_VAL (1 << 16) +#define PWR_CTRL2_DUR_STANDBY1_VAL (1 << 8) +#define PWR_CTRL2_CORE2_UP_RATIO (1 << 4) +#define PWR_CTRL2_CORE1_UP_RATIO (1 << 0) + /* list of PLLs to be registered */ enum exynos5250_plls { apll, mpll, cpll, epll, vpll, gpll, bpll, @@ -98,8 +119,11 @@ static struct samsung_clk_reg_dump *exynos5250_save; static unsigned long exynos5250_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, + PWR_CTRL1, + PWR_CTRL2, SRC_CORE1, SRC_TOP0, + SRC_TOP1, SRC_TOP2, SRC_TOP3, SRC_GSCL, @@ -133,6 +157,7 @@ static unsigned long exynos5250_clk_regs[] __initdata = { DIV_PERIC5, GATE_IP_GSCL, GATE_IP_MFC, + GATE_IP_G3D, GATE_IP_GEN, GATE_IP_FSYS, GATE_IP_PERIC, @@ -189,10 +214,12 @@ 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_gpll_p) = { "fin_pll", "fout_gpll" }; PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" }; PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" }; PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" }; PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" }; +PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" }; PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" }; PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" }; PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" }; @@ -273,12 +300,16 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1), MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1), MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1), + MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1), + + MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1), MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1), MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1), MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1), MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1), MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1), + MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1), MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1), MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1), @@ -351,6 +382,8 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3), DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3), DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3), + DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0, + 24, 3), DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3), @@ -428,6 +461,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { * CMU_ACP */ GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0), + GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0), GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0), GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0), @@ -533,7 +567,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { 0), GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0, 0), - + GATE(CLK_G3D, "g3d", "div_aclk400_g3d", GATE_IP_G3D, 0, + CLK_SET_RATE_PARENT, 0), GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0), GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0), GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0), @@ -686,6 +721,9 @@ static struct of_device_id ext_clk_match[] __initdata = { /* register exynox5250 clocks */ static void __init exynos5250_clk_init(struct device_node *np) { + struct samsung_clk_provider *ctx; + unsigned int tmp; + if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -694,11 +732,13 @@ static void __init exynos5250_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_mux(exynos5250_pll_pmux_clks, + samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks, ARRAY_SIZE(exynos5250_pll_pmux_clks)); if (_get_rate("fin_pll") == 24 * MHZ) { @@ -709,19 +749,40 @@ static void __init exynos5250_clk_init(struct device_node *np) if (_get_rate("mout_vpllsrc") == 24 * MHZ) exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; - samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), - reg_base); - samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, + samsung_clk_register_pll(ctx, exynos5250_plls, + ARRAY_SIZE(exynos5250_plls), + reg_base); + samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, + samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks, ARRAY_SIZE(exynos5250_fixed_factor_clks)); - samsung_clk_register_mux(exynos5250_mux_clks, + samsung_clk_register_mux(ctx, exynos5250_mux_clks, ARRAY_SIZE(exynos5250_mux_clks)); - samsung_clk_register_div(exynos5250_div_clks, + samsung_clk_register_div(ctx, exynos5250_div_clks, ARRAY_SIZE(exynos5250_div_clks)); - samsung_clk_register_gate(exynos5250_gate_clks, + samsung_clk_register_gate(ctx, exynos5250_gate_clks, ARRAY_SIZE(exynos5250_gate_clks)); + /* + * Enable arm clock down (in idle) and set arm divider + * ratios in WFI/WFE state. + */ + tmp = (PWR_CTRL1_CORE2_DOWN_RATIO | PWR_CTRL1_CORE1_DOWN_RATIO | + PWR_CTRL1_DIV2_DOWN_EN | PWR_CTRL1_DIV1_DOWN_EN | + PWR_CTRL1_USE_CORE1_WFE | PWR_CTRL1_USE_CORE0_WFE | + PWR_CTRL1_USE_CORE1_WFI | PWR_CTRL1_USE_CORE0_WFI); + __raw_writel(tmp, reg_base + PWR_CTRL1); + + /* + * Enable arm clock up (on exiting idle). Set arm divider + * ratios when not in idle along with the standby duration + * ratios. + */ + tmp = (PWR_CTRL2_DIV2_UP_EN | PWR_CTRL2_DIV1_UP_EN | + PWR_CTRL2_DUR_STANDBY2_VAL | PWR_CTRL2_DUR_STANDBY1_VAL | + PWR_CTRL2_CORE2_UP_RATIO | PWR_CTRL2_CORE1_UP_RATIO); + __raw_writel(tmp, reg_base + PWR_CTRL2); + exynos5250_clk_sleep_init(); pr_info("Exynos5250: clock setup completed, armclk=%ld\n", diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c new file mode 100644 index 0000000..64596ba --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -0,0 +1,1980 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Rahul Sharma <rahul.sharma@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 Exynos5260 SoC. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include "clk-exynos5260.h" +#include "clk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/exynos5260-clk.h> + +static LIST_HEAD(clock_reg_cache_list); + +struct exynos5260_clock_reg_cache { + struct list_head node; + void __iomem *reg_base; + struct samsung_clk_reg_dump *rdump; + unsigned int rd_num; +}; + +struct exynos5260_cmu_info { + /* list of pll clocks and respective count */ + struct samsung_pll_clock *pll_clks; + unsigned int nr_pll_clks; + /* list of mux clocks and respective count */ + struct samsung_mux_clock *mux_clks; + unsigned int nr_mux_clks; + /* list of div clocks and respective count */ + struct samsung_div_clock *div_clks; + unsigned int nr_div_clks; + /* list of gate clocks and respective count */ + struct samsung_gate_clock *gate_clks; + unsigned int nr_gate_clks; + /* list of fixed clocks and respective count */ + struct samsung_fixed_rate_clock *fixed_clks; + unsigned int nr_fixed_clks; + /* total number of clocks with IDs assigned*/ + unsigned int nr_clk_ids; + + /* list and number of clocks registers */ + unsigned long *clk_regs; + unsigned int nr_clk_regs; +}; + +/* + * Applicable for all 2550 Type PLLS for Exynos5260, listed below + * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. + */ +static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = { + PLL_35XX_RATE(1700000000, 425, 6, 0), + PLL_35XX_RATE(1600000000, 200, 3, 0), + PLL_35XX_RATE(1500000000, 250, 4, 0), + PLL_35XX_RATE(1400000000, 175, 3, 0), + PLL_35XX_RATE(1300000000, 325, 6, 0), + PLL_35XX_RATE(1200000000, 400, 4, 1), + PLL_35XX_RATE(1100000000, 275, 3, 1), + PLL_35XX_RATE(1000000000, 250, 3, 1), + PLL_35XX_RATE(933000000, 311, 4, 1), + PLL_35XX_RATE(900000000, 300, 4, 1), + PLL_35XX_RATE(800000000, 200, 3, 1), + PLL_35XX_RATE(733000000, 733, 12, 1), + PLL_35XX_RATE(700000000, 175, 3, 1), + PLL_35XX_RATE(667000000, 667, 12, 1), + PLL_35XX_RATE(633000000, 211, 4, 1), + PLL_35XX_RATE(620000000, 310, 3, 2), + PLL_35XX_RATE(600000000, 400, 4, 2), + PLL_35XX_RATE(543000000, 362, 4, 2), + PLL_35XX_RATE(533000000, 533, 6, 2), + PLL_35XX_RATE(500000000, 250, 3, 2), + PLL_35XX_RATE(450000000, 300, 4, 2), + PLL_35XX_RATE(400000000, 200, 3, 2), + PLL_35XX_RATE(350000000, 175, 3, 2), + PLL_35XX_RATE(300000000, 400, 4, 3), + PLL_35XX_RATE(266000000, 266, 3, 3), + PLL_35XX_RATE(200000000, 200, 3, 3), + PLL_35XX_RATE(160000000, 160, 3, 3), +}; + +/* + * Applicable for 2650 Type PLL for AUD_PLL. + */ +static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { + PLL_36XX_RATE(1600000000, 200, 3, 0, 0), + PLL_36XX_RATE(1200000000, 100, 2, 0, 0), + PLL_36XX_RATE(1000000000, 250, 3, 1, 0), + PLL_36XX_RATE(800000000, 200, 3, 1, 0), + PLL_36XX_RATE(600000000, 100, 2, 1, 0), + PLL_36XX_RATE(532000000, 266, 3, 2, 0), + PLL_36XX_RATE(480000000, 160, 2, 2, 0), + PLL_36XX_RATE(432000000, 144, 2, 2, 0), + PLL_36XX_RATE(400000000, 200, 3, 2, 0), + PLL_36XX_RATE(394073130, 459, 7, 2, 49282), + PLL_36XX_RATE(333000000, 111, 2, 2, 0), + PLL_36XX_RATE(300000000, 100, 2, 2, 0), + PLL_36XX_RATE(266000000, 266, 3, 3, 0), + PLL_36XX_RATE(200000000, 200, 3, 3, 0), + PLL_36XX_RATE(166000000, 166, 3, 3, 0), + PLL_36XX_RATE(133000000, 266, 3, 4, 0), + PLL_36XX_RATE(100000000, 200, 3, 4, 0), + PLL_36XX_RATE(66000000, 176, 2, 5, 0), +}; + +#ifdef CONFIG_PM_SLEEP + +static int exynos5260_clk_suspend(void) +{ + struct exynos5260_clock_reg_cache *cache; + + list_for_each_entry(cache, &clock_reg_cache_list, node) + samsung_clk_save(cache->reg_base, cache->rdump, + cache->rd_num); + + return 0; +} + +static void exynos5260_clk_resume(void) +{ + struct exynos5260_clock_reg_cache *cache; + + list_for_each_entry(cache, &clock_reg_cache_list, node) + samsung_clk_restore(cache->reg_base, cache->rdump, + cache->rd_num); +} + +static struct syscore_ops exynos5260_clk_syscore_ops = { + .suspend = exynos5260_clk_suspend, + .resume = exynos5260_clk_resume, +}; + +static void exynos5260_clk_sleep_init(void __iomem *reg_base, + unsigned long *rdump, + unsigned long nr_rdump) +{ + struct exynos5260_clock_reg_cache *reg_cache; + + reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache), + GFP_KERNEL); + if (!reg_cache) + panic("could not allocate register cache.\n"); + + reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); + + if (!reg_cache->rdump) + panic("could not allocate register dump storage.\n"); + + if (list_empty(&clock_reg_cache_list)) + register_syscore_ops(&exynos5260_clk_syscore_ops); + + reg_cache->rd_num = nr_rdump; + reg_cache->reg_base = reg_base; + list_add_tail(®_cache->node, &clock_reg_cache_list); +} + +#else +static void exynos5260_clk_sleep_init(void __iomem *reg_base, + unsigned long *rdump, + unsigned long nr_rdump){} +#endif + +/* + * Common function which registers plls, muxes, dividers and gates + * for each CMU. It also add CMU register list to register cache. + */ + +void __init exynos5260_cmu_register_one(struct device_node *np, + struct exynos5260_cmu_info *cmu) +{ + void __iomem *reg_base; + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); + if (!ctx) + panic("%s: unable to alllocate ctx\n", __func__); + + if (cmu->pll_clks) + samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, + reg_base); + if (cmu->mux_clks) + samsung_clk_register_mux(ctx, cmu->mux_clks, + cmu->nr_mux_clks); + if (cmu->div_clks) + samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); + if (cmu->gate_clks) + samsung_clk_register_gate(ctx, cmu->gate_clks, + cmu->nr_gate_clks); + if (cmu->fixed_clks) + samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, + cmu->nr_fixed_clks); + if (cmu->clk_regs) + exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, + cmu->nr_clk_regs); +} + + +/* CMU_AUD */ + +static unsigned long aud_clk_regs[] __initdata = { + MUX_SEL_AUD, + DIV_AUD0, + DIV_AUD1, + EN_ACLK_AUD, + EN_PCLK_AUD, + EN_SCLK_AUD, + EN_IP_AUD, +}; + +PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"}; +PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"}; +PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"}; + +struct samsung_mux_clock aud_mux_clks[] __initdata = { + MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p, + MUX_SEL_AUD, 0, 1), + MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p, + MUX_SEL_AUD, 4, 1), + MUX(AUD_MOUT_SCLK_AUD_PCM, "mout_sclk_aud_pcm", mout_sclk_aud_pcm_p, + MUX_SEL_AUD, 8, 1), +}; + +struct samsung_div_clock aud_div_clks[] __initdata = { + DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user", + DIV_AUD0, 0, 4), + + DIV(AUD_DOUT_SCLK_AUD_I2S, "dout_sclk_aud_i2s", "mout_sclk_aud_i2s", + DIV_AUD1, 0, 4), + DIV(AUD_DOUT_SCLK_AUD_PCM, "dout_sclk_aud_pcm", "mout_sclk_aud_pcm", + DIV_AUD1, 4, 8), + DIV(AUD_DOUT_SCLK_AUD_UART, "dout_sclk_aud_uart", "mout_aud_pll_user", + DIV_AUD1, 12, 4), +}; + +struct samsung_gate_clock aud_gate_clks[] __initdata = { + GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s", + EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0), + GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm", + EN_SCLK_AUD, 1, CLK_SET_RATE_PARENT, 0), + GATE(AUD_SCLK_AUD_UART, "sclk_aud_uart", "dout_sclk_aud_uart", + EN_SCLK_AUD, 2, CLK_SET_RATE_PARENT, 0), + + GATE(AUD_CLK_SRAMC, "clk_sramc", "dout_aclk_aud_131", EN_IP_AUD, + 0, 0, 0), + GATE(AUD_CLK_DMAC, "clk_dmac", "dout_aclk_aud_131", + EN_IP_AUD, 1, 0, 0), + GATE(AUD_CLK_I2S, "clk_i2s", "dout_aclk_aud_131", EN_IP_AUD, 2, 0, 0), + GATE(AUD_CLK_PCM, "clk_pcm", "dout_aclk_aud_131", EN_IP_AUD, 3, 0, 0), + GATE(AUD_CLK_AUD_UART, "clk_aud_uart", "dout_aclk_aud_131", + EN_IP_AUD, 4, 0, 0), +}; + +static void __init exynos5260_clk_aud_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", + exynos5260_clk_aud_init); + + +/* CMU_DISP */ + +static unsigned long disp_clk_regs[] __initdata = { + MUX_SEL_DISP0, + MUX_SEL_DISP1, + MUX_SEL_DISP2, + MUX_SEL_DISP3, + MUX_SEL_DISP4, + DIV_DISP, + EN_ACLK_DISP, + EN_PCLK_DISP, + EN_SCLK_DISP0, + EN_SCLK_DISP1, + EN_IP_DISP, + EN_IP_DISP_BUS, +}; + +PNAME(mout_phyclk_dptx_phy_ch3_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch3_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch2_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch2_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch1_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch1_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch0_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch0_txd_clk"}; +PNAME(mout_aclk_disp_222_user_p) = {"fin_pll", "dout_aclk_disp_222"}; +PNAME(mout_sclk_disp_pixel_user_p) = {"fin_pll", "dout_sclk_disp_pixel"}; +PNAME(mout_aclk_disp_333_user_p) = {"fin_pll", "dout_aclk_disp_333"}; +PNAME(mout_phyclk_hdmi_phy_tmds_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_tmds_clko"}; +PNAME(mout_phyclk_hdmi_phy_ref_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_ref_clko"}; +PNAME(mout_phyclk_hdmi_phy_pixel_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_pixel_clko"}; +PNAME(mout_phyclk_hdmi_link_o_tmds_clkhi_user_p) = {"fin_pll", + "phyclk_hdmi_link_o_tmds_clkhi"}; +PNAME(mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p) = {"fin_pll", + "phyclk_mipi_dphy_4l_m_txbyte_clkhs"}; +PNAME(mout_phyclk_dptx_phy_o_ref_clk_24m_user_p) = {"fin_pll", + "phyclk_dptx_phy_o_ref_clk_24m"}; +PNAME(mout_phyclk_dptx_phy_clk_div2_user_p) = {"fin_pll", + "phyclk_dptx_phy_clk_div2"}; +PNAME(mout_sclk_hdmi_pixel_p) = {"mout_sclk_disp_pixel_user", + "mout_aclk_disp_222_user"}; +PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll", + "phyclk_mipi_dphy_4l_m_rxclkesc0"}; +PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk", + "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; + +struct samsung_mux_clock disp_mux_clks[] __initdata = { + MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user", + mout_aclk_disp_333_user_p, + MUX_SEL_DISP0, 0, 1), + MUX(DISP_MOUT_SCLK_DISP_PIXEL_USER, "mout_sclk_disp_pixel_user", + mout_sclk_disp_pixel_user_p, + MUX_SEL_DISP0, 4, 1), + MUX(DISP_MOUT_ACLK_DISP_222_USER, "mout_aclk_disp_222_user", + mout_aclk_disp_222_user_p, + MUX_SEL_DISP0, 8, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH0_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch0_txd_clk_user", + mout_phyclk_dptx_phy_ch0_txd_clk_user_p, + MUX_SEL_DISP0, 16, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH1_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch1_txd_clk_user", + mout_phyclk_dptx_phy_ch1_txd_clk_user_p, + MUX_SEL_DISP0, 20, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH2_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch2_txd_clk_user", + mout_phyclk_dptx_phy_ch2_txd_clk_user_p, + MUX_SEL_DISP0, 24, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH3_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch3_txd_clk_user", + mout_phyclk_dptx_phy_ch3_txd_clk_user_p, + MUX_SEL_DISP0, 28, 1), + + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CLK_DIV2_USER, + "mout_phyclk_dptx_phy_clk_div2_user", + mout_phyclk_dptx_phy_clk_div2_user_p, + MUX_SEL_DISP1, 0, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_O_REF_CLK_24M_USER, + "mout_phyclk_dptx_phy_o_ref_clk_24m_user", + mout_phyclk_dptx_phy_o_ref_clk_24m_user_p, + MUX_SEL_DISP1, 4, 1), + MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4L_M_TXBYTE_CLKHS, + "mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs", + mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p, + MUX_SEL_DISP1, 8, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_LINK_O_TMDS_CLKHI_USER, + "mout_phyclk_hdmi_link_o_tmds_clkhi_user", + mout_phyclk_hdmi_link_o_tmds_clkhi_user_p, + MUX_SEL_DISP1, 16, 1), + MUX(DISP_MOUT_HDMI_PHY_PIXEL, + "mout_phyclk_hdmi_phy_pixel_clko_user", + mout_phyclk_hdmi_phy_pixel_clko_user_p, + MUX_SEL_DISP1, 20, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_PHY_REF_CLKO_USER, + "mout_phyclk_hdmi_phy_ref_clko_user", + mout_phyclk_hdmi_phy_ref_clko_user_p, + MUX_SEL_DISP1, 24, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_PHY_TMDS_CLKO_USER, + "mout_phyclk_hdmi_phy_tmds_clko_user", + mout_phyclk_hdmi_phy_tmds_clko_user_p, + MUX_SEL_DISP1, 28, 1), + + MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4LMRXCLK_ESC0_USER, + "mout_phyclk_mipi_dphy_4lmrxclk_esc0_user", + mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p, + MUX_SEL_DISP2, 0, 1), + MUX(DISP_MOUT_SCLK_HDMI_PIXEL, "mout_sclk_hdmi_pixel", + mout_sclk_hdmi_pixel_p, + MUX_SEL_DISP2, 4, 1), + + MUX(DISP_MOUT_SCLK_HDMI_SPDIF, "mout_sclk_hdmi_spdif", + mout_sclk_hdmi_spdif_p, + MUX_SEL_DISP4, 4, 2), +}; + +struct samsung_div_clock disp_div_clks[] __initdata = { + DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111", + "mout_aclk_disp_222_user", + DIV_DISP, 8, 4), + DIV(DISP_DOUT_SCLK_FIMD1_EXTCLKPLL, "dout_sclk_fimd1_extclkpll", + "mout_sclk_disp_pixel_user", + DIV_DISP, 12, 4), + DIV(DISP_DOUT_SCLK_HDMI_PHY_PIXEL_CLKI, + "dout_sclk_hdmi_phy_pixel_clki", + "mout_sclk_hdmi_pixel", + DIV_DISP, 16, 4), +}; + +struct samsung_gate_clock disp_gate_clks[] __initdata = { + GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel", + "mout_phyclk_hdmi_phy_pixel_clko_user", + EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0), + GATE(DISP_SCLK_PIXEL, "sclk_hdmi_phy_pixel_clki", + "dout_sclk_hdmi_phy_pixel_clki", + EN_SCLK_DISP0, 29, CLK_SET_RATE_PARENT, 0), + + GATE(DISP_CLK_DP, "clk_dptx_link", "mout_aclk_disp_222_user", + EN_IP_DISP, 4, 0, 0), + GATE(DISP_CLK_DPPHY, "clk_dptx_phy", "mout_aclk_disp_222_user", + EN_IP_DISP, 5, 0, 0), + GATE(DISP_CLK_DSIM1, "clk_dsim1", "mout_aclk_disp_222_user", + EN_IP_DISP, 6, 0, 0), + GATE(DISP_CLK_FIMD1, "clk_fimd1", "mout_aclk_disp_222_user", + EN_IP_DISP, 7, 0, 0), + GATE(DISP_CLK_HDMI, "clk_hdmi", "mout_aclk_disp_222_user", + EN_IP_DISP, 8, 0, 0), + GATE(DISP_CLK_HDMIPHY, "clk_hdmiphy", "mout_aclk_disp_222_user", + EN_IP_DISP, 9, 0, 0), + GATE(DISP_CLK_MIPIPHY, "clk_mipi_dphy", "mout_aclk_disp_222_user", + EN_IP_DISP, 10, 0, 0), + GATE(DISP_CLK_MIXER, "clk_mixer", "mout_aclk_disp_222_user", + EN_IP_DISP, 11, 0, 0), + GATE(DISP_CLK_PIXEL_DISP, "clk_pixel_disp", "mout_aclk_disp_222_user", + EN_IP_DISP, 12, CLK_IGNORE_UNUSED, 0), + GATE(DISP_CLK_PIXEL_MIXER, "clk_pixel_mixer", "mout_aclk_disp_222_user", + EN_IP_DISP, 13, CLK_IGNORE_UNUSED, 0), + GATE(DISP_CLK_SMMU_FIMD1M0, "clk_smmu3_fimd1m0", + "mout_aclk_disp_222_user", + EN_IP_DISP, 22, 0, 0), + GATE(DISP_CLK_SMMU_FIMD1M1, "clk_smmu3_fimd1m1", + "mout_aclk_disp_222_user", + EN_IP_DISP, 23, 0, 0), + GATE(DISP_CLK_SMMU_TV, "clk_smmu3_tv", "mout_aclk_disp_222_user", + EN_IP_DISP, 25, 0, 0), +}; + +static void __init exynos5260_clk_disp_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", + exynos5260_clk_disp_init); + + +/* CMU_EGL */ + +static unsigned long egl_clk_regs[] __initdata = { + EGL_PLL_LOCK, + EGL_PLL_CON0, + EGL_PLL_CON1, + EGL_PLL_FREQ_DET, + MUX_SEL_EGL, + MUX_ENABLE_EGL, + DIV_EGL, + DIV_EGL_PLL_FDET, + EN_ACLK_EGL, + EN_PCLK_EGL, + EN_SCLK_EGL, +}; + +PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"}; +PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"}; + +struct samsung_mux_clock egl_mux_clks[] __initdata = { + MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p, + MUX_SEL_EGL, 4, 1), + MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1), +}; + +struct samsung_div_clock egl_div_clks[] __initdata = { + DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3), + DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3), + DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3), + DIV(EGL_DOUT_PCLK_EGL, "dout_pclk_egl", "dout_egl_atclk", + DIV_EGL, 12, 3), + DIV(EGL_DOUT_EGL_ATCLK, "dout_egl_atclk", "dout_egl2", DIV_EGL, 16, 3), + DIV(EGL_DOUT_EGL_PCLK_DBG, "dout_egl_pclk_dbg", "dout_egl_atclk", + DIV_EGL, 20, 3), + DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3), +}; + +static struct samsung_pll_clock egl_pll_clks[] __initdata = { + PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll", + EGL_PLL_LOCK, EGL_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_egl_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", + exynos5260_clk_egl_init); + + +/* CMU_FSYS */ + +static unsigned long fsys_clk_regs[] __initdata = { + MUX_SEL_FSYS0, + MUX_SEL_FSYS1, + EN_ACLK_FSYS, + EN_ACLK_FSYS_SECURE_RTIC, + EN_ACLK_FSYS_SECURE_SMMU_RTIC, + EN_SCLK_FSYS, + EN_IP_FSYS, + EN_IP_FSYS_SECURE_RTIC, + EN_IP_FSYS_SECURE_SMMU_RTIC, +}; + +PNAME(mout_phyclk_usbhost20_phyclk_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_phyclock"}; +PNAME(mout_phyclk_usbhost20_freeclk_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_freeclk"}; +PNAME(mout_phyclk_usbhost20_clk48mohci_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_clk48mohci"}; +PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll", + "phyclk_usbdrd30_udrd30_pipe_pclk"}; +PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll", + "phyclk_usbdrd30_udrd30_phyclock"}; + +struct samsung_mux_clock fsys_mux_clks[] __initdata = { + MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER, + "mout_phyclk_usbdrd30_phyclock_user", + mout_phyclk_usbdrd30_phyclock_user_p, + MUX_SEL_FSYS1, 0, 1), + MUX(FSYS_MOUT_PHYCLK_USBDRD30_PIPE_PCLK_USER, + "mout_phyclk_usbdrd30_pipe_pclk_user", + mout_phyclk_usbdrd30_pipe_pclk_user_p, + MUX_SEL_FSYS1, 4, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_CLK48MOHCI_USER, + "mout_phyclk_usbhost20_clk48mohci_user", + mout_phyclk_usbhost20_clk48mohci_user_p, + MUX_SEL_FSYS1, 8, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_FREECLK_USER, + "mout_phyclk_usbhost20_freeclk_user", + mout_phyclk_usbhost20_freeclk_user_p, + MUX_SEL_FSYS1, 12, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_PHYCLK_USER, + "mout_phyclk_usbhost20_phyclk_user", + mout_phyclk_usbhost20_phyclk_user_p, + MUX_SEL_FSYS1, 16, 1), +}; + +struct samsung_gate_clock fsys_gate_clks[] __initdata = { + GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock", + "mout_phyclk_usbdrd30_phyclock_user", + EN_SCLK_FSYS, 1, 0, 0), + GATE(FSYS_PHYCLK_USBDRD30, "phyclk_usbdrd30_udrd30_phyclock_g", + "mout_phyclk_usbdrd30_phyclock_user", + EN_SCLK_FSYS, 7, 0, 0), + + GATE(FSYS_CLK_MMC0, "clk_mmc0", "dout_aclk_fsys_200", + EN_IP_FSYS, 6, 0, 0), + GATE(FSYS_CLK_MMC1, "clk_mmc1", "dout_aclk_fsys_200", + EN_IP_FSYS, 7, 0, 0), + GATE(FSYS_CLK_MMC2, "clk_mmc2", "dout_aclk_fsys_200", + EN_IP_FSYS, 8, 0, 0), + GATE(FSYS_CLK_PDMA, "clk_pdma", "dout_aclk_fsys_200", + EN_IP_FSYS, 9, 0, 0), + GATE(FSYS_CLK_SROMC, "clk_sromc", "dout_aclk_fsys_200", + EN_IP_FSYS, 13, 0, 0), + GATE(FSYS_CLK_USBDRD30, "clk_usbdrd30", "dout_aclk_fsys_200", + EN_IP_FSYS, 14, 0, 0), + GATE(FSYS_CLK_USBHOST20, "clk_usbhost20", "dout_aclk_fsys_200", + EN_IP_FSYS, 15, 0, 0), + GATE(FSYS_CLK_USBLINK, "clk_usblink", "dout_aclk_fsys_200", + EN_IP_FSYS, 18, 0, 0), + GATE(FSYS_CLK_TSI, "clk_tsi", "dout_aclk_fsys_200", + EN_IP_FSYS, 20, 0, 0), + + GATE(FSYS_CLK_RTIC, "clk_rtic", "dout_aclk_fsys_200", + EN_IP_FSYS_SECURE_RTIC, 11, 0, 0), + GATE(FSYS_CLK_SMMU_RTIC, "clk_smmu_rtic", "dout_aclk_fsys_200", + EN_IP_FSYS_SECURE_SMMU_RTIC, 12, 0, 0), +}; + +static void __init exynos5260_clk_fsys_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", + exynos5260_clk_fsys_init); + + +/* CMU_G2D */ + +static unsigned long g2d_clk_regs[] __initdata = { + MUX_SEL_G2D, + MUX_STAT_G2D, + DIV_G2D, + EN_ACLK_G2D, + EN_ACLK_G2D_SECURE_SSS, + EN_ACLK_G2D_SECURE_SLIM_SSS, + EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS, + EN_ACLK_G2D_SECURE_SMMU_SSS, + EN_ACLK_G2D_SECURE_SMMU_MDMA, + EN_ACLK_G2D_SECURE_SMMU_G2D, + EN_PCLK_G2D, + EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS, + EN_PCLK_G2D_SECURE_SMMU_SSS, + EN_PCLK_G2D_SECURE_SMMU_MDMA, + EN_PCLK_G2D_SECURE_SMMU_G2D, + EN_IP_G2D, + EN_IP_G2D_SECURE_SSS, + EN_IP_G2D_SECURE_SLIM_SSS, + EN_IP_G2D_SECURE_SMMU_SLIM_SSS, + EN_IP_G2D_SECURE_SMMU_SSS, + EN_IP_G2D_SECURE_SMMU_MDMA, + EN_IP_G2D_SECURE_SMMU_G2D, +}; + +PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"}; + +struct samsung_mux_clock g2d_mux_clks[] __initdata = { + MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user", + mout_aclk_g2d_333_user_p, + MUX_SEL_G2D, 0, 1), +}; + +struct samsung_div_clock g2d_div_clks[] __initdata = { + DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user", + DIV_G2D, 0, 3), +}; + +struct samsung_gate_clock g2d_gate_clks[] __initdata = { + GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user", + EN_IP_G2D, 4, 0, 0), + GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user", + EN_IP_G2D, 5, 0, 0), + GATE(G2D_CLK_MDMA, "clk_mdma", "mout_aclk_g2d_333_user", + EN_IP_G2D, 6, 0, 0), + GATE(G2D_CLK_SMMU3_JPEG, "clk_smmu3_jpeg", "mout_aclk_g2d_333_user", + EN_IP_G2D, 16, 0, 0), + + GATE(G2D_CLK_SSS, "clk_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SSS, 17, 0, 0), + + GATE(G2D_CLK_SLIM_SSS, "clk_slim_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SLIM_SSS, 11, 0, 0), + + GATE(G2D_CLK_SMMU_SLIM_SSS, "clk_smmu_slim_sss", + "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_SLIM_SSS, 13, 0, 0), + + GATE(G2D_CLK_SMMU_SSS, "clk_smmu_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_SSS, 14, 0, 0), + + GATE(G2D_CLK_SMMU_MDMA, "clk_smmu_mdma", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_MDMA, 12, 0, 0), + + GATE(G2D_CLK_SMMU3_G2D, "clk_smmu3_g2d", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_G2D, 15, 0, 0), +}; + +static void __init exynos5260_clk_g2d_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", + exynos5260_clk_g2d_init); + + +/* CMU_G3D */ + +static unsigned long g3d_clk_regs[] __initdata = { + G3D_PLL_LOCK, + G3D_PLL_CON0, + G3D_PLL_CON1, + G3D_PLL_FDET, + MUX_SEL_G3D, + DIV_G3D, + DIV_G3D_PLL_FDET, + EN_ACLK_G3D, + EN_PCLK_G3D, + EN_SCLK_G3D, + EN_IP_G3D, +}; + +PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"}; + +struct samsung_mux_clock g3d_mux_clks[] __initdata = { + MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p, + MUX_SEL_G3D, 0, 1), +}; + +struct samsung_div_clock g3d_div_clks[] __initdata = { + DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3), + DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3), +}; + +struct samsung_gate_clock g3d_gate_clks[] __initdata = { + GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0), + GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d", + EN_IP_G3D, 3, 0, 0), +}; + +static struct samsung_pll_clock g3d_pll_clks[] __initdata = { + PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll", + G3D_PLL_LOCK, G3D_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_g3d_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", + exynos5260_clk_g3d_init); + + +/* CMU_GSCL */ + +static unsigned long gscl_clk_regs[] __initdata = { + MUX_SEL_GSCL, + DIV_GSCL, + EN_ACLK_GSCL, + EN_ACLK_GSCL_FIMC, + EN_ACLK_GSCL_SECURE_SMMU_GSCL0, + EN_ACLK_GSCL_SECURE_SMMU_GSCL1, + EN_ACLK_GSCL_SECURE_SMMU_MSCL0, + EN_ACLK_GSCL_SECURE_SMMU_MSCL1, + EN_PCLK_GSCL, + EN_PCLK_GSCL_FIMC, + EN_PCLK_GSCL_SECURE_SMMU_GSCL0, + EN_PCLK_GSCL_SECURE_SMMU_GSCL1, + EN_PCLK_GSCL_SECURE_SMMU_MSCL0, + EN_PCLK_GSCL_SECURE_SMMU_MSCL1, + EN_SCLK_GSCL, + EN_SCLK_GSCL_FIMC, + EN_IP_GSCL, + EN_IP_GSCL_FIMC, + EN_IP_GSCL_SECURE_SMMU_GSCL0, + EN_IP_GSCL_SECURE_SMMU_GSCL1, + EN_IP_GSCL_SECURE_SMMU_MSCL0, + EN_IP_GSCL_SECURE_SMMU_MSCL1, +}; + +PNAME(mout_aclk_gscl_333_user_p) = {"fin_pll", "dout_aclk_gscl_333"}; +PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; +PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; +PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"}; + +struct samsung_mux_clock gscl_mux_clks[] __initdata = { + MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user", + mout_aclk_gscl_333_user_p, + MUX_SEL_GSCL, 0, 1), + MUX(GSCL_MOUT_ACLK_M2M_400_USER, "mout_aclk_m2m_400_user", + mout_aclk_m2m_400_user_p, + MUX_SEL_GSCL, 4, 1), + MUX(GSCL_MOUT_ACLK_GSCL_FIMC_USER, "mout_aclk_gscl_fimc_user", + mout_aclk_gscl_fimc_user_p, + MUX_SEL_GSCL, 8, 1), + MUX(GSCL_MOUT_ACLK_CSIS, "mout_aclk_csis", mout_aclk_csis_p, + MUX_SEL_GSCL, 24, 1), +}; + +struct samsung_div_clock gscl_div_clks[] __initdata = { + DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100", + "mout_aclk_m2m_400_user", + DIV_GSCL, 0, 3), + DIV(GSCL_DOUT_ACLK_CSIS_200, "dout_aclk_csis_200", + "mout_aclk_m2m_400_user", + DIV_GSCL, 4, 3), +}; + +struct samsung_gate_clock gscl_gate_clks[] __initdata = { + GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200", + EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0), + GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200", + EN_SCLK_GSCL_FIMC, 1, CLK_SET_RATE_PARENT, 0), + + GATE(GSCL_CLK_GSCL0, "clk_gscl0", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 2, 0, 0), + GATE(GSCL_CLK_GSCL1, "clk_gscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 3, 0, 0), + GATE(GSCL_CLK_MSCL0, "clk_mscl0", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 4, 0, 0), + GATE(GSCL_CLK_MSCL1, "clk_mscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 5, 0, 0), + GATE(GSCL_CLK_PIXEL_GSCL0, "clk_pixel_gscl0", + "mout_aclk_gscl_333_user", + EN_IP_GSCL, 8, 0, 0), + GATE(GSCL_CLK_PIXEL_GSCL1, "clk_pixel_gscl1", + "mout_aclk_gscl_333_user", + EN_IP_GSCL, 9, 0, 0), + + GATE(GSCL_CLK_SMMU3_LITE_A, "clk_smmu3_lite_a", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 5, 0, 0), + GATE(GSCL_CLK_SMMU3_LITE_B, "clk_smmu3_lite_b", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 6, 0, 0), + GATE(GSCL_CLK_SMMU3_LITE_D, "clk_smmu3_lite_d", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 7, 0, 0), + GATE(GSCL_CLK_CSIS0, "clk_csis0", "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 8, 0, 0), + GATE(GSCL_CLK_CSIS1, "clk_csis1", "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 9, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_A, "clk_fimc_lite_a", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 10, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_B, "clk_fimc_lite_b", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 11, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_D, "clk_fimc_lite_d", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 12, 0, 0), + + GATE(GSCL_CLK_SMMU3_GSCL0, "clk_smmu3_gscl0", + "mout_aclk_gscl_333_user", + EN_IP_GSCL_SECURE_SMMU_GSCL0, 17, 0, 0), + GATE(GSCL_CLK_SMMU3_GSCL1, "clk_smmu3_gscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL_SECURE_SMMU_GSCL1, 18, 0, 0), + GATE(GSCL_CLK_SMMU3_MSCL0, "clk_smmu3_mscl0", + "mout_aclk_m2m_400_user", + EN_IP_GSCL_SECURE_SMMU_MSCL0, 19, 0, 0), + GATE(GSCL_CLK_SMMU3_MSCL1, "clk_smmu3_mscl1", + "mout_aclk_m2m_400_user", + EN_IP_GSCL_SECURE_SMMU_MSCL1, 20, 0, 0), +}; + +static void __init exynos5260_clk_gscl_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", + exynos5260_clk_gscl_init); + + +/* CMU_ISP */ + +static unsigned long isp_clk_regs[] __initdata = { + MUX_SEL_ISP0, + MUX_SEL_ISP1, + DIV_ISP, + EN_ACLK_ISP0, + EN_ACLK_ISP1, + EN_PCLK_ISP0, + EN_PCLK_ISP1, + EN_SCLK_ISP, + EN_IP_ISP0, + EN_IP_ISP1, +}; + +PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"}; +PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"}; + +struct samsung_mux_clock isp_mux_clks[] __initdata = { + MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p, + MUX_SEL_ISP0, 0, 1), + MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p, + MUX_SEL_ISP0, 4, 1), +}; + +struct samsung_div_clock isp_div_clks[] __initdata = { + DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc", + DIV_ISP, 0, 3), + DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc", + DIV_ISP, 4, 4), + DIV(ISP_DOUT_CA5_ATCLKIN, "dout_ca5_atclkin", "mout_kfc", + DIV_ISP, 12, 3), + DIV(ISP_DOUT_CA5_PCLKDBG, "dout_ca5_pclkdbg", "mout_kfc", + DIV_ISP, 16, 4), + DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2), +}; + +struct samsung_gate_clock isp_gate_clks[] __initdata = { + GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266", + EN_IP_ISP0, 15, 0, 0), + + GATE(ISP_CLK_CA5, "clk_isp_ca5", "mout_aclk_isp1_266", + EN_IP_ISP1, 1, 0, 0), + GATE(ISP_CLK_FIMC_DRC, "clk_isp_fimc_drc", "mout_aclk_isp1_266", + EN_IP_ISP1, 2, 0, 0), + GATE(ISP_CLK_FIMC_FD, "clk_isp_fimc_fd", "mout_aclk_isp1_266", + EN_IP_ISP1, 3, 0, 0), + GATE(ISP_CLK_FIMC, "clk_isp_fimc", "mout_aclk_isp1_266", + EN_IP_ISP1, 4, 0, 0), + GATE(ISP_CLK_FIMC_SCALERC, "clk_isp_fimc_scalerc", + "mout_aclk_isp1_266", + EN_IP_ISP1, 5, 0, 0), + GATE(ISP_CLK_FIMC_SCALERP, "clk_isp_fimc_scalerp", + "mout_aclk_isp1_266", + EN_IP_ISP1, 6, 0, 0), + GATE(ISP_CLK_I2C0, "clk_isp_i2c0", "mout_aclk_isp1_266", + EN_IP_ISP1, 7, 0, 0), + GATE(ISP_CLK_I2C1, "clk_isp_i2c1", "mout_aclk_isp1_266", + EN_IP_ISP1, 8, 0, 0), + GATE(ISP_CLK_MCUCTL, "clk_isp_mcuctl", "mout_aclk_isp1_266", + EN_IP_ISP1, 9, 0, 0), + GATE(ISP_CLK_MPWM, "clk_isp_mpwm", "mout_aclk_isp1_266", + EN_IP_ISP1, 10, 0, 0), + GATE(ISP_CLK_MTCADC, "clk_isp_mtcadc", "mout_aclk_isp1_266", + EN_IP_ISP1, 11, 0, 0), + GATE(ISP_CLK_PWM, "clk_isp_pwm", "mout_aclk_isp1_266", + EN_IP_ISP1, 14, 0, 0), + GATE(ISP_CLK_SMMU_DRC, "clk_smmu_drc", "mout_aclk_isp1_266", + EN_IP_ISP1, 21, 0, 0), + GATE(ISP_CLK_SMMU_FD, "clk_smmu_fd", "mout_aclk_isp1_266", + EN_IP_ISP1, 22, 0, 0), + GATE(ISP_CLK_SMMU_ISP, "clk_smmu_isp", "mout_aclk_isp1_266", + EN_IP_ISP1, 23, 0, 0), + GATE(ISP_CLK_SMMU_ISPCX, "clk_smmu_ispcx", "mout_aclk_isp1_266", + EN_IP_ISP1, 24, 0, 0), + GATE(ISP_CLK_SMMU_SCALERC, "clk_isp_smmu_scalerc", + "mout_aclk_isp1_266", + EN_IP_ISP1, 25, 0, 0), + GATE(ISP_CLK_SMMU_SCALERP, "clk_isp_smmu_scalerp", + "mout_aclk_isp1_266", + EN_IP_ISP1, 26, 0, 0), + GATE(ISP_CLK_SPI0, "clk_isp_spi0", "mout_aclk_isp1_266", + EN_IP_ISP1, 27, 0, 0), + GATE(ISP_CLK_SPI1, "clk_isp_spi1", "mout_aclk_isp1_266", + EN_IP_ISP1, 28, 0, 0), + GATE(ISP_CLK_WDT, "clk_isp_wdt", "mout_aclk_isp1_266", + EN_IP_ISP1, 31, 0, 0), + GATE(ISP_CLK_UART, "clk_isp_uart", "mout_aclk_isp1_266", + EN_IP_ISP1, 30, 0, 0), + + GATE(ISP_SCLK_UART_EXT, "sclk_isp_uart_ext", "fin_pll", + EN_SCLK_ISP, 7, CLK_SET_RATE_PARENT, 0), + GATE(ISP_SCLK_SPI1_EXT, "sclk_isp_spi1_ext", "fin_pll", + EN_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0), + GATE(ISP_SCLK_SPI0_EXT, "sclk_isp_spi0_ext", "fin_pll", + EN_SCLK_ISP, 9, CLK_SET_RATE_PARENT, 0), +}; + +static void __init exynos5260_clk_isp_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", + exynos5260_clk_isp_init); + + +/* CMU_KFC */ + +static unsigned long kfc_clk_regs[] __initdata = { + KFC_PLL_LOCK, + KFC_PLL_CON0, + KFC_PLL_CON1, + KFC_PLL_FDET, + MUX_SEL_KFC0, + MUX_SEL_KFC2, + DIV_KFC, + DIV_KFC_PLL_FDET, + EN_ACLK_KFC, + EN_PCLK_KFC, + EN_SCLK_KFC, + EN_IP_KFC, +}; + +PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"}; +PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"}; + +struct samsung_mux_clock kfc_mux_clks[] __initdata = { + MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p, + MUX_SEL_KFC0, 0, 1), + MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1), +}; + +struct samsung_div_clock kfc_div_clks[] __initdata = { + DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3), + DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3), + DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3), + DIV(KFC_DOUT_KFC_PCLK_DBG, "dout_kfc_pclk_dbg", "dout_kfc2", + DIV_KFC, 12, 3), + DIV(KFC_DOUT_ACLK_KFC, "dout_aclk_kfc", "dout_kfc2", DIV_KFC, 16, 3), + DIV(KFC_DOUT_PCLK_KFC, "dout_pclk_kfc", "dout_kfc2", DIV_KFC, 20, 3), + DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3), +}; + +static struct samsung_pll_clock kfc_pll_clks[] __initdata = { + PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll", + KFC_PLL_LOCK, KFC_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_kfc_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", + exynos5260_clk_kfc_init); + + +/* CMU_MFC */ + +static unsigned long mfc_clk_regs[] __initdata = { + MUX_SEL_MFC, + DIV_MFC, + EN_ACLK_MFC, + EN_ACLK_SECURE_SMMU2_MFC, + EN_PCLK_MFC, + EN_PCLK_SECURE_SMMU2_MFC, + EN_IP_MFC, + EN_IP_MFC_SECURE_SMMU2_MFC, +}; + +PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"}; + +struct samsung_mux_clock mfc_mux_clks[] __initdata = { + MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user", + mout_aclk_mfc_333_user_p, + MUX_SEL_MFC, 0, 1), +}; + +struct samsung_div_clock mfc_div_clks[] __initdata = { + DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user", + DIV_MFC, 0, 3), +}; + +struct samsung_gate_clock mfc_gate_clks[] __initdata = { + GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user", + EN_IP_MFC, 1, 0, 0), + GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user", + EN_IP_MFC_SECURE_SMMU2_MFC, 6, 0, 0), + GATE(MFC_CLK_SMMU2_MFCM1, "clk_smmu2_mfcm1", "mout_aclk_mfc_333_user", + EN_IP_MFC_SECURE_SMMU2_MFC, 7, 0, 0), +}; + +static void __init exynos5260_clk_mfc_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", + exynos5260_clk_mfc_init); + + +/* CMU_MIF */ + +static unsigned long mif_clk_regs[] __initdata = { + MEM_PLL_LOCK, + BUS_PLL_LOCK, + MEDIA_PLL_LOCK, + MEM_PLL_CON0, + MEM_PLL_CON1, + MEM_PLL_FDET, + BUS_PLL_CON0, + BUS_PLL_CON1, + BUS_PLL_FDET, + MEDIA_PLL_CON0, + MEDIA_PLL_CON1, + MEDIA_PLL_FDET, + MUX_SEL_MIF, + DIV_MIF, + DIV_MIF_PLL_FDET, + EN_ACLK_MIF, + EN_ACLK_MIF_SECURE_DREX1_TZ, + EN_ACLK_MIF_SECURE_DREX0_TZ, + EN_ACLK_MIF_SECURE_INTMEM, + EN_PCLK_MIF, + EN_PCLK_MIF_SECURE_MONOCNT, + EN_PCLK_MIF_SECURE_RTC_APBIF, + EN_PCLK_MIF_SECURE_DREX1_TZ, + EN_PCLK_MIF_SECURE_DREX0_TZ, + EN_SCLK_MIF, + EN_IP_MIF, + EN_IP_MIF_SECURE_MONOCNT, + EN_IP_MIF_SECURE_RTC_APBIF, + EN_IP_MIF_SECURE_DREX1_TZ, + EN_IP_MIF_SECURE_DREX0_TZ, + EN_IP_MIF_SECURE_INTEMEM, +}; + +PNAME(mout_mem_pll_p) = {"fin_pll", "fout_mem_pll"}; +PNAME(mout_bus_pll_p) = {"fin_pll", "fout_bus_pll"}; +PNAME(mout_media_pll_p) = {"fin_pll", "fout_media_pll"}; +PNAME(mout_mif_drex_p) = {"dout_mem_pll", "dout_bus_pll"}; +PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"}; +PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"}; +PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"}; + +struct samsung_mux_clock mif_mux_clks[] __initdata = { + MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p, + MUX_SEL_MIF, 0, 1), + MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p, + MUX_SEL_MIF, 4, 1), + MUX(MIF_MOUT_MEDIA_PLL, "mout_media_pll", mout_media_pll_p, + MUX_SEL_MIF, 8, 1), + MUX(MIF_MOUT_MIF_DREX, "mout_mif_drex", mout_mif_drex_p, + MUX_SEL_MIF, 12, 1), + MUX(MIF_MOUT_CLKM_PHY, "mout_clkm_phy", mout_clkm_phy_p, + MUX_SEL_MIF, 16, 1), + MUX(MIF_MOUT_MIF_DREX2X, "mout_mif_drex2x", mout_mif_drex2x_p, + MUX_SEL_MIF, 20, 1), + MUX(MIF_MOUT_CLK2X_PHY, "mout_clk2x_phy", mout_clk2x_phy_p, + MUX_SEL_MIF, 24, 1), +}; + +struct samsung_div_clock mif_div_clks[] __initdata = { + DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll", + DIV_MIF, 0, 3), + DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll", + DIV_MIF, 4, 3), + DIV(MIF_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", + DIV_MIF, 8, 3), + DIV(MIF_DOUT_CLKM_PHY, "dout_clkm_phy", "mout_clkm_phy", + DIV_MIF, 12, 3), + DIV(MIF_DOUT_CLK2X_PHY, "dout_clk2x_phy", "mout_clk2x_phy", + DIV_MIF, 16, 4), + DIV(MIF_DOUT_ACLK_MIF_466, "dout_aclk_mif_466", "dout_clk2x_phy", + DIV_MIF, 20, 3), + DIV(MIF_DOUT_ACLK_BUS_200, "dout_aclk_bus_200", "dout_bus_pll", + DIV_MIF, 24, 3), + DIV(MIF_DOUT_ACLK_BUS_100, "dout_aclk_bus_100", "dout_bus_pll", + DIV_MIF, 28, 4), +}; + +struct samsung_gate_clock mif_gate_clks[] __initdata = { + GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy", + EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0), + GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy", + EN_IP_MIF, 13, CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_MONOCNT, "clk_monocnt", "dout_aclk_bus_100", + EN_IP_MIF_SECURE_MONOCNT, 22, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_MIF_RTC, "clk_mif_rtc", "dout_aclk_bus_100", + EN_IP_MIF_SECURE_RTC_APBIF, 23, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_DREX1, "clk_drex1", "dout_aclk_mif_466", + EN_IP_MIF_SECURE_DREX1_TZ, 9, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_DREX0, "clk_drex0", "dout_aclk_mif_466", + EN_IP_MIF_SECURE_DREX0_TZ, 9, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_INTMEM, "clk_intmem", "dout_aclk_bus_200", + EN_IP_MIF_SECURE_INTEMEM, 11, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_SCLK_LPDDR3PHY_WRAP_U0, "sclk_lpddr3phy_wrap_u0", + "dout_clkm_phy", EN_SCLK_MIF, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), + GATE(MIF_SCLK_LPDDR3PHY_WRAP_U1, "sclk_lpddr3phy_wrap_u1", + "dout_clkm_phy", EN_SCLK_MIF, 1, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_pll_clock mif_pll_clks[] __initdata = { + PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll", + MEM_PLL_LOCK, MEM_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2550xx, MIF_FOUT_BUS_PLL, "fout_bus_pll", "fin_pll", + BUS_PLL_LOCK, BUS_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2550xx, MIF_FOUT_MEDIA_PLL, "fout_media_pll", "fin_pll", + MEDIA_PLL_LOCK, MEDIA_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_mif_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", + exynos5260_clk_mif_init); + + +/* CMU_PERI */ + +static unsigned long peri_clk_regs[] __initdata = { + MUX_SEL_PERI, + MUX_SEL_PERI1, + DIV_PERI, + EN_PCLK_PERI0, + EN_PCLK_PERI1, + EN_PCLK_PERI2, + EN_PCLK_PERI3, + EN_PCLK_PERI_SECURE_CHIPID, + EN_PCLK_PERI_SECURE_PROVKEY0, + EN_PCLK_PERI_SECURE_PROVKEY1, + EN_PCLK_PERI_SECURE_SECKEY, + EN_PCLK_PERI_SECURE_ANTIRBKCNT, + EN_PCLK_PERI_SECURE_TOP_RTC, + EN_PCLK_PERI_SECURE_TZPC, + EN_SCLK_PERI, + EN_SCLK_PERI_SECURE_TOP_RTC, + EN_IP_PERI0, + EN_IP_PERI1, + EN_IP_PERI2, + EN_IP_PERI_SECURE_CHIPID, + EN_IP_PERI_SECURE_PROVKEY0, + EN_IP_PERI_SECURE_PROVKEY1, + EN_IP_PERI_SECURE_SECKEY, + EN_IP_PERI_SECURE_ANTIRBKCNT, + EN_IP_PERI_SECURE_TOP_RTC, + EN_IP_PERI_SECURE_TZPC, +}; + +PNAME(mout_sclk_pcm_p) = {"ioclk_pcm_extclk", "fin_pll", "dout_aclk_peri_aud", + "phyclk_hdmi_phy_ref_cko"}; +PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud", + "phyclk_hdmi_phy_ref_cko"}; +PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll", + "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; + +struct samsung_mux_clock peri_mux_clks[] __initdata = { + MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p, + MUX_SEL_PERI1, 4, 2), + MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p, + MUX_SEL_PERI1, 12, 2), + MUX(PERI_MOUT_SCLK_SPDIF, "mout_sclk_spdif", mout_sclk_spdif_p, + MUX_SEL_PERI1, 20, 2), +}; + +struct samsung_div_clock peri_div_clks[] __initdata = { + DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8), + DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6), +}; + +struct samsung_gate_clock peri_gate_clks[] __initdata = { + GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0, + CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1, + CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPDIF, "sclk_spdif", "dout_sclk_peri_spi0_b", + EN_SCLK_PERI, 2, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI0, "sclk_spi0", "dout_sclk_peri_spi0_b", + EN_SCLK_PERI, 7, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI1, "sclk_spi1", "dout_sclk_peri_spi1_b", + EN_SCLK_PERI, 8, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI2, "sclk_spi2", "dout_sclk_peri_spi2_b", + EN_SCLK_PERI, 9, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART0, "sclk_uart0", "dout_sclk_peri_uart0", + EN_SCLK_PERI, 10, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART1, "sclk_uart1", "dout_sclk_peri_uart1", + EN_SCLK_PERI, 11, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART2, "sclk_uart2", "dout_sclk_peri_uart2", + EN_SCLK_PERI, 12, CLK_SET_RATE_PARENT, 0), + + GATE(PERI_CLK_ABB, "clk_abb", "dout_aclk_peri_66", + EN_IP_PERI0, 1, 0, 0), + GATE(PERI_CLK_EFUSE_WRITER, "clk_efuse_writer", "dout_aclk_peri_66", + EN_IP_PERI0, 5, 0, 0), + GATE(PERI_CLK_HDMICEC, "clk_hdmicec", "dout_aclk_peri_66", + EN_IP_PERI0, 6, 0, 0), + GATE(PERI_CLK_I2C10, "clk_i2c10", "dout_aclk_peri_66", + EN_IP_PERI0, 7, 0, 0), + GATE(PERI_CLK_I2C11, "clk_i2c11", "dout_aclk_peri_66", + EN_IP_PERI0, 8, 0, 0), + GATE(PERI_CLK_I2C8, "clk_i2c8", "dout_aclk_peri_66", + EN_IP_PERI0, 9, 0, 0), + GATE(PERI_CLK_I2C9, "clk_i2c9", "dout_aclk_peri_66", + EN_IP_PERI0, 10, 0, 0), + GATE(PERI_CLK_I2C4, "clk_i2c4", "dout_aclk_peri_66", + EN_IP_PERI0, 11, 0, 0), + GATE(PERI_CLK_I2C5, "clk_i2c5", "dout_aclk_peri_66", + EN_IP_PERI0, 12, 0, 0), + GATE(PERI_CLK_I2C6, "clk_i2c6", "dout_aclk_peri_66", + EN_IP_PERI0, 13, 0, 0), + GATE(PERI_CLK_I2C7, "clk_i2c7", "dout_aclk_peri_66", + EN_IP_PERI0, 14, 0, 0), + GATE(PERI_CLK_I2CHDMI, "clk_i2chdmi", "dout_aclk_peri_66", + EN_IP_PERI0, 15, 0, 0), + GATE(PERI_CLK_I2S, "clk_peri_i2s", "dout_aclk_peri_66", + EN_IP_PERI0, 16, 0, 0), + GATE(PERI_CLK_MCT, "clk_mct", "dout_aclk_peri_66", + EN_IP_PERI0, 17, 0, 0), + GATE(PERI_CLK_PCM, "clk_peri_pcm", "dout_aclk_peri_66", + EN_IP_PERI0, 18, 0, 0), + GATE(PERI_CLK_HSIC0, "clk_hsic0", "dout_aclk_peri_66", + EN_IP_PERI0, 20, 0, 0), + GATE(PERI_CLK_HSIC1, "clk_hsic1", "dout_aclk_peri_66", + EN_IP_PERI0, 21, 0, 0), + GATE(PERI_CLK_HSIC2, "clk_hsic2", "dout_aclk_peri_66", + EN_IP_PERI0, 22, 0, 0), + GATE(PERI_CLK_HSIC3, "clk_hsic3", "dout_aclk_peri_66", + EN_IP_PERI0, 23, 0, 0), + GATE(PERI_CLK_WDT_EGL, "clk_wdt_egl", "dout_aclk_peri_66", + EN_IP_PERI0, 24, 0, 0), + GATE(PERI_CLK_WDT_KFC, "clk_wdt_kfc", "dout_aclk_peri_66", + EN_IP_PERI0, 25, 0, 0), + + GATE(PERI_CLK_UART4, "clk_uart4", "dout_aclk_peri_66", + EN_IP_PERI2, 0, 0, 0), + GATE(PERI_CLK_PWM, "clk_pwm", "dout_aclk_peri_66", + EN_IP_PERI2, 3, 0, 0), + GATE(PERI_CLK_SPDIF, "clk_spdif", "dout_aclk_peri_66", + EN_IP_PERI2, 6, 0, 0), + GATE(PERI_CLK_SPI0, "clk_spi0", "dout_aclk_peri_66", + EN_IP_PERI2, 7, 0, 0), + GATE(PERI_CLK_SPI1, "clk_spi1", "dout_aclk_peri_66", + EN_IP_PERI2, 8, 0, 0), + GATE(PERI_CLK_SPI2, "clk_spi2", "dout_aclk_peri_66", + EN_IP_PERI2, 9, 0, 0), + GATE(PERI_CLK_TMU0, "clk_tmu0", "dout_aclk_peri_66", + EN_IP_PERI2, 10, 0, 0), + GATE(PERI_CLK_TMU1, "clk_tmu1", "dout_aclk_peri_66", + EN_IP_PERI2, 11, 0, 0), + GATE(PERI_CLK_TMU2, "clk_tmu2", "dout_aclk_peri_66", + EN_IP_PERI2, 12, 0, 0), + GATE(PERI_CLK_TMU3, "clk_tmu3", "dout_aclk_peri_66", + EN_IP_PERI2, 13, 0, 0), + GATE(PERI_CLK_TMU4, "clk_tmu4", "dout_aclk_peri_66", + EN_IP_PERI2, 14, 0, 0), + GATE(PERI_CLK_ADC, "clk_adc", "dout_aclk_peri_66", + EN_IP_PERI2, 18, 0, 0), + GATE(PERI_CLK_UART0, "clk_uart0", "dout_aclk_peri_66", + EN_IP_PERI2, 19, 0, 0), + GATE(PERI_CLK_UART1, "clk_uart1", "dout_aclk_peri_66", + EN_IP_PERI2, 20, 0, 0), + GATE(PERI_CLK_UART2, "clk_uart2", "dout_aclk_peri_66", + EN_IP_PERI2, 21, 0, 0), + + GATE(PERI_CLK_CHIPID, "clk_chipid", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_CHIPID, 2, 0, 0), + + GATE(PERI_CLK_PROVKEY0, "clk_provkey0", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_PROVKEY0, 1, 0, 0), + + GATE(PERI_CLK_PROVKEY1, "clk_provkey1", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_PROVKEY1, 2, 0, 0), + + GATE(PERI_CLK_SECKEY, "clk_seckey", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_SECKEY, 5, 0, 0), + + GATE(PERI_CLK_TOP_RTC, "clk_top_rtc", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TOP_RTC, 5, 0, 0), + + GATE(PERI_CLK_TZPC0, "clk_tzpc0", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 10, 0, 0), + GATE(PERI_CLK_TZPC1, "clk_tzpc1", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 11, 0, 0), + GATE(PERI_CLK_TZPC2, "clk_tzpc2", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 12, 0, 0), + GATE(PERI_CLK_TZPC3, "clk_tzpc3", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 13, 0, 0), + GATE(PERI_CLK_TZPC4, "clk_tzpc4", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 14, 0, 0), + GATE(PERI_CLK_TZPC5, "clk_tzpc5", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 15, 0, 0), + GATE(PERI_CLK_TZPC6, "clk_tzpc6", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 16, 0, 0), + GATE(PERI_CLK_TZPC7, "clk_tzpc7", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 17, 0, 0), + GATE(PERI_CLK_TZPC8, "clk_tzpc8", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 18, 0, 0), + GATE(PERI_CLK_TZPC9, "clk_tzpc9", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 19, 0, 0), + GATE(PERI_CLK_TZPC10, "clk_tzpc10", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 20, 0, 0), +}; + +static void __init exynos5260_clk_peri_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", + exynos5260_clk_peri_init); + + +/* CMU_TOP */ + +static unsigned long top_clk_regs[] __initdata = { + DISP_PLL_LOCK, + AUD_PLL_LOCK, + DISP_PLL_CON0, + DISP_PLL_CON1, + DISP_PLL_FDET, + AUD_PLL_CON0, + AUD_PLL_CON1, + AUD_PLL_CON2, + AUD_PLL_FDET, + MUX_SEL_TOP_PLL0, + MUX_SEL_TOP_MFC, + MUX_SEL_TOP_G2D, + MUX_SEL_TOP_GSCL, + MUX_SEL_TOP_ISP10, + MUX_SEL_TOP_ISP11, + MUX_SEL_TOP_DISP0, + MUX_SEL_TOP_DISP1, + MUX_SEL_TOP_BUS, + MUX_SEL_TOP_PERI0, + MUX_SEL_TOP_PERI1, + MUX_SEL_TOP_FSYS, + DIV_TOP_G2D_MFC, + DIV_TOP_GSCL_ISP0, + DIV_TOP_ISP10, + DIV_TOP_ISP11, + DIV_TOP_DISP, + DIV_TOP_BUS, + DIV_TOP_PERI0, + DIV_TOP_PERI1, + DIV_TOP_PERI2, + DIV_TOP_FSYS0, + DIV_TOP_FSYS1, + DIV_TOP_HPM, + DIV_TOP_PLL_FDET, + EN_ACLK_TOP, + EN_SCLK_TOP, + EN_IP_TOP, +}; + +/* fixed rate clocks generated inside the soc */ +struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = { + FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH1_TXD_CLK, "phyclk_dptx_phy_ch1_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH0_TXD_CLK, "phyclk_dptx_phy_ch0_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(phyclk_hdmi_phy_tmds_clko, "phyclk_hdmi_phy_tmds_clko", NULL, + CLK_IS_ROOT, 250000000), + FRATE(PHYCLK_HDMI_PHY_PIXEL_CLKO, "phyclk_hdmi_phy_pixel_clko", NULL, + CLK_IS_ROOT, 1660000000), + FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi", + NULL, CLK_IS_ROOT, 125000000), + FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS, + "phyclk_mipi_dphy_4l_m_txbyteclkhs" , NULL, + CLK_IS_ROOT, 187500000), + FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m", + NULL, CLK_IS_ROOT, 24000000), + FRATE(PHYCLK_DPTX_PHY_CLK_DIV2, "phyclk_dptx_phy_clk_div2", NULL, + CLK_IS_ROOT, 135000000), + FRATE(PHYCLK_MIPI_DPHY_4L_M_RXCLKESC0, + "phyclk_mipi_dphy_4l_m_rxclkesc0", NULL, + CLK_IS_ROOT, 20000000), + FRATE(PHYCLK_USBHOST20_PHY_PHYCLOCK, "phyclk_usbhost20_phy_phyclock", + NULL, CLK_IS_ROOT, 60000000), + FRATE(PHYCLK_USBHOST20_PHY_FREECLK, "phyclk_usbhost20_phy_freeclk", + NULL, CLK_IS_ROOT, 60000000), + FRATE(PHYCLK_USBHOST20_PHY_CLK48MOHCI, + "phyclk_usbhost20_phy_clk48mohci", + NULL, CLK_IS_ROOT, 48000000), + FRATE(PHYCLK_USBDRD30_UDRD30_PIPE_PCLK, + "phyclk_usbdrd30_udrd30_pipe_pclk", NULL, + CLK_IS_ROOT, 125000000), + FRATE(PHYCLK_USBDRD30_UDRD30_PHYCLOCK, + "phyclk_usbdrd30_udrd30_phyclock", NULL, + CLK_IS_ROOT, 60000000), +}; + +PNAME(mout_memtop_pll_user_p) = {"fin_pll", "dout_mem_pll"}; +PNAME(mout_bustop_pll_user_p) = {"fin_pll", "dout_bus_pll"}; +PNAME(mout_mediatop_pll_user_p) = {"fin_pll", "dout_media_pll"}; +PNAME(mout_audtop_pll_user_p) = {"fin_pll", "mout_aud_pll"}; +PNAME(mout_aud_pll_p) = {"fin_pll", "fout_aud_pll"}; +PNAME(mout_disp_pll_p) = {"fin_pll", "fout_disp_pll"}; +PNAME(mout_mfc_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_mfc_333_p) = {"mout_mediatop_pll_user", "mout_mfc_bustop_333"}; +PNAME(mout_g2d_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_g2d_333_p) = {"mout_mediatop_pll_user", "mout_g2d_bustop_333"}; +PNAME(mout_gscl_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_333_p) = {"mout_mediatop_pll_user", + "mout_gscl_bustop_333"}; +PNAME(mout_m2m_mediatop_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_400_p) = {"mout_bustop_pll_user", + "mout_m2m_mediatop_400"}; +PNAME(mout_gscl_bustop_fimc_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_fimc_p) = {"mout_mediatop_pll_user", + "mout_gscl_bustop_fimc"}; +PNAME(mout_isp1_media_266_p) = {"mout_mediatop_pll_user", + "mout_memtop_pll_user"}; +PNAME(mout_aclk_isp1_266_p) = {"mout_bustop_pll_user", "mout_isp1_media_266"}; +PNAME(mout_isp1_media_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_isp1_400_p) = {"mout_bustop_pll_user", "mout_isp1_media_400"}; +PNAME(mout_sclk_isp_spi_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_isp_uart_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_isp_sensor_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_disp_disp_333_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; +PNAME(mout_aclk_disp_333_p) = {"mout_mediatop_pll_user", "mout_disp_disp_333"}; +PNAME(mout_disp_disp_222_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; +PNAME(mout_aclk_disp_222_p) = {"mout_mediatop_pll_user", "mout_disp_disp_222"}; +PNAME(mout_disp_media_pixel_p) = {"mout_mediatop_pll_user", + "mout_bustop_pll_user"}; +PNAME(mout_sclk_disp_pixel_p) = {"mout_disp_pll", "mout_disp_media_pixel"}; +PNAME(mout_bus_bustop_400_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; +PNAME(mout_bus_bustop_100_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; +PNAME(mout_sclk_peri_spi_clk_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_peri_uart_uclk_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_usb_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_mmc_sdclkin_a_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_mmc0_sdclkin_b_p) = {"mout_sclk_fsys_mmc0_sdclkin_a", + "mout_mediatop_pll_user"}; +PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a", + "mout_mediatop_pll_user"}; +PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a", + "mout_mediatop_pll_user"}; + +struct samsung_mux_clock top_mux_clks[] __initdata = { + MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user", + mout_mediatop_pll_user_p, + MUX_SEL_TOP_PLL0, 0, 1), + MUX(TOP_MOUT_MEMTOP_PLL_USER, "mout_memtop_pll_user", + mout_memtop_pll_user_p, + MUX_SEL_TOP_PLL0, 4, 1), + MUX(TOP_MOUT_BUSTOP_PLL_USER, "mout_bustop_pll_user", + mout_bustop_pll_user_p, + MUX_SEL_TOP_PLL0, 8, 1), + MUX(TOP_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, + MUX_SEL_TOP_PLL0, 12, 1), + MUX(TOP_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, + MUX_SEL_TOP_PLL0, 16, 1), + MUX(TOP_MOUT_AUDTOP_PLL_USER, "mout_audtop_pll_user", + mout_audtop_pll_user_p, + MUX_SEL_TOP_PLL0, 24, 1), + + MUX(TOP_MOUT_DISP_DISP_333, "mout_disp_disp_333", mout_disp_disp_333_p, + MUX_SEL_TOP_DISP0, 0, 1), + MUX(TOP_MOUT_ACLK_DISP_333, "mout_aclk_disp_333", mout_aclk_disp_333_p, + MUX_SEL_TOP_DISP0, 8, 1), + MUX(TOP_MOUT_DISP_DISP_222, "mout_disp_disp_222", mout_disp_disp_222_p, + MUX_SEL_TOP_DISP0, 12, 1), + MUX(TOP_MOUT_ACLK_DISP_222, "mout_aclk_disp_222", mout_aclk_disp_222_p, + MUX_SEL_TOP_DISP0, 20, 1), + + MUX(TOP_MOUT_FIMD1, "mout_sclk_disp_pixel", mout_sclk_disp_pixel_p, + MUX_SEL_TOP_DISP1, 0, 1), + MUX(TOP_MOUT_DISP_MEDIA_PIXEL, "mout_disp_media_pixel", + mout_disp_media_pixel_p, + MUX_SEL_TOP_DISP1, 8, 1), + + MUX(TOP_MOUT_SCLK_PERI_SPI2_CLK, "mout_sclk_peri_spi2_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 0, 1), + MUX(TOP_MOUT_SCLK_PERI_SPI1_CLK, "mout_sclk_peri_spi1_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 4, 1), + MUX(TOP_MOUT_SCLK_PERI_SPI0_CLK, "mout_sclk_peri_spi0_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 8, 1), + MUX(TOP_MOUT_SCLK_PERI_UART1_UCLK, "mout_sclk_peri_uart1_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 12, 1), + MUX(TOP_MOUT_SCLK_PERI_UART2_UCLK, "mout_sclk_peri_uart2_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 16, 1), + MUX(TOP_MOUT_SCLK_PERI_UART0_UCLK, "mout_sclk_peri_uart0_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 20, 1), + + + MUX(TOP_MOUT_BUS1_BUSTOP_400, "mout_bus1_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 0, 1), + MUX(TOP_MOUT_BUS1_BUSTOP_100, "mout_bus1_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 4, 1), + MUX(TOP_MOUT_BUS2_BUSTOP_100, "mout_bus2_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 8, 1), + MUX(TOP_MOUT_BUS2_BUSTOP_400, "mout_bus2_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 12, 1), + MUX(TOP_MOUT_BUS3_BUSTOP_400, "mout_bus3_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 16, 1), + MUX(TOP_MOUT_BUS3_BUSTOP_100, "mout_bus3_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 20, 1), + MUX(TOP_MOUT_BUS4_BUSTOP_400, "mout_bus4_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 24, 1), + MUX(TOP_MOUT_BUS4_BUSTOP_100, "mout_bus4_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 28, 1), + + MUX(TOP_MOUT_SCLK_FSYS_USB, "mout_sclk_fsys_usb", + mout_sclk_fsys_usb_p, + MUX_SEL_TOP_FSYS, 0, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "mout_sclk_fsys_mmc2_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 4, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "mout_sclk_fsys_mmc2_sdclkin_b", + mout_sclk_fsys_mmc2_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 8, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "mout_sclk_fsys_mmc1_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 12, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "mout_sclk_fsys_mmc1_sdclkin_b", + mout_sclk_fsys_mmc1_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 16, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "mout_sclk_fsys_mmc0_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 20, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "mout_sclk_fsys_mmc0_sdclkin_b", + mout_sclk_fsys_mmc0_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 24, 1), + + MUX(TOP_MOUT_ISP1_MEDIA_400, "mout_isp1_media_400", + mout_isp1_media_400_p, + MUX_SEL_TOP_ISP10, 4, 1), + MUX(TOP_MOUT_ACLK_ISP1_400, "mout_aclk_isp1_400", mout_aclk_isp1_400_p, + MUX_SEL_TOP_ISP10, 8 , 1), + MUX(TOP_MOUT_ISP1_MEDIA_266, "mout_isp1_media_266", + mout_isp1_media_266_p, + MUX_SEL_TOP_ISP10, 16, 1), + MUX(TOP_MOUT_ACLK_ISP1_266, "mout_aclk_isp1_266", mout_aclk_isp1_266_p, + MUX_SEL_TOP_ISP10, 20, 1), + + MUX(TOP_MOUT_SCLK_ISP1_SPI0, "mout_sclk_isp1_spi0", mout_sclk_isp_spi_p, + MUX_SEL_TOP_ISP11, 4, 1), + MUX(TOP_MOUT_SCLK_ISP1_SPI1, "mout_sclk_isp1_spi1", mout_sclk_isp_spi_p, + MUX_SEL_TOP_ISP11, 8, 1), + MUX(TOP_MOUT_SCLK_ISP1_UART, "mout_sclk_isp1_uart", + mout_sclk_isp_uart_p, + MUX_SEL_TOP_ISP11, 12, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR0, "mout_sclk_isp1_sensor0", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 16, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR1, "mout_sclk_isp1_sensor1", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 20, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR2, "mout_sclk_isp1_sensor2", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 24, 1), + + MUX(TOP_MOUT_MFC_BUSTOP_333, "mout_mfc_bustop_333", + mout_mfc_bustop_333_p, + MUX_SEL_TOP_MFC, 4, 1), + MUX(TOP_MOUT_ACLK_MFC_333, "mout_aclk_mfc_333", mout_aclk_mfc_333_p, + MUX_SEL_TOP_MFC, 8, 1), + + MUX(TOP_MOUT_G2D_BUSTOP_333, "mout_g2d_bustop_333", + mout_g2d_bustop_333_p, + MUX_SEL_TOP_G2D, 4, 1), + MUX(TOP_MOUT_ACLK_G2D_333, "mout_aclk_g2d_333", mout_aclk_g2d_333_p, + MUX_SEL_TOP_G2D, 8, 1), + + MUX(TOP_MOUT_M2M_MEDIATOP_400, "mout_m2m_mediatop_400", + mout_m2m_mediatop_400_p, + MUX_SEL_TOP_GSCL, 0, 1), + MUX(TOP_MOUT_ACLK_GSCL_400, "mout_aclk_gscl_400", + mout_aclk_gscl_400_p, + MUX_SEL_TOP_GSCL, 4, 1), + MUX(TOP_MOUT_GSCL_BUSTOP_333, "mout_gscl_bustop_333", + mout_gscl_bustop_333_p, + MUX_SEL_TOP_GSCL, 8, 1), + MUX(TOP_MOUT_ACLK_GSCL_333, "mout_aclk_gscl_333", + mout_aclk_gscl_333_p, + MUX_SEL_TOP_GSCL, 12, 1), + MUX(TOP_MOUT_GSCL_BUSTOP_FIMC, "mout_gscl_bustop_fimc", + mout_gscl_bustop_fimc_p, + MUX_SEL_TOP_GSCL, 16, 1), + MUX(TOP_MOUT_ACLK_GSCL_FIMC, "mout_aclk_gscl_fimc", + mout_aclk_gscl_fimc_p, + MUX_SEL_TOP_GSCL, 20, 1), +}; + +struct samsung_div_clock top_div_clks[] __initdata = { + DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333", + DIV_TOP_G2D_MFC, 0, 3), + DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333", + DIV_TOP_G2D_MFC, 4, 3), + + DIV(TOP_DOUT_ACLK_GSCL_333, "dout_aclk_gscl_333", "mout_aclk_gscl_333", + DIV_TOP_GSCL_ISP0, 0, 3), + DIV(TOP_DOUT_ACLK_GSCL_400, "dout_aclk_gscl_400", "mout_aclk_gscl_400", + DIV_TOP_GSCL_ISP0, 4, 3), + DIV(TOP_DOUT_ACLK_GSCL_FIMC, "dout_aclk_gscl_fimc", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 8, 3), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_A, "dout_sclk_isp1_sensor0_a", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 16, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_A, "dout_sclk_isp1_sensor1_a", + "mout_aclk_gscl_400", DIV_TOP_GSCL_ISP0, 20, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_A, "dout_sclk_isp1_sensor2_a", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 24, 4), + + DIV(TOP_DOUT_ACLK_ISP1_266, "dout_aclk_isp1_266", "mout_aclk_isp1_266", + DIV_TOP_ISP10, 0, 3), + DIV(TOP_DOUT_ACLK_ISP1_400, "dout_aclk_isp1_400", "mout_aclk_isp1_400", + DIV_TOP_ISP10, 4, 3), + DIV(TOP_DOUT_SCLK_ISP1_SPI0_A, "dout_sclk_isp1_spi0_a", + "mout_sclk_isp1_spi0", DIV_TOP_ISP10, 12, 4), + DIV(TOP_DOUT_SCLK_ISP1_SPI0_B, "dout_sclk_isp1_spi0_b", + "dout_sclk_isp1_spi0_a", DIV_TOP_ISP10, 16, 8), + + DIV(TOP_DOUT_SCLK_ISP1_SPI1_A, "dout_sclk_isp1_spi1_a", + "mout_sclk_isp1_spi1", DIV_TOP_ISP11, 0, 4), + DIV(TOP_DOUT_SCLK_ISP1_SPI1_B, "dout_sclk_isp1_spi1_b", + "dout_sclk_isp1_spi1_a", DIV_TOP_ISP11, 4, 8), + DIV(TOP_DOUT_SCLK_ISP1_UART, "dout_sclk_isp1_uart", + "mout_sclk_isp1_uart", DIV_TOP_ISP11, 12, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_B, "dout_sclk_isp1_sensor0_b", + "dout_sclk_isp1_sensor0_a", DIV_TOP_ISP11, 16, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_B, "dout_sclk_isp1_sensor1_b", + "dout_sclk_isp1_sensor1_a", DIV_TOP_ISP11, 20, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_B, "dout_sclk_isp1_sensor2_b", + "dout_sclk_isp1_sensor2_a", DIV_TOP_ISP11, 24, 4), + + DIV(TOP_DOUTTOP__SCLK_HPM_TARGETCLK, "dout_sclk_hpm_targetclk", + "mout_bustop_pll_user", DIV_TOP_HPM, 0, 3), + + DIV(TOP_DOUT_ACLK_DISP_333, "dout_aclk_disp_333", "mout_aclk_disp_333", + DIV_TOP_DISP, 0, 3), + DIV(TOP_DOUT_ACLK_DISP_222, "dout_aclk_disp_222", "mout_aclk_disp_222", + DIV_TOP_DISP, 4, 3), + DIV(TOP_DOUT_SCLK_DISP_PIXEL, "dout_sclk_disp_pixel", + "mout_sclk_disp_pixel", DIV_TOP_DISP, 8, 3), + + DIV(TOP_DOUT_ACLK_BUS1_400, "dout_aclk_bus1_400", + "mout_bus1_bustop_400", DIV_TOP_BUS, 0, 3), + DIV(TOP_DOUT_ACLK_BUS1_100, "dout_aclk_bus1_100", + "mout_bus1_bustop_100", DIV_TOP_BUS, 4, 4), + DIV(TOP_DOUT_ACLK_BUS2_400, "dout_aclk_bus2_400", + "mout_bus2_bustop_400", DIV_TOP_BUS, 8, 3), + DIV(TOP_DOUT_ACLK_BUS2_100, "dout_aclk_bus2_100", + "mout_bus2_bustop_100", DIV_TOP_BUS, 12, 4), + DIV(TOP_DOUT_ACLK_BUS3_400, "dout_aclk_bus3_400", + "mout_bus3_bustop_400", DIV_TOP_BUS, 16, 3), + DIV(TOP_DOUT_ACLK_BUS3_100, "dout_aclk_bus3_100", + "mout_bus3_bustop_100", DIV_TOP_BUS, 20, 4), + DIV(TOP_DOUT_ACLK_BUS4_400, "dout_aclk_bus4_400", + "mout_bus4_bustop_400", DIV_TOP_BUS, 24, 3), + DIV(TOP_DOUT_ACLK_BUS4_100, "dout_aclk_bus4_100", + "mout_bus4_bustop_100", DIV_TOP_BUS, 28, 4), + + DIV(TOP_DOUT_SCLK_PERI_SPI0_A, "dout_sclk_peri_spi0_a", + "mout_sclk_peri_spi0_clk", DIV_TOP_PERI0, 4, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI0_B, "dout_sclk_peri_spi0_b", + "dout_sclk_peri_spi0_a", DIV_TOP_PERI0, 8, 8), + DIV(TOP_DOUT_SCLK_PERI_SPI1_A, "dout_sclk_peri_spi1_a", + "mout_sclk_peri_spi1_clk", DIV_TOP_PERI0, 16, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI1_B, "dout_sclk_peri_spi1_b", + "dout_sclk_peri_spi1_a", DIV_TOP_PERI0, 20, 8), + + DIV(TOP_DOUT_SCLK_PERI_SPI2_A, "dout_sclk_peri_spi2_a", + "mout_sclk_peri_spi2_clk", DIV_TOP_PERI1, 0, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI2_B, "dout_sclk_peri_spi2_b", + "dout_sclk_peri_spi2_a", DIV_TOP_PERI1, 4, 8), + DIV(TOP_DOUT_SCLK_PERI_UART1, "dout_sclk_peri_uart1", + "mout_sclk_peri_uart1_uclk", DIV_TOP_PERI1, 16, 4), + DIV(TOP_DOUT_SCLK_PERI_UART2, "dout_sclk_peri_uart2", + "mout_sclk_peri_uart2_uclk", DIV_TOP_PERI1, 20, 4), + DIV(TOP_DOUT_SCLK_PERI_UART0, "dout_sclk_peri_uart0", + "mout_sclk_peri_uart0_uclk", DIV_TOP_PERI1, 24, 4), + + DIV(TOP_DOUT_ACLK_PERI_66, "dout_aclk_peri_66", "mout_bustop_pll_user", + DIV_TOP_PERI2, 20, 4), + DIV(TOP_DOUT_ACLK_PERI_AUD, "dout_aclk_peri_aud", + "mout_audtop_pll_user", DIV_TOP_PERI2, 24, 3), + + DIV(TOP_DOUT_ACLK_FSYS_200, "dout_aclk_fsys_200", + "mout_bustop_pll_user", DIV_TOP_FSYS0, 0, 3), + DIV(TOP_DOUT_SCLK_FSYS_USBDRD30_SUSPEND_CLK, + "dout_sclk_fsys_usbdrd30_suspend_clk", + "mout_sclk_fsys_usb", DIV_TOP_FSYS0, 4, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "dout_sclk_fsys_mmc0_sdclkin_a", + "mout_sclk_fsys_mmc0_sdclkin_b", + DIV_TOP_FSYS0, 12, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "dout_sclk_fsys_mmc0_sdclkin_b", + "dout_sclk_fsys_mmc0_sdclkin_a", + DIV_TOP_FSYS0, 16, 8), + + + DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "dout_sclk_fsys_mmc1_sdclkin_a", + "mout_sclk_fsys_mmc1_sdclkin_b", + DIV_TOP_FSYS1, 0, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "dout_sclk_fsys_mmc1_sdclkin_b", + "dout_sclk_fsys_mmc1_sdclkin_a", + DIV_TOP_FSYS1, 4, 8), + DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "dout_sclk_fsys_mmc2_sdclkin_a", + "mout_sclk_fsys_mmc2_sdclkin_b", + DIV_TOP_FSYS1, 12, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "dout_sclk_fsys_mmc2_sdclkin_b", + "dout_sclk_fsys_mmc2_sdclkin_a", + DIV_TOP_FSYS1, 16, 8), + +}; + +struct samsung_gate_clock top_gate_clks[] __initdata = { + GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin", + "dout_sclk_fsys_mmc0_sdclkin_b", + EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_MMC1, "sclk_fsys_mmc1_sdclkin", + "dout_sclk_fsys_mmc1_sdclkin_b", + EN_SCLK_TOP, 8, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_MMC2, "sclk_fsys_mmc2_sdclkin", + "dout_sclk_fsys_mmc2_sdclkin_b", + EN_SCLK_TOP, 9, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_FIMD1, "sclk_disp_pixel", "dout_sclk_disp_pixel", + EN_ACLK_TOP, 10, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_pll_clock top_pll_clks[] __initdata = { + PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll", + DISP_PLL_LOCK, DISP_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2650xx, TOP_FOUT_AUD_PLL, "fout_aud_pll", "fin_pll", + AUD_PLL_LOCK, AUD_PLL_CON0, + pll2650_24mhz_tbl), +}; + +static void __init exynos5260_clk_top_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + 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); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", + exynos5260_clk_top_init); diff --git a/drivers/clk/samsung/clk-exynos5260.h b/drivers/clk/samsung/clk-exynos5260.h new file mode 100644 index 0000000..d739716 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5260.h @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Rahul Sharma <rahul.sharma@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 Exynos5260 SoC. + */ + +#ifndef __CLK_EXYNOS5260_H +#define __CLK_EXYNOS5260_H + +/* +*Registers for CMU_AUD +*/ +#define MUX_SEL_AUD 0x0200 +#define MUX_ENABLE_AUD 0x0300 +#define MUX_STAT_AUD 0x0400 +#define MUX_IGNORE_AUD 0x0500 +#define DIV_AUD0 0x0600 +#define DIV_AUD1 0x0604 +#define DIV_STAT_AUD0 0x0700 +#define DIV_STAT_AUD1 0x0704 +#define EN_ACLK_AUD 0x0800 +#define EN_PCLK_AUD 0x0900 +#define EN_SCLK_AUD 0x0a00 +#define EN_IP_AUD 0x0b00 + +/* +*Registers for CMU_DISP +*/ +#define MUX_SEL_DISP0 0x0200 +#define MUX_SEL_DISP1 0x0204 +#define MUX_SEL_DISP2 0x0208 +#define MUX_SEL_DISP3 0x020C +#define MUX_SEL_DISP4 0x0210 +#define MUX_ENABLE_DISP0 0x0300 +#define MUX_ENABLE_DISP1 0x0304 +#define MUX_ENABLE_DISP2 0x0308 +#define MUX_ENABLE_DISP3 0x030c +#define MUX_ENABLE_DISP4 0x0310 +#define MUX_STAT_DISP0 0x0400 +#define MUX_STAT_DISP1 0x0404 +#define MUX_STAT_DISP2 0x0408 +#define MUX_STAT_DISP3 0x040c +#define MUX_STAT_DISP4 0x0410 +#define MUX_IGNORE_DISP0 0x0500 +#define MUX_IGNORE_DISP1 0x0504 +#define MUX_IGNORE_DISP2 0x0508 +#define MUX_IGNORE_DISP3 0x050c +#define MUX_IGNORE_DISP4 0x0510 +#define DIV_DISP 0x0600 +#define DIV_STAT_DISP 0x0700 +#define EN_ACLK_DISP 0x0800 +#define EN_PCLK_DISP 0x0900 +#define EN_SCLK_DISP0 0x0a00 +#define EN_SCLK_DISP1 0x0a04 +#define EN_IP_DISP 0x0b00 +#define EN_IP_DISP_BUS 0x0b04 + + +/* +*Registers for CMU_EGL +*/ +#define EGL_PLL_LOCK 0x0000 +#define EGL_DPLL_LOCK 0x0004 +#define EGL_PLL_CON0 0x0100 +#define EGL_PLL_CON1 0x0104 +#define EGL_PLL_FREQ_DET 0x010c +#define EGL_DPLL_CON0 0x0110 +#define EGL_DPLL_CON1 0x0114 +#define EGL_DPLL_FREQ_DET 0x011c +#define MUX_SEL_EGL 0x0200 +#define MUX_ENABLE_EGL 0x0300 +#define MUX_STAT_EGL 0x0400 +#define DIV_EGL 0x0600 +#define DIV_EGL_PLL_FDET 0x0604 +#define DIV_STAT_EGL 0x0700 +#define DIV_STAT_EGL_PLL_FDET 0x0704 +#define EN_ACLK_EGL 0x0800 +#define EN_PCLK_EGL 0x0900 +#define EN_SCLK_EGL 0x0a00 +#define EN_IP_EGL 0x0b00 +#define CLKOUT_CMU_EGL 0x0c00 +#define CLKOUT_CMU_EGL_DIV_STAT 0x0c04 +#define ARMCLK_STOPCTRL 0x1000 +#define EAGLE_EMA_CTRL 0x1008 +#define EAGLE_EMA_STATUS 0x100c +#define PWR_CTRL 0x1020 +#define PWR_CTRL2 0x1024 +#define CLKSTOP_CTRL 0x1028 +#define INTR_SPREAD_EN 0x1080 +#define INTR_SPREAD_USE_STANDBYWFI 0x1084 +#define INTR_SPREAD_BLOCKING_DURATION 0x1088 +#define CMU_EGL_SPARE0 0x2000 +#define CMU_EGL_SPARE1 0x2004 +#define CMU_EGL_SPARE2 0x2008 +#define CMU_EGL_SPARE3 0x200c +#define CMU_EGL_SPARE4 0x2010 + +/* +*Registers for CMU_FSYS +*/ + +#define MUX_SEL_FSYS0 0x0200 +#define MUX_SEL_FSYS1 0x0204 +#define MUX_ENABLE_FSYS0 0x0300 +#define MUX_ENABLE_FSYS1 0x0304 +#define MUX_STAT_FSYS0 0x0400 +#define MUX_STAT_FSYS1 0x0404 +#define MUX_IGNORE_FSYS0 0x0500 +#define MUX_IGNORE_FSYS1 0x0504 +#define EN_ACLK_FSYS 0x0800 +#define EN_ACLK_FSYS_SECURE_RTIC 0x0804 +#define EN_ACLK_FSYS_SECURE_SMMU_RTIC 0x0808 +#define EN_PCLK_FSYS 0x0900 +#define EN_SCLK_FSYS 0x0a00 +#define EN_IP_FSYS 0x0b00 +#define EN_IP_FSYS_SECURE_RTIC 0x0b04 +#define EN_IP_FSYS_SECURE_SMMU_RTIC 0x0b08 + +/* +*Registers for CMU_G2D +*/ + +#define MUX_SEL_G2D 0x0200 +#define MUX_ENABLE_G2D 0x0300 +#define MUX_STAT_G2D 0x0400 +#define DIV_G2D 0x0600 +#define DIV_STAT_G2D 0x0700 +#define EN_ACLK_G2D 0x0800 +#define EN_ACLK_G2D_SECURE_SSS 0x0804 +#define EN_ACLK_G2D_SECURE_SLIM_SSS 0x0808 +#define EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS 0x080c +#define EN_ACLK_G2D_SECURE_SMMU_SSS 0x0810 +#define EN_ACLK_G2D_SECURE_SMMU_MDMA 0x0814 +#define EN_ACLK_G2D_SECURE_SMMU_G2D 0x0818 +#define EN_PCLK_G2D 0x0900 +#define EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS 0x0904 +#define EN_PCLK_G2D_SECURE_SMMU_SSS 0x0908 +#define EN_PCLK_G2D_SECURE_SMMU_MDMA 0x090c +#define EN_PCLK_G2D_SECURE_SMMU_G2D 0x0910 +#define EN_IP_G2D 0x0b00 +#define EN_IP_G2D_SECURE_SSS 0x0b04 +#define EN_IP_G2D_SECURE_SLIM_SSS 0x0b08 +#define EN_IP_G2D_SECURE_SMMU_SLIM_SSS 0x0b0c +#define EN_IP_G2D_SECURE_SMMU_SSS 0x0b10 +#define EN_IP_G2D_SECURE_SMMU_MDMA 0x0b14 +#define EN_IP_G2D_SECURE_SMMU_G2D 0x0b18 + +/* +*Registers for CMU_G3D +*/ + +#define G3D_PLL_LOCK 0x0000 +#define G3D_PLL_CON0 0x0100 +#define G3D_PLL_CON1 0x0104 +#define G3D_PLL_FDET 0x010c +#define MUX_SEL_G3D 0x0200 +#define MUX_EN_G3D 0x0300 +#define MUX_STAT_G3D 0x0400 +#define MUX_IGNORE_G3D 0x0500 +#define DIV_G3D 0x0600 +#define DIV_G3D_PLL_FDET 0x0604 +#define DIV_STAT_G3D 0x0700 +#define DIV_STAT_G3D_PLL_FDET 0x0704 +#define EN_ACLK_G3D 0x0800 +#define EN_PCLK_G3D 0x0900 +#define EN_SCLK_G3D 0x0a00 +#define EN_IP_G3D 0x0b00 +#define CLKOUT_CMU_G3D 0x0c00 +#define CLKOUT_CMU_G3D_DIV_STAT 0x0c04 +#define G3DCLK_STOPCTRL 0x1000 +#define G3D_EMA_CTRL 0x1008 +#define G3D_EMA_STATUS 0x100c + +/* +*Registers for CMU_GSCL +*/ + +#define MUX_SEL_GSCL 0x0200 +#define MUX_EN_GSCL 0x0300 +#define MUX_STAT_GSCL 0x0400 +#define MUX_IGNORE_GSCL 0x0500 +#define DIV_GSCL 0x0600 +#define DIV_STAT_GSCL 0x0700 +#define EN_ACLK_GSCL 0x0800 +#define EN_ACLK_GSCL_FIMC 0x0804 +#define EN_ACLK_GSCL_SECURE_SMMU_GSCL0 0x0808 +#define EN_ACLK_GSCL_SECURE_SMMU_GSCL1 0x080c +#define EN_ACLK_GSCL_SECURE_SMMU_MSCL0 0x0810 +#define EN_ACLK_GSCL_SECURE_SMMU_MSCL1 0x0814 +#define EN_PCLK_GSCL 0x0900 +#define EN_PCLK_GSCL_FIMC 0x0904 +#define EN_PCLK_GSCL_SECURE_SMMU_GSCL0 0x0908 +#define EN_PCLK_GSCL_SECURE_SMMU_GSCL1 0x090c +#define EN_PCLK_GSCL_SECURE_SMMU_MSCL0 0x0910 +#define EN_PCLK_GSCL_SECURE_SMMU_MSCL1 0x0914 +#define EN_SCLK_GSCL 0x0a00 +#define EN_SCLK_GSCL_FIMC 0x0a04 +#define EN_IP_GSCL 0x0b00 +#define EN_IP_GSCL_FIMC 0x0b04 +#define EN_IP_GSCL_SECURE_SMMU_GSCL0 0x0b08 +#define EN_IP_GSCL_SECURE_SMMU_GSCL1 0x0b0c +#define EN_IP_GSCL_SECURE_SMMU_MSCL0 0x0b10 +#define EN_IP_GSCL_SECURE_SMMU_MSCL1 0x0b14 + +/* +*Registers for CMU_ISP +*/ +#define MUX_SEL_ISP0 0x0200 +#define MUX_SEL_ISP1 0x0204 +#define MUX_ENABLE_ISP0 0x0300 +#define MUX_ENABLE_ISP1 0x0304 +#define MUX_STAT_ISP0 0x0400 +#define MUX_STAT_ISP1 0x0404 +#define MUX_IGNORE_ISP0 0x0500 +#define MUX_IGNORE_ISP1 0x0504 +#define DIV_ISP 0x0600 +#define DIV_STAT_ISP 0x0700 +#define EN_ACLK_ISP0 0x0800 +#define EN_ACLK_ISP1 0x0804 +#define EN_PCLK_ISP0 0x0900 +#define EN_PCLK_ISP1 0x0904 +#define EN_SCLK_ISP 0x0a00 +#define EN_IP_ISP0 0x0b00 +#define EN_IP_ISP1 0x0b04 + +/* +*Registers for CMU_KFC +*/ +#define KFC_PLL_LOCK 0x0000 +#define KFC_PLL_CON0 0x0100 +#define KFC_PLL_CON1 0x0104 +#define KFC_PLL_FDET 0x010c +#define MUX_SEL_KFC0 0x0200 +#define MUX_SEL_KFC2 0x0208 +#define MUX_ENABLE_KFC0 0x0300 +#define MUX_ENABLE_KFC2 0x0308 +#define MUX_STAT_KFC0 0x0400 +#define MUX_STAT_KFC2 0x0408 +#define DIV_KFC 0x0600 +#define DIV_KFC_PLL_FDET 0x0604 +#define DIV_STAT_KFC 0x0700 +#define DIV_STAT_KFC_PLL_FDET 0x0704 +#define EN_ACLK_KFC 0x0800 +#define EN_PCLK_KFC 0x0900 +#define EN_SCLK_KFC 0x0a00 +#define EN_IP_KFC 0x0b00 +#define CLKOUT_CMU_KFC 0x0c00 +#define CLKOUT_CMU_KFC_DIV_STAT 0x0c04 +#define ARMCLK_STOPCTRL_KFC 0x1000 +#define ARM_EMA_CTRL 0x1008 +#define ARM_EMA_STATUS 0x100c +#define PWR_CTRL_KFC 0x1020 +#define PWR_CTRL2_KFC 0x1024 +#define CLKSTOP_CTRL_KFC 0x1028 +#define INTR_SPREAD_ENABLE_KFC 0x1080 +#define INTR_SPREAD_USE_STANDBYWFI_KFC 0x1084 +#define INTR_SPREAD_BLOCKING_DURATION_KFC 0x1088 +#define CMU_KFC_SPARE0 0x2000 +#define CMU_KFC_SPARE1 0x2004 +#define CMU_KFC_SPARE2 0x2008 +#define CMU_KFC_SPARE3 0x200c +#define CMU_KFC_SPARE4 0x2010 + +/* +*Registers for CMU_MFC +*/ +#define MUX_SEL_MFC 0x0200 +#define MUX_ENABLE_MFC 0x0300 +#define MUX_STAT_MFC 0x0400 +#define DIV_MFC 0x0600 +#define DIV_STAT_MFC 0x0700 +#define EN_ACLK_MFC 0x0800 +#define EN_ACLK_SECURE_SMMU2_MFC 0x0804 +#define EN_PCLK_MFC 0x0900 +#define EN_PCLK_SECURE_SMMU2_MFC 0x0904 +#define EN_IP_MFC 0x0b00 +#define EN_IP_MFC_SECURE_SMMU2_MFC 0x0b04 + +/* +*Registers for CMU_MIF +*/ +#define MEM_PLL_LOCK 0x0000 +#define BUS_PLL_LOCK 0x0004 +#define MEDIA_PLL_LOCK 0x0008 +#define MEM_PLL_CON0 0x0100 +#define MEM_PLL_CON1 0x0104 +#define MEM_PLL_FDET 0x010c +#define BUS_PLL_CON0 0x0110 +#define BUS_PLL_CON1 0x0114 +#define BUS_PLL_FDET 0x011c +#define MEDIA_PLL_CON0 0x0120 +#define MEDIA_PLL_CON1 0x0124 +#define MEDIA_PLL_FDET 0x012c +#define MUX_SEL_MIF 0x0200 +#define MUX_ENABLE_MIF 0x0300 +#define MUX_STAT_MIF 0x0400 +#define MUX_IGNORE_MIF 0x0500 +#define DIV_MIF 0x0600 +#define DIV_MIF_PLL_FDET 0x0604 +#define DIV_STAT_MIF 0x0700 +#define DIV_STAT_MIF_PLL_FDET 0x0704 +#define EN_ACLK_MIF 0x0800 +#define EN_ACLK_MIF_SECURE_DREX1_TZ 0x0804 +#define EN_ACLK_MIF_SECURE_DREX0_TZ 0x0808 +#define EN_ACLK_MIF_SECURE_INTMEM 0x080c +#define EN_PCLK_MIF 0x0900 +#define EN_PCLK_MIF_SECURE_MONOCNT 0x0904 +#define EN_PCLK_MIF_SECURE_RTC_APBIF 0x0908 +#define EN_PCLK_MIF_SECURE_DREX1_TZ 0x090c +#define EN_PCLK_MIF_SECURE_DREX0_TZ 0x0910 +#define EN_SCLK_MIF 0x0a00 +#define EN_IP_MIF 0x0b00 +#define EN_IP_MIF_SECURE_MONOCNT 0x0b04 +#define EN_IP_MIF_SECURE_RTC_APBIF 0x0b08 +#define EN_IP_MIF_SECURE_DREX1_TZ 0x0b0c +#define EN_IP_MIF_SECURE_DREX0_TZ 0x0b10 +#define EN_IP_MIF_SECURE_INTEMEM 0x0b14 +#define CLKOUT_CMU_MIF_DIV_STAT 0x0c04 +#define DREX_FREQ_CTRL 0x1000 +#define PAUSE 0x1004 +#define DDRPHY_LOCK_CTRL 0x1008 +#define CLKOUT_CMU_MIF 0xcb00 + +/* +*Registers for CMU_PERI +*/ +#define MUX_SEL_PERI 0x0200 +#define MUX_SEL_PERI1 0x0204 +#define MUX_ENABLE_PERI 0x0300 +#define MUX_ENABLE_PERI1 0x0304 +#define MUX_STAT_PERI 0x0400 +#define MUX_STAT_PERI1 0x0404 +#define MUX_IGNORE_PERI 0x0500 +#define MUX_IGNORE_PERI1 0x0504 +#define DIV_PERI 0x0600 +#define DIV_STAT_PERI 0x0700 +#define EN_PCLK_PERI0 0x0800 +#define EN_PCLK_PERI1 0x0804 +#define EN_PCLK_PERI2 0x0808 +#define EN_PCLK_PERI3 0x080c +#define EN_PCLK_PERI_SECURE_CHIPID 0x0810 +#define EN_PCLK_PERI_SECURE_PROVKEY0 0x0814 +#define EN_PCLK_PERI_SECURE_PROVKEY1 0x0818 +#define EN_PCLK_PERI_SECURE_SECKEY 0x081c +#define EN_PCLK_PERI_SECURE_ANTIRBKCNT 0x0820 +#define EN_PCLK_PERI_SECURE_TOP_RTC 0x0824 +#define EN_PCLK_PERI_SECURE_TZPC 0x0828 +#define EN_SCLK_PERI 0x0a00 +#define EN_SCLK_PERI_SECURE_TOP_RTC 0x0a04 +#define EN_IP_PERI0 0x0b00 +#define EN_IP_PERI1 0x0b04 +#define EN_IP_PERI2 0x0b08 +#define EN_IP_PERI_SECURE_CHIPID 0x0b0c +#define EN_IP_PERI_SECURE_PROVKEY0 0x0b10 +#define EN_IP_PERI_SECURE_PROVKEY1 0x0b14 +#define EN_IP_PERI_SECURE_SECKEY 0x0b18 +#define EN_IP_PERI_SECURE_ANTIRBKCNT 0x0b1c +#define EN_IP_PERI_SECURE_TOP_RTC 0x0b20 +#define EN_IP_PERI_SECURE_TZPC 0x0b24 + +/* +*Registers for CMU_TOP +*/ +#define DISP_PLL_LOCK 0x0000 +#define AUD_PLL_LOCK 0x0004 +#define DISP_PLL_CON0 0x0100 +#define DISP_PLL_CON1 0x0104 +#define DISP_PLL_FDET 0x0108 +#define AUD_PLL_CON0 0x0110 +#define AUD_PLL_CON1 0x0114 +#define AUD_PLL_CON2 0x0118 +#define AUD_PLL_FDET 0x011c +#define MUX_SEL_TOP_PLL0 0x0200 +#define MUX_SEL_TOP_MFC 0x0204 +#define MUX_SEL_TOP_G2D 0x0208 +#define MUX_SEL_TOP_GSCL 0x020c +#define MUX_SEL_TOP_ISP10 0x0214 +#define MUX_SEL_TOP_ISP11 0x0218 +#define MUX_SEL_TOP_DISP0 0x021c +#define MUX_SEL_TOP_DISP1 0x0220 +#define MUX_SEL_TOP_BUS 0x0224 +#define MUX_SEL_TOP_PERI0 0x0228 +#define MUX_SEL_TOP_PERI1 0x022c +#define MUX_SEL_TOP_FSYS 0x0230 +#define MUX_ENABLE_TOP_PLL0 0x0300 +#define MUX_ENABLE_TOP_MFC 0x0304 +#define MUX_ENABLE_TOP_G2D 0x0308 +#define MUX_ENABLE_TOP_GSCL 0x030c +#define MUX_ENABLE_TOP_ISP10 0x0314 +#define MUX_ENABLE_TOP_ISP11 0x0318 +#define MUX_ENABLE_TOP_DISP0 0x031c +#define MUX_ENABLE_TOP_DISP1 0x0320 +#define MUX_ENABLE_TOP_BUS 0x0324 +#define MUX_ENABLE_TOP_PERI0 0x0328 +#define MUX_ENABLE_TOP_PERI1 0x032c +#define MUX_ENABLE_TOP_FSYS 0x0330 +#define MUX_STAT_TOP_PLL0 0x0400 +#define MUX_STAT_TOP_MFC 0x0404 +#define MUX_STAT_TOP_G2D 0x0408 +#define MUX_STAT_TOP_GSCL 0x040c +#define MUX_STAT_TOP_ISP10 0x0414 +#define MUX_STAT_TOP_ISP11 0x0418 +#define MUX_STAT_TOP_DISP0 0x041c +#define MUX_STAT_TOP_DISP1 0x0420 +#define MUX_STAT_TOP_BUS 0x0424 +#define MUX_STAT_TOP_PERI0 0x0428 +#define MUX_STAT_TOP_PERI1 0x042c +#define MUX_STAT_TOP_FSYS 0x0430 +#define MUX_IGNORE_TOP_PLL0 0x0500 +#define MUX_IGNORE_TOP_MFC 0x0504 +#define MUX_IGNORE_TOP_G2D 0x0508 +#define MUX_IGNORE_TOP_GSCL 0x050c +#define MUX_IGNORE_TOP_ISP10 0x0514 +#define MUX_IGNORE_TOP_ISP11 0x0518 +#define MUX_IGNORE_TOP_DISP0 0x051c +#define MUX_IGNORE_TOP_DISP1 0x0520 +#define MUX_IGNORE_TOP_BUS 0x0524 +#define MUX_IGNORE_TOP_PERI0 0x0528 +#define MUX_IGNORE_TOP_PERI1 0x052c +#define MUX_IGNORE_TOP_FSYS 0x0530 +#define DIV_TOP_G2D_MFC 0x0600 +#define DIV_TOP_GSCL_ISP0 0x0604 +#define DIV_TOP_ISP10 0x0608 +#define DIV_TOP_ISP11 0x060c +#define DIV_TOP_DISP 0x0610 +#define DIV_TOP_BUS 0x0614 +#define DIV_TOP_PERI0 0x0618 +#define DIV_TOP_PERI1 0x061c +#define DIV_TOP_PERI2 0x0620 +#define DIV_TOP_FSYS0 0x0624 +#define DIV_TOP_FSYS1 0x0628 +#define DIV_TOP_HPM 0x062c +#define DIV_TOP_PLL_FDET 0x0630 +#define DIV_STAT_TOP_G2D_MFC 0x0700 +#define DIV_STAT_TOP_GSCL_ISP0 0x0704 +#define DIV_STAT_TOP_ISP10 0x0708 +#define DIV_STAT_TOP_ISP11 0x070c +#define DIV_STAT_TOP_DISP 0x0710 +#define DIV_STAT_TOP_BUS 0x0714 +#define DIV_STAT_TOP_PERI0 0x0718 +#define DIV_STAT_TOP_PERI1 0x071c +#define DIV_STAT_TOP_PERI2 0x0720 +#define DIV_STAT_TOP_FSYS0 0x0724 +#define DIV_STAT_TOP_FSYS1 0x0728 +#define DIV_STAT_TOP_HPM 0x072c +#define DIV_STAT_TOP_PLL_FDET 0x0730 +#define EN_ACLK_TOP 0x0800 +#define EN_SCLK_TOP 0x0a00 +#define EN_IP_TOP 0x0b00 +#define CLKOUT_CMU_TOP 0x0c00 +#define CLKOUT_CMU_TOP_DIV_STAT 0x0c04 + +#endif /*__CLK_EXYNOS5260_H */ + diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 60b2681..9d7d7ee 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -27,18 +27,24 @@ #define DIV_CPU1 0x504 #define GATE_BUS_CPU 0x700 #define GATE_SCLK_CPU 0x800 +#define CLKOUT_CMU_CPU 0xa00 +#define GATE_IP_G2D 0x8800 #define CPLL_LOCK 0x10020 #define DPLL_LOCK 0x10030 #define EPLL_LOCK 0x10040 #define RPLL_LOCK 0x10050 #define IPLL_LOCK 0x10060 #define SPLL_LOCK 0x10070 -#define VPLL_LOCK 0x10070 +#define VPLL_LOCK 0x10080 #define MPLL_LOCK 0x10090 #define CPLL_CON0 0x10120 #define DPLL_CON0 0x10128 #define EPLL_CON0 0x10130 +#define EPLL_CON1 0x10134 +#define EPLL_CON2 0x10138 #define RPLL_CON0 0x10140 +#define RPLL_CON1 0x10144 +#define RPLL_CON2 0x10148 #define IPLL_CON0 0x10150 #define SPLL_CON0 0x10160 #define VPLL_CON0 0x10170 @@ -51,21 +57,31 @@ #define SRC_TOP5 0x10214 #define SRC_TOP6 0x10218 #define SRC_TOP7 0x1021c +#define SRC_TOP8 0x10220 /* 5800 specific */ +#define SRC_TOP9 0x10224 /* 5800 specific */ #define SRC_DISP10 0x1022c #define SRC_MAU 0x10240 #define SRC_FSYS 0x10244 #define SRC_PERIC0 0x10250 #define SRC_PERIC1 0x10254 +#define SRC_ISP 0x10270 +#define SRC_CAM 0x10274 /* 5800 specific */ #define SRC_TOP10 0x10280 #define SRC_TOP11 0x10284 #define SRC_TOP12 0x10288 -#define SRC_MASK_DISP10 0x1032c +#define SRC_TOP13 0x1028c /* 5800 specific */ +#define SRC_MASK_TOP2 0x10308 +#define SRC_MASK_TOP7 0x1031c +#define SRC_MASK_DISP10 0x1032c +#define SRC_MASK_MAU 0x10334 #define SRC_MASK_FSYS 0x10340 #define SRC_MASK_PERIC0 0x10350 #define SRC_MASK_PERIC1 0x10354 #define DIV_TOP0 0x10500 #define DIV_TOP1 0x10504 #define DIV_TOP2 0x10508 +#define DIV_TOP8 0x10520 /* 5800 specific */ +#define DIV_TOP9 0x10524 /* 5800 specific */ #define DIV_DISP10 0x1052c #define DIV_MAU 0x10544 #define DIV_FSYS0 0x10548 @@ -76,54 +92,82 @@ #define DIV_PERIC2 0x10560 #define DIV_PERIC3 0x10564 #define DIV_PERIC4 0x10568 +#define DIV_CAM 0x10574 /* 5800 specific */ +#define SCLK_DIV_ISP0 0x10580 +#define SCLK_DIV_ISP1 0x10584 +#define DIV2_RATIO0 0x10590 +#define DIV4_RATIO 0x105a0 #define GATE_BUS_TOP 0x10700 +#define GATE_BUS_GEN 0x1073c #define GATE_BUS_FSYS0 0x10740 +#define GATE_BUS_FSYS2 0x10748 #define GATE_BUS_PERIC 0x10750 #define GATE_BUS_PERIC1 0x10754 #define GATE_BUS_PERIS0 0x10760 #define GATE_BUS_PERIS1 0x10764 +#define GATE_BUS_NOC 0x10770 +#define GATE_TOP_SCLK_ISP 0x10870 #define GATE_IP_GSCL0 0x10910 #define GATE_IP_GSCL1 0x10920 +#define GATE_IP_CAM 0x10924 /* 5800 specific */ #define GATE_IP_MFC 0x1092c #define GATE_IP_DISP1 0x10928 #define GATE_IP_G3D 0x10930 #define GATE_IP_GEN 0x10934 +#define GATE_IP_FSYS 0x10944 +#define GATE_IP_PERIC 0x10950 +#define GATE_IP_PERIS 0x10960 #define GATE_IP_MSCL 0x10970 #define GATE_TOP_SCLK_GSCL 0x10820 #define GATE_TOP_SCLK_DISP1 0x10828 #define GATE_TOP_SCLK_MAU 0x1083c #define GATE_TOP_SCLK_FSYS 0x10840 #define GATE_TOP_SCLK_PERIC 0x10850 +#define TOP_SPARE2 0x10b08 #define BPLL_LOCK 0x20010 #define BPLL_CON0 0x20110 -#define SRC_CDREX 0x20200 #define KPLL_LOCK 0x28000 #define KPLL_CON0 0x28100 #define SRC_KFC 0x28200 #define DIV_KFC0 0x28500 +/* Exynos5x SoC type */ +enum exynos5x_soc { + EXYNOS5420, + EXYNOS5800, +}; + /* list of PLLs */ -enum exynos5420_plls { +enum exynos5x_plls { apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll, bpll, kpll, nr_plls /* number of PLLs */ }; static void __iomem *reg_base; +static enum exynos5x_soc exynos5x_soc; #ifdef CONFIG_PM_SLEEP -static struct samsung_clk_reg_dump *exynos5420_save; +static struct samsung_clk_reg_dump *exynos5x_save; +static struct samsung_clk_reg_dump *exynos5800_save; /* * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static unsigned long exynos5420_clk_regs[] __initdata = { +static unsigned long exynos5x_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, DIV_CPU1, GATE_BUS_CPU, GATE_SCLK_CPU, + CLKOUT_CMU_CPU, + EPLL_CON0, + EPLL_CON1, + EPLL_CON2, + RPLL_CON0, + RPLL_CON1, + RPLL_CON2, SRC_TOP0, SRC_TOP1, SRC_TOP2, @@ -140,10 +184,13 @@ static unsigned long exynos5420_clk_regs[] __initdata = { SRC_TOP10, SRC_TOP11, SRC_TOP12, + SRC_MASK_TOP2, + SRC_MASK_TOP7, SRC_MASK_DISP10, SRC_MASK_FSYS, SRC_MASK_PERIC0, SRC_MASK_PERIC1, + SRC_ISP, DIV_TOP0, DIV_TOP1, DIV_TOP2, @@ -157,41 +204,71 @@ static unsigned long exynos5420_clk_regs[] __initdata = { DIV_PERIC2, DIV_PERIC3, DIV_PERIC4, + SCLK_DIV_ISP0, + SCLK_DIV_ISP1, + DIV2_RATIO0, + DIV4_RATIO, GATE_BUS_TOP, + GATE_BUS_GEN, GATE_BUS_FSYS0, + GATE_BUS_FSYS2, GATE_BUS_PERIC, GATE_BUS_PERIC1, GATE_BUS_PERIS0, GATE_BUS_PERIS1, + GATE_BUS_NOC, + GATE_TOP_SCLK_ISP, GATE_IP_GSCL0, GATE_IP_GSCL1, GATE_IP_MFC, GATE_IP_DISP1, GATE_IP_G3D, GATE_IP_GEN, + GATE_IP_FSYS, + GATE_IP_PERIC, + GATE_IP_PERIS, GATE_IP_MSCL, GATE_TOP_SCLK_GSCL, GATE_TOP_SCLK_DISP1, GATE_TOP_SCLK_MAU, GATE_TOP_SCLK_FSYS, GATE_TOP_SCLK_PERIC, - SRC_CDREX, + TOP_SPARE2, SRC_KFC, DIV_KFC0, }; +static unsigned long exynos5800_clk_regs[] __initdata = { + SRC_TOP8, + SRC_TOP9, + SRC_CAM, + SRC_TOP1, + DIV_TOP8, + DIV_TOP9, + DIV_CAM, + GATE_IP_CAM, +}; + static int exynos5420_clk_suspend(void) { - samsung_clk_save(reg_base, exynos5420_save, - ARRAY_SIZE(exynos5420_clk_regs)); + samsung_clk_save(reg_base, exynos5x_save, + ARRAY_SIZE(exynos5x_clk_regs)); + + if (exynos5x_soc == EXYNOS5800) + samsung_clk_save(reg_base, exynos5800_save, + ARRAY_SIZE(exynos5800_clk_regs)); return 0; } static void exynos5420_clk_resume(void) { - samsung_clk_restore(reg_base, exynos5420_save, - ARRAY_SIZE(exynos5420_clk_regs)); + samsung_clk_restore(reg_base, exynos5x_save, + ARRAY_SIZE(exynos5x_clk_regs)); + + if (exynos5x_soc == EXYNOS5800) + samsung_clk_restore(reg_base, exynos5800_save, + ARRAY_SIZE(exynos5800_clk_regs)); } static struct syscore_ops exynos5420_clk_syscore_ops = { @@ -201,108 +278,183 @@ static struct syscore_ops exynos5420_clk_syscore_ops = { static void exynos5420_clk_sleep_init(void) { - exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs, - ARRAY_SIZE(exynos5420_clk_regs)); - if (!exynos5420_save) { + exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs, + ARRAY_SIZE(exynos5x_clk_regs)); + if (!exynos5x_save) { pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", __func__); return; } + if (exynos5x_soc == EXYNOS5800) { + exynos5800_save = + samsung_clk_alloc_reg_dump(exynos5800_clk_regs, + ARRAY_SIZE(exynos5800_clk_regs)); + if (!exynos5800_save) + goto err_soc; + } + register_syscore_ops(&exynos5420_clk_syscore_ops); + return; +err_soc: + kfree(exynos5x_save); + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; } #else static void exynos5420_clk_sleep_init(void) {} #endif /* list of all parent clocks */ -PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", - "sclk_mpll", "sclk_spll" }; -PNAME(cpu_p) = { "mout_apll" , "mout_mspll_cpu" }; -PNAME(kfc_p) = { "mout_kpll" , "mout_mspll_kfc" }; -PNAME(apll_p) = { "fin_pll", "fout_apll", }; -PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; -PNAME(cpll_p) = { "fin_pll", "fout_cpll", }; -PNAME(dpll_p) = { "fin_pll", "fout_dpll", }; -PNAME(epll_p) = { "fin_pll", "fout_epll", }; -PNAME(ipll_p) = { "fin_pll", "fout_ipll", }; -PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; -PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; -PNAME(rpll_p) = { "fin_pll", "fout_rpll", }; -PNAME(spll_p) = { "fin_pll", "fout_spll", }; -PNAME(vpll_p) = { "fin_pll", "fout_vpll", }; - -PNAME(group1_p) = { "sclk_cpll", "sclk_dpll", "sclk_mpll" }; -PNAME(group2_p) = { "fin_pll", "sclk_cpll", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(group3_p) = { "sclk_rpll", "sclk_spll" }; -PNAME(group4_p) = { "sclk_ipll", "sclk_dpll", "sclk_mpll" }; -PNAME(group5_p) = { "sclk_vpll", "sclk_dpll" }; - -PNAME(sw_aclk66_p) = { "dout_aclk66", "sclk_spll" }; -PNAME(aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66" }; - -PNAME(sw_aclk200_fsys_p) = { "dout_aclk200_fsys", "sclk_spll"}; -PNAME(user_aclk200_fsys_p) = { "fin_pll", "mout_sw_aclk200_fsys" }; - -PNAME(sw_aclk200_fsys2_p) = { "dout_aclk200_fsys2", "sclk_spll"}; -PNAME(user_aclk200_fsys2_p) = { "fin_pll", "mout_sw_aclk200_fsys2" }; - -PNAME(sw_aclk200_p) = { "dout_aclk200", "sclk_spll"}; -PNAME(aclk200_disp1_p) = { "fin_pll", "mout_sw_aclk200" }; - -PNAME(sw_aclk400_mscl_p) = { "dout_aclk400_mscl", "sclk_spll"}; -PNAME(user_aclk400_mscl_p) = { "fin_pll", "mout_sw_aclk400_mscl" }; - -PNAME(sw_aclk333_p) = { "dout_aclk333", "sclk_spll"}; -PNAME(user_aclk333_p) = { "fin_pll", "mout_sw_aclk333" }; - -PNAME(sw_aclk166_p) = { "dout_aclk166", "sclk_spll"}; -PNAME(user_aclk166_p) = { "fin_pll", "mout_sw_aclk166" }; - -PNAME(sw_aclk266_p) = { "dout_aclk266", "sclk_spll"}; -PNAME(user_aclk266_p) = { "fin_pll", "mout_sw_aclk266" }; - -PNAME(sw_aclk333_432_gscl_p) = { "dout_aclk333_432_gscl", "sclk_spll"}; -PNAME(user_aclk333_432_gscl_p) = { "fin_pll", "mout_sw_aclk333_432_gscl" }; - -PNAME(sw_aclk300_gscl_p) = { "dout_aclk300_gscl", "sclk_spll"}; -PNAME(user_aclk300_gscl_p) = { "fin_pll", "mout_sw_aclk300_gscl" }; - -PNAME(sw_aclk300_disp1_p) = { "dout_aclk300_disp1", "sclk_spll"}; -PNAME(user_aclk300_disp1_p) = { "fin_pll", "mout_sw_aclk300_disp1" }; - -PNAME(sw_aclk300_jpeg_p) = { "dout_aclk300_jpeg", "sclk_spll"}; -PNAME(user_aclk300_jpeg_p) = { "fin_pll", "mout_sw_aclk300_jpeg" }; - -PNAME(sw_aclk_g3d_p) = { "dout_aclk_g3d", "sclk_spll"}; -PNAME(user_aclk_g3d_p) = { "fin_pll", "mout_sw_aclk_g3d" }; - -PNAME(sw_aclk266_g2d_p) = { "dout_aclk266_g2d", "sclk_spll"}; -PNAME(user_aclk266_g2d_p) = { "fin_pll", "mout_sw_aclk266_g2d" }; - -PNAME(sw_aclk333_g2d_p) = { "dout_aclk333_g2d", "sclk_spll"}; -PNAME(user_aclk333_g2d_p) = { "fin_pll", "mout_sw_aclk333_g2d" }; - -PNAME(audio0_p) = { "fin_pll", "cdclk0", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(audio1_p) = { "fin_pll", "cdclk1", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2", - "spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" }; -PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; +PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll"}; +PNAME(mout_cpu_p) = {"mout_apll" , "mout_mspll_cpu"}; +PNAME(mout_kfc_p) = {"mout_kpll" , "mout_mspll_kfc"}; +PNAME(mout_apll_p) = {"fin_pll", "fout_apll"}; +PNAME(mout_bpll_p) = {"fin_pll", "fout_bpll"}; +PNAME(mout_cpll_p) = {"fin_pll", "fout_cpll"}; +PNAME(mout_dpll_p) = {"fin_pll", "fout_dpll"}; +PNAME(mout_epll_p) = {"fin_pll", "fout_epll"}; +PNAME(mout_ipll_p) = {"fin_pll", "fout_ipll"}; +PNAME(mout_kpll_p) = {"fin_pll", "fout_kpll"}; +PNAME(mout_mpll_p) = {"fin_pll", "fout_mpll"}; +PNAME(mout_rpll_p) = {"fin_pll", "fout_rpll"}; +PNAME(mout_spll_p) = {"fin_pll", "fout_spll"}; +PNAME(mout_vpll_p) = {"fin_pll", "fout_vpll"}; + +PNAME(mout_group1_p) = {"mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll"}; +PNAME(mout_group2_p) = {"fin_pll", "mout_sclk_cpll", + "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll", + "mout_sclk_ipll", "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_group3_p) = {"mout_sclk_rpll", "mout_sclk_spll"}; +PNAME(mout_group4_p) = {"mout_sclk_ipll", "mout_sclk_dpll", "mout_sclk_mpll"}; +PNAME(mout_group5_p) = {"mout_sclk_vpll", "mout_sclk_dpll"}; + +PNAME(mout_fimd1_final_p) = {"mout_fimd1", "mout_fimd1_opt"}; +PNAME(mout_sw_aclk66_p) = {"dout_aclk66", "mout_sclk_spll"}; +PNAME(mout_user_aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66"}; +PNAME(mout_user_pclk66_gpio_p) = {"mout_sw_aclk66", "ff_sw_aclk66"}; + +PNAME(mout_sw_aclk200_fsys_p) = {"dout_aclk200_fsys", "mout_sclk_spll"}; +PNAME(mout_sw_pclk200_fsys_p) = {"dout_pclk200_fsys", "mout_sclk_spll"}; +PNAME(mout_user_pclk200_fsys_p) = {"fin_pll", "mout_sw_pclk200_fsys"}; +PNAME(mout_user_aclk200_fsys_p) = {"fin_pll", "mout_sw_aclk200_fsys"}; + +PNAME(mout_sw_aclk200_fsys2_p) = {"dout_aclk200_fsys2", "mout_sclk_spll"}; +PNAME(mout_user_aclk200_fsys2_p) = {"fin_pll", "mout_sw_aclk200_fsys2"}; +PNAME(mout_sw_aclk100_noc_p) = {"dout_aclk100_noc", "mout_sclk_spll"}; +PNAME(mout_user_aclk100_noc_p) = {"fin_pll", "mout_sw_aclk100_noc"}; + +PNAME(mout_sw_aclk400_wcore_p) = {"dout_aclk400_wcore", "mout_sclk_spll"}; +PNAME(mout_aclk400_wcore_bpll_p) = {"mout_aclk400_wcore", "sclk_bpll"}; +PNAME(mout_user_aclk400_wcore_p) = {"fin_pll", "mout_sw_aclk400_wcore"}; + +PNAME(mout_sw_aclk400_isp_p) = {"dout_aclk400_isp", "mout_sclk_spll"}; +PNAME(mout_user_aclk400_isp_p) = {"fin_pll", "mout_sw_aclk400_isp"}; + +PNAME(mout_sw_aclk333_432_isp0_p) = {"dout_aclk333_432_isp0", + "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_isp0_p) = {"fin_pll", "mout_sw_aclk333_432_isp0"}; + +PNAME(mout_sw_aclk333_432_isp_p) = {"dout_aclk333_432_isp", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_isp_p) = {"fin_pll", "mout_sw_aclk333_432_isp"}; + +PNAME(mout_sw_aclk200_p) = {"dout_aclk200", "mout_sclk_spll"}; +PNAME(mout_user_aclk200_disp1_p) = {"fin_pll", "mout_sw_aclk200"}; + +PNAME(mout_sw_aclk400_mscl_p) = {"dout_aclk400_mscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk400_mscl_p) = {"fin_pll", "mout_sw_aclk400_mscl"}; + +PNAME(mout_sw_aclk333_p) = {"dout_aclk333", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_p) = {"fin_pll", "mout_sw_aclk333"}; + +PNAME(mout_sw_aclk166_p) = {"dout_aclk166", "mout_sclk_spll"}; +PNAME(mout_user_aclk166_p) = {"fin_pll", "mout_sw_aclk166"}; + +PNAME(mout_sw_aclk266_p) = {"dout_aclk266", "mout_sclk_spll"}; +PNAME(mout_user_aclk266_p) = {"fin_pll", "mout_sw_aclk266"}; +PNAME(mout_user_aclk266_isp_p) = {"fin_pll", "mout_sw_aclk266"}; + +PNAME(mout_sw_aclk333_432_gscl_p) = {"dout_aclk333_432_gscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_gscl_p) = {"fin_pll", "mout_sw_aclk333_432_gscl"}; + +PNAME(mout_sw_aclk300_gscl_p) = {"dout_aclk300_gscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_gscl_p) = {"fin_pll", "mout_sw_aclk300_gscl"}; + +PNAME(mout_sw_aclk300_disp1_p) = {"dout_aclk300_disp1", "mout_sclk_spll"}; +PNAME(mout_sw_aclk400_disp1_p) = {"dout_aclk400_disp1", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_disp1_p) = {"fin_pll", "mout_sw_aclk300_disp1"}; +PNAME(mout_user_aclk400_disp1_p) = {"fin_pll", "mout_sw_aclk400_disp1"}; + +PNAME(mout_sw_aclk300_jpeg_p) = {"dout_aclk300_jpeg", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_jpeg_p) = {"fin_pll", "mout_sw_aclk300_jpeg"}; + +PNAME(mout_sw_aclk_g3d_p) = {"dout_aclk_g3d", "mout_sclk_spll"}; +PNAME(mout_user_aclk_g3d_p) = {"fin_pll", "mout_sw_aclk_g3d"}; + +PNAME(mout_sw_aclk266_g2d_p) = {"dout_aclk266_g2d", "mout_sclk_spll"}; +PNAME(mout_user_aclk266_g2d_p) = {"fin_pll", "mout_sw_aclk266_g2d"}; + +PNAME(mout_sw_aclk333_g2d_p) = {"dout_aclk333_g2d", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_g2d_p) = {"fin_pll", "mout_sw_aclk333_g2d"}; + +PNAME(mout_audio0_p) = {"fin_pll", "cdclk0", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_audio1_p) = {"fin_pll", "cdclk1", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_audio2_p) = {"fin_pll", "cdclk2", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_spdif_p) = {"fin_pll", "dout_audio0", "dout_audio1", + "dout_audio2", "spdif_extclk", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_hdmi_p) = {"dout_hdmi_pixel", "sclk_hdmiphy"}; +PNAME(mout_maudio0_p) = {"fin_pll", "maudio_clk", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_mau_epll_clk_p) = {"mout_sclk_epll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll"}; +/* 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", + "mout_sclk_mpll", "ff_dout_spll2" }; +PNAME(mout_group2_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2", + "mout_epll2", "mout_sclk_ipll" }; +PNAME(mout_group3_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2", + "mout_epll2" }; +PNAME(mout_group5_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll" }; +PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2" }; +PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", + "mout_epll2", "mout_sclk_ipll" }; +PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll", + "mout_sclk_mpll", + "ff_dout_spll2" }; +PNAME(mout_group8_5800_p) = { "dout_aclk432_scaler", "dout_sclk_sw" }; +PNAME(mout_group9_5800_p) = { "dout_osc_div", "mout_sw_aclk432_scaler" }; +PNAME(mout_group10_5800_p) = { "dout_aclk432_cam", "dout_sclk_sw" }; +PNAME(mout_group11_5800_p) = { "dout_osc_div", "mout_sw_aclk432_cam" }; +PNAME(mout_group12_5800_p) = { "dout_aclkfl1_550_cam", "dout_sclk_sw" }; +PNAME(mout_group13_5800_p) = { "dout_osc_div", "mout_sw_aclkfl1_550_cam" }; +PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" }; +PNAME(mout_group15_5800_p) = { "dout_osc_div", "mout_sw_aclk550_cam" }; /* fixed rate clocks generated outside the soc */ -static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock + exynos5x_fixed_rate_ext_clks[] __initdata = { FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000), @@ -310,146 +462,309 @@ static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = FRATE(0, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000), }; -static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { - FFACTOR(0, "sclk_hsic_12m", "fin_pll", 1, 2, 0), +static struct samsung_fixed_factor_clock + exynos5x_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0), + FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0), }; -static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { - MUX(0, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2), - MUX(0, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2), - MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1), - MUX(0, "mout_cpu", cpu_p, SRC_CPU, 16, 1), - MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1), - MUX(0, "mout_cpu_kfc", kfc_p, SRC_KFC, 16, 1), - - MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), - - MUX_A(0, "mout_aclk400_mscl", group1_p, - SRC_TOP0, 4, 2, "aclk400_mscl"), - MUX(0, "mout_aclk200", group1_p, SRC_TOP0, 8, 2), - MUX(0, "mout_aclk200_fsys2", group1_p, SRC_TOP0, 12, 2), - MUX(0, "mout_aclk200_fsys", group1_p, SRC_TOP0, 28, 2), - - MUX(0, "mout_aclk333_432_gscl", group4_p, SRC_TOP1, 0, 2), - MUX(0, "mout_aclk66", group1_p, SRC_TOP1, 8, 2), - MUX(0, "mout_aclk266", group1_p, SRC_TOP1, 20, 2), - MUX(0, "mout_aclk166", group1_p, SRC_TOP1, 24, 2), - MUX(0, "mout_aclk333", group1_p, SRC_TOP1, 28, 2), - - MUX(0, "mout_aclk333_g2d", group1_p, SRC_TOP2, 8, 2), - MUX(0, "mout_aclk266_g2d", group1_p, SRC_TOP2, 12, 2), - MUX(0, "mout_aclk_g3d", group5_p, SRC_TOP2, 16, 1), - MUX(0, "mout_aclk300_jpeg", group1_p, SRC_TOP2, 20, 2), - MUX(0, "mout_aclk300_disp1", group1_p, SRC_TOP2, 24, 2), - MUX(0, "mout_aclk300_gscl", group1_p, SRC_TOP2, 28, 2), - - MUX(0, "mout_user_aclk400_mscl", user_aclk400_mscl_p, +static struct samsung_fixed_factor_clock + exynos5800_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0), + FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0), +}; + +struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { + MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3), + MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3), + MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3), + MUX(0, "mout_aclk100_noc", mout_group1_5800_p, SRC_TOP0, 20, 2), + + MUX(0, "mout_aclk333_432_gscl", mout_group6_5800_p, SRC_TOP1, 0, 2), + MUX(0, "mout_aclk333_432_isp", mout_group6_5800_p, SRC_TOP1, 4, 2), + MUX(0, "mout_aclk333_432_isp0", mout_group6_5800_p, SRC_TOP1, 12, 2), + MUX(0, "mout_aclk266", mout_group5_5800_p, SRC_TOP1, 20, 2), + MUX(0, "mout_aclk333", mout_group1_5800_p, SRC_TOP1, 28, 2), + + MUX(0, "mout_aclk400_disp1", mout_group7_5800_p, SRC_TOP2, 4, 3), + MUX(0, "mout_aclk333_g2d", mout_group5_5800_p, SRC_TOP2, 8, 2), + MUX(0, "mout_aclk266_g2d", mout_group5_5800_p, SRC_TOP2, 12, 2), + MUX(0, "mout_aclk300_jpeg", mout_group5_5800_p, SRC_TOP2, 20, 2), + 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(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), + MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1), + + MUX(0, "mout_aclk550_cam", mout_group3_5800_p, SRC_TOP8, 16, 3), + MUX(0, "mout_aclkfl1_550_cam", mout_group3_5800_p, SRC_TOP8, 20, 3), + MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2), + MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2), + + MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p, + SRC_TOP9, 16, 1), + MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p, + SRC_TOP9, 20, 1), + MUX(0, "mout_user_aclk432_cam", mout_group11_5800_p, + SRC_TOP9, 24, 1), + MUX(0, "mout_user_aclk432_scaler", mout_group9_5800_p, + SRC_TOP9, 28, 1), + + MUX(0, "mout_sw_aclk550_cam", mout_group14_5800_p, SRC_TOP13, 16, 1), + MUX(0, "mout_sw_aclkfl1_550_cam", mout_group12_5800_p, + SRC_TOP13, 20, 1), + MUX(0, "mout_sw_aclk432_cam", mout_group10_5800_p, + SRC_TOP13, 24, 1), + MUX(0, "mout_sw_aclk432_scaler", mout_group8_5800_p, + SRC_TOP13, 28, 1), + + MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3), +}; + +struct samsung_div_clock exynos5800_div_clks[] __initdata = { + DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3), + + DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", + DIV_TOP8, 16, 3), + DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", + DIV_TOP8, 20, 3), + DIV(0, "dout_aclk432_cam", "mout_aclk432_cam", + DIV_TOP8, 24, 3), + DIV(0, "dout_aclk432_scaler", "mout_aclk432_scaler", + DIV_TOP8, 28, 3), + + DIV(0, "dout_osc_div", "fin_pll", DIV_TOP9, 20, 3), + DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6), +}; + +struct samsung_gate_clock exynos5800_gate_clks[] __initdata = { + GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam", + GATE_BUS_TOP, 24, 0, 0), + GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", + GATE_BUS_TOP, 27, 0, 0), +}; + +struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { + MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1), + MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p, + TOP_SPARE2, 4, 1), + + MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2), + MUX_A(0, "mout_aclk400_mscl", mout_group1_p, + SRC_TOP0, 4, 2, "aclk400_mscl"), + MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2), + MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2), + + MUX(0, "mout_aclk333_432_gscl", mout_group4_p, SRC_TOP1, 0, 2), + MUX(0, "mout_aclk333_432_isp", mout_group4_p, + SRC_TOP1, 4, 2), + MUX(0, "mout_aclk333_432_isp0", mout_group4_p, SRC_TOP1, 12, 2), + MUX(0, "mout_aclk266", mout_group1_p, SRC_TOP1, 20, 2), + MUX(0, "mout_aclk333", mout_group1_p, SRC_TOP1, 28, 2), + + MUX(0, "mout_aclk400_disp1", mout_group1_p, SRC_TOP2, 4, 2), + MUX(0, "mout_aclk333_g2d", mout_group1_p, SRC_TOP2, 8, 2), + MUX(0, "mout_aclk266_g2d", mout_group1_p, SRC_TOP2, 12, 2), + MUX(0, "mout_aclk300_jpeg", mout_group1_p, SRC_TOP2, 20, 2), + 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(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), +}; + +struct samsung_div_clock exynos5420_div_clks[] __initdata = { + DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", + DIV_TOP0, 16, 3), +}; + +static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { + MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, + SRC_TOP7, 4, 1), + MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2), + MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2), + + MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1), + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), + MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1), + MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1), + + MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2), + MUX(0, "mout_aclk200_fsys2", mout_group1_p, SRC_TOP0, 12, 2), + MUX(0, "mout_pclk200_fsys", mout_group1_p, SRC_TOP0, 24, 2), + MUX(0, "mout_aclk200_fsys", mout_group1_p, SRC_TOP0, 28, 2), + + MUX(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2), + MUX(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2), + + MUX(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1), + + MUX(0, "mout_user_aclk400_isp", mout_user_aclk400_isp_p, + SRC_TOP3, 0, 1), + MUX(0, "mout_user_aclk400_mscl", mout_user_aclk400_mscl_p, SRC_TOP3, 4, 1), - MUX_A(0, "mout_aclk200_disp1", aclk200_disp1_p, - SRC_TOP3, 8, 1, "aclk200_disp1"), - MUX(0, "mout_user_aclk200_fsys2", user_aclk200_fsys2_p, + MUX(0, "mout_user_aclk200_disp1", mout_user_aclk200_disp1_p, + SRC_TOP3, 8, 1), + MUX(0, "mout_user_aclk200_fsys2", mout_user_aclk200_fsys2_p, SRC_TOP3, 12, 1), - MUX(0, "mout_user_aclk200_fsys", user_aclk200_fsys_p, + MUX(0, "mout_user_aclk400_wcore", mout_user_aclk400_wcore_p, + SRC_TOP3, 16, 1), + MUX(0, "mout_user_aclk100_noc", mout_user_aclk100_noc_p, + SRC_TOP3, 20, 1), + MUX(0, "mout_user_pclk200_fsys", mout_user_pclk200_fsys_p, + SRC_TOP3, 24, 1), + MUX(0, "mout_user_aclk200_fsys", mout_user_aclk200_fsys_p, SRC_TOP3, 28, 1), - MUX(0, "mout_user_aclk333_432_gscl", user_aclk333_432_gscl_p, + MUX(0, "mout_user_aclk333_432_gscl", mout_user_aclk333_432_gscl_p, SRC_TOP4, 0, 1), - MUX(0, "mout_aclk66_peric", aclk66_peric_p, SRC_TOP4, 8, 1), - MUX(0, "mout_user_aclk266", user_aclk266_p, SRC_TOP4, 20, 1), - MUX(0, "mout_user_aclk166", user_aclk166_p, SRC_TOP4, 24, 1), - MUX(0, "mout_user_aclk333", user_aclk333_p, SRC_TOP4, 28, 1), - - MUX(0, "mout_aclk66_psgen", aclk66_peric_p, SRC_TOP5, 4, 1), - MUX(0, "mout_user_aclk333_g2d", user_aclk333_g2d_p, SRC_TOP5, 8, 1), - MUX(0, "mout_user_aclk266_g2d", user_aclk266_g2d_p, SRC_TOP5, 12, 1), - MUX_A(0, "mout_user_aclk_g3d", user_aclk_g3d_p, - SRC_TOP5, 16, 1, "aclkg3d"), - MUX(0, "mout_user_aclk300_jpeg", user_aclk300_jpeg_p, + MUX(0, "mout_user_aclk333_432_isp", mout_user_aclk333_432_isp_p, + SRC_TOP4, 4, 1), + MUX(0, "mout_user_aclk66_peric", mout_user_aclk66_peric_p, + SRC_TOP4, 8, 1), + MUX(0, "mout_user_aclk333_432_isp0", mout_user_aclk333_432_isp0_p, + SRC_TOP4, 12, 1), + MUX(0, "mout_user_aclk266_isp", mout_user_aclk266_isp_p, + SRC_TOP4, 16, 1), + MUX(0, "mout_user_aclk266", mout_user_aclk266_p, SRC_TOP4, 20, 1), + MUX(0, "mout_user_aclk166", mout_user_aclk166_p, SRC_TOP4, 24, 1), + MUX(0, "mout_user_aclk333", mout_user_aclk333_p, SRC_TOP4, 28, 1), + + MUX(0, "mout_user_aclk400_disp1", mout_user_aclk400_disp1_p, + SRC_TOP5, 0, 1), + MUX(0, "mout_user_aclk66_psgen", mout_user_aclk66_peric_p, + SRC_TOP5, 4, 1), + MUX(0, "mout_user_aclk333_g2d", mout_user_aclk333_g2d_p, + SRC_TOP5, 8, 1), + MUX(0, "mout_user_aclk266_g2d", mout_user_aclk266_g2d_p, + SRC_TOP5, 12, 1), + MUX(CLK_MOUT_G3D, "mout_user_aclk_g3d", mout_user_aclk_g3d_p, + SRC_TOP5, 16, 1), + MUX(0, "mout_user_aclk300_jpeg", mout_user_aclk300_jpeg_p, SRC_TOP5, 20, 1), - MUX(0, "mout_user_aclk300_disp1", user_aclk300_disp1_p, + MUX(0, "mout_user_aclk300_disp1", mout_user_aclk300_disp1_p, SRC_TOP5, 24, 1), - MUX(0, "mout_user_aclk300_gscl", user_aclk300_gscl_p, + MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p, SRC_TOP5, 28, 1), - MUX(0, "sclk_mpll", mpll_p, SRC_TOP6, 0, 1), - MUX(0, "sclk_vpll", vpll_p, SRC_TOP6, 4, 1), - MUX(0, "sclk_spll", spll_p, SRC_TOP6, 8, 1), - MUX(0, "sclk_ipll", ipll_p, SRC_TOP6, 12, 1), - MUX(0, "sclk_rpll", rpll_p, SRC_TOP6, 16, 1), - MUX(0, "sclk_epll", epll_p, SRC_TOP6, 20, 1), - MUX(0, "sclk_dpll", dpll_p, SRC_TOP6, 24, 1), - MUX(0, "sclk_cpll", cpll_p, SRC_TOP6, 28, 1), - - MUX(0, "mout_sw_aclk400_mscl", sw_aclk400_mscl_p, SRC_TOP10, 4, 1), - MUX(0, "mout_sw_aclk200", sw_aclk200_p, SRC_TOP10, 8, 1), - MUX(0, "mout_sw_aclk200_fsys2", sw_aclk200_fsys2_p, + MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1), + MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1), + MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1), + MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1), + MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1), + MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1), + MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1), + MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1), + + MUX(0, "mout_sw_aclk400_isp", mout_sw_aclk400_isp_p, + SRC_TOP10, 0, 1), + MUX(0, "mout_sw_aclk400_mscl", mout_sw_aclk400_mscl_p, + SRC_TOP10, 4, 1), + MUX(0, "mout_sw_aclk200", mout_sw_aclk200_p, SRC_TOP10, 8, 1), + MUX(0, "mout_sw_aclk200_fsys2", mout_sw_aclk200_fsys2_p, SRC_TOP10, 12, 1), - MUX(0, "mout_sw_aclk200_fsys", sw_aclk200_fsys_p, SRC_TOP10, 28, 1), - - MUX(0, "mout_sw_aclk333_432_gscl", sw_aclk333_432_gscl_p, + MUX(0, "mout_sw_aclk400_wcore", mout_sw_aclk400_wcore_p, + SRC_TOP10, 16, 1), + MUX(0, "mout_sw_aclk100_noc", mout_sw_aclk100_noc_p, + SRC_TOP10, 20, 1), + MUX(0, "mout_sw_pclk200_fsys", mout_sw_pclk200_fsys_p, + SRC_TOP10, 24, 1), + MUX(0, "mout_sw_aclk200_fsys", mout_sw_aclk200_fsys_p, + SRC_TOP10, 28, 1), + + MUX(0, "mout_sw_aclk333_432_gscl", mout_sw_aclk333_432_gscl_p, SRC_TOP11, 0, 1), - MUX(0, "mout_sw_aclk66", sw_aclk66_p, SRC_TOP11, 8, 1), - MUX(0, "mout_sw_aclk266", sw_aclk266_p, SRC_TOP11, 20, 1), - MUX(0, "mout_sw_aclk166", sw_aclk166_p, SRC_TOP11, 24, 1), - MUX(0, "mout_sw_aclk333", sw_aclk333_p, SRC_TOP11, 28, 1), - - MUX(0, "mout_sw_aclk333_g2d", sw_aclk333_g2d_p, SRC_TOP12, 8, 1), - MUX(0, "mout_sw_aclk266_g2d", sw_aclk266_g2d_p, SRC_TOP12, 12, 1), - MUX(0, "mout_sw_aclk_g3d", sw_aclk_g3d_p, SRC_TOP12, 16, 1), - MUX(0, "mout_sw_aclk300_jpeg", sw_aclk300_jpeg_p, SRC_TOP12, 20, 1), - MUX(0, "mout_sw_aclk300_disp1", sw_aclk300_disp1_p, + MUX(0, "mout_sw_aclk333_432_isp", mout_sw_aclk333_432_isp_p, + SRC_TOP11, 4, 1), + MUX(0, "mout_sw_aclk66", mout_sw_aclk66_p, SRC_TOP11, 8, 1), + MUX(0, "mout_sw_aclk333_432_isp0", mout_sw_aclk333_432_isp0_p, + SRC_TOP11, 12, 1), + MUX(0, "mout_sw_aclk266", mout_sw_aclk266_p, SRC_TOP11, 20, 1), + MUX(0, "mout_sw_aclk166", mout_sw_aclk166_p, SRC_TOP11, 24, 1), + MUX(0, "mout_sw_aclk333", mout_sw_aclk333_p, SRC_TOP11, 28, 1), + + MUX(0, "mout_sw_aclk400_disp1", mout_sw_aclk400_disp1_p, + SRC_TOP12, 4, 1), + MUX(0, "mout_sw_aclk333_g2d", mout_sw_aclk333_g2d_p, + SRC_TOP12, 8, 1), + MUX(0, "mout_sw_aclk266_g2d", mout_sw_aclk266_g2d_p, + SRC_TOP12, 12, 1), + MUX(0, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, SRC_TOP12, 16, 1), + MUX(0, "mout_sw_aclk300_jpeg", mout_sw_aclk300_jpeg_p, + SRC_TOP12, 20, 1), + MUX(0, "mout_sw_aclk300_disp1", mout_sw_aclk300_disp1_p, SRC_TOP12, 24, 1), - MUX(0, "mout_sw_aclk300_gscl", sw_aclk300_gscl_p, SRC_TOP12, 28, 1), + MUX(0, "mout_sw_aclk300_gscl", mout_sw_aclk300_gscl_p, + SRC_TOP12, 28, 1), /* DISP1 Block */ - MUX(0, "mout_fimd1", group3_p, SRC_DISP10, 4, 1), - MUX(0, "mout_mipi1", group2_p, SRC_DISP10, 16, 3), - MUX(0, "mout_dp1", group2_p, SRC_DISP10, 20, 3), - MUX(0, "mout_pixel", group2_p, SRC_DISP10, 24, 3), - MUX(CLK_MOUT_HDMI, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1), + MUX(0, "mout_mipi1", mout_group2_p, SRC_DISP10, 16, 3), + MUX(0, "mout_dp1", mout_group2_p, SRC_DISP10, 20, 3), + MUX(0, "mout_pixel", mout_group2_p, SRC_DISP10, 24, 3), + MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP10, 28, 1), + MUX(0, "mout_fimd1_opt", mout_group2_p, SRC_DISP10, 8, 3), + + MUX(0, "mout_fimd1_final", mout_fimd1_final_p, TOP_SPARE2, 8, 1), /* MAU Block */ - MUX(0, "mout_maudio0", maudio0_p, SRC_MAU, 28, 3), + MUX(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3), /* FSYS Block */ - MUX(0, "mout_usbd301", group2_p, SRC_FSYS, 4, 3), - MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 8, 3), - MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 12, 3), - MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 16, 3), - MUX(0, "mout_usbd300", group2_p, SRC_FSYS, 20, 3), - MUX(0, "mout_unipro", group2_p, SRC_FSYS, 24, 3), + MUX(0, "mout_usbd301", mout_group2_p, SRC_FSYS, 4, 3), + MUX(0, "mout_mmc0", mout_group2_p, SRC_FSYS, 8, 3), + MUX(0, "mout_mmc1", mout_group2_p, SRC_FSYS, 12, 3), + MUX(0, "mout_mmc2", mout_group2_p, SRC_FSYS, 16, 3), + MUX(0, "mout_usbd300", mout_group2_p, SRC_FSYS, 20, 3), + MUX(0, "mout_unipro", mout_group2_p, SRC_FSYS, 24, 3), + MUX(0, "mout_mphy_refclk", mout_group2_p, SRC_FSYS, 28, 3), /* PERIC Block */ - MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 4, 3), - MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 8, 3), - MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 12, 3), - MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 16, 3), - MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 3), - MUX(0, "mout_spdif", spdif_p, SRC_PERIC0, 28, 3), - MUX(0, "mout_audio0", audio0_p, SRC_PERIC1, 8, 3), - MUX(0, "mout_audio1", audio1_p, SRC_PERIC1, 12, 3), - MUX(0, "mout_audio2", audio2_p, SRC_PERIC1, 16, 3), - MUX(0, "mout_spi0", group2_p, SRC_PERIC1, 20, 3), - MUX(0, "mout_spi1", group2_p, SRC_PERIC1, 24, 3), - MUX(0, "mout_spi2", group2_p, SRC_PERIC1, 28, 3), + MUX(0, "mout_uart0", mout_group2_p, SRC_PERIC0, 4, 3), + MUX(0, "mout_uart1", mout_group2_p, SRC_PERIC0, 8, 3), + MUX(0, "mout_uart2", mout_group2_p, SRC_PERIC0, 12, 3), + MUX(0, "mout_uart3", mout_group2_p, SRC_PERIC0, 16, 3), + MUX(0, "mout_pwm", mout_group2_p, SRC_PERIC0, 24, 3), + MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIC0, 28, 3), + MUX(0, "mout_audio0", mout_audio0_p, SRC_PERIC1, 8, 3), + MUX(0, "mout_audio1", mout_audio1_p, SRC_PERIC1, 12, 3), + MUX(0, "mout_audio2", mout_audio2_p, SRC_PERIC1, 16, 3), + MUX(0, "mout_spi0", mout_group2_p, SRC_PERIC1, 20, 3), + MUX(0, "mout_spi1", mout_group2_p, SRC_PERIC1, 24, 3), + MUX(0, "mout_spi2", mout_group2_p, SRC_PERIC1, 28, 3), + + /* ISP Block */ + MUX(0, "mout_pwm_isp", mout_group2_p, SRC_ISP, 24, 3), + MUX(0, "mout_uart_isp", mout_group2_p, SRC_ISP, 20, 3), + MUX(0, "mout_spi0_isp", mout_group2_p, SRC_ISP, 12, 3), + MUX(0, "mout_spi1_isp", mout_group2_p, SRC_ISP, 16, 3), + MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3), }; -static struct samsung_div_clock exynos5420_div_clks[] __initdata = { +static struct samsung_div_clock exynos5x_div_clks[] __initdata = { DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3), - DIV(0, "div_kfc", "mout_cpu_kfc", DIV_KFC0, 0, 3), + DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), + DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3), DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3), DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3), DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3), + DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3), DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3), DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3), DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl", DIV_TOP1, 0, 3), + DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp", + DIV_TOP1, 4, 3), DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6), + DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0", + DIV_TOP1, 16, 3), DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3), DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3), DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3), @@ -458,15 +773,16 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3), DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3), DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3), - DIV_A(0, "dout_aclk300_disp1", "mout_aclk300_disp1", - DIV_TOP2, 24, 3, "aclk300_disp1"), + DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3), DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3), /* DISP1 Block */ - DIV(0, "dout_fimd1", "mout_fimd1", DIV_DISP10, 0, 4), + DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4), DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8), DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), + DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), + DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), /* Audio Block */ DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), @@ -484,6 +800,7 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_mmc2", "mout_mmc2", DIV_FSYS1, 20, 10), DIV(0, "dout_unipro", "mout_unipro", DIV_FSYS2, 24, 8), + DIV(0, "dout_mphy_refclk", "mout_mphy_refclk", DIV_FSYS2, 16, 8), /* UART and PWM */ DIV(0, "dout_uart0", "mout_uart0", DIV_PERIC0, 8, 4), @@ -497,6 +814,9 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4), DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4), + /* Mfc Block */ + DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2), + /* PCM */ DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8), DIV(0, "dout_pcm2", "dout_audio2", DIV_PERIC2, 24, 8), @@ -509,15 +829,43 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4), /* SPI Pre-Ratio */ - DIV(0, "dout_pre_spi0", "dout_spi0", DIV_PERIC4, 8, 8), - DIV(0, "dout_pre_spi1", "dout_spi1", DIV_PERIC4, 16, 8), - DIV(0, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8), + DIV(0, "dout_spi0_pre", "dout_spi0", DIV_PERIC4, 8, 8), + DIV(0, "dout_spi1_pre", "dout_spi1", DIV_PERIC4, 16, 8), + DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8), + + /* GSCL Block */ + DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl", + DIV2_RATIO0, 4, 2), + DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2), + + /* MSCL Block */ + DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2), + + /* PSGEN */ + DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1), + DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1), + + /* ISP Block */ + DIV(0, "dout_isp_sensor0", "mout_isp_sensor", SCLK_DIV_ISP0, 8, 8), + DIV(0, "dout_isp_sensor1", "mout_isp_sensor", SCLK_DIV_ISP0, 16, 8), + DIV(0, "dout_isp_sensor2", "mout_isp_sensor", SCLK_DIV_ISP0, 24, 8), + DIV(0, "dout_pwm_isp", "mout_pwm_isp", SCLK_DIV_ISP1, 28, 4), + DIV(0, "dout_uart_isp", "mout_uart_isp", SCLK_DIV_ISP1, 24, 4), + DIV(0, "dout_spi0_isp", "mout_spi0_isp", SCLK_DIV_ISP1, 16, 4), + DIV(0, "dout_spi1_isp", "mout_spi1_isp", SCLK_DIV_ISP1, 20, 4), + DIV_F(0, "dout_spi0_isp_pre", "dout_spi0_isp", SCLK_DIV_ISP1, 0, 8, + CLK_SET_RATE_PARENT, 0), + DIV_F(0, "dout_spi1_isp_pre", "dout_spi1_isp", SCLK_DIV_ISP1, 8, 8, + CLK_SET_RATE_PARENT, 0), }; -static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { - /* TODO: Re-verify the CG bits for all the gate clocks */ - GATE_A(CLK_MCT, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, - "mct"), +static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { + /* G2D */ + GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0), + GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0), + GATE(CLK_G2D, "g2d", "aclk333_g2d", GATE_IP_G2D, 3, 0, 0), + GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "aclk266_g2d", GATE_IP_G2D, 5, 0, 0), + GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk333_g2d", GATE_IP_G2D, 7, 0, 0), GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys", GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0), @@ -530,20 +878,42 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg", GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0", + GATE_BUS_TOP, 5, 0, 0), GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl", GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl", GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0), - GATE(0, "pclk66_gpio", "mout_sw_aclk66", + GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp", + GATE_BUS_TOP, 8, 0, 0), + GATE(CLK_PCLK66_GPIO, "pclk66_gpio", "mout_user_pclk66_gpio", GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0), - GATE(0, "aclk66_psgen", "mout_aclk66_psgen", + GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen", GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0), - GATE(0, "aclk66_peric", "mout_aclk66_peric", - GATE_BUS_TOP, 11, 0, 0), + GATE(CLK_ACLK66_PERIC, "aclk66_peric", "mout_user_aclk66_peric", + GATE_BUS_TOP, 11, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk266_isp", "mout_user_aclk266_isp", + GATE_BUS_TOP, 13, 0, 0), GATE(0, "aclk166", "mout_user_aclk166", GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333", "mout_aclk333", GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk400_isp", "mout_user_aclk400_isp", + GATE_BUS_TOP, 16, 0, 0), + GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl", + GATE_BUS_TOP, 17, 0, 0), + GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1", + GATE_BUS_TOP, 18, 0, 0), + GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24", + GATE_BUS_TOP, 28, 0, 0), + GATE(CLK_SCLK_HSIC_12M, "sclk_hsic_12m", "ff_hsic_12m", + GATE_BUS_TOP, 29, 0, 0), + + GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1", + SRC_MASK_TOP2, 24, 0, 0), + + GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", + SRC_MASK_TOP7, 20, 0, 0), /* sclk */ GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", @@ -554,11 +924,11 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE_TOP_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_uart3", GATE_TOP_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_pre_spi0", + GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_spi0_pre", GATE_TOP_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_pre_spi1", + GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_spi1_pre", GATE_TOP_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_pre_spi2", + GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_spi2_pre", GATE_TOP_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", GATE_TOP_SCLK_PERIC, 9, CLK_SET_RATE_PARENT, 0), @@ -588,164 +958,191 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301", GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_USBD301, "sclk_unipro", "dout_unipro", - SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), - - GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "aclK333_432_gscl", - GATE_TOP_SCLK_GSCL, 6, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "aclk333_432_gscl", - GATE_TOP_SCLK_GSCL, 7, CLK_SET_RATE_PARENT, 0), - /* Display */ GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "dout_fimd1", - GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "dout_mipi1", - GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", - GATE_TOP_SCLK_DISP1, 9, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 9, 0, 0), GATE(CLK_SCLK_PIXEL, "sclk_pixel", "dout_hdmi_pixel", - GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1", - GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), /* Maudio Block */ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0", GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0", GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0), - /* FSYS */ + + /* FSYS Block */ GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0), GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0), GATE(CLK_PDMA1, "pdma1", "aclk200_fsys", GATE_BUS_FSYS0, 2, 0, 0), GATE(CLK_UFS, "ufs", "aclk200_fsys2", GATE_BUS_FSYS0, 3, 0, 0), - GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_BUS_FSYS0, 5, 0, 0), - GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_BUS_FSYS0, 12, 0, 0), - GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_BUS_FSYS0, 13, 0, 0), - GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_BUS_FSYS0, 14, 0, 0), + GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_IP_FSYS, 9, 0, 0), + GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_IP_FSYS, 12, 0, 0), + GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_IP_FSYS, 13, 0, 0), + GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_IP_FSYS, 14, 0, 0), GATE(CLK_SROMC, "sromc", "aclk200_fsys2", - GATE_BUS_FSYS0, 19, CLK_IGNORE_UNUSED, 0), - GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_BUS_FSYS0, 20, 0, 0), - GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_BUS_FSYS0, 21, 0, 0), - GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_BUS_FSYS0, 28, 0, 0), - - /* UART */ - GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_BUS_PERIC, 4, 0, 0), - GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_BUS_PERIC, 5, 0, 0), - GATE_A(CLK_UART2, "uart2", "aclk66_peric", - GATE_BUS_PERIC, 6, CLK_IGNORE_UNUSED, 0, "uart2"), - GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_BUS_PERIC, 7, 0, 0), - /* I2C */ - GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_BUS_PERIC, 9, 0, 0), - GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_BUS_PERIC, 10, 0, 0), - GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_BUS_PERIC, 11, 0, 0), - GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_BUS_PERIC, 12, 0, 0), - GATE(CLK_I2C4, "i2c4", "aclk66_peric", GATE_BUS_PERIC, 13, 0, 0), - GATE(CLK_I2C5, "i2c5", "aclk66_peric", GATE_BUS_PERIC, 14, 0, 0), - GATE(CLK_I2C6, "i2c6", "aclk66_peric", GATE_BUS_PERIC, 15, 0, 0), - GATE(CLK_I2C7, "i2c7", "aclk66_peric", GATE_BUS_PERIC, 16, 0, 0), - GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_BUS_PERIC, 17, 0, - 0), - GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_BUS_PERIC, 18, 0, 0), - /* SPI */ - GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_BUS_PERIC, 19, 0, 0), - GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_BUS_PERIC, 20, 0, 0), - GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_BUS_PERIC, 21, 0, 0), - GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0), - /* I2S */ - GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_BUS_PERIC, 23, 0, 0), - GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_BUS_PERIC, 24, 0, 0), - /* PCM */ - GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_BUS_PERIC, 25, 0, 0), - GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_BUS_PERIC, 26, 0, 0), - /* PWM */ - GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_BUS_PERIC, 27, 0, 0), - /* SPDIF */ - GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_BUS_PERIC, 29, 0, 0), + GATE_IP_FSYS, 17, CLK_IGNORE_UNUSED, 0), + GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0), + GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0), + GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0), + GATE(CLK_SCLK_UNIPRO, "sclk_unipro", "dout_unipro", + SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), - GATE(CLK_I2C8, "i2c8", "aclk66_peric", GATE_BUS_PERIC1, 0, 0, 0), - GATE(CLK_I2C9, "i2c9", "aclk66_peric", GATE_BUS_PERIC1, 1, 0, 0), - GATE(CLK_I2C10, "i2c10", "aclk66_peric", GATE_BUS_PERIC1, 2, 0, 0), + /* PERIC Block */ + GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_IP_PERIC, 0, 0, 0), + GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_IP_PERIC, 1, 0, 0), + GATE(CLK_UART2, "uart2", "aclk66_peric", GATE_IP_PERIC, 2, 0, 0), + GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_IP_PERIC, 3, 0, 0), + GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_IP_PERIC, 6, 0, 0), + GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_IP_PERIC, 7, 0, 0), + GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_IP_PERIC, 8, 0, 0), + GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_IP_PERIC, 9, 0, 0), + GATE(CLK_USI0, "usi0", "aclk66_peric", GATE_IP_PERIC, 10, 0, 0), + GATE(CLK_USI1, "usi1", "aclk66_peric", GATE_IP_PERIC, 11, 0, 0), + GATE(CLK_USI2, "usi2", "aclk66_peric", GATE_IP_PERIC, 12, 0, 0), + GATE(CLK_USI3, "usi3", "aclk66_peric", GATE_IP_PERIC, 13, 0, 0), + GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_IP_PERIC, 14, 0, 0), + GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_IP_PERIC, 15, 0, 0), + GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_IP_PERIC, 16, 0, 0), + GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_IP_PERIC, 17, 0, 0), + GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_IP_PERIC, 18, 0, 0), + GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_IP_PERIC, 20, 0, 0), + GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_IP_PERIC, 21, 0, 0), + GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_IP_PERIC, 22, 0, 0), + GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_IP_PERIC, 23, 0, 0), + GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_IP_PERIC, 24, 0, 0), + GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_IP_PERIC, 26, 0, 0), + GATE(CLK_USI4, "usi4", "aclk66_peric", GATE_IP_PERIC, 28, 0, 0), + GATE(CLK_USI5, "usi5", "aclk66_peric", GATE_IP_PERIC, 30, 0, 0), + GATE(CLK_USI6, "usi6", "aclk66_peric", GATE_IP_PERIC, 31, 0, 0), + GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0), + + /* PERIS Block */ GATE(CLK_CHIPID, "chipid", "aclk66_psgen", - GATE_BUS_PERIS0, 12, CLK_IGNORE_UNUSED, 0), + GATE_IP_PERIS, 0, CLK_IGNORE_UNUSED, 0), GATE(CLK_SYSREG, "sysreg", "aclk66_psgen", - GATE_BUS_PERIS0, 13, CLK_IGNORE_UNUSED, 0), - GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_BUS_PERIS0, 18, 0, 0), - GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_BUS_PERIS0, 19, 0, 0), - GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_BUS_PERIS0, 20, 0, 0), - GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_BUS_PERIS0, 21, 0, 0), - GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_BUS_PERIS0, 22, 0, 0), - GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_BUS_PERIS0, 23, 0, 0), - GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_BUS_PERIS0, 24, 0, 0), - GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_BUS_PERIS0, 25, 0, 0), - GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_BUS_PERIS0, 26, 0, 0), - GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_BUS_PERIS0, 27, 0, 0), - - GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_BUS_PERIS1, 0, 0, - 0), + GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_IP_PERIS, 6, 0, 0), + GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_IP_PERIS, 7, 0, 0), + GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_IP_PERIS, 8, 0, 0), + GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_IP_PERIS, 9, 0, 0), + GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_IP_PERIS, 10, 0, 0), + GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_IP_PERIS, 11, 0, 0), + GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_IP_PERIS, 12, 0, 0), + GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_IP_PERIS, 13, 0, 0), + GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_IP_PERIS, 14, 0, 0), + GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_IP_PERIS, 15, 0, 0), + GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_IP_PERIS, 16, 0, 0), + GATE(CLK_MCT, "mct", "aclk66_psgen", GATE_IP_PERIS, 18, 0, 0), + GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_IP_PERIS, 19, 0, 0), + GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_IP_PERIS, 20, 0, 0), + GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_IP_PERIS, 21, 0, 0), + GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_IP_PERIS, 22, 0, 0), + GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0), - GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_BUS_PERIS1, 3, 0, 0), - GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_BUS_PERIS1, 4, 0, 0), - GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_BUS_PERIS1, 5, 0, 0), - GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_BUS_PERIS1, 6, 0, 0), + + /* GEN Block */ + GATE(CLK_ROTATOR, "rotator", "mout_user_aclk266", GATE_IP_GEN, 1, 0, 0), + GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0), + GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0), + GATE(CLK_MDMA1, "mdma1", "mout_user_aclk266", GATE_IP_GEN, 4, 0, 0), + GATE(CLK_TOP_RTC, "top_rtc", "aclk66_psgen", GATE_IP_GEN, 5, 0, 0), + GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "dout_gen_blk", + GATE_IP_GEN, 6, 0, 0), + GATE(CLK_SMMU_JPEG, "smmu_jpeg", "dout_jpg_blk", GATE_IP_GEN, 7, 0, 0), + GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "dout_gen_blk", + GATE_IP_GEN, 9, 0, 0), + + /* GATE_IP_GEN doesn't list gates for smmu_jpeg2 and mc */ + GATE(CLK_SMMU_JPEG2, "smmu_jpeg2", "dout_jpg_blk", + GATE_BUS_GEN, 28, 0, 0), + GATE(CLK_MC, "mc", "aclk66_psgen", GATE_BUS_GEN, 12, 0, 0), + + /* GSCL Block */ + GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "mout_user_aclk333_432_gscl", + GATE_TOP_SCLK_GSCL, 6, 0, 0), + GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl", + GATE_TOP_SCLK_GSCL, 7, 0, 0), GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0), GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0), - GATE(CLK_CLK_3AA, "clk_3aa", "aclk300_gscl", GATE_IP_GSCL0, 4, 0, 0), - - GATE(CLK_SMMU_3AA, "smmu_3aa", "aclk333_432_gscl", GATE_IP_GSCL1, 2, 0, - 0), - GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "aclk333_432_gscl", + GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl", + GATE_IP_GSCL0, 4, 0, 0), + GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl", + GATE_IP_GSCL0, 5, 0, 0), + GATE(CLK_FIMC_LITE1, "fimc_lite1", "aclk333_432_gscl", + GATE_IP_GSCL0, 6, 0, 0), + + GATE(CLK_SMMU_3AA, "smmu_3aa", "dout_gscl_blk_333", + GATE_IP_GSCL1, 2, 0, 0), + GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "dout_gscl_blk_333", GATE_IP_GSCL1, 3, 0, 0), - GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "aclk333_432_gscl", + GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333", GATE_IP_GSCL1, 4, 0, 0), - GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "aclk300_gscl", GATE_IP_GSCL1, 6, 0, - 0), - GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "aclk300_gscl", GATE_IP_GSCL1, 7, 0, - 0), - GATE(CLK_GSCL_WA, "gscl_wa", "aclk300_gscl", GATE_IP_GSCL1, 12, 0, 0), - GATE(CLK_GSCL_WB, "gscl_wb", "aclk300_gscl", GATE_IP_GSCL1, 13, 0, 0), - GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "aclk333_432_gscl", + GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300", + GATE_IP_GSCL1, 6, 0, 0), + GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300", + GATE_IP_GSCL1, 7, 0, 0), + GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0), + GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0), + GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333", GATE_IP_GSCL1, 16, 0, 0), GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl", GATE_IP_GSCL1, 17, 0, 0), + /* MSCL Block */ + GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0), + GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0), + GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0), + GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk", + GATE_IP_MSCL, 8, 0, 0), + GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk", + GATE_IP_MSCL, 9, 0, 0), + GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk", + GATE_IP_MSCL, 10, 0, 0), + GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0), GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0), GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0), - GATE(CLK_MIXER, "mixer", "aclk166", GATE_IP_DISP1, 5, 0, 0), + GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0), GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), - GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "aclk300_disp1", GATE_IP_DISP1, 8, 0, - 0), + GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk", + GATE_IP_DISP1, 7, 0, 0), + GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk", + GATE_IP_DISP1, 8, 0, 0), + GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", + GATE_IP_DISP1, 9, 0, 0), + + /* ISP */ + GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp", + GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "dout_spi0_isp_pre", + GATE_TOP_SCLK_ISP, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "dout_spi1_isp_pre", + GATE_TOP_SCLK_ISP, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_PWM_ISP, "sclk_pwm_isp", "dout_pwm_isp", + GATE_TOP_SCLK_ISP, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR0, "sclk_isp_sensor0", "dout_isp_sensor0", + GATE_TOP_SCLK_ISP, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR1, "sclk_isp_sensor1", "dout_isp_sensor1", + GATE_TOP_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2", + GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0), - GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0), - GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0), - - GATE(CLK_G3D, "g3d", "aclkg3d", GATE_IP_G3D, 9, 0, 0), + GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0), + GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0), - GATE(CLK_ROTATOR, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0), - GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0), - GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0), - GATE(CLK_MDMA1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0), - GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0), - GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk300_jpeg", GATE_IP_GEN, 7, 0, 0), - GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0), - - GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0), - GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0), - GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0), - GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "aclk400_mscl", GATE_IP_MSCL, 8, 0, - 0), - GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "aclk400_mscl", GATE_IP_MSCL, 9, 0, - 0), - GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, - 0), - GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", GATE_IP_DISP1, 9, 0, - 0), + GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), }; -static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { +static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = { [apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_2550, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, @@ -776,8 +1173,11 @@ static struct of_device_id ext_clk_match[] __initdata = { }; /* register exynos5420 clocks */ -static void __init exynos5420_clk_init(struct device_node *np) +static void __init exynos5x_clk_init(struct device_node *np, + enum exynos5x_soc soc) { + struct samsung_clk_provider *ctx; + if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -786,23 +1186,56 @@ static void __init exynos5420_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, - ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), + exynos5x_soc = soc; + + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks, + ARRAY_SIZE(exynos5x_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), + samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls), reg_base); - samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, - ARRAY_SIZE(exynos5420_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, - ARRAY_SIZE(exynos5420_fixed_factor_clks)); - samsung_clk_register_mux(exynos5420_mux_clks, - ARRAY_SIZE(exynos5420_mux_clks)); - samsung_clk_register_div(exynos5420_div_clks, - ARRAY_SIZE(exynos5420_div_clks)); - samsung_clk_register_gate(exynos5420_gate_clks, - ARRAY_SIZE(exynos5420_gate_clks)); + samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks, + ARRAY_SIZE(exynos5x_fixed_rate_clks)); + samsung_clk_register_fixed_factor(ctx, exynos5x_fixed_factor_clks, + ARRAY_SIZE(exynos5x_fixed_factor_clks)); + samsung_clk_register_mux(ctx, exynos5x_mux_clks, + ARRAY_SIZE(exynos5x_mux_clks)); + samsung_clk_register_div(ctx, exynos5x_div_clks, + ARRAY_SIZE(exynos5x_div_clks)); + samsung_clk_register_gate(ctx, exynos5x_gate_clks, + ARRAY_SIZE(exynos5x_gate_clks)); + + if (soc == EXYNOS5420) { + samsung_clk_register_mux(ctx, exynos5420_mux_clks, + ARRAY_SIZE(exynos5420_mux_clks)); + samsung_clk_register_div(ctx, exynos5420_div_clks, + ARRAY_SIZE(exynos5420_div_clks)); + } else { + samsung_clk_register_fixed_factor( + ctx, exynos5800_fixed_factor_clks, + ARRAY_SIZE(exynos5800_fixed_factor_clks)); + samsung_clk_register_mux(ctx, exynos5800_mux_clks, + ARRAY_SIZE(exynos5800_mux_clks)); + samsung_clk_register_div(ctx, exynos5800_div_clks, + ARRAY_SIZE(exynos5800_div_clks)); + samsung_clk_register_gate(ctx, exynos5800_gate_clks, + ARRAY_SIZE(exynos5800_gate_clks)); + } exynos5420_clk_sleep_init(); } + +static void __init exynos5420_clk_init(struct device_node *np) +{ + exynos5x_clk_init(np, EXYNOS5420); +} CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); + +static void __init exynos5800_clk_init(struct device_node *np) +{ + exynos5x_clk_init(np, EXYNOS5800); +} +CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init); diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 2bfad5a..647f144 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -93,6 +93,7 @@ static struct of_device_id ext_clk_match[] __initdata = { static void __init exynos5440_clk_init(struct device_node *np) { void __iomem *reg_base; + struct samsung_clk_provider *ctx; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -101,22 +102,25 @@ static void __init exynos5440_clk_init(struct device_node *np) return; } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + 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_fixed_rate(exynos5440_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks, ARRAY_SIZE(exynos5440_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks, + samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks, ARRAY_SIZE(exynos5440_fixed_factor_clks)); - samsung_clk_register_mux(exynos5440_mux_clks, + samsung_clk_register_mux(ctx, exynos5440_mux_clks, ARRAY_SIZE(exynos5440_mux_clks)); - samsung_clk_register_div(exynos5440_div_clks, + samsung_clk_register_div(ctx, exynos5440_div_clks, ARRAY_SIZE(exynos5440_div_clks)); - samsung_clk_register_gate(exynos5440_gate_clks, + samsung_clk_register_gate(ctx, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 81e6d2f..b07fad2 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -11,6 +11,7 @@ #include <linux/errno.h> #include <linux/hrtimer.h> +#include <linux/delay.h> #include "clk.h" #include "clk-pll.h" @@ -59,6 +60,72 @@ static long samsung_pll_round_rate(struct clk_hw *hw, } /* + * PLL2126 Clock Type + */ + +#define PLL2126_MDIV_MASK (0xff) +#define PLL2126_PDIV_MASK (0x3f) +#define PLL2126_SDIV_MASK (0x3) +#define PLL2126_MDIV_SHIFT (16) +#define PLL2126_PDIV_SHIFT (8) +#define PLL2126_SDIV_SHIFT (0) + +static unsigned long samsung_pll2126_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL2126_MDIV_SHIFT) & PLL2126_MDIV_MASK; + pdiv = (pll_con >> PLL2126_PDIV_SHIFT) & PLL2126_PDIV_MASK; + sdiv = (pll_con >> PLL2126_SDIV_SHIFT) & PLL2126_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll2126_clk_ops = { + .recalc_rate = samsung_pll2126_recalc_rate, +}; + +/* + * PLL3000 Clock Type + */ + +#define PLL3000_MDIV_MASK (0xff) +#define PLL3000_PDIV_MASK (0x3) +#define PLL3000_SDIV_MASK (0x3) +#define PLL3000_MDIV_SHIFT (16) +#define PLL3000_PDIV_SHIFT (8) +#define PLL3000_SDIV_SHIFT (0) + +static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL3000_MDIV_SHIFT) & PLL3000_MDIV_MASK; + pdiv = (pll_con >> PLL3000_PDIV_SHIFT) & PLL3000_PDIV_MASK; + sdiv = (pll_con >> PLL3000_SDIV_SHIFT) & PLL3000_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, pdiv << sdiv); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll3000_clk_ops = { + .recalc_rate = samsung_pll3000_recalc_rate, +}; + +/* * PLL35xx Clock Type */ /* Maximum lock time can be 270 * PDIV cycles */ @@ -564,7 +631,9 @@ static const struct clk_ops samsung_pll46xx_clk_min_ops = { #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 #define PLL6552_MDIV_SHIFT 16 +#define PLL6552_MDIV_SHIFT_2416 14 #define PLL6552_PDIV_SHIFT 8 +#define PLL6552_PDIV_SHIFT_2416 5 #define PLL6552_SDIV_SHIFT 0 static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, @@ -575,8 +644,13 @@ static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, u64 fvco = parent_rate; pll_con = __raw_readl(pll->con_reg); - mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; - pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + if (pll->type == pll_6552_s3c2416) { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT_2416) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT_2416) & PLL6552_PDIV_MASK; + } else { + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + } sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; fvco *= mdiv; @@ -628,6 +702,169 @@ static const struct clk_ops samsung_pll6553_clk_ops = { }; /* + * PLL Clock Type of S3C24XX before S3C2443 + */ + +#define PLLS3C2410_MDIV_MASK (0xff) +#define PLLS3C2410_PDIV_MASK (0x1f) +#define PLLS3C2410_SDIV_MASK (0x3) +#define PLLS3C2410_MDIV_SHIFT (12) +#define PLLS3C2410_PDIV_SHIFT (4) +#define PLLS3C2410_SDIV_SHIFT (0) + +#define PLLS3C2410_ENABLE_REG_OFFSET 0x10 + +static unsigned long samsung_s3c2410_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (mdiv + 8); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static unsigned long samsung_s3c2440_mpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_con, mdiv, pdiv, sdiv; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLLS3C2410_MDIV_SHIFT) & PLLS3C2410_MDIV_MASK; + pdiv = (pll_con >> PLLS3C2410_PDIV_SHIFT) & PLLS3C2410_PDIV_MASK; + sdiv = (pll_con >> PLLS3C2410_SDIV_SHIFT) & PLLS3C2410_SDIV_MASK; + + fvco *= (2 * (mdiv + 8)); + do_div(fvco, (pdiv + 2) << sdiv); + + return (unsigned int)fvco; +} + +static int samsung_s3c2410_pll_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 tmp; + + /* 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_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLLS3C2410_MDIV_MASK << PLLS3C2410_MDIV_SHIFT) | + (PLLS3C2410_PDIV_MASK << PLLS3C2410_PDIV_SHIFT) | + (PLLS3C2410_SDIV_MASK << PLLS3C2410_SDIV_SHIFT)); + tmp |= (rate->mdiv << PLLS3C2410_MDIV_SHIFT) | + (rate->pdiv << PLLS3C2410_PDIV_SHIFT) | + (rate->sdiv << PLLS3C2410_SDIV_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* Time to settle according to the manual */ + udelay(300); + + return 0; +} + +static int samsung_s3c2410_pll_enable(struct clk_hw *hw, int bit, bool enable) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 pll_en = __raw_readl(pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + u32 pll_en_orig = pll_en; + + if (enable) + pll_en &= ~BIT(bit); + else + pll_en |= BIT(bit); + + __raw_writel(pll_en, pll->lock_reg + PLLS3C2410_ENABLE_REG_OFFSET); + + /* if we started the UPLL, then allow to settle */ + if (enable && (pll_en_orig & BIT(bit))) + udelay(300); + + return 0; +} + +static int samsung_s3c2410_mpll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 5, true); +} + +static void samsung_s3c2410_mpll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 5, false); +} + +static int samsung_s3c2410_upll_enable(struct clk_hw *hw) +{ + return samsung_s3c2410_pll_enable(hw, 7, true); +} + +static void samsung_s3c2410_upll_disable(struct clk_hw *hw) +{ + samsung_s3c2410_pll_enable(hw, 7, false); +} + +static const struct clk_ops samsung_s3c2410_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_min_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_min_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, +}; + +static const struct clk_ops samsung_s3c2410_mpll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2410_upll_clk_ops = { + .recalc_rate = samsung_s3c2410_pll_recalc_rate, + .enable = samsung_s3c2410_upll_enable, + .disable = samsung_s3c2410_upll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +static const struct clk_ops samsung_s3c2440_mpll_clk_ops = { + .recalc_rate = samsung_s3c2440_mpll_recalc_rate, + .enable = samsung_s3c2410_mpll_enable, + .disable = samsung_s3c2410_mpll_disable, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_s3c2410_pll_set_rate, +}; + +/* * PLL2550x Clock Type */ @@ -710,8 +947,206 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, return clk; } -static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, - void __iomem *base) +/* + * PLL2550xx Clock Type + */ + +/* Maximum lock time can be 270 * PDIV cycles */ +#define PLL2550XX_LOCK_FACTOR 270 + +#define PLL2550XX_M_MASK 0x3FF +#define PLL2550XX_P_MASK 0x3F +#define PLL2550XX_S_MASK 0x7 +#define PLL2550XX_LOCK_STAT_MASK 0x1 +#define PLL2550XX_M_SHIFT 9 +#define PLL2550XX_P_SHIFT 3 +#define PLL2550XX_S_SHIFT 0 +#define PLL2550XX_LOCK_STAT_SHIFT 21 + +static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; + pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; + sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con) +{ + u32 old_mdiv, old_pdiv; + + old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; + old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; + + return mdiv != old_mdiv || pdiv != old_pdiv; +} + +static int samsung_pll2550xx_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 tmp; + + /* 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_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) { + /* If only s change, change just s value only*/ + tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT); + tmp |= rate->sdiv << PLL2550XX_S_SHIFT; + __raw_writel(tmp, pll->con_reg); + + return 0; + } + + /* Set PLL lock time. */ + __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) | + (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) | + (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT)); + tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) | + (rate->pdiv << PLL2550XX_P_SHIFT) | + (rate->sdiv << PLL2550XX_S_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK + << PLL2550XX_LOCK_STAT_SHIFT))); + + return 0; +} + +static const struct clk_ops samsung_pll2550xx_clk_ops = { + .recalc_rate = samsung_pll2550xx_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll2550xx_set_rate, +}; + +static const struct clk_ops samsung_pll2550xx_clk_min_ops = { + .recalc_rate = samsung_pll2550xx_recalc_rate, +}; + +/* + * PLL2650XX Clock Type + */ + +/* Maximum lock time can be 3000 * PDIV cycles */ +#define PLL2650XX_LOCK_FACTOR 3000 + +#define PLL2650XX_MDIV_SHIFT 9 +#define PLL2650XX_PDIV_SHIFT 3 +#define PLL2650XX_SDIV_SHIFT 0 +#define PLL2650XX_KDIV_SHIFT 0 +#define PLL2650XX_MDIV_MASK 0x1ff +#define PLL2650XX_PDIV_MASK 0x3f +#define PLL2650XX_SDIV_MASK 0x7 +#define PLL2650XX_KDIV_MASK 0xffff +#define PLL2650XX_PLL_ENABLE_SHIFT 23 +#define PLL2650XX_PLL_LOCKTIME_SHIFT 21 +#define PLL2650XX_PLL_FOUTMASK_SHIFT 31 + +static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con0, pll_con2; + s16 kdiv; + u64 fvco = parent_rate; + + pll_con0 = __raw_readl(pll->con_reg); + pll_con2 = __raw_readl(pll->con_reg + 8); + mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK; + pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK; + sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK; + kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK); + + fvco *= (mdiv << 16) + kdiv; + do_div(fvco, (pdiv << sdiv)); + fvco >>= 16; + + return (unsigned long)fvco; +} + +static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp, pll_con0, pll_con2; + const struct samsung_pll_rate_table *rate; + + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + pll_con0 = __raw_readl(pll->con_reg); + pll_con2 = __raw_readl(pll->con_reg + 8); + + /* Change PLL PMS values */ + pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT | + PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT | + PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT); + pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT; + pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT; + pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT; + pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT; + pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT; + + pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT); + pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK) + << PLL2650XX_KDIV_SHIFT; + + /* Set PLL lock time. */ + __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg); + + __raw_writel(pll_con0, pll->con_reg); + __raw_writel(pll_con2, pll->con_reg + 8); + + do { + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); + + return 0; +} + +static const struct clk_ops samsung_pll2650xx_clk_ops = { + .recalc_rate = samsung_pll2650xx_recalc_rate, + .set_rate = samsung_pll2650xx_set_rate, + .round_rate = samsung_pll_round_rate, +}; + +static const struct clk_ops samsung_pll2650xx_clk_min_ops = { + .recalc_rate = samsung_pll2650xx_recalc_rate, +}; + +static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_clk, + void __iomem *base) { struct samsung_clk_pll *pll; struct clk *clk; @@ -746,6 +1181,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, } switch (pll_clk->type) { + case pll_2126: + init.ops = &samsung_pll2126_clk_ops; + break; + case pll_3000: + init.ops = &samsung_pll3000_clk_ops; + break; /* clk_ops for 35xx and 2550 are similar */ case pll_35xx: case pll_2550: @@ -773,6 +1214,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, init.ops = &samsung_pll36xx_clk_ops; break; case pll_6552: + case pll_6552_s3c2416: init.ops = &samsung_pll6552_clk_ops; break; case pll_6553: @@ -786,6 +1228,36 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_pll46xx_clk_ops; break; + case pll_s3c2410_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2410_mpll_clk_ops; + break; + case pll_s3c2410_upll: + if (!pll->rate_table) + init.ops = &samsung_s3c2410_upll_clk_min_ops; + else + init.ops = &samsung_s3c2410_upll_clk_ops; + break; + case pll_s3c2440_mpll: + if (!pll->rate_table) + init.ops = &samsung_s3c2440_mpll_clk_min_ops; + else + init.ops = &samsung_s3c2440_mpll_clk_ops; + break; + case pll_2550xx: + if (!pll->rate_table) + init.ops = &samsung_pll2550xx_clk_min_ops; + else + init.ops = &samsung_pll2550xx_clk_ops; + break; + case pll_2650xx: + if (!pll->rate_table) + init.ops = &samsung_pll2650xx_clk_min_ops; + else + init.ops = &samsung_pll2650xx_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); @@ -804,7 +1276,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, return; } - samsung_clk_add_lookup(clk, pll_clk->id); + samsung_clk_add_lookup(ctx, clk, pll_clk->id); if (!pll_clk->alias) return; @@ -815,11 +1287,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, __func__, pll_clk->name, ret); } -void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_pll, void __iomem *base) +void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_list, + unsigned int nr_pll, void __iomem *base) { int cnt; for (cnt = 0; cnt < nr_pll; cnt++) - _samsung_clk_register_pll(&pll_list[cnt], base); + _samsung_clk_register_pll(ctx, &pll_list[cnt], base); } diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6c39030..c0ed4d4 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -13,6 +13,8 @@ #define __SAMSUNG_CLK_PLL_H enum samsung_pll_type { + pll_2126, + pll_3000, pll_35xx, pll_36xx, pll_2550, @@ -24,7 +26,13 @@ enum samsung_pll_type { pll_4650, pll_4650c, pll_6552, + pll_6552_s3c2416, pll_6553, + pll_s3c2410_mpll, + pll_s3c2410_upll, + pll_s3c2440_mpll, + pll_2550xx, + pll_2650xx, }; #define PLL_35XX_RATE(_rate, _m, _p, _s) \ diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c new file mode 100644 index 0000000..8d8dff0 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410-dclk.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de> + * + * 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 s3c24xx external clock output. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include "clk.h" + +/* legacy access to misccr, until dt conversion is finished */ +#include <mach/hardware.h> +#include <mach/regs-gpio.h> + +#define MUX_DCLK0 0 +#define MUX_DCLK1 1 +#define DIV_DCLK0 2 +#define DIV_DCLK1 3 +#define GATE_DCLK0 4 +#define GATE_DCLK1 5 +#define MUX_CLKOUT0 6 +#define MUX_CLKOUT1 7 +#define DCLK_MAX_CLKS (MUX_CLKOUT1 + 1) + +enum supported_socs { + S3C2410, + S3C2412, + S3C2440, + S3C2443, +}; + +struct s3c24xx_dclk_drv_data { + const char **clkout0_parent_names; + int clkout0_num_parents; + const char **clkout1_parent_names; + int clkout1_num_parents; + const char **mux_parent_names; + int mux_num_parents; +}; + +/* + * Clock for output-parent selection in misccr + */ + +struct s3c24xx_clkout { + struct clk_hw hw; + u32 mask; + u8 shift; +}; + +#define to_s3c24xx_clkout(_hw) container_of(_hw, struct s3c24xx_clkout, hw) + +static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int num_parents = __clk_get_num_parents(hw->clk); + u32 val; + + val = readl_relaxed(S3C24XX_MISCCR) >> clkout->shift; + val >>= clkout->shift; + val &= clkout->mask; + + if (val >= num_parents) + return -EINVAL; + + return val; +} + +static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index) +{ + struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw); + int ret = 0; + + s3c2410_modify_misccr((clkout->mask << clkout->shift), + (index << clkout->shift)); + + return ret; +} + +const struct clk_ops s3c24xx_clkout_ops = { + .get_parent = s3c24xx_clkout_get_parent, + .set_parent = s3c24xx_clkout_set_parent, + .determine_rate = __clk_mux_determine_rate, +}; + +struct clk *s3c24xx_register_clkout(struct device *dev, const char *name, + const char **parent_names, u8 num_parents, + u8 shift, u32 mask) +{ + struct s3c24xx_clkout *clkout; + struct clk *clk; + struct clk_init_data init; + + /* allocate the clkout */ + clkout = kzalloc(sizeof(*clkout), GFP_KERNEL); + if (!clkout) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &s3c24xx_clkout_ops; + init.flags = CLK_IS_BASIC; + init.parent_names = parent_names; + init.num_parents = num_parents; + + clkout->shift = shift; + clkout->mask = mask; + clkout->hw.init = &init; + + clk = clk_register(dev, &clkout->hw); + + return clk; +} + +/* + * dclk and clkout init + */ + +struct s3c24xx_dclk { + struct device *dev; + void __iomem *base; + struct clk_onecell_data clk_data; + struct notifier_block dclk0_div_change_nb; + struct notifier_block dclk1_div_change_nb; + spinlock_t dclk_lock; + unsigned long reg_save; +}; + +#define to_s3c24xx_dclk0(x) \ + container_of(x, struct s3c24xx_dclk, dclk0_div_change_nb) + +#define to_s3c24xx_dclk1(x) \ + container_of(x, struct s3c24xx_dclk, dclk1_div_change_nb) + +PNAME(dclk_s3c2410_p) = { "pclk", "uclk" }; +PNAME(clkout0_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2410_p) = { "mpll", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2412_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk0" }; +PNAME(clkout1_s3c2412_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk1" }; + +PNAME(clkout0_s3c2440_p) = { "xti", "upll", "fclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2440_p) = { "mpll", "upll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +PNAME(dclk_s3c2443_p) = { "pclk", "epll" }; +PNAME(clkout0_s3c2443_p) = { "xti", "epll", "armclk", "hclk", "pclk", + "gate_dclk0" }; +PNAME(clkout1_s3c2443_p) = { "dummy", "epll", "rtc_clkout", + "hclk", "pclk", "gate_dclk1" }; + +#define DCLKCON_DCLK_DIV_MASK 0xf +#define DCLKCON_DCLK0_DIV_SHIFT 4 +#define DCLKCON_DCLK0_CMP_SHIFT 8 +#define DCLKCON_DCLK1_DIV_SHIFT 20 +#define DCLKCON_DCLK1_CMP_SHIFT 24 + +static void s3c24xx_dclk_update_cmp(struct s3c24xx_dclk *s3c24xx_dclk, + int div_shift, int cmp_shift) +{ + unsigned long flags = 0; + u32 dclk_con, div, cmp; + + spin_lock_irqsave(&s3c24xx_dclk->dclk_lock, flags); + + dclk_con = readl_relaxed(s3c24xx_dclk->base); + + div = ((dclk_con >> div_shift) & DCLKCON_DCLK_DIV_MASK) + 1; + cmp = ((div + 1) / 2) - 1; + + dclk_con &= ~(DCLKCON_DCLK_DIV_MASK << cmp_shift); + dclk_con |= (cmp << cmp_shift); + + writel_relaxed(dclk_con, s3c24xx_dclk->base); + + spin_unlock_irqrestore(&s3c24xx_dclk->dclk_lock, flags); +} + +static int s3c24xx_dclk0_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk0(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK0_DIV_SHIFT, DCLKCON_DCLK0_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +static int s3c24xx_dclk1_div_notify(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct s3c24xx_dclk *s3c24xx_dclk = to_s3c24xx_dclk1(nb); + + if (event == POST_RATE_CHANGE) { + s3c24xx_dclk_update_cmp(s3c24xx_dclk, + DCLKCON_DCLK1_DIV_SHIFT, DCLKCON_DCLK1_CMP_SHIFT); + } + + return NOTIFY_DONE; +} + +#ifdef CONFIG_PM_SLEEP +static int s3c24xx_dclk_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + s3c24xx_dclk->reg_save = readl_relaxed(s3c24xx_dclk->base); + return 0; +} + +static int s3c24xx_dclk_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + + writel_relaxed(s3c24xx_dclk->reg_save, s3c24xx_dclk->base); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(s3c24xx_dclk_pm_ops, + s3c24xx_dclk_suspend, s3c24xx_dclk_resume); + +static int s3c24xx_dclk_probe(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk; + struct resource *mem; + struct clk **clk_table; + struct s3c24xx_dclk_drv_data *dclk_variant; + int ret, i; + + s3c24xx_dclk = devm_kzalloc(&pdev->dev, sizeof(*s3c24xx_dclk), + GFP_KERNEL); + if (!s3c24xx_dclk) + return -ENOMEM; + + s3c24xx_dclk->dev = &pdev->dev; + platform_set_drvdata(pdev, s3c24xx_dclk); + spin_lock_init(&s3c24xx_dclk->dclk_lock); + + clk_table = devm_kzalloc(&pdev->dev, + sizeof(struct clk *) * DCLK_MAX_CLKS, + GFP_KERNEL); + if (!clk_table) + return -ENOMEM; + + s3c24xx_dclk->clk_data.clks = clk_table; + s3c24xx_dclk->clk_data.clk_num = DCLK_MAX_CLKS; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + s3c24xx_dclk->base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(s3c24xx_dclk->base)) + return PTR_ERR(s3c24xx_dclk->base); + + dclk_variant = (struct s3c24xx_dclk_drv_data *) + platform_get_device_id(pdev)->driver_data; + + + clk_table[MUX_DCLK0] = clk_register_mux(&pdev->dev, "mux_dclk0", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 1, 1, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[MUX_DCLK1] = clk_register_mux(&pdev->dev, "mux_dclk1", + dclk_variant->mux_parent_names, + dclk_variant->mux_num_parents, 0, + s3c24xx_dclk->base, 17, 1, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[DIV_DCLK0] = clk_register_divider(&pdev->dev, "div_dclk0", + "mux_dclk0", 0, s3c24xx_dclk->base, + 4, 4, 0, &s3c24xx_dclk->dclk_lock); + clk_table[DIV_DCLK1] = clk_register_divider(&pdev->dev, "div_dclk1", + "mux_dclk1", 0, s3c24xx_dclk->base, + 20, 4, 0, &s3c24xx_dclk->dclk_lock); + + clk_table[GATE_DCLK0] = clk_register_gate(&pdev->dev, "gate_dclk0", + "div_dclk0", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 0, 0, + &s3c24xx_dclk->dclk_lock); + clk_table[GATE_DCLK1] = clk_register_gate(&pdev->dev, "gate_dclk1", + "div_dclk1", CLK_SET_RATE_PARENT, + s3c24xx_dclk->base, 16, 0, + &s3c24xx_dclk->dclk_lock); + + clk_table[MUX_CLKOUT0] = s3c24xx_register_clkout(&pdev->dev, + "clkout0", dclk_variant->clkout0_parent_names, + dclk_variant->clkout0_num_parents, 4, 7); + clk_table[MUX_CLKOUT1] = s3c24xx_register_clkout(&pdev->dev, + "clkout1", dclk_variant->clkout1_parent_names, + dclk_variant->clkout1_num_parents, 8, 7); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (IS_ERR(clk_table[i])) { + dev_err(&pdev->dev, "clock %d failed to register\n", i); + ret = PTR_ERR(clk_table[i]); + goto err_clk_register; + } + + ret = clk_register_clkdev(clk_table[MUX_DCLK0], "dclk0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_DCLK1], "dclk1", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT0], + "clkout0", NULL); + if (!ret) + ret = clk_register_clkdev(clk_table[MUX_CLKOUT1], + "clkout1", NULL); + if (ret) { + dev_err(&pdev->dev, "failed to register aliases, %d\n", ret); + goto err_clk_register; + } + + s3c24xx_dclk->dclk0_div_change_nb.notifier_call = + s3c24xx_dclk0_div_notify; + + s3c24xx_dclk->dclk1_div_change_nb.notifier_call = + s3c24xx_dclk1_div_notify; + + ret = clk_notifier_register(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + if (ret) + goto err_clk_register; + + ret = clk_notifier_register(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + if (ret) + goto err_dclk_notify; + + return 0; + +err_dclk_notify: + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); +err_clk_register: + for (i = 0; i < DCLK_MAX_CLKS; i++) + if (clk_table[i] && !IS_ERR(clk_table[i])) + clk_unregister(clk_table[i]); + + return ret; +} + +static int s3c24xx_dclk_remove(struct platform_device *pdev) +{ + struct s3c24xx_dclk *s3c24xx_dclk = platform_get_drvdata(pdev); + struct clk **clk_table = s3c24xx_dclk->clk_data.clks; + int i; + + clk_notifier_unregister(clk_table[DIV_DCLK1], + &s3c24xx_dclk->dclk1_div_change_nb); + clk_notifier_unregister(clk_table[DIV_DCLK0], + &s3c24xx_dclk->dclk0_div_change_nb); + + for (i = 0; i < DCLK_MAX_CLKS; i++) + clk_unregister(clk_table[i]); + + return 0; +} + +static struct s3c24xx_dclk_drv_data dclk_variants[] = { + [S3C2410] = { + .clkout0_parent_names = clkout0_s3c2410_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2410_p), + .clkout1_parent_names = clkout1_s3c2410_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2410_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2412] = { + .clkout0_parent_names = clkout0_s3c2412_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2412_p), + .clkout1_parent_names = clkout1_s3c2412_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2412_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2440] = { + .clkout0_parent_names = clkout0_s3c2440_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2440_p), + .clkout1_parent_names = clkout1_s3c2440_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2440_p), + .mux_parent_names = dclk_s3c2410_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2410_p), + }, + [S3C2443] = { + .clkout0_parent_names = clkout0_s3c2443_p, + .clkout0_num_parents = ARRAY_SIZE(clkout0_s3c2443_p), + .clkout1_parent_names = clkout1_s3c2443_p, + .clkout1_num_parents = ARRAY_SIZE(clkout1_s3c2443_p), + .mux_parent_names = dclk_s3c2443_p, + .mux_num_parents = ARRAY_SIZE(dclk_s3c2443_p), + }, +}; + +static struct platform_device_id s3c24xx_dclk_driver_ids[] = { + { + .name = "s3c2410-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2410], + }, { + .name = "s3c2412-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2412], + }, { + .name = "s3c2440-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2440], + }, { + .name = "s3c2443-dclk", + .driver_data = (kernel_ulong_t)&dclk_variants[S3C2443], + }, + { } +}; + +MODULE_DEVICE_TABLE(platform, s3c24xx_dclk_driver_ids); + +static struct platform_driver s3c24xx_dclk_driver = { + .driver = { + .name = "s3c24xx-dclk", + .owner = THIS_MODULE, + .pm = &s3c24xx_dclk_pm_ops, + }, + .probe = s3c24xx_dclk_probe, + .remove = s3c24xx_dclk_remove, + .id_table = s3c24xx_dclk_driver_ids, +}; +module_platform_driver(s3c24xx_dclk_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); +MODULE_DESCRIPTION("Driver for the S3C24XX external clock outputs"); diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c new file mode 100644 index 0000000..ba07168 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de> + * + * 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 S3C2410 and following SoCs. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clock/s3c2410.h> + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKSLOW 0x10 +#define CLKDIVN 0x14 +#define CAMDIVN 0x18 + +/* the soc types */ +enum supported_socs { + S3C2410, + S3C2440, + S3C2442, +}; + +/* list of PLLs to be registered */ +enum s3c2410_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2410_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2410_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKSLOW, + CLKDIVN, + CAMDIVN, +}; + +static int s3c2410_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); + + return 0; +} + +static void s3c2410_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2410_save, + ARRAY_SIZE(s3c2410_clk_regs)); +} + +static struct syscore_ops s3c2410_clk_syscore_ops = { + .suspend = s3c2410_clk_suspend, + .resume = s3c2410_clk_resume, +}; + +static void s3c2410_clk_sleep_init(void) +{ + s3c2410_save = samsung_clk_alloc_reg_dump(s3c2410_clk_regs, + ARRAY_SIZE(s3c2410_clk_regs)); + if (!s3c2410_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2410_clk_syscore_ops); + return; +} +#else +static void s3c2410_clk_sleep_init(void) {} +#endif + +PNAME(fclk_p) = { "mpll", "div_slow" }; + +struct samsung_mux_clock s3c2410_common_muxes[] __initdata = { + MUX(FCLK, "fclk", fclk_p, CLKSLOW, 4, 1), +}; + +static struct clk_div_table divslow_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2410_common_dividers[] __initdata = { + DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1), +}; + +struct samsung_gate_clock s3c2410_common_gates[] __initdata = { + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), +}; + +/* should be added _after_ the soc-specific clocks are created */ +struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(UCLK, NULL, "usb-bus-host"), + ALIAS(UCLK, NULL, "usb-bus-gadget"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(UCLK, NULL, "uclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(FCLK, NULL, "fclk"), +}; + +/* S3C2410 specific clocks */ + +static struct samsung_pll_rate_table pll_s3c2410_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + /* 2410A extras */ + PLL_35XX_RATE(270000000, 127, 1, 1), + PLL_35XX_RATE(268000000, 126, 1, 1), + PLL_35XX_RATE(266000000, 125, 1, 1), + PLL_35XX_RATE(226000000, 105, 1, 1), + PLL_35XX_RATE(210000000, 132, 2, 1), + /* 2410 common */ + PLL_35XX_RATE(203000000, 161, 3, 1), + PLL_35XX_RATE(192000000, 88, 1, 1), + PLL_35XX_RATE(186000000, 85, 1, 1), + PLL_35XX_RATE(180000000, 82, 1, 1), + PLL_35XX_RATE(170000000, 77, 1, 1), + PLL_35XX_RATE(158000000, 71, 1, 1), + PLL_35XX_RATE(152000000, 68, 1, 1), + PLL_35XX_RATE(147000000, 90, 2, 1), + PLL_35XX_RATE(135000000, 82, 2, 1), + PLL_35XX_RATE(124000000, 116, 1, 2), + PLL_35XX_RATE(118000000, 150, 2, 2), + PLL_35XX_RATE(113000000, 105, 1, 2), + PLL_35XX_RATE(101000000, 127, 2, 2), + PLL_35XX_RATE(90000000, 112, 2, 2), + PLL_35XX_RATE(85000000, 105, 2, 2), + PLL_35XX_RATE(79000000, 71, 1, 2), + PLL_35XX_RATE(68000000, 82, 2, 2), + PLL_35XX_RATE(56000000, 142, 2, 3), + PLL_35XX_RATE(48000000, 120, 2, 3), + PLL_35XX_RATE(51000000, 161, 3, 3), + PLL_35XX_RATE(45000000, 82, 1, 3), + PLL_35XX_RATE(34000000, 82, 2, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c2410_plls[] __initdata = { + [mpll] = PLL(pll_s3c2410_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_div_clock s3c2410_dividers[] __initdata = { + DIV(HCLK, "hclk", "mpll", CLKDIVN, 1, 1), +}; + +struct samsung_fixed_factor_clock s3c2410_ffactor[] __initdata = { + /* + * armclk is directly supplied by the fclk, without + * switching possibility like on the s3c244x below. + */ + FFACTOR(ARMCLK, "armclk", "fclk", 1, 1, 0), + + /* uclk is fed from the unmodified upll */ + FFACTOR(UCLK, "uclk", "upll", 1, 1, 0), +}; + +struct samsung_clock_alias s3c2410_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2410-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2410-uart.0", "clk_uart_baud0"), + ALIAS(PCLK_UART1, "s3c2410-uart.1", "clk_uart_baud0"), + ALIAS(PCLK_UART2, "s3c2410-uart.2", "clk_uart_baud0"), + ALIAS(UCLK, NULL, "clk_uart_baud1"), +}; + +/* S3C244x specific clocks */ + +static struct samsung_pll_rate_table pll_s3c244x_12mhz_tbl[] __initdata = { + /* sorted in descending order */ + PLL_35XX_RATE(400000000, 0x5c, 1, 1), + PLL_35XX_RATE(390000000, 0x7a, 2, 1), + PLL_35XX_RATE(380000000, 0x57, 1, 1), + PLL_35XX_RATE(370000000, 0xb1, 4, 1), + PLL_35XX_RATE(360000000, 0x70, 2, 1), + PLL_35XX_RATE(350000000, 0xa7, 4, 1), + PLL_35XX_RATE(340000000, 0x4d, 1, 1), + PLL_35XX_RATE(330000000, 0x66, 2, 1), + PLL_35XX_RATE(320000000, 0x98, 4, 1), + PLL_35XX_RATE(310000000, 0x93, 4, 1), + PLL_35XX_RATE(300000000, 0x75, 3, 1), + PLL_35XX_RATE(240000000, 0x70, 1, 2), + PLL_35XX_RATE(230000000, 0x6b, 1, 2), + PLL_35XX_RATE(220000000, 0x66, 1, 2), + PLL_35XX_RATE(210000000, 0x84, 2, 2), + PLL_35XX_RATE(200000000, 0x5c, 1, 2), + PLL_35XX_RATE(190000000, 0x57, 1, 2), + PLL_35XX_RATE(180000000, 0x70, 2, 2), + PLL_35XX_RATE(170000000, 0x4d, 1, 2), + PLL_35XX_RATE(160000000, 0x98, 4, 2), + PLL_35XX_RATE(150000000, 0x75, 3, 2), + PLL_35XX_RATE(120000000, 0x70, 1, 3), + PLL_35XX_RATE(110000000, 0x66, 1, 3), + PLL_35XX_RATE(100000000, 0x5c, 1, 3), + PLL_35XX_RATE(90000000, 0x70, 2, 3), + PLL_35XX_RATE(80000000, 0x98, 4, 3), + PLL_35XX_RATE(75000000, 0x75, 3, 3), + { /* sentinel */ }, +}; + +static struct samsung_pll_clock s3c244x_common_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "xti", + LOCKTIME, UPLLCON, NULL), +}; + +PNAME(hclk_p) = { "fclk", "div_hclk_2", "div_hclk_4", "div_hclk_3" }; +PNAME(armclk_p) = { "fclk", "hclk" }; + +struct samsung_mux_clock s3c244x_common_muxes[] __initdata = { + MUX(HCLK, "hclk", hclk_p, CLKDIVN, 1, 2), + MUX(ARMCLK, "armclk", armclk_p, CAMDIVN, 12, 1), +}; + +struct samsung_fixed_factor_clock s3c244x_common_ffactor[] __initdata = { + FFACTOR(0, "div_hclk_2", "fclk", 1, 2, 0), + FFACTOR(0, "ff_cam", "div_cam", 2, 1, CLK_SET_RATE_PARENT), +}; + +static struct clk_div_table div_hclk_4_d[] = { + { .val = 0, .div = 4 }, + { .val = 1, .div = 8 }, + { /* sentinel */ }, +}; + +static struct clk_div_table div_hclk_3_d[] = { + { .val = 0, .div = 3 }, + { .val = 1, .div = 6 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c244x_common_dividers[] __initdata = { + DIV(UCLK, "uclk", "upll", CLKDIVN, 3, 1), + DIV(0, "div_hclk", "fclk", CLKDIVN, 1, 1), + DIV_T(0, "div_hclk_4", "fclk", CAMDIVN, 9, 1, div_hclk_4_d), + DIV_T(0, "div_hclk_3", "fclk", CAMDIVN, 8, 1, div_hclk_3_d), + DIV(0, "div_cam", "upll", CAMDIVN, 0, 3), +}; + +struct samsung_gate_clock s3c244x_common_gates[] __initdata = { + GATE(HCLK_CAM, "cam", "hclk", CLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c244x_common_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(HCLK_CAM, NULL, "camif"), + ALIAS(CAMIF, NULL, "camif-upll"), +}; + +/* S3C2440 specific clocks */ + +PNAME(s3c2440_camif_p) = { "upll", "ff_cam" }; + +struct samsung_mux_clock s3c2440_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2440_camif_p, CAMDIVN, 4, 1), +}; + +struct samsung_gate_clock s3c2440_gates[] __initdata = { + GATE(PCLK_AC97, "ac97", "pclk", CLKCON, 20, 0, 0), +}; + +/* S3C2442 specific clocks */ + +struct samsung_fixed_factor_clock s3c2442_ffactor[] __initdata = { + FFACTOR(0, "upll_3", "upll", 1, 3, 0), +}; + +PNAME(s3c2442_camif_p) = { "upll", "ff_cam", "upll", "upll_3" }; + +struct samsung_mux_clock s3c2442_muxes[] __initdata = { + MUX(CAMIF, "camif", s3c2442_camif_p, CAMDIVN, 4, 2), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2410_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long xti_f) +{ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2410_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(ctx, s3c2410_common_frate_clks, + ARRAY_SIZE(s3c2410_common_frate_clks)); + + samsung_clk_register_alias(ctx, &xti_alias, 1); +} + +void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + struct samsung_clk_provider *ctx; + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2410_common_clk_register_fixed_ext(ctx, xti_f); + + if (current_soc == 2410) { + if (_get_rate("xti") == 12 * MHZ) { + s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl; + s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(ctx, s3c2410_plls, + ARRAY_SIZE(s3c2410_plls), reg_base); + + } else { /* S3C2440, S3C2442 */ + if (_get_rate("xti") == 12 * MHZ) { + /* + * plls follow different calculation schemes, with the + * upll following the same scheme as the s3c2410 plls + */ + s3c244x_common_plls[mpll].rate_table = + pll_s3c244x_12mhz_tbl; + s3c244x_common_plls[upll].rate_table = + pll_s3c2410_12mhz_tbl; + } + + /* Register PLLs. */ + samsung_clk_register_pll(ctx, s3c244x_common_plls, + ARRAY_SIZE(s3c244x_common_plls), reg_base); + } + + /* Register common internal clocks. */ + samsung_clk_register_mux(ctx, s3c2410_common_muxes, + ARRAY_SIZE(s3c2410_common_muxes)); + samsung_clk_register_div(ctx, s3c2410_common_dividers, + ARRAY_SIZE(s3c2410_common_dividers)); + samsung_clk_register_gate(ctx, s3c2410_common_gates, + ARRAY_SIZE(s3c2410_common_gates)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_div(ctx, s3c244x_common_dividers, + ARRAY_SIZE(s3c244x_common_dividers)); + samsung_clk_register_gate(ctx, s3c244x_common_gates, + ARRAY_SIZE(s3c244x_common_gates)); + samsung_clk_register_mux(ctx, s3c244x_common_muxes, + ARRAY_SIZE(s3c244x_common_muxes)); + samsung_clk_register_fixed_factor(ctx, s3c244x_common_ffactor, + ARRAY_SIZE(s3c244x_common_ffactor)); + } + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2410: + samsung_clk_register_div(ctx, s3c2410_dividers, + ARRAY_SIZE(s3c2410_dividers)); + samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor, + ARRAY_SIZE(s3c2410_ffactor)); + samsung_clk_register_alias(ctx, s3c2410_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + break; + case S3C2440: + samsung_clk_register_mux(ctx, s3c2440_muxes, + ARRAY_SIZE(s3c2440_muxes)); + samsung_clk_register_gate(ctx, s3c2440_gates, + ARRAY_SIZE(s3c2440_gates)); + break; + case S3C2442: + samsung_clk_register_mux(ctx, s3c2442_muxes, + ARRAY_SIZE(s3c2442_muxes)); + samsung_clk_register_fixed_factor(ctx, s3c2442_ffactor, + ARRAY_SIZE(s3c2442_ffactor)); + break; + } + + /* + * Register common aliases at the end, as some of the aliased clocks + * are SoC specific. + */ + samsung_clk_register_alias(ctx, s3c2410_common_aliases, + ARRAY_SIZE(s3c2410_common_aliases)); + + if (current_soc == S3C2440 || current_soc == S3C2442) { + samsung_clk_register_alias(ctx, s3c244x_common_aliases, + ARRAY_SIZE(s3c244x_common_aliases)); + } + + s3c2410_clk_sleep_init(); +} + +static void __init s3c2410_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2410, 0); +} +CLK_OF_DECLARE(s3c2410_clk, "samsung,s3c2410-clock", s3c2410_clk_init); + +static void __init s3c2440_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2440, 0); +} +CLK_OF_DECLARE(s3c2440_clk, "samsung,s3c2440-clock", s3c2440_clk_init); + +static void __init s3c2442_clk_init(struct device_node *np) +{ + s3c2410_common_clk_init(np, 0, S3C2442, 0); +} +CLK_OF_DECLARE(s3c2442_clk, "samsung,s3c2442-clock", s3c2442_clk_init); diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c new file mode 100644 index 0000000..23e4313 --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de> + * + * 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 S3C2412 and S3C2413. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clock/s3c2412.h> + +#include "clk.h" +#include "clk-pll.h" + +#define LOCKTIME 0x00 +#define MPLLCON 0x04 +#define UPLLCON 0x08 +#define CLKCON 0x0c +#define CLKDIVN 0x14 +#define CLKSRC 0x1c + +/* list of PLLs to be registered */ +enum s3c2412_plls { + mpll, upll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2412_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2412_clk_regs[] __initdata = { + LOCKTIME, + MPLLCON, + UPLLCON, + CLKCON, + CLKDIVN, + CLKSRC, +}; + +static int s3c2412_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); + + return 0; +} + +static void s3c2412_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2412_save, + ARRAY_SIZE(s3c2412_clk_regs)); +} + +static struct syscore_ops s3c2412_clk_syscore_ops = { + .suspend = s3c2412_clk_suspend, + .resume = s3c2412_clk_resume, +}; + +static void s3c2412_clk_sleep_init(void) +{ + s3c2412_save = samsung_clk_alloc_reg_dump(s3c2412_clk_regs, + ARRAY_SIZE(s3c2412_clk_regs)); + if (!s3c2412_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2412_clk_syscore_ops); + return; +} +#else +static void s3c2412_clk_sleep_init(void) {} +#endif + +static struct clk_div_table divxti_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 6 }, + { .val = 4, .div = 8 }, + { .val = 5, .div = 10 }, + { .val = 6, .div = 12 }, + { .val = 7, .div = 14 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2412_dividers[] __initdata = { + DIV_T(0, "div_xti", "xti", CLKSRC, 0, 3, divxti_d), + DIV(0, "div_cam", "mux_cam", CLKDIVN, 16, 4), + DIV(0, "div_i2s", "mux_i2s", CLKDIVN, 12, 4), + DIV(0, "div_uart", "mux_uart", CLKDIVN, 8, 4), + DIV(0, "div_usb", "mux_usb", CLKDIVN, 6, 1), + DIV(0, "div_hclk_half", "hclk", CLKDIVN, 5, 1), + DIV(ARMDIV, "armdiv", "msysclk", CLKDIVN, 3, 1), + DIV(PCLK, "pclk", "hclk", CLKDIVN, 2, 1), + DIV(HCLK, "hclk", "armdiv", CLKDIVN, 0, 2), +}; + +struct samsung_fixed_factor_clock s3c2412_ffactor[] __initdata = { + FFACTOR(0, "ff_hclk", "hclk", 2, 1, CLK_SET_RATE_PARENT), +}; + +/* + * The first two use the OM[4] setting, which is not readable from + * software, so assume it is set to xti. + */ +PNAME(erefclk_p) = { "xti", "xti", "xti", "ext" }; +PNAME(urefclk_p) = { "xti", "xti", "xti", "ext" }; + +PNAME(camclk_p) = { "usysclk", "hclk" }; +PNAME(usbclk_p) = { "usysclk", "hclk" }; +PNAME(i2sclk_p) = { "erefclk", "mpll" }; +PNAME(uartclk_p) = { "erefclk", "mpll" }; +PNAME(usysclk_p) = { "urefclk", "upll" }; +PNAME(msysclk_p) = { "mdivclk", "mpll" }; +PNAME(mdivclk_p) = { "xti", "div_xti" }; +PNAME(armclk_p) = { "armdiv", "hclk" }; + +struct samsung_mux_clock s3c2412_muxes[] __initdata = { + MUX(0, "erefclk", erefclk_p, CLKSRC, 14, 2), + MUX(0, "urefclk", urefclk_p, CLKSRC, 12, 2), + MUX(0, "mux_cam", camclk_p, CLKSRC, 11, 1), + MUX(0, "mux_usb", usbclk_p, CLKSRC, 10, 1), + MUX(0, "mux_i2s", i2sclk_p, CLKSRC, 9, 1), + MUX(0, "mux_uart", uartclk_p, CLKSRC, 8, 1), + MUX(USYSCLK, "usysclk", usysclk_p, CLKSRC, 5, 1), + MUX(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1), + MUX(MDIVCLK, "mdivclk", mdivclk_p, CLKSRC, 3, 1), + MUX(ARMCLK, "armclk", armclk_p, CLKDIVN, 4, 1), +}; + +static struct samsung_pll_clock s3c2412_plls[] __initdata = { + [mpll] = PLL(pll_s3c2440_mpll, MPLL, "mpll", "xti", + LOCKTIME, MPLLCON, NULL), + [upll] = PLL(pll_s3c2410_upll, UPLL, "upll", "urefclk", + LOCKTIME, UPLLCON, NULL), +}; + +struct samsung_gate_clock s3c2412_gates[] __initdata = { + GATE(PCLK_WDT, "wdt", "pclk", CLKCON, 28, 0, 0), + GATE(PCLK_SPI, "spi", "pclk", CLKCON, 27, 0, 0), + GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 26, 0, 0), + GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 25, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", CLKCON, 24, 0, 0), + GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 23, 0, 0), + GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 22, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 21, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 20, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 19, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 18, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 17, 0, 0), + GATE(PCLK_USBD, "usb-device", "pclk", CLKCON, 16, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", CLKCON, 15, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", CLKCON, 14, 0, 0), + GATE(SCLK_I2S, "sclk_i2s", "div_i2s", CLKCON, 13, 0, 0), + GATE(SCLK_USBH, "sclk_usbh", "div_usb", CLKCON, 12, 0, 0), + GATE(SCLK_USBD, "sclk_usbd", "div_usb", CLKCON, 11, 0, 0), + GATE(HCLK_HALF, "hclk_half", "div_hclk_half", CLKCON, 10, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_X2, "hclkx2", "ff_hclk", CLKCON, 9, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SDRAM, "sdram", "hclk", CLKCON, 8, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), + GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), + GATE(HCLK_DMA3, "dma3", "hclk", CLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", CLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", CLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", CLKCON, 0, CLK_IGNORE_UNUSED, 0), +}; + +struct samsung_clock_alias s3c2412_aliases[] __initdata = { + ALIAS(PCLK_UART0, "s3c2412-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "uart"), + ALIAS(PCLK_UART0, "s3c2412-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2412-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2412-uart.2", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_I2C, "s3c2410-i2c.0", "i2c"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(PCLK_USBD, NULL, "usb-device"), + ALIAS(SCLK_USBD, NULL, "usb-bus-gadget"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(ARMCLK, NULL, "armclk"), + ALIAS(HCLK, NULL, "hclk"), + ALIAS(MPLL, NULL, "mpll"), + ALIAS(MSYSCLK, NULL, "fclk"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +#define XTI 1 +struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { + FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2412_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long xti_f, unsigned long ext_f) +{ + /* xtal alias is necessary for the current cpufreq driver */ + struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); + + s3c2412_common_frate_clks[0].fixed_rate = xti_f; + s3c2412_common_frate_clks[1].fixed_rate = ext_f; + samsung_clk_register_fixed_rate(ctx, s3c2412_common_frate_clks, + ARRAY_SIZE(s3c2412_common_frate_clks)); + + samsung_clk_register_alias(ctx, &xti_alias, 1); +} + +void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, + unsigned long ext_f, void __iomem *base) +{ + struct samsung_clk_provider *ctx; + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2412_common_clk_register_fixed_ext(ctx, xti_f, ext_f); + + /* Register PLLs. */ + samsung_clk_register_pll(ctx, s3c2412_plls, ARRAY_SIZE(s3c2412_plls), + reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(ctx, s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); + samsung_clk_register_div(ctx, s3c2412_dividers, + ARRAY_SIZE(s3c2412_dividers)); + samsung_clk_register_gate(ctx, s3c2412_gates, + ARRAY_SIZE(s3c2412_gates)); + samsung_clk_register_fixed_factor(ctx, s3c2412_ffactor, + ARRAY_SIZE(s3c2412_ffactor)); + samsung_clk_register_alias(ctx, s3c2412_aliases, + ARRAY_SIZE(s3c2412_aliases)); + + s3c2412_clk_sleep_init(); +} + +static void __init s3c2412_clk_init(struct device_node *np) +{ + s3c2412_common_clk_init(np, 0, 0, 0); +} +CLK_OF_DECLARE(s3c2412_clk, "samsung,s3c2412-clock", s3c2412_clk_init); diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c new file mode 100644 index 0000000..c4bbdab --- /dev/null +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de> + * + * 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 S3C2443 and following SoCs. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clock/s3c2443.h> + +#include "clk.h" +#include "clk-pll.h" + +/* S3C2416 clock controller register offsets */ +#define LOCKCON0 0x00 +#define LOCKCON1 0x04 +#define MPLLCON 0x10 +#define EPLLCON 0x18 +#define EPLLCON_K 0x1C +#define CLKSRC 0x20 +#define CLKDIV0 0x24 +#define CLKDIV1 0x28 +#define CLKDIV2 0x2C +#define HCLKCON 0x30 +#define PCLKCON 0x34 +#define SCLKCON 0x38 + +/* the soc types */ +enum supported_socs { + S3C2416, + S3C2443, + S3C2450, +}; + +/* list of PLLs to be registered */ +enum s3c2443_plls { + mpll, epll, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s3c2443_save; + +/* + * list of controller registers to be saved and restored during a + * suspend/resume cycle. + */ +static unsigned long s3c2443_clk_regs[] __initdata = { + LOCKCON0, + LOCKCON1, + MPLLCON, + EPLLCON, + EPLLCON_K, + CLKSRC, + CLKDIV0, + CLKDIV1, + CLKDIV2, + PCLKCON, + HCLKCON, + SCLKCON, +}; + +static int s3c2443_clk_suspend(void) +{ + samsung_clk_save(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); + + return 0; +} + +static void s3c2443_clk_resume(void) +{ + samsung_clk_restore(reg_base, s3c2443_save, + ARRAY_SIZE(s3c2443_clk_regs)); +} + +static struct syscore_ops s3c2443_clk_syscore_ops = { + .suspend = s3c2443_clk_suspend, + .resume = s3c2443_clk_resume, +}; + +static void s3c2443_clk_sleep_init(void) +{ + s3c2443_save = samsung_clk_alloc_reg_dump(s3c2443_clk_regs, + ARRAY_SIZE(s3c2443_clk_regs)); + if (!s3c2443_save) { + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; + } + + register_syscore_ops(&s3c2443_clk_syscore_ops); + return; +} +#else +static void s3c2443_clk_sleep_init(void) {} +#endif + +PNAME(epllref_p) = { "mpllref", "mpllref", "xti", "ext" }; +PNAME(esysclk_p) = { "epllref", "epll" }; +PNAME(mpllref_p) = { "xti", "mdivclk" }; +PNAME(msysclk_p) = { "mpllref", "mpll" }; +PNAME(armclk_p) = { "armdiv" , "hclk" }; +PNAME(i2s0_p) = { "div_i2s0", "ext_i2s", "epllref", "epllref" }; + +struct samsung_mux_clock s3c2443_common_muxes[] __initdata = { + MUX(0, "epllref", epllref_p, CLKSRC, 7, 2), + MUX(ESYSCLK, "esysclk", esysclk_p, CLKSRC, 6, 1), + MUX(0, "mpllref", mpllref_p, CLKSRC, 3, 1), + MUX_A(MSYSCLK, "msysclk", msysclk_p, CLKSRC, 4, 1, "msysclk"), + MUX_A(ARMCLK, "armclk", armclk_p, CLKDIV0, 13, 1, "armclk"), + MUX(0, "mux_i2s0", i2s0_p, CLKSRC, 14, 2), +}; + +static struct clk_div_table hclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 3, .div = 4 }, + { /* sentinel */ }, +}; + +static struct clk_div_table mdivclk_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 3 }, + { .val = 2, .div = 5 }, + { .val = 3, .div = 7 }, + { .val = 4, .div = 9 }, + { .val = 5, .div = 11 }, + { .val = 6, .div = 13 }, + { .val = 7, .div = 15 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_common_dividers[] __initdata = { + DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d), + DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2), + DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d), + DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1), + DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2), + DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8), + DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4), + DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4), + DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2), + DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2), +}; + +struct samsung_gate_clock s3c2443_common_gates[] __initdata = { + GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0), + GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0), + GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0), + GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0), + GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0), + GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0), + GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0), + GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0), + GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0), + GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0), + GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA1, "dma1", "hclk", HCLKCON, 1, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA0, "dma0", "hclk", HCLKCON, 0, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_GPIO, "gpio", "pclk", PCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_RTC, "rtc", "pclk", PCLKCON, 12, 0, 0), + GATE(PCLK_WDT, "wdt", "pclk", PCLKCON, 11, 0, 0), + GATE(PCLK_PWM, "pwm", "pclk", PCLKCON, 10, 0, 0), + GATE(PCLK_I2S0, "i2s0", "pclk", PCLKCON, 9, 0, 0), + GATE(PCLK_AC97, "ac97", "pclk", PCLKCON, 8, 0, 0), + GATE(PCLK_ADC, "adc", "pclk", PCLKCON, 7, 0, 0), + GATE(PCLK_SPI0, "spi0", "pclk", PCLKCON, 6, 0, 0), + GATE(PCLK_I2C0, "i2c0", "pclk", PCLKCON, 4, 0, 0), + GATE(PCLK_UART3, "uart3", "pclk", PCLKCON, 3, 0, 0), + GATE(PCLK_UART2, "uart2", "pclk", PCLKCON, 2, 0, 0), + GATE(PCLK_UART1, "uart1", "pclk", PCLKCON, 1, 0, 0), + GATE(PCLK_UART0, "uart0", "pclk", PCLKCON, 0, 0, 0), +}; + +struct samsung_clock_alias s3c2443_common_aliases[] __initdata = { + ALIAS(HCLK, NULL, "hclk"), + ALIAS(HCLK_SSMC, NULL, "nand"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "uart"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "uart"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "uart"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "uart"), + ALIAS(PCLK_UART0, "s3c2440-uart.0", "clk_uart_baud2"), + ALIAS(PCLK_UART1, "s3c2440-uart.1", "clk_uart_baud2"), + ALIAS(PCLK_UART2, "s3c2440-uart.2", "clk_uart_baud2"), + ALIAS(PCLK_UART3, "s3c2440-uart.3", "clk_uart_baud2"), + ALIAS(SCLK_UART, NULL, "clk_uart_baud3"), + ALIAS(PCLK_PWM, NULL, "timers"), + ALIAS(PCLK_RTC, NULL, "rtc"), + ALIAS(PCLK_WDT, NULL, "watchdog"), + ALIAS(PCLK_ADC, NULL, "adc"), + ALIAS(PCLK_I2C0, "s3c2410-i2c.0", "i2c"), + ALIAS(HCLK_USBD, NULL, "usb-device"), + ALIAS(HCLK_USBH, NULL, "usb-host"), + ALIAS(SCLK_USBH, NULL, "usb-bus-host"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi"), + ALIAS(PCLK_SPI0, "s3c2443-spi.0", "spi_busclk0"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"), + ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"), + ALIAS(PCLK_I2S0, "samsung-i2s.0", "iis"), + ALIAS(SCLK_I2S0, NULL, "i2s-if"), + ALIAS(HCLK_LCD, NULL, "lcd"), + ALIAS(SCLK_FIMD, NULL, "sclk_fimd"), +}; + +/* S3C2416 specific clocks */ + +static struct samsung_pll_clock s3c2416_pll_clks[] __initdata = { + [mpll] = PLL(pll_6552_s3c2416, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_6553, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +PNAME(s3c2416_hsmmc0_p) = { "sclk_hsmmc0", "sclk_hsmmcext" }; +PNAME(s3c2416_hsmmc1_p) = { "sclk_hsmmc1", "sclk_hsmmcext" }; +PNAME(s3c2416_hsspi0_p) = { "hsspi0_epll", "hsspi0_mpll" }; + +static struct clk_div_table armdiv_s3c2416_d[] = { + { .val = 0, .div = 1 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { .val = 5, .div = 6 }, + { .val = 7, .div = 8 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2416_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 3, armdiv_s3c2416_d), + DIV(0, "div_hsspi0_mpll", "msysclk", CLKDIV2, 0, 4), + DIV(0, "div_hsmmc0", "esysclk", CLKDIV2, 6, 2), +}; + +struct samsung_mux_clock s3c2416_muxes[] __initdata = { + MUX(MUX_HSMMC0, "mux_hsmmc0", s3c2416_hsmmc0_p, CLKSRC, 16, 1), + MUX(MUX_HSMMC1, "mux_hsmmc1", s3c2416_hsmmc1_p, CLKSRC, 17, 1), + MUX(MUX_HSSPI0, "mux_hsspi0", s3c2416_hsspi0_p, CLKSRC, 18, 1), +}; + +struct samsung_gate_clock s3c2416_gates[] __initdata = { + GATE(0, "hsspi0_mpll", "div_hsspi0_mpll", SCLKCON, 19, 0, 0), + GATE(0, "hsspi0_epll", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(0, "sclk_hsmmc0", "div_hsmmc0", SCLKCON, 6, 0, 0), + GATE(HCLK_2D, "2d", "hclk", HCLKCON, 20, 0, 0), + GATE(HCLK_HSMMC0, "hsmmc0", "hclk", HCLKCON, 15, 0, 0), + GATE(HCLK_IROM, "irom", "hclk", HCLKCON, 13, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_PCM, "pcm", "pclk", PCLKCON, 19, 0, 0), +}; + +struct samsung_clock_alias s3c2416_aliases[] __initdata = { + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"), + ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"), + ALIAS(MUX_HSMMC0, "s3c-sdhci.0", "mmc_busclk.2"), + ALIAS(MUX_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(MUX_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2443 specific clocks */ + +static struct samsung_pll_clock s3c2443_pll_clks[] __initdata = { + [mpll] = PLL(pll_3000, 0, "mpll", "mpllref", + LOCKCON0, MPLLCON, NULL), + [epll] = PLL(pll_2126, 0, "epll", "epllref", + LOCKCON1, EPLLCON, NULL), +}; + +static struct clk_div_table armdiv_s3c2443_d[] = { + { .val = 0, .div = 1 }, + { .val = 8, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 9, .div = 4 }, + { .val = 10, .div = 6 }, + { .val = 11, .div = 8 }, + { .val = 13, .div = 12 }, + { .val = 15, .div = 16 }, + { /* sentinel */ }, +}; + +struct samsung_div_clock s3c2443_dividers[] __initdata = { + DIV_T(ARMDIV, "armdiv", "msysclk", CLKDIV0, 9, 4, armdiv_s3c2443_d), + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), +}; + +struct samsung_gate_clock s3c2443_gates[] __initdata = { + GATE(SCLK_HSSPI0, "sclk_hsspi0", "div_hsspi0_epll", SCLKCON, 14, 0, 0), + GATE(SCLK_CAM, "sclk_cam", "div_cam", SCLKCON, 11, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 15, 0, 0), + GATE(PCLK_SDI, "sdi", "pclk", PCLKCON, 5, 0, 0), +}; + +struct samsung_clock_alias s3c2443_aliases[] __initdata = { + ALIAS(SCLK_HSSPI0, "s3c2443-spi.0", "spi_busclk2"), + ALIAS(SCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.2"), + ALIAS(SCLK_CAM, NULL, "camif-upll"), + ALIAS(PCLK_SPI1, "s3c2410-spi.0", "spi"), + ALIAS(PCLK_SDI, NULL, "sdi"), + ALIAS(HCLK_CFC, NULL, "cfc"), + ALIAS(ARMDIV, NULL, "armdiv"), +}; + +/* S3C2450 specific clocks */ + +PNAME(s3c2450_cam_p) = { "div_cam", "hclk" }; +PNAME(s3c2450_hsspi1_p) = { "hsspi1_epll", "hsspi1_mpll" }; +PNAME(i2s1_p) = { "div_i2s1", "ext_i2s", "epllref", "epllref" }; + +struct samsung_div_clock s3c2450_dividers[] __initdata = { + DIV(0, "div_cam", "esysclk", CLKDIV1, 26, 4), + DIV(0, "div_hsspi1_epll", "esysclk", CLKDIV2, 24, 2), + DIV(0, "div_hsspi1_mpll", "msysclk", CLKDIV2, 16, 4), + DIV(0, "div_i2s1", "esysclk", CLKDIV2, 12, 4), +}; + +struct samsung_mux_clock s3c2450_muxes[] __initdata = { + MUX(0, "mux_cam", s3c2450_cam_p, CLKSRC, 20, 1), + MUX(MUX_HSSPI1, "mux_hsspi1", s3c2450_hsspi1_p, CLKSRC, 19, 1), + MUX(0, "mux_i2s1", i2s1_p, CLKSRC, 12, 2), +}; + +struct samsung_gate_clock s3c2450_gates[] __initdata = { + GATE(SCLK_I2S1, "sclk_i2s1", "div_i2s1", SCLKCON, 5, 0, 0), + GATE(HCLK_CFC, "cfc", "hclk", HCLKCON, 17, 0, 0), + GATE(HCLK_CAM, "cam", "hclk", HCLKCON, 8, 0, 0), + GATE(HCLK_DMA7, "dma7", "hclk", HCLKCON, 7, CLK_IGNORE_UNUSED, 0), + GATE(HCLK_DMA6, "dma6", "hclk", HCLKCON, 6, CLK_IGNORE_UNUSED, 0), + GATE(PCLK_I2S1, "i2s1", "pclk", PCLKCON, 17, 0, 0), + GATE(PCLK_I2C1, "i2c1", "pclk", PCLKCON, 16, 0, 0), + GATE(PCLK_SPI1, "spi1", "pclk", PCLKCON, 14, 0, 0), +}; + +struct samsung_clock_alias s3c2450_aliases[] __initdata = { + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi"), + ALIAS(PCLK_SPI1, "s3c2443-spi.1", "spi_busclk0"), + ALIAS(MUX_HSSPI1, "s3c2443-spi.1", "spi_busclk2"), + ALIAS(PCLK_I2C1, "s3c2410-i2c.1", "i2c"), +}; + +/* + * fixed rate clocks generated outside the soc + * Only necessary until the devicetree-move is complete + */ +struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { + FRATE(0, "xti", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_i2s", NULL, CLK_IS_ROOT, 0), + FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0), +}; + +static void __init s3c2443_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, unsigned long xti_f) +{ + s3c2443_common_frate_clks[0].fixed_rate = xti_f; + samsung_clk_register_fixed_rate(ctx, s3c2443_common_frate_clks, + ARRAY_SIZE(s3c2443_common_frate_clks)); +} + +void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, + int current_soc, + void __iomem *base) +{ + struct samsung_clk_provider *ctx; + reg_base = base; + + if (np) { + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + } + + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + /* Register external clocks only in non-dt cases */ + if (!np) + s3c2443_common_clk_register_fixed_ext(ctx, xti_f); + + /* Register PLLs. */ + if (current_soc == S3C2416 || current_soc == S3C2450) + samsung_clk_register_pll(ctx, s3c2416_pll_clks, + ARRAY_SIZE(s3c2416_pll_clks), reg_base); + else + samsung_clk_register_pll(ctx, s3c2443_pll_clks, + ARRAY_SIZE(s3c2443_pll_clks), reg_base); + + /* Register common internal clocks. */ + samsung_clk_register_mux(ctx, s3c2443_common_muxes, + ARRAY_SIZE(s3c2443_common_muxes)); + samsung_clk_register_div(ctx, s3c2443_common_dividers, + ARRAY_SIZE(s3c2443_common_dividers)); + samsung_clk_register_gate(ctx, s3c2443_common_gates, + ARRAY_SIZE(s3c2443_common_gates)); + samsung_clk_register_alias(ctx, s3c2443_common_aliases, + ARRAY_SIZE(s3c2443_common_aliases)); + + /* Register SoC-specific clocks. */ + switch (current_soc) { + case S3C2450: + samsung_clk_register_div(ctx, s3c2450_dividers, + ARRAY_SIZE(s3c2450_dividers)); + samsung_clk_register_mux(ctx, s3c2450_muxes, + ARRAY_SIZE(s3c2450_muxes)); + samsung_clk_register_gate(ctx, s3c2450_gates, + ARRAY_SIZE(s3c2450_gates)); + samsung_clk_register_alias(ctx, s3c2450_aliases, + ARRAY_SIZE(s3c2450_aliases)); + /* fall through, as s3c2450 extends the s3c2416 clocks */ + case S3C2416: + samsung_clk_register_div(ctx, s3c2416_dividers, + ARRAY_SIZE(s3c2416_dividers)); + samsung_clk_register_mux(ctx, s3c2416_muxes, + ARRAY_SIZE(s3c2416_muxes)); + samsung_clk_register_gate(ctx, s3c2416_gates, + ARRAY_SIZE(s3c2416_gates)); + samsung_clk_register_alias(ctx, s3c2416_aliases, + ARRAY_SIZE(s3c2416_aliases)); + break; + case S3C2443: + samsung_clk_register_div(ctx, s3c2443_dividers, + ARRAY_SIZE(s3c2443_dividers)); + samsung_clk_register_gate(ctx, s3c2443_gates, + ARRAY_SIZE(s3c2443_gates)); + samsung_clk_register_alias(ctx, s3c2443_aliases, + ARRAY_SIZE(s3c2443_aliases)); + break; + } + + s3c2443_clk_sleep_init(); +} + +static void __init s3c2416_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2416, 0); +} +CLK_OF_DECLARE(s3c2416_clk, "samsung,s3c2416-clock", s3c2416_clk_init); + +static void __init s3c2443_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2443, 0); +} +CLK_OF_DECLARE(s3c2443_clk, "samsung,s3c2443-clock", s3c2443_clk_init); + +static void __init s3c2450_clk_init(struct device_node *np) +{ + s3c2443_common_clk_init(np, 0, S3C2450, 0); +} +CLK_OF_DECLARE(s3c2450_clk, "samsung,s3c2450-clock", s3c2450_clk_init); diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 8bda658..efa16ee 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -442,12 +442,14 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = { ALIAS(MEM0_SROM, NULL, "srom"), }; -static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, - unsigned long xusbxti_f) +static void __init s3c64xx_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long fin_pll_f, + unsigned long xusbxti_f) { s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, + samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_ext_clks, ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); } @@ -456,6 +458,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, unsigned long xusbxti_f, bool s3c6400, void __iomem *base) { + struct samsung_clk_provider *ctx; + reg_base = base; is_s3c6400 = s3c6400; @@ -465,48 +469,50 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS); + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); /* Register external clocks. */ if (!np) - s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); + s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f); /* Register PLLs. */ - samsung_clk_register_pll(s3c64xx_pll_clks, + samsung_clk_register_pll(ctx, s3c64xx_pll_clks, ARRAY_SIZE(s3c64xx_pll_clks), reg_base); /* Register common internal clocks. */ - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks, ARRAY_SIZE(s3c64xx_fixed_rate_clks)); - samsung_clk_register_mux(s3c64xx_mux_clks, + samsung_clk_register_mux(ctx, s3c64xx_mux_clks, ARRAY_SIZE(s3c64xx_mux_clks)); - samsung_clk_register_div(s3c64xx_div_clks, + samsung_clk_register_div(ctx, s3c64xx_div_clks, ARRAY_SIZE(s3c64xx_div_clks)); - samsung_clk_register_gate(s3c64xx_gate_clks, + samsung_clk_register_gate(ctx, s3c64xx_gate_clks, ARRAY_SIZE(s3c64xx_gate_clks)); /* Register SoC-specific clocks. */ if (is_s3c6400) { - samsung_clk_register_mux(s3c6400_mux_clks, + samsung_clk_register_mux(ctx, s3c6400_mux_clks, ARRAY_SIZE(s3c6400_mux_clks)); - samsung_clk_register_div(s3c6400_div_clks, + samsung_clk_register_div(ctx, s3c6400_div_clks, ARRAY_SIZE(s3c6400_div_clks)); - samsung_clk_register_gate(s3c6400_gate_clks, + samsung_clk_register_gate(ctx, s3c6400_gate_clks, ARRAY_SIZE(s3c6400_gate_clks)); - samsung_clk_register_alias(s3c6400_clock_aliases, + samsung_clk_register_alias(ctx, s3c6400_clock_aliases, ARRAY_SIZE(s3c6400_clock_aliases)); } else { - samsung_clk_register_mux(s3c6410_mux_clks, + samsung_clk_register_mux(ctx, s3c6410_mux_clks, ARRAY_SIZE(s3c6410_mux_clks)); - samsung_clk_register_div(s3c6410_div_clks, + samsung_clk_register_div(ctx, s3c6410_div_clks, ARRAY_SIZE(s3c6410_div_clks)); - samsung_clk_register_gate(s3c6410_gate_clks, + samsung_clk_register_gate(ctx, s3c6410_gate_clks, ARRAY_SIZE(s3c6410_gate_clks)); - samsung_clk_register_alias(s3c6410_clock_aliases, + samsung_clk_register_alias(ctx, s3c6410_clock_aliases, ARRAY_SIZE(s3c6410_clock_aliases)); } - samsung_clk_register_alias(s3c64xx_clock_aliases, + samsung_clk_register_alias(ctx, s3c64xx_clock_aliases, ARRAY_SIZE(s3c64xx_clock_aliases)); s3c64xx_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 91bec3e..49629c7 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -14,13 +14,6 @@ #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 - void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs) @@ -55,40 +48,58 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( } /* 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) +struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, + void __iomem *base, unsigned long nr_clks) { - reg_base = base; + struct samsung_clk_provider *ctx; + struct clk **clk_table; + int ret; + int i; - clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); + ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL); + if (!ctx) + panic("could not allocate clock provider context.\n"); + + clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); if (!clk_table) panic("could not allocate clock lookup table\n"); + for (i = 0; i < nr_clks; ++i) + clk_table[i] = ERR_PTR(-ENOENT); + + ctx->reg_base = base; + ctx->clk_data.clks = clk_table; + ctx->clk_data.clk_num = nr_clks; + spin_lock_init(&ctx->lock); + if (!np) - return; + return ctx; -#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 + ret = of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data); + if (ret) + panic("could not register clock provide\n"); + + return ctx; } /* 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) +void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, + unsigned int id) { - if (clk_table && id) - clk_table[id] = clk; + if (ctx->clk_data.clks && id) + ctx->clk_data.clks[id] = clk; } /* register a list of aliases */ -void __init samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk) +void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx, + struct samsung_clock_alias *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; - if (!clk_table) { + if (!ctx->clk_data.clks) { pr_err("%s: clock table missing\n", __func__); return; } @@ -100,7 +111,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, continue; } - clk = clk_table[list->id]; + clk = ctx->clk_data.clks[list->id]; if (!clk) { pr_err("%s: failed to find clock %d\n", __func__, list->id); @@ -115,7 +126,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, } /* register a list of fixed clocks */ -void __init samsung_clk_register_fixed_rate( +void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -130,7 +141,7 @@ void __init samsung_clk_register_fixed_rate( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); /* * Unconditionally add a clock lookup for the fixed rate clocks. @@ -144,7 +155,7 @@ void __init samsung_clk_register_fixed_rate( } /* register a list of fixed factor clocks */ -void __init samsung_clk_register_fixed_factor( +void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, struct samsung_fixed_factor_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -159,28 +170,30 @@ void __init samsung_clk_register_fixed_factor( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); } } /* register a list of mux clocks */ -void __init samsung_clk_register_mux(struct samsung_mux_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, + 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); + list->num_parents, list->flags, + ctx->reg_base + list->offset, + list->shift, list->width, list->mux_flags, &ctx->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); + samsung_clk_add_lookup(ctx, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -194,8 +207,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list, } /* register a list of div clocks */ -void __init samsung_clk_register_div(struct samsung_div_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, + struct samsung_div_clock *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; @@ -203,22 +217,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, 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); + list->parent_name, list->flags, + ctx->reg_base + list->offset, + list->shift, list->width, list->div_flags, + list->table, &ctx->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); + list->parent_name, list->flags, + ctx->reg_base + list->offset, list->shift, + list->width, list->div_flags, &ctx->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); + samsung_clk_add_lookup(ctx, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -232,16 +246,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, } /* register a list of gate clocks */ -void __init samsung_clk_register_gate(struct samsung_gate_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, + 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); + list->flags, ctx->reg_base + list->offset, + list->bit_idx, list->gate_flags, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); @@ -257,7 +272,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, __func__, list->alias); } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); } } @@ -266,21 +281,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, * tree and register it */ #ifdef CONFIG_OF -void __init samsung_clk_of_register_fixed_ext( +void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, 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; + struct device_node *clk_np; u32 freq; - for_each_matching_node_and_match(np, clk_matches, &match) { - if (of_property_read_u32(np, "clock-frequency", &freq)) + for_each_matching_node_and_match(clk_np, clk_matches, &match) { + if (of_property_read_u32(clk_np, "clock-frequency", &freq)) continue; - fixed_rate_clk[(u32)match->data].fixed_rate = freq; + fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq; } - samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk); + samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); } #endif diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index c7141ba..9693b80 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -22,6 +22,18 @@ #include "clk-pll.h" /** + * struct samsung_clk_provider: information about clock provider + * @reg_base: virtual address for the register base. + * @clk_data: holds clock related data like clk* and number of clocks. + * @lock: maintains exclusion bwtween callbacks for a given clock-provider. + */ +struct samsung_clk_provider { + void __iomem *reg_base; + struct clk_onecell_data clk_data; + spinlock_t lock; +}; + +/** * 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. @@ -312,40 +324,52 @@ struct samsung_pll_clock { __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ _lock, _con, _rtable, _alias) -extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks); +extern struct samsung_clk_provider *__init samsung_clk_init( + struct device_node *np, void __iomem *base, + unsigned long nr_clks); 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); + struct samsung_clk_provider *ctx, + 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_add_lookup(struct samsung_clk_provider *ctx, + struct clk *clk, unsigned int id); -extern void samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk); +extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx, + 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); + struct samsung_clk_provider *ctx, + 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 void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_clk, void __iomem *base); + struct samsung_clk_provider *ctx, + struct samsung_fixed_factor_clock *list, + unsigned int nr_clk); +extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, + struct samsung_mux_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, + struct samsung_div_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, + struct samsung_gate_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_list, + unsigned int nr_clk, void __iomem *base); extern unsigned long _get_rate(const char *clk_name); extern void samsung_clk_save(void __iomem *base, - struct samsung_clk_reg_dump *rd, - unsigned int num_regs); + struct samsung_clk_reg_dump *rd, + unsigned int num_regs); extern void samsung_clk_restore(void __iomem *base, - const struct samsung_clk_reg_dump *rd, - unsigned int num_regs); + const struct samsung_clk_reg_dump *rd, + unsigned int num_regs); extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( - const unsigned long *rdump, - unsigned long nr_rdump); + const unsigned long *rdump, + unsigned long nr_rdump); #endif /* __SAMSUNG_CLK_H */ diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index be1b2b5..227ebf7 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -141,6 +141,7 @@ static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg) { + cfg->mpll = _clk_mpll; (cfg->info->set_fvco)(cfg); } diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 97ccc31..695507a 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -44,3 +44,9 @@ config ARM_AT91_CPUIDLE depends on ARCH_AT91 help Select this to enable cpuidle for AT91 processors + +config ARM_EXYNOS_CPUIDLE + bool "Cpu Idle Driver for the Exynos processors" + depends on ARCH_EXYNOS + help + Select this to enable cpuidle for Exynos processors diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index f71ae1b..0d1540a 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o +obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o ############################################################################### # POWERPC drivers diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c new file mode 100644 index 0000000..7c01512 --- /dev/null +++ b/drivers/cpuidle/cpuidle-exynos.c @@ -0,0 +1,99 @@ +/* linux/arch/arm/mach-exynos/cpuidle.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.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. +*/ + +#include <linux/cpuidle.h> +#include <linux/cpu_pm.h> +#include <linux/export.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/proc-fns.h> +#include <asm/suspend.h> +#include <asm/cpuidle.h> + +static void (*exynos_enter_aftr)(void); + +static int idle_finisher(unsigned long flags) +{ + exynos_enter_aftr(); + cpu_do_idle(); + + return 1; +} + +static int exynos_enter_core0_aftr(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + cpu_pm_enter(); + cpu_suspend(0, idle_finisher); + cpu_pm_exit(); + + return index; +} + +static int exynos_enter_lowpower(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + int new_index = index; + + /* AFTR can only be entered when cores other than CPU0 are offline */ + if (num_online_cpus() > 1 || dev->cpu != 0) + new_index = drv->safe_state_index; + + if (new_index == 0) + return arm_cpuidle_simple_enter(dev, drv, new_index); + else + return exynos_enter_core0_aftr(dev, drv, new_index); +} + +static struct cpuidle_driver exynos_idle_driver = { + .name = "exynos_idle", + .owner = THIS_MODULE, + .states = { + [0] = ARM_CPUIDLE_WFI_STATE, + [1] = { + .enter = exynos_enter_lowpower, + .exit_latency = 300, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "C1", + .desc = "ARM power down", + }, + }, + .state_count = 2, + .safe_state_index = 0, +}; + +static int exynos_cpuidle_probe(struct platform_device *pdev) +{ + int ret; + + exynos_enter_aftr = (void *)(pdev->dev.platform_data); + + ret = cpuidle_register(&exynos_idle_driver, NULL); + if (ret) { + dev_err(&pdev->dev, "failed to register cpuidle driver\n"); + return ret; + } + + return 0; +} + +static struct platform_driver exynos_cpuidle_driver = { + .probe = exynos_cpuidle_probe, + .driver = { + .name = "exynos_cpuidle", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(exynos_cpuidle_driver); |