aboutsummaryrefslogtreecommitdiff
path: root/drivers/clk/samsung
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/samsung')
-rw-r--r--drivers/clk/samsung/Kconfig26
-rw-r--r--drivers/clk/samsung/Makefile18
-rw-r--r--drivers/clk/samsung/clk-exynos-audss.c248
-rw-r--r--drivers/clk/samsung/clk-exynos3250.c780
-rw-r--r--drivers/clk/samsung/clk-exynos4.c1274
-rw-r--r--drivers/clk/samsung/clk-exynos5250.c826
-rw-r--r--drivers/clk/samsung/clk-exynos5260.c1980
-rw-r--r--drivers/clk/samsung/clk-exynos5260.h459
-rw-r--r--drivers/clk/samsung/clk-exynos5410.c209
-rw-r--r--drivers/clk/samsung/clk-exynos5420.c1268
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c129
-rw-r--r--drivers/clk/samsung/clk-pll.c1298
-rw-r--r--drivers/clk/samsung/clk-pll.h104
-rw-r--r--drivers/clk/samsung/clk-s3c2410-dclk.c440
-rw-r--r--drivers/clk/samsung/clk-s3c2410.c487
-rw-r--r--drivers/clk/samsung/clk-s3c2412.c274
-rw-r--r--drivers/clk/samsung/clk-s3c2443.c466
-rw-r--r--drivers/clk/samsung/clk-s3c64xx.c538
-rw-r--r--drivers/clk/samsung/clk.c314
-rw-r--r--drivers/clk/samsung/clk.h375
20 files changed, 11513 insertions, 0 deletions
diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig
new file mode 100644
index 00000000000..84196ecdaa1
--- /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
new file mode 100644
index 00000000000..69e81773164
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,18 @@
+#
+# Samsung Clock specific Makefile
+#
+
+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_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_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-exynos-audss.c b/drivers/clk/samsung/clk-exynos-audss.c
new file mode 100644
index 00000000000..13eae14c2cc
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos-audss.c
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ *
+ * Common Clock Framework support for Audio Subsystem Clock Controller.
+*/
+
+#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/exynos-audss-clk.h>
+
+enum exynos_audss_clk_type {
+ TYPE_EXYNOS4210,
+ TYPE_EXYNOS5250,
+ TYPE_EXYNOS5420,
+};
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+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 exynos_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 exynos_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 exynos_audss_clk_syscore_ops = {
+ .suspend = exynos_audss_clk_suspend,
+ .resume = exynos_audss_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct of_device_id exynos_audss_clk_of_match[] = {
+ { .compatible = "samsung,exynos4210-audss-clock",
+ .data = (void *)TYPE_EXYNOS4210, },
+ { .compatible = "samsung,exynos5250-audss-clock",
+ .data = (void *)TYPE_EXYNOS5250, },
+ { .compatible = "samsung,exynos5420-audss-clock",
+ .data = (void *)TYPE_EXYNOS5420, },
+ {},
+};
+
+/* register exynos_audss clocks */
+static int exynos_audss_clk_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct resource *res;
+ const char *mout_audss_p[] = {"fin_pll", "fout_epll"};
+ const char *mout_i2s_p[] = {"mout_audss", "cdclk0", "sclk_audio0"};
+ const char *sclk_pcm_p = "sclk_pcm0";
+ struct clk *pll_ref, *pll_in, *cdclk, *sclk_audio, *sclk_pcm_in;
+ const struct of_device_id *match;
+ enum exynos_audss_clk_type variant;
+
+ match = of_match_node(exynos_audss_clk_of_match, pdev->dev.of_node);
+ if (!match)
+ return -EINVAL;
+ variant = (enum exynos_audss_clk_type)match->data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg_base = devm_ioremap_resource(&pdev->dev, res);
+ 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 *) * EXYNOS_AUDSS_MAX_CLKS,
+ GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ clk_data.clks = clk_table;
+ if (variant == TYPE_EXYNOS5420)
+ clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS;
+ else
+ clk_data.clk_num = EXYNOS_AUDSS_MAX_CLKS - 1;
+
+ pll_ref = devm_clk_get(&pdev->dev, "pll_ref");
+ pll_in = devm_clk_get(&pdev->dev, "pll_in");
+ if (!IS_ERR(pll_ref))
+ mout_audss_p[0] = __clk_get_name(pll_ref);
+ if (!IS_ERR(pll_in))
+ mout_audss_p[1] = __clk_get_name(pll_in);
+ clk_table[EXYNOS_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);
+
+ cdclk = devm_clk_get(&pdev->dev, "cdclk");
+ sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio");
+ if (!IS_ERR(cdclk))
+ mout_i2s_p[1] = __clk_get_name(cdclk);
+ if (!IS_ERR(sclk_audio))
+ mout_i2s_p[2] = __clk_get_name(sclk_audio);
+ clk_table[EXYNOS_MOUT_I2S] = clk_register_mux(NULL, "mout_i2s",
+ mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
+ CLK_SET_RATE_NO_REPARENT,
+ reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
+
+ clk_table[EXYNOS_DOUT_SRP] = clk_register_divider(NULL, "dout_srp",
+ "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4,
+ 0, &lock);
+
+ clk_table[EXYNOS_DOUT_AUD_BUS] = clk_register_divider(NULL,
+ "dout_aud_bus", "dout_srp", 0,
+ reg_base + ASS_CLK_DIV, 4, 4, 0, &lock);
+
+ clk_table[EXYNOS_DOUT_I2S] = clk_register_divider(NULL, "dout_i2s",
+ "mout_i2s", 0, reg_base + ASS_CLK_DIV, 8, 4, 0,
+ &lock);
+
+ clk_table[EXYNOS_SRP_CLK] = clk_register_gate(NULL, "srp_clk",
+ "dout_srp", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 0, 0, &lock);
+
+ clk_table[EXYNOS_I2S_BUS] = clk_register_gate(NULL, "i2s_bus",
+ "dout_aud_bus", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 2, 0, &lock);
+
+ clk_table[EXYNOS_SCLK_I2S] = clk_register_gate(NULL, "sclk_i2s",
+ "dout_i2s", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 3, 0, &lock);
+
+ clk_table[EXYNOS_PCM_BUS] = clk_register_gate(NULL, "pcm_bus",
+ "sclk_pcm", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 4, 0, &lock);
+
+ sclk_pcm_in = devm_clk_get(&pdev->dev, "sclk_pcm_in");
+ if (!IS_ERR(sclk_pcm_in))
+ sclk_pcm_p = __clk_get_name(sclk_pcm_in);
+ clk_table[EXYNOS_SCLK_PCM] = clk_register_gate(NULL, "sclk_pcm",
+ sclk_pcm_p, CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 5, 0, &lock);
+
+ if (variant == TYPE_EXYNOS5420) {
+ clk_table[EXYNOS_ADMA] = clk_register_gate(NULL, "adma",
+ "dout_srp", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 9, 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(&exynos_audss_clk_syscore_ops);
+#endif
+
+ dev_info(&pdev->dev, "setup completed\n");
+
+ 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 exynos_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 struct platform_driver exynos_audss_clk_driver = {
+ .driver = {
+ .name = "exynos-audss-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = exynos_audss_clk_of_match,
+ },
+ .probe = exynos_audss_clk_probe,
+ .remove = exynos_audss_clk_remove,
+};
+
+static int __init exynos_audss_clk_init(void)
+{
+ return platform_driver_register(&exynos_audss_clk_driver);
+}
+core_initcall(exynos_audss_clk_init);
+
+static void __exit exynos_audss_clk_exit(void)
+{
+ platform_driver_unregister(&exynos_audss_clk_driver);
+}
+module_exit(exynos_audss_clk_exit);
+
+MODULE_AUTHOR("Padmavathi Venna <padma.v@samsung.com>");
+MODULE_DESCRIPTION("Exynos Audio Subsystem Clock Controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:exynos-audss-clk");
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
new file mode 100644
index 00000000000..7a17bd40d1d
--- /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
new file mode 100644
index 00000000000..7f4a473a7ad
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,1274 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all Exynos4 SoCs.
+*/
+
+#include <dt-bindings/clock/exynos4.h>
+#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"
+
+/* Exynos4 clock controller register offsets */
+#define SRC_LEFTBUS 0x4200
+#define DIV_LEFTBUS 0x4500
+#define GATE_IP_LEFTBUS 0x4800
+#define E4X12_GATE_IP_IMAGE 0x4930
+#define SRC_RIGHTBUS 0x8200
+#define DIV_RIGHTBUS 0x8500
+#define GATE_IP_RIGHTBUS 0x8800
+#define E4X12_GATE_IP_PERIR 0x8960
+#define EPLL_LOCK 0xc010
+#define VPLL_LOCK 0xc020
+#define EPLL_CON0 0xc110
+#define EPLL_CON1 0xc114
+#define EPLL_CON2 0xc118
+#define VPLL_CON0 0xc120
+#define VPLL_CON1 0xc124
+#define VPLL_CON2 0xc128
+#define SRC_TOP0 0xc210
+#define SRC_TOP1 0xc214
+#define SRC_CAM 0xc220
+#define SRC_TV 0xc224
+#define SRC_MFC 0xc228
+#define SRC_G3D 0xc22c
+#define E4210_SRC_IMAGE 0xc230
+#define SRC_LCD0 0xc234
+#define E4210_SRC_LCD1 0xc238
+#define E4X12_SRC_ISP 0xc238
+#define SRC_MAUDIO 0xc23c
+#define SRC_FSYS 0xc240
+#define SRC_PERIL0 0xc250
+#define SRC_PERIL1 0xc254
+#define E4X12_SRC_CAM1 0xc258
+#define SRC_MASK_TOP 0xc310
+#define SRC_MASK_CAM 0xc320
+#define SRC_MASK_TV 0xc324
+#define SRC_MASK_LCD0 0xc334
+#define E4210_SRC_MASK_LCD1 0xc338
+#define E4X12_SRC_MASK_ISP 0xc338
+#define SRC_MASK_MAUDIO 0xc33c
+#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_TV 0xc524
+#define DIV_MFC 0xc528
+#define DIV_G3D 0xc52c
+#define DIV_IMAGE 0xc530
+#define DIV_LCD0 0xc534
+#define E4210_DIV_LCD1 0xc538
+#define E4X12_DIV_ISP 0xc538
+#define DIV_MAUDIO 0xc53c
+#define DIV_FSYS0 0xc540
+#define DIV_FSYS1 0xc544
+#define DIV_FSYS2 0xc548
+#define DIV_FSYS3 0xc54c
+#define DIV_PERIL0 0xc550
+#define DIV_PERIL1 0xc554
+#define DIV_PERIL2 0xc558
+#define DIV_PERIL3 0xc55c
+#define DIV_PERIL4 0xc560
+#define DIV_PERIL5 0xc564
+#define E4X12_DIV_CAM1 0xc568
+#define GATE_SCLK_CAM 0xc820
+#define GATE_IP_CAM 0xc920
+#define GATE_IP_TV 0xc924
+#define GATE_IP_MFC 0xc928
+#define GATE_IP_G3D 0xc92c
+#define E4210_GATE_IP_IMAGE 0xc930
+#define GATE_IP_LCD0 0xc934
+#define E4210_GATE_IP_LCD1 0xc938
+#define E4X12_GATE_IP_ISP 0xc938
+#define E4X12_GATE_IP_MAUDIO 0xc93c
+#define GATE_IP_FSYS 0xc940
+#define GATE_IP_GPS 0xc94c
+#define GATE_IP_PERIL 0xc950
+#define E4210_GATE_IP_PERIR 0xc960
+#define GATE_BLOCK 0xc970
+#define E4X12_MPLL_LOCK 0x10008
+#define E4X12_MPLL_CON0 0x10108
+#define SRC_DMC 0x10200
+#define SRC_MASK_DMC 0x10300
+#define DIV_DMC0 0x10500
+#define DIV_DMC1 0x10504
+#define GATE_IP_DMC 0x10900
+#define APLL_LOCK 0x14000
+#define E4210_MPLL_LOCK 0x14008
+#define APLL_CON0 0x14100
+#define E4210_MPLL_CON0 0x14108
+#define SRC_CPU 0x14200
+#define DIV_CPU0 0x14500
+#define DIV_CPU1 0x14504
+#define GATE_SCLK_CPU 0x14800
+#define GATE_IP_CPU 0x14900
+#define E4X12_DIV_ISP0 0x18300
+#define E4X12_DIV_ISP1 0x18304
+#define E4X12_GATE_ISP0 0x18800
+#define E4X12_GATE_ISP1 0x18804
+
+/* the exynos4 soc type */
+enum exynos4_soc {
+ EXYNOS4210,
+ EXYNOS4X12,
+};
+
+/* list of PLLs to be registered */
+enum exynos4_plls {
+ apll, mpll, epll, vpll,
+ nr_plls /* number of PLLs */
+};
+
+static void __iomem *reg_base;
+static enum exynos4_soc exynos4_soc;
+
+/*
+ * Support for CMU save/restore across system suspends
+ */
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos4_save_common;
+static struct samsung_clk_reg_dump *exynos4_save_soc;
+static struct samsung_clk_reg_dump *exynos4_save_pll;
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static unsigned long exynos4210_clk_save[] __initdata = {
+ E4210_SRC_IMAGE,
+ E4210_SRC_LCD1,
+ E4210_SRC_MASK_LCD1,
+ E4210_DIV_LCD1,
+ E4210_GATE_IP_IMAGE,
+ E4210_GATE_IP_LCD1,
+ E4210_GATE_IP_PERIR,
+ E4210_MPLL_CON0,
+};
+
+static unsigned long exynos4x12_clk_save[] __initdata = {
+ E4X12_GATE_IP_IMAGE,
+ E4X12_GATE_IP_PERIR,
+ E4X12_SRC_CAM1,
+ E4X12_DIV_ISP,
+ E4X12_DIV_CAM1,
+ E4X12_MPLL_CON0,
+};
+
+static unsigned long exynos4_clk_pll_regs[] __initdata = {
+ EPLL_LOCK,
+ VPLL_LOCK,
+ EPLL_CON0,
+ EPLL_CON1,
+ EPLL_CON2,
+ VPLL_CON0,
+ VPLL_CON1,
+ VPLL_CON2,
+};
+
+static unsigned long exynos4_clk_regs[] __initdata = {
+ SRC_LEFTBUS,
+ DIV_LEFTBUS,
+ GATE_IP_LEFTBUS,
+ SRC_RIGHTBUS,
+ DIV_RIGHTBUS,
+ GATE_IP_RIGHTBUS,
+ SRC_TOP0,
+ SRC_TOP1,
+ SRC_CAM,
+ SRC_TV,
+ SRC_MFC,
+ SRC_G3D,
+ SRC_LCD0,
+ SRC_MAUDIO,
+ SRC_FSYS,
+ SRC_PERIL0,
+ SRC_PERIL1,
+ SRC_MASK_TOP,
+ SRC_MASK_CAM,
+ SRC_MASK_TV,
+ SRC_MASK_LCD0,
+ SRC_MASK_MAUDIO,
+ SRC_MASK_FSYS,
+ SRC_MASK_PERIL0,
+ SRC_MASK_PERIL1,
+ DIV_TOP,
+ DIV_CAM,
+ DIV_TV,
+ DIV_MFC,
+ DIV_G3D,
+ DIV_IMAGE,
+ DIV_LCD0,
+ DIV_MAUDIO,
+ DIV_FSYS0,
+ DIV_FSYS1,
+ DIV_FSYS2,
+ DIV_FSYS3,
+ DIV_PERIL0,
+ DIV_PERIL1,
+ DIV_PERIL2,
+ DIV_PERIL3,
+ DIV_PERIL4,
+ DIV_PERIL5,
+ GATE_SCLK_CAM,
+ GATE_IP_CAM,
+ GATE_IP_TV,
+ GATE_IP_MFC,
+ GATE_IP_G3D,
+ GATE_IP_LCD0,
+ GATE_IP_FSYS,
+ GATE_IP_GPS,
+ GATE_IP_PERIL,
+ GATE_BLOCK,
+ SRC_MASK_DMC,
+ SRC_DMC,
+ DIV_DMC0,
+ DIV_DMC1,
+ GATE_IP_DMC,
+ APLL_CON0,
+ SRC_CPU,
+ DIV_CPU0,
+ DIV_CPU1,
+ GATE_SCLK_CPU,
+ GATE_IP_CPU,
+};
+
+static const struct samsung_clk_reg_dump src_mask_suspend[] = {
+ { .offset = SRC_MASK_TOP, .value = 0x00000001, },
+ { .offset = SRC_MASK_CAM, .value = 0x11111111, },
+ { .offset = SRC_MASK_TV, .value = 0x00000111, },
+ { .offset = SRC_MASK_LCD0, .value = 0x00001111, },
+ { .offset = SRC_MASK_MAUDIO, .value = 0x00000001, },
+ { .offset = SRC_MASK_FSYS, .value = 0x01011111, },
+ { .offset = SRC_MASK_PERIL0, .value = 0x01111111, },
+ { .offset = SRC_MASK_PERIL1, .value = 0x01110111, },
+ { .offset = SRC_MASK_DMC, .value = 0x00010000, },
+};
+
+static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
+ { .offset = E4210_SRC_MASK_LCD1, .value = 0x00001111, },
+};
+
+#define PLL_ENABLED (1 << 31)
+#define PLL_LOCKED (1 << 29)
+
+static void exynos4_clk_wait_for_pll(u32 reg)
+{
+ u32 pll_con;
+
+ pll_con = readl(reg_base + reg);
+ if (!(pll_con & PLL_ENABLED))
+ return;
+
+ while (!(pll_con & PLL_LOCKED)) {
+ cpu_relax();
+ pll_con = readl(reg_base + reg);
+ }
+}
+
+static int exynos4_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, exynos4_save_common,
+ ARRAY_SIZE(exynos4_clk_regs));
+ samsung_clk_save(reg_base, exynos4_save_pll,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
+
+ if (exynos4_soc == EXYNOS4210) {
+ samsung_clk_save(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4210_clk_save));
+ samsung_clk_restore(reg_base, src_mask_suspend_e4210,
+ ARRAY_SIZE(src_mask_suspend_e4210));
+ } else {
+ samsung_clk_save(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4x12_clk_save));
+ }
+
+ samsung_clk_restore(reg_base, src_mask_suspend,
+ ARRAY_SIZE(src_mask_suspend));
+
+ return 0;
+}
+
+static void exynos4_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, exynos4_save_pll,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
+
+ exynos4_clk_wait_for_pll(EPLL_CON0);
+ exynos4_clk_wait_for_pll(VPLL_CON0);
+
+ samsung_clk_restore(reg_base, exynos4_save_common,
+ ARRAY_SIZE(exynos4_clk_regs));
+
+ if (exynos4_soc == EXYNOS4210)
+ samsung_clk_restore(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4210_clk_save));
+ else
+ samsung_clk_restore(reg_base, exynos4_save_soc,
+ ARRAY_SIZE(exynos4x12_clk_save));
+}
+
+static struct syscore_ops exynos4_clk_syscore_ops = {
+ .suspend = exynos4_clk_suspend,
+ .resume = exynos4_clk_resume,
+};
+
+static void __init exynos4_clk_sleep_init(void)
+{
+ exynos4_save_common = samsung_clk_alloc_reg_dump(exynos4_clk_regs,
+ ARRAY_SIZE(exynos4_clk_regs));
+ if (!exynos4_save_common)
+ goto err_warn;
+
+ if (exynos4_soc == EXYNOS4210)
+ exynos4_save_soc = samsung_clk_alloc_reg_dump(
+ exynos4210_clk_save,
+ ARRAY_SIZE(exynos4210_clk_save));
+ else
+ exynos4_save_soc = samsung_clk_alloc_reg_dump(
+ exynos4x12_clk_save,
+ ARRAY_SIZE(exynos4x12_clk_save));
+ if (!exynos4_save_soc)
+ goto err_common;
+
+ exynos4_save_pll = samsung_clk_alloc_reg_dump(exynos4_clk_pll_regs,
+ ARRAY_SIZE(exynos4_clk_pll_regs));
+ if (!exynos4_save_pll)
+ goto err_soc;
+
+ register_syscore_ops(&exynos4_clk_syscore_ops);
+ return;
+
+err_soc:
+ kfree(exynos4_save_soc);
+err_common:
+ kfree(exynos4_save_common);
+err_warn:
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+}
+#else
+static void __init exynos4_clk_sleep_init(void) {}
+#endif
+
+/* list of all parent clock list */
+PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
+PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", };
+PNAME(mout_epll_p) = { "fin_pll", "fout_epll", };
+PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi24m", };
+PNAME(mout_vpll_p) = { "fin_pll", "fout_vpll", };
+PNAME(sclk_evpll_p) = { "sclk_epll", "sclk_vpll", };
+PNAME(mout_mfc_p) = { "mout_mfc0", "mout_mfc1", };
+PNAME(mout_g3d_p) = { "mout_g3d0", "mout_g3d1", };
+PNAME(mout_g2d_p) = { "mout_g2d0", "mout_g2d1", };
+PNAME(mout_hdmi_p) = { "sclk_pixel", "sclk_hdmiphy", };
+PNAME(mout_jpeg_p) = { "mout_jpeg0", "mout_jpeg1", };
+PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+ "spdif_extclk", };
+PNAME(mout_onenand_p) = {"aclk133", "aclk160", };
+PNAME(mout_onenand1_p) = {"mout_onenand", "sclk_vpll", };
+
+/* Exynos 4210-specific parent groups */
+PNAME(sclk_vpll_p4210) = { "mout_vpllsrc", "fout_vpll", };
+PNAME(mout_core_p4210) = { "mout_apll", "sclk_mpll", };
+PNAME(sclk_ampll_p4210) = { "sclk_mpll", "sclk_apll", };
+PNAME(group1_p4210) = { "xxti", "xusbxti", "sclk_hdmi24m",
+ "sclk_usbphy0", "none", "sclk_hdmiphy",
+ "sclk_mpll", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4210) = { "cdclk0", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+ "sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4210) = { "cdclk1", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+ "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+ "sclk_epll", "sclk_vpll", };
+PNAME(mout_mixer_p4210) = { "sclk_dac", "sclk_hdmi", };
+PNAME(mout_dac_p4210) = { "sclk_vpll", "sclk_hdmiphy", };
+
+/* 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(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",
+ "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4x12) = { "cdclk0", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti",
+ "mout_mpll_user_t", "sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4x12) = { "cdclk1", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti",
+ "mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4x12) = { "cdclk2", "none", "sclk_hdmi24m",
+ "sclk_usbphy0", "xxti", "xusbxti",
+ "mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+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", };
+
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+ FRATE(CLK_XXTI, "xxti", NULL, CLK_IS_ROOT, 0),
+ FRATE(CLK_XUSBXTI, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* 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(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+ FRATE(0, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* 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,
+ CLK_SET_RATE_PARENT, 0, "mout_apll"),
+ MUX(0, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
+ MUX(0, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
+ MUX(0, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
+ MUX_F(CLK_MOUT_G3D1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1,
+ CLK_SET_RATE_PARENT, 0),
+ MUX_F(CLK_MOUT_G3D, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1,
+ CLK_SET_RATE_PARENT, 0),
+ MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIL1, 8, 2),
+ 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),
+};
+
+/* list of mux clocks supported in exynos4210 soc */
+static struct samsung_mux_clock exynos4210_mux_early[] __initdata = {
+ MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
+};
+
+static struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+ 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),
+ MUX(0, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
+ MUX(0, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
+ MUX(0, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
+ MUX(0, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
+ MUX(0, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1),
+ MUX(0, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
+ MUX(0, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
+ 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(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),
+ MUX(CLK_MOUT_FIMC2, "mout_fimc2", group1_p4210, SRC_CAM, 8, 4),
+ MUX(CLK_MOUT_FIMC3, "mout_fimc3", group1_p4210, SRC_CAM, 12, 4),
+ MUX(CLK_MOUT_CAM0, "mout_cam0", group1_p4210, SRC_CAM, 16, 4),
+ MUX(CLK_MOUT_CAM1, "mout_cam1", group1_p4210, SRC_CAM, 20, 4),
+ MUX(CLK_MOUT_CSIS0, "mout_csis0", group1_p4210, SRC_CAM, 24, 4),
+ MUX(CLK_MOUT_CSIS1, "mout_csis1", group1_p4210, SRC_CAM, 28, 4),
+ MUX(0, "mout_mfc0", sclk_ampll_p4210, SRC_MFC, 0, 1),
+ MUX_F(CLK_MOUT_G3D0, "mout_g3d0", sclk_ampll_p4210, SRC_G3D, 0, 1,
+ CLK_SET_RATE_PARENT, 0),
+ MUX(0, "mout_fimd0", group1_p4210, SRC_LCD0, 0, 4),
+ MUX(0, "mout_mipi0", group1_p4210, SRC_LCD0, 12, 4),
+ MUX(0, "mout_audio0", mout_audio0_p4210, SRC_MAUDIO, 0, 4),
+ MUX(0, "mout_mmc0", group1_p4210, SRC_FSYS, 0, 4),
+ MUX(0, "mout_mmc1", group1_p4210, SRC_FSYS, 4, 4),
+ MUX(0, "mout_mmc2", group1_p4210, SRC_FSYS, 8, 4),
+ MUX(0, "mout_mmc3", group1_p4210, SRC_FSYS, 12, 4),
+ MUX(0, "mout_mmc4", group1_p4210, SRC_FSYS, 16, 4),
+ MUX(0, "mout_sata", sclk_ampll_p4210, SRC_FSYS, 24, 1),
+ MUX(0, "mout_uart0", group1_p4210, SRC_PERIL0, 0, 4),
+ MUX(0, "mout_uart1", group1_p4210, SRC_PERIL0, 4, 4),
+ MUX(0, "mout_uart2", group1_p4210, SRC_PERIL0, 8, 4),
+ MUX(0, "mout_uart3", group1_p4210, SRC_PERIL0, 12, 4),
+ MUX(0, "mout_uart4", group1_p4210, SRC_PERIL0, 16, 4),
+ MUX(0, "mout_audio1", mout_audio1_p4210, SRC_PERIL1, 0, 4),
+ MUX(0, "mout_audio2", mout_audio2_p4210, SRC_PERIL1, 4, 4),
+ 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),
+};
+
+/* list of mux clocks supported in exynos4x12 soc */
+static struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+ MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p4x12,
+ SRC_CPU, 24, 1),
+ 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,
+ SRC_TOP1, 12, 1),
+ MUX(0, "mout_user_aclk266_gps", mout_user_aclk266_gps_p4x12,
+ SRC_TOP1, 16, 1),
+ MUX(CLK_ACLK200, "aclk200", mout_user_aclk200_p4x12, SRC_TOP1, 20, 1),
+ MUX(CLK_ACLK400_MCUISP, "aclk400_mcuisp",
+ mout_user_aclk400_mcuisp_p4x12, SRC_TOP1, 24, 1),
+ MUX(0, "mout_aclk200", aclk_p4412, SRC_TOP0, 12, 1),
+ MUX(0, "mout_aclk100", aclk_p4412, SRC_TOP0, 16, 1),
+ MUX(0, "mout_aclk160", aclk_p4412, SRC_TOP0, 20, 1),
+ MUX(0, "mout_aclk133", aclk_p4412, SRC_TOP0, 24, 1),
+ MUX(0, "mout_mdnie0", group1_p4x12, SRC_LCD0, 4, 4),
+ MUX(0, "mout_mdnie_pwm0", group1_p4x12, SRC_LCD0, 8, 4),
+ MUX(0, "mout_sata", sclk_ampll_p4x12, SRC_FSYS, 24, 1),
+ MUX(0, "mout_jpeg0", sclk_ampll_p4x12, E4X12_SRC_CAM1, 0, 1),
+ MUX(0, "mout_jpeg1", sclk_evpll_p, E4X12_SRC_CAM1, 4, 1),
+ MUX(0, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
+ 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(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),
+ MUX(CLK_MOUT_FIMC3, "mout_fimc3", group1_p4x12, SRC_CAM, 12, 4),
+ MUX(CLK_MOUT_CAM0, "mout_cam0", group1_p4x12, SRC_CAM, 16, 4),
+ MUX(CLK_MOUT_CAM1, "mout_cam1", group1_p4x12, SRC_CAM, 20, 4),
+ MUX(CLK_MOUT_CSIS0, "mout_csis0", group1_p4x12, SRC_CAM, 24, 4),
+ MUX(CLK_MOUT_CSIS1, "mout_csis1", group1_p4x12, SRC_CAM, 28, 4),
+ MUX(0, "mout_mfc0", sclk_ampll_p4x12, SRC_MFC, 0, 1),
+ MUX_F(CLK_MOUT_G3D0, "mout_g3d0", sclk_ampll_p4x12, SRC_G3D, 0, 1,
+ CLK_SET_RATE_PARENT, 0),
+ MUX(0, "mout_fimd0", group1_p4x12, SRC_LCD0, 0, 4),
+ MUX(0, "mout_mipi0", group1_p4x12, SRC_LCD0, 12, 4),
+ MUX(0, "mout_audio0", mout_audio0_p4x12, SRC_MAUDIO, 0, 4),
+ MUX(0, "mout_mmc0", group1_p4x12, SRC_FSYS, 0, 4),
+ MUX(0, "mout_mmc1", group1_p4x12, SRC_FSYS, 4, 4),
+ MUX(0, "mout_mmc2", group1_p4x12, SRC_FSYS, 8, 4),
+ MUX(0, "mout_mmc3", group1_p4x12, SRC_FSYS, 12, 4),
+ MUX(0, "mout_mmc4", group1_p4x12, SRC_FSYS, 16, 4),
+ MUX(0, "mout_mipihsi", aclk_p4412, SRC_FSYS, 24, 1),
+ MUX(0, "mout_uart0", group1_p4x12, SRC_PERIL0, 0, 4),
+ MUX(0, "mout_uart1", group1_p4x12, SRC_PERIL0, 4, 4),
+ MUX(0, "mout_uart2", group1_p4x12, SRC_PERIL0, 8, 4),
+ MUX(0, "mout_uart3", group1_p4x12, SRC_PERIL0, 12, 4),
+ MUX(0, "mout_uart4", group1_p4x12, SRC_PERIL0, 16, 4),
+ MUX(0, "mout_audio1", mout_audio1_p4x12, SRC_PERIL1, 0, 4),
+ MUX(0, "mout_audio2", mout_audio2_p4x12, SRC_PERIL1, 4, 4),
+ MUX(0, "mout_spi0", group1_p4x12, SRC_PERIL1, 16, 4),
+ MUX(0, "mout_spi1", group1_p4x12, SRC_PERIL1, 20, 4),
+ MUX(0, "mout_spi2", group1_p4x12, SRC_PERIL1, 24, 4),
+ MUX(0, "mout_pwm_isp", group1_p4x12, E4X12_SRC_ISP, 0, 4),
+ 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_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),
+};
+
+/* list of divider clocks supported in all exynos4 soc's */
+static struct samsung_div_clock exynos4_div_clks[] __initdata = {
+ DIV(0, "div_core", "mout_core", DIV_CPU0, 0, 3),
+ DIV(0, "div_core2", "div_core", DIV_CPU0, 28, 3),
+ 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),
+ DIV(0, "div_fimc3", "mout_fimc3", DIV_CAM, 12, 4),
+ DIV(0, "div_cam0", "mout_cam0", DIV_CAM, 16, 4),
+ DIV(0, "div_cam1", "mout_cam1", DIV_CAM, 20, 4),
+ DIV(0, "div_csis0", "mout_csis0", DIV_CAM, 24, 4),
+ DIV(0, "div_csis1", "mout_csis1", DIV_CAM, 28, 4),
+ DIV(CLK_SCLK_MFC, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4),
+ DIV_F(0, "div_g3d", "mout_g3d", DIV_G3D, 0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4),
+ DIV(0, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4),
+ DIV(0, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4),
+ DIV(CLK_SCLK_PCM0, "sclk_pcm0", "sclk_audio0", DIV_MAUDIO, 4, 8),
+ DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+ DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+ DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+ DIV(0, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
+ DIV(CLK_SCLK_PIXEL, "sclk_pixel", "sclk_vpll", DIV_TV, 0, 4),
+ DIV(CLK_ACLK100, "aclk100", "mout_aclk100", DIV_TOP, 4, 4),
+ DIV(CLK_ACLK160, "aclk160", "mout_aclk160", DIV_TOP, 8, 3),
+ DIV(CLK_ACLK133, "aclk133", "mout_aclk133", DIV_TOP, 12, 3),
+ DIV(0, "div_onenand", "mout_onenand1", DIV_TOP, 16, 3),
+ DIV(CLK_SCLK_SLIMBUS, "sclk_slimbus", "sclk_epll", DIV_PERIL3, 4, 4),
+ DIV(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_audio1", DIV_PERIL4, 4, 8),
+ DIV(CLK_SCLK_PCM2, "sclk_pcm2", "sclk_audio2", DIV_PERIL4, 20, 8),
+ DIV(CLK_SCLK_I2S1, "sclk_i2s1", "sclk_audio1", DIV_PERIL5, 0, 6),
+ DIV(CLK_SCLK_I2S2, "sclk_i2s2", "sclk_audio2", DIV_PERIL5, 8, 6),
+ DIV(0, "div_mmc4", "mout_mmc4", DIV_FSYS3, 0, 4),
+ DIV_F(0, "div_mmc_pre4", "div_mmc4", DIV_FSYS3, 8, 8,
+ CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4),
+ DIV(0, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4),
+ DIV(0, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4),
+ DIV(0, "div_uart3", "mout_uart3", DIV_PERIL0, 12, 4),
+ DIV(0, "div_uart4", "mout_uart4", DIV_PERIL0, 16, 4),
+ DIV(0, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4),
+ DIV(0, "div_spi_pre0", "div_spi0", DIV_PERIL1, 8, 8),
+ DIV(0, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4),
+ DIV(0, "div_spi_pre1", "div_spi1", DIV_PERIL1, 24, 8),
+ DIV(0, "div_spi2", "mout_spi2", DIV_PERIL2, 0, 4),
+ DIV(0, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
+ DIV(0, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
+ DIV(0, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
+ DIV(CLK_ARM_CLK, "arm_clk", "div_core2", DIV_CPU0, 28, 3),
+ DIV(CLK_SCLK_APLL, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
+ DIV_F(0, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre1", "div_mmc1", DIV_FSYS1, 24, 8,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre2", "div_mmc2", DIV_FSYS2, 8, 8,
+ CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4210 soc */
+static struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+ DIV(CLK_ACLK200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+ DIV(CLK_SCLK_FIMG2D, "sclk_fimg2d", "mout_g2d", DIV_IMAGE, 0, 4),
+ DIV(0, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
+ DIV(0, "div_mipi1", "mout_mipi1", E4210_DIV_LCD1, 16, 4),
+ DIV(0, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+ DIV_F(0, "div_mipi_pre1", "div_mipi1", E4210_DIV_LCD1, 20, 4,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4x12 soc */
+static struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+ DIV(0, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
+ DIV(0, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
+ DIV(0, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
+ DIV(0, "div_mipihsi", "mout_mipihsi", DIV_FSYS0, 20, 4),
+ DIV(0, "div_jpeg", "mout_jpeg", E4X12_DIV_CAM1, 0, 4),
+ DIV(CLK_DIV_ACLK200, "div_aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+ DIV(0, "div_aclk266_gps", "mout_aclk266_gps", DIV_TOP, 20, 3),
+ DIV(CLK_DIV_ACLK400_MCUISP, "div_aclk400_mcuisp", "mout_aclk400_mcuisp",
+ DIV_TOP, 24, 3),
+ DIV(0, "div_pwm_isp", "mout_pwm_isp", E4X12_DIV_ISP, 0, 4),
+ DIV(0, "div_spi0_isp", "mout_spi0_isp", E4X12_DIV_ISP, 4, 4),
+ DIV(0, "div_spi0_isp_pre", "div_spi0_isp", E4X12_DIV_ISP, 8, 8),
+ DIV(0, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
+ DIV(0, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
+ DIV(0, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
+ DIV_F(CLK_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
+ CLK_GET_RATE_NOCACHE, 0),
+ DIV_F(CLK_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
+ CLK_GET_RATE_NOCACHE, 0),
+ DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
+ DIV_F(CLK_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
+ 4, 3, CLK_GET_RATE_NOCACHE, 0),
+ 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),
+};
+
+/* list of gate clocks supported in all exynos4 soc's */
+static struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+ /*
+ * After all Exynos4 based platforms are migrated to use device tree,
+ * the device name and clock alias names specified below for some
+ * of the clocks can be removed.
+ */
+ 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),
+ GATE(CLK_JPEG, "jpeg", "aclk160", GATE_IP_CAM, 6, 0, 0),
+ GATE(CLK_MIE0, "mie0", "aclk160", GATE_IP_LCD0, 1, 0, 0),
+ GATE(CLK_DSIM0, "dsim0", "aclk160", GATE_IP_LCD0, 3, 0, 0),
+ GATE(CLK_FIMD1, "fimd1", "aclk160", E4210_GATE_IP_LCD1, 0, 0, 0),
+ GATE(CLK_MIE1, "mie1", "aclk160", E4210_GATE_IP_LCD1, 1, 0, 0),
+ GATE(CLK_DSIM1, "dsim1", "aclk160", E4210_GATE_IP_LCD1, 3, 0, 0),
+ GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "aclk160", E4210_GATE_IP_LCD1, 4, 0,
+ 0),
+ GATE(CLK_TSI, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0),
+ 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_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_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),
+ GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1", GATE_SCLK_CAM, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MIPI0, "sclk_mipi0", "div_mipi_pre0",
+ SRC_MASK_LCD0, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_audio0", SRC_MASK_MAUDIO, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_audio1", SRC_MASK_PERIL1, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_VP, "vp", "aclk160", GATE_IP_TV, 0, 0, 0),
+ GATE(CLK_MIXER, "mixer", "aclk160", GATE_IP_TV, 1, 0, 0),
+ GATE(CLK_HDMI, "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0),
+ GATE(CLK_PWM, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0),
+ GATE(CLK_SDMMC4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0),
+ GATE(CLK_USB_HOST, "usb_host", "aclk133", GATE_IP_FSYS, 12, 0, 0),
+ GATE(CLK_SCLK_FIMC0, "sclk_fimc0", "div_fimc0", SRC_MASK_CAM, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_FIMC1, "sclk_fimc1", "div_fimc1", SRC_MASK_CAM, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_FIMC2, "sclk_fimc2", "div_fimc2", SRC_MASK_CAM, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_FIMC3, "sclk_fimc3", "div_fimc3", SRC_MASK_CAM, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_CSIS0, "sclk_csis0", "div_csis0", SRC_MASK_CAM, 24,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_CSIS1, "sclk_csis1", "div_csis1", SRC_MASK_CAM, 28,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_FIMD0, "sclk_fimd0", "div_fimd0", SRC_MASK_LCD0, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1", SRC_MASK_FSYS, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2", SRC_MASK_FSYS, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC3, "sclk_mmc3", "div_mmc_pre3", SRC_MASK_FSYS, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC4, "sclk_mmc4", "div_mmc_pre4", SRC_MASK_FSYS, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART0, "uclk0", "div_uart0", SRC_MASK_PERIL0, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART1, "uclk1", "div_uart1", SRC_MASK_PERIL0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART2, "uclk2", "div_uart2", SRC_MASK_PERIL0, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART3, "uclk3", "div_uart3", SRC_MASK_PERIL0, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART4, "uclk4", "div_uart4", SRC_MASK_PERIL0, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_AUDIO2, "sclk_audio2", "div_audio2", SRC_MASK_PERIL1, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi_pre0", SRC_MASK_PERIL1, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi_pre1", SRC_MASK_PERIL1, 20,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI2, "sclk_spi2", "div_spi_pre2", SRC_MASK_PERIL1, 24,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_FIMC0, "fimc0", "aclk160", GATE_IP_CAM, 0,
+ 0, 0),
+ GATE(CLK_FIMC1, "fimc1", "aclk160", GATE_IP_CAM, 1,
+ 0, 0),
+ GATE(CLK_FIMC2, "fimc2", "aclk160", GATE_IP_CAM, 2,
+ 0, 0),
+ GATE(CLK_FIMC3, "fimc3", "aclk160", GATE_IP_CAM, 3,
+ 0, 0),
+ GATE(CLK_CSIS0, "csis0", "aclk160", GATE_IP_CAM, 4,
+ 0, 0),
+ GATE(CLK_CSIS1, "csis1", "aclk160", GATE_IP_CAM, 5,
+ 0, 0),
+ GATE(CLK_SMMU_FIMC0, "smmu_fimc0", "aclk160", GATE_IP_CAM, 7,
+ 0, 0),
+ GATE(CLK_SMMU_FIMC1, "smmu_fimc1", "aclk160", GATE_IP_CAM, 8,
+ 0, 0),
+ GATE(CLK_SMMU_FIMC2, "smmu_fimc2", "aclk160", GATE_IP_CAM, 9,
+ 0, 0),
+ GATE(CLK_SMMU_FIMC3, "smmu_fimc3", "aclk160", GATE_IP_CAM, 10,
+ 0, 0),
+ GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk160", GATE_IP_CAM, 11,
+ 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_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_FIMD0, "fimd0", "aclk160", GATE_IP_LCD0, 0,
+ 0, 0),
+ GATE(CLK_SMMU_FIMD0, "smmu_fimd0", "aclk160", GATE_IP_LCD0, 4,
+ 0, 0),
+ GATE(CLK_PDMA0, "pdma0", "aclk133", GATE_IP_FSYS, 0,
+ 0, 0),
+ GATE(CLK_PDMA1, "pdma1", "aclk133", GATE_IP_FSYS, 1,
+ 0, 0),
+ GATE(CLK_SDMMC0, "sdmmc0", "aclk133", GATE_IP_FSYS, 5,
+ 0, 0),
+ GATE(CLK_SDMMC1, "sdmmc1", "aclk133", GATE_IP_FSYS, 6,
+ 0, 0),
+ GATE(CLK_SDMMC2, "sdmmc2", "aclk133", GATE_IP_FSYS, 7,
+ 0, 0),
+ GATE(CLK_SDMMC3, "sdmmc3", "aclk133", GATE_IP_FSYS, 8,
+ 0, 0),
+ GATE(CLK_UART0, "uart0", "aclk100", GATE_IP_PERIL, 0,
+ 0, 0),
+ GATE(CLK_UART1, "uart1", "aclk100", GATE_IP_PERIL, 1,
+ 0, 0),
+ GATE(CLK_UART2, "uart2", "aclk100", GATE_IP_PERIL, 2,
+ 0, 0),
+ GATE(CLK_UART3, "uart3", "aclk100", GATE_IP_PERIL, 3,
+ 0, 0),
+ GATE(CLK_UART4, "uart4", "aclk100", GATE_IP_PERIL, 4,
+ 0, 0),
+ GATE(CLK_I2C0, "i2c0", "aclk100", GATE_IP_PERIL, 6,
+ 0, 0),
+ GATE(CLK_I2C1, "i2c1", "aclk100", GATE_IP_PERIL, 7,
+ 0, 0),
+ GATE(CLK_I2C2, "i2c2", "aclk100", GATE_IP_PERIL, 8,
+ 0, 0),
+ GATE(CLK_I2C3, "i2c3", "aclk100", GATE_IP_PERIL, 9,
+ 0, 0),
+ GATE(CLK_I2C4, "i2c4", "aclk100", GATE_IP_PERIL, 10,
+ 0, 0),
+ GATE(CLK_I2C5, "i2c5", "aclk100", GATE_IP_PERIL, 11,
+ 0, 0),
+ GATE(CLK_I2C6, "i2c6", "aclk100", GATE_IP_PERIL, 12,
+ 0, 0),
+ GATE(CLK_I2C7, "i2c7", "aclk100", GATE_IP_PERIL, 13,
+ 0, 0),
+ GATE(CLK_I2C_HDMI, "i2c-hdmi", "aclk100", GATE_IP_PERIL, 14,
+ 0, 0),
+ GATE(CLK_SPI0, "spi0", "aclk100", GATE_IP_PERIL, 16,
+ 0, 0),
+ GATE(CLK_SPI1, "spi1", "aclk100", GATE_IP_PERIL, 17,
+ 0, 0),
+ GATE(CLK_SPI2, "spi2", "aclk100", GATE_IP_PERIL, 18,
+ 0, 0),
+ GATE(CLK_I2S1, "i2s1", "aclk100", GATE_IP_PERIL, 20,
+ 0, 0),
+ GATE(CLK_I2S2, "i2s2", "aclk100", GATE_IP_PERIL, 21,
+ 0, 0),
+ GATE(CLK_PCM1, "pcm1", "aclk100", GATE_IP_PERIL, 22,
+ 0, 0),
+ GATE(CLK_PCM2, "pcm2", "aclk100", GATE_IP_PERIL, 23,
+ 0, 0),
+ GATE(CLK_SPDIF, "spdif", "aclk100", GATE_IP_PERIL, 26,
+ 0, 0),
+ GATE(CLK_AC97, "ac97", "aclk100", GATE_IP_PERIL, 27,
+ 0, 0),
+};
+
+/* list of gate clocks supported in exynos4210 soc */
+static struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+ GATE(CLK_TVENC, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
+ GATE(CLK_G2D, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
+ GATE(CLK_ROTATOR, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
+ GATE(CLK_MDMA, "mdma", "aclk200", E4210_GATE_IP_IMAGE, 2, 0, 0),
+ 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_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),
+ GATE(CLK_PCIE, "pcie", "aclk133", GATE_IP_FSYS, 14, 0, 0),
+ GATE(CLK_SMMU_PCIE, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
+ GATE(CLK_MODEMIF, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
+ GATE(CLK_CHIPID, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+ GATE(CLK_SYSREG, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0,
+ CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0,
+ 0),
+ GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "aclk200",
+ E4210_GATE_IP_IMAGE, 4, 0, 0),
+ GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "div_mipi_pre1",
+ E4210_SRC_MASK_LCD1, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SATA, "sclk_sata", "div_sata",
+ SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MIXER, "sclk_mixer", "mout_mixer", SRC_MASK_TV, 4, 0, 0),
+ GATE(CLK_SCLK_DAC, "sclk_dac", "mout_dac", SRC_MASK_TV, 8, 0, 0),
+ GATE(CLK_TSADC, "tsadc", "aclk100", GATE_IP_PERIL, 15,
+ 0, 0),
+ GATE(CLK_MCT, "mct", "aclk100", E4210_GATE_IP_PERIR, 13,
+ 0, 0),
+ GATE(CLK_WDT, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14,
+ 0, 0),
+ GATE(CLK_RTC, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15,
+ 0, 0),
+ GATE(CLK_KEYIF, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16,
+ 0, 0),
+ GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "div_fimd1", E4210_SRC_MASK_LCD1, 0,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4210_GATE_IP_PERIR, 17, 0,
+ 0),
+};
+
+/* list of gate clocks supported in exynos4x12 soc */
+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_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),
+ GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
+ GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
+ CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0,
+ 0),
+ GATE(CLK_SCLK_MDNIE0, "sclk_mdnie0", "div_mdnie0",
+ SRC_MASK_LCD0, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MDNIE_PWM0, "sclk_mdnie_pwm0", "div_mdnie_pwm_pre0",
+ SRC_MASK_LCD0, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MIPIHSI, "sclk_mipihsi", "div_mipihsi",
+ SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "aclk200",
+ E4X12_GATE_IP_IMAGE, 4, 0, 0),
+ GATE(CLK_MCT, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13,
+ 0, 0),
+ 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_PWM_ISP_SCLK, "pwm_isp_sclk", "div_pwm_isp",
+ E4X12_GATE_IP_ISP, 0, 0, 0),
+ 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", "div_spi1_isp_pre",
+ E4X12_GATE_IP_ISP, 2, 0, 0),
+ 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,
+ 0, 0),
+ GATE(CLK_I2S0, "i2s0", "aclk100", E4X12_GATE_IP_MAUDIO, 3,
+ 0, 0),
+ GATE(CLK_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_PPMUISPX, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_MCUCTL_ISP, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_MPWM_ISP, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_I2C0_ISP, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_I2C1_ISP, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_MTCADC_ISP, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_PWM_ISP, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_WDT_ISP, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_UART_ISP, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_ASYNCAXIM, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SMMU_ISPCX, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SPI0_ISP, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
+ CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
+ GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
+ GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
+ 0),
+};
+
+static struct samsung_clock_alias exynos4_aliases[] __initdata = {
+ ALIAS(CLK_MOUT_CORE, NULL, "moutcore"),
+ ALIAS(CLK_ARM_CLK, NULL, "armclk"),
+ ALIAS(CLK_SCLK_APLL, NULL, "mout_apll"),
+};
+
+static struct samsung_clock_alias exynos4210_aliases[] __initdata = {
+ ALIAS(CLK_SCLK_MPLL, NULL, "mout_mpll"),
+};
+
+static struct samsung_clock_alias exynos4x12_aliases[] __initdata = {
+ ALIAS(CLK_MOUT_MPLL_USER_C, NULL, "mout_mpll"),
+};
+
+/*
+ * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit
+ * resides in chipid register space, outside of the clock controller memory
+ * mapped space. So to determine the parent of fin_pll clock, the chipid
+ * controller is first remapped and the value of XOM[0] bit is read to
+ * determine the parent clock.
+ */
+static unsigned long exynos4_get_xom(void)
+{
+ unsigned long xom = 0;
+ void __iomem *chipid_base;
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
+ if (np) {
+ chipid_base = of_iomap(np, 0);
+
+ if (chipid_base)
+ xom = readl(chipid_base + 8);
+
+ iounmap(chipid_base);
+ }
+
+ return xom;
+}
+
+static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx)
+{
+ struct samsung_fixed_rate_clock fclk;
+ struct clk *clk;
+ unsigned long finpll_f = 24000000;
+ char *parent_name;
+ unsigned int xom = exynos4_get_xom();
+
+ parent_name = xom & 1 ? "xusbxti" : "xxti";
+ clk = clk_get(NULL, parent_name);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to lookup parent clock %s, assuming "
+ "fin_pll clock frequency is 24MHz\n", __func__,
+ parent_name);
+ } else {
+ finpll_f = clk_get_rate(clk);
+ }
+
+ fclk.id = CLK_FIN_PLL;
+ fclk.name = "fin_pll";
+ fclk.parent_name = NULL;
+ fclk.flags = CLK_IS_ROOT;
+ fclk.fixed_rate = finpll_f;
+ samsung_clk_register_fixed_rate(ctx, &fclk, 1);
+
+}
+
+static struct of_device_id ext_clk_match[] __initdata = {
+ { .compatible = "samsung,clock-xxti", .data = (void *)0, },
+ { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
+ {},
+};
+
+/* PLLs PMS values */
+static struct samsung_pll_rate_table exynos4210_apll_rates[] __initdata = {
+ PLL_45XX_RATE(1200000000, 150, 3, 1, 28),
+ PLL_45XX_RATE(1000000000, 250, 6, 1, 28),
+ PLL_45XX_RATE( 800000000, 200, 6, 1, 28),
+ PLL_45XX_RATE( 666857142, 389, 14, 1, 13),
+ PLL_45XX_RATE( 600000000, 100, 4, 1, 13),
+ PLL_45XX_RATE( 533000000, 533, 24, 1, 5),
+ PLL_45XX_RATE( 500000000, 250, 6, 2, 28),
+ PLL_45XX_RATE( 400000000, 200, 6, 2, 28),
+ PLL_45XX_RATE( 200000000, 200, 6, 3, 28),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_rate_table exynos4210_epll_rates[] __initdata = {
+ PLL_4600_RATE(192000000, 48, 3, 1, 0, 0),
+ PLL_4600_RATE(180633605, 45, 3, 1, 10381, 0),
+ PLL_4600_RATE(180000000, 45, 3, 1, 0, 0),
+ PLL_4600_RATE( 73727996, 73, 3, 3, 47710, 1),
+ PLL_4600_RATE( 67737602, 90, 4, 3, 20762, 1),
+ PLL_4600_RATE( 49151992, 49, 3, 3, 9961, 0),
+ PLL_4600_RATE( 45158401, 45, 3, 3, 10381, 0),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_rate_table exynos4210_vpll_rates[] __initdata = {
+ PLL_4650_RATE(360000000, 44, 3, 0, 1024, 0, 14, 0),
+ PLL_4650_RATE(324000000, 53, 2, 1, 1024, 1, 1, 1),
+ PLL_4650_RATE(259617187, 63, 3, 1, 1950, 0, 20, 1),
+ PLL_4650_RATE(110000000, 53, 3, 2, 2048, 0, 17, 0),
+ PLL_4650_RATE( 55360351, 53, 3, 3, 2417, 0, 17, 0),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_rate_table exynos4x12_apll_rates[] __initdata = {
+ 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, 4, 0),
+ PLL_35XX_RATE(1100000000, 275, 6, 0),
+ PLL_35XX_RATE(1000000000, 125, 3, 0),
+ PLL_35XX_RATE( 900000000, 150, 4, 0),
+ PLL_35XX_RATE( 800000000, 100, 3, 0),
+ PLL_35XX_RATE( 700000000, 175, 3, 1),
+ PLL_35XX_RATE( 600000000, 200, 4, 1),
+ PLL_35XX_RATE( 500000000, 125, 3, 1),
+ PLL_35XX_RATE( 400000000, 100, 3, 1),
+ PLL_35XX_RATE( 300000000, 200, 4, 2),
+ PLL_35XX_RATE( 200000000, 100, 3, 2),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_rate_table exynos4x12_epll_rates[] __initdata = {
+ PLL_36XX_RATE(192000000, 48, 3, 1, 0),
+ PLL_36XX_RATE(180633605, 45, 3, 1, 10381),
+ PLL_36XX_RATE(180000000, 45, 3, 1, 0),
+ PLL_36XX_RATE( 73727996, 73, 3, 3, 47710),
+ PLL_36XX_RATE( 67737602, 90, 4, 3, 20762),
+ PLL_36XX_RATE( 49151992, 49, 3, 3, 9961),
+ PLL_36XX_RATE( 45158401, 45, 3, 3, 10381),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_rate_table exynos4x12_vpll_rates[] __initdata = {
+ PLL_36XX_RATE(533000000, 133, 3, 1, 16384),
+ PLL_36XX_RATE(440000000, 110, 3, 1, 0),
+ PLL_36XX_RATE(350000000, 175, 3, 2, 0),
+ PLL_36XX_RATE(266000000, 133, 3, 2, 0),
+ PLL_36XX_RATE(160000000, 160, 3, 3, 0),
+ PLL_36XX_RATE(106031250, 53, 3, 2, 1024),
+ PLL_36XX_RATE( 53015625, 53, 3, 3, 1024),
+ { /* sentinel */ }
+};
+
+static struct samsung_pll_clock exynos4210_plls[nr_plls] __initdata = {
+ [apll] = PLL_A(pll_4508, CLK_FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, "fout_apll", NULL),
+ [mpll] = PLL_A(pll_4508, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
+ E4210_MPLL_LOCK, E4210_MPLL_CON0, "fout_mpll", NULL),
+ [epll] = PLL_A(pll_4600, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, "fout_epll", NULL),
+ [vpll] = PLL_A(pll_4650c, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
+ VPLL_LOCK, VPLL_CON0, "fout_vpll", NULL),
+};
+
+static struct samsung_pll_clock exynos4x12_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",
+ E4X12_MPLL_LOCK, E4X12_MPLL_CON0, NULL),
+ [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+ [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll",
+ VPLL_LOCK, VPLL_CON0, NULL),
+};
+
+/* register exynos4 clocks */
+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__);
+
+ 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, exynos4_fixed_rate_ext_clks,
+ ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
+ ext_clk_match);
+
+ exynos4_clk_register_finpll(ctx);
+
+ if (exynos4_soc == EXYNOS4210) {
+ samsung_clk_register_mux(ctx, exynos4210_mux_early,
+ ARRAY_SIZE(exynos4210_mux_early));
+
+ if (_get_rate("fin_pll") == 24000000) {
+ exynos4210_plls[apll].rate_table =
+ exynos4210_apll_rates;
+ exynos4210_plls[epll].rate_table =
+ exynos4210_epll_rates;
+ }
+
+ if (_get_rate("mout_vpllsrc") == 24000000)
+ exynos4210_plls[vpll].rate_table =
+ exynos4210_vpll_rates;
+
+ samsung_clk_register_pll(ctx, exynos4210_plls,
+ ARRAY_SIZE(exynos4210_plls), reg_base);
+ } else {
+ if (_get_rate("fin_pll") == 24000000) {
+ exynos4x12_plls[apll].rate_table =
+ exynos4x12_apll_rates;
+ exynos4x12_plls[epll].rate_table =
+ exynos4x12_epll_rates;
+ exynos4x12_plls[vpll].rate_table =
+ exynos4x12_vpll_rates;
+ }
+
+ samsung_clk_register_pll(ctx, exynos4x12_plls,
+ ARRAY_SIZE(exynos4x12_plls), reg_base);
+ }
+
+ samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,
+ ARRAY_SIZE(exynos4_fixed_rate_clks));
+ samsung_clk_register_mux(ctx, exynos4_mux_clks,
+ ARRAY_SIZE(exynos4_mux_clks));
+ samsung_clk_register_div(ctx, exynos4_div_clks,
+ ARRAY_SIZE(exynos4_div_clks));
+ samsung_clk_register_gate(ctx, exynos4_gate_clks,
+ ARRAY_SIZE(exynos4_gate_clks));
+
+ if (exynos4_soc == EXYNOS4210) {
+ samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks,
+ ARRAY_SIZE(exynos4210_fixed_rate_clks));
+ samsung_clk_register_mux(ctx, exynos4210_mux_clks,
+ ARRAY_SIZE(exynos4210_mux_clks));
+ samsung_clk_register_div(ctx, exynos4210_div_clks,
+ ARRAY_SIZE(exynos4210_div_clks));
+ samsung_clk_register_gate(ctx, exynos4210_gate_clks,
+ ARRAY_SIZE(exynos4210_gate_clks));
+ samsung_clk_register_alias(ctx, exynos4210_aliases,
+ ARRAY_SIZE(exynos4210_aliases));
+ } else {
+ samsung_clk_register_mux(ctx, exynos4x12_mux_clks,
+ ARRAY_SIZE(exynos4x12_mux_clks));
+ samsung_clk_register_div(ctx, exynos4x12_div_clks,
+ ARRAY_SIZE(exynos4x12_div_clks));
+ samsung_clk_register_gate(ctx, exynos4x12_gate_clks,
+ ARRAY_SIZE(exynos4x12_gate_clks));
+ samsung_clk_register_alias(ctx, exynos4x12_aliases,
+ ARRAY_SIZE(exynos4x12_aliases));
+ }
+
+ samsung_clk_register_alias(ctx, exynos4_aliases,
+ ARRAY_SIZE(exynos4_aliases));
+
+ exynos4_clk_sleep_init();
+
+ 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",
+ _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
+ _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
+ _get_rate("arm_clk"));
+}
+
+
+static void __init exynos4210_clk_init(struct device_node *np)
+{
+ exynos4_clk_init(np, EXYNOS4210);
+}
+CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init);
+
+static void __init exynos4412_clk_init(struct device_node *np)
+{
+ exynos4_clk_init(np, EXYNOS4X12);
+}
+CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
new file mode 100644
index 00000000000..184f64293b2
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -0,0 +1,826 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for Exynos5250 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5250.h>
+#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"
+
+#define APLL_LOCK 0x0
+#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
+#define GATE_IP_ACP 0x8800
+#define GATE_IP_ISP0 0xc800
+#define GATE_IP_ISP1 0xc804
+#define CPLL_LOCK 0x10020
+#define EPLL_LOCK 0x10030
+#define VPLL_LOCK 0x10040
+#define GPLL_LOCK 0x10050
+#define CPLL_CON0 0x10120
+#define EPLL_CON0 0x10130
+#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
+#define SRC_DISP1_0 0x1022c
+#define SRC_MAU 0x10240
+#define SRC_FSYS 0x10244
+#define SRC_GEN 0x10248
+#define SRC_PERIC0 0x10250
+#define SRC_PERIC1 0x10254
+#define SRC_MASK_GSCL 0x10320
+#define SRC_MASK_DISP1_0 0x1032c
+#define SRC_MASK_MAU 0x10334
+#define SRC_MASK_FSYS 0x10340
+#define SRC_MASK_GEN 0x10344
+#define SRC_MASK_PERIC0 0x10350
+#define SRC_MASK_PERIC1 0x10354
+#define DIV_TOP0 0x10510
+#define DIV_TOP1 0x10514
+#define DIV_GSCL 0x10520
+#define DIV_DISP1_0 0x1052c
+#define DIV_GEN 0x1053c
+#define DIV_MAU 0x10544
+#define DIV_FSYS0 0x10548
+#define DIV_FSYS1 0x1054c
+#define DIV_FSYS2 0x10550
+#define DIV_PERIC0 0x10558
+#define DIV_PERIC1 0x1055c
+#define DIV_PERIC2 0x10560
+#define DIV_PERIC3 0x10564
+#define DIV_PERIC4 0x10568
+#define DIV_PERIC5 0x1056c
+#define GATE_IP_GSCL 0x10920
+#define GATE_IP_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
+#define GATE_IP_PERIS 0x10960
+#define BPLL_LOCK 0x20010
+#define BPLL_CON0 0x20110
+#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,
+ nr_plls /* number of PLLs */
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *exynos5250_save;
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+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,
+ SRC_DISP1_0,
+ SRC_MAU,
+ SRC_FSYS,
+ SRC_GEN,
+ SRC_PERIC0,
+ SRC_PERIC1,
+ SRC_MASK_GSCL,
+ SRC_MASK_DISP1_0,
+ SRC_MASK_MAU,
+ SRC_MASK_FSYS,
+ SRC_MASK_GEN,
+ SRC_MASK_PERIC0,
+ SRC_MASK_PERIC1,
+ DIV_TOP0,
+ DIV_TOP1,
+ DIV_GSCL,
+ DIV_DISP1_0,
+ DIV_GEN,
+ DIV_MAU,
+ DIV_FSYS0,
+ DIV_FSYS1,
+ DIV_FSYS2,
+ DIV_PERIC0,
+ DIV_PERIC1,
+ DIV_PERIC2,
+ DIV_PERIC3,
+ DIV_PERIC4,
+ DIV_PERIC5,
+ GATE_IP_GSCL,
+ GATE_IP_MFC,
+ GATE_IP_G3D,
+ GATE_IP_GEN,
+ GATE_IP_FSYS,
+ GATE_IP_PERIC,
+ GATE_IP_PERIS,
+ SRC_CDREX,
+ PLL_DIV2_SEL,
+ GATE_IP_DISP1,
+ GATE_IP_ACP,
+ GATE_IP_ISP0,
+ GATE_IP_ISP1,
+};
+
+static int exynos5250_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, exynos5250_save,
+ ARRAY_SIZE(exynos5250_clk_regs));
+
+ return 0;
+}
+
+static void exynos5250_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, exynos5250_save,
+ ARRAY_SIZE(exynos5250_clk_regs));
+}
+
+static struct syscore_ops exynos5250_clk_syscore_ops = {
+ .suspend = exynos5250_clk_suspend,
+ .resume = exynos5250_clk_resume,
+};
+
+static void exynos5250_clk_sleep_init(void)
+{
+ exynos5250_save = samsung_clk_alloc_reg_dump(exynos5250_clk_regs,
+ ARRAY_SIZE(exynos5250_clk_regs));
+ if (!exynos5250_save) {
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+ return;
+ }
+
+ register_syscore_ops(&exynos5250_clk_syscore_ops);
+}
+#else
+static void exynos5250_clk_sleep_init(void) {}
+#endif
+
+/* list of all parent clock list */
+PNAME(mout_apll_p) = { "fin_pll", "fout_apll", };
+PNAME(mout_cpu_p) = { "mout_apll", "mout_mpll", };
+PNAME(mout_mpll_fout_p) = { "fout_mplldiv2", "fout_mpll" };
+PNAME(mout_mpll_p) = { "fin_pll", "mout_mpll_fout" };
+PNAME(mout_bpll_fout_p) = { "fout_bplldiv2", "fout_bpll" };
+PNAME(mout_bpll_p) = { "fin_pll", "mout_bpll_fout" };
+PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" };
+PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" };
+PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" };
+PNAME(mout_epll_p) = { "fin_pll", "fout_epll" };
+PNAME(mout_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" };
+PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" };
+PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" };
+PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" };
+PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m",
+ "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy",
+ "mout_mpll_user", "mout_epll", "mout_vpll",
+ "mout_cpll", "none", "none",
+ "none", "none", "none",
+ "none" };
+PNAME(mout_audio0_p) = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+ "sclk_uhostphy", "fin_pll",
+ "mout_mpll_user", "mout_epll", "mout_vpll",
+ "mout_cpll", "none", "none",
+ "none", "none", "none",
+ "none" };
+PNAME(mout_audio1_p) = { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+ "sclk_uhostphy", "fin_pll",
+ "mout_mpll_user", "mout_epll", "mout_vpll",
+ "mout_cpll", "none", "none",
+ "none", "none", "none",
+ "none" };
+PNAME(mout_audio2_p) = { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+ "sclk_uhostphy", "fin_pll",
+ "mout_mpll_user", "mout_epll", "mout_vpll",
+ "mout_cpll", "none", "none",
+ "none", "none", "none",
+ "none" };
+PNAME(mout_spdif_p) = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+ "spdif_extclk" };
+
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock exynos5250_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 exynos5250_fixed_rate_clks[] __initdata = {
+ FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+ FRATE(0, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(0, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
+ FRATE(0, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+ FFACTOR(0, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
+ FFACTOR(0, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
+};
+
+static struct samsung_mux_clock exynos5250_pll_pmux_clks[] __initdata = {
+ MUX(0, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+};
+
+static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+ /*
+ * NOTE: Following table is sorted by (clock domain, register address,
+ * bitfield shift) triplet in ascending order. When adding new entries,
+ * please make sure that the order is kept, to avoid merge conflicts
+ * and make further work with defined data easier.
+ */
+
+ /*
+ * CMU_CPU
+ */
+ MUX_FA(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+ CLK_SET_RATE_PARENT, 0, "mout_apll"),
+ MUX_A(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1, "mout_cpu"),
+
+ /*
+ * CMU_CORE
+ */
+ MUX_A(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1, "mout_mpll"),
+
+ /*
+ * CMU_TOP
+ */
+ 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_isp", mout_aclk200_p, SRC_TOP1, 24, 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),
+ MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1),
+ MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p,
+ SRC_TOP3, 20, 1),
+ MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1),
+
+ MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
+ MUX(0, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
+ MUX(0, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
+ MUX(0, "mout_gscl_wa", mout_group1_p, SRC_GSCL, 24, 4),
+ MUX(0, "mout_gscl_wb", mout_group1_p, SRC_GSCL, 28, 4),
+
+ MUX(0, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
+ MUX(0, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
+ MUX(0, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
+ MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+
+ MUX(0, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
+
+ MUX(0, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
+ MUX(0, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
+ MUX(0, "mout_mmc2", mout_group1_p, SRC_FSYS, 8, 4),
+ MUX(0, "mout_mmc3", mout_group1_p, SRC_FSYS, 12, 4),
+ MUX(0, "mout_sata", mout_aclk200_p, SRC_FSYS, 24, 1),
+ MUX(0, "mout_usb3", mout_usb3_p, SRC_FSYS, 28, 1),
+
+ MUX(0, "mout_jpeg", mout_group1_p, SRC_GEN, 0, 4),
+
+ MUX(0, "mout_uart0", mout_group1_p, SRC_PERIC0, 0, 4),
+ MUX(0, "mout_uart1", mout_group1_p, SRC_PERIC0, 4, 4),
+ MUX(0, "mout_uart2", mout_group1_p, SRC_PERIC0, 8, 4),
+ MUX(0, "mout_uart3", mout_group1_p, SRC_PERIC0, 12, 4),
+ MUX(0, "mout_pwm", mout_group1_p, SRC_PERIC0, 24, 4),
+
+ MUX(0, "mout_audio1", mout_audio1_p, SRC_PERIC1, 0, 4),
+ MUX(0, "mout_audio2", mout_audio2_p, SRC_PERIC1, 4, 4),
+ MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIC1, 8, 2),
+ MUX(0, "mout_spi0", mout_group1_p, SRC_PERIC1, 16, 4),
+ MUX(0, "mout_spi1", mout_group1_p, SRC_PERIC1, 20, 4),
+ MUX(0, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
+
+ /*
+ * CMU_CDREX
+ */
+ MUX(0, "mout_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
+
+ MUX(0, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
+ MUX(0, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
+};
+
+static struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+ /*
+ * NOTE: Following table is sorted by (clock domain, register address,
+ * bitfield shift) triplet in ascending order. When adding new entries,
+ * please make sure that the order is kept, to avoid merge conflicts
+ * and make further work with defined data easier.
+ */
+
+ /*
+ * CMU_CPU
+ */
+ DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+ DIV(0, "div_apll", "mout_apll", DIV_CPU0, 24, 3),
+ DIV_A(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3, "armclk"),
+
+ /*
+ * CMU_TOP
+ */
+ DIV(0, "div_aclk66", "div_aclk66_pre", DIV_TOP0, 0, 3),
+ DIV(0, "div_aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
+ 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_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3),
+ DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3),
+
+ DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
+ DIV(0, "div_cam0", "mout_cam0", DIV_GSCL, 16, 4),
+ DIV(0, "div_cam1", "mout_cam1", DIV_GSCL, 20, 4),
+ DIV(0, "div_gscl_wa", "mout_gscl_wa", DIV_GSCL, 24, 4),
+ DIV(0, "div_gscl_wb", "mout_gscl_wb", DIV_GSCL, 28, 4),
+
+ DIV(0, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4),
+ DIV(0, "div_mipi1", "mout_mipi1", DIV_DISP1_0, 16, 4),
+ DIV_F(0, "div_mipi1_pre", "div_mipi1",
+ DIV_DISP1_0, 20, 4, CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_dp", "mout_dp", DIV_DISP1_0, 24, 4),
+ DIV(CLK_SCLK_PIXEL, "div_hdmi_pixel", "mout_vpll", DIV_DISP1_0, 28, 4),
+
+ DIV(0, "div_jpeg", "mout_jpeg", DIV_GEN, 4, 4),
+
+ DIV(0, "div_audio0", "mout_audio0", DIV_MAU, 0, 4),
+ DIV(CLK_DIV_PCM0, "div_pcm0", "sclk_audio0", DIV_MAU, 4, 8),
+
+ DIV(0, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+ DIV(0, "div_usb3", "mout_usb3", DIV_FSYS0, 24, 4),
+
+ DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+ DIV_F(0, "div_mmc_pre0", "div_mmc0",
+ DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+ DIV_F(0, "div_mmc_pre1", "div_mmc1",
+ DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+ DIV_F(0, "div_mmc_pre2", "div_mmc2",
+ DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
+ DIV_F(0, "div_mmc_pre3", "div_mmc3",
+ DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+ DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+ DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+ DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+
+ DIV(0, "div_spi0", "mout_spi0", DIV_PERIC1, 0, 4),
+ DIV_F(0, "div_spi_pre0", "div_spi0",
+ DIV_PERIC1, 8, 8, CLK_SET_RATE_PARENT, 0),
+ DIV(0, "div_spi1", "mout_spi1", DIV_PERIC1, 16, 4),
+ DIV_F(0, "div_spi_pre1", "div_spi1",
+ DIV_PERIC1, 24, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_spi2", "mout_spi2", DIV_PERIC2, 0, 4),
+ DIV_F(0, "div_spi_pre2", "div_spi2",
+ DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+
+ DIV(0, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4),
+ DIV(0, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8),
+ DIV(0, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4),
+ DIV(0, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8),
+
+ DIV(CLK_DIV_I2S1, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6),
+ DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
+};
+
+static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+ /*
+ * NOTE: Following table is sorted by (clock domain, register address,
+ * bitfield shift) triplet in ascending order. When adding new entries,
+ * please make sure that the order is kept, to avoid merge conflicts
+ * and make further work with defined data easier.
+ */
+
+ /*
+ * 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),
+
+ /*
+ * CMU_TOP
+ */
+ GATE(CLK_SCLK_CAM_BAYER, "sclk_cam_bayer", "div_cam_bayer",
+ SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0",
+ SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1",
+ SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "div_gscl_wa",
+ SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "div_gscl_wb",
+ SRC_MASK_GSCL, 28, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "div_fimd1",
+ SRC_MASK_DISP1_0, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "div_mipi1",
+ SRC_MASK_DISP1_0, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_DP, "sclk_dp", "div_dp",
+ SRC_MASK_DISP1_0, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi",
+ SRC_MASK_DISP1_0, 20, 0, 0),
+
+ GATE(CLK_SCLK_AUDIO0, "sclk_audio0", "div_audio0",
+ SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
+ SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
+ SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
+ SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC3, "sclk_mmc3", "div_mmc_pre3",
+ SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SATA, "sclk_sata", "div_sata",
+ SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_USB3, "sclk_usb3", "div_usb3",
+ SRC_MASK_FSYS, 28, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_jpeg",
+ SRC_MASK_GEN, 0, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
+ SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
+ SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
+ SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART3, "sclk_uart3", "div_uart3",
+ SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_PWM, "sclk_pwm", "div_pwm",
+ SRC_MASK_PERIC0, 24, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_AUDIO1, "sclk_audio1", "div_audio1",
+ SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_AUDIO2, "sclk_audio2", "div_audio2",
+ SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif",
+ SRC_MASK_PERIC1, 4, 0, 0),
+ GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi_pre0",
+ SRC_MASK_PERIC1, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi_pre1",
+ SRC_MASK_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_SPI2, "sclk_spi2", "div_spi_pre2",
+ SRC_MASK_PERIC1, 24, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_GSCL0, "gscl0", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 0, 0,
+ 0),
+ GATE(CLK_GSCL1, "gscl1", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 1, 0,
+ 0),
+ GATE(CLK_GSCL2, "gscl2", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 2, 0,
+ 0),
+ GATE(CLK_GSCL3, "gscl3", "mout_aclk266_gscl_sub", GATE_IP_GSCL, 3, 0,
+ 0),
+ GATE(CLK_GSCL_WA, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
+ GATE(CLK_GSCL_WB, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
+ GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "mout_aclk266_gscl_sub",
+ GATE_IP_GSCL, 7, 0, 0),
+ GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "mout_aclk266_gscl_sub",
+ GATE_IP_GSCL, 8, 0, 0),
+ GATE(CLK_SMMU_GSCL2, "smmu_gscl2", "mout_aclk266_gscl_sub",
+ GATE_IP_GSCL, 9, 0, 0),
+ GATE(CLK_SMMU_GSCL3, "smmu_gscl3", "mout_aclk266_gscl_sub",
+ GATE_IP_GSCL, 10, 0, 0),
+
+ GATE(CLK_FIMD1, "fimd1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 0, 0,
+ 0),
+ GATE(CLK_MIE1, "mie1", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 1, 0,
+ 0),
+ GATE(CLK_DSIM0, "dsim0", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 3, 0,
+ 0),
+ GATE(CLK_DP, "dp", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 4, 0, 0),
+ GATE(CLK_MIXER, "mixer", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 5, 0,
+ 0),
+ GATE(CLK_HDMI, "hdmi", "mout_aclk200_disp1_sub", GATE_IP_DISP1, 6, 0,
+ 0),
+
+ GATE(CLK_MFC, "mfc", "mout_aclk333_sub", GATE_IP_MFC, 0, 0, 0),
+ GATE(CLK_SMMU_MFCR, "smmu_mfcr", "mout_aclk333_sub", GATE_IP_MFC, 1, 0,
+ 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),
+ GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "div_aclk266", GATE_IP_GEN, 6, 0,
+ 0),
+ GATE(CLK_SMMU_JPEG, "smmu_jpeg", "div_aclk166", GATE_IP_GEN, 7, 0, 0),
+ GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "div_aclk266", GATE_IP_GEN, 9, 0, 0),
+
+ GATE(CLK_PDMA0, "pdma0", "div_aclk200", GATE_IP_FSYS, 1, 0, 0),
+ GATE(CLK_PDMA1, "pdma1", "div_aclk200", GATE_IP_FSYS, 2, 0, 0),
+ GATE(CLK_SATA, "sata", "div_aclk200", GATE_IP_FSYS, 6, 0, 0),
+ GATE(CLK_USBOTG, "usbotg", "div_aclk200", GATE_IP_FSYS, 7, 0, 0),
+ GATE(CLK_MIPI_HSI, "mipi_hsi", "div_aclk200", GATE_IP_FSYS, 8, 0, 0),
+ GATE(CLK_SDMMC0, "sdmmc0", "div_aclk200", GATE_IP_FSYS, 12, 0, 0),
+ GATE(CLK_SDMMC1, "sdmmc1", "div_aclk200", GATE_IP_FSYS, 13, 0, 0),
+ GATE(CLK_SDMMC2, "sdmmc2", "div_aclk200", GATE_IP_FSYS, 14, 0, 0),
+ GATE(CLK_SDMMC3, "sdmmc3", "div_aclk200", GATE_IP_FSYS, 15, 0, 0),
+ GATE(CLK_SROMC, "sromc", "div_aclk200", GATE_IP_FSYS, 17, 0, 0),
+ GATE(CLK_USB2, "usb2", "div_aclk200", GATE_IP_FSYS, 18, 0, 0),
+ GATE(CLK_USB3, "usb3", "div_aclk200", GATE_IP_FSYS, 19, 0, 0),
+ GATE(CLK_SATA_PHYCTRL, "sata_phyctrl", "div_aclk200",
+ GATE_IP_FSYS, 24, 0, 0),
+ GATE(CLK_SATA_PHYI2C, "sata_phyi2c", "div_aclk200", GATE_IP_FSYS, 25, 0,
+ 0),
+
+ GATE(CLK_UART0, "uart0", "div_aclk66", GATE_IP_PERIC, 0, 0, 0),
+ GATE(CLK_UART1, "uart1", "div_aclk66", GATE_IP_PERIC, 1, 0, 0),
+ GATE(CLK_UART2, "uart2", "div_aclk66", GATE_IP_PERIC, 2, 0, 0),
+ GATE(CLK_UART3, "uart3", "div_aclk66", GATE_IP_PERIC, 3, 0, 0),
+ GATE(CLK_UART4, "uart4", "div_aclk66", GATE_IP_PERIC, 4, 0, 0),
+ GATE(CLK_I2C0, "i2c0", "div_aclk66", GATE_IP_PERIC, 6, 0, 0),
+ GATE(CLK_I2C1, "i2c1", "div_aclk66", GATE_IP_PERIC, 7, 0, 0),
+ GATE(CLK_I2C2, "i2c2", "div_aclk66", GATE_IP_PERIC, 8, 0, 0),
+ GATE(CLK_I2C3, "i2c3", "div_aclk66", GATE_IP_PERIC, 9, 0, 0),
+ GATE(CLK_I2C4, "i2c4", "div_aclk66", GATE_IP_PERIC, 10, 0, 0),
+ GATE(CLK_I2C5, "i2c5", "div_aclk66", GATE_IP_PERIC, 11, 0, 0),
+ GATE(CLK_I2C6, "i2c6", "div_aclk66", GATE_IP_PERIC, 12, 0, 0),
+ GATE(CLK_I2C7, "i2c7", "div_aclk66", GATE_IP_PERIC, 13, 0, 0),
+ GATE(CLK_I2C_HDMI, "i2c_hdmi", "div_aclk66", GATE_IP_PERIC, 14, 0, 0),
+ GATE(CLK_ADC, "adc", "div_aclk66", GATE_IP_PERIC, 15, 0, 0),
+ GATE(CLK_SPI0, "spi0", "div_aclk66", GATE_IP_PERIC, 16, 0, 0),
+ GATE(CLK_SPI1, "spi1", "div_aclk66", GATE_IP_PERIC, 17, 0, 0),
+ GATE(CLK_SPI2, "spi2", "div_aclk66", GATE_IP_PERIC, 18, 0, 0),
+ GATE(CLK_I2S1, "i2s1", "div_aclk66", GATE_IP_PERIC, 20, 0, 0),
+ GATE(CLK_I2S2, "i2s2", "div_aclk66", GATE_IP_PERIC, 21, 0, 0),
+ GATE(CLK_PCM1, "pcm1", "div_aclk66", GATE_IP_PERIC, 22, 0, 0),
+ GATE(CLK_PCM2, "pcm2", "div_aclk66", GATE_IP_PERIC, 23, 0, 0),
+ GATE(CLK_PWM, "pwm", "div_aclk66", GATE_IP_PERIC, 24, 0, 0),
+ GATE(CLK_SPDIF, "spdif", "div_aclk66", GATE_IP_PERIC, 26, 0, 0),
+ GATE(CLK_AC97, "ac97", "div_aclk66", GATE_IP_PERIC, 27, 0, 0),
+ GATE(CLK_HSI2C0, "hsi2c0", "div_aclk66", GATE_IP_PERIC, 28, 0, 0),
+ GATE(CLK_HSI2C1, "hsi2c1", "div_aclk66", GATE_IP_PERIC, 29, 0, 0),
+ GATE(CLK_HSI2C2, "hsi2c2", "div_aclk66", GATE_IP_PERIC, 30, 0, 0),
+ GATE(CLK_HSI2C3, "hsi2c3", "div_aclk66", GATE_IP_PERIC, 31, 0, 0),
+
+ GATE(CLK_CHIPID, "chipid", "div_aclk66", GATE_IP_PERIS, 0, 0, 0),
+ GATE(CLK_SYSREG, "sysreg", "div_aclk66",
+ GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_PMU, "pmu", "div_aclk66", GATE_IP_PERIS, 2, CLK_IGNORE_UNUSED,
+ 0),
+ GATE(CLK_CMU_TOP, "cmu_top", "div_aclk66",
+ GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_CMU_CORE, "cmu_core", "div_aclk66",
+ GATE_IP_PERIS, 4, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_CMU_MEM, "cmu_mem", "div_aclk66",
+ GATE_IP_PERIS, 5, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_TZPC0, "tzpc0", "div_aclk66", GATE_IP_PERIS, 6, 0, 0),
+ GATE(CLK_TZPC1, "tzpc1", "div_aclk66", GATE_IP_PERIS, 7, 0, 0),
+ GATE(CLK_TZPC2, "tzpc2", "div_aclk66", GATE_IP_PERIS, 8, 0, 0),
+ GATE(CLK_TZPC3, "tzpc3", "div_aclk66", GATE_IP_PERIS, 9, 0, 0),
+ GATE(CLK_TZPC4, "tzpc4", "div_aclk66", GATE_IP_PERIS, 10, 0, 0),
+ GATE(CLK_TZPC5, "tzpc5", "div_aclk66", GATE_IP_PERIS, 11, 0, 0),
+ GATE(CLK_TZPC6, "tzpc6", "div_aclk66", GATE_IP_PERIS, 12, 0, 0),
+ GATE(CLK_TZPC7, "tzpc7", "div_aclk66", GATE_IP_PERIS, 13, 0, 0),
+ GATE(CLK_TZPC8, "tzpc8", "div_aclk66", GATE_IP_PERIS, 14, 0, 0),
+ GATE(CLK_TZPC9, "tzpc9", "div_aclk66", GATE_IP_PERIS, 15, 0, 0),
+ GATE(CLK_HDMI_CEC, "hdmi_cec", "div_aclk66", GATE_IP_PERIS, 16, 0, 0),
+ GATE(CLK_MCT, "mct", "div_aclk66", GATE_IP_PERIS, 18, 0, 0),
+ GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0),
+ 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, 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),
+ GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 8, 0, 0),
+ GATE(CLK_SMMU_FIMC_DRC, "smmu_fimc_drc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 9, 0, 0),
+ GATE(CLK_SMMU_FIMC_FD, "smmu_fimc_fd", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 10, 0, 0),
+ GATE(CLK_SMMU_FIMC_SCC, "smmu_fimc_scc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 11, 0, 0),
+ GATE(CLK_SMMU_FIMC_SCP, "smmu_fimc_scp", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP0, 12, 0, 0),
+ GATE(CLK_SMMU_FIMC_MCU, "smmu_fimc_mcu", "mout_aclk_400_isp_sub",
+ GATE_IP_ISP0, 13, 0, 0),
+ GATE(CLK_SMMU_FIMC_ODC, "smmu_fimc_odc", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 4, 0, 0),
+ GATE(CLK_SMMU_FIMC_DIS0, "smmu_fimc_dis0", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 5, 0, 0),
+ GATE(CLK_SMMU_FIMC_DIS1, "smmu_fimc_dis1", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 6, 0, 0),
+ GATE(CLK_SMMU_FIMC_3DNR, "smmu_fimc_3dnr", "mout_aclk_266_isp_sub",
+ GATE_IP_ISP1, 7, 0, 0),
+};
+
+static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = {
+ /* sorted in descending order */
+ /* PLL_36XX_RATE(rate, m, p, s, k) */
+ PLL_36XX_RATE(266000000, 266, 3, 3, 0),
+ /* Not in UM, but need for eDP on snow */
+ PLL_36XX_RATE(70500000, 94, 2, 4, 0),
+ { },
+};
+
+static struct samsung_pll_rate_table epll_24mhz_tbl[] __initdata = {
+ /* sorted in descending order */
+ /* PLL_36XX_RATE(rate, m, p, s, k) */
+ PLL_36XX_RATE(192000000, 64, 2, 2, 0),
+ PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+ PLL_36XX_RATE(180000000, 90, 3, 2, 0),
+ PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
+ PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+ PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
+ PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
+ PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+ { },
+};
+
+static struct samsung_pll_rate_table apll_24mhz_tbl[] __initdata = {
+ /* sorted in descending order */
+ /* PLL_35XX_RATE(rate, m, p, s) */
+ 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, 4, 0),
+ PLL_35XX_RATE(1100000000, 275, 6, 0),
+ PLL_35XX_RATE(1000000000, 125, 3, 0),
+ PLL_35XX_RATE(900000000, 150, 4, 0),
+ PLL_35XX_RATE(800000000, 100, 3, 0),
+ PLL_35XX_RATE(700000000, 175, 3, 1),
+ PLL_35XX_RATE(600000000, 200, 4, 1),
+ PLL_35XX_RATE(500000000, 125, 3, 1),
+ PLL_35XX_RATE(400000000, 100, 3, 1),
+ PLL_35XX_RATE(300000000, 200, 4, 2),
+ PLL_35XX_RATE(200000000, 100, 3, 2),
+};
+
+static struct samsung_pll_clock exynos5250_plls[nr_plls] __initdata = {
+ [apll] = PLL_A(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, "fout_apll", NULL),
+ [mpll] = PLL_A(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON0, "fout_mpll", NULL),
+ [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+ BPLL_CON0, NULL),
+ [gpll] = PLL(pll_35xx, CLK_FOUT_GPLL, "fout_gpll", "fin_pll", GPLL_LOCK,
+ GPLL_CON0, NULL),
+ [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+ CPLL_CON0, NULL),
+ [epll] = PLL(pll_36xx, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
+ EPLL_CON0, NULL),
+ [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
+ VPLL_LOCK, VPLL_CON0, NULL),
+};
+
+static struct of_device_id ext_clk_match[] __initdata = {
+ { .compatible = "samsung,clock-xxti", .data = (void *)0, },
+ { },
+};
+
+/* 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)
+ panic("%s: failed to map registers\n", __func__);
+ } else {
+ panic("%s: unable to determine soc\n", __func__);
+ }
+
+ 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(ctx, exynos5250_pll_pmux_clks,
+ ARRAY_SIZE(exynos5250_pll_pmux_clks));
+
+ if (_get_rate("fin_pll") == 24 * MHZ) {
+ exynos5250_plls[epll].rate_table = epll_24mhz_tbl;
+ exynos5250_plls[apll].rate_table = apll_24mhz_tbl;
+ }
+
+ if (_get_rate("mout_vpllsrc") == 24 * MHZ)
+ exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl;
+
+ 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(ctx, exynos5250_fixed_factor_clks,
+ ARRAY_SIZE(exynos5250_fixed_factor_clks));
+ samsung_clk_register_mux(ctx, exynos5250_mux_clks,
+ ARRAY_SIZE(exynos5250_mux_clks));
+ samsung_clk_register_div(ctx, exynos5250_div_clks,
+ ARRAY_SIZE(exynos5250_div_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",
+ _get_rate("div_arm2"));
+}
+CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
new file mode 100644
index 00000000000..64596ba58df
--- /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(&reg_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 00000000000..d739716d6ea
--- /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-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
new file mode 100644
index 00000000000..c9505ab9ee7
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Tarek Dakhran <t.dakhran@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 Exynos5410 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5410.h>
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+#define APLL_LOCK 0x0
+#define APLL_CON0 0x100
+#define CPLL_LOCK 0x10020
+#define CPLL_CON0 0x10120
+#define MPLL_LOCK 0x4000
+#define MPLL_CON0 0x4100
+#define BPLL_LOCK 0x20010
+#define BPLL_CON0 0x20110
+#define KPLL_LOCK 0x28000
+#define KPLL_CON0 0x28100
+
+#define SRC_CPU 0x200
+#define DIV_CPU0 0x500
+#define SRC_CPERI1 0x4204
+#define DIV_TOP0 0x10510
+#define DIV_TOP1 0x10514
+#define DIV_FSYS1 0x1054c
+#define DIV_FSYS2 0x10550
+#define DIV_PERIC0 0x10558
+#define SRC_TOP0 0x10210
+#define SRC_TOP1 0x10214
+#define SRC_TOP2 0x10218
+#define SRC_FSYS 0x10244
+#define SRC_PERIC0 0x10250
+#define SRC_MASK_FSYS 0x10340
+#define SRC_MASK_PERIC0 0x10350
+#define GATE_BUS_FSYS0 0x10740
+#define GATE_IP_FSYS 0x10944
+#define GATE_IP_PERIC 0x10950
+#define GATE_IP_PERIS 0x10960
+#define SRC_CDREX 0x20200
+#define SRC_KFC 0x28200
+#define DIV_KFC0 0x28500
+
+/* list of PLLs */
+enum exynos5410_plls {
+ apll, cpll, mpll,
+ bpll, kpll,
+ nr_plls /* number of PLLs */
+};
+
+/* list of all parent clocks */
+PNAME(apll_p) = { "fin_pll", "fout_apll", };
+PNAME(bpll_p) = { "fin_pll", "fout_bpll", };
+PNAME(cpll_p) = { "fin_pll", "fout_cpll" };
+PNAME(mpll_p) = { "fin_pll", "fout_mpll", };
+PNAME(kpll_p) = { "fin_pll", "fout_kpll", };
+
+PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", };
+PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", };
+
+PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", };
+PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", };
+PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+
+PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none",
+ "none", "none", "sclk_mpll_bpll",
+ "none", "none", "sclk_cpll" };
+
+static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
+ MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
+ MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
+
+ MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
+ MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
+
+ MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
+ MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
+
+ MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
+ MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
+
+ MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
+
+ MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
+
+ MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
+ MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
+ MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+
+ MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
+ MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
+ MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+
+ MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
+ MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
+};
+
+static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
+ DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+ DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
+
+ DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
+ DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
+ DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
+ DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
+
+ DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
+ DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
+ DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
+
+ DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
+ DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
+
+ DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+ DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+ DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+
+ DIV_F(0, "div_mmc_pre0", "div_mmc0",
+ DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre1", "div_mmc1",
+ DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+ DIV_F(0, "div_mmc_pre2", "div_mmc2",
+ DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+
+ DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+ DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+ DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+ DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+
+ DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+ DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
+};
+
+static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
+ GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+
+ GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
+ SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
+ SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
+ SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
+ GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
+ GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
+
+ GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
+ GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
+ GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+
+ GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
+ SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
+ SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
+ SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
+ [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
+ APLL_CON0, NULL),
+ [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+ CPLL_CON0, NULL),
+ [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+ MPLL_CON0, NULL),
+ [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+ BPLL_CON0, NULL),
+ [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+ KPLL_CON0, NULL),
+};
+
+/* register exynos5410 clocks */
+static void __init exynos5410_clk_init(struct device_node *np)
+{
+ struct samsung_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
+
+ samsung_clk_register_pll(ctx, exynos5410_plls,
+ ARRAY_SIZE(exynos5410_plls), reg_base);
+
+ samsung_clk_register_mux(ctx, exynos5410_mux_clks,
+ ARRAY_SIZE(exynos5410_mux_clks));
+ samsung_clk_register_div(ctx, exynos5410_div_clks,
+ ARRAY_SIZE(exynos5410_div_clks));
+ samsung_clk_register_gate(ctx, exynos5410_gate_clks,
+ ARRAY_SIZE(exynos5410_gate_clks));
+
+ 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
new file mode 100644
index 00000000000..a4e6cc782e5
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5420.c
@@ -0,0 +1,1268 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Thomas Abraham <thomas.ab@samsung.com>
+ * Chander Kashyap <k.chander@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 Exynos5420 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5420.h>
+#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"
+
+#define APLL_LOCK 0x0
+#define APLL_CON0 0x100
+#define SRC_CPU 0x200
+#define DIV_CPU0 0x500
+#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 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
+#define MPLL_CON0 0x10180
+#define SRC_TOP0 0x10200
+#define SRC_TOP1 0x10204
+#define SRC_TOP2 0x10208
+#define SRC_TOP3 0x1020c
+#define SRC_TOP4 0x10210
+#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_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
+#define DIV_FSYS1 0x1054c
+#define DIV_FSYS2 0x10550
+#define DIV_PERIC0 0x10558
+#define DIV_PERIC1 0x1055c
+#define DIV_PERIC2 0x10560
+#define DIV_PERIC3 0x10564
+#define DIV_PERIC4 0x10568
+#define DIV_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 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 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 *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 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,
+ SRC_TOP3,
+ SRC_TOP4,
+ SRC_TOP5,
+ SRC_TOP6,
+ SRC_TOP7,
+ SRC_DISP10,
+ SRC_MAU,
+ SRC_FSYS,
+ SRC_PERIC0,
+ SRC_PERIC1,
+ 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,
+ DIV_DISP10,
+ DIV_MAU,
+ DIV_FSYS0,
+ DIV_FSYS1,
+ DIV_FSYS2,
+ DIV_PERIC0,
+ DIV_PERIC1,
+ 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,
+ 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, 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, 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 = {
+ .suspend = exynos5420_clk_suspend,
+ .resume = exynos5420_clk_resume,
+};
+
+static void exynos5420_clk_sleep_init(void)
+{
+ 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(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
+ 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 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),
+ FRATE(0, "mphy_refclk_ixtal24", NULL, CLK_IS_ROOT, 48000000),
+ FRATE(0, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000),
+};
+
+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_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(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_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", mout_user_aclk333_432_gscl_p,
+ SRC_TOP4, 0, 1),
+ 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(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),
+ 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", mout_user_aclk300_disp1_p,
+ SRC_TOP5, 24, 1),
+ MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p,
+ SRC_TOP5, 28, 1),
+
+ 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_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_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(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),
+ 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", mout_sw_aclk300_gscl_p,
+ SRC_TOP12, 28, 1),
+
+ /* DISP1 Block */
+ 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(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3),
+
+ /* FSYS Block */
+ 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", 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 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_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),
+
+ DIV(0, "dout_aclk333_g2d", "mout_aclk333_g2d", DIV_TOP2, 8, 3),
+ 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(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_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),
+ DIV(0, "dout_maupcm0", "dout_maudio0", DIV_MAU, 24, 8),
+
+ /* USB3.0 */
+ DIV(0, "dout_usbphy301", "mout_usbd301", DIV_FSYS0, 12, 4),
+ DIV(0, "dout_usbphy300", "mout_usbd300", DIV_FSYS0, 16, 4),
+ DIV(0, "dout_usbd301", "mout_usbd301", DIV_FSYS0, 20, 4),
+ DIV(0, "dout_usbd300", "mout_usbd300", DIV_FSYS0, 24, 4),
+
+ /* MMC */
+ DIV(0, "dout_mmc0", "mout_mmc0", DIV_FSYS1, 0, 10),
+ DIV(0, "dout_mmc1", "mout_mmc1", DIV_FSYS1, 10, 10),
+ 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),
+ DIV(0, "dout_uart1", "mout_uart1", DIV_PERIC0, 12, 4),
+ DIV(0, "dout_uart2", "mout_uart2", DIV_PERIC0, 16, 4),
+ DIV(0, "dout_uart3", "mout_uart3", DIV_PERIC0, 20, 4),
+ DIV(0, "dout_pwm", "mout_pwm", DIV_PERIC0, 28, 4),
+
+ /* SPI */
+ DIV(0, "dout_spi0", "mout_spi0", DIV_PERIC1, 20, 4),
+ 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),
+
+ /* Audio - I2S */
+ DIV(0, "dout_i2s1", "dout_audio1", DIV_PERIC3, 6, 6),
+ DIV(0, "dout_i2s2", "dout_audio2", DIV_PERIC3, 12, 6),
+ DIV(0, "dout_audio0", "mout_audio0", DIV_PERIC3, 20, 4),
+ DIV(0, "dout_audio1", "mout_audio1", DIV_PERIC3, 24, 4),
+ DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4),
+
+ /* SPI Pre-Ratio */
+ 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 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),
+ GATE(0, "aclk200_fsys2", "mout_user_aclk200_fsys2",
+ GATE_BUS_FSYS0, 10, CLK_IGNORE_UNUSED, 0),
+
+ GATE(0, "aclk333_g2d", "mout_user_aclk333_g2d",
+ GATE_BUS_TOP, 0, CLK_IGNORE_UNUSED, 0),
+ GATE(0, "aclk266_g2d", "mout_user_aclk266_g2d",
+ 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, "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_user_aclk66_psgen",
+ GATE_BUS_TOP, 10, 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",
+ GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART1, "sclk_uart1", "dout_uart1",
+ GATE_TOP_SCLK_PERIC, 1, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_UART2, "sclk_uart2", "dout_uart2",
+ 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_spi0_pre",
+ GATE_TOP_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0),
+ 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_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),
+ GATE(CLK_SCLK_PWM, "sclk_pwm", "dout_pwm",
+ GATE_TOP_SCLK_PERIC, 11, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_pcm1",
+ GATE_TOP_SCLK_PERIC, 15, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_PCM2, "sclk_pcm2", "dout_pcm2",
+ GATE_TOP_SCLK_PERIC, 16, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_I2S1, "sclk_i2s1", "dout_i2s1",
+ GATE_TOP_SCLK_PERIC, 17, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_I2S2, "sclk_i2s2", "dout_i2s2",
+ GATE_TOP_SCLK_PERIC, 18, CLK_SET_RATE_PARENT, 0),
+
+ GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_mmc0",
+ GATE_TOP_SCLK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_mmc1",
+ GATE_TOP_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_mmc2",
+ GATE_TOP_SCLK_FSYS, 2, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_USBPHY301, "sclk_usbphy301", "dout_usbphy301",
+ GATE_TOP_SCLK_FSYS, 7, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_USBPHY300, "sclk_usbphy300", "dout_usbphy300",
+ GATE_TOP_SCLK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_USBD300, "sclk_usbd300", "dout_usbd300",
+ GATE_TOP_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301",
+ GATE_TOP_SCLK_FSYS, 10, 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(CLK_SCLK_MIPI1, "sclk_mipi1", "dout_mipi1",
+ GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi",
+ 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(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1",
+ 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 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_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_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),
+
+ /* PERIC Block */
+ 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",
+ GATE_IP_PERIS, 0, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_SYSREG, "sysreg", "aclk66_psgen",
+ 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),
+
+ /* 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_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", "dout_gscl_blk_333",
+ GATE_IP_GSCL1, 4, 0, 0),
+ 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", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0),
+ GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 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", "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_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0),
+};
+
+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,
+ CPLL_CON0, NULL),
+ [dpll] = PLL(pll_2550, CLK_FOUT_DPLL, "fout_dpll", "fin_pll", DPLL_LOCK,
+ DPLL_CON0, NULL),
+ [epll] = PLL(pll_2650, CLK_FOUT_EPLL, "fout_epll", "fin_pll", EPLL_LOCK,
+ EPLL_CON0, NULL),
+ [rpll] = PLL(pll_2650, CLK_FOUT_RPLL, "fout_rpll", "fin_pll", RPLL_LOCK,
+ RPLL_CON0, NULL),
+ [ipll] = PLL(pll_2550, CLK_FOUT_IPLL, "fout_ipll", "fin_pll", IPLL_LOCK,
+ IPLL_CON0, NULL),
+ [spll] = PLL(pll_2550, CLK_FOUT_SPLL, "fout_spll", "fin_pll", SPLL_LOCK,
+ SPLL_CON0, NULL),
+ [vpll] = PLL(pll_2550, CLK_FOUT_VPLL, "fout_vpll", "fin_pll", VPLL_LOCK,
+ VPLL_CON0, NULL),
+ [mpll] = PLL(pll_2550, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+ MPLL_CON0, NULL),
+ [bpll] = PLL(pll_2550, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+ BPLL_CON0, NULL),
+ [kpll] = PLL(pll_2550, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+ KPLL_CON0, NULL),
+};
+
+static struct of_device_id ext_clk_match[] __initdata = {
+ { .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
+ { },
+};
+
+/* register exynos5420 clocks */
+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)
+ panic("%s: failed to map registers\n", __func__);
+ } else {
+ panic("%s: unable to determine soc\n", __func__);
+ }
+
+ 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(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls),
+ reg_base);
+ 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
new file mode 100644
index 00000000000..647f1440aa6
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5440.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for Exynos5440 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5440.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#define CLKEN_OV_VAL 0xf8
+#define CPU_CLK_STATUS 0xfc
+#define MISC_DOUT1 0x558
+
+/* parent clock name list */
+PNAME(mout_armclk_p) = { "cplla", "cpllb" };
+PNAME(mout_spi_p) = { "div125", "div200" };
+
+/* fixed rate clocks generated outside the soc */
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
+ FRATE(0, "xtal", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks */
+static struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+ FRATE(0, "ppll", NULL, CLK_IS_ROOT, 1000000000),
+ FRATE(0, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
+ FRATE(0, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
+ FRATE(0, "usb_ohci12", NULL, CLK_IS_ROOT, 12000000),
+ FRATE(0, "usb_ohci48", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* fixed factor clocks */
+static struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+ FFACTOR(0, "div250", "ppll", 1, 4, 0),
+ FFACTOR(0, "div200", "ppll", 1, 5, 0),
+ FFACTOR(0, "div125", "div250", 1, 2, 0),
+};
+
+/* mux clocks */
+static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+ MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
+ MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p,
+ CPU_CLK_STATUS, 0, 1, "armclk"),
+};
+
+/* divider clocks */
+static struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+ DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
+};
+
+/* gate clocks */
+static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+ GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
+ GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
+ GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
+ GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
+ GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
+ GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
+ GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
+ GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
+ GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
+ GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
+ GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
+ GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
+ GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
+ GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
+ GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
+ GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
+ GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
+ GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
+ GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
+ GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
+};
+
+static struct of_device_id ext_clk_match[] __initdata = {
+ { .compatible = "samsung,clock-xtal", .data = (void *)0, },
+ {},
+};
+
+/* register exynos5440 clocks */
+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) {
+ pr_err("%s: failed to map clock controller registers,"
+ " aborting clock initialization\n", __func__);
+ return;
+ }
+
+ 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(ctx, exynos5440_fixed_rate_clks,
+ ARRAY_SIZE(exynos5440_fixed_rate_clks));
+ samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
+ ARRAY_SIZE(exynos5440_fixed_factor_clks));
+ samsung_clk_register_mux(ctx, exynos5440_mux_clks,
+ ARRAY_SIZE(exynos5440_mux_clks));
+ samsung_clk_register_div(ctx, exynos5440_div_clks,
+ ARRAY_SIZE(exynos5440_div_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"));
+ pr_info("exynos5440 clock initialization complete\n");
+}
+CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
new file mode 100644
index 00000000000..b07fad2a916
--- /dev/null
+++ b/drivers/clk/samsung/clk-pll.c
@@ -0,0 +1,1298 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file contains the utility functions to register the pll clocks.
+*/
+
+#include <linux/errno.h>
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+#define PLL_TIMEOUT_MS 10
+
+struct samsung_clk_pll {
+ struct clk_hw hw;
+ void __iomem *lock_reg;
+ void __iomem *con_reg;
+ enum samsung_pll_type type;
+ unsigned int rate_count;
+ const struct samsung_pll_rate_table *rate_table;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
+
+static const struct samsung_pll_rate_table *samsung_get_pll_settings(
+ struct samsung_clk_pll *pll, unsigned long rate)
+{
+ const struct samsung_pll_rate_table *rate_table = pll->rate_table;
+ int i;
+
+ for (i = 0; i < pll->rate_count; i++) {
+ if (rate == rate_table[i].rate)
+ return &rate_table[i];
+ }
+
+ return NULL;
+}
+
+static long samsung_pll_round_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_table = pll->rate_table;
+ int i;
+
+ /* Assumming rate_table is in descending order */
+ for (i = 0; i < pll->rate_count; i++) {
+ if (drate >= rate_table[i].rate)
+ return rate_table[i].rate;
+ }
+
+ /* return minimum supported value */
+ return rate_table[i - 1].rate;
+}
+
+/*
+ * 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 */
+#define PLL35XX_LOCK_FACTOR (270)
+
+#define PLL35XX_MDIV_MASK (0x3FF)
+#define PLL35XX_PDIV_MASK (0x3F)
+#define PLL35XX_SDIV_MASK (0x7)
+#define PLL35XX_LOCK_STAT_MASK (0x1)
+#define PLL35XX_MDIV_SHIFT (16)
+#define PLL35XX_PDIV_SHIFT (8)
+#define PLL35XX_SDIV_SHIFT (0)
+#define PLL35XX_LOCK_STAT_SHIFT (29)
+
+static unsigned long samsung_pll35xx_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 >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+static inline bool samsung_pll35xx_mp_change(
+ const struct samsung_pll_rate_table *rate, u32 pll_con)
+{
+ u32 old_mdiv, old_pdiv;
+
+ old_mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
+ old_pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
+
+ return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv);
+}
+
+static int samsung_pll35xx_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_pll35xx_mp_change(rate, tmp))) {
+ /* If only s change, change just s value only*/
+ tmp &= ~(PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT);
+ tmp |= rate->sdiv << PLL35XX_SDIV_SHIFT;
+ __raw_writel(tmp, pll->con_reg);
+
+ return 0;
+ }
+
+ /* Set PLL lock time. */
+ __raw_writel(rate->pdiv * PLL35XX_LOCK_FACTOR,
+ pll->lock_reg);
+
+ /* Change PLL PMS values */
+ tmp &= ~((PLL35XX_MDIV_MASK << PLL35XX_MDIV_SHIFT) |
+ (PLL35XX_PDIV_MASK << PLL35XX_PDIV_SHIFT) |
+ (PLL35XX_SDIV_MASK << PLL35XX_SDIV_SHIFT));
+ tmp |= (rate->mdiv << PLL35XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL35XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL35XX_SDIV_SHIFT);
+ __raw_writel(tmp, pll->con_reg);
+
+ /* wait_lock_time */
+ do {
+ cpu_relax();
+ tmp = __raw_readl(pll->con_reg);
+ } while (!(tmp & (PLL35XX_LOCK_STAT_MASK
+ << PLL35XX_LOCK_STAT_SHIFT)));
+ return 0;
+}
+
+static const struct clk_ops samsung_pll35xx_clk_ops = {
+ .recalc_rate = samsung_pll35xx_recalc_rate,
+ .round_rate = samsung_pll_round_rate,
+ .set_rate = samsung_pll35xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll35xx_clk_min_ops = {
+ .recalc_rate = samsung_pll35xx_recalc_rate,
+};
+
+/*
+ * PLL36xx Clock Type
+ */
+/* Maximum lock time can be 3000 * PDIV cycles */
+#define PLL36XX_LOCK_FACTOR (3000)
+
+#define PLL36XX_KDIV_MASK (0xFFFF)
+#define PLL36XX_MDIV_MASK (0x1FF)
+#define PLL36XX_PDIV_MASK (0x3F)
+#define PLL36XX_SDIV_MASK (0x7)
+#define PLL36XX_MDIV_SHIFT (16)
+#define PLL36XX_PDIV_SHIFT (8)
+#define PLL36XX_SDIV_SHIFT (0)
+#define PLL36XX_KDIV_SHIFT (0)
+#define PLL36XX_LOCK_STAT_SHIFT (29)
+
+static unsigned long samsung_pll36xx_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_con1;
+ s16 kdiv;
+ u64 fvco = parent_rate;
+
+ pll_con0 = __raw_readl(pll->con_reg);
+ pll_con1 = __raw_readl(pll->con_reg + 4);
+ mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
+ kdiv = (s16)(pll_con1 & PLL36XX_KDIV_MASK);
+
+ fvco *= (mdiv << 16) + kdiv;
+ do_div(fvco, (pdiv << sdiv));
+ fvco >>= 16;
+
+ return (unsigned long)fvco;
+}
+
+static inline bool samsung_pll36xx_mpk_change(
+ const struct samsung_pll_rate_table *rate, u32 pll_con0, u32 pll_con1)
+{
+ u32 old_mdiv, old_pdiv, old_kdiv;
+
+ old_mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
+ old_pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
+ old_kdiv = (pll_con1 >> PLL36XX_KDIV_SHIFT) & PLL36XX_KDIV_MASK;
+
+ return (rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+ rate->kdiv != old_kdiv);
+}
+
+static int samsung_pll36xx_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_con1;
+ 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_con1 = __raw_readl(pll->con_reg + 4);
+
+ if (!(samsung_pll36xx_mpk_change(rate, pll_con0, pll_con1))) {
+ /* If only s change, change just s value only*/
+ pll_con0 &= ~(PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT);
+ pll_con0 |= (rate->sdiv << PLL36XX_SDIV_SHIFT);
+ __raw_writel(pll_con0, pll->con_reg);
+
+ return 0;
+ }
+
+ /* Set PLL lock time. */
+ __raw_writel(rate->pdiv * PLL36XX_LOCK_FACTOR, pll->lock_reg);
+
+ /* Change PLL PMS values */
+ pll_con0 &= ~((PLL36XX_MDIV_MASK << PLL36XX_MDIV_SHIFT) |
+ (PLL36XX_PDIV_MASK << PLL36XX_PDIV_SHIFT) |
+ (PLL36XX_SDIV_MASK << PLL36XX_SDIV_SHIFT));
+ pll_con0 |= (rate->mdiv << PLL36XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL36XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL36XX_SDIV_SHIFT);
+ __raw_writel(pll_con0, pll->con_reg);
+
+ pll_con1 &= ~(PLL36XX_KDIV_MASK << PLL36XX_KDIV_SHIFT);
+ pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT;
+ __raw_writel(pll_con1, pll->con_reg + 4);
+
+ /* wait_lock_time */
+ do {
+ cpu_relax();
+ tmp = __raw_readl(pll->con_reg);
+ } while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
+
+ return 0;
+}
+
+static const struct clk_ops samsung_pll36xx_clk_ops = {
+ .recalc_rate = samsung_pll36xx_recalc_rate,
+ .set_rate = samsung_pll36xx_set_rate,
+ .round_rate = samsung_pll_round_rate,
+};
+
+static const struct clk_ops samsung_pll36xx_clk_min_ops = {
+ .recalc_rate = samsung_pll36xx_recalc_rate,
+};
+
+/*
+ * PLL45xx Clock Type
+ */
+#define PLL4502_LOCK_FACTOR 400
+#define PLL4508_LOCK_FACTOR 240
+
+#define PLL45XX_MDIV_MASK (0x3FF)
+#define PLL45XX_PDIV_MASK (0x3F)
+#define PLL45XX_SDIV_MASK (0x7)
+#define PLL45XX_AFC_MASK (0x1F)
+#define PLL45XX_MDIV_SHIFT (16)
+#define PLL45XX_PDIV_SHIFT (8)
+#define PLL45XX_SDIV_SHIFT (0)
+#define PLL45XX_AFC_SHIFT (0)
+
+#define PLL45XX_ENABLE BIT(31)
+#define PLL45XX_LOCKED BIT(29)
+
+static unsigned long samsung_pll45xx_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 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+ pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+ sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
+
+ if (pll->type == pll_4508)
+ sdiv = sdiv - 1;
+
+ fvco *= mdiv;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+static bool samsung_pll45xx_mp_change(u32 pll_con0, u32 pll_con1,
+ const struct samsung_pll_rate_table *rate)
+{
+ u32 old_mdiv, old_pdiv, old_afc;
+
+ old_mdiv = (pll_con0 >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
+ old_pdiv = (pll_con0 >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
+ old_afc = (pll_con1 >> PLL45XX_AFC_SHIFT) & PLL45XX_AFC_MASK;
+
+ return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
+ || old_afc != rate->afc);
+}
+
+static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ const struct samsung_pll_rate_table *rate;
+ u32 con0, con1;
+ ktime_t start;
+
+ /* 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;
+ }
+
+ con0 = __raw_readl(pll->con_reg);
+ con1 = __raw_readl(pll->con_reg + 0x4);
+
+ if (!(samsung_pll45xx_mp_change(con0, con1, rate))) {
+ /* If only s change, change just s value only*/
+ con0 &= ~(PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT);
+ con0 |= rate->sdiv << PLL45XX_SDIV_SHIFT;
+ __raw_writel(con0, pll->con_reg);
+
+ return 0;
+ }
+
+ /* Set PLL PMS values. */
+ con0 &= ~((PLL45XX_MDIV_MASK << PLL45XX_MDIV_SHIFT) |
+ (PLL45XX_PDIV_MASK << PLL45XX_PDIV_SHIFT) |
+ (PLL45XX_SDIV_MASK << PLL45XX_SDIV_SHIFT));
+ con0 |= (rate->mdiv << PLL45XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL45XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL45XX_SDIV_SHIFT);
+
+ /* Set PLL AFC value. */
+ con1 = __raw_readl(pll->con_reg + 0x4);
+ con1 &= ~(PLL45XX_AFC_MASK << PLL45XX_AFC_SHIFT);
+ con1 |= (rate->afc << PLL45XX_AFC_SHIFT);
+
+ /* Set PLL lock time. */
+ switch (pll->type) {
+ case pll_4502:
+ __raw_writel(rate->pdiv * PLL4502_LOCK_FACTOR, pll->lock_reg);
+ break;
+ case pll_4508:
+ __raw_writel(rate->pdiv * PLL4508_LOCK_FACTOR, pll->lock_reg);
+ break;
+ default:
+ break;
+ }
+
+ /* Set new configuration. */
+ __raw_writel(con1, pll->con_reg + 0x4);
+ __raw_writel(con0, pll->con_reg);
+
+ /* Wait for locking. */
+ start = ktime_get();
+ while (!(__raw_readl(pll->con_reg) & PLL45XX_LOCKED)) {
+ ktime_t delta = ktime_sub(ktime_get(), start);
+
+ if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
+ pr_err("%s: could not lock PLL %s\n",
+ __func__, __clk_get_name(hw->clk));
+ return -EFAULT;
+ }
+
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static const struct clk_ops samsung_pll45xx_clk_ops = {
+ .recalc_rate = samsung_pll45xx_recalc_rate,
+ .round_rate = samsung_pll_round_rate,
+ .set_rate = samsung_pll45xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll45xx_clk_min_ops = {
+ .recalc_rate = samsung_pll45xx_recalc_rate,
+};
+
+/*
+ * PLL46xx Clock Type
+ */
+#define PLL46XX_LOCK_FACTOR 3000
+
+#define PLL46XX_VSEL_MASK (1)
+#define PLL46XX_MDIV_MASK (0x1FF)
+#define PLL46XX_PDIV_MASK (0x3F)
+#define PLL46XX_SDIV_MASK (0x7)
+#define PLL46XX_VSEL_SHIFT (27)
+#define PLL46XX_MDIV_SHIFT (16)
+#define PLL46XX_PDIV_SHIFT (8)
+#define PLL46XX_SDIV_SHIFT (0)
+
+#define PLL46XX_KDIV_MASK (0xFFFF)
+#define PLL4650C_KDIV_MASK (0xFFF)
+#define PLL46XX_KDIV_SHIFT (0)
+#define PLL46XX_MFR_MASK (0x3F)
+#define PLL46XX_MRR_MASK (0x1F)
+#define PLL46XX_KDIV_SHIFT (0)
+#define PLL46XX_MFR_SHIFT (16)
+#define PLL46XX_MRR_SHIFT (24)
+
+#define PLL46XX_ENABLE BIT(31)
+#define PLL46XX_LOCKED BIT(29)
+#define PLL46XX_VSEL BIT(27)
+
+static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
+ u64 fvco = parent_rate;
+
+ pll_con0 = __raw_readl(pll->con_reg);
+ pll_con1 = __raw_readl(pll->con_reg + 4);
+ mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
+ kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
+ pll_con1 & PLL46XX_KDIV_MASK;
+
+ shift = pll->type == pll_4600 ? 16 : 10;
+ fvco *= (mdiv << shift) + kdiv;
+ do_div(fvco, (pdiv << sdiv));
+ fvco >>= shift;
+
+ return (unsigned long)fvco;
+}
+
+static bool samsung_pll46xx_mpk_change(u32 pll_con0, u32 pll_con1,
+ const struct samsung_pll_rate_table *rate)
+{
+ u32 old_mdiv, old_pdiv, old_kdiv;
+
+ old_mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
+ old_pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
+ old_kdiv = (pll_con1 >> PLL46XX_KDIV_SHIFT) & PLL46XX_KDIV_MASK;
+
+ return (old_mdiv != rate->mdiv || old_pdiv != rate->pdiv
+ || old_kdiv != rate->kdiv);
+}
+
+static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ const struct samsung_pll_rate_table *rate;
+ u32 con0, con1, lock;
+ ktime_t start;
+
+ /* 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;
+ }
+
+ con0 = __raw_readl(pll->con_reg);
+ con1 = __raw_readl(pll->con_reg + 0x4);
+
+ if (!(samsung_pll46xx_mpk_change(con0, con1, rate))) {
+ /* If only s change, change just s value only*/
+ con0 &= ~(PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+ con0 |= rate->sdiv << PLL46XX_SDIV_SHIFT;
+ __raw_writel(con0, pll->con_reg);
+
+ return 0;
+ }
+
+ /* Set PLL lock time. */
+ lock = rate->pdiv * PLL46XX_LOCK_FACTOR;
+ if (lock > 0xffff)
+ /* Maximum lock time bitfield is 16-bit. */
+ lock = 0xffff;
+
+ /* Set PLL PMS and VSEL values. */
+ con0 &= ~((PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT) |
+ (PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT) |
+ (PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT) |
+ (PLL46XX_VSEL_MASK << PLL46XX_VSEL_SHIFT));
+ con0 |= (rate->mdiv << PLL46XX_MDIV_SHIFT) |
+ (rate->pdiv << PLL46XX_PDIV_SHIFT) |
+ (rate->sdiv << PLL46XX_SDIV_SHIFT) |
+ (rate->vsel << PLL46XX_VSEL_SHIFT);
+
+ /* Set PLL K, MFR and MRR values. */
+ con1 = __raw_readl(pll->con_reg + 0x4);
+ con1 &= ~((PLL46XX_KDIV_MASK << PLL46XX_KDIV_SHIFT) |
+ (PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT) |
+ (PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT));
+ con1 |= (rate->kdiv << PLL46XX_KDIV_SHIFT) |
+ (rate->mfr << PLL46XX_MFR_SHIFT) |
+ (rate->mrr << PLL46XX_MRR_SHIFT);
+
+ /* Write configuration to PLL */
+ __raw_writel(lock, pll->lock_reg);
+ __raw_writel(con0, pll->con_reg);
+ __raw_writel(con1, pll->con_reg + 0x4);
+
+ /* Wait for locking. */
+ start = ktime_get();
+ while (!(__raw_readl(pll->con_reg) & PLL46XX_LOCKED)) {
+ ktime_t delta = ktime_sub(ktime_get(), start);
+
+ if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) {
+ pr_err("%s: could not lock PLL %s\n",
+ __func__, __clk_get_name(hw->clk));
+ return -EFAULT;
+ }
+
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static const struct clk_ops samsung_pll46xx_clk_ops = {
+ .recalc_rate = samsung_pll46xx_recalc_rate,
+ .round_rate = samsung_pll_round_rate,
+ .set_rate = samsung_pll46xx_set_rate,
+};
+
+static const struct clk_ops samsung_pll46xx_clk_min_ops = {
+ .recalc_rate = samsung_pll46xx_recalc_rate,
+};
+
+/*
+ * PLL6552 Clock Type
+ */
+
+#define PLL6552_MDIV_MASK 0x3ff
+#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,
+ 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);
+ 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;
+ do_div(fvco, (pdiv << sdiv));
+
+ return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll6552_clk_ops = {
+ .recalc_rate = samsung_pll6552_recalc_rate,
+};
+
+/*
+ * PLL6553 Clock Type
+ */
+
+#define PLL6553_MDIV_MASK 0xff
+#define PLL6553_PDIV_MASK 0x3f
+#define PLL6553_SDIV_MASK 0x7
+#define PLL6553_KDIV_MASK 0xffff
+#define PLL6553_MDIV_SHIFT 16
+#define PLL6553_PDIV_SHIFT 8
+#define PLL6553_SDIV_SHIFT 0
+#define PLL6553_KDIV_SHIFT 0
+
+static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll *pll = to_clk_pll(hw);
+ u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
+ u64 fvco = parent_rate;
+
+ pll_con0 = __raw_readl(pll->con_reg);
+ pll_con1 = __raw_readl(pll->con_reg + 0x4);
+ mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK;
+ pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK;
+ sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK;
+ kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK;
+
+ fvco *= (mdiv << 16) + kdiv;
+ do_div(fvco, (pdiv << sdiv));
+ fvco >>= 16;
+
+ return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll6553_clk_ops = {
+ .recalc_rate = samsung_pll6553_recalc_rate,
+};
+
+/*
+ * 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
+ */
+
+#define PLL2550X_R_MASK (0x1)
+#define PLL2550X_P_MASK (0x3F)
+#define PLL2550X_M_MASK (0x3FF)
+#define PLL2550X_S_MASK (0x7)
+#define PLL2550X_R_SHIFT (20)
+#define PLL2550X_P_SHIFT (14)
+#define PLL2550X_M_SHIFT (4)
+#define PLL2550X_S_SHIFT (0)
+
+struct samsung_clk_pll2550x {
+ struct clk_hw hw;
+ const void __iomem *reg_base;
+ unsigned long offset;
+};
+
+#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
+
+static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
+ u32 r, p, m, s, pll_stat;
+ u64 fvco = parent_rate;
+
+ pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
+ r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
+ if (!r)
+ return 0;
+ p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
+ m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
+ s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
+
+ fvco *= m;
+ do_div(fvco, (p << s));
+
+ return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll2550x_clk_ops = {
+ .recalc_rate = samsung_pll2550x_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll2550x(const char *name,
+ const char *pname, const void __iomem *reg_base,
+ const unsigned long offset)
+{
+ struct samsung_clk_pll2550x *pll;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll) {
+ pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+ return NULL;
+ }
+
+ init.name = name;
+ init.ops = &samsung_pll2550x_clk_ops;
+ init.flags = CLK_GET_RATE_NOCACHE;
+ init.parent_names = &pname;
+ init.num_parents = 1;
+
+ pll->hw.init = &init;
+ pll->reg_base = reg_base;
+ pll->offset = offset;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register pll clock %s\n", __func__,
+ name);
+ kfree(pll);
+ }
+
+ if (clk_register_clkdev(clk, name, NULL))
+ pr_err("%s: failed to register lookup for %s", __func__, name);
+
+ return clk;
+}
+
+/*
+ * 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;
+ struct clk_init_data init;
+ int ret, len;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll) {
+ pr_err("%s: could not allocate pll clk %s\n",
+ __func__, pll_clk->name);
+ return;
+ }
+
+ init.name = pll_clk->name;
+ init.flags = pll_clk->flags;
+ init.parent_names = &pll_clk->parent_name;
+ init.num_parents = 1;
+
+ if (pll_clk->rate_table) {
+ /* find count of rates in rate_table */
+ for (len = 0; pll_clk->rate_table[len].rate != 0; )
+ len++;
+
+ pll->rate_count = len;
+ pll->rate_table = kmemdup(pll_clk->rate_table,
+ pll->rate_count *
+ sizeof(struct samsung_pll_rate_table),
+ GFP_KERNEL);
+ WARN(!pll->rate_table,
+ "%s: could not allocate rate table for %s\n",
+ __func__, pll_clk->name);
+ }
+
+ 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:
+ if (!pll->rate_table)
+ init.ops = &samsung_pll35xx_clk_min_ops;
+ else
+ init.ops = &samsung_pll35xx_clk_ops;
+ break;
+ case pll_4500:
+ init.ops = &samsung_pll45xx_clk_min_ops;
+ break;
+ case pll_4502:
+ case pll_4508:
+ if (!pll->rate_table)
+ init.ops = &samsung_pll45xx_clk_min_ops;
+ else
+ init.ops = &samsung_pll45xx_clk_ops;
+ break;
+ /* clk_ops for 36xx and 2650 are similar */
+ case pll_36xx:
+ case pll_2650:
+ if (!pll->rate_table)
+ init.ops = &samsung_pll36xx_clk_min_ops;
+ else
+ init.ops = &samsung_pll36xx_clk_ops;
+ break;
+ case pll_6552:
+ case pll_6552_s3c2416:
+ init.ops = &samsung_pll6552_clk_ops;
+ break;
+ case pll_6553:
+ init.ops = &samsung_pll6553_clk_ops;
+ break;
+ case pll_4600:
+ case pll_4650:
+ case pll_4650c:
+ if (!pll->rate_table)
+ init.ops = &samsung_pll46xx_clk_min_ops;
+ 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);
+ }
+
+ pll->hw.init = &init;
+ pll->type = pll_clk->type;
+ pll->lock_reg = base + pll_clk->lock_offset;
+ pll->con_reg = base + pll_clk->con_offset;
+
+ clk = clk_register(NULL, &pll->hw);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register pll clock %s : %ld\n",
+ __func__, pll_clk->name, PTR_ERR(clk));
+ kfree(pll);
+ return;
+ }
+
+ samsung_clk_add_lookup(ctx, clk, pll_clk->id);
+
+ if (!pll_clk->alias)
+ return;
+
+ ret = clk_register_clkdev(clk, pll_clk->alias, pll_clk->dev_name);
+ if (ret)
+ pr_err("%s: failed to register lookup for %s : %d",
+ __func__, pll_clk->name, ret);
+}
+
+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(ctx, &pll_list[cnt], base);
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
new file mode 100644
index 00000000000..c0ed4d41fd9
--- /dev/null
+++ b/drivers/clk/samsung/clk-pll.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all PLL's in Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_PLL_H
+#define __SAMSUNG_CLK_PLL_H
+
+enum samsung_pll_type {
+ pll_2126,
+ pll_3000,
+ pll_35xx,
+ pll_36xx,
+ pll_2550,
+ pll_2650,
+ pll_4500,
+ pll_4502,
+ pll_4508,
+ pll_4600,
+ 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) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ }
+
+#define PLL_36XX_RATE(_rate, _m, _p, _s, _k) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ }
+
+#define PLL_45XX_RATE(_rate, _m, _p, _s, _afc) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .afc = (_afc), \
+ }
+
+#define PLL_4600_RATE(_rate, _m, _p, _s, _k, _vsel) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ .vsel = (_vsel), \
+ }
+
+#define PLL_4650_RATE(_rate, _m, _p, _s, _k, _mfr, _mrr, _vsel) \
+ { \
+ .rate = (_rate), \
+ .mdiv = (_m), \
+ .pdiv = (_p), \
+ .sdiv = (_s), \
+ .kdiv = (_k), \
+ .mfr = (_mfr), \
+ .mrr = (_mrr), \
+ .vsel = (_vsel), \
+ }
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+
+struct samsung_pll_rate_table {
+ unsigned int rate;
+ unsigned int pdiv;
+ unsigned int mdiv;
+ unsigned int sdiv;
+ unsigned int kdiv;
+ unsigned int afc;
+ unsigned int mfr;
+ unsigned int mrr;
+ unsigned int vsel;
+};
+
+extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
+ const char *pname, const void __iomem *reg_base,
+ const unsigned long offset);
+
+#endif /* __SAMSUNG_CLK_PLL_H */
diff --git a/drivers/clk/samsung/clk-s3c2410-dclk.c b/drivers/clk/samsung/clk-s3c2410-dclk.c
new file mode 100644
index 00000000000..0449cc0458e
--- /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)
+
+static const char *dclk_s3c2410_p[] = { "pclk", "uclk" };
+static const char *clkout0_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
+ "gate_dclk0" };
+static const char *clkout1_s3c2410_p[] = { "mpll", "upll", "fclk", "hclk", "pclk",
+ "gate_dclk1" };
+
+static const char *clkout0_s3c2412_p[] = { "mpll", "upll", "rtc_clkout",
+ "hclk", "pclk", "gate_dclk0" };
+static const char *clkout1_s3c2412_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
+ "gate_dclk1" };
+
+static const char *clkout0_s3c2440_p[] = { "xti", "upll", "fclk", "hclk", "pclk",
+ "gate_dclk0" };
+static const char *clkout1_s3c2440_p[] = { "mpll", "upll", "rtc_clkout",
+ "hclk", "pclk", "gate_dclk1" };
+
+static const char *dclk_s3c2443_p[] = { "pclk", "epll" };
+static const char *clkout0_s3c2443_p[] = { "xti", "epll", "armclk", "hclk", "pclk",
+ "gate_dclk0" };
+static const char *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 00000000000..140f4733c02
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -0,0 +1,487 @@
+/*
+ * 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"),
+ 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 */
+
+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 == 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;
+ }
+
+ /* 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_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 00000000000..23e4313f625
--- /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 00000000000..c4bbdabebaa
--- /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
new file mode 100644
index 00000000000..8889ff1c10f
--- /dev/null
+++ b/drivers/clk/samsung/clk-s3c64xx.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all S3C64xx 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/samsung,s3c64xx-clock.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+/* S3C64xx clock controller register offsets. */
+#define APLL_LOCK 0x000
+#define MPLL_LOCK 0x004
+#define EPLL_LOCK 0x008
+#define APLL_CON 0x00c
+#define MPLL_CON 0x010
+#define EPLL_CON0 0x014
+#define EPLL_CON1 0x018
+#define CLK_SRC 0x01c
+#define CLK_DIV0 0x020
+#define CLK_DIV1 0x024
+#define CLK_DIV2 0x028
+#define HCLK_GATE 0x030
+#define PCLK_GATE 0x034
+#define SCLK_GATE 0x038
+#define MEM0_GATE 0x03c
+#define CLK_SRC2 0x10c
+#define OTHERS 0x900
+
+/* Helper macros to define clock arrays. */
+#define FIXED_RATE_CLOCKS(name) \
+ static struct samsung_fixed_rate_clock name[]
+#define MUX_CLOCKS(name) \
+ static struct samsung_mux_clock name[]
+#define DIV_CLOCKS(name) \
+ static struct samsung_div_clock name[]
+#define GATE_CLOCKS(name) \
+ static struct samsung_gate_clock name[]
+
+/* Helper macros for gate types present on S3C64xx. */
+#define GATE_BUS(_id, cname, pname, o, b) \
+ GATE(_id, cname, pname, o, b, 0, 0)
+#define GATE_SCLK(_id, cname, pname, o, b) \
+ GATE(_id, cname, pname, o, b, CLK_SET_RATE_PARENT, 0)
+#define GATE_ON(_id, cname, pname, o, b) \
+ GATE(_id, cname, pname, o, b, CLK_IGNORE_UNUSED, 0)
+
+/* list of PLLs to be registered */
+enum s3c64xx_plls {
+ apll, mpll, epll,
+};
+
+static void __iomem *reg_base;
+static bool is_s3c6400;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s3c64xx_save_common;
+static struct samsung_clk_reg_dump *s3c64xx_save_soc;
+
+/*
+ * List of controller registers to be saved and restored during
+ * a suspend/resume cycle.
+ */
+static unsigned long s3c64xx_clk_regs[] __initdata = {
+ APLL_LOCK,
+ MPLL_LOCK,
+ EPLL_LOCK,
+ APLL_CON,
+ MPLL_CON,
+ EPLL_CON0,
+ EPLL_CON1,
+ CLK_SRC,
+ CLK_DIV0,
+ CLK_DIV1,
+ CLK_DIV2,
+ HCLK_GATE,
+ PCLK_GATE,
+ SCLK_GATE,
+};
+
+static unsigned long s3c6410_clk_regs[] __initdata = {
+ CLK_SRC2,
+ MEM0_GATE,
+};
+
+static int s3c64xx_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, s3c64xx_save_common,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+
+ if (!is_s3c6400)
+ samsung_clk_save(reg_base, s3c64xx_save_soc,
+ ARRAY_SIZE(s3c6410_clk_regs));
+
+ return 0;
+}
+
+static void s3c64xx_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, s3c64xx_save_common,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+
+ if (!is_s3c6400)
+ samsung_clk_restore(reg_base, s3c64xx_save_soc,
+ ARRAY_SIZE(s3c6410_clk_regs));
+}
+
+static struct syscore_ops s3c64xx_clk_syscore_ops = {
+ .suspend = s3c64xx_clk_suspend,
+ .resume = s3c64xx_clk_resume,
+};
+
+static void s3c64xx_clk_sleep_init(void)
+{
+ s3c64xx_save_common = samsung_clk_alloc_reg_dump(s3c64xx_clk_regs,
+ ARRAY_SIZE(s3c64xx_clk_regs));
+ if (!s3c64xx_save_common)
+ goto err_warn;
+
+ if (!is_s3c6400) {
+ s3c64xx_save_soc = samsung_clk_alloc_reg_dump(s3c6410_clk_regs,
+ ARRAY_SIZE(s3c6410_clk_regs));
+ if (!s3c64xx_save_soc)
+ goto err_soc;
+ }
+
+ register_syscore_ops(&s3c64xx_clk_syscore_ops);
+ return;
+
+err_soc:
+ kfree(s3c64xx_save_common);
+err_warn:
+ pr_warn("%s: failed to allocate sleep save data, no sleep support!\n",
+ __func__);
+}
+#else
+static void s3c64xx_clk_sleep_init(void) {}
+#endif
+
+/* List of parent clocks common for all S3C64xx SoCs. */
+PNAME(spi_mmc_p) = { "mout_epll", "dout_mpll", "fin_pll", "clk27m" };
+PNAME(uart_p) = { "mout_epll", "dout_mpll" };
+PNAME(audio0_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk0",
+ "pcmcdclk0", "none", "none", "none" };
+PNAME(audio1_p) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk1",
+ "pcmcdclk0", "none", "none", "none" };
+PNAME(mfc_p) = { "hclkx2", "mout_epll" };
+PNAME(apll_p) = { "fin_pll", "fout_apll" };
+PNAME(mpll_p) = { "fin_pll", "fout_mpll" };
+PNAME(epll_p) = { "fin_pll", "fout_epll" };
+PNAME(hclkx2_p) = { "mout_mpll", "mout_apll" };
+
+/* S3C6400-specific parent clocks. */
+PNAME(scaler_lcd_p6400) = { "mout_epll", "dout_mpll", "none", "none" };
+PNAME(irda_p6400) = { "mout_epll", "dout_mpll", "none", "clk48m" };
+PNAME(uhost_p6400) = { "clk48m", "mout_epll", "dout_mpll", "none" };
+
+/* S3C6410-specific parent clocks. */
+PNAME(clk27_p6410) = { "clk27m", "fin_pll" };
+PNAME(scaler_lcd_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "none" };
+PNAME(irda_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "clk48m" };
+PNAME(uhost_p6410) = { "clk48m", "mout_epll", "dout_mpll", "fin_pll" };
+PNAME(audio2_p6410) = { "mout_epll", "dout_mpll", "fin_pll", "iiscdclk2",
+ "pcmcdclk1", "none", "none", "none" };
+
+/* Fixed rate clocks generated outside the SoC. */
+FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_ext_clks) __initdata = {
+ FRATE(0, "fin_pll", NULL, CLK_IS_ROOT, 0),
+ FRATE(0, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* Fixed rate clocks generated inside the SoC. */
+FIXED_RATE_CLOCKS(s3c64xx_fixed_rate_clks) __initdata = {
+ FRATE(CLK27M, "clk27m", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(CLK48M, "clk48m", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* List of clock muxes present on all S3C64xx SoCs. */
+MUX_CLOCKS(s3c64xx_mux_clks) __initdata = {
+ MUX_F(0, "mout_syncmux", hclkx2_p, OTHERS, 6, 1, 0, CLK_MUX_READ_ONLY),
+ MUX(MOUT_APLL, "mout_apll", apll_p, CLK_SRC, 0, 1),
+ MUX(MOUT_MPLL, "mout_mpll", mpll_p, CLK_SRC, 1, 1),
+ MUX(MOUT_EPLL, "mout_epll", epll_p, CLK_SRC, 2, 1),
+ MUX(MOUT_MFC, "mout_mfc", mfc_p, CLK_SRC, 4, 1),
+ MUX(MOUT_AUDIO0, "mout_audio0", audio0_p, CLK_SRC, 7, 3),
+ MUX(MOUT_AUDIO1, "mout_audio1", audio1_p, CLK_SRC, 10, 3),
+ MUX(MOUT_UART, "mout_uart", uart_p, CLK_SRC, 13, 1),
+ MUX(MOUT_SPI0, "mout_spi0", spi_mmc_p, CLK_SRC, 14, 2),
+ MUX(MOUT_SPI1, "mout_spi1", spi_mmc_p, CLK_SRC, 16, 2),
+ MUX(MOUT_MMC0, "mout_mmc0", spi_mmc_p, CLK_SRC, 18, 2),
+ MUX(MOUT_MMC1, "mout_mmc1", spi_mmc_p, CLK_SRC, 20, 2),
+ MUX(MOUT_MMC2, "mout_mmc2", spi_mmc_p, CLK_SRC, 22, 2),
+};
+
+/* List of clock muxes present on S3C6400. */
+MUX_CLOCKS(s3c6400_mux_clks) __initdata = {
+ MUX(MOUT_UHOST, "mout_uhost", uhost_p6400, CLK_SRC, 5, 2),
+ MUX(MOUT_IRDA, "mout_irda", irda_p6400, CLK_SRC, 24, 2),
+ MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6400, CLK_SRC, 26, 2),
+ MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6400, CLK_SRC, 28, 2),
+};
+
+/* List of clock muxes present on S3C6410. */
+MUX_CLOCKS(s3c6410_mux_clks) __initdata = {
+ MUX(MOUT_UHOST, "mout_uhost", uhost_p6410, CLK_SRC, 5, 2),
+ MUX(MOUT_IRDA, "mout_irda", irda_p6410, CLK_SRC, 24, 2),
+ MUX(MOUT_LCD, "mout_lcd", scaler_lcd_p6410, CLK_SRC, 26, 2),
+ MUX(MOUT_SCALER, "mout_scaler", scaler_lcd_p6410, CLK_SRC, 28, 2),
+ MUX(MOUT_DAC27, "mout_dac27", clk27_p6410, CLK_SRC, 30, 1),
+ MUX(MOUT_TV27, "mout_tv27", clk27_p6410, CLK_SRC, 31, 1),
+ MUX(MOUT_AUDIO2, "mout_audio2", audio2_p6410, CLK_SRC2, 0, 3),
+};
+
+/* List of clock dividers present on all S3C64xx SoCs. */
+DIV_CLOCKS(s3c64xx_div_clks) __initdata = {
+ DIV(DOUT_MPLL, "dout_mpll", "mout_mpll", CLK_DIV0, 4, 1),
+ DIV(HCLKX2, "hclkx2", "mout_syncmux", CLK_DIV0, 9, 3),
+ DIV(HCLK, "hclk", "hclkx2", CLK_DIV0, 8, 1),
+ DIV(PCLK, "pclk", "hclkx2", CLK_DIV0, 12, 4),
+ DIV(DOUT_SECUR, "dout_secur", "hclkx2", CLK_DIV0, 18, 2),
+ DIV(DOUT_CAM, "dout_cam", "hclkx2", CLK_DIV0, 20, 4),
+ DIV(DOUT_JPEG, "dout_jpeg", "hclkx2", CLK_DIV0, 24, 4),
+ DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV0, 28, 4),
+ DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV1, 0, 4),
+ DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV1, 4, 4),
+ DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV1, 8, 4),
+ DIV(DOUT_LCD, "dout_lcd", "mout_lcd", CLK_DIV1, 12, 4),
+ DIV(DOUT_SCALER, "dout_scaler", "mout_scaler", CLK_DIV1, 16, 4),
+ DIV(DOUT_UHOST, "dout_uhost", "mout_uhost", CLK_DIV1, 20, 4),
+ DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV2, 0, 4),
+ DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV2, 4, 4),
+ DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV2, 8, 4),
+ DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV2, 12, 4),
+ DIV(DOUT_UART, "dout_uart", "mout_uart", CLK_DIV2, 16, 4),
+ DIV(DOUT_IRDA, "dout_irda", "mout_irda", CLK_DIV2, 20, 4),
+};
+
+/* List of clock dividers present on S3C6400. */
+DIV_CLOCKS(s3c6400_div_clks) __initdata = {
+ DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 3),
+};
+
+/* List of clock dividers present on S3C6410. */
+DIV_CLOCKS(s3c6410_div_clks) __initdata = {
+ DIV(ARMCLK, "armclk", "mout_apll", CLK_DIV0, 0, 4),
+ DIV(DOUT_FIMC, "dout_fimc", "hclk", CLK_DIV1, 24, 4),
+ DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV2, 24, 4),
+};
+
+/* List of clock gates present on all S3C64xx SoCs. */
+GATE_CLOCKS(s3c64xx_gate_clks) __initdata = {
+ GATE_BUS(HCLK_UHOST, "hclk_uhost", "hclk", HCLK_GATE, 29),
+ GATE_BUS(HCLK_SECUR, "hclk_secur", "hclk", HCLK_GATE, 28),
+ GATE_BUS(HCLK_SDMA1, "hclk_sdma1", "hclk", HCLK_GATE, 27),
+ GATE_BUS(HCLK_SDMA0, "hclk_sdma0", "hclk", HCLK_GATE, 26),
+ GATE_ON(HCLK_DDR1, "hclk_ddr1", "hclk", HCLK_GATE, 24),
+ GATE_BUS(HCLK_USB, "hclk_usb", "hclk", HCLK_GATE, 20),
+ GATE_BUS(HCLK_HSMMC2, "hclk_hsmmc2", "hclk", HCLK_GATE, 19),
+ GATE_BUS(HCLK_HSMMC1, "hclk_hsmmc1", "hclk", HCLK_GATE, 18),
+ GATE_BUS(HCLK_HSMMC0, "hclk_hsmmc0", "hclk", HCLK_GATE, 17),
+ GATE_BUS(HCLK_MDP, "hclk_mdp", "hclk", HCLK_GATE, 16),
+ GATE_BUS(HCLK_DHOST, "hclk_dhost", "hclk", HCLK_GATE, 15),
+ GATE_BUS(HCLK_IHOST, "hclk_ihost", "hclk", HCLK_GATE, 14),
+ GATE_BUS(HCLK_DMA1, "hclk_dma1", "hclk", HCLK_GATE, 13),
+ GATE_BUS(HCLK_DMA0, "hclk_dma0", "hclk", HCLK_GATE, 12),
+ GATE_BUS(HCLK_JPEG, "hclk_jpeg", "hclk", HCLK_GATE, 11),
+ GATE_BUS(HCLK_CAMIF, "hclk_camif", "hclk", HCLK_GATE, 10),
+ GATE_BUS(HCLK_SCALER, "hclk_scaler", "hclk", HCLK_GATE, 9),
+ GATE_BUS(HCLK_2D, "hclk_2d", "hclk", HCLK_GATE, 8),
+ GATE_BUS(HCLK_TV, "hclk_tv", "hclk", HCLK_GATE, 7),
+ GATE_BUS(HCLK_POST0, "hclk_post0", "hclk", HCLK_GATE, 5),
+ GATE_BUS(HCLK_ROT, "hclk_rot", "hclk", HCLK_GATE, 4),
+ GATE_BUS(HCLK_LCD, "hclk_lcd", "hclk", HCLK_GATE, 3),
+ GATE_BUS(HCLK_TZIC, "hclk_tzic", "hclk", HCLK_GATE, 2),
+ GATE_ON(HCLK_INTC, "hclk_intc", "hclk", HCLK_GATE, 1),
+ GATE_ON(PCLK_SKEY, "pclk_skey", "pclk", PCLK_GATE, 24),
+ GATE_ON(PCLK_CHIPID, "pclk_chipid", "pclk", PCLK_GATE, 23),
+ GATE_BUS(PCLK_SPI1, "pclk_spi1", "pclk", PCLK_GATE, 22),
+ GATE_BUS(PCLK_SPI0, "pclk_spi0", "pclk", PCLK_GATE, 21),
+ GATE_BUS(PCLK_HSIRX, "pclk_hsirx", "pclk", PCLK_GATE, 20),
+ GATE_BUS(PCLK_HSITX, "pclk_hsitx", "pclk", PCLK_GATE, 19),
+ GATE_ON(PCLK_GPIO, "pclk_gpio", "pclk", PCLK_GATE, 18),
+ GATE_BUS(PCLK_IIC0, "pclk_iic0", "pclk", PCLK_GATE, 17),
+ GATE_BUS(PCLK_IIS1, "pclk_iis1", "pclk", PCLK_GATE, 16),
+ GATE_BUS(PCLK_IIS0, "pclk_iis0", "pclk", PCLK_GATE, 15),
+ GATE_BUS(PCLK_AC97, "pclk_ac97", "pclk", PCLK_GATE, 14),
+ GATE_BUS(PCLK_TZPC, "pclk_tzpc", "pclk", PCLK_GATE, 13),
+ GATE_BUS(PCLK_TSADC, "pclk_tsadc", "pclk", PCLK_GATE, 12),
+ GATE_BUS(PCLK_KEYPAD, "pclk_keypad", "pclk", PCLK_GATE, 11),
+ GATE_BUS(PCLK_IRDA, "pclk_irda", "pclk", PCLK_GATE, 10),
+ GATE_BUS(PCLK_PCM1, "pclk_pcm1", "pclk", PCLK_GATE, 9),
+ GATE_BUS(PCLK_PCM0, "pclk_pcm0", "pclk", PCLK_GATE, 8),
+ GATE_BUS(PCLK_PWM, "pclk_pwm", "pclk", PCLK_GATE, 7),
+ GATE_BUS(PCLK_RTC, "pclk_rtc", "pclk", PCLK_GATE, 6),
+ GATE_BUS(PCLK_WDT, "pclk_wdt", "pclk", PCLK_GATE, 5),
+ GATE_BUS(PCLK_UART3, "pclk_uart3", "pclk", PCLK_GATE, 4),
+ GATE_BUS(PCLK_UART2, "pclk_uart2", "pclk", PCLK_GATE, 3),
+ GATE_BUS(PCLK_UART1, "pclk_uart1", "pclk", PCLK_GATE, 2),
+ GATE_BUS(PCLK_UART0, "pclk_uart0", "pclk", PCLK_GATE, 1),
+ GATE_BUS(PCLK_MFC, "pclk_mfc", "pclk", PCLK_GATE, 0),
+ GATE_SCLK(SCLK_UHOST, "sclk_uhost", "dout_uhost", SCLK_GATE, 30),
+ GATE_SCLK(SCLK_MMC2_48, "sclk_mmc2_48", "clk48m", SCLK_GATE, 29),
+ GATE_SCLK(SCLK_MMC1_48, "sclk_mmc1_48", "clk48m", SCLK_GATE, 28),
+ GATE_SCLK(SCLK_MMC0_48, "sclk_mmc0_48", "clk48m", SCLK_GATE, 27),
+ GATE_SCLK(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", SCLK_GATE, 26),
+ GATE_SCLK(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", SCLK_GATE, 25),
+ GATE_SCLK(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", SCLK_GATE, 24),
+ GATE_SCLK(SCLK_SPI1_48, "sclk_spi1_48", "clk48m", SCLK_GATE, 23),
+ GATE_SCLK(SCLK_SPI0_48, "sclk_spi0_48", "clk48m", SCLK_GATE, 22),
+ GATE_SCLK(SCLK_SPI1, "sclk_spi1", "dout_spi1", SCLK_GATE, 21),
+ GATE_SCLK(SCLK_SPI0, "sclk_spi0", "dout_spi0", SCLK_GATE, 20),
+ GATE_SCLK(SCLK_DAC27, "sclk_dac27", "mout_dac27", SCLK_GATE, 19),
+ GATE_SCLK(SCLK_TV27, "sclk_tv27", "mout_tv27", SCLK_GATE, 18),
+ GATE_SCLK(SCLK_SCALER27, "sclk_scaler27", "clk27m", SCLK_GATE, 17),
+ GATE_SCLK(SCLK_SCALER, "sclk_scaler", "dout_scaler", SCLK_GATE, 16),
+ GATE_SCLK(SCLK_LCD27, "sclk_lcd27", "clk27m", SCLK_GATE, 15),
+ GATE_SCLK(SCLK_LCD, "sclk_lcd", "dout_lcd", SCLK_GATE, 14),
+ GATE_SCLK(SCLK_POST0_27, "sclk_post0_27", "clk27m", SCLK_GATE, 12),
+ GATE_SCLK(SCLK_POST0, "sclk_post0", "dout_lcd", SCLK_GATE, 10),
+ GATE_SCLK(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", SCLK_GATE, 9),
+ GATE_SCLK(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", SCLK_GATE, 8),
+ GATE_SCLK(SCLK_SECUR, "sclk_secur", "dout_secur", SCLK_GATE, 7),
+ GATE_SCLK(SCLK_IRDA, "sclk_irda", "dout_irda", SCLK_GATE, 6),
+ GATE_SCLK(SCLK_UART, "sclk_uart", "dout_uart", SCLK_GATE, 5),
+ GATE_SCLK(SCLK_MFC, "sclk_mfc", "dout_mfc", SCLK_GATE, 3),
+ GATE_SCLK(SCLK_CAM, "sclk_cam", "dout_cam", SCLK_GATE, 2),
+ GATE_SCLK(SCLK_JPEG, "sclk_jpeg", "dout_jpeg", SCLK_GATE, 1),
+};
+
+/* List of clock gates present on S3C6400. */
+GATE_CLOCKS(s3c6400_gate_clks) __initdata = {
+ GATE_ON(HCLK_DDR0, "hclk_ddr0", "hclk", HCLK_GATE, 23),
+ GATE_SCLK(SCLK_ONENAND, "sclk_onenand", "parent", SCLK_GATE, 4),
+};
+
+/* List of clock gates present on S3C6410. */
+GATE_CLOCKS(s3c6410_gate_clks) __initdata = {
+ GATE_BUS(HCLK_3DSE, "hclk_3dse", "hclk", HCLK_GATE, 31),
+ GATE_ON(HCLK_IROM, "hclk_irom", "hclk", HCLK_GATE, 25),
+ GATE_ON(HCLK_MEM1, "hclk_mem1", "hclk", HCLK_GATE, 22),
+ GATE_ON(HCLK_MEM0, "hclk_mem0", "hclk", HCLK_GATE, 21),
+ GATE_BUS(HCLK_MFC, "hclk_mfc", "hclk", HCLK_GATE, 0),
+ GATE_BUS(PCLK_IIC1, "pclk_iic1", "pclk", PCLK_GATE, 27),
+ GATE_BUS(PCLK_IIS2, "pclk_iis2", "pclk", PCLK_GATE, 26),
+ GATE_SCLK(SCLK_FIMC, "sclk_fimc", "dout_fimc", SCLK_GATE, 13),
+ GATE_SCLK(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", SCLK_GATE, 11),
+ GATE_BUS(MEM0_CFCON, "mem0_cfcon", "hclk_mem0", MEM0_GATE, 5),
+ GATE_BUS(MEM0_ONENAND1, "mem0_onenand1", "hclk_mem0", MEM0_GATE, 4),
+ GATE_BUS(MEM0_ONENAND0, "mem0_onenand0", "hclk_mem0", MEM0_GATE, 3),
+ GATE_BUS(MEM0_NFCON, "mem0_nfcon", "hclk_mem0", MEM0_GATE, 2),
+ GATE_ON(MEM0_SROM, "mem0_srom", "hclk_mem0", MEM0_GATE, 1),
+};
+
+/* List of PLL clocks. */
+static struct samsung_pll_clock s3c64xx_pll_clks[] __initdata = {
+ [apll] = PLL(pll_6552, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON, NULL),
+ [mpll] = PLL(pll_6552, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ [epll] = PLL(pll_6553, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+};
+
+/* Aliases for common s3c64xx clocks. */
+static struct samsung_clock_alias s3c64xx_clock_aliases[] = {
+ ALIAS(FOUT_APLL, NULL, "fout_apll"),
+ ALIAS(FOUT_MPLL, NULL, "fout_mpll"),
+ ALIAS(FOUT_EPLL, NULL, "fout_epll"),
+ ALIAS(MOUT_EPLL, NULL, "mout_epll"),
+ ALIAS(DOUT_MPLL, NULL, "dout_mpll"),
+ ALIAS(HCLKX2, NULL, "hclk2"),
+ ALIAS(HCLK, NULL, "hclk"),
+ ALIAS(PCLK, NULL, "pclk"),
+ ALIAS(PCLK, NULL, "clk_uart_baud2"),
+ ALIAS(ARMCLK, NULL, "armclk"),
+ ALIAS(HCLK_UHOST, "s3c2410-ohci", "usb-host"),
+ ALIAS(HCLK_USB, "s3c-hsotg", "otg"),
+ ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "hsmmc"),
+ ALIAS(HCLK_HSMMC2, "s3c-sdhci.2", "mmc_busclk.0"),
+ ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "hsmmc"),
+ ALIAS(HCLK_HSMMC1, "s3c-sdhci.1", "mmc_busclk.0"),
+ ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "hsmmc"),
+ ALIAS(HCLK_HSMMC0, "s3c-sdhci.0", "mmc_busclk.0"),
+ ALIAS(HCLK_DMA1, "dma-pl080s.1", "apb_pclk"),
+ ALIAS(HCLK_DMA0, "dma-pl080s.0", "apb_pclk"),
+ ALIAS(HCLK_CAMIF, "s3c-camif", "camif"),
+ ALIAS(HCLK_LCD, "s3c-fb", "lcd"),
+ ALIAS(PCLK_SPI1, "s3c6410-spi.1", "spi"),
+ ALIAS(PCLK_SPI0, "s3c6410-spi.0", "spi"),
+ ALIAS(PCLK_IIC0, "s3c2440-i2c.0", "i2c"),
+ ALIAS(PCLK_IIS1, "samsung-i2s.1", "iis"),
+ ALIAS(PCLK_IIS0, "samsung-i2s.0", "iis"),
+ ALIAS(PCLK_AC97, "samsung-ac97", "ac97"),
+ ALIAS(PCLK_TSADC, "s3c64xx-adc", "adc"),
+ ALIAS(PCLK_KEYPAD, "samsung-keypad", "keypad"),
+ ALIAS(PCLK_PCM1, "samsung-pcm.1", "pcm"),
+ ALIAS(PCLK_PCM0, "samsung-pcm.0", "pcm"),
+ ALIAS(PCLK_PWM, NULL, "timers"),
+ ALIAS(PCLK_RTC, "s3c64xx-rtc", "rtc"),
+ ALIAS(PCLK_WDT, NULL, "watchdog"),
+ ALIAS(PCLK_UART3, "s3c6400-uart.3", "uart"),
+ ALIAS(PCLK_UART2, "s3c6400-uart.2", "uart"),
+ ALIAS(PCLK_UART1, "s3c6400-uart.1", "uart"),
+ ALIAS(PCLK_UART0, "s3c6400-uart.0", "uart"),
+ ALIAS(SCLK_UHOST, "s3c2410-ohci", "usb-bus-host"),
+ 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(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"),
+ ALIAS(SCLK_AUDIO0, "samsung-i2s.0", "audio-bus"),
+ ALIAS(SCLK_UART, NULL, "clk_uart_baud3"),
+ ALIAS(SCLK_CAM, "s3c-camif", "camera"),
+};
+
+/* Aliases for s3c6400-specific clocks. */
+static struct samsung_clock_alias s3c6400_clock_aliases[] = {
+ /* Nothing to place here yet. */
+};
+
+/* Aliases for s3c6410-specific clocks. */
+static struct samsung_clock_alias s3c6410_clock_aliases[] = {
+ ALIAS(PCLK_IIC1, "s3c2440-i2c.1", "i2c"),
+ ALIAS(PCLK_IIS2, "samsung-i2s.2", "iis"),
+ ALIAS(SCLK_FIMC, "s3c-camif", "fimc"),
+ ALIAS(SCLK_AUDIO2, "samsung-i2s.2", "audio-bus"),
+ ALIAS(MEM0_SROM, NULL, "srom"),
+};
+
+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(ctx, s3c64xx_fixed_rate_ext_clks,
+ ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks));
+}
+
+/* Register s3c64xx clocks. */
+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;
+
+ 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. */
+ if (!np)
+ s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f);
+
+ /* Register PLLs. */
+ samsung_clk_register_pll(ctx, s3c64xx_pll_clks,
+ ARRAY_SIZE(s3c64xx_pll_clks), reg_base);
+
+ /* Register common internal clocks. */
+ samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks,
+ ARRAY_SIZE(s3c64xx_fixed_rate_clks));
+ samsung_clk_register_mux(ctx, s3c64xx_mux_clks,
+ ARRAY_SIZE(s3c64xx_mux_clks));
+ samsung_clk_register_div(ctx, s3c64xx_div_clks,
+ ARRAY_SIZE(s3c64xx_div_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(ctx, s3c6400_mux_clks,
+ ARRAY_SIZE(s3c6400_mux_clks));
+ samsung_clk_register_div(ctx, s3c6400_div_clks,
+ ARRAY_SIZE(s3c6400_div_clks));
+ samsung_clk_register_gate(ctx, s3c6400_gate_clks,
+ ARRAY_SIZE(s3c6400_gate_clks));
+ samsung_clk_register_alias(ctx, s3c6400_clock_aliases,
+ ARRAY_SIZE(s3c6400_clock_aliases));
+ } else {
+ samsung_clk_register_mux(ctx, s3c6410_mux_clks,
+ ARRAY_SIZE(s3c6410_mux_clks));
+ samsung_clk_register_div(ctx, s3c6410_div_clks,
+ ARRAY_SIZE(s3c6410_div_clks));
+ samsung_clk_register_gate(ctx, s3c6410_gate_clks,
+ ARRAY_SIZE(s3c6410_gate_clks));
+ samsung_clk_register_alias(ctx, s3c6410_clock_aliases,
+ ARRAY_SIZE(s3c6410_clock_aliases));
+ }
+
+ samsung_clk_register_alias(ctx, s3c64xx_clock_aliases,
+ ARRAY_SIZE(s3c64xx_clock_aliases));
+ s3c64xx_clk_sleep_init();
+
+ pr_info("%s clocks: apll = %lu, mpll = %lu\n"
+ "\tepll = %lu, arm_clk = %lu\n",
+ is_s3c6400 ? "S3C6400" : "S3C6410",
+ _get_rate("fout_apll"), _get_rate("fout_mpll"),
+ _get_rate("fout_epll"), _get_rate("armclk"));
+}
+
+static void __init s3c6400_clk_init(struct device_node *np)
+{
+ s3c64xx_clk_init(np, 0, 0, true, NULL);
+}
+CLK_OF_DECLARE(s3c6400_clk, "samsung,s3c6400-clock", s3c6400_clk_init);
+
+static void __init s3c6410_clk_init(struct device_node *np)
+{
+ s3c64xx_clk_init(np, 0, 0, false, NULL);
+}
+CLK_OF_DECLARE(s3c6410_clk, "samsung,s3c6410-clock", s3c6410_clk_init);
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 00000000000..49629c71c9e
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This file includes utility functions to register clocks to common
+ * clock framework for Samsung platforms.
+*/
+
+#include <linux/syscore_ops.h>
+#include "clk.h"
+
+void samsung_clk_save(void __iomem *base,
+ struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs)
+{
+ for (; num_regs > 0; --num_regs, ++rd)
+ rd->value = readl(base + rd->offset);
+}
+
+void samsung_clk_restore(void __iomem *base,
+ const struct samsung_clk_reg_dump *rd,
+ unsigned int num_regs)
+{
+ for (; num_regs > 0; --num_regs, ++rd)
+ writel(rd->value, base + rd->offset);
+}
+
+struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(
+ const unsigned long *rdump,
+ unsigned long nr_rdump)
+{
+ struct samsung_clk_reg_dump *rd;
+ unsigned int i;
+
+ rd = kcalloc(nr_rdump, sizeof(*rd), GFP_KERNEL);
+ if (!rd)
+ return NULL;
+
+ for (i = 0; i < nr_rdump; ++i)
+ rd[i].offset = rdump[i];
+
+ return rd;
+}
+
+/* setup the essentials required to support clock lookup using ccf */
+struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np,
+ void __iomem *base, unsigned long nr_clks)
+{
+ struct samsung_clk_provider *ctx;
+ struct clk **clk_table;
+ int ret;
+ int i;
+
+ 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 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;
+}
+
+/* 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)
+{
+ 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_clk_provider *ctx,
+ struct samsung_clock_alias *list,
+ unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ if (!ctx->clk_data.clks) {
+ pr_err("%s: clock table missing\n", __func__);
+ return;
+ }
+
+ for (idx = 0; idx < nr_clk; idx++, list++) {
+ if (!list->id) {
+ pr_err("%s: clock id missing for index %d\n", __func__,
+ idx);
+ continue;
+ }
+
+ clk = ctx->clk_data.clks[list->id];
+ if (!clk) {
+ pr_err("%s: failed to find clock %d\n", __func__,
+ list->id);
+ continue;
+ }
+
+ ret = clk_register_clkdev(clk, list->alias, list->dev_name);
+ if (ret)
+ pr_err("%s: failed to register lookup %s\n",
+ __func__, list->alias);
+ }
+}
+
+/* register a list of fixed clocks */
+void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx,
+ struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, list++) {
+ clk = clk_register_fixed_rate(NULL, list->name,
+ list->parent_name, list->flags, list->fixed_rate);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ list->name);
+ continue;
+ }
+
+ samsung_clk_add_lookup(ctx, clk, list->id);
+
+ /*
+ * Unconditionally add a clock lookup for the fixed rate clocks.
+ * There are not many of these on any of Samsung platforms.
+ */
+ ret = clk_register_clkdev(clk, list->name, NULL);
+ if (ret)
+ pr_err("%s: failed to register clock lookup for %s",
+ __func__, list->name);
+ }
+}
+
+/* register a list of fixed factor clocks */
+void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx,
+ struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx;
+
+ for (idx = 0; idx < nr_clk; idx++, list++) {
+ clk = clk_register_fixed_factor(NULL, list->name,
+ list->parent_name, list->flags, list->mult, list->div);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n", __func__,
+ list->name);
+ continue;
+ }
+
+ samsung_clk_add_lookup(ctx, clk, list->id);
+ }
+}
+
+/* register a list of mux clocks */
+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,
+ 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(ctx, clk, list->id);
+
+ /* register a clock lookup only if a clock alias is specified */
+ if (list->alias) {
+ ret = clk_register_clkdev(clk, list->alias,
+ list->dev_name);
+ if (ret)
+ pr_err("%s: failed to register lookup %s\n",
+ __func__, list->alias);
+ }
+ }
+}
+
+/* register a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_clk_provider *ctx,
+ struct samsung_div_clock *list,
+ unsigned int nr_clk)
+{
+ struct clk *clk;
+ unsigned int idx, ret;
+
+ for (idx = 0; idx < nr_clk; idx++, list++) {
+ if (list->table)
+ clk = clk_register_divider_table(NULL, list->name,
+ list->parent_name, list->flags,
+ 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,
+ 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(ctx, clk, list->id);
+
+ /* register a clock lookup only if a clock alias is specified */
+ if (list->alias) {
+ ret = clk_register_clkdev(clk, list->alias,
+ list->dev_name);
+ if (ret)
+ pr_err("%s: failed to register lookup %s\n",
+ __func__, list->alias);
+ }
+ }
+}
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_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, 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);
+ continue;
+ }
+
+ /* register a clock lookup only if a clock alias is specified */
+ if (list->alias) {
+ ret = clk_register_clkdev(clk, list->alias,
+ list->dev_name);
+ if (ret)
+ pr_err("%s: failed to register lookup %s\n",
+ __func__, list->alias);
+ }
+
+ samsung_clk_add_lookup(ctx, clk, list->id);
+ }
+}
+
+/*
+ * obtain the clock speed of all external fixed clock sources from device
+ * tree and register it
+ */
+#ifdef CONFIG_OF
+void __init samsung_clk_of_register_fixed_ext(struct samsung_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 *clk_np;
+ u32 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[(unsigned long)match->data].fixed_rate = freq;
+ }
+ samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk);
+}
+#endif
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+ struct clk *clk;
+
+ clk = __clk_lookup(clk_name);
+ if (!clk) {
+ pr_err("%s: could not find clock %s\n", __func__, clk_name);
+ return 0;
+ }
+
+ return clk_get_rate(clk);
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 00000000000..9693b80d924
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_H
+#define __SAMSUNG_CLK_H
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include "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.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_clock_alias {
+ unsigned int id;
+ const char *dev_name;
+ const char *alias;
+};
+
+#define ALIAS(_id, dname, a) \
+ { \
+ .id = _id, \
+ .dev_name = dname, \
+ .alias = a, \
+ }
+
+#define MHZ (1000 * 1000)
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-rate clock.
+ * @parent_name: optional parent clock name.
+ * @flags: optional fixed-rate clock flags.
+ * @fixed-rate: fixed clock rate of this clock.
+ */
+struct samsung_fixed_rate_clock {
+ unsigned int id;
+ char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long fixed_rate;
+};
+
+#define FRATE(_id, cname, pname, f, frate) \
+ { \
+ .id = _id, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .fixed_rate = frate, \
+ }
+
+/*
+ * struct samsung_fixed_factor_clock: information about fixed-factor clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-factor clock.
+ * @parent_name: parent clock name.
+ * @mult: fixed multiplication factor.
+ * @div: fixed division factor.
+ * @flags: optional fixed-factor clock flags.
+ */
+struct samsung_fixed_factor_clock {
+ unsigned int id;
+ char *name;
+ const char *parent_name;
+ unsigned long mult;
+ unsigned long div;
+ unsigned long flags;
+};
+
+#define FFACTOR(_id, cname, pname, m, d, f) \
+ { \
+ .id = _id, \
+ .name = cname, \
+ .parent_name = pname, \
+ .mult = m, \
+ .div = d, \
+ .flags = f, \
+ }
+
+/**
+ * struct samsung_mux_clock: information about mux clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this mux clock.
+ * @parent_names: array of pointer to parent clock names.
+ * @num_parents: number of parents listed in @parent_names.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the mux.
+ * @shift: starting bit location of the mux control bit-field in @reg.
+ * @width: width of the mux control bit-field in @reg.
+ * @mux_flags: flags for mux-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_mux_clock {
+ unsigned int id;
+ const char *dev_name;
+ const char *name;
+ const char **parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long offset;
+ u8 shift;
+ u8 width;
+ u8 mux_flags;
+ const char *alias;
+};
+
+#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a) \
+ { \
+ .id = _id, \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_names = pnames, \
+ .num_parents = ARRAY_SIZE(pnames), \
+ .flags = (f) | CLK_SET_RATE_NO_REPARENT, \
+ .offset = o, \
+ .shift = s, \
+ .width = w, \
+ .mux_flags = mf, \
+ .alias = a, \
+ }
+
+#define MUX(_id, cname, pnames, o, s, w) \
+ __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
+
+#define MUX_A(_id, cname, pnames, o, s, w, a) \
+ __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
+
+#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
+ __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
+
+#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \
+ __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a)
+
+/**
+ * @id: platform specific id of the clock.
+ * struct samsung_div_clock: information about div clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this div clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the div.
+ * @shift: starting bit location of the div control bit-field in @reg.
+ * @div_flags: flags for div-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_div_clock {
+ unsigned int id;
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long offset;
+ u8 shift;
+ u8 width;
+ u8 div_flags;
+ const char *alias;
+ struct clk_div_table *table;
+};
+
+#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t) \
+ { \
+ .id = _id, \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .offset = o, \
+ .shift = s, \
+ .width = w, \
+ .div_flags = df, \
+ .alias = a, \
+ .table = t, \
+ }
+
+#define DIV(_id, cname, pname, o, s, w) \
+ __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
+
+#define DIV_A(_id, cname, pname, o, s, w, a) \
+ __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
+
+#define DIV_F(_id, cname, pname, o, s, w, f, df) \
+ __DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
+
+#define DIV_T(_id, cname, pname, o, s, w, t) \
+ __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
+
+/**
+ * struct samsung_gate_clock: information about gate clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this gate clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the gate.
+ * @bit_idx: bit index of the gate control bit-field in @reg.
+ * @gate_flags: flags for gate-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_gate_clock {
+ unsigned int id;
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long offset;
+ u8 bit_idx;
+ u8 gate_flags;
+ const char *alias;
+};
+
+#define __GATE(_id, dname, cname, pname, o, b, f, gf, a) \
+ { \
+ .id = _id, \
+ .dev_name = dname, \
+ .name = cname, \
+ .parent_name = pname, \
+ .flags = f, \
+ .offset = o, \
+ .bit_idx = b, \
+ .gate_flags = gf, \
+ .alias = a, \
+ }
+
+#define GATE(_id, cname, pname, o, b, f, gf) \
+ __GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_A(_id, cname, pname, o, b, f, gf, a) \
+ __GATE(_id, NULL, cname, pname, o, b, f, gf, a)
+
+#define GATE_D(_id, dname, cname, pname, o, b, f, gf) \
+ __GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a) \
+ __GATE(_id, dname, cname, pname, o, b, f, gf, a)
+
+#define PNAME(x) static const char *x[] __initdata
+
+/**
+ * struct samsung_clk_reg_dump: register dump of clock controller registers.
+ * @offset: clock register offset from the controller base address.
+ * @value: the value to be register at offset.
+ */
+struct samsung_clk_reg_dump {
+ u32 offset;
+ u32 value;
+};
+
+/**
+ * struct samsung_pll_clock: information about pll clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this pll clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @con_offset: offset of the register for configuring the PLL.
+ * @lock_offset: offset of the register for locking the PLL.
+ * @type: Type of PLL to be registered.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_pll_clock {
+ unsigned int id;
+ const char *dev_name;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ int con_offset;
+ int lock_offset;
+ enum samsung_pll_type type;
+ const struct samsung_pll_rate_table *rate_table;
+ const char *alias;
+};
+
+#define __PLL(_typ, _id, _dname, _name, _pname, _flags, _lock, _con, \
+ _rtable, _alias) \
+ { \
+ .id = _id, \
+ .type = _typ, \
+ .dev_name = _dname, \
+ .name = _name, \
+ .parent_name = _pname, \
+ .flags = CLK_GET_RATE_NOCACHE, \
+ .con_offset = _con, \
+ .lock_offset = _lock, \
+ .rate_table = _rtable, \
+ .alias = _alias, \
+ }
+
+#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \
+ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
+ _lock, _con, _rtable, _name)
+
+#define PLL_A(_typ, _id, _name, _pname, _lock, _con, _alias, _rtable) \
+ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
+ _lock, _con, _rtable, _alias)
+
+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_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 samsung_clk_provider *ctx,
+ struct clk *clk, unsigned int id);
+
+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_clk_provider *ctx,
+ struct samsung_fixed_rate_clock *clk_list,
+ unsigned int nr_clk);
+extern void __init samsung_clk_register_fixed_factor(
+ 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);
+extern void samsung_clk_restore(void __iomem *base,
+ 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);
+
+#endif /* __SAMSUNG_CLK_H */