diff options
Diffstat (limited to 'drivers/clk/samsung')
-rw-r--r-- | drivers/clk/samsung/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos-clkout.c | 153 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos3250.c | 43 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos4.c | 247 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5250.c | 6 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5260.c | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5410.c | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5420.c | 152 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5440.c | 4 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s3c2410.c | 11 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s3c2412.c | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s3c2443.c | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s3c64xx.c | 8 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s5pv210-audss.c | 241 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-s5pv210.c | 856 | ||||
-rw-r--r-- | drivers/clk/samsung/clk.c | 21 | ||||
-rw-r--r-- | drivers/clk/samsung/clk.h | 4 |
17 files changed, 1692 insertions, 64 deletions
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 69e81773164e..6fb4bc602e8a 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -11,8 +11,10 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.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_ARCH_EXYNOS) += clk-exynos-clkout.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 +obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c new file mode 100644 index 000000000000..3a7cb2506731 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos-clkout.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Tomasz Figa <t.figa@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. + * + * Clock driver for Exynos clock output + */ + +#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> + +#define EXYNOS_CLKOUT_NR_CLKS 1 +#define EXYNOS_CLKOUT_PARENTS 32 + +#define EXYNOS_PMU_DEBUG_REG 0xa00 +#define EXYNOS_CLKOUT_DISABLE_SHIFT 0 +#define EXYNOS_CLKOUT_MUX_SHIFT 8 +#define EXYNOS4_CLKOUT_MUX_MASK 0xf +#define EXYNOS5_CLKOUT_MUX_MASK 0x1f + +struct exynos_clkout { + struct clk_gate gate; + struct clk_mux mux; + spinlock_t slock; + struct clk_onecell_data data; + struct clk *clk_table[EXYNOS_CLKOUT_NR_CLKS]; + void __iomem *reg; + u32 pmu_debug_save; +}; + +static struct exynos_clkout *clkout; + +static int exynos_clkout_suspend(void) +{ + clkout->pmu_debug_save = readl(clkout->reg + EXYNOS_PMU_DEBUG_REG); + + return 0; +} + +static void exynos_clkout_resume(void) +{ + writel(clkout->pmu_debug_save, clkout->reg + EXYNOS_PMU_DEBUG_REG); +} + +static struct syscore_ops exynos_clkout_syscore_ops = { + .suspend = exynos_clkout_suspend, + .resume = exynos_clkout_resume, +}; + +static void __init exynos_clkout_init(struct device_node *node, u32 mux_mask) +{ + const char *parent_names[EXYNOS_CLKOUT_PARENTS]; + struct clk *parents[EXYNOS_CLKOUT_PARENTS]; + int parent_count; + int ret; + int i; + + clkout = kzalloc(sizeof(*clkout), GFP_KERNEL); + if (!clkout) + return; + + spin_lock_init(&clkout->slock); + + parent_count = 0; + for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i) { + char name[] = "clkoutXX"; + + snprintf(name, sizeof(name), "clkout%d", i); + parents[i] = of_clk_get_by_name(node, name); + if (IS_ERR(parents[i])) { + parent_names[i] = "none"; + continue; + } + + parent_names[i] = __clk_get_name(parents[i]); + parent_count = i + 1; + } + + if (!parent_count) + goto free_clkout; + + clkout->reg = of_iomap(node, 0); + if (!clkout->reg) + goto clks_put; + + clkout->gate.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG; + clkout->gate.bit_idx = EXYNOS_CLKOUT_DISABLE_SHIFT; + clkout->gate.flags = CLK_GATE_SET_TO_DISABLE; + clkout->gate.lock = &clkout->slock; + + clkout->mux.reg = clkout->reg + EXYNOS_PMU_DEBUG_REG; + clkout->mux.mask = mux_mask; + clkout->mux.shift = EXYNOS_CLKOUT_MUX_SHIFT; + clkout->mux.lock = &clkout->slock; + + clkout->clk_table[0] = clk_register_composite(NULL, "clkout", + parent_names, parent_count, &clkout->mux.hw, + &clk_mux_ops, NULL, NULL, &clkout->gate.hw, + &clk_gate_ops, CLK_SET_RATE_PARENT + | CLK_SET_RATE_NO_REPARENT); + if (IS_ERR(clkout->clk_table[0])) + goto err_unmap; + + clkout->data.clks = clkout->clk_table; + clkout->data.clk_num = EXYNOS_CLKOUT_NR_CLKS; + ret = of_clk_add_provider(node, of_clk_src_onecell_get, &clkout->data); + if (ret) + goto err_clk_unreg; + + register_syscore_ops(&exynos_clkout_syscore_ops); + + return; + +err_clk_unreg: + clk_unregister(clkout->clk_table[0]); +err_unmap: + iounmap(clkout->reg); +clks_put: + for (i = 0; i < EXYNOS_CLKOUT_PARENTS; ++i) + if (!IS_ERR(parents[i])) + clk_put(parents[i]); +free_clkout: + kfree(clkout); + + pr_err("%s: failed to register clkout clock\n", __func__); +} + +static void __init exynos4_clkout_init(struct device_node *node) +{ + exynos_clkout_init(node, EXYNOS4_CLKOUT_MUX_MASK); +} +CLK_OF_DECLARE(exynos4210_clkout, "samsung,exynos4210-pmu", + exynos4_clkout_init); +CLK_OF_DECLARE(exynos4212_clkout, "samsung,exynos4212-pmu", + exynos4_clkout_init); +CLK_OF_DECLARE(exynos4412_clkout, "samsung,exynos4412-pmu", + exynos4_clkout_init); + +static void __init exynos5_clkout_init(struct device_node *node) +{ + exynos_clkout_init(node, EXYNOS5_CLKOUT_MUX_MASK); +} +CLK_OF_DECLARE(exynos5250_clkout, "samsung,exynos5250-pmu", + exynos5_clkout_init); +CLK_OF_DECLARE(exynos5420_clkout, "samsung,exynos5420-pmu", + exynos5_clkout_init); diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index 7a17bd40d1dd..dc85f8e7a2d7 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -87,6 +87,22 @@ #define SRC_CPU 0x14200 #define DIV_CPU0 0x14500 #define DIV_CPU1 0x14504 +#define PWR_CTRL1 0x15020 +#define PWR_CTRL2 0x15024 + +/* Below definitions are used for PWR_CTRL settings */ +#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28) +#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16) +#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9) +#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8) +#define PWR_CTRL1_USE_CORE3_WFE (1 << 7) +#define PWR_CTRL1_USE_CORE2_WFE (1 << 6) +#define PWR_CTRL1_USE_CORE1_WFE (1 << 5) +#define PWR_CTRL1_USE_CORE0_WFE (1 << 4) +#define PWR_CTRL1_USE_CORE3_WFI (1 << 3) +#define PWR_CTRL1_USE_CORE2_WFI (1 << 2) +#define PWR_CTRL1_USE_CORE1_WFI (1 << 1) +#define PWR_CTRL1_USE_CORE0_WFI (1 << 0) /* list of PLLs to be registered */ enum exynos3250_plls { @@ -168,6 +184,8 @@ static unsigned long exynos3250_cmu_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, DIV_CPU1, + PWR_CTRL1, + PWR_CTRL2, }; static int exynos3250_clk_suspend(void) @@ -748,6 +766,27 @@ static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = { UPLL_LOCK, UPLL_CON0, NULL), }; +static void __init exynos3_core_down_clock(void) +{ + unsigned int tmp; + + /* + * Enable arm clock down (in idle) and set arm divider + * ratios in WFI/WFE state. + */ + tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) | + 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); + + /* + * Disable the clock up feature on Exynos4x12, in case it was + * enabled by bootloader. + */ + __raw_writel(0x0, reg_base + PWR_CTRL2); +} + static void __init exynos3250_cmu_init(struct device_node *np) { struct samsung_clk_provider *ctx; @@ -775,6 +814,10 @@ static void __init exynos3250_cmu_init(struct device_node *np) samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks)); samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks)); + exynos3_core_down_clock(); + exynos3250_clk_sleep_init(); + + samsung_clk_of_add_provider(np, ctx); } 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 4f150c9dd38c..ac163d7f5bc3 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -25,10 +25,12 @@ #define DIV_LEFTBUS 0x4500 #define GATE_IP_LEFTBUS 0x4800 #define E4X12_GATE_IP_IMAGE 0x4930 +#define CLKOUT_CMU_LEFTBUS 0x4a00 #define SRC_RIGHTBUS 0x8200 #define DIV_RIGHTBUS 0x8500 #define GATE_IP_RIGHTBUS 0x8800 #define E4X12_GATE_IP_PERIR 0x8960 +#define CLKOUT_CMU_RIGHTBUS 0x8a00 #define EPLL_LOCK 0xc010 #define VPLL_LOCK 0xc020 #define EPLL_CON0 0xc110 @@ -98,6 +100,7 @@ #define GATE_IP_PERIL 0xc950 #define E4210_GATE_IP_PERIR 0xc960 #define GATE_BLOCK 0xc970 +#define CLKOUT_CMU_TOP 0xca00 #define E4X12_MPLL_LOCK 0x10008 #define E4X12_MPLL_CON0 0x10108 #define SRC_DMC 0x10200 @@ -105,6 +108,7 @@ #define DIV_DMC0 0x10500 #define DIV_DMC1 0x10504 #define GATE_IP_DMC 0x10900 +#define CLKOUT_CMU_DMC 0x10a00 #define APLL_LOCK 0x14000 #define E4210_MPLL_LOCK 0x14008 #define APLL_CON0 0x14100 @@ -114,11 +118,28 @@ #define DIV_CPU1 0x14504 #define GATE_SCLK_CPU 0x14800 #define GATE_IP_CPU 0x14900 +#define CLKOUT_CMU_CPU 0x14a00 +#define PWR_CTRL1 0x15020 +#define E4X12_PWR_CTRL2 0x15024 #define E4X12_DIV_ISP0 0x18300 #define E4X12_DIV_ISP1 0x18304 #define E4X12_GATE_ISP0 0x18800 #define E4X12_GATE_ISP1 0x18804 +/* Below definitions are used for PWR_CTRL settings */ +#define PWR_CTRL1_CORE2_DOWN_RATIO(x) (((x) & 0x7) << 28) +#define PWR_CTRL1_CORE1_DOWN_RATIO(x) (((x) & 0x7) << 16) +#define PWR_CTRL1_DIV2_DOWN_EN (1 << 9) +#define PWR_CTRL1_DIV1_DOWN_EN (1 << 8) +#define PWR_CTRL1_USE_CORE3_WFE (1 << 7) +#define PWR_CTRL1_USE_CORE2_WFE (1 << 6) +#define PWR_CTRL1_USE_CORE1_WFE (1 << 5) +#define PWR_CTRL1_USE_CORE0_WFE (1 << 4) +#define PWR_CTRL1_USE_CORE3_WFI (1 << 3) +#define PWR_CTRL1_USE_CORE2_WFI (1 << 2) +#define PWR_CTRL1_USE_CORE1_WFI (1 << 1) +#define PWR_CTRL1_USE_CORE0_WFI (1 << 0) + /* the exynos4 soc type */ enum exynos4_soc { EXYNOS4210, @@ -155,6 +176,7 @@ static unsigned long exynos4210_clk_save[] __initdata = { E4210_GATE_IP_LCD1, E4210_GATE_IP_PERIR, E4210_MPLL_CON0, + PWR_CTRL1, }; static unsigned long exynos4x12_clk_save[] __initdata = { @@ -164,6 +186,8 @@ static unsigned long exynos4x12_clk_save[] __initdata = { E4X12_DIV_ISP, E4X12_DIV_CAM1, E4X12_MPLL_CON0, + PWR_CTRL1, + E4X12_PWR_CTRL2, }; static unsigned long exynos4_clk_pll_regs[] __initdata = { @@ -242,6 +266,11 @@ static unsigned long exynos4_clk_regs[] __initdata = { DIV_CPU1, GATE_SCLK_CPU, GATE_IP_CPU, + CLKOUT_CMU_LEFTBUS, + CLKOUT_CMU_RIGHTBUS, + CLKOUT_CMU_TOP, + CLKOUT_CMU_DMC, + CLKOUT_CMU_CPU, }; static const struct samsung_clk_reg_dump src_mask_suspend[] = { @@ -397,10 +426,32 @@ PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m", "sclk_epll", "sclk_vpll", }; PNAME(mout_mixer_p4210) = { "sclk_dac", "sclk_hdmi", }; PNAME(mout_dac_p4210) = { "sclk_vpll", "sclk_hdmiphy", }; +PNAME(mout_pwi_p4210) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0", + "sclk_usbphy1", "sclk_hdmiphy", "none", + "sclk_epll", "sclk_vpll" }; +PNAME(clkout_left_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2", + "div_gdl", "div_gpl" }; +PNAME(clkout_right_p4210) = { "sclk_mpll_div_2", "sclk_apll_div_2", + "div_gdr", "div_gpr" }; +PNAME(clkout_top_p4210) = { "fout_epll", "fout_vpll", "sclk_hdmi24m", + "sclk_usbphy0", "sclk_usbphy1", "sclk_hdmiphy", + "cdclk0", "cdclk1", "cdclk2", "spdif_extclk", + "aclk160", "aclk133", "aclk200", "aclk100", + "sclk_mfc", "sclk_g3d", "sclk_g2d", + "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l", + "s_rxbyteclkhs0_4l" }; +PNAME(clkout_dmc_p4210) = { "div_dmcd", "div_dmcp", "div_acp_pclk", "div_dmc", + "div_dphy", "none", "div_pwi" }; +PNAME(clkout_cpu_p4210) = { "fout_apll_div_2", "none", "fout_mpll_div_2", + "none", "arm_clk_div_2", "div_corem0", + "div_corem1", "div_corem0", "div_atb", + "div_periph", "div_pclk_dbg", "div_hpm" }; /* Exynos 4x12-specific parent groups */ PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", }; PNAME(mout_core_p4x12) = { "mout_apll", "mout_mpll_user_c", }; +PNAME(mout_gdl_p4x12) = { "mout_mpll_user_l", "sclk_apll", }; +PNAME(mout_gdr_p4x12) = { "mout_mpll_user_r", "sclk_apll", }; PNAME(sclk_ampll_p4x12) = { "mout_mpll_user_t", "sclk_apll", }; PNAME(group1_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0", "none", "sclk_hdmiphy", "mout_mpll_user_t", @@ -418,6 +469,32 @@ PNAME(aclk_p4412) = { "mout_mpll_user_t", "sclk_apll", }; PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", }; PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", }; PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", }; +PNAME(mout_pwi_p4x12) = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0", + "none", "sclk_hdmiphy", "sclk_mpll", + "sclk_epll", "sclk_vpll" }; +PNAME(clkout_left_p4x12) = { "sclk_mpll_user_l_div_2", "sclk_apll_div_2", + "div_gdl", "div_gpl" }; +PNAME(clkout_right_p4x12) = { "sclk_mpll_user_r_div_2", "sclk_apll_div_2", + "div_gdr", "div_gpr" }; +PNAME(clkout_top_p4x12) = { "fout_epll", "fout_vpll", "sclk_hdmi24m", + "sclk_usbphy0", "none", "sclk_hdmiphy", + "cdclk0", "cdclk1", "cdclk2", "spdif_extclk", + "aclk160", "aclk133", "aclk200", "aclk100", + "sclk_mfc", "sclk_g3d", "aclk400_mcuisp", + "cam_a_pclk", "cam_b_pclk", "s_rxbyteclkhs0_2l", + "s_rxbyteclkhs0_4l", "rx_half_byte_clk_csis0", + "rx_half_byte_clk_csis1", "div_jpeg", + "sclk_pwm_isp", "sclk_spi0_isp", + "sclk_spi1_isp", "sclk_uart_isp", + "sclk_mipihsi", "sclk_hdmi", "sclk_fimd0", + "sclk_pcm0" }; +PNAME(clkout_dmc_p4x12) = { "div_dmcd", "div_dmcp", "aclk_acp", "div_acp_pclk", + "div_dmc", "div_dphy", "fout_mpll_div_2", + "div_pwi", "none", "div_c2c", "div_c2c_aclk" }; +PNAME(clkout_cpu_p4x12) = { "fout_apll_div_2", "none", "none", "none", + "arm_clk_div_2", "div_corem0", "div_corem1", + "div_cores", "div_atb", "div_periph", + "div_pclk_dbg", "div_hpm" }; /* fixed rate clocks generated outside the soc */ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = { @@ -436,6 +513,24 @@ static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = FRATE(0, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000), }; +static struct samsung_fixed_factor_clock exynos4_fixed_factor_clks[] __initdata = { + FFACTOR(0, "sclk_apll_div_2", "sclk_apll", 1, 2, 0), + FFACTOR(0, "fout_mpll_div_2", "fout_mpll", 1, 2, 0), + FFACTOR(0, "fout_apll_div_2", "fout_apll", 1, 2, 0), + FFACTOR(0, "arm_clk_div_2", "arm_clk", 1, 2, 0), +}; + +static struct samsung_fixed_factor_clock exynos4210_fixed_factor_clks[] __initdata = { + FFACTOR(0, "sclk_mpll_div_2", "sclk_mpll", 1, 2, 0), +}; + +static struct samsung_fixed_factor_clock exynos4x12_fixed_factor_clks[] __initdata = { + FFACTOR(0, "sclk_mpll_user_l_div_2", "mout_mpll_user_l", 1, 2, 0), + FFACTOR(0, "sclk_mpll_user_r_div_2", "mout_mpll_user_r", 1, 2, 0), + FFACTOR(0, "sclk_mpll_user_t_div_2", "mout_mpll_user_t", 1, 2, 0), + FFACTOR(0, "sclk_mpll_user_c_div_2", "mout_mpll_user_c", 1, 2, 0), +}; + /* list of mux clocks supported in all exynos4 soc's */ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { MUX_FA(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, @@ -451,6 +546,9 @@ static struct samsung_mux_clock exynos4_mux_clks[] __initdata = { MUX(0, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1), MUX(CLK_SCLK_EPLL, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1), MUX(0, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1), + + MUX(0, "mout_dmc_bus", sclk_ampll_p4210, SRC_DMC, 4, 1), + MUX(0, "mout_dphy", sclk_ampll_p4210, SRC_DMC, 8, 1), }; /* list of mux clocks supported in exynos4210 soc */ @@ -459,6 +557,14 @@ static struct samsung_mux_clock exynos4210_mux_early[] __initdata = { }; static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { + MUX(0, "mout_gdl", sclk_ampll_p4210, SRC_LEFTBUS, 0, 1), + MUX(0, "mout_clkout_leftbus", clkout_left_p4210, + CLKOUT_CMU_LEFTBUS, 0, 5), + + MUX(0, "mout_gdr", sclk_ampll_p4210, SRC_RIGHTBUS, 0, 1), + MUX(0, "mout_clkout_rightbus", clkout_right_p4210, + CLKOUT_CMU_RIGHTBUS, 0, 5), + MUX(0, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1), MUX(0, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1), MUX(0, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1), @@ -472,6 +578,7 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(0, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4), MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1), MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4210, SRC_CPU, 16, 1), + MUX(0, "mout_hpm", mout_core_p4210, SRC_CPU, 20, 1), MUX(CLK_SCLK_VPLL, "sclk_vpll", sclk_vpll_p4210, SRC_TOP0, 8, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4), @@ -503,12 +610,30 @@ static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = { MUX(0, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4), MUX(0, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4), MUX(0, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4), + MUX(0, "mout_clkout_top", clkout_top_p4210, CLKOUT_CMU_TOP, 0, 5), + + MUX(0, "mout_pwi", mout_pwi_p4210, SRC_DMC, 16, 4), + MUX(0, "mout_clkout_dmc", clkout_dmc_p4210, CLKOUT_CMU_DMC, 0, 5), + + MUX(0, "mout_clkout_cpu", clkout_cpu_p4210, CLKOUT_CMU_CPU, 0, 5), }; /* list of mux clocks supported in exynos4x12 soc */ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { + MUX(0, "mout_mpll_user_l", mout_mpll_p, SRC_LEFTBUS, 4, 1), + MUX(0, "mout_gdl", mout_gdl_p4x12, SRC_LEFTBUS, 0, 1), + MUX(0, "mout_clkout_leftbus", clkout_left_p4x12, + CLKOUT_CMU_LEFTBUS, 0, 5), + + MUX(0, "mout_mpll_user_r", mout_mpll_p, SRC_RIGHTBUS, 4, 1), + MUX(0, "mout_gdr", mout_gdr_p4x12, SRC_RIGHTBUS, 0, 1), + MUX(0, "mout_clkout_rightbus", clkout_right_p4x12, + CLKOUT_CMU_RIGHTBUS, 0, 5), + MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p4x12, SRC_CPU, 24, 1), + MUX(0, "mout_clkout_cpu", clkout_cpu_p4x12, CLKOUT_CMU_CPU, 0, 5), + MUX(0, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1), MUX(0, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1), MUX(CLK_MOUT_MPLL_USER_T, "mout_mpll_user_t", mout_mpll_user_p4x12, @@ -531,6 +656,7 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { MUX(CLK_SCLK_MPLL, "sclk_mpll", mout_mpll_p, SRC_DMC, 12, 1), MUX(CLK_SCLK_VPLL, "sclk_vpll", mout_vpll_p, SRC_TOP0, 8, 1), MUX(CLK_MOUT_CORE, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1), + MUX(0, "mout_hpm", mout_core_p4x12, SRC_CPU, 20, 1), MUX(CLK_MOUT_FIMC0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4), MUX(CLK_MOUT_FIMC1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4), MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4), @@ -565,15 +691,39 @@ static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = { MUX(0, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4), MUX(0, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4), MUX(0, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4), + MUX(0, "mout_clkout_top", clkout_top_p4x12, CLKOUT_CMU_TOP, 0, 5), + + MUX(0, "mout_c2c", sclk_ampll_p4210, SRC_DMC, 0, 1), + MUX(0, "mout_pwi", mout_pwi_p4x12, SRC_DMC, 16, 4), MUX(0, "mout_g2d0", sclk_ampll_p4210, SRC_DMC, 20, 1), MUX(0, "mout_g2d1", sclk_evpll_p, SRC_DMC, 24, 1), MUX(0, "mout_g2d", mout_g2d_p, SRC_DMC, 28, 1), + MUX(0, "mout_clkout_dmc", clkout_dmc_p4x12, CLKOUT_CMU_DMC, 0, 5), }; /* list of divider clocks supported in all exynos4 soc's */ static struct samsung_div_clock exynos4_div_clks[] __initdata = { + DIV(0, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 3), + DIV(0, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3), + DIV(0, "div_clkout_leftbus", "mout_clkout_leftbus", + CLKOUT_CMU_LEFTBUS, 8, 6), + + DIV(0, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 3), + DIV(0, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3), + DIV(0, "div_clkout_rightbus", "mout_clkout_rightbus", + CLKOUT_CMU_RIGHTBUS, 8, 6), + DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3), + DIV(0, "div_corem0", "div_core2", DIV_CPU0, 4, 3), + DIV(0, "div_corem1", "div_core2", DIV_CPU0, 8, 3), + DIV(0, "div_periph", "div_core2", DIV_CPU0, 12, 3), + DIV(0, "div_atb", "mout_core", DIV_CPU0, 16, 3), + DIV(0, "div_pclk_dbg", "div_atb", DIV_CPU0, 20, 3), DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3), + DIV(0, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), + DIV(0, "div_hpm", "div_copy", DIV_CPU1, 4, 3), + DIV(0, "div_clkout_cpu", "mout_clkout_cpu", CLKOUT_CMU_CPU, 8, 6), + DIV(0, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4), DIV(0, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4), DIV(0, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4), @@ -631,6 +781,16 @@ static struct samsung_div_clock exynos4_div_clks[] __initdata = { CLK_SET_RATE_PARENT, 0), DIV_F(0, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0), + DIV(0, "div_clkout_top", "mout_clkout_top", CLKOUT_CMU_TOP, 8, 6), + + DIV(0, "div_acp", "mout_dmc_bus", DIV_DMC0, 0, 3), + DIV(0, "div_acp_pclk", "div_acp", DIV_DMC0, 4, 3), + DIV(0, "div_dphy", "mout_dphy", DIV_DMC0, 8, 3), + DIV(0, "div_dmc", "mout_dmc_bus", DIV_DMC0, 12, 3), + DIV(0, "div_dmcd", "div_dmc", DIV_DMC0, 16, 3), + DIV(0, "div_dmcp", "div_dmcd", DIV_DMC0, 20, 3), + DIV(0, "div_pwi", "mout_pwi", DIV_DMC1, 8, 4), + DIV(0, "div_clkout_dmc", "mout_clkout_dmc", CLKOUT_CMU_DMC, 8, 6), }; /* list of divider clocks supported in exynos4210 soc */ @@ -671,6 +831,8 @@ static struct samsung_div_clock exynos4x12_div_clks[] __initdata = { DIV_F(CLK_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3, CLK_GET_RATE_NOCACHE, 0), DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), + DIV(0, "div_c2c", "mout_c2c", DIV_DMC1, 4, 3), + DIV(0, "div_c2c_aclk", "div_c2c", DIV_DMC1, 12, 3), }; /* list of gate clocks supported in all exynos4 soc's */ @@ -680,6 +842,8 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { * the device name and clock alias names specified below for some * of the clocks can be removed. */ + GATE(CLK_PPMULEFT, "ppmuleft", "aclk200", GATE_IP_LEFTBUS, 1, 0, 0), + GATE(CLK_PPMURIGHT, "ppmuright", "aclk200", GATE_IP_RIGHTBUS, 1, 0, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0, 0), @@ -695,11 +859,13 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { GATE(CLK_SROMC, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0), GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_PPMUG3D, "ppmug3d", "aclk200", GATE_IP_G3D, 1, 0, 0), GATE(CLK_USB_DEVICE, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0), GATE(CLK_ONENAND, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0), GATE(CLK_NFCON, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0), GATE(CLK_GPS, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0), GATE(CLK_SMMU_GPS, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0), + GATE(CLK_PPMUGPS, "ppmugps", "aclk200", GATE_IP_GPS, 2, 0, 0), GATE(CLK_SLIMBUS, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0), GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4, CLK_SET_RATE_PARENT, 0), @@ -781,19 +947,24 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { 0, 0), GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11, 0, 0), + GATE(CLK_PPMUCAMIF, "ppmucamif", "aclk160", GATE_IP_CAM, 16, 0, 0), GATE(CLK_PIXELASYNCM0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0), GATE(CLK_PIXELASYNCM1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0), GATE(CLK_SMMU_TV, "smmu_tv", "aclk160", GATE_IP_TV, 4, 0, 0), + GATE(CLK_PPMUTV, "ppmutv", "aclk160", GATE_IP_TV, 5, 0, 0), GATE(CLK_MFC, "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0), GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk100", GATE_IP_MFC, 1, 0, 0), GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk100", GATE_IP_MFC, 2, 0, 0), + GATE(CLK_PPMUMFC_L, "ppmumfc_l", "aclk100", GATE_IP_MFC, 3, 0, 0), + GATE(CLK_PPMUMFC_R, "ppmumfc_r", "aclk100", GATE_IP_MFC, 4, 0, 0), GATE(CLK_FIMD0, "fimd0", "aclk160", GATE_IP_LCD0, 0, 0, 0), GATE(CLK_SMMU_FIMD0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4, 0, 0), + GATE(CLK_PPMULCD0, "ppmulcd0", "aclk160", GATE_IP_LCD0, 5, 0, 0), GATE(CLK_PDMA0, "pdma0", "aclk133", GATE_IP_FSYS, 0, 0, 0), GATE(CLK_PDMA1, "pdma1", "aclk133", GATE_IP_FSYS, 1, @@ -806,6 +977,7 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { 0, 0), GATE(CLK_SDMMC3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8, 0, 0), + GATE(CLK_PPMUFILE, "ppmufile", "aclk133", GATE_IP_FSYS, 17, 0, 0), GATE(CLK_UART0, "uart0", "aclk100", GATE_IP_PERIL, 0, 0, 0), GATE(CLK_UART1, "uart1", "aclk100", GATE_IP_PERIL, 1, @@ -852,6 +1024,21 @@ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { 0, 0), GATE(CLK_AC97, "ac97", "aclk100", GATE_IP_PERIL, 27, 0, 0), + GATE(CLK_PPMUDMC0, "ppmudmc0", "aclk133", GATE_IP_DMC, 8, 0, 0), + GATE(CLK_PPMUDMC1, "ppmudmc1", "aclk133", GATE_IP_DMC, 9, 0, 0), + GATE(CLK_PPMUCPU, "ppmucpu", "aclk133", GATE_IP_DMC, 10, 0, 0), + GATE(CLK_PPMUACP, "ppmuacp", "aclk133", GATE_IP_DMC, 16, 0, 0), + + GATE(CLK_OUT_LEFTBUS, "clkout_leftbus", "div_clkout_leftbus", + CLKOUT_CMU_LEFTBUS, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_OUT_RIGHTBUS, "clkout_rightbus", "div_clkout_rightbus", + CLKOUT_CMU_RIGHTBUS, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_OUT_TOP, "clkout_top", "div_clkout_top", + CLKOUT_CMU_TOP, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_OUT_DMC, "clkout_dmc", "div_clkout_dmc", + CLKOUT_CMU_DMC, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_OUT_CPU, "clkout_cpu", "div_clkout_cpu", + CLKOUT_CMU_CPU, 16, CLK_SET_RATE_PARENT, 0), }; /* list of gate clocks supported in exynos4210 soc */ @@ -863,6 +1050,9 @@ static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = { GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0), GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0, 0), + GATE(CLK_PPMUIMAGE, "ppmuimage", "aclk200", E4210_GATE_IP_IMAGE, 9, 0, + 0), + GATE(CLK_PPMULCD1, "ppmulcd1", "aclk160", E4210_GATE_IP_LCD1, 5, 0, 0), GATE(CLK_PCIE_PHY, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0), GATE(CLK_SATA_PHY, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0), GATE(CLK_SATA, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0), @@ -906,6 +1096,8 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { 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_PPMUIMAGE, "ppmuimage", "aclk200", E4X12_GATE_IP_IMAGE, 9, 0, + 0), GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0), GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0), GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1, @@ -925,21 +1117,13 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(CLK_RTC, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, 0, 0), GATE(CLK_KEYIF, "keyif", "aclk100", E4X12_GATE_IP_PERIR, 16, 0, 0), - GATE(CLK_SCLK_PWM_ISP, "sclk_pwm_isp", "div_pwm_isp", - E4X12_SRC_MASK_ISP, 0, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "div_spi0_isp_pre", - E4X12_SRC_MASK_ISP, 4, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "div_spi1_isp_pre", - E4X12_SRC_MASK_ISP, 8, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "div_uart_isp", - E4X12_SRC_MASK_ISP, 12, CLK_SET_RATE_PARENT, 0), - GATE(CLK_PWM_ISP_SCLK, "pwm_isp_sclk", "sclk_pwm_isp", + GATE(CLK_PWM_ISP_SCLK, "pwm_isp_sclk", "div_pwm_isp", E4X12_GATE_IP_ISP, 0, 0, 0), - GATE(CLK_SPI0_ISP_SCLK, "spi0_isp_sclk", "sclk_spi0_isp", + GATE(CLK_SPI0_ISP_SCLK, "spi0_isp_sclk", "div_spi0_isp_pre", E4X12_GATE_IP_ISP, 1, 0, 0), - GATE(CLK_SPI1_ISP_SCLK, "spi1_isp_sclk", "sclk_spi1_isp", + GATE(CLK_SPI1_ISP_SCLK, "spi1_isp_sclk", "div_spi1_isp_pre", E4X12_GATE_IP_ISP, 2, 0, 0), - GATE(CLK_UART_ISP_SCLK, "uart_isp_sclk", "sclk_uart_isp", + GATE(CLK_UART_ISP_SCLK, "uart_isp_sclk", "div_uart_isp", E4X12_GATE_IP_ISP, 3, 0, 0), GATE(CLK_WDT, "watchdog", "aclk100", E4X12_GATE_IP_PERIR, 14, 0, 0), GATE(CLK_PCM0, "pcm0", "aclk100", E4X12_GATE_IP_MAUDIO, 2, @@ -1070,7 +1254,7 @@ static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx) } -static struct of_device_id ext_clk_match[] __initdata = { +static const struct of_device_id ext_clk_match[] __initconst = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { .compatible = "samsung,clock-xusbxti", .data = (void *)1, }, {}, @@ -1172,6 +1356,32 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { VPLL_LOCK, VPLL_CON0, NULL), }; +static void __init exynos4_core_down_clock(enum exynos4_soc soc) +{ + unsigned int tmp; + + /* + * Enable arm clock down (in idle) and set arm divider + * ratios in WFI/WFE state. + */ + tmp = (PWR_CTRL1_CORE2_DOWN_RATIO(7) | PWR_CTRL1_CORE1_DOWN_RATIO(7) | + 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); + /* On Exynos4412 enable it also on core 2 and 3 */ + if (num_possible_cpus() == 4) + tmp |= PWR_CTRL1_USE_CORE3_WFE | PWR_CTRL1_USE_CORE2_WFE | + PWR_CTRL1_USE_CORE3_WFI | PWR_CTRL1_USE_CORE2_WFI; + __raw_writel(tmp, reg_base + PWR_CTRL1); + + /* + * Disable the clock up feature on Exynos4x12, in case it was + * enabled by bootloader. + */ + if (exynos4_soc == EXYNOS4X12) + __raw_writel(0x0, reg_base + E4X12_PWR_CTRL2); +} + /* register exynos4 clocks */ static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc soc) @@ -1232,6 +1442,8 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4_div_clks)); samsung_clk_register_gate(ctx, exynos4_gate_clks, ARRAY_SIZE(exynos4_gate_clks)); + samsung_clk_register_fixed_factor(ctx, exynos4_fixed_factor_clks, + ARRAY_SIZE(exynos4_fixed_factor_clks)); if (exynos4_soc == EXYNOS4210) { samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks, @@ -1244,6 +1456,9 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4210_gate_clks)); samsung_clk_register_alias(ctx, exynos4210_aliases, ARRAY_SIZE(exynos4210_aliases)); + samsung_clk_register_fixed_factor(ctx, + exynos4210_fixed_factor_clks, + ARRAY_SIZE(exynos4210_fixed_factor_clks)); } else { samsung_clk_register_mux(ctx, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); @@ -1253,13 +1468,19 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4x12_gate_clks)); samsung_clk_register_alias(ctx, exynos4x12_aliases, ARRAY_SIZE(exynos4x12_aliases)); + samsung_clk_register_fixed_factor(ctx, + exynos4x12_fixed_factor_clks, + ARRAY_SIZE(exynos4x12_fixed_factor_clks)); } samsung_clk_register_alias(ctx, exynos4_aliases, ARRAY_SIZE(exynos4_aliases)); + exynos4_core_down_clock(soc); exynos4_clk_sleep_init(); + samsung_clk_of_add_provider(np, ctx); + pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n" "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n", exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12", diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 1fad4c5e3f5d..70ec3d2608a1 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -661,7 +661,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0), GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0), GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub", - GATE_IP_DISP1, 2, 0, 0), + GATE_IP_DISP1, 9, 0, 0), GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 8, 0, 0), GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0), @@ -748,7 +748,7 @@ static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = { VPLL_LOCK, VPLL_CON0, NULL), }; -static struct of_device_id ext_clk_match[] __initdata = { +static const struct of_device_id ext_clk_match[] __initconst = { { .compatible = "samsung,clock-xxti", .data = (void *)0, }, { }, }; @@ -820,6 +820,8 @@ static void __init exynos5250_clk_init(struct device_node *np) exynos5250_clk_sleep_init(); + samsung_clk_of_add_provider(np, ctx); + pr_info("Exynos5250: clock setup completed, armclk=%ld\n", _get_rate("div_arm2")); } diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c index 64596ba58df1..ce3de97e5f11 100644 --- a/drivers/clk/samsung/clk-exynos5260.c +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -206,6 +206,8 @@ void __init exynos5260_cmu_register_one(struct device_node *np, if (cmu->clk_regs) exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, cmu->nr_clk_regs); + + samsung_clk_of_add_provider(np, ctx); } diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c index c9505ab9ee70..231475bc2b99 100644 --- a/drivers/clk/samsung/clk-exynos5410.c +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -204,6 +204,8 @@ static void __init exynos5410_clk_init(struct device_node *np) samsung_clk_register_gate(ctx, exynos5410_gate_clks, ARRAY_SIZE(exynos5410_gate_clks)); + samsung_clk_of_add_provider(np, ctx); + pr_debug("Exynos5410: clock setup completed.\n"); } CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 9d7d7eed03fd..848d602efc06 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -28,6 +28,7 @@ #define GATE_BUS_CPU 0x700 #define GATE_SCLK_CPU 0x800 #define CLKOUT_CMU_CPU 0xa00 +#define SRC_MASK_CPERI 0x4300 #define GATE_IP_G2D 0x8800 #define CPLL_LOCK 0x10020 #define DPLL_LOCK 0x10030 @@ -70,6 +71,8 @@ #define SRC_TOP11 0x10284 #define SRC_TOP12 0x10288 #define SRC_TOP13 0x1028c /* 5800 specific */ +#define SRC_MASK_TOP0 0x10300 +#define SRC_MASK_TOP1 0x10304 #define SRC_MASK_TOP2 0x10308 #define SRC_MASK_TOP7 0x1031c #define SRC_MASK_DISP10 0x1032c @@ -77,6 +80,7 @@ #define SRC_MASK_FSYS 0x10340 #define SRC_MASK_PERIC0 0x10350 #define SRC_MASK_PERIC1 0x10354 +#define SRC_MASK_ISP 0x10370 #define DIV_TOP0 0x10500 #define DIV_TOP1 0x10504 #define DIV_TOP2 0x10508 @@ -98,6 +102,7 @@ #define DIV2_RATIO0 0x10590 #define DIV4_RATIO 0x105a0 #define GATE_BUS_TOP 0x10700 +#define GATE_BUS_DISP1 0x10728 #define GATE_BUS_GEN 0x1073c #define GATE_BUS_FSYS0 0x10740 #define GATE_BUS_FSYS2 0x10748 @@ -190,6 +195,10 @@ static unsigned long exynos5x_clk_regs[] __initdata = { SRC_MASK_FSYS, SRC_MASK_PERIC0, SRC_MASK_PERIC1, + SRC_MASK_TOP0, + SRC_MASK_TOP1, + SRC_MASK_MAU, + SRC_MASK_ISP, SRC_ISP, DIV_TOP0, DIV_TOP1, @@ -208,6 +217,7 @@ static unsigned long exynos5x_clk_regs[] __initdata = { SCLK_DIV_ISP1, DIV2_RATIO0, DIV4_RATIO, + GATE_BUS_DISP1, GATE_BUS_TOP, GATE_BUS_GEN, GATE_BUS_FSYS0, @@ -249,6 +259,22 @@ static unsigned long exynos5800_clk_regs[] __initdata = { GATE_IP_CAM, }; +static const struct samsung_clk_reg_dump exynos5420_set_clksrc[] = { + { .offset = SRC_MASK_CPERI, .value = 0xffffffff, }, + { .offset = SRC_MASK_TOP0, .value = 0x11111111, }, + { .offset = SRC_MASK_TOP1, .value = 0x11101111, }, + { .offset = SRC_MASK_TOP2, .value = 0x11111110, }, + { .offset = SRC_MASK_TOP7, .value = 0x00111100, }, + { .offset = SRC_MASK_DISP10, .value = 0x11111110, }, + { .offset = SRC_MASK_MAU, .value = 0x10000000, }, + { .offset = SRC_MASK_FSYS, .value = 0x11111110, }, + { .offset = SRC_MASK_PERIC0, .value = 0x11111110, }, + { .offset = SRC_MASK_PERIC1, .value = 0x11111100, }, + { .offset = SRC_MASK_ISP, .value = 0x11111000, }, + { .offset = GATE_BUS_DISP1, .value = 0xffffffff, }, + { .offset = GATE_IP_PERIC, .value = 0xffffffff, }, +}; + static int exynos5420_clk_suspend(void) { samsung_clk_save(reg_base, exynos5x_save, @@ -258,6 +284,9 @@ static int exynos5420_clk_suspend(void) samsung_clk_save(reg_base, exynos5800_save, ARRAY_SIZE(exynos5800_clk_regs)); + samsung_clk_restore(reg_base, exynos5420_set_clksrc, + ARRAY_SIZE(exynos5420_set_clksrc)); + return 0; } @@ -631,7 +660,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { 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(CLK_MOUT_USER_ACLK333, "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), @@ -684,7 +714,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { 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(CLK_MOUT_SW_ACLK333, "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), @@ -890,8 +921,6 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen", GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 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", @@ -994,34 +1023,61 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 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), + GATE(CLK_UART0, "uart0", "mout_user_aclk66_peric", + GATE_IP_PERIC, 0, 0, 0), + GATE(CLK_UART1, "uart1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 1, 0, 0), + GATE(CLK_UART2, "uart2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 2, 0, 0), + GATE(CLK_UART3, "uart3", "mout_user_aclk66_peric", + GATE_IP_PERIC, 3, 0, 0), + GATE(CLK_I2C0, "i2c0", "mout_user_aclk66_peric", + GATE_IP_PERIC, 6, 0, 0), + GATE(CLK_I2C1, "i2c1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 7, 0, 0), + GATE(CLK_I2C2, "i2c2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 8, 0, 0), + GATE(CLK_I2C3, "i2c3", "mout_user_aclk66_peric", + GATE_IP_PERIC, 9, 0, 0), + GATE(CLK_USI0, "usi0", "mout_user_aclk66_peric", + GATE_IP_PERIC, 10, 0, 0), + GATE(CLK_USI1, "usi1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 11, 0, 0), + GATE(CLK_USI2, "usi2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 12, 0, 0), + GATE(CLK_USI3, "usi3", "mout_user_aclk66_peric", + GATE_IP_PERIC, 13, 0, 0), + GATE(CLK_I2C_HDMI, "i2c_hdmi", "mout_user_aclk66_peric", + GATE_IP_PERIC, 14, 0, 0), + GATE(CLK_TSADC, "tsadc", "mout_user_aclk66_peric", + GATE_IP_PERIC, 15, 0, 0), + GATE(CLK_SPI0, "spi0", "mout_user_aclk66_peric", + GATE_IP_PERIC, 16, 0, 0), + GATE(CLK_SPI1, "spi1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 17, 0, 0), + GATE(CLK_SPI2, "spi2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 18, 0, 0), + GATE(CLK_I2S1, "i2s1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 20, 0, 0), + GATE(CLK_I2S2, "i2s2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 21, 0, 0), + GATE(CLK_PCM1, "pcm1", "mout_user_aclk66_peric", + GATE_IP_PERIC, 22, 0, 0), + GATE(CLK_PCM2, "pcm2", "mout_user_aclk66_peric", + GATE_IP_PERIC, 23, 0, 0), + GATE(CLK_PWM, "pwm", "mout_user_aclk66_peric", + GATE_IP_PERIC, 24, 0, 0), + GATE(CLK_SPDIF, "spdif", "mout_user_aclk66_peric", + GATE_IP_PERIC, 26, 0, 0), + GATE(CLK_USI4, "usi4", "mout_user_aclk66_peric", + GATE_IP_PERIC, 28, 0, 0), + GATE(CLK_USI5, "usi5", "mout_user_aclk66_peric", + GATE_IP_PERIC, 30, 0, 0), + GATE(CLK_USI6, "usi6", "mout_user_aclk66_peric", + GATE_IP_PERIC, 31, 0, 0), + + GATE(CLK_KEYIF, "keyif", "mout_user_aclk66_peric", + GATE_BUS_PERIC, 22, 0, 0), /* PERIS Block */ GATE(CLK_CHIPID, "chipid", "aclk66_psgen", @@ -1142,6 +1198,28 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), }; +static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] = { + PLL_35XX_RATE(2000000000, 250, 3, 0), + PLL_35XX_RATE(1900000000, 475, 6, 0), + PLL_35XX_RATE(1800000000, 225, 3, 0), + 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, 200, 2, 1), + PLL_35XX_RATE(1100000000, 275, 3, 1), + PLL_35XX_RATE(1000000000, 250, 3, 1), + PLL_35XX_RATE(900000000, 150, 2, 1), + PLL_35XX_RATE(800000000, 200, 3, 1), + PLL_35XX_RATE(700000000, 175, 3, 1), + PLL_35XX_RATE(600000000, 200, 2, 2), + PLL_35XX_RATE(500000000, 250, 3, 2), + PLL_35XX_RATE(400000000, 200, 3, 2), + PLL_35XX_RATE(300000000, 200, 2, 3), + PLL_35XX_RATE(200000000, 200, 3, 3), +}; + 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), @@ -1167,7 +1245,7 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = { KPLL_CON0, NULL), }; -static struct of_device_id ext_clk_match[] __initdata = { +static const struct of_device_id ext_clk_match[] __initconst = { { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, }, { }, }; @@ -1195,6 +1273,12 @@ static void __init exynos5x_clk_init(struct device_node *np, samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks, ARRAY_SIZE(exynos5x_fixed_rate_ext_clks), ext_clk_match); + + if (_get_rate("fin_pll") == 24 * MHZ) { + exynos5x_plls[apll].rate_table = exynos5420_pll2550x_24mhz_tbl; + exynos5x_plls[kpll].rate_table = exynos5420_pll2550x_24mhz_tbl; + } + samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls), reg_base); samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks, @@ -1226,6 +1310,8 @@ static void __init exynos5x_clk_init(struct device_node *np, } exynos5420_clk_sleep_init(); + + samsung_clk_of_add_provider(np, ctx); } static void __init exynos5420_clk_init(struct device_node *np) diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 647f1440aa6a..00d1d00a41de 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -84,7 +84,7 @@ static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0), }; -static struct of_device_id ext_clk_match[] __initdata = { +static const struct of_device_id ext_clk_match[] __initconst = { { .compatible = "samsung,clock-xtal", .data = (void *)0, }, {}, }; @@ -123,6 +123,8 @@ static void __init exynos5440_clk_init(struct device_node *np) samsung_clk_register_gate(ctx, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); + samsung_clk_of_add_provider(np, ctx); + pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); pr_info("exynos5440 clock initialization complete\n"); } diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index ba0716801db2..5d2f03461bc5 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -152,6 +152,11 @@ struct samsung_clock_alias s3c2410_common_aliases[] __initdata = { ALIAS(HCLK, NULL, "hclk"), ALIAS(MPLL, NULL, "mpll"), ALIAS(FCLK, NULL, "fclk"), + ALIAS(PCLK, NULL, "watchdog"), + ALIAS(PCLK_SDI, NULL, "sdi"), + ALIAS(HCLK_NAND, NULL, "nand"), + ALIAS(PCLK_I2S, NULL, "iis"), + ALIAS(PCLK_I2C, NULL, "i2c"), }; /* S3C2410 specific clocks */ @@ -378,7 +383,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, if (!np) s3c2410_common_clk_register_fixed_ext(ctx, xti_f); - if (current_soc == 2410) { + if (current_soc == S3C2410) { if (_get_rate("xti") == 12 * MHZ) { s3c2410_plls[mpll].rate_table = pll_s3c2410_12mhz_tbl; s3c2410_plls[upll].rate_table = pll_s3c2410_12mhz_tbl; @@ -432,7 +437,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor, ARRAY_SIZE(s3c2410_ffactor)); samsung_clk_register_alias(ctx, s3c2410_aliases, - ARRAY_SIZE(s3c2410_common_aliases)); + ARRAY_SIZE(s3c2410_aliases)); break; case S3C2440: samsung_clk_register_mux(ctx, s3c2440_muxes, @@ -461,6 +466,8 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, } s3c2410_clk_sleep_init(); + + samsung_clk_of_add_provider(np, ctx); } static void __init s3c2410_clk_init(struct device_node *np) diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c index 23e4313f625e..34af09f6a155 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -265,6 +265,8 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, ARRAY_SIZE(s3c2412_aliases)); s3c2412_clk_sleep_init(); + + samsung_clk_of_add_provider(np, ctx); } static void __init s3c2412_clk_init(struct device_node *np) diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index c4bbdabebaa4..c92f853fca9f 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -445,6 +445,8 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, } s3c2443_clk_sleep_init(); + + samsung_clk_of_add_provider(np, ctx); } static void __init s3c2416_clk_init(struct device_node *np) diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index efa16ee592c8..0f590e5550cb 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -418,8 +418,10 @@ static struct samsung_clock_alias s3c64xx_clock_aliases[] = { ALIAS(SCLK_MMC2, "s3c-sdhci.2", "mmc_busclk.2"), ALIAS(SCLK_MMC1, "s3c-sdhci.1", "mmc_busclk.2"), ALIAS(SCLK_MMC0, "s3c-sdhci.0", "mmc_busclk.2"), - ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi-bus"), - ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi-bus"), + ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi_busclk0"), + ALIAS(SCLK_SPI1, "s3c6410-spi.1", "spi_busclk2"), + ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi_busclk0"), + ALIAS(SCLK_SPI0, "s3c6410-spi.0", "spi_busclk2"), ALIAS(SCLK_AUDIO1, "samsung-pcm.1", "audio-bus"), ALIAS(SCLK_AUDIO1, "samsung-i2s.1", "audio-bus"), ALIAS(SCLK_AUDIO0, "samsung-pcm.0", "audio-bus"), @@ -516,6 +518,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, ARRAY_SIZE(s3c64xx_clock_aliases)); s3c64xx_clk_sleep_init(); + samsung_clk_of_add_provider(np, ctx); + pr_info("%s clocks: apll = %lu, mpll = %lu\n" "\tepll = %lu, arm_clk = %lu\n", is_s3c6400 ? "S3C6400" : "S3C6410", diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c new file mode 100644 index 000000000000..a8053b4aca56 --- /dev/null +++ b/drivers/clk/samsung/clk-s5pv210-audss.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com> + * + * Based on Exynos Audio Subsystem Clock Controller driver: + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Author: Padmavathi Venna <padma.v@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. + * + * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs. +*/ + +#include <linux/clkdev.h> +#include <linux/io.h> +#include <linux/clk-provider.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <dt-bindings/clock/s5pv210-audss.h> + +static DEFINE_SPINLOCK(lock); +static struct clk **clk_table; +static void __iomem *reg_base; +static struct clk_onecell_data clk_data; + +#define ASS_CLK_SRC 0x0 +#define ASS_CLK_DIV 0x4 +#define ASS_CLK_GATE 0x8 + +#ifdef CONFIG_PM_SLEEP +static unsigned long reg_save[][2] = { + {ASS_CLK_SRC, 0}, + {ASS_CLK_DIV, 0}, + {ASS_CLK_GATE, 0}, +}; + +static int s5pv210_audss_clk_suspend(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_save); i++) + reg_save[i][1] = readl(reg_base + reg_save[i][0]); + + return 0; +} + +static void s5pv210_audss_clk_resume(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(reg_save); i++) + writel(reg_save[i][1], reg_base + reg_save[i][0]); +} + +static struct syscore_ops s5pv210_audss_clk_syscore_ops = { + .suspend = s5pv210_audss_clk_suspend, + .resume = s5pv210_audss_clk_resume, +}; +#endif /* CONFIG_PM_SLEEP */ + +/* register s5pv210_audss clocks */ +static int s5pv210_audss_clk_probe(struct platform_device *pdev) +{ + int i, ret = 0; + struct resource *res; + const char *mout_audss_p[2]; + const char *mout_i2s_p[3]; + const char *hclk_p; + struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(reg_base)) { + dev_err(&pdev->dev, "failed to map audss registers\n"); + return PTR_ERR(reg_base); + } + + clk_table = devm_kzalloc(&pdev->dev, + sizeof(struct clk *) * AUDSS_MAX_CLKS, + GFP_KERNEL); + if (!clk_table) + return -ENOMEM; + + clk_data.clks = clk_table; + clk_data.clk_num = AUDSS_MAX_CLKS; + + hclk = devm_clk_get(&pdev->dev, "hclk"); + if (IS_ERR(hclk)) { + dev_err(&pdev->dev, "failed to get hclk clock\n"); + return PTR_ERR(hclk); + } + + pll_in = devm_clk_get(&pdev->dev, "fout_epll"); + if (IS_ERR(pll_in)) { + dev_err(&pdev->dev, "failed to get fout_epll clock\n"); + return PTR_ERR(pll_in); + } + + sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0"); + if (IS_ERR(sclk_audio)) { + dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n"); + return PTR_ERR(sclk_audio); + } + + /* iiscdclk0 is an optional external I2S codec clock */ + cdclk = devm_clk_get(&pdev->dev, "iiscdclk0"); + pll_ref = devm_clk_get(&pdev->dev, "xxti"); + + if (!IS_ERR(pll_ref)) + mout_audss_p[0] = __clk_get_name(pll_ref); + else + mout_audss_p[0] = "xxti"; + mout_audss_p[1] = __clk_get_name(pll_in); + clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss", + mout_audss_p, ARRAY_SIZE(mout_audss_p), + CLK_SET_RATE_NO_REPARENT, + reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); + + mout_i2s_p[0] = "mout_audss"; + if (!IS_ERR(cdclk)) + mout_i2s_p[1] = __clk_get_name(cdclk); + else + mout_i2s_p[1] = "iiscdclk0"; + mout_i2s_p[2] = __clk_get_name(sclk_audio); + clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss", + mout_i2s_p, ARRAY_SIZE(mout_i2s_p), + CLK_SET_RATE_NO_REPARENT, + reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); + + clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL, + "dout_aud_bus", "mout_audss", 0, + reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); + clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss", + "mout_i2s_audss", 0, reg_base + ASS_CLK_DIV, + 4, 4, 0, &lock); + + clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss", + "dout_i2s_audss", CLK_SET_RATE_PARENT, + reg_base + ASS_CLK_GATE, 6, 0, &lock); + + hclk_p = __clk_get_name(hclk); + + clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 5, 0, &lock); + clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 4, 0, &lock); + clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 3, 0, &lock); + clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 2, 0, &lock); + clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 1, 0, &lock); + clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss", + hclk_p, CLK_IGNORE_UNUSED, + reg_base + ASS_CLK_GATE, 0, 0, &lock); + + for (i = 0; i < clk_data.clk_num; i++) { + if (IS_ERR(clk_table[i])) { + dev_err(&pdev->dev, "failed to register clock %d\n", i); + ret = PTR_ERR(clk_table[i]); + goto unregister; + } + } + + ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, + &clk_data); + if (ret) { + dev_err(&pdev->dev, "failed to add clock provider\n"); + goto unregister; + } + +#ifdef CONFIG_PM_SLEEP + register_syscore_ops(&s5pv210_audss_clk_syscore_ops); +#endif + + return 0; + +unregister: + for (i = 0; i < clk_data.clk_num; i++) { + if (!IS_ERR(clk_table[i])) + clk_unregister(clk_table[i]); + } + + return ret; +} + +static int s5pv210_audss_clk_remove(struct platform_device *pdev) +{ + int i; + + of_clk_del_provider(pdev->dev.of_node); + + for (i = 0; i < clk_data.clk_num; i++) { + if (!IS_ERR(clk_table[i])) + clk_unregister(clk_table[i]); + } + + return 0; +} + +static const struct of_device_id s5pv210_audss_clk_of_match[] = { + { .compatible = "samsung,s5pv210-audss-clock", }, + {}, +}; + +static struct platform_driver s5pv210_audss_clk_driver = { + .driver = { + .name = "s5pv210-audss-clk", + .owner = THIS_MODULE, + .of_match_table = s5pv210_audss_clk_of_match, + }, + .probe = s5pv210_audss_clk_probe, + .remove = s5pv210_audss_clk_remove, +}; + +static int __init s5pv210_audss_clk_init(void) +{ + return platform_driver_register(&s5pv210_audss_clk_driver); +} +core_initcall(s5pv210_audss_clk_init); + +static void __exit s5pv210_audss_clk_exit(void) +{ + platform_driver_unregister(&s5pv210_audss_clk_driver); +} +module_exit(s5pv210_audss_clk_exit); + +MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>"); +MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:s5pv210-audss-clk"); diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c new file mode 100644 index 000000000000..d270a2084644 --- /dev/null +++ b/drivers/clk/samsung/clk-s5pv210.c @@ -0,0 +1,856 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com> + * + * Based on clock drivers for S3C64xx and Exynos4 SoCs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for all S5PC110/S5PV210 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 "clk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/s5pv210.h> + +/* S5PC110/S5PV210 clock controller register offsets */ +#define APLL_LOCK 0x0000 +#define MPLL_LOCK 0x0008 +#define EPLL_LOCK 0x0010 +#define VPLL_LOCK 0x0020 +#define APLL_CON0 0x0100 +#define APLL_CON1 0x0104 +#define MPLL_CON 0x0108 +#define EPLL_CON0 0x0110 +#define EPLL_CON1 0x0114 +#define VPLL_CON 0x0120 +#define CLK_SRC0 0x0200 +#define CLK_SRC1 0x0204 +#define CLK_SRC2 0x0208 +#define CLK_SRC3 0x020c +#define CLK_SRC4 0x0210 +#define CLK_SRC5 0x0214 +#define CLK_SRC6 0x0218 +#define CLK_SRC_MASK0 0x0280 +#define CLK_SRC_MASK1 0x0284 +#define CLK_DIV0 0x0300 +#define CLK_DIV1 0x0304 +#define CLK_DIV2 0x0308 +#define CLK_DIV3 0x030c +#define CLK_DIV4 0x0310 +#define CLK_DIV5 0x0314 +#define CLK_DIV6 0x0318 +#define CLK_DIV7 0x031c +#define CLK_GATE_MAIN0 0x0400 +#define CLK_GATE_MAIN1 0x0404 +#define CLK_GATE_MAIN2 0x0408 +#define CLK_GATE_PERI0 0x0420 +#define CLK_GATE_PERI1 0x0424 +#define CLK_GATE_SCLK0 0x0440 +#define CLK_GATE_SCLK1 0x0444 +#define CLK_GATE_IP0 0x0460 +#define CLK_GATE_IP1 0x0464 +#define CLK_GATE_IP2 0x0468 +#define CLK_GATE_IP3 0x046c +#define CLK_GATE_IP4 0x0470 +#define CLK_GATE_BLOCK 0x0480 +#define CLK_GATE_IP5 0x0484 +#define CLK_OUT 0x0500 +#define MISC 0xe000 +#define OM_STAT 0xe100 + +/* IDs of PLLs available on S5PV210/S5P6442 SoCs */ +enum { + apll, + mpll, + epll, + vpll, +}; + +/* IDs of external clocks (used for legacy boards) */ +enum { + xxti, + xusbxti, +}; + +static void __iomem *reg_base; + +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *s5pv210_clk_dump; + +/* List of registers that need to be preserved across suspend/resume. */ +static unsigned long s5pv210_clk_regs[] __initdata = { + CLK_SRC0, + CLK_SRC1, + CLK_SRC2, + CLK_SRC3, + CLK_SRC4, + CLK_SRC5, + CLK_SRC6, + CLK_SRC_MASK0, + CLK_SRC_MASK1, + CLK_DIV0, + CLK_DIV1, + CLK_DIV2, + CLK_DIV3, + CLK_DIV4, + CLK_DIV5, + CLK_DIV6, + CLK_DIV7, + CLK_GATE_MAIN0, + CLK_GATE_MAIN1, + CLK_GATE_MAIN2, + CLK_GATE_PERI0, + CLK_GATE_PERI1, + CLK_GATE_SCLK0, + CLK_GATE_SCLK1, + CLK_GATE_IP0, + CLK_GATE_IP1, + CLK_GATE_IP2, + CLK_GATE_IP3, + CLK_GATE_IP4, + CLK_GATE_IP5, + CLK_GATE_BLOCK, + APLL_LOCK, + MPLL_LOCK, + EPLL_LOCK, + VPLL_LOCK, + APLL_CON0, + APLL_CON1, + MPLL_CON, + EPLL_CON0, + EPLL_CON1, + VPLL_CON, + CLK_OUT, +}; + +static int s5pv210_clk_suspend(void) +{ + samsung_clk_save(reg_base, s5pv210_clk_dump, + ARRAY_SIZE(s5pv210_clk_regs)); + return 0; +} + +static void s5pv210_clk_resume(void) +{ + samsung_clk_restore(reg_base, s5pv210_clk_dump, + ARRAY_SIZE(s5pv210_clk_regs)); +} + +static struct syscore_ops s5pv210_clk_syscore_ops = { + .suspend = s5pv210_clk_suspend, + .resume = s5pv210_clk_resume, +}; + +static void s5pv210_clk_sleep_init(void) +{ + s5pv210_clk_dump = + samsung_clk_alloc_reg_dump(s5pv210_clk_regs, + ARRAY_SIZE(s5pv210_clk_regs)); + if (!s5pv210_clk_dump) { + pr_warn("%s: Failed to allocate sleep save data\n", __func__); + return; + } + + register_syscore_ops(&s5pv210_clk_syscore_ops); +} +#else +static inline void s5pv210_clk_sleep_init(void) { } +#endif + +/* Mux parent lists. */ +static const char *fin_pll_p[] __initconst = { + "xxti", + "xusbxti" +}; + +static const char *mout_apll_p[] __initconst = { + "fin_pll", + "fout_apll" +}; + +static const char *mout_mpll_p[] __initconst = { + "fin_pll", + "fout_mpll" +}; + +static const char *mout_epll_p[] __initconst = { + "fin_pll", + "fout_epll" +}; + +static const char *mout_vpllsrc_p[] __initconst = { + "fin_pll", + "sclk_hdmi27m" +}; + +static const char *mout_vpll_p[] __initconst = { + "mout_vpllsrc", + "fout_vpll" +}; + +static const char *mout_group1_p[] __initconst = { + "dout_a2m", + "mout_mpll", + "mout_epll", + "mout_vpll" +}; + +static const char *mout_group2_p[] __initconst = { + "xxti", + "xusbxti", + "sclk_hdmi27m", + "sclk_usbphy0", + "sclk_usbphy1", + "sclk_hdmiphy", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_audio0_p[] __initconst = { + "xxti", + "pcmcdclk0", + "sclk_hdmi27m", + "sclk_usbphy0", + "sclk_usbphy1", + "sclk_hdmiphy", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_audio1_p[] __initconst = { + "i2scdclk1", + "pcmcdclk1", + "sclk_hdmi27m", + "sclk_usbphy0", + "sclk_usbphy1", + "sclk_hdmiphy", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_audio2_p[] __initconst = { + "i2scdclk2", + "pcmcdclk2", + "sclk_hdmi27m", + "sclk_usbphy0", + "sclk_usbphy1", + "sclk_hdmiphy", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_spdif_p[] __initconst = { + "dout_audio0", + "dout_audio1", + "dout_audio3", +}; + +static const char *mout_group3_p[] __initconst = { + "mout_apll", + "mout_mpll" +}; + +static const char *mout_group4_p[] __initconst = { + "mout_mpll", + "dout_a2m" +}; + +static const char *mout_flash_p[] __initconst = { + "dout_hclkd", + "dout_hclkp" +}; + +static const char *mout_dac_p[] __initconst = { + "mout_vpll", + "sclk_hdmiphy" +}; + +static const char *mout_hdmi_p[] __initconst = { + "sclk_hdmiphy", + "dout_tblk" +}; + +static const char *mout_mixer_p[] __initconst = { + "mout_dac", + "mout_hdmi" +}; + +static const char *mout_vpll_6442_p[] __initconst = { + "fin_pll", + "fout_vpll" +}; + +static const char *mout_mixer_6442_p[] __initconst = { + "mout_vpll", + "dout_mixer" +}; + +static const char *mout_d0sync_6442_p[] __initconst = { + "mout_dsys", + "div_apll" +}; + +static const char *mout_d1sync_6442_p[] __initconst = { + "mout_psys", + "div_apll" +}; + +static const char *mout_group2_6442_p[] __initconst = { + "fin_pll", + "none", + "none", + "sclk_usbphy0", + "none", + "none", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_audio0_6442_p[] __initconst = { + "fin_pll", + "pcmcdclk0", + "none", + "sclk_usbphy0", + "none", + "none", + "mout_mpll", + "mout_epll", + "mout_vpll", +}; + +static const char *mout_audio1_6442_p[] __initconst = { + "i2scdclk1", + "pcmcdclk1", + "none", + "sclk_usbphy0", + "none", + "none", + "mout_mpll", + "mout_epll", + "mout_vpll", + "fin_pll", +}; + +static const char *mout_clksel_p[] __initconst = { + "fout_apll_clkout", + "fout_mpll_clkout", + "fout_epll", + "fout_vpll", + "sclk_usbphy0", + "sclk_usbphy1", + "sclk_hdmiphy", + "rtc", + "rtc_tick", + "dout_hclkm", + "dout_pclkm", + "dout_hclkd", + "dout_pclkd", + "dout_hclkp", + "dout_pclkp", + "dout_apll_clkout", + "dout_hpm", + "xxti", + "xusbxti", + "div_dclk" +}; + +static const char *mout_clksel_6442_p[] __initconst = { + "fout_apll_clkout", + "fout_mpll_clkout", + "fout_epll", + "fout_vpll", + "sclk_usbphy0", + "none", + "none", + "rtc", + "rtc_tick", + "none", + "none", + "dout_hclkd", + "dout_pclkd", + "dout_hclkp", + "dout_pclkp", + "dout_apll_clkout", + "none", + "fin_pll", + "none", + "div_dclk" +}; + +static const char *mout_clkout_p[] __initconst = { + "dout_clkout", + "none", + "xxti", + "xusbxti" +}; + +/* Common fixed factor clocks. */ +static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = { + FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0), + FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0), + FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0), +}; + +/* PLL input mux (fin_pll), which needs to be registered before PLLs. */ +static struct samsung_mux_clock early_mux_clks[] __initdata = { + MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1, + CLK_MUX_READ_ONLY, 0), +}; + +/* Common clock muxes. */ +static struct samsung_mux_clock mux_clks[] __initdata = { + MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1), + MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1), + MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1), + MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1), + MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1), + MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1), + MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1), + + MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2), +}; + +/* S5PV210-specific clock muxes. */ +static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = { + MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1), + + MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1), + MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4), + MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4), + MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4), + MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4), + MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1), + MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1), + MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1), + + MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2), + MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2), + MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2), + + MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4), + MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4), + MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4), + + MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4), + MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4), + MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4), + MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4), + MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4), + MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4), + MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4), + MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4), + + MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4), + MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4), + MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4), + + MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2), + MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4), + MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1), + MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2), + MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4), + MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4), + MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4), + + MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5), +}; + +/* S5P6442-specific clock muxes. */ +static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = { + MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1), + + MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4), + MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4), + MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4), + MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1), + + MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1), + MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1), + + MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4), + MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4), + MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4), + + MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4), + MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4), + MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4), + MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4), + MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4), + MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4), + + MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4), + MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4), + + MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4), + MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4), + + MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5), +}; + +/* S5PV210-specific fixed rate clocks generated inside the SoC. */ +static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = { + FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000), + FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), + FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), + FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000), +}; + +/* S5P6442-specific fixed rate clocks generated inside the SoC. */ +static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = { + FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000), +}; + +/* Common clock dividers. */ +static struct samsung_div_clock div_clks[] __initdata = { + DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3), + DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3), + DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3), + DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3), + + DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4), + DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4), + DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4), + + DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4), + DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4), + DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4), + + DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4), + DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4), + DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4), + DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4), + DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4), + DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4), + + DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4), + DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4), + + DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3), + DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4), + DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4), + + DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4), +}; + +/* S5PV210-specific clock dividers. */ +static struct samsung_div_clock s5pv210_div_clks[] __initdata = { + DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4), + DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4), + DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3), + DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3), + + DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4), + DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4), + + DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4), + DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4), + DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4), + + DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4), + DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4), + + DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4), + + DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4), + DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4), + DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3), + DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3), + DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4), + + DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7), + DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7), +}; + +/* S5P6442-specific clock dividers. */ +static struct samsung_div_clock s5p6442_div_clks[] __initdata = { + DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4), + DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4), + + DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4), +}; + +/* Common clock gates. */ +static struct samsung_gate_clock gate_clks[] __initdata = { + GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0), + GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0), + GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0), + GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0), + GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0), + GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0), + + GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0), + GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0), + GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0), + GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0), + GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0), + GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0), + GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0), + + GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0), + GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0), + GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0), + GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0), + GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0), + + GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0), + GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0), + GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0), + GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0), + GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0), + GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0), + GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0), + GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0), + GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0), + GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0), + GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0), + GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0), + GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0), + GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0), + GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0), + GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0), + + GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0), + GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0), + + GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1, + CLK_SET_RATE_PARENT, 0), + + GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2, + CLK_SET_RATE_PARENT, 0), +}; + +/* S5PV210-specific clock gates. */ +static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = { + GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0), + GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0), + GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0), + GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0), + GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0), + GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0), + + GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0), + GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0), + GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0), + GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0), + GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0), + + GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0), + GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0), + GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0), + GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0), + GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0), + GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0), + GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0), + GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0), + GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0), + + GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0), + GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0), + GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0), + GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd", + CLK_GATE_IP3, 11, 0, 0), + GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0), + GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0), + GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0), + GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0), + + GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0), + GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0), + GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0), + GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0), + GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0), + GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0), + + GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0), + + GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2, + CLK_SET_RATE_PARENT, 0), + GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0, + CLK_SET_RATE_PARENT, 0), +}; + +/* S5P6442-specific clock gates. */ +static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = { + GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0), + GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0), + GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0), + GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0), + GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0), + + GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0), + GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0), + + GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0), + + GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2, + CLK_SET_RATE_PARENT, 0), +}; + +/* + * Clock aliases for legacy clkdev look-up. + * NOTE: Needed only to support legacy board files. + */ +static struct samsung_clock_alias s5pv210_aliases[] = { + ALIAS(DOUT_APLL, NULL, "armclk"), + ALIAS(DOUT_HCLKM, NULL, "hclk_msys"), + ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"), +}; + +/* S5PV210-specific PLLs. */ +static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = { + [apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON, NULL), + [epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), + [vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc", + VPLL_LOCK, VPLL_CON, NULL), +}; + +/* S5P6442-specific PLLs. */ +static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = { + [apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON, NULL), + [epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll", + EPLL_LOCK, EPLL_CON0, NULL), + [vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll", + VPLL_LOCK, VPLL_CON, NULL), +}; + +static void __init __s5pv210_clk_init(struct device_node *np, + unsigned long xxti_f, + unsigned long xusbxti_f, + bool is_s5p6442) +{ + struct samsung_clk_provider *ctx; + + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_register_mux(ctx, early_mux_clks, + ARRAY_SIZE(early_mux_clks)); + + if (is_s5p6442) { + samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks, + ARRAY_SIZE(s5p6442_frate_clks)); + samsung_clk_register_pll(ctx, s5p6442_pll_clks, + ARRAY_SIZE(s5p6442_pll_clks), reg_base); + samsung_clk_register_mux(ctx, s5p6442_mux_clks, + ARRAY_SIZE(s5p6442_mux_clks)); + samsung_clk_register_div(ctx, s5p6442_div_clks, + ARRAY_SIZE(s5p6442_div_clks)); + samsung_clk_register_gate(ctx, s5p6442_gate_clks, + ARRAY_SIZE(s5p6442_gate_clks)); + } else { + samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks, + ARRAY_SIZE(s5pv210_frate_clks)); + samsung_clk_register_pll(ctx, s5pv210_pll_clks, + ARRAY_SIZE(s5pv210_pll_clks), reg_base); + samsung_clk_register_mux(ctx, s5pv210_mux_clks, + ARRAY_SIZE(s5pv210_mux_clks)); + samsung_clk_register_div(ctx, s5pv210_div_clks, + ARRAY_SIZE(s5pv210_div_clks)); + samsung_clk_register_gate(ctx, s5pv210_gate_clks, + ARRAY_SIZE(s5pv210_gate_clks)); + } + + 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)); + + samsung_clk_register_fixed_factor(ctx, ffactor_clks, + ARRAY_SIZE(ffactor_clks)); + + samsung_clk_register_alias(ctx, s5pv210_aliases, + ARRAY_SIZE(s5pv210_aliases)); + + s5pv210_clk_sleep_init(); + + pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n" + "\tmout_epll = %ld, mout_vpll = %ld\n", + is_s5p6442 ? "S5P6442" : "S5PV210", + _get_rate("mout_apll"), _get_rate("mout_mpll"), + _get_rate("mout_epll"), _get_rate("mout_vpll")); +} + +static void __init s5pv210_clk_dt_init(struct device_node *np) +{ + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + __s5pv210_clk_init(np, 0, 0, false); +} +CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init); + +static void __init s5p6442_clk_dt_init(struct device_node *np) +{ + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + __s5pv210_clk_init(np, 0, 0, true); +} +CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 49629c71c9e7..deab84d9f37d 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -53,7 +53,6 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, { struct samsung_clk_provider *ctx; struct clk **clk_table; - int ret; int i; ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL); @@ -72,17 +71,19 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, ctx->clk_data.clk_num = nr_clks; spin_lock_init(&ctx->lock); - if (!np) - return ctx; - - 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; } +void __init samsung_clk_of_add_provider(struct device_node *np, + struct samsung_clk_provider *ctx) +{ + if (np) { + if (of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data)) + panic("could not register clk provider\n"); + } +} + /* add a clock instance to the clock lookup table used for dt based lookup */ void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, unsigned int id) @@ -284,7 +285,7 @@ void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, 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 *clk_matches) { const struct of_device_id *match; struct device_node *clk_np; diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 9693b80d924f..66ab36b5cef1 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -327,11 +327,13 @@ struct samsung_pll_clock { 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_add_provider(struct device_node *np, + struct samsung_clk_provider *ctx); extern 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 *clk_matches); extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, unsigned int id); |