summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-07-26 14:01:10 +0400
committerArnd Bergmann <arnd@arndb.de>2014-07-26 14:01:27 +0400
commit96bda115ec552ff75319f85828f6c333d101b401 (patch)
treee30895f65413fdf8fd91c026faad1a3fb54b0653 /drivers
parent8e5655cd4f7e140ceb24705f913406e9f56b7d54 (diff)
parentf1ff47454bb2fe0d5644f981679d1bea532816fd (diff)
downloadlinux-96bda115ec552ff75319f85828f6c333d101b401.tar.xz
Merge tag 's5pv210-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/soc
Merge "Samsung S5PV210 DT support for v3.17" from Kukjin Kim: - support common clock framework for s5pv210 clock - add generic PHY driver on s5pv210 to support it via DT - add dt support for s5pv210-goni, smdkc110, smdkv210 and torbreck boards - remove board files from mach-s5pv210 and unused codes - enable multiplatform for s5pv210 * tag 's5pv210-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung: clk: samsung: s5pv210: Remove legacy board support ARM: SAMSUNG: Remove remaining legacy code gpio: samsung: Remove legacy support of S5PV210 ARM: S5PV210: Enable multi-platform build support cpufreq: s5pv210: Make the driver multiplatform aware ARM: S5PV210: Register cpufreq platform device ARM: S5PV210: move debug-macro.S into the common space ARM: S5PV210: Untie PM support from legacy code ARM: S5PV210: Remove support for board files ARM: dts: Add Device tree for s5pc110/s5pv210 boards ARM: dts: Add Device tree for s5pv210 SoC ARM: S5PV210: Add board file for boot using Device Tree phy: Add support for S5PV210 to the Exynos USB 2.0 PHY driver clk: samsung: Add S5PV210 Audio Subsystem clock driver ARM: SAMSUNG: Remove legacy clock code serial: samsung: Remove support for legacy clock code cpufreq: s3c24xx: Remove some dead code ARM: S5PV210: Migrate clock handling to Common Clock Framework clk: samsung: Add clock driver for S5PV210 and compatible SoCs Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-s5pv210-audss.c241
-rw-r--r--drivers/clk/samsung/clk-s5pv210.c856
-rw-r--r--drivers/cpufreq/s3c2410-cpufreq.c2
-rw-r--r--drivers/cpufreq/s3c2412-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c2440-cpufreq.c3
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c1
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c131
-rw-r--r--drivers/gpio/gpio-samsung.c240
-rw-r--r--drivers/phy/Kconfig10
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-s5pv210-usb2.c187
-rw-r--r--drivers/phy/phy-samsung-usb2.c6
-rw-r--r--drivers/phy/phy-samsung-usb2.h1
-rw-r--r--drivers/tty/serial/samsung.c4
15 files changed, 1425 insertions, 262 deletions
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 69e81773164e..9f256a4ba775 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o
obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o
obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o
obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o
+obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o
diff --git a/drivers/clk/samsung/clk-s5pv210-audss.c b/drivers/clk/samsung/clk-s5pv210-audss.c
new file mode 100644
index 000000000000..a8053b4aca56
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210-audss.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014 Tomasz Figa <t.figa@samsung.com>
+ *
+ * Based on Exynos Audio Subsystem Clock Controller driver:
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Padmavathi Venna <padma.v@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for Audio Subsystem Clock Controller of S5PV210-compatible SoCs.
+*/
+
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/s5pv210-audss.h>
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+static struct clk_onecell_data clk_data;
+
+#define ASS_CLK_SRC 0x0
+#define ASS_CLK_DIV 0x4
+#define ASS_CLK_GATE 0x8
+
+#ifdef CONFIG_PM_SLEEP
+static unsigned long reg_save[][2] = {
+ {ASS_CLK_SRC, 0},
+ {ASS_CLK_DIV, 0},
+ {ASS_CLK_GATE, 0},
+};
+
+static int s5pv210_audss_clk_suspend(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ reg_save[i][1] = readl(reg_base + reg_save[i][0]);
+
+ return 0;
+}
+
+static void s5pv210_audss_clk_resume(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(reg_save); i++)
+ writel(reg_save[i][1], reg_base + reg_save[i][0]);
+}
+
+static struct syscore_ops s5pv210_audss_clk_syscore_ops = {
+ .suspend = s5pv210_audss_clk_suspend,
+ .resume = s5pv210_audss_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+/* register s5pv210_audss clocks */
+static int s5pv210_audss_clk_probe(struct platform_device *pdev)
+{
+ int i, ret = 0;
+ struct resource *res;
+ const char *mout_audss_p[2];
+ const char *mout_i2s_p[3];
+ const char *hclk_p;
+ struct clk *hclk, *pll_ref, *pll_in, *cdclk, *sclk_audio;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg_base)) {
+ dev_err(&pdev->dev, "failed to map audss registers\n");
+ return PTR_ERR(reg_base);
+ }
+
+ clk_table = devm_kzalloc(&pdev->dev,
+ sizeof(struct clk *) * AUDSS_MAX_CLKS,
+ GFP_KERNEL);
+ if (!clk_table)
+ return -ENOMEM;
+
+ clk_data.clks = clk_table;
+ clk_data.clk_num = AUDSS_MAX_CLKS;
+
+ hclk = devm_clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk clock\n");
+ return PTR_ERR(hclk);
+ }
+
+ pll_in = devm_clk_get(&pdev->dev, "fout_epll");
+ if (IS_ERR(pll_in)) {
+ dev_err(&pdev->dev, "failed to get fout_epll clock\n");
+ return PTR_ERR(pll_in);
+ }
+
+ sclk_audio = devm_clk_get(&pdev->dev, "sclk_audio0");
+ if (IS_ERR(sclk_audio)) {
+ dev_err(&pdev->dev, "failed to get sclk_audio0 clock\n");
+ return PTR_ERR(sclk_audio);
+ }
+
+ /* iiscdclk0 is an optional external I2S codec clock */
+ cdclk = devm_clk_get(&pdev->dev, "iiscdclk0");
+ pll_ref = devm_clk_get(&pdev->dev, "xxti");
+
+ if (!IS_ERR(pll_ref))
+ mout_audss_p[0] = __clk_get_name(pll_ref);
+ else
+ mout_audss_p[0] = "xxti";
+ mout_audss_p[1] = __clk_get_name(pll_in);
+ clk_table[CLK_MOUT_AUDSS] = clk_register_mux(NULL, "mout_audss",
+ mout_audss_p, ARRAY_SIZE(mout_audss_p),
+ CLK_SET_RATE_NO_REPARENT,
+ reg_base + ASS_CLK_SRC, 0, 1, 0, &lock);
+
+ mout_i2s_p[0] = "mout_audss";
+ if (!IS_ERR(cdclk))
+ mout_i2s_p[1] = __clk_get_name(cdclk);
+ else
+ mout_i2s_p[1] = "iiscdclk0";
+ mout_i2s_p[2] = __clk_get_name(sclk_audio);
+ clk_table[CLK_MOUT_I2S_A] = clk_register_mux(NULL, "mout_i2s_audss",
+ mout_i2s_p, ARRAY_SIZE(mout_i2s_p),
+ CLK_SET_RATE_NO_REPARENT,
+ reg_base + ASS_CLK_SRC, 2, 2, 0, &lock);
+
+ clk_table[CLK_DOUT_AUD_BUS] = clk_register_divider(NULL,
+ "dout_aud_bus", "mout_audss", 0,
+ reg_base + ASS_CLK_DIV, 0, 4, 0, &lock);
+ clk_table[CLK_DOUT_I2S_A] = clk_register_divider(NULL, "dout_i2s_audss",
+ "mout_i2s_audss", 0, reg_base + ASS_CLK_DIV,
+ 4, 4, 0, &lock);
+
+ clk_table[CLK_I2S] = clk_register_gate(NULL, "i2s_audss",
+ "dout_i2s_audss", CLK_SET_RATE_PARENT,
+ reg_base + ASS_CLK_GATE, 6, 0, &lock);
+
+ hclk_p = __clk_get_name(hclk);
+
+ clk_table[CLK_HCLK_I2S] = clk_register_gate(NULL, "hclk_i2s_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 5, 0, &lock);
+ clk_table[CLK_HCLK_UART] = clk_register_gate(NULL, "hclk_uart_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 4, 0, &lock);
+ clk_table[CLK_HCLK_HWA] = clk_register_gate(NULL, "hclk_hwa_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 3, 0, &lock);
+ clk_table[CLK_HCLK_DMA] = clk_register_gate(NULL, "hclk_dma_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 2, 0, &lock);
+ clk_table[CLK_HCLK_BUF] = clk_register_gate(NULL, "hclk_buf_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 1, 0, &lock);
+ clk_table[CLK_HCLK_RP] = clk_register_gate(NULL, "hclk_rp_audss",
+ hclk_p, CLK_IGNORE_UNUSED,
+ reg_base + ASS_CLK_GATE, 0, 0, &lock);
+
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (IS_ERR(clk_table[i])) {
+ dev_err(&pdev->dev, "failed to register clock %d\n", i);
+ ret = PTR_ERR(clk_table[i]);
+ goto unregister;
+ }
+ }
+
+ ret = of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get,
+ &clk_data);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add clock provider\n");
+ goto unregister;
+ }
+
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&s5pv210_audss_clk_syscore_ops);
+#endif
+
+ return 0;
+
+unregister:
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister(clk_table[i]);
+ }
+
+ return ret;
+}
+
+static int s5pv210_audss_clk_remove(struct platform_device *pdev)
+{
+ int i;
+
+ of_clk_del_provider(pdev->dev.of_node);
+
+ for (i = 0; i < clk_data.clk_num; i++) {
+ if (!IS_ERR(clk_table[i]))
+ clk_unregister(clk_table[i]);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id s5pv210_audss_clk_of_match[] = {
+ { .compatible = "samsung,s5pv210-audss-clock", },
+ {},
+};
+
+static struct platform_driver s5pv210_audss_clk_driver = {
+ .driver = {
+ .name = "s5pv210-audss-clk",
+ .owner = THIS_MODULE,
+ .of_match_table = s5pv210_audss_clk_of_match,
+ },
+ .probe = s5pv210_audss_clk_probe,
+ .remove = s5pv210_audss_clk_remove,
+};
+
+static int __init s5pv210_audss_clk_init(void)
+{
+ return platform_driver_register(&s5pv210_audss_clk_driver);
+}
+core_initcall(s5pv210_audss_clk_init);
+
+static void __exit s5pv210_audss_clk_exit(void)
+{
+ platform_driver_unregister(&s5pv210_audss_clk_driver);
+}
+module_exit(s5pv210_audss_clk_exit);
+
+MODULE_AUTHOR("Tomasz Figa <t.figa@samsung.com>");
+MODULE_DESCRIPTION("S5PV210 Audio Subsystem Clock Controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:s5pv210-audss-clk");
diff --git a/drivers/clk/samsung/clk-s5pv210.c b/drivers/clk/samsung/clk-s5pv210.c
new file mode 100644
index 000000000000..d270a2084644
--- /dev/null
+++ b/drivers/clk/samsung/clk-s5pv210.c
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Mateusz Krawczuk <m.krawczuk@partner.samsung.com>
+ *
+ * Based on clock drivers for S3C64xx and Exynos4 SoCs.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for all S5PC110/S5PV210 SoCs.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#include <dt-bindings/clock/s5pv210.h>
+
+/* S5PC110/S5PV210 clock controller register offsets */
+#define APLL_LOCK 0x0000
+#define MPLL_LOCK 0x0008
+#define EPLL_LOCK 0x0010
+#define VPLL_LOCK 0x0020
+#define APLL_CON0 0x0100
+#define APLL_CON1 0x0104
+#define MPLL_CON 0x0108
+#define EPLL_CON0 0x0110
+#define EPLL_CON1 0x0114
+#define VPLL_CON 0x0120
+#define CLK_SRC0 0x0200
+#define CLK_SRC1 0x0204
+#define CLK_SRC2 0x0208
+#define CLK_SRC3 0x020c
+#define CLK_SRC4 0x0210
+#define CLK_SRC5 0x0214
+#define CLK_SRC6 0x0218
+#define CLK_SRC_MASK0 0x0280
+#define CLK_SRC_MASK1 0x0284
+#define CLK_DIV0 0x0300
+#define CLK_DIV1 0x0304
+#define CLK_DIV2 0x0308
+#define CLK_DIV3 0x030c
+#define CLK_DIV4 0x0310
+#define CLK_DIV5 0x0314
+#define CLK_DIV6 0x0318
+#define CLK_DIV7 0x031c
+#define CLK_GATE_MAIN0 0x0400
+#define CLK_GATE_MAIN1 0x0404
+#define CLK_GATE_MAIN2 0x0408
+#define CLK_GATE_PERI0 0x0420
+#define CLK_GATE_PERI1 0x0424
+#define CLK_GATE_SCLK0 0x0440
+#define CLK_GATE_SCLK1 0x0444
+#define CLK_GATE_IP0 0x0460
+#define CLK_GATE_IP1 0x0464
+#define CLK_GATE_IP2 0x0468
+#define CLK_GATE_IP3 0x046c
+#define CLK_GATE_IP4 0x0470
+#define CLK_GATE_BLOCK 0x0480
+#define CLK_GATE_IP5 0x0484
+#define CLK_OUT 0x0500
+#define MISC 0xe000
+#define OM_STAT 0xe100
+
+/* IDs of PLLs available on S5PV210/S5P6442 SoCs */
+enum {
+ apll,
+ mpll,
+ epll,
+ vpll,
+};
+
+/* IDs of external clocks (used for legacy boards) */
+enum {
+ xxti,
+ xusbxti,
+};
+
+static void __iomem *reg_base;
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *s5pv210_clk_dump;
+
+/* List of registers that need to be preserved across suspend/resume. */
+static unsigned long s5pv210_clk_regs[] __initdata = {
+ CLK_SRC0,
+ CLK_SRC1,
+ CLK_SRC2,
+ CLK_SRC3,
+ CLK_SRC4,
+ CLK_SRC5,
+ CLK_SRC6,
+ CLK_SRC_MASK0,
+ CLK_SRC_MASK1,
+ CLK_DIV0,
+ CLK_DIV1,
+ CLK_DIV2,
+ CLK_DIV3,
+ CLK_DIV4,
+ CLK_DIV5,
+ CLK_DIV6,
+ CLK_DIV7,
+ CLK_GATE_MAIN0,
+ CLK_GATE_MAIN1,
+ CLK_GATE_MAIN2,
+ CLK_GATE_PERI0,
+ CLK_GATE_PERI1,
+ CLK_GATE_SCLK0,
+ CLK_GATE_SCLK1,
+ CLK_GATE_IP0,
+ CLK_GATE_IP1,
+ CLK_GATE_IP2,
+ CLK_GATE_IP3,
+ CLK_GATE_IP4,
+ CLK_GATE_IP5,
+ CLK_GATE_BLOCK,
+ APLL_LOCK,
+ MPLL_LOCK,
+ EPLL_LOCK,
+ VPLL_LOCK,
+ APLL_CON0,
+ APLL_CON1,
+ MPLL_CON,
+ EPLL_CON0,
+ EPLL_CON1,
+ VPLL_CON,
+ CLK_OUT,
+};
+
+static int s5pv210_clk_suspend(void)
+{
+ samsung_clk_save(reg_base, s5pv210_clk_dump,
+ ARRAY_SIZE(s5pv210_clk_regs));
+ return 0;
+}
+
+static void s5pv210_clk_resume(void)
+{
+ samsung_clk_restore(reg_base, s5pv210_clk_dump,
+ ARRAY_SIZE(s5pv210_clk_regs));
+}
+
+static struct syscore_ops s5pv210_clk_syscore_ops = {
+ .suspend = s5pv210_clk_suspend,
+ .resume = s5pv210_clk_resume,
+};
+
+static void s5pv210_clk_sleep_init(void)
+{
+ s5pv210_clk_dump =
+ samsung_clk_alloc_reg_dump(s5pv210_clk_regs,
+ ARRAY_SIZE(s5pv210_clk_regs));
+ if (!s5pv210_clk_dump) {
+ pr_warn("%s: Failed to allocate sleep save data\n", __func__);
+ return;
+ }
+
+ register_syscore_ops(&s5pv210_clk_syscore_ops);
+}
+#else
+static inline void s5pv210_clk_sleep_init(void) { }
+#endif
+
+/* Mux parent lists. */
+static const char *fin_pll_p[] __initconst = {
+ "xxti",
+ "xusbxti"
+};
+
+static const char *mout_apll_p[] __initconst = {
+ "fin_pll",
+ "fout_apll"
+};
+
+static const char *mout_mpll_p[] __initconst = {
+ "fin_pll",
+ "fout_mpll"
+};
+
+static const char *mout_epll_p[] __initconst = {
+ "fin_pll",
+ "fout_epll"
+};
+
+static const char *mout_vpllsrc_p[] __initconst = {
+ "fin_pll",
+ "sclk_hdmi27m"
+};
+
+static const char *mout_vpll_p[] __initconst = {
+ "mout_vpllsrc",
+ "fout_vpll"
+};
+
+static const char *mout_group1_p[] __initconst = {
+ "dout_a2m",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll"
+};
+
+static const char *mout_group2_p[] __initconst = {
+ "xxti",
+ "xusbxti",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio0_p[] __initconst = {
+ "xxti",
+ "pcmcdclk0",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio1_p[] __initconst = {
+ "i2scdclk1",
+ "pcmcdclk1",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio2_p[] __initconst = {
+ "i2scdclk2",
+ "pcmcdclk2",
+ "sclk_hdmi27m",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_spdif_p[] __initconst = {
+ "dout_audio0",
+ "dout_audio1",
+ "dout_audio3",
+};
+
+static const char *mout_group3_p[] __initconst = {
+ "mout_apll",
+ "mout_mpll"
+};
+
+static const char *mout_group4_p[] __initconst = {
+ "mout_mpll",
+ "dout_a2m"
+};
+
+static const char *mout_flash_p[] __initconst = {
+ "dout_hclkd",
+ "dout_hclkp"
+};
+
+static const char *mout_dac_p[] __initconst = {
+ "mout_vpll",
+ "sclk_hdmiphy"
+};
+
+static const char *mout_hdmi_p[] __initconst = {
+ "sclk_hdmiphy",
+ "dout_tblk"
+};
+
+static const char *mout_mixer_p[] __initconst = {
+ "mout_dac",
+ "mout_hdmi"
+};
+
+static const char *mout_vpll_6442_p[] __initconst = {
+ "fin_pll",
+ "fout_vpll"
+};
+
+static const char *mout_mixer_6442_p[] __initconst = {
+ "mout_vpll",
+ "dout_mixer"
+};
+
+static const char *mout_d0sync_6442_p[] __initconst = {
+ "mout_dsys",
+ "div_apll"
+};
+
+static const char *mout_d1sync_6442_p[] __initconst = {
+ "mout_psys",
+ "div_apll"
+};
+
+static const char *mout_group2_6442_p[] __initconst = {
+ "fin_pll",
+ "none",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio0_6442_p[] __initconst = {
+ "fin_pll",
+ "pcmcdclk0",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+};
+
+static const char *mout_audio1_6442_p[] __initconst = {
+ "i2scdclk1",
+ "pcmcdclk1",
+ "none",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "mout_mpll",
+ "mout_epll",
+ "mout_vpll",
+ "fin_pll",
+};
+
+static const char *mout_clksel_p[] __initconst = {
+ "fout_apll_clkout",
+ "fout_mpll_clkout",
+ "fout_epll",
+ "fout_vpll",
+ "sclk_usbphy0",
+ "sclk_usbphy1",
+ "sclk_hdmiphy",
+ "rtc",
+ "rtc_tick",
+ "dout_hclkm",
+ "dout_pclkm",
+ "dout_hclkd",
+ "dout_pclkd",
+ "dout_hclkp",
+ "dout_pclkp",
+ "dout_apll_clkout",
+ "dout_hpm",
+ "xxti",
+ "xusbxti",
+ "div_dclk"
+};
+
+static const char *mout_clksel_6442_p[] __initconst = {
+ "fout_apll_clkout",
+ "fout_mpll_clkout",
+ "fout_epll",
+ "fout_vpll",
+ "sclk_usbphy0",
+ "none",
+ "none",
+ "rtc",
+ "rtc_tick",
+ "none",
+ "none",
+ "dout_hclkd",
+ "dout_pclkd",
+ "dout_hclkp",
+ "dout_pclkp",
+ "dout_apll_clkout",
+ "none",
+ "fin_pll",
+ "none",
+ "div_dclk"
+};
+
+static const char *mout_clkout_p[] __initconst = {
+ "dout_clkout",
+ "none",
+ "xxti",
+ "xusbxti"
+};
+
+/* Common fixed factor clocks. */
+static struct samsung_fixed_factor_clock ffactor_clks[] __initdata = {
+ FFACTOR(FOUT_APLL_CLKOUT, "fout_apll_clkout", "fout_apll", 1, 4, 0),
+ FFACTOR(FOUT_MPLL_CLKOUT, "fout_mpll_clkout", "fout_mpll", 1, 2, 0),
+ FFACTOR(DOUT_APLL_CLKOUT, "dout_apll_clkout", "dout_apll", 1, 4, 0),
+};
+
+/* PLL input mux (fin_pll), which needs to be registered before PLLs. */
+static struct samsung_mux_clock early_mux_clks[] __initdata = {
+ MUX_F(FIN_PLL, "fin_pll", fin_pll_p, OM_STAT, 0, 1,
+ CLK_MUX_READ_ONLY, 0),
+};
+
+/* Common clock muxes. */
+static struct samsung_mux_clock mux_clks[] __initdata = {
+ MUX(MOUT_FLASH, "mout_flash", mout_flash_p, CLK_SRC0, 28, 1),
+ MUX(MOUT_PSYS, "mout_psys", mout_group4_p, CLK_SRC0, 24, 1),
+ MUX(MOUT_DSYS, "mout_dsys", mout_group4_p, CLK_SRC0, 20, 1),
+ MUX(MOUT_MSYS, "mout_msys", mout_group3_p, CLK_SRC0, 16, 1),
+ MUX(MOUT_EPLL, "mout_epll", mout_epll_p, CLK_SRC0, 8, 1),
+ MUX(MOUT_MPLL, "mout_mpll", mout_mpll_p, CLK_SRC0, 4, 1),
+ MUX(MOUT_APLL, "mout_apll", mout_apll_p, CLK_SRC0, 0, 1),
+
+ MUX(MOUT_CLKOUT, "mout_clkout", mout_clkout_p, MISC, 8, 2),
+};
+
+/* S5PV210-specific clock muxes. */
+static struct samsung_mux_clock s5pv210_mux_clks[] __initdata = {
+ MUX(MOUT_VPLL, "mout_vpll", mout_vpll_p, CLK_SRC0, 12, 1),
+
+ MUX(MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, CLK_SRC1, 28, 1),
+ MUX(MOUT_CSIS, "mout_csis", mout_group2_p, CLK_SRC1, 24, 4),
+ MUX(MOUT_FIMD, "mout_fimd", mout_group2_p, CLK_SRC1, 20, 4),
+ MUX(MOUT_CAM1, "mout_cam1", mout_group2_p, CLK_SRC1, 16, 4),
+ MUX(MOUT_CAM0, "mout_cam0", mout_group2_p, CLK_SRC1, 12, 4),
+ MUX(MOUT_DAC, "mout_dac", mout_dac_p, CLK_SRC1, 8, 1),
+ MUX(MOUT_MIXER, "mout_mixer", mout_mixer_p, CLK_SRC1, 4, 1),
+ MUX(MOUT_HDMI, "mout_hdmi", mout_hdmi_p, CLK_SRC1, 0, 1),
+
+ MUX(MOUT_G2D, "mout_g2d", mout_group1_p, CLK_SRC2, 8, 2),
+ MUX(MOUT_MFC, "mout_mfc", mout_group1_p, CLK_SRC2, 4, 2),
+ MUX(MOUT_G3D, "mout_g3d", mout_group1_p, CLK_SRC2, 0, 2),
+
+ MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_p, CLK_SRC3, 20, 4),
+ MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_p, CLK_SRC3, 16, 4),
+ MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_p, CLK_SRC3, 12, 4),
+
+ MUX(MOUT_UART3, "mout_uart3", mout_group2_p, CLK_SRC4, 28, 4),
+ MUX(MOUT_UART2, "mout_uart2", mout_group2_p, CLK_SRC4, 24, 4),
+ MUX(MOUT_UART1, "mout_uart1", mout_group2_p, CLK_SRC4, 20, 4),
+ MUX(MOUT_UART0, "mout_uart0", mout_group2_p, CLK_SRC4, 16, 4),
+ MUX(MOUT_MMC3, "mout_mmc3", mout_group2_p, CLK_SRC4, 12, 4),
+ MUX(MOUT_MMC2, "mout_mmc2", mout_group2_p, CLK_SRC4, 8, 4),
+ MUX(MOUT_MMC1, "mout_mmc1", mout_group2_p, CLK_SRC4, 4, 4),
+ MUX(MOUT_MMC0, "mout_mmc0", mout_group2_p, CLK_SRC4, 0, 4),
+
+ MUX(MOUT_PWM, "mout_pwm", mout_group2_p, CLK_SRC5, 12, 4),
+ MUX(MOUT_SPI1, "mout_spi1", mout_group2_p, CLK_SRC5, 4, 4),
+ MUX(MOUT_SPI0, "mout_spi0", mout_group2_p, CLK_SRC5, 0, 4),
+
+ MUX(MOUT_DMC0, "mout_dmc0", mout_group1_p, CLK_SRC6, 24, 2),
+ MUX(MOUT_PWI, "mout_pwi", mout_group2_p, CLK_SRC6, 20, 4),
+ MUX(MOUT_HPM, "mout_hpm", mout_group3_p, CLK_SRC6, 16, 1),
+ MUX(MOUT_SPDIF, "mout_spdif", mout_spdif_p, CLK_SRC6, 12, 2),
+ MUX(MOUT_AUDIO2, "mout_audio2", mout_audio2_p, CLK_SRC6, 8, 4),
+ MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_p, CLK_SRC6, 4, 4),
+ MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_p, CLK_SRC6, 0, 4),
+
+ MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_p, CLK_OUT, 12, 5),
+};
+
+/* S5P6442-specific clock muxes. */
+static struct samsung_mux_clock s5p6442_mux_clks[] __initdata = {
+ MUX(MOUT_VPLL, "mout_vpll", mout_vpll_6442_p, CLK_SRC0, 12, 1),
+
+ MUX(MOUT_FIMD, "mout_fimd", mout_group2_6442_p, CLK_SRC1, 20, 4),
+ MUX(MOUT_CAM1, "mout_cam1", mout_group2_6442_p, CLK_SRC1, 16, 4),
+ MUX(MOUT_CAM0, "mout_cam0", mout_group2_6442_p, CLK_SRC1, 12, 4),
+ MUX(MOUT_MIXER, "mout_mixer", mout_mixer_6442_p, CLK_SRC1, 4, 1),
+
+ MUX(MOUT_D0SYNC, "mout_d0sync", mout_d0sync_6442_p, CLK_SRC2, 28, 1),
+ MUX(MOUT_D1SYNC, "mout_d1sync", mout_d1sync_6442_p, CLK_SRC2, 24, 1),
+
+ MUX(MOUT_FIMC2, "mout_fimc2", mout_group2_6442_p, CLK_SRC3, 20, 4),
+ MUX(MOUT_FIMC1, "mout_fimc1", mout_group2_6442_p, CLK_SRC3, 16, 4),
+ MUX(MOUT_FIMC0, "mout_fimc0", mout_group2_6442_p, CLK_SRC3, 12, 4),
+
+ MUX(MOUT_UART2, "mout_uart2", mout_group2_6442_p, CLK_SRC4, 24, 4),
+ MUX(MOUT_UART1, "mout_uart1", mout_group2_6442_p, CLK_SRC4, 20, 4),
+ MUX(MOUT_UART0, "mout_uart0", mout_group2_6442_p, CLK_SRC4, 16, 4),
+ MUX(MOUT_MMC2, "mout_mmc2", mout_group2_6442_p, CLK_SRC4, 8, 4),
+ MUX(MOUT_MMC1, "mout_mmc1", mout_group2_6442_p, CLK_SRC4, 4, 4),
+ MUX(MOUT_MMC0, "mout_mmc0", mout_group2_6442_p, CLK_SRC4, 0, 4),
+
+ MUX(MOUT_PWM, "mout_pwm", mout_group2_6442_p, CLK_SRC5, 12, 4),
+ MUX(MOUT_SPI0, "mout_spi0", mout_group2_6442_p, CLK_SRC5, 0, 4),
+
+ MUX(MOUT_AUDIO1, "mout_audio1", mout_audio1_6442_p, CLK_SRC6, 4, 4),
+ MUX(MOUT_AUDIO0, "mout_audio0", mout_audio0_6442_p, CLK_SRC6, 0, 4),
+
+ MUX(MOUT_CLKSEL, "mout_clksel", mout_clksel_6442_p, CLK_OUT, 12, 5),
+};
+
+/* S5PV210-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5pv210_frate_clks[] __initdata = {
+ FRATE(SCLK_HDMI27M, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+ FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+ FRATE(SCLK_USBPHY1, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* S5P6442-specific fixed rate clocks generated inside the SoC. */
+static struct samsung_fixed_rate_clock s5p6442_frate_clks[] __initdata = {
+ FRATE(SCLK_USBPHY0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 30000000),
+};
+
+/* Common clock dividers. */
+static struct samsung_div_clock div_clks[] __initdata = {
+ DIV(DOUT_PCLKP, "dout_pclkp", "dout_hclkp", CLK_DIV0, 28, 3),
+ DIV(DOUT_PCLKD, "dout_pclkd", "dout_hclkd", CLK_DIV0, 20, 3),
+ DIV(DOUT_A2M, "dout_a2m", "mout_apll", CLK_DIV0, 4, 3),
+ DIV(DOUT_APLL, "dout_apll", "mout_msys", CLK_DIV0, 0, 3),
+
+ DIV(DOUT_FIMD, "dout_fimd", "mout_fimd", CLK_DIV1, 20, 4),
+ DIV(DOUT_CAM1, "dout_cam1", "mout_cam1", CLK_DIV1, 16, 4),
+ DIV(DOUT_CAM0, "dout_cam0", "mout_cam0", CLK_DIV1, 12, 4),
+
+ DIV(DOUT_FIMC2, "dout_fimc2", "mout_fimc2", CLK_DIV3, 20, 4),
+ DIV(DOUT_FIMC1, "dout_fimc1", "mout_fimc1", CLK_DIV3, 16, 4),
+ DIV(DOUT_FIMC0, "dout_fimc0", "mout_fimc0", CLK_DIV3, 12, 4),
+
+ DIV(DOUT_UART2, "dout_uart2", "mout_uart2", CLK_DIV4, 24, 4),
+ DIV(DOUT_UART1, "dout_uart1", "mout_uart1", CLK_DIV4, 20, 4),
+ DIV(DOUT_UART0, "dout_uart0", "mout_uart0", CLK_DIV4, 16, 4),
+ DIV(DOUT_MMC2, "dout_mmc2", "mout_mmc2", CLK_DIV4, 8, 4),
+ DIV(DOUT_MMC1, "dout_mmc1", "mout_mmc1", CLK_DIV4, 4, 4),
+ DIV(DOUT_MMC0, "dout_mmc0", "mout_mmc0", CLK_DIV4, 0, 4),
+
+ DIV(DOUT_PWM, "dout_pwm", "mout_pwm", CLK_DIV5, 12, 4),
+ DIV(DOUT_SPI0, "dout_spi0", "mout_spi0", CLK_DIV5, 0, 4),
+
+ DIV(DOUT_FLASH, "dout_flash", "mout_flash", CLK_DIV6, 12, 3),
+ DIV(DOUT_AUDIO1, "dout_audio1", "mout_audio1", CLK_DIV6, 4, 4),
+ DIV(DOUT_AUDIO0, "dout_audio0", "mout_audio0", CLK_DIV6, 0, 4),
+
+ DIV(DOUT_CLKOUT, "dout_clkout", "mout_clksel", CLK_OUT, 20, 4),
+};
+
+/* S5PV210-specific clock dividers. */
+static struct samsung_div_clock s5pv210_div_clks[] __initdata = {
+ DIV(DOUT_HCLKP, "dout_hclkp", "mout_psys", CLK_DIV0, 24, 4),
+ DIV(DOUT_HCLKD, "dout_hclkd", "mout_dsys", CLK_DIV0, 16, 4),
+ DIV(DOUT_PCLKM, "dout_pclkm", "dout_hclkm", CLK_DIV0, 12, 3),
+ DIV(DOUT_HCLKM, "dout_hclkm", "dout_apll", CLK_DIV0, 8, 3),
+
+ DIV(DOUT_CSIS, "dout_csis", "mout_csis", CLK_DIV1, 28, 4),
+ DIV(DOUT_TBLK, "dout_tblk", "mout_vpll", CLK_DIV1, 0, 4),
+
+ DIV(DOUT_G2D, "dout_g2d", "mout_g2d", CLK_DIV2, 8, 4),
+ DIV(DOUT_MFC, "dout_mfc", "mout_mfc", CLK_DIV2, 4, 4),
+ DIV(DOUT_G3D, "dout_g3d", "mout_g3d", CLK_DIV2, 0, 4),
+
+ DIV(DOUT_UART3, "dout_uart3", "mout_uart3", CLK_DIV4, 28, 4),
+ DIV(DOUT_MMC3, "dout_mmc3", "mout_mmc3", CLK_DIV4, 12, 4),
+
+ DIV(DOUT_SPI1, "dout_spi1", "mout_spi1", CLK_DIV5, 4, 4),
+
+ DIV(DOUT_DMC0, "dout_dmc0", "mout_dmc0", CLK_DIV6, 28, 4),
+ DIV(DOUT_PWI, "dout_pwi", "mout_pwi", CLK_DIV6, 24, 4),
+ DIV(DOUT_HPM, "dout_hpm", "dout_copy", CLK_DIV6, 20, 3),
+ DIV(DOUT_COPY, "dout_copy", "mout_hpm", CLK_DIV6, 16, 3),
+ DIV(DOUT_AUDIO2, "dout_audio2", "mout_audio2", CLK_DIV6, 8, 4),
+
+ DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7),
+ DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7),
+};
+
+/* S5P6442-specific clock dividers. */
+static struct samsung_div_clock s5p6442_div_clks[] __initdata = {
+ DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4),
+ DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4),
+
+ DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4),
+};
+
+/* Common clock gates. */
+static struct samsung_gate_clock gate_clks[] __initdata = {
+ GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0),
+ GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0),
+ GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0),
+ GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0),
+ GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0),
+ GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0),
+
+ GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0),
+ GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0),
+ GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0),
+ GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0),
+ GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0),
+ GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0),
+ GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0),
+
+ GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
+ GATE(CLK_HSMMC1, "hsmmc1", "dout_hclkp", CLK_GATE_IP2, 17, 0, 0),
+ GATE(CLK_HSMMC0, "hsmmc0", "dout_hclkp", CLK_GATE_IP2, 16, 0, 0),
+ GATE(CLK_MODEMIF, "modemif", "dout_hclkp", CLK_GATE_IP2, 9, 0, 0),
+ GATE(CLK_SECSS, "secss", "dout_hclkp", CLK_GATE_IP2, 0, 0, 0),
+
+ GATE(CLK_PCM1, "pcm1", "dout_pclkp", CLK_GATE_IP3, 29, 0, 0),
+ GATE(CLK_PCM0, "pcm0", "dout_pclkp", CLK_GATE_IP3, 28, 0, 0),
+ GATE(CLK_TSADC, "tsadc", "dout_pclkp", CLK_GATE_IP3, 24, 0, 0),
+ GATE(CLK_PWM, "pwm", "dout_pclkp", CLK_GATE_IP3, 23, 0, 0),
+ GATE(CLK_WDT, "watchdog", "dout_pclkp", CLK_GATE_IP3, 22, 0, 0),
+ GATE(CLK_KEYIF, "keyif", "dout_pclkp", CLK_GATE_IP3, 21, 0, 0),
+ GATE(CLK_UART2, "uart2", "dout_pclkp", CLK_GATE_IP3, 19, 0, 0),
+ GATE(CLK_UART1, "uart1", "dout_pclkp", CLK_GATE_IP3, 18, 0, 0),
+ GATE(CLK_UART0, "uart0", "dout_pclkp", CLK_GATE_IP3, 17, 0, 0),
+ GATE(CLK_SYSTIMER, "systimer", "dout_pclkp", CLK_GATE_IP3, 16, 0, 0),
+ GATE(CLK_RTC, "rtc", "dout_pclkp", CLK_GATE_IP3, 15, 0, 0),
+ GATE(CLK_SPI0, "spi0", "dout_pclkp", CLK_GATE_IP3, 12, 0, 0),
+ GATE(CLK_I2C2, "i2c2", "dout_pclkp", CLK_GATE_IP3, 9, 0, 0),
+ GATE(CLK_I2C0, "i2c0", "dout_pclkp", CLK_GATE_IP3, 7, 0, 0),
+ GATE(CLK_I2S1, "i2s1", "dout_pclkp", CLK_GATE_IP3, 5, 0, 0),
+ GATE(CLK_I2S0, "i2s0", "dout_pclkp", CLK_GATE_IP3, 4, 0, 0),
+
+ GATE(CLK_SECKEY, "seckey", "dout_pclkp", CLK_GATE_IP4, 3, 0, 0),
+ GATE(CLK_CHIPID, "chipid", "dout_pclkp", CLK_GATE_IP4, 0, 0, 0),
+
+ GATE(SCLK_AUDIO1, "sclk_audio1", "dout_audio1", CLK_SRC_MASK0, 25,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_AUDIO0, "sclk_audio0", "dout_audio0", CLK_SRC_MASK0, 24,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_PWM, "sclk_pwm", "dout_pwm", CLK_SRC_MASK0, 19,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI0, "sclk_spi0", "dout_spi0", CLK_SRC_MASK0, 16,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART2, "sclk_uart2", "dout_uart2", CLK_SRC_MASK0, 14,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART1, "sclk_uart1", "dout_uart1", CLK_SRC_MASK0, 13,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART0, "sclk_uart0", "dout_uart0", CLK_SRC_MASK0, 12,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC2, "sclk_mmc2", "dout_mmc2", CLK_SRC_MASK0, 10,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC1, "sclk_mmc1", "dout_mmc1", CLK_SRC_MASK0, 9,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC0, "sclk_mmc0", "dout_mmc0", CLK_SRC_MASK0, 8,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMD, "sclk_fimd", "dout_fimd", CLK_SRC_MASK0, 5,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CAM1, "sclk_cam1", "dout_cam1", CLK_SRC_MASK0, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CAM0, "sclk_cam0", "dout_cam0", CLK_SRC_MASK0, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MIXER, "sclk_mixer", "mout_mixer", CLK_SRC_MASK0, 1,
+ CLK_SET_RATE_PARENT, 0),
+
+ GATE(SCLK_FIMC2, "sclk_fimc2", "dout_fimc2", CLK_SRC_MASK1, 4,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMC1, "sclk_fimc1", "dout_fimc1", CLK_SRC_MASK1, 3,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_FIMC0, "sclk_fimc0", "dout_fimc0", CLK_SRC_MASK1, 2,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5PV210-specific clock gates. */
+static struct samsung_gate_clock s5pv210_gate_clks[] __initdata = {
+ GATE(CLK_CSIS, "clk_csis", "dout_hclkd", CLK_GATE_IP0, 31, 0, 0),
+ GATE(CLK_MFC, "mfc", "dout_hclkm", CLK_GATE_IP0, 16, 0, 0),
+ GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+ GATE(CLK_G3D, "g3d", "dout_hclkm", CLK_GATE_IP0, 8, 0, 0),
+ GATE(CLK_IMEM, "imem", "dout_hclkm", CLK_GATE_IP0, 5, 0, 0),
+ GATE(CLK_PDMA1, "pdma1", "dout_hclkp", CLK_GATE_IP0, 4, 0, 0),
+
+ GATE(CLK_NFCON, "nfcon", "dout_hclkp", CLK_GATE_IP1, 28, 0, 0),
+ GATE(CLK_CFCON, "cfcon", "dout_hclkp", CLK_GATE_IP1, 25, 0, 0),
+ GATE(CLK_USB_HOST, "usb_host", "dout_hclkp", CLK_GATE_IP1, 17, 0, 0),
+ GATE(CLK_HDMI, "hdmi", "dout_hclkd", CLK_GATE_IP1, 11, 0, 0),
+ GATE(CLK_DSIM, "dsim", "dout_pclkd", CLK_GATE_IP1, 2, 0, 0),
+
+ GATE(CLK_TZIC3, "tzic3", "dout_hclkm", CLK_GATE_IP2, 31, 0, 0),
+ GATE(CLK_TZIC2, "tzic2", "dout_hclkm", CLK_GATE_IP2, 30, 0, 0),
+ GATE(CLK_TZIC1, "tzic1", "dout_hclkm", CLK_GATE_IP2, 29, 0, 0),
+ GATE(CLK_TZIC0, "tzic0", "dout_hclkm", CLK_GATE_IP2, 28, 0, 0),
+ GATE(CLK_TSI, "tsi", "dout_hclkd", CLK_GATE_IP2, 20, 0, 0),
+ GATE(CLK_HSMMC3, "hsmmc3", "dout_hclkp", CLK_GATE_IP2, 19, 0, 0),
+ GATE(CLK_JTAG, "jtag", "dout_hclkp", CLK_GATE_IP2, 11, 0, 0),
+ GATE(CLK_CORESIGHT, "coresight", "dout_pclkp", CLK_GATE_IP2, 8, 0, 0),
+ GATE(CLK_SDM, "sdm", "dout_pclkm", CLK_GATE_IP2, 1, 0, 0),
+
+ GATE(CLK_PCM2, "pcm2", "dout_pclkp", CLK_GATE_IP3, 30, 0, 0),
+ GATE(CLK_UART3, "uart3", "dout_pclkp", CLK_GATE_IP3, 20, 0, 0),
+ GATE(CLK_SPI1, "spi1", "dout_pclkp", CLK_GATE_IP3, 13, 0, 0),
+ GATE(CLK_I2C_HDMI_PHY, "i2c_hdmi_phy", "dout_pclkd",
+ CLK_GATE_IP3, 11, 0, 0),
+ GATE(CLK_I2C1, "i2c1", "dout_pclkd", CLK_GATE_IP3, 10, 0, 0),
+ GATE(CLK_I2S2, "i2s2", "dout_pclkp", CLK_GATE_IP3, 6, 0, 0),
+ GATE(CLK_AC97, "ac97", "dout_pclkp", CLK_GATE_IP3, 1, 0, 0),
+ GATE(CLK_SPDIF, "spdif", "dout_pclkp", CLK_GATE_IP3, 0, 0, 0),
+
+ GATE(CLK_TZPC3, "tzpc.3", "dout_pclkd", CLK_GATE_IP4, 8, 0, 0),
+ GATE(CLK_TZPC2, "tzpc.2", "dout_pclkd", CLK_GATE_IP4, 7, 0, 0),
+ GATE(CLK_TZPC1, "tzpc.1", "dout_pclkp", CLK_GATE_IP4, 6, 0, 0),
+ GATE(CLK_TZPC0, "tzpc.0", "dout_pclkm", CLK_GATE_IP4, 5, 0, 0),
+ GATE(CLK_IEM_APC, "iem_apc", "dout_pclkp", CLK_GATE_IP4, 2, 0, 0),
+ GATE(CLK_IEM_IEC, "iem_iec", "dout_pclkp", CLK_GATE_IP4, 1, 0, 0),
+
+ GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP5, 29, 0, 0),
+
+ GATE(SCLK_SPDIF, "sclk_spdif", "mout_spdif", CLK_SRC_MASK0, 27,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_AUDIO2, "sclk_audio2", "dout_audio2", CLK_SRC_MASK0, 26,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_SPI1, "sclk_spi1", "dout_spi1", CLK_SRC_MASK0, 17,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_UART3, "sclk_uart3", "dout_uart3", CLK_SRC_MASK0, 15,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_MMC3, "sclk_mmc3", "dout_mmc3", CLK_SRC_MASK0, 11,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_CSIS, "sclk_csis", "dout_csis", CLK_SRC_MASK0, 6,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_DAC, "sclk_dac", "mout_dac", CLK_SRC_MASK0, 2,
+ CLK_SET_RATE_PARENT, 0),
+ GATE(SCLK_HDMI, "sclk_hdmi", "mout_hdmi", CLK_SRC_MASK0, 0,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/* S5P6442-specific clock gates. */
+static struct samsung_gate_clock s5p6442_gate_clks[] __initdata = {
+ GATE(CLK_JPEG, "jpeg", "dout_hclkd", CLK_GATE_IP0, 28, 0, 0),
+ GATE(CLK_MFC, "mfc", "dout_hclkd", CLK_GATE_IP0, 16, 0, 0),
+ GATE(CLK_G2D, "g2d", "dout_hclkd", CLK_GATE_IP0, 12, 0, 0),
+ GATE(CLK_G3D, "g3d", "dout_hclkd", CLK_GATE_IP0, 8, 0, 0),
+ GATE(CLK_IMEM, "imem", "dout_hclkd", CLK_GATE_IP0, 5, 0, 0),
+
+ GATE(CLK_ETB, "etb", "dout_hclkd", CLK_GATE_IP1, 31, 0, 0),
+ GATE(CLK_ETM, "etm", "dout_hclkd", CLK_GATE_IP1, 30, 0, 0),
+
+ GATE(CLK_I2C1, "i2c1", "dout_pclkp", CLK_GATE_IP3, 8, 0, 0),
+
+ GATE(SCLK_DAC, "sclk_dac", "mout_vpll", CLK_SRC_MASK0, 2,
+ CLK_SET_RATE_PARENT, 0),
+};
+
+/*
+ * Clock aliases for legacy clkdev look-up.
+ * NOTE: Needed only to support legacy board files.
+ */
+static struct samsung_clock_alias s5pv210_aliases[] = {
+ ALIAS(DOUT_APLL, NULL, "armclk"),
+ ALIAS(DOUT_HCLKM, NULL, "hclk_msys"),
+ ALIAS(MOUT_DMC0, NULL, "sclk_dmc0"),
+};
+
+/* S5PV210-specific PLLs. */
+static struct samsung_pll_clock s5pv210_pll_clks[] __initdata = {
+ [apll] = PLL(pll_4508, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, NULL),
+ [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ [epll] = PLL(pll_4600, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+ [vpll] = PLL(pll_4502, FOUT_VPLL, "fout_vpll", "mout_vpllsrc",
+ VPLL_LOCK, VPLL_CON, NULL),
+};
+
+/* S5P6442-specific PLLs. */
+static struct samsung_pll_clock s5p6442_pll_clks[] __initdata = {
+ [apll] = PLL(pll_4502, FOUT_APLL, "fout_apll", "fin_pll",
+ APLL_LOCK, APLL_CON0, NULL),
+ [mpll] = PLL(pll_4502, FOUT_MPLL, "fout_mpll", "fin_pll",
+ MPLL_LOCK, MPLL_CON, NULL),
+ [epll] = PLL(pll_4500, FOUT_EPLL, "fout_epll", "fin_pll",
+ EPLL_LOCK, EPLL_CON0, NULL),
+ [vpll] = PLL(pll_4500, FOUT_VPLL, "fout_vpll", "fin_pll",
+ VPLL_LOCK, VPLL_CON, NULL),
+};
+
+static void __init __s5pv210_clk_init(struct device_node *np,
+ unsigned long xxti_f,
+ unsigned long xusbxti_f,
+ bool is_s5p6442)
+{
+ struct samsung_clk_provider *ctx;
+
+ ctx = samsung_clk_init(np, reg_base, NR_CLKS);
+ if (!ctx)
+ panic("%s: unable to allocate context.\n", __func__);
+
+ samsung_clk_register_mux(ctx, early_mux_clks,
+ ARRAY_SIZE(early_mux_clks));
+
+ if (is_s5p6442) {
+ samsung_clk_register_fixed_rate(ctx, s5p6442_frate_clks,
+ ARRAY_SIZE(s5p6442_frate_clks));
+ samsung_clk_register_pll(ctx, s5p6442_pll_clks,
+ ARRAY_SIZE(s5p6442_pll_clks), reg_base);
+ samsung_clk_register_mux(ctx, s5p6442_mux_clks,
+ ARRAY_SIZE(s5p6442_mux_clks));
+ samsung_clk_register_div(ctx, s5p6442_div_clks,
+ ARRAY_SIZE(s5p6442_div_clks));
+ samsung_clk_register_gate(ctx, s5p6442_gate_clks,
+ ARRAY_SIZE(s5p6442_gate_clks));
+ } else {
+ samsung_clk_register_fixed_rate(ctx, s5pv210_frate_clks,
+ ARRAY_SIZE(s5pv210_frate_clks));
+ samsung_clk_register_pll(ctx, s5pv210_pll_clks,
+ ARRAY_SIZE(s5pv210_pll_clks), reg_base);
+ samsung_clk_register_mux(ctx, s5pv210_mux_clks,
+ ARRAY_SIZE(s5pv210_mux_clks));
+ samsung_clk_register_div(ctx, s5pv210_div_clks,
+ ARRAY_SIZE(s5pv210_div_clks));
+ samsung_clk_register_gate(ctx, s5pv210_gate_clks,
+ ARRAY_SIZE(s5pv210_gate_clks));
+ }
+
+ samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks));
+ samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks));
+ samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks));
+
+ samsung_clk_register_fixed_factor(ctx, ffactor_clks,
+ ARRAY_SIZE(ffactor_clks));
+
+ samsung_clk_register_alias(ctx, s5pv210_aliases,
+ ARRAY_SIZE(s5pv210_aliases));
+
+ s5pv210_clk_sleep_init();
+
+ pr_info("%s clocks: mout_apll = %ld, mout_mpll = %ld\n"
+ "\tmout_epll = %ld, mout_vpll = %ld\n",
+ is_s5p6442 ? "S5P6442" : "S5PV210",
+ _get_rate("mout_apll"), _get_rate("mout_mpll"),
+ _get_rate("mout_epll"), _get_rate("mout_vpll"));
+}
+
+static void __init s5pv210_clk_dt_init(struct device_node *np)
+{
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ __s5pv210_clk_init(np, 0, 0, false);
+}
+CLK_OF_DECLARE(s5pv210_clk, "samsung,s5pv210-clock", s5pv210_clk_dt_init);
+
+static void __init s5p6442_clk_dt_init(struct device_node *np)
+{
+ reg_base = of_iomap(np, 0);
+ if (!reg_base)
+ panic("%s: failed to map registers\n", __func__);
+
+ __s5pv210_clk_init(np, 0, 0, true);
+}
+CLK_OF_DECLARE(s5p6442_clk, "samsung,s5p6442-clock", s5p6442_clk_dt_init);
diff --git a/drivers/cpufreq/s3c2410-cpufreq.c b/drivers/cpufreq/s3c2410-cpufreq.c
index cfa0dd8723ec..b8e5da8e188b 100644
--- a/drivers/cpufreq/s3c2410-cpufreq.c
+++ b/drivers/cpufreq/s3c2410-cpufreq.c
@@ -26,7 +26,6 @@
#include <mach/regs-clock.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
@@ -104,7 +103,6 @@ static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
.calc_iotiming = s3c2410_iotiming_calc,
.set_iotiming = s3c2410_iotiming_set,
.get_iotiming = s3c2410_iotiming_get,
- .resume_clocks = s3c2410_setup_clocks,
.set_fvco = s3c2410_set_fvco,
.set_refresh = s3c2410_cpufreq_setrefresh,
diff --git a/drivers/cpufreq/s3c2412-cpufreq.c b/drivers/cpufreq/s3c2412-cpufreq.c
index 4645b4898996..eb262133fef2 100644
--- a/drivers/cpufreq/s3c2412-cpufreq.c
+++ b/drivers/cpufreq/s3c2412-cpufreq.c
@@ -28,7 +28,6 @@
#include <mach/s3c2412.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
/* our clock resources. */
@@ -188,8 +187,6 @@ static struct s3c_cpufreq_info s3c2412_cpufreq_info = {
.set_iotiming = s3c2412_iotiming_set,
.get_iotiming = s3c2412_iotiming_get,
- .resume_clocks = s3c2412_setup_clocks,
-
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2412_iotiming_debugfs),
};
diff --git a/drivers/cpufreq/s3c2440-cpufreq.c b/drivers/cpufreq/s3c2440-cpufreq.c
index f84ed10755b5..0129f5c70a61 100644
--- a/drivers/cpufreq/s3c2440-cpufreq.c
+++ b/drivers/cpufreq/s3c2440-cpufreq.c
@@ -29,7 +29,6 @@
#include <plat/cpu.h>
#include <plat/cpu-freq-core.h>
-#include <plat/clock.h>
static struct clk *xtal;
static struct clk *fclk;
@@ -262,8 +261,6 @@ static struct s3c_cpufreq_info s3c2440_cpufreq_info = {
.calc_divs = s3c2440_cpufreq_calcdivs,
.calc_freqtable = s3c2440_cpufreq_calctable,
- .resume_clocks = s3c244x_setup_clocks,
-
.debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
};
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 227ebf7c1eea..d00f1cee4509 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -27,7 +27,6 @@
#include <asm/mach/map.h>
#include <plat/cpu.h>
-#include <plat/clock.h>
#include <plat/cpu-freq-core.h>
#include <mach/regs-clock.h>
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 19a10b89fef7..9a68225a757e 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -16,11 +16,70 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regulator/consumer.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
+static void __iomem *clk_base;
+static void __iomem *dmc_base[2];
+
+#define S5P_CLKREG(x) (clk_base + (x))
+
+#define S5P_APLL_LOCK S5P_CLKREG(0x00)
+#define S5P_APLL_CON S5P_CLKREG(0x100)
+#define S5P_CLK_SRC0 S5P_CLKREG(0x200)
+#define S5P_CLK_SRC2 S5P_CLKREG(0x208)
+#define S5P_CLK_DIV0 S5P_CLKREG(0x300)
+#define S5P_CLK_DIV2 S5P_CLKREG(0x308)
+#define S5P_CLK_DIV6 S5P_CLKREG(0x318)
+#define S5P_CLKDIV_STAT0 S5P_CLKREG(0x1000)
+#define S5P_CLKDIV_STAT1 S5P_CLKREG(0x1004)
+#define S5P_CLKMUX_STAT0 S5P_CLKREG(0x1100)
+#define S5P_CLKMUX_STAT1 S5P_CLKREG(0x1104)
+
+#define S5P_ARM_MCS_CON S5P_CLKREG(0x6100)
+
+/* CLKSRC0 */
+#define S5P_CLKSRC0_MUX200_SHIFT (16)
+#define S5P_CLKSRC0_MUX200_MASK (0x1 << S5P_CLKSRC0_MUX200_SHIFT)
+#define S5P_CLKSRC0_MUX166_MASK (0x1<<20)
+#define S5P_CLKSRC0_MUX133_MASK (0x1<<24)
+
+/* CLKSRC2 */
+#define S5P_CLKSRC2_G3D_SHIFT (0)
+#define S5P_CLKSRC2_G3D_MASK (0x3 << S5P_CLKSRC2_G3D_SHIFT)
+#define S5P_CLKSRC2_MFC_SHIFT (4)
+#define S5P_CLKSRC2_MFC_MASK (0x3 << S5P_CLKSRC2_MFC_SHIFT)
+
+/* CLKDIV0 */
+#define S5P_CLKDIV0_APLL_SHIFT (0)
+#define S5P_CLKDIV0_APLL_MASK (0x7 << S5P_CLKDIV0_APLL_SHIFT)
+#define S5P_CLKDIV0_A2M_SHIFT (4)
+#define S5P_CLKDIV0_A2M_MASK (0x7 << S5P_CLKDIV0_A2M_SHIFT)
+#define S5P_CLKDIV0_HCLK200_SHIFT (8)
+#define S5P_CLKDIV0_HCLK200_MASK (0x7 << S5P_CLKDIV0_HCLK200_SHIFT)
+#define S5P_CLKDIV0_PCLK100_SHIFT (12)
+#define S5P_CLKDIV0_PCLK100_MASK (0x7 << S5P_CLKDIV0_PCLK100_SHIFT)
+#define S5P_CLKDIV0_HCLK166_SHIFT (16)
+#define S5P_CLKDIV0_HCLK166_MASK (0xF << S5P_CLKDIV0_HCLK166_SHIFT)
+#define S5P_CLKDIV0_PCLK83_SHIFT (20)
+#define S5P_CLKDIV0_PCLK83_MASK (0x7 << S5P_CLKDIV0_PCLK83_SHIFT)
+#define S5P_CLKDIV0_HCLK133_SHIFT (24)
+#define S5P_CLKDIV0_HCLK133_MASK (0xF << S5P_CLKDIV0_HCLK133_SHIFT)
+#define S5P_CLKDIV0_PCLK66_SHIFT (28)
+#define S5P_CLKDIV0_PCLK66_MASK (0x7 << S5P_CLKDIV0_PCLK66_SHIFT)
+
+/* CLKDIV2 */
+#define S5P_CLKDIV2_G3D_SHIFT (0)
+#define S5P_CLKDIV2_G3D_MASK (0xF << S5P_CLKDIV2_G3D_SHIFT)
+#define S5P_CLKDIV2_MFC_SHIFT (4)
+#define S5P_CLKDIV2_MFC_MASK (0xF << S5P_CLKDIV2_MFC_SHIFT)
+
+/* CLKDIV6 */
+#define S5P_CLKDIV6_ONEDRAM_SHIFT (28)
+#define S5P_CLKDIV6_ONEDRAM_MASK (0xF << S5P_CLKDIV6_ONEDRAM_SHIFT)
static struct clk *dmc0_clk;
static struct clk *dmc1_clk;
@@ -142,9 +201,9 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
void __iomem *reg = NULL;
if (ch == DMC0) {
- reg = (S5P_VA_DMC0 + 0x30);
+ reg = (dmc_base[0] + 0x30);
} else if (ch == DMC1) {
- reg = (S5P_VA_DMC1 + 0x30);
+ reg = (dmc_base[1] + 0x30);
} else {
printk(KERN_ERR "Cannot find DMC port\n");
return;
@@ -472,7 +531,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
* check_mem_type : This driver only support LPDDR & LPDDR2.
* other memory type is not supported.
*/
- mem_type = check_mem_type(S5P_VA_DMC0);
+ mem_type = check_mem_type(dmc_base[0]);
if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
@@ -481,10 +540,10 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
}
/* Find current refresh counter and frequency each DMC */
- s5pv210_dram_conf[0].refresh = (__raw_readl(S5P_VA_DMC0 + 0x30) * 1000);
+ s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000);
s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
- s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
+ s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000);
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
policy->suspend_freq = SLEEP_FREQ;
@@ -527,8 +586,55 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = {
.notifier_call = s5pv210_cpufreq_reboot_notifier_event,
};
-static int __init s5pv210_cpufreq_init(void)
+static int s5pv210_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *np;
+ int id;
+
+ /*
+ * HACK: This is a temporary workaround to get access to clock
+ * and DMC controller registers directly and remove static mappings
+ * and dependencies on platform headers. It is necessary to enable
+ * S5PV210 multi-platform support and will be removed together with
+ * this whole driver as soon as S5PV210 gets migrated to use
+ * cpufreq-cpu0 driver.
+ */
+ np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock");
+ if (!np) {
+ pr_err("%s: failed to find clock controller DT node\n",
+ __func__);
+ return -ENODEV;
+ }
+
+ clk_base = of_iomap(np, 0);
+ if (!clk_base) {
+ pr_err("%s: failed to map clock registers\n", __func__);
+ return -EFAULT;
+ }
+
+ for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") {
+ id = of_alias_get_id(np, "dmc");
+ if (id < 0 || id >= ARRAY_SIZE(dmc_base)) {
+ pr_err("%s: failed to get alias of dmc node '%s'\n",
+ __func__, np->name);
+ return id;
+ }
+
+ dmc_base[id] = of_iomap(np, 0);
+ if (!dmc_base[id]) {
+ pr_err("%s: failed to map dmc%d registers\n",
+ __func__, id);
+ return -EFAULT;
+ }
+ }
+
+ for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) {
+ if (!dmc_base[id]) {
+ pr_err("%s: failed to find dmc%d node\n", __func__, id);
+ return -ENODEV;
+ }
+ }
+
arm_regulator = regulator_get(NULL, "vddarm");
if (IS_ERR(arm_regulator)) {
pr_err("failed to get regulator vddarm");
@@ -547,4 +653,11 @@ static int __init s5pv210_cpufreq_init(void)
return cpufreq_register_driver(&s5pv210_driver);
}
-late_initcall(s5pv210_cpufreq_init);
+static struct platform_driver s5pv210_cpufreq_platdrv = {
+ .driver = {
+ .name = "s5pv210-cpufreq",
+ .owner = THIS_MODULE,
+ },
+ .probe = s5pv210_cpufreq_probe,
+};
+module_platform_driver(s5pv210_cpufreq_platdrv);
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 7d4281e0d901..27298fd212d7 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -1169,234 +1169,9 @@ static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
#endif
};
-/*
- * Followings are the gpio banks in S5PV210/S5PC110
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure samsung_gpio_cfgs[3] in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of samsung_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-
-static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
-#ifdef CONFIG_CPU_S5PV210
- {
- .chip = {
- .base = S5PV210_GPA0(0),
- .ngpio = S5PV210_GPIO_A0_NR,
- .label = "GPA0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPA1(0),
- .ngpio = S5PV210_GPIO_A1_NR,
- .label = "GPA1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPB(0),
- .ngpio = S5PV210_GPIO_B_NR,
- .label = "GPB",
- },
- }, {
- .chip = {
- .base = S5PV210_GPC0(0),
- .ngpio = S5PV210_GPIO_C0_NR,
- .label = "GPC0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPC1(0),
- .ngpio = S5PV210_GPIO_C1_NR,
- .label = "GPC1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPD0(0),
- .ngpio = S5PV210_GPIO_D0_NR,
- .label = "GPD0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPD1(0),
- .ngpio = S5PV210_GPIO_D1_NR,
- .label = "GPD1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPE0(0),
- .ngpio = S5PV210_GPIO_E0_NR,
- .label = "GPE0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPE1(0),
- .ngpio = S5PV210_GPIO_E1_NR,
- .label = "GPE1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF0(0),
- .ngpio = S5PV210_GPIO_F0_NR,
- .label = "GPF0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF1(0),
- .ngpio = S5PV210_GPIO_F1_NR,
- .label = "GPF1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF2(0),
- .ngpio = S5PV210_GPIO_F2_NR,
- .label = "GPF2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPF3(0),
- .ngpio = S5PV210_GPIO_F3_NR,
- .label = "GPF3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG0(0),
- .ngpio = S5PV210_GPIO_G0_NR,
- .label = "GPG0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG1(0),
- .ngpio = S5PV210_GPIO_G1_NR,
- .label = "GPG1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG2(0),
- .ngpio = S5PV210_GPIO_G2_NR,
- .label = "GPG2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPG3(0),
- .ngpio = S5PV210_GPIO_G3_NR,
- .label = "GPG3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPI(0),
- .ngpio = S5PV210_GPIO_I_NR,
- .label = "GPI",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ0(0),
- .ngpio = S5PV210_GPIO_J0_NR,
- .label = "GPJ0",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ1(0),
- .ngpio = S5PV210_GPIO_J1_NR,
- .label = "GPJ1",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ2(0),
- .ngpio = S5PV210_GPIO_J2_NR,
- .label = "GPJ2",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ3(0),
- .ngpio = S5PV210_GPIO_J3_NR,
- .label = "GPJ3",
- },
- }, {
- .chip = {
- .base = S5PV210_GPJ4(0),
- .ngpio = S5PV210_GPIO_J4_NR,
- .label = "GPJ4",
- },
- }, {
- .chip = {
- .base = S5PV210_MP01(0),
- .ngpio = S5PV210_GPIO_MP01_NR,
- .label = "MP01",
- },
- }, {
- .chip = {
- .base = S5PV210_MP02(0),
- .ngpio = S5PV210_GPIO_MP02_NR,
- .label = "MP02",
- },
- }, {
- .chip = {
- .base = S5PV210_MP03(0),
- .ngpio = S5PV210_GPIO_MP03_NR,
- .label = "MP03",
- },
- }, {
- .chip = {
- .base = S5PV210_MP04(0),
- .ngpio = S5PV210_GPIO_MP04_NR,
- .label = "MP04",
- },
- }, {
- .chip = {
- .base = S5PV210_MP05(0),
- .ngpio = S5PV210_GPIO_MP05_NR,
- .label = "MP05",
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC00),
- .irq_base = IRQ_EINT(0),
- .chip = {
- .base = S5PV210_GPH0(0),
- .ngpio = S5PV210_GPIO_H0_NR,
- .label = "GPH0",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC20),
- .irq_base = IRQ_EINT(8),
- .chip = {
- .base = S5PV210_GPH1(0),
- .ngpio = S5PV210_GPIO_H1_NR,
- .label = "GPH1",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC40),
- .irq_base = IRQ_EINT(16),
- .chip = {
- .base = S5PV210_GPH2(0),
- .ngpio = S5PV210_GPIO_H2_NR,
- .label = "GPH2",
- .to_irq = samsung_gpiolib_to_irq,
- },
- }, {
- .base = (S5P_VA_GPIO + 0xC60),
- .irq_base = IRQ_EINT(24),
- .chip = {
- .base = S5PV210_GPH3(0),
- .ngpio = S5PV210_GPIO_H3_NR,
- .label = "GPH3",
- .to_irq = samsung_gpiolib_to_irq,
- },
- },
-#endif
-};
-
/* TODO: cleanup soc_is_* */
static __init int samsung_gpiolib_init(void)
{
- struct samsung_gpio_chip *chip;
- int i, nr_chips;
- int group = 0;
-
/*
* Currently there are two drivers that can provide GPIO support for
* Samsung SoCs. For device tree enabled platforms, the new
@@ -1420,21 +1195,6 @@ static __init int samsung_gpiolib_init(void)
S3C64XX_VA_GPIO);
samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
ARRAY_SIZE(s3c64xx_gpios_4bit2));
- } else if (soc_is_s5pv210()) {
- group = 0;
- chip = s5pv210_gpios_4bit;
- nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
-
- for (i = 0; i < nr_chips; i++, chip++) {
- if (!chip->config) {
- chip->config = &samsung_gpio_cfgs[3];
- chip->group = group++;
- }
- }
- samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
-#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
- s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-#endif
} else {
WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
return -ENODEV;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 64b98d242ea6..b0525e03782a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -132,6 +132,16 @@ config PHY_SAMSUNG_USB2
particular SoCs has to be enabled in addition to this driver. Number
and type of supported phys depends on the SoC.
+config PHY_S5PV210_USB2
+ bool "Support for S5PV210"
+ depends on PHY_SAMSUNG_USB2
+ depends on ARCH_S5PV210
+ help
+ Enable USB PHY support for S5PV210. This option requires that Samsung
+ USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of S5PV210 two phys
+ are available - device and host.
+
config PHY_EXYNOS4210_USB2
bool "Support for Exynos 4210"
depends on PHY_SAMSUNG_USB2
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b4f1d5770601..2983808e1626 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -18,5 +18,6 @@ phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
+phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
diff --git a/drivers/phy/phy-s5pv210-usb2.c b/drivers/phy/phy-s5pv210-usb2.c
new file mode 100644
index 000000000000..004d320767e4
--- /dev/null
+++ b/drivers/phy/phy-s5pv210-usb2.c
@@ -0,0 +1,187 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - S5PV210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Authors: Kamil Debski <k.debski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define S5PV210_UPHYPWR 0x0
+
+#define S5PV210_UPHYPWR_PHY0_SUSPEND BIT(0)
+#define S5PV210_UPHYPWR_PHY0_PWR BIT(3)
+#define S5PV210_UPHYPWR_PHY0_OTG_PWR BIT(4)
+#define S5PV210_UPHYPWR_PHY0 ( \
+ S5PV210_UPHYPWR_PHY0_SUSPEND | \
+ S5PV210_UPHYPWR_PHY0_PWR | \
+ S5PV210_UPHYPWR_PHY0_OTG_PWR)
+
+#define S5PV210_UPHYPWR_PHY1_SUSPEND BIT(6)
+#define S5PV210_UPHYPWR_PHY1_PWR BIT(7)
+#define S5PV210_UPHYPWR_PHY1 ( \
+ S5PV210_UPHYPWR_PHY1_SUSPEND | \
+ S5PV210_UPHYPWR_PHY1_PWR)
+
+/* PHY clock control */
+#define S5PV210_UPHYCLK 0x4
+
+#define S5PV210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
+#define S5PV210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
+
+#define S5PV210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
+#define S5PV210_UPHYCLK_PHY0_COMMON_ON BIT(4)
+#define S5PV210_UPHYCLK_PHY1_COMMON_ON BIT(7)
+
+/* PHY reset control */
+#define S5PV210_UPHYRST 0x8
+
+#define S5PV210_URSTCON_PHY0 BIT(0)
+#define S5PV210_URSTCON_OTG_HLINK BIT(1)
+#define S5PV210_URSTCON_OTG_PHYLINK BIT(2)
+#define S5PV210_URSTCON_PHY1_ALL BIT(3)
+#define S5PV210_URSTCON_HOST_LINK_ALL BIT(4)
+
+/* Isolation, configured in the power management unit */
+#define S5PV210_USB_ISOL_OFFSET 0x680c
+#define S5PV210_USB_ISOL_DEVICE BIT(0)
+#define S5PV210_USB_ISOL_HOST BIT(1)
+
+
+enum s5pv210_phy_id {
+ S5PV210_DEVICE,
+ S5PV210_HOST,
+ S5PV210_NUM_PHYS,
+};
+
+/*
+ * s5pv210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int s5pv210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ switch (rate) {
+ case 12 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_12MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_24MHZ;
+ break;
+ case 48 * MHZ:
+ *reg = S5PV210_UPHYCLK_PHYFSEL_48MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void s5pv210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 mask;
+
+ switch (inst->cfg->id) {
+ case S5PV210_DEVICE:
+ mask = S5PV210_USB_ISOL_DEVICE;
+ break;
+ case S5PV210_HOST:
+ mask = S5PV210_USB_ISOL_HOST;
+ break;
+ default:
+ return;
+ };
+
+ regmap_update_bits(drv->reg_pmu, S5PV210_USB_ISOL_OFFSET,
+ mask, on ? 0 : mask);
+}
+
+static void s5pv210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 rstbits = 0;
+ u32 phypwr = 0;
+ u32 rst;
+ u32 pwr;
+
+ switch (inst->cfg->id) {
+ case S5PV210_DEVICE:
+ phypwr = S5PV210_UPHYPWR_PHY0;
+ rstbits = S5PV210_URSTCON_PHY0;
+ break;
+ case S5PV210_HOST:
+ phypwr = S5PV210_UPHYPWR_PHY1;
+ rstbits = S5PV210_URSTCON_PHY1_ALL |
+ S5PV210_URSTCON_HOST_LINK_ALL;
+ break;
+ };
+
+ if (on) {
+ writel(drv->ref_reg_val, drv->reg_phy + S5PV210_UPHYCLK);
+
+ pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+ pwr &= ~phypwr;
+ writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+
+ rst = readl(drv->reg_phy + S5PV210_UPHYRST);
+ rst |= rstbits;
+ writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+ udelay(10);
+ rst &= ~rstbits;
+ writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+ } else {
+ pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
+ pwr |= phypwr;
+ writel(pwr, drv->reg_phy + S5PV210_UPHYPWR);
+ }
+}
+
+static int s5pv210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ s5pv210_isol(inst, 0);
+ s5pv210_phy_pwr(inst, 1);
+
+ return 0;
+}
+
+static int s5pv210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ s5pv210_phy_pwr(inst, 0);
+ s5pv210_isol(inst, 1);
+
+ return 0;
+}
+
+static const struct samsung_usb2_common_phy s5pv210_phys[S5PV210_NUM_PHYS] = {
+ [S5PV210_DEVICE] = {
+ .label = "device",
+ .id = S5PV210_DEVICE,
+ .power_on = s5pv210_power_on,
+ .power_off = s5pv210_power_off,
+ },
+ [S5PV210_HOST] = {
+ .label = "host",
+ .id = S5PV210_HOST,
+ .power_on = s5pv210_power_on,
+ .power_off = s5pv210_power_off,
+ },
+};
+
+const struct samsung_usb2_phy_config s5pv210_usb2_phy_config = {
+ .num_phys = ARRAY_SIZE(s5pv210_phys),
+ .phys = s5pv210_phys,
+ .rate_to_clk = s5pv210_rate_to_clk,
+};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 1e69a32c221d..29e4ab987645 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev,
}
static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_S5PV210_USB2
+ {
+ .compatible = "samsung,s5pv210-usb2-phy",
+ .data = &s5pv210_usb2_phy_config,
+ },
+#endif
#ifdef CONFIG_PHY_EXYNOS4210_USB2
{
.compatible = "samsung,exynos4210-usb2-phy",
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 45b3170652bd..1c55795d4429 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -61,6 +61,7 @@ struct samsung_usb2_phy_config {
bool has_mode_switch;
};
+extern const struct samsung_usb2_phy_config s5pv210_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index c1d3ebdf3b97..bc8674a63082 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -47,10 +47,6 @@
#include <asm/irq.h>
-#ifdef CONFIG_SAMSUNG_CLOCK
-#include <plat/clock.h>
-#endif
-
#include "samsung.h"
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \