All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] clk: exynos4: migrate to common clock framework
@ 2012-10-07 17:10 ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

This patch series removes the usage of Samsung specific clock for Exynos4
based platforms and migrates to use the common clock framework to register
the clocks. Both legacy and device tree enabled Exynos4 platforms are
supported. For legacy platforms, the clock instances are statically listed.
For device tree based platforms, the device tree is searched for clock nodes
and all available clock nodes are registered.

Thomas Abraham (5):
  clk: samsung: add common clock framework support for Samsung platforms
  clk: exynos4: register clocks using common clock framework
  ARM: dts: Add Exynos4210 clock nodes
  ARM: dts: list the clock providers for serial ports
  ARM: Exynos4: Migrate clock support to common clock framework

 arch/arm/boot/dts/exynos4-clock.dtsi       |  389 +++++++++++++++++
 arch/arm/boot/dts/exynos4.dtsi             |    9 +
 arch/arm/mach-exynos/Kconfig               |    1 +
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.h       |   35 --
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 --------
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 --------
 arch/arm/mach-exynos/common.c              |   22 +-
 arch/arm/mach-exynos/common.h              |    3 +
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 arch/arm/mach-exynos/mct.c                 |   11 +-
 arch/arm/plat-samsung/Kconfig              |    4 +-
 drivers/clk/Makefile                       |    1 +
 drivers/clk/samsung/Makefile               |    6 +
 drivers/clk/samsung/clk-exynos4.c          |  647 ++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.c                  |  414 ++++++++++++++++++
 drivers/clk/samsung/clk.h                  |  212 +++++++++
 23 files changed, 1696 insertions(+), 448 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4-clock.dtsi
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk-exynos4.c
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 0/5] clk: exynos4: migrate to common clock framework
@ 2012-10-07 17:10 ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series removes the usage of Samsung specific clock for Exynos4
based platforms and migrates to use the common clock framework to register
the clocks. Both legacy and device tree enabled Exynos4 platforms are
supported. For legacy platforms, the clock instances are statically listed.
For device tree based platforms, the device tree is searched for clock nodes
and all available clock nodes are registered.

Thomas Abraham (5):
  clk: samsung: add common clock framework support for Samsung platforms
  clk: exynos4: register clocks using common clock framework
  ARM: dts: Add Exynos4210 clock nodes
  ARM: dts: list the clock providers for serial ports
  ARM: Exynos4: Migrate clock support to common clock framework

 arch/arm/boot/dts/exynos4-clock.dtsi       |  389 +++++++++++++++++
 arch/arm/boot/dts/exynos4.dtsi             |    9 +
 arch/arm/mach-exynos/Kconfig               |    1 +
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.h       |   35 --
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 --------
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 --------
 arch/arm/mach-exynos/common.c              |   22 +-
 arch/arm/mach-exynos/common.h              |    3 +
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 arch/arm/mach-exynos/mct.c                 |   11 +-
 arch/arm/plat-samsung/Kconfig              |    4 +-
 drivers/clk/Makefile                       |    1 +
 drivers/clk/samsung/Makefile               |    6 +
 drivers/clk/samsung/clk-exynos4.c          |  647 ++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.c                  |  414 ++++++++++++++++++
 drivers/clk/samsung/clk.h                  |  212 +++++++++
 23 files changed, 1696 insertions(+), 448 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4-clock.dtsi
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk-exynos4.c
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

-- 
1.7.5.4

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-07 17:10 ` Thomas Abraham
@ 2012-10-07 17:10   ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

All Samsung platforms include several types of clocks including fixed-rate,
mux, divider and gate clock types. There are typically hundreds of such clocks
on each of the Samsung platforms. To enable Samsung platforms to register these
clocks using the common clock framework, a bunch of utility functions are
introduced here which simplify the clock registration process.

In addition to the basic types of clock supported by common clock framework,
a Samsung specific representation of the PLL clocks is also introduced.

Both legacy and device tree based Samsung platforms are supported. On legacy
platforms, the clocks are statically instantiated and registered with common
clock framework. On device tree enabled platforms, the device tree is
searched and all clock nodes found are registered. It is also possible to
register statically instantiated clocks on device tree enabled platforms.

Cc: Mike Turquette <mturquette@ti.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 drivers/clk/Makefile         |    1 +
 drivers/clk/samsung/Makefile |    5 +
 drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
 4 files changed, 632 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b9..95644e3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,6 +19,7 @@ endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
+obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644
index 0000000..3f926b0
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,5 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 0000000..f5e269a
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 includes utility functions to register clocks to common
+ * clock framework for Samsung platforms. This includes an implementation
+ * of Samsung 'pll type' clock to represent the implementation of the
+ * pll found on Samsung platforms. In addition to that, utility functions
+ * to register mux, div, gate and fixed rate types of clocks are included.
+*/
+
+#include <linux/of.h>
+#include "clk.h"
+
+#define MAX_PARENT_CLKS		16
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
+
+static DEFINE_SPINLOCK(lock);
+static void __iomem *reg_base;
+static void __iomem *reg_fin_pll;
+
+void __init samsung_clk_set_ctrl_base(void __iomem *base)
+{
+	reg_base = base;
+}
+
+void __init samsung_clk_set_finpll_reg(void __iomem *reg)
+{
+	reg_fin_pll = reg;
+}
+
+/* determine the output clock speed of the pll */
+static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->get_rate)
+		return to_clk_pll(hw)->get_rate(parent_rate);
+
+	return 0;
+}
+
+/* round operation not supported */
+static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long *prate)
+{
+	return samsung_pll_clock_recalc_rate(hw, *prate);
+}
+
+/* set the clock output rate of the pll */
+static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->set_rate)
+		return to_clk_pll(hw)->set_rate(drate);
+
+	return 0;
+}
+
+/* clock operations for samsung pll clock type */
+static const struct clk_ops samsung_pll_clock_ops = {
+	.recalc_rate = samsung_pll_clock_recalc_rate,
+	.round_rate = samsung_pll_clock_round_rate,
+	.set_rate = samsung_pll_clock_set_rate,
+};
+
+/* register a samsung pll type clock */
+void __init samsung_clk_register_pll(const char *name, const char **pnames,
+				struct device_node *np,
+				int (*set_rate)(unsigned long rate),
+				unsigned long (*get_rate)(unsigned long rate))
+{
+	struct samsung_pll_clock *clk_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	int ret;
+
+	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+	if (!clk_pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll_clock_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = pnames;
+	init.num_parents = 1;
+
+	clk_pll->set_rate = set_rate;
+	clk_pll->get_rate = get_rate;
+	clk_pll->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(clk_pll);
+		return;
+	}
+
+#ifdef CONFIG_OF
+	if (np)
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+#endif
+
+	/*
+	 * Register a clock lookup for the pll-type clock even if this
+	 * has been instantiated from device tree. This helps to do
+	 * clk_get() lookup on this clock for pruposes of displaying its
+	 * clock speed at boot time.
+	 */
+	ret = clk_register_clkdev(clk, name, NULL);
+	if (ret)
+		pr_err("%s: failed to register clock lookup for %s", __func__,
+				name);
+}
+
+#ifdef CONFIG_OF
+/* register a samsung pll type clock instantiated from device tree */
+void __init samsung_of_clk_register_pll(struct device_node *np)
+{
+	const char *clk_name = np->name;
+	const char *parent_name;
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
+}
+#endif
+
+/*
+ * Allow platform specific implementations to attach set_rate and get_rate
+ * callbacks for the pll type clock. Typical calling sequence..
+ *
+ * struct clk *clk = clk_get(NULL, "pll-clk-name");
+ * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
+ */
+void __init samsung_pll_clk_set_cb(struct clk *clk,
+			int (*set_rate)(unsigned long rate),
+			unsigned long (*get_rate)(unsigned long rate))
+{
+	struct samsung_pll_clock *clk_pll;
+	struct clk_hw *hw = __clk_get_hw(clk);
+
+	clk_pll = to_clk_pll(hw);
+	clk_pll->set_rate = set_rate;
+	clk_pll->get_rate = get_rate;
+}
+
+/* register a list of fixed clocks (used only for non-dt platforms) */
+void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
+				clk_list->flags, clk_list->fixed_rate);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				clk_list->name);
+			continue;
+		}
+
+		/*
+		 * Register a lookup which will help in clk_get() and
+		 * printing the clock rate during clock initialization.
+		 */
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+	}
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_mux(NULL, clk_list->name,
+			clk_list->parent_names, clk_list->num_parents,
+			clk_list->flags, clk_list->reg, clk_list->shift,
+			clk_list->width, clk_list->mux_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung mux type clock instantiated from device tree */
+void __init samsung_of_clk_register_mux(struct device_node *np)
+{
+	struct samsung_mux_clock mux_clk;
+	const char *clk_name = np->name;
+	const char *parent_names[MAX_PARENT_CLKS];
+	u32 reg_info[3];
+	int idx = 0;
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	do {
+		/* get names of all parent clocks */
+		parent_names[idx] = of_clk_get_parent_name(np, idx);
+		idx++;
+	} while (parent_names[idx-1]);
+
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	mux_clk.name = clk_name;
+	mux_clk.parent_names = parent_names;
+	mux_clk.num_parents = idx - 1;
+	mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
+	mux_clk.shift = reg_info[1];
+	mux_clk.width = reg_info[2];
+	mux_clk.dev_name = NULL;
+	mux_clk.flags = 0;
+	mux_clk.mux_flags = 0;
+	mux_clk.alias = NULL;
+	mux_clk.np = np;
+
+	if (!strcmp(mux_clk.name, "fin_pll"))
+		mux_clk.reg = reg_fin_pll;
+
+	samsung_clk_register_mux(&mux_clk, 1);
+}
+#endif
+
+/* register a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_divider(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->shift, clk_list->width, clk_list->div_flags,
+			&lock);
+		if (IS_ERR(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung div type clock instantiated from device tree */
+void __init samsung_of_clk_register_div(struct device_node *np)
+{
+	struct samsung_div_clock clk_div;
+	const char *clk_name = np->name;
+	const char *parent_name;
+	u32 reg_info[3];
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	clk_div.name = clk_name;
+	clk_div.parent_name = parent_name;
+	clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
+	clk_div.shift = reg_info[1];
+	clk_div.width = reg_info[2];
+	clk_div.dev_name = NULL;
+	clk_div.flags = 0;
+	clk_div.div_flags = 0;
+	clk_div.alias = NULL;
+	clk_div.np = np;
+
+	samsung_clk_register_div(&clk_div, 1);
+}
+#endif
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_gate(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->bit_idx, clk_list->gate_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung gate type clock instantiated from device tree */
+void __init samsung_of_clk_register_gate(struct device_node *np)
+{
+	struct samsung_gate_clock clk_gate;
+	const char *clk_name = np->name;
+	const char *parent_name;
+	u32 reg_info[2];
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	clk_gate.name = clk_name;
+	clk_gate.parent_name = parent_name;
+	clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
+	clk_gate.bit_idx = reg_info[1];
+	clk_gate.dev_name = NULL;
+	clk_gate.flags = 0;
+	clk_gate.gate_flags = 0;
+	clk_gate.alias = NULL;
+	clk_gate.np = np;
+
+	samsung_clk_register_gate(&clk_gate, 1);
+}
+#endif
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get(NULL, clk_name);
+	if (IS_ERR(clk))
+		return 0;
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+	return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 0000000..391607d
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 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 <mach/regs-clock.h>
+
+/**
+ * struct samsung_clk_pll: represents a samsung pll type clock
+ * @hw: connection to struct clk.
+ * @set_rate: callback for setting the pll clock rate
+ * @get_rate: callback for determing the pll clock rate
+ *
+ * Internal representation of the pll type clock. Platform specific
+ * implementation can instantiate clocks of this type by calling
+ * samsung_clk_register_pll() function.
+ */
+struct samsung_pll_clock {
+	struct clk_hw		hw;
+	int			(*set_rate)(unsigned long rate);
+	unsigned long		(*get_rate)(unsigned long xtal_rate);
+};
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_fixed_rate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		fixed_rate;
+	struct device_node	*np;
+};
+
+#define FRATE_CLK(dname, cname, pname, f, frate)	\
+	{						\
+		.dev_name	= dname,		\
+		.name		= cname,		\
+		.parent_name	= pname,		\
+		.flags		= f,			\
+		.fixed_rate	= frate,		\
+		.np		= NULL,			\
+	}
+
+/**
+ * struct samsung_mux_clock: information about mux 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_mux_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			mux_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define MUXCLK(dname, cname, pnames, f, r, s, w, mf)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.mux_flags	= mf,				\
+		.np		= NULL,				\
+	}
+
+/**
+ * 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_div_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			div_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define DIVCLK(dname, cname, pname, f, r, s, w, df)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.div_flags	= df,				\
+		.np		= NULL,				\
+	}
+
+/**
+ * struct samsung_gate_clock: information about gate 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_gate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			bit_idx;
+	u8			gate_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define GATECLK(dname, cname, pname, f, r, b, a)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.bit_idx	= b,				\
+		.alias		= a,				\
+		.np		= NULL,				\
+	}
+
+extern void __init samsung_clk_set_ctrl_base(void __iomem *base);
+extern void __init samsung_clk_set_finpll_reg(void __iomem *reg);
+
+extern void __init samsung_clk_register_pll(const char *name,
+		const char **parent_names, struct device_node *np,
+		int (*set_rate)(unsigned long rate),
+		unsigned long (*get_rate)(unsigned long rate));
+
+extern void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_gate(
+		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_of_clk_register_mux(struct device_node *np);
+extern void __init samsung_of_clk_register_pll(struct device_node *np);
+extern void __init samsung_of_clk_register_div(struct device_node *np);
+extern void __init samsung_of_clk_register_gate(struct device_node *np);
+
+extern void __init samsung_pll_clk_set_cb(struct clk *clk,
+			int (*set_rate)(unsigned long rate),
+			unsigned long (*get_rate)(unsigned long rate));
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-07 17:10   ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

All Samsung platforms include several types of clocks including fixed-rate,
mux, divider and gate clock types. There are typically hundreds of such clocks
on each of the Samsung platforms. To enable Samsung platforms to register these
clocks using the common clock framework, a bunch of utility functions are
introduced here which simplify the clock registration process.

In addition to the basic types of clock supported by common clock framework,
a Samsung specific representation of the PLL clocks is also introduced.

Both legacy and device tree based Samsung platforms are supported. On legacy
platforms, the clocks are statically instantiated and registered with common
clock framework. On device tree enabled platforms, the device tree is
searched and all clock nodes found are registered. It is also possible to
register statically instantiated clocks on device tree enabled platforms.

Cc: Mike Turquette <mturquette@ti.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 drivers/clk/Makefile         |    1 +
 drivers/clk/samsung/Makefile |    5 +
 drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
 4 files changed, 632 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/samsung/Makefile
 create mode 100644 drivers/clk/samsung/clk.c
 create mode 100644 drivers/clk/samsung/clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 71a25b9..95644e3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -19,6 +19,7 @@ endif
 obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
 obj-$(CONFIG_ARCH_U8500)	+= ux500/
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
+obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644
index 0000000..3f926b0
--- /dev/null
+++ b/drivers/clk/samsung/Makefile
@@ -0,0 +1,5 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644
index 0000000..f5e269a
--- /dev/null
+++ b/drivers/clk/samsung/clk.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 includes utility functions to register clocks to common
+ * clock framework for Samsung platforms. This includes an implementation
+ * of Samsung 'pll type' clock to represent the implementation of the
+ * pll found on Samsung platforms. In addition to that, utility functions
+ * to register mux, div, gate and fixed rate types of clocks are included.
+*/
+
+#include <linux/of.h>
+#include "clk.h"
+
+#define MAX_PARENT_CLKS		16
+#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
+
+static DEFINE_SPINLOCK(lock);
+static void __iomem *reg_base;
+static void __iomem *reg_fin_pll;
+
+void __init samsung_clk_set_ctrl_base(void __iomem *base)
+{
+	reg_base = base;
+}
+
+void __init samsung_clk_set_finpll_reg(void __iomem *reg)
+{
+	reg_fin_pll = reg;
+}
+
+/* determine the output clock speed of the pll */
+static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->get_rate)
+		return to_clk_pll(hw)->get_rate(parent_rate);
+
+	return 0;
+}
+
+/* round operation not supported */
+static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long *prate)
+{
+	return samsung_pll_clock_recalc_rate(hw, *prate);
+}
+
+/* set the clock output rate of the pll */
+static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
+
+	if (clk_pll->set_rate)
+		return to_clk_pll(hw)->set_rate(drate);
+
+	return 0;
+}
+
+/* clock operations for samsung pll clock type */
+static const struct clk_ops samsung_pll_clock_ops = {
+	.recalc_rate = samsung_pll_clock_recalc_rate,
+	.round_rate = samsung_pll_clock_round_rate,
+	.set_rate = samsung_pll_clock_set_rate,
+};
+
+/* register a samsung pll type clock */
+void __init samsung_clk_register_pll(const char *name, const char **pnames,
+				struct device_node *np,
+				int (*set_rate)(unsigned long rate),
+				unsigned long (*get_rate)(unsigned long rate))
+{
+	struct samsung_pll_clock *clk_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+	int ret;
+
+	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
+	if (!clk_pll) {
+		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+		return;
+	}
+
+	init.name = name;
+	init.ops = &samsung_pll_clock_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = pnames;
+	init.num_parents = 1;
+
+	clk_pll->set_rate = set_rate;
+	clk_pll->get_rate = get_rate;
+	clk_pll->hw.init = &init;
+
+	/* register the clock */
+	clk = clk_register(NULL, &clk_pll->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to register pll clock %s\n", __func__,
+				name);
+		kfree(clk_pll);
+		return;
+	}
+
+#ifdef CONFIG_OF
+	if (np)
+		of_clk_add_provider(np, of_clk_src_simple_get, clk);
+#endif
+
+	/*
+	 * Register a clock lookup for the pll-type clock even if this
+	 * has been instantiated from device tree. This helps to do
+	 * clk_get() lookup on this clock for pruposes of displaying its
+	 * clock speed at boot time.
+	 */
+	ret = clk_register_clkdev(clk, name, NULL);
+	if (ret)
+		pr_err("%s: failed to register clock lookup for %s", __func__,
+				name);
+}
+
+#ifdef CONFIG_OF
+/* register a samsung pll type clock instantiated from device tree */
+void __init samsung_of_clk_register_pll(struct device_node *np)
+{
+	const char *clk_name = np->name;
+	const char *parent_name;
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
+}
+#endif
+
+/*
+ * Allow platform specific implementations to attach set_rate and get_rate
+ * callbacks for the pll type clock. Typical calling sequence..
+ *
+ * struct clk *clk = clk_get(NULL, "pll-clk-name");
+ * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
+ */
+void __init samsung_pll_clk_set_cb(struct clk *clk,
+			int (*set_rate)(unsigned long rate),
+			unsigned long (*get_rate)(unsigned long rate))
+{
+	struct samsung_pll_clock *clk_pll;
+	struct clk_hw *hw = __clk_get_hw(clk);
+
+	clk_pll = to_clk_pll(hw);
+	clk_pll->set_rate = set_rate;
+	clk_pll->get_rate = get_rate;
+}
+
+/* register a list of fixed clocks (used only for non-dt platforms) */
+void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
+				clk_list->flags, clk_list->fixed_rate);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				clk_list->name);
+			continue;
+		}
+
+		/*
+		 * Register a lookup which will help in clk_get() and
+		 * printing the clock rate during clock initialization.
+		 */
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("clock: failed to register clock lookup for %s",
+				clk_list->name);
+	}
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_mux(NULL, clk_list->name,
+			clk_list->parent_names, clk_list->num_parents,
+			clk_list->flags, clk_list->reg, clk_list->shift,
+			clk_list->width, clk_list->mux_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("%s: failed to register clock %s\n", __func__,
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung mux type clock instantiated from device tree */
+void __init samsung_of_clk_register_mux(struct device_node *np)
+{
+	struct samsung_mux_clock mux_clk;
+	const char *clk_name = np->name;
+	const char *parent_names[MAX_PARENT_CLKS];
+	u32 reg_info[3];
+	int idx = 0;
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	do {
+		/* get names of all parent clocks */
+		parent_names[idx] = of_clk_get_parent_name(np, idx);
+		idx++;
+	} while (parent_names[idx-1]);
+
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	mux_clk.name = clk_name;
+	mux_clk.parent_names = parent_names;
+	mux_clk.num_parents = idx - 1;
+	mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
+	mux_clk.shift = reg_info[1];
+	mux_clk.width = reg_info[2];
+	mux_clk.dev_name = NULL;
+	mux_clk.flags = 0;
+	mux_clk.mux_flags = 0;
+	mux_clk.alias = NULL;
+	mux_clk.np = np;
+
+	if (!strcmp(mux_clk.name, "fin_pll"))
+		mux_clk.reg = reg_fin_pll;
+
+	samsung_clk_register_mux(&mux_clk, 1);
+}
+#endif
+
+/* register a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_divider(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->shift, clk_list->width, clk_list->div_flags,
+			&lock);
+		if (IS_ERR(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung div type clock instantiated from device tree */
+void __init samsung_of_clk_register_div(struct device_node *np)
+{
+	struct samsung_div_clock clk_div;
+	const char *clk_name = np->name;
+	const char *parent_name;
+	u32 reg_info[3];
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	clk_div.name = clk_name;
+	clk_div.parent_name = parent_name;
+	clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
+	clk_div.shift = reg_info[1];
+	clk_div.width = reg_info[2];
+	clk_div.dev_name = NULL;
+	clk_div.flags = 0;
+	clk_div.div_flags = 0;
+	clk_div.alias = NULL;
+	clk_div.np = np;
+
+	samsung_clk_register_div(&clk_div, 1);
+}
+#endif
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
+						unsigned int nr_clk)
+{
+	struct clk *clk;
+	unsigned int idx, ret;
+
+	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
+		clk = clk_register_gate(NULL, clk_list->name,
+			clk_list->parent_name, clk_list->flags, clk_list->reg,
+			clk_list->bit_idx, clk_list->gate_flags, &lock);
+		if (IS_ERR(clk)) {
+			pr_err("clock: failed to register clock %s\n",
+				clk_list->name);
+			continue;
+		}
+
+#ifdef CONFIG_OF
+		if (clk_list->np)
+			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
+							clk);
+#endif
+
+		ret = clk_register_clkdev(clk, clk_list->name,
+						clk_list->dev_name);
+		if (ret)
+			pr_err("%s: failed to register clock lookup for %s",
+					__func__, clk_list->name);
+
+		if (clk_list->alias) {
+			ret = clk_register_clkdev(clk, clk_list->alias,
+						clk_list->dev_name);
+			if (ret)
+				pr_err("%s: failed to register lookup %s\n",
+					__func__, clk_list->alias);
+		}
+	}
+}
+
+#ifdef CONFIG_OF
+/* register a samsung gate type clock instantiated from device tree */
+void __init samsung_of_clk_register_gate(struct device_node *np)
+{
+	struct samsung_gate_clock clk_gate;
+	const char *clk_name = np->name;
+	const char *parent_name;
+	u32 reg_info[2];
+
+	of_property_read_string(np, "clock-output-names", &clk_name);
+	parent_name = of_clk_get_parent_name(np, 0);
+	if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
+		pr_err("%s: invalid register info in node\n", __func__);
+
+	clk_gate.name = clk_name;
+	clk_gate.parent_name = parent_name;
+	clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
+	clk_gate.bit_idx = reg_info[1];
+	clk_gate.dev_name = NULL;
+	clk_gate.flags = 0;
+	clk_gate.gate_flags = 0;
+	clk_gate.alias = NULL;
+	clk_gate.np = np;
+
+	samsung_clk_register_gate(&clk_gate, 1);
+}
+#endif
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get(NULL, clk_name);
+	if (IS_ERR(clk))
+		return 0;
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+	return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644
index 0000000..391607d
--- /dev/null
+++ b/drivers/clk/samsung/clk.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 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 <mach/regs-clock.h>
+
+/**
+ * struct samsung_clk_pll: represents a samsung pll type clock
+ * @hw: connection to struct clk.
+ * @set_rate: callback for setting the pll clock rate
+ * @get_rate: callback for determing the pll clock rate
+ *
+ * Internal representation of the pll type clock. Platform specific
+ * implementation can instantiate clocks of this type by calling
+ * samsung_clk_register_pll() function.
+ */
+struct samsung_pll_clock {
+	struct clk_hw		hw;
+	int			(*set_rate)(unsigned long rate);
+	unsigned long		(*get_rate)(unsigned long xtal_rate);
+};
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_fixed_rate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	unsigned long		fixed_rate;
+	struct device_node	*np;
+};
+
+#define FRATE_CLK(dname, cname, pname, f, frate)	\
+	{						\
+		.dev_name	= dname,		\
+		.name		= cname,		\
+		.parent_name	= pname,		\
+		.flags		= f,			\
+		.fixed_rate	= frate,		\
+		.np		= NULL,			\
+	}
+
+/**
+ * struct samsung_mux_clock: information about mux 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_mux_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		**parent_names;
+	u8			num_parents;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			mux_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define MUXCLK(dname, cname, pnames, f, r, s, w, mf)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.mux_flags	= mf,				\
+		.np		= NULL,				\
+	}
+
+/**
+ * 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_div_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			shift;
+	u8			width;
+	u8			div_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define DIVCLK(dname, cname, pname, f, r, s, w, df)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.shift		= s,				\
+		.width		= w,				\
+		.div_flags	= df,				\
+		.np		= NULL,				\
+	}
+
+/**
+ * struct samsung_gate_clock: information about gate 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.
+ * @reg: address of 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.
+ * @np: node pointer for this clock.
+ */
+struct samsung_gate_clock {
+	const char		*dev_name;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	void __iomem		*reg;
+	u8			bit_idx;
+	u8			gate_flags;
+	const char		*alias;
+	struct device_node	*np;
+};
+
+#define GATECLK(dname, cname, pname, f, r, b, a)		\
+	{							\
+		.dev_name	= dname,			\
+		.name		= cname,			\
+		.parent_name	= pname,			\
+		.flags		= f,				\
+		.reg		= r,				\
+		.bit_idx	= b,				\
+		.alias		= a,				\
+		.np		= NULL,				\
+	}
+
+extern void __init samsung_clk_set_ctrl_base(void __iomem *base);
+extern void __init samsung_clk_set_finpll_reg(void __iomem *reg);
+
+extern void __init samsung_clk_register_pll(const char *name,
+		const char **parent_names, struct device_node *np,
+		int (*set_rate)(unsigned long rate),
+		unsigned long (*get_rate)(unsigned long rate));
+
+extern void __init samsung_clk_register_fixed_rate(
+		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+		unsigned int nr_clk);
+
+extern void __init samsung_clk_register_gate(
+		struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern void __init samsung_of_clk_register_mux(struct device_node *np);
+extern void __init samsung_of_clk_register_pll(struct device_node *np);
+extern void __init samsung_of_clk_register_div(struct device_node *np);
+extern void __init samsung_of_clk_register_gate(struct device_node *np);
+
+extern void __init samsung_pll_clk_set_cb(struct clk *clk,
+			int (*set_rate)(unsigned long rate),
+			unsigned long (*get_rate)(unsigned long rate));
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
  2012-10-07 17:10 ` Thomas Abraham
@ 2012-10-07 17:10   ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

For legacy Exynos4 platforms, the available clocks are statically
listed and then registered using the common clock framework. On device
tree enabled exynos platfotms, the device tree is searched and all
clock nodes found are registered. Support for Exynos4210 and
Exynos4x12 platforms is included.

Cc: Mike Turquette <mturquette@ti.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 drivers/clk/samsung/Makefile      |    1 +
 drivers/clk/samsung/clk-exynos4.c |  647 +++++++++++++++++++++++++++++++++++++
 2 files changed, 648 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/samsung/clk-exynos4.c

diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 3f926b0..69487f7 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644
index 0000000..e74b004
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 Exynos4 platforms
+ * ToDo: Remove all static instantiation of clocks after migrating all Exynos4
+ *	 based boards to use device tree support.
+*/
+
+#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 <plat/pll.h>
+#include <plat/cpu.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <plat/map-s5p.h>
+#include "clk.h"
+
+#define EXYNOS4_OP_MODE		(S5P_VA_CHIPID + 8)
+
+/* base address of io remapped clock controller register space */
+static	void __iomem *clk_base;
+
+static const char *pll_parent_names[] __initdata = { "fin_pll" };
+static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
+static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
+static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
+static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
+
+static const char *sclk_ampll_parents[] __initdata = {
+		"mout_mpll", "sclk_apll", };
+
+static const char *sclk_evpll_parents[] __initdata = {
+		"mout_epll", "mout_vpll", };
+
+static const char *mout_core_parents[] __initdata = {
+		"mout_apll", "mout_mpll", };
+
+static const char *mout_mfc_parents[] __initdata = {
+		"mout_mfc0", "mout_mfc1", };
+
+static const char *mout_dac_parents[] __initdata = {
+		"mout_vpll", "sclk_hdmiphy", };
+
+static const char *mout_hdmi_parents[] __initdata = {
+		"sclk_pixel", "sclk_hdmiphy", };
+
+static const char *mout_mixer_parents[] __initdata = {
+		"sclk_dac", "sclk_hdmi", };
+
+static const char *group1_parents[] __initdata = {
+		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+		"none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
+		"mout_vpll" };
+
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_mux_clock exynos4_mux_clks[] = {
+	MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
+			EXYNOS4_OP_MODE, 0, 1, 0),
+	MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 0, 1, 0),
+	MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
+	MUXCLK(NULL, "mout_core", mout_core_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
+	MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
+	MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
+	MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
+	MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
+	MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
+	MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
+	MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
+	MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
+	MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
+	MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
+	MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
+	MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 0, 1, 0),
+	MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 4, 1, 0),
+	MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 8, 1, 0),
+	MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 24, 4, 0),
+	MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 28, 4, 0),
+	MUXCLK(NULL, "mout_cam0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 16, 4, 0),
+	MUXCLK(NULL, "mout_cam1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 20, 4, 0),
+	MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 0, 4, 0),
+	MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 4, 4, 0),
+	MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 8, 4, 0),
+	MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 12, 4, 0),
+	MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
+			EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
+	MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
+			EXYNOS4_CLKSRC_TV, 8, 1, 0),
+	MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
+			EXYNOS4_CLKSRC_TV, 0, 1, 0),
+	MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
+			EXYNOS4_CLKSRC_TV, 4, 1, 0),
+};
+
+static struct samsung_div_clock exynos4_div_clks[] = {
+	DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
+			EXYNOS4_CLKDIV_CPU, 24, 3, 0),
+	DIVCLK(NULL, "div_core", "mout_core", 0,
+			EXYNOS4_CLKDIV_CPU, 0, 3, 0),
+	DIVCLK(NULL, "armclk", "div_core", 0,
+			EXYNOS4_CLKDIV_CPU, 28, 3, 0),
+	DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
+			EXYNOS4_CLKDIV_TOP, 0, 3, 0),
+	DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
+			EXYNOS4_CLKDIV_TOP, 4, 4, 0),
+	DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
+			EXYNOS4_CLKDIV_TOP, 8, 3, 0),
+	DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
+			EXYNOS4_CLKDIV_TOP, 12, 3, 0),
+	DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
+			EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
+	DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
+			EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
+	DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
+			EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
+	DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
+			EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
+	DIVCLK(NULL, "div_sata", "mout_sata", 0,
+			EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
+	DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
+			EXYNOS4_CLKDIV_MFC, 0, 4, 0),
+	DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
+			EXYNOS4_CLKDIV_CAM, 24, 4, 0),
+	DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
+			EXYNOS4_CLKDIV_CAM, 28, 4, 0),
+	DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
+			EXYNOS4_CLKDIV_CAM, 16, 4, 0),
+	DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
+			EXYNOS4_CLKDIV_CAM, 20, 4, 0),
+	DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
+			EXYNOS4_CLKDIV_CAM, 0, 4, 0),
+	DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
+			EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
+	DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
+			EXYNOS4_CLKDIV_TV, 0, 4, 0),
+};
+
+struct samsung_gate_clock exynos4_gate_clks[] = {
+	GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
+	GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
+	GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
+	GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
+	GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
+	GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
+	GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
+	GATECLK(NULL, "timers", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
+	GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
+	GATECLK(NULL, "jpeg", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
+	GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
+	GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
+	GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
+	GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
+	GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
+	GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
+	GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
+	GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
+	GATECLK(NULL, "dwmmc", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
+	GATECLK("s5p-sdo", "dac", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 2, NULL),
+	GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 1, NULL),
+	GATECLK("s5p-mixer", "vp", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 0, NULL),
+	GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 3, NULL),
+	GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
+			S5P_HDMI_PHY_CONTROL, 0, NULL),
+	GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
+			S5P_DAC_PHY_CONTROL, 0, NULL),
+	GATECLK(NULL, "adc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
+	GATECLK(NULL, "keypad", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
+	GATECLK(NULL, "rtc", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
+	GATECLK(NULL, "watchdog", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
+	GATECLK(NULL, "usbhost", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
+	GATECLK(NULL, "otg", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
+	GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
+	GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
+	GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
+	GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
+	GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
+	GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
+	GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
+	GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
+	GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
+	GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
+	GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
+	GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
+	GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
+	GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
+	GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
+	GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
+	GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
+			EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
+	GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
+	GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
+	GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
+	GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
+	GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
+	GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
+	GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
+	GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
+	GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
+	GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
+	GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
+	GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
+	GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
+	GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
+	GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
+	GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
+			EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
+};
+
+/* register clock common to all Exynos4 platforms */
+void __init exynos4_clk_init(void)
+{
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4_mux_clks,
+			ARRAY_SIZE(exynos4_mux_clks));
+	samsung_clk_register_div(exynos4_div_clks,
+			ARRAY_SIZE(exynos4_div_clks));
+	samsung_clk_register_gate(exynos4_gate_clks,
+			ARRAY_SIZE(exynos4_gate_clks));
+}
+
+/*
+ * Exynos4210 Specific Clocks
+ */
+
+static const char *exynos4210_vpll_parent_names[] __initdata = {
+		"mout_vpll_src" };
+static const char *mout_vpll_src_parents[] __initdata = {
+		"fin_pll", "sclk_hdmi24m" };
+static const char *exynos4210_mout_vpll_parents[] __initdata = {
+		"mout_vpll_src", "fout_vpll", };
+
+/* Exynos4210 specific fixed rate clocks */
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* Exynos4210 specific mux-type clocks */
+static struct samsung_mux_clock exynos4210_mux_clks[] = {
+	MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
+			EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 8, 1, 0),
+};
+
+static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_APLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
+}
+
+static unsigned long exynos4210_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
+}
+
+static u32 exynos4_vpll_div[][8] = {
+	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static int exynos4210_vpll_set_rate(unsigned long rate)
+{
+	unsigned int vpll_con0, vpll_con1 = 0;
+	unsigned int i;
+
+	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
+	vpll_con0 &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
+	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
+			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
+			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
+		if (exynos4_vpll_div[i][0] == rate) {
+			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
+		pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
+	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+		continue;
+
+	return 0;
+}
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock",
+		.data = of_fixed_clk_setup, },
+	{ .compatible = "samsung,clock-mux",
+		.data = samsung_of_clk_register_mux, },
+	{ .compatible = "samsung,clock-pll",
+		.data = samsung_of_clk_register_pll, },
+	{ .compatible = "samsung,clock-div",
+		.data = samsung_of_clk_register_div, },
+	{ .compatible = "samsung,clock-gate",
+		.data = samsung_of_clk_register_gate, },
+	{},
+};
+
+#ifdef CONFIG_OF
+void __init exynos4_of_clk_init(void)
+{
+	struct device_node *np;
+	struct clk *clk;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4-clock-ctrl");
+	if (!np) {
+		pr_err("%s: clock controller node not found\n", __func__);
+		return;
+	}
+
+	clk_base = of_iomap(np, 0);
+	WARN(!clk_base, "unable to map clocks registers\n");
+
+	samsung_clk_set_ctrl_base(clk_base);
+	samsung_clk_set_finpll_reg(EXYNOS4_OP_MODE);
+	of_clk_init(clk_match);
+
+	clk = clk_get(NULL, "fout_apll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_apll);
+	clk = clk_get(NULL, "fout_mpll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_mpll);
+	clk = clk_get(NULL, "fout_epll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_epll);
+	clk = clk_get(NULL, "fout_vpll");
+	samsung_pll_clk_set_cb(clk, exynos4210_vpll_set_rate,
+				exynos4210_get_rate_mpll);
+}
+#else
+void __init exynos4_of_clk_init(void)
+{
+}
+#endif
+
+/* Exynos4210 specific clock registration */
+void __init exynos4210_clk_init(void)
+{
+	if (of_have_populated_dt()) {
+		exynos4_of_clk_init();
+		goto disp_rates;
+	}
+
+	/* exynos4210 specific fix up for group1_parents */
+	group1_parents[4] = "sclk_usbphy1";
+
+	samsung_clk_set_ctrl_base(S5P_VA_CMU);
+	exynos4_clk_init();
+	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
+		NULL, exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
+
+	samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+			ARRAY_SIZE(exynos4210_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4210_mux_clks,
+			ARRAY_SIZE(exynos4210_mux_clks));
+
+disp_rates:
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
+
+/*
+ * Exynos4x12 Specific Clocks
+ */
+
+static const char *exynos4x12_mout_vpll_parents[] __initdata = {
+		"fin_pll", "fout_vpll", };
+
+/* Exynos4x12 specific mux clocks */
+static struct samsung_mux_clock exynos4x12_mux_clks[] = {
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_DMC, 12, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4x12_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+};
+
+static unsigned long exynos4x12_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
+}
+
+static unsigned long exynos4x12_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
+}
+
+static unsigned long exynos4x12_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1));
+}
+
+static unsigned long exynos4x12_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1));
+}
+
+/* Exynos4x12 specific clock registeration */
+void __init exynos4x12_clk_init(void)
+{
+	exynos4_clk_init();
+
+	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_vpll);
+
+	samsung_clk_register_mux(exynos4x12_mux_clks,
+			ARRAY_SIZE(exynos4x12_mux_clks));
+
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
@ 2012-10-07 17:10   ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

For legacy Exynos4 platforms, the available clocks are statically
listed and then registered using the common clock framework. On device
tree enabled exynos platfotms, the device tree is searched and all
clock nodes found are registered. Support for Exynos4210 and
Exynos4x12 platforms is included.

Cc: Mike Turquette <mturquette@ti.com>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 drivers/clk/samsung/Makefile      |    1 +
 drivers/clk/samsung/clk-exynos4.c |  647 +++++++++++++++++++++++++++++++++++++
 2 files changed, 648 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/samsung/clk-exynos4.c

diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 3f926b0..69487f7 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
+obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644
index 0000000..e74b004
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2012 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 Exynos4 platforms
+ * ToDo: Remove all static instantiation of clocks after migrating all Exynos4
+ *	 based boards to use device tree support.
+*/
+
+#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 <plat/pll.h>
+#include <plat/cpu.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+#include <plat/map-s5p.h>
+#include "clk.h"
+
+#define EXYNOS4_OP_MODE		(S5P_VA_CHIPID + 8)
+
+/* base address of io remapped clock controller register space */
+static	void __iomem *clk_base;
+
+static const char *pll_parent_names[] __initdata = { "fin_pll" };
+static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
+static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
+static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
+static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
+
+static const char *sclk_ampll_parents[] __initdata = {
+		"mout_mpll", "sclk_apll", };
+
+static const char *sclk_evpll_parents[] __initdata = {
+		"mout_epll", "mout_vpll", };
+
+static const char *mout_core_parents[] __initdata = {
+		"mout_apll", "mout_mpll", };
+
+static const char *mout_mfc_parents[] __initdata = {
+		"mout_mfc0", "mout_mfc1", };
+
+static const char *mout_dac_parents[] __initdata = {
+		"mout_vpll", "sclk_hdmiphy", };
+
+static const char *mout_hdmi_parents[] __initdata = {
+		"sclk_pixel", "sclk_hdmiphy", };
+
+static const char *mout_mixer_parents[] __initdata = {
+		"sclk_dac", "sclk_hdmi", };
+
+static const char *group1_parents[] __initdata = {
+		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+		"none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
+		"mout_vpll" };
+
+static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+	FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+	FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+static struct samsung_mux_clock exynos4_mux_clks[] = {
+	MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
+			EXYNOS4_OP_MODE, 0, 1, 0),
+	MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 0, 1, 0),
+	MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
+	MUXCLK(NULL, "mout_core", mout_core_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
+	MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
+	MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
+	MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
+	MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
+	MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
+	MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
+	MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
+	MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
+	MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
+	MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
+	MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
+	MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
+			EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
+	MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
+	MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 0, 1, 0),
+	MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 4, 1, 0),
+	MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
+			EXYNOS4_CLKSRC_MFC, 8, 1, 0),
+	MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 24, 4, 0),
+	MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 28, 4, 0),
+	MUXCLK(NULL, "mout_cam0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 16, 4, 0),
+	MUXCLK(NULL, "mout_cam1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 20, 4, 0),
+	MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 0, 4, 0),
+	MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 4, 4, 0),
+	MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 8, 4, 0),
+	MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
+			EXYNOS4_CLKSRC_CAM, 12, 4, 0),
+	MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
+			EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
+	MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
+			EXYNOS4_CLKSRC_TV, 8, 1, 0),
+	MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
+			EXYNOS4_CLKSRC_TV, 0, 1, 0),
+	MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
+			EXYNOS4_CLKSRC_TV, 4, 1, 0),
+};
+
+static struct samsung_div_clock exynos4_div_clks[] = {
+	DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
+			EXYNOS4_CLKDIV_CPU, 24, 3, 0),
+	DIVCLK(NULL, "div_core", "mout_core", 0,
+			EXYNOS4_CLKDIV_CPU, 0, 3, 0),
+	DIVCLK(NULL, "armclk", "div_core", 0,
+			EXYNOS4_CLKDIV_CPU, 28, 3, 0),
+	DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
+			EXYNOS4_CLKDIV_TOP, 0, 3, 0),
+	DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
+			EXYNOS4_CLKDIV_TOP, 4, 4, 0),
+	DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
+			EXYNOS4_CLKDIV_TOP, 8, 3, 0),
+	DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
+			EXYNOS4_CLKDIV_TOP, 12, 3, 0),
+	DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
+			EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
+	DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
+			EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
+	DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
+			EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
+	DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
+			EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
+			EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
+			EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
+	DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
+			EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
+	DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
+			EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
+	DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
+			EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
+	DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
+			EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
+	DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
+			EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
+	DIVCLK(NULL, "div_sata", "mout_sata", 0,
+			EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
+	DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
+			EXYNOS4_CLKDIV_MFC, 0, 4, 0),
+	DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
+			EXYNOS4_CLKDIV_CAM, 24, 4, 0),
+	DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
+			EXYNOS4_CLKDIV_CAM, 28, 4, 0),
+	DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
+			EXYNOS4_CLKDIV_CAM, 16, 4, 0),
+	DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
+			EXYNOS4_CLKDIV_CAM, 20, 4, 0),
+	DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
+			EXYNOS4_CLKDIV_CAM, 0, 4, 0),
+	DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
+			EXYNOS4_CLKDIV_CAM, 4, 4, 0),
+	DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
+			EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
+	DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
+			EXYNOS4_CLKDIV_TV, 0, 4, 0),
+};
+
+struct samsung_gate_clock exynos4_gate_clks[] = {
+	GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
+	GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
+	GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
+	GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
+	GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
+	GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
+	GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
+	GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
+			EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
+	GATECLK(NULL, "timers", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
+	GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
+	GATECLK(NULL, "jpeg", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
+	GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
+	GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
+	GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
+	GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
+	GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
+	GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
+	GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
+	GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
+	GATECLK(NULL, "dwmmc", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
+	GATECLK("s5p-sdo", "dac", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 2, NULL),
+	GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 1, NULL),
+	GATECLK("s5p-mixer", "vp", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 0, NULL),
+	GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 3, NULL),
+	GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
+			S5P_HDMI_PHY_CONTROL, 0, NULL),
+	GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
+			S5P_DAC_PHY_CONTROL, 0, NULL),
+	GATECLK(NULL, "adc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
+	GATECLK(NULL, "keypad", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
+	GATECLK(NULL, "rtc", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
+	GATECLK(NULL, "watchdog", "aclk_100", 0,
+			EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
+	GATECLK(NULL, "usbhost", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
+	GATECLK(NULL, "otg", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
+	GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
+	GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
+	GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
+	GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
+	GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
+	GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
+	GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
+	GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
+	GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
+	GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
+	GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
+	GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
+	GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
+	GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
+	GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
+	GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
+	GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
+			EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
+			EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
+	GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
+	GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
+	GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
+			EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
+	GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
+			EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
+	GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
+	GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
+	GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
+	GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
+	GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
+			EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
+	GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
+	GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
+	GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
+	GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
+	GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
+	GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
+	GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
+	GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
+			EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
+	GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
+			EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
+};
+
+/* register clock common to all Exynos4 platforms */
+void __init exynos4_clk_init(void)
+{
+	samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+			ARRAY_SIZE(exynos4_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4_mux_clks,
+			ARRAY_SIZE(exynos4_mux_clks));
+	samsung_clk_register_div(exynos4_div_clks,
+			ARRAY_SIZE(exynos4_div_clks));
+	samsung_clk_register_gate(exynos4_gate_clks,
+			ARRAY_SIZE(exynos4_gate_clks));
+}
+
+/*
+ * Exynos4210 Specific Clocks
+ */
+
+static const char *exynos4210_vpll_parent_names[] __initdata = {
+		"mout_vpll_src" };
+static const char *mout_vpll_src_parents[] __initdata = {
+		"fin_pll", "sclk_hdmi24m" };
+static const char *exynos4210_mout_vpll_parents[] __initdata = {
+		"mout_vpll_src", "fout_vpll", };
+
+/* Exynos4210 specific fixed rate clocks */
+static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
+	FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* Exynos4210 specific mux-type clocks */
+static struct samsung_mux_clock exynos4210_mux_clks[] = {
+	MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
+			EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_CPU, 8, 1, 0),
+};
+
+static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_APLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll45xx(xtal_rate,
+		__raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
+}
+
+static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
+}
+
+static unsigned long exynos4210_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
+}
+
+static u32 exynos4_vpll_div[][8] = {
+	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
+	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
+};
+
+static int exynos4210_vpll_set_rate(unsigned long rate)
+{
+	unsigned int vpll_con0, vpll_con1 = 0;
+	unsigned int i;
+
+	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
+	vpll_con0 &= ~(0x1 << 27 |					\
+			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
+			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
+			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
+
+	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
+	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
+			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
+			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
+		if (exynos4_vpll_div[i][0] == rate) {
+			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
+			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
+			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
+		pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
+		return -EINVAL;
+	}
+
+	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
+	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
+
+	/* Wait for VPLL lock */
+	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
+		continue;
+
+	return 0;
+}
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock",
+		.data = of_fixed_clk_setup, },
+	{ .compatible = "samsung,clock-mux",
+		.data = samsung_of_clk_register_mux, },
+	{ .compatible = "samsung,clock-pll",
+		.data = samsung_of_clk_register_pll, },
+	{ .compatible = "samsung,clock-div",
+		.data = samsung_of_clk_register_div, },
+	{ .compatible = "samsung,clock-gate",
+		.data = samsung_of_clk_register_gate, },
+	{},
+};
+
+#ifdef CONFIG_OF
+void __init exynos4_of_clk_init(void)
+{
+	struct device_node *np;
+	struct clk *clk;
+
+	np = of_find_compatible_node(NULL, NULL, "samsung,exynos4-clock-ctrl");
+	if (!np) {
+		pr_err("%s: clock controller node not found\n", __func__);
+		return;
+	}
+
+	clk_base = of_iomap(np, 0);
+	WARN(!clk_base, "unable to map clocks registers\n");
+
+	samsung_clk_set_ctrl_base(clk_base);
+	samsung_clk_set_finpll_reg(EXYNOS4_OP_MODE);
+	of_clk_init(clk_match);
+
+	clk = clk_get(NULL, "fout_apll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_apll);
+	clk = clk_get(NULL, "fout_mpll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_mpll);
+	clk = clk_get(NULL, "fout_epll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_epll);
+	clk = clk_get(NULL, "fout_vpll");
+	samsung_pll_clk_set_cb(clk, exynos4210_vpll_set_rate,
+				exynos4210_get_rate_mpll);
+}
+#else
+void __init exynos4_of_clk_init(void)
+{
+}
+#endif
+
+/* Exynos4210 specific clock registration */
+void __init exynos4210_clk_init(void)
+{
+	if (of_have_populated_dt()) {
+		exynos4_of_clk_init();
+		goto disp_rates;
+	}
+
+	/* exynos4210 specific fix up for group1_parents */
+	group1_parents[4] = "sclk_usbphy1";
+
+	samsung_clk_set_ctrl_base(S5P_VA_CMU);
+	exynos4_clk_init();
+	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
+		NULL, exynos4210_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
+		NULL, exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
+
+	samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+			ARRAY_SIZE(exynos4210_fixed_rate_clks));
+	samsung_clk_register_mux(exynos4210_mux_clks,
+			ARRAY_SIZE(exynos4210_mux_clks));
+
+disp_rates:
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
+
+/*
+ * Exynos4x12 Specific Clocks
+ */
+
+static const char *exynos4x12_mout_vpll_parents[] __initdata = {
+		"fin_pll", "fout_vpll", };
+
+/* Exynos4x12 specific mux clocks */
+static struct samsung_mux_clock exynos4x12_mux_clks[] = {
+	MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
+			EXYNOS4_CLKSRC_DMC, 12, 1, 0),
+	MUXCLK(NULL, "mout_vpll", exynos4x12_mout_vpll_parents, 0,
+			EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
+};
+
+static unsigned long exynos4x12_get_rate_apll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
+}
+
+static unsigned long exynos4x12_get_rate_mpll(unsigned long xtal_rate)
+{
+	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
+}
+
+static unsigned long exynos4x12_get_rate_epll(unsigned long xtal_rate)
+{
+	return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
+		__raw_readl(EXYNOS4_EPLL_CON1));
+}
+
+static unsigned long exynos4x12_get_rate_vpll(unsigned long vpllsrc_rate)
+{
+	return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
+		__raw_readl(EXYNOS4_VPLL_CON1));
+}
+
+/* Exynos4x12 specific clock registeration */
+void __init exynos4x12_clk_init(void)
+{
+	exynos4_clk_init();
+
+	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_apll);
+	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_mpll);
+	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_epll);
+	samsung_clk_register_pll("fout_vpll", pll_parent_names, NULL,
+		NULL, exynos4x12_get_rate_vpll);
+
+	samsung_clk_register_mux(exynos4x12_mux_clks,
+			ARRAY_SIZE(exynos4x12_mux_clks));
+
+	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
+		_get_rate("fout_apll"), _get_rate("fout_mpll"),
+		_get_rate("fout_epll"), _get_rate("fout_vpll"));
+
+	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
+		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
+		_get_rate("aclk_200"), _get_rate("aclk_100"),
+		_get_rate("aclk_160"), _get_rate("aclk_133"));
+}
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 3/5] ARM: dts: Add Exynos4210 clock nodes
  2012-10-07 17:10 ` Thomas Abraham
@ 2012-10-07 17:10   ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

Add initial set of Exynos4210 clock nodes with which device tree enabled
boards based on Exynos4210 can be booted.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4-clock.dtsi |  389 ++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/exynos4.dtsi       |    1 +
 2 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4-clock.dtsi

diff --git a/arch/arm/boot/dts/exynos4-clock.dtsi b/arch/arm/boot/dts/exynos4-clock.dtsi
new file mode 100644
index 0000000..eb07613
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4-clock.dtsi
@@ -0,0 +1,389 @@
+/*
+ * Samsung's Exynos4210 SoC clock nodes
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *		www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/ {
+	clock_ctrl@10030000 {
+		compatible = "samsung,exynos4-clock-ctrl";
+		reg = <0x10030000 0x20000>;
+
+		xxti: xxti {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "xxti";
+			clock-frequency = <24000000>;
+		};
+
+		xusbxti: xusbxti {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "xusbxti";
+			clock-frequency = <24000000>;
+		};
+
+		sclk_hdmi24m: sclk_hdmi24m {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_hdmi24m";
+			clock-frequency = <24000000>;
+		};
+
+		sclk_hdmiphy: sclk_hdmiphy {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_hdmiphy";
+			clock-frequency = <27000000>;
+		};
+
+		sclk_usbphy0: sclk_usbphy0 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_usbphy0";
+			clock-frequency = <48000000>;
+		};
+
+		sclk_usbphy1: sclk_usbphy1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_usbphy1";
+			clock-frequency = <48000000>;
+		};
+
+		fin_pll: fin_pll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "fin_pll";
+			clocks = <&xxti>, <&xusbxti>;
+			reg-info = <0x00 0 1>;
+		};
+
+		fout_apll: fout_apll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_apll";
+			clocks = <&fin_pll>;
+		};
+
+		fout_mpll: fout_mpll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_mpll";
+			clocks = <&fin_pll>;
+		};
+
+		fout_epll: fout_epll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_epll";
+			clocks = <&fin_pll>;
+		};
+
+		mout_epll: mout_epll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_epll";
+			clocks = <&fin_pll>, <&fout_epll>;
+			reg-info = <0xc210 8 1>;
+		};
+
+		mout_vpll_src: mout_vpll_src {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_vpll_src";
+			clocks = <&fin_pll>, <&sclk_hdmi24m>;
+			reg-info = <0xc214 0 1>;
+		};
+
+		fout_vpll: fout_vpll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_vpll";
+			clocks = <&mout_vpll_src>;
+		};
+
+		mout_vpll: mout_vpll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_vpll";
+			clocks = <&mout_vpll_src>, <&fout_vpll>;
+			reg-info = <0xc210 8 1>;
+		};
+
+		mout_apll: mout_apll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_apll";
+			clocks = <&fin_pll>, <&fout_apll>;
+			reg-info = <0x14200 0 1>;
+		};
+
+		mout_mpll: mout_mpll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_mpll";
+			clocks = <&fin_pll>, <&fout_mpll>;
+			reg-info = <0x14200 8 1>;
+		};
+
+		sclk_apll: sclk_apll {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_apll";
+			clocks = <&mout_apll>;
+			reg-info = <0x14500 24 3>;
+		};
+
+		mout_core: mout_core {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_core";
+			clocks = <&mout_apll>, <&mout_mpll>;
+			reg-info = <0x14200 16 1>;
+		};
+
+		div_core: div_core {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "div_core";
+			clocks = <&mout_core>;
+			reg-info = <0x14500 0 3>;
+		};
+
+		armclk: armclk {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "armclk";
+			clocks = <&div_core>;
+			reg-info = <0x14500 28 3>;
+		};
+
+		mout_aclk_200: mout_aclk_200 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_200";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 12 1>;
+		};
+
+		mout_aclk_100: mout_aclk_100 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_100";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 16 1>;
+		};
+
+		mout_aclk_160: mout_aclk_160 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_160";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 20 1>;
+		};
+
+		mout_aclk_133: mout_aclk_133 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_133";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 24 1>;
+		};
+
+		aclk_200: aclk_200 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_200";
+			clocks = <&mout_aclk_200>;
+			reg-info = <0xc510 0 3>;
+		};
+
+		aclk_100: aclk_100 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_100";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc510 4 3>;
+		};
+
+		aclk_160: aclk_160 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_160";
+			clocks = <&mout_aclk_160>;
+			reg-info = <0xc510 8 3>;
+		};
+
+		aclk_133: aclk_133 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_133";
+			clocks = <&mout_aclk_133>;
+			reg-info = <0xc510 12 3>;
+		};
+
+		uart0: uart0 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart0";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 0>;
+		};
+
+		uart1: uart1 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart1";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 1>;
+		};
+
+		uart2: uart2 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart2";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 2>;
+		};
+
+		uart3: uart3 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart3";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 3>;
+		};
+
+		uart4: uart4 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart4";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 4>;
+		};
+
+		uart5: uart5 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart5";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 5>;
+		};
+
+		mout_uart0: mout_uart0 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart0";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 0 4>;
+		};
+
+		mout_uart1: mout_uart1 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart1";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 4 4>;
+		};
+
+		mout_uart2: mout_uart2 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart2";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 8 4>;
+		};
+
+		mout_uart3: mout_uart3 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart3";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 12 4>;
+		};
+
+		dout_uart0: dout_uart0 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart0";
+			clocks = <&mout_uart0>;
+			reg-info = <0xc550 0 4>;
+		};
+
+		dout_uart1: dout_uart1 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart1";
+			clocks = <&mout_uart1>;
+			reg-info = <0xc550 4 4>;
+		};
+
+		dout_uart2: dout_uart2 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart2";
+			clocks = <&mout_uart2>;
+			reg-info = <0xc550 8 4>;
+		};
+
+		dout_uart3: dout_uart3 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart3";
+			clocks = <&mout_uart3>;
+			reg-info = <0xc550 12 4>;
+		};
+
+		sclk_uart0: sclk_uart0 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart0";
+			clocks = <&dout_uart0>;
+			reg-info = <0xc350 0>;
+		};
+
+		sclk_uart1: sclk_uart1 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart1";
+			clocks = <&dout_uart1>;
+			reg-info = <0xc350 4>;
+		};
+
+		sclk_uart2: sclk_uart2 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart2";
+			clocks = <&dout_uart2>;
+			reg-info = <0xc350 8>;
+		};
+
+		sclk_uart3: sclk_uart3 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart3";
+			clocks = <&dout_uart3>;
+			reg-info = <0xc350 12>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index a26c3dd..1c923d3 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -20,6 +20,7 @@
  */
 
 /include/ "skeleton.dtsi"
+/include/ "exynos4-clock.dtsi"
 
 / {
 	interrupt-parent = <&gic>;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 3/5] ARM: dts: Add Exynos4210 clock nodes
@ 2012-10-07 17:10   ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

Add initial set of Exynos4210 clock nodes with which device tree enabled
boards based on Exynos4210 can be booted.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4-clock.dtsi |  389 ++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/exynos4.dtsi       |    1 +
 2 files changed, 390 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/dts/exynos4-clock.dtsi

diff --git a/arch/arm/boot/dts/exynos4-clock.dtsi b/arch/arm/boot/dts/exynos4-clock.dtsi
new file mode 100644
index 0000000..eb07613
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4-clock.dtsi
@@ -0,0 +1,389 @@
+/*
+ * Samsung's Exynos4210 SoC clock nodes
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *		www.linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/ {
+	clock_ctrl at 10030000 {
+		compatible = "samsung,exynos4-clock-ctrl";
+		reg = <0x10030000 0x20000>;
+
+		xxti: xxti {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "xxti";
+			clock-frequency = <24000000>;
+		};
+
+		xusbxti: xusbxti {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "xusbxti";
+			clock-frequency = <24000000>;
+		};
+
+		sclk_hdmi24m: sclk_hdmi24m {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_hdmi24m";
+			clock-frequency = <24000000>;
+		};
+
+		sclk_hdmiphy: sclk_hdmiphy {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_hdmiphy";
+			clock-frequency = <27000000>;
+		};
+
+		sclk_usbphy0: sclk_usbphy0 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_usbphy0";
+			clock-frequency = <48000000>;
+		};
+
+		sclk_usbphy1: sclk_usbphy1 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_usbphy1";
+			clock-frequency = <48000000>;
+		};
+
+		fin_pll: fin_pll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "fin_pll";
+			clocks = <&xxti>, <&xusbxti>;
+			reg-info = <0x00 0 1>;
+		};
+
+		fout_apll: fout_apll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_apll";
+			clocks = <&fin_pll>;
+		};
+
+		fout_mpll: fout_mpll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_mpll";
+			clocks = <&fin_pll>;
+		};
+
+		fout_epll: fout_epll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_epll";
+			clocks = <&fin_pll>;
+		};
+
+		mout_epll: mout_epll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_epll";
+			clocks = <&fin_pll>, <&fout_epll>;
+			reg-info = <0xc210 8 1>;
+		};
+
+		mout_vpll_src: mout_vpll_src {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_vpll_src";
+			clocks = <&fin_pll>, <&sclk_hdmi24m>;
+			reg-info = <0xc214 0 1>;
+		};
+
+		fout_vpll: fout_vpll {
+			compatible = "samsung,clock-pll";
+			#clock-cells = <0>;
+			clock-output-names = "fout_vpll";
+			clocks = <&mout_vpll_src>;
+		};
+
+		mout_vpll: mout_vpll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_vpll";
+			clocks = <&mout_vpll_src>, <&fout_vpll>;
+			reg-info = <0xc210 8 1>;
+		};
+
+		mout_apll: mout_apll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_apll";
+			clocks = <&fin_pll>, <&fout_apll>;
+			reg-info = <0x14200 0 1>;
+		};
+
+		mout_mpll: mout_mpll {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_mpll";
+			clocks = <&fin_pll>, <&fout_mpll>;
+			reg-info = <0x14200 8 1>;
+		};
+
+		sclk_apll: sclk_apll {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_apll";
+			clocks = <&mout_apll>;
+			reg-info = <0x14500 24 3>;
+		};
+
+		mout_core: mout_core {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_core";
+			clocks = <&mout_apll>, <&mout_mpll>;
+			reg-info = <0x14200 16 1>;
+		};
+
+		div_core: div_core {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "div_core";
+			clocks = <&mout_core>;
+			reg-info = <0x14500 0 3>;
+		};
+
+		armclk: armclk {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "armclk";
+			clocks = <&div_core>;
+			reg-info = <0x14500 28 3>;
+		};
+
+		mout_aclk_200: mout_aclk_200 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_200";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 12 1>;
+		};
+
+		mout_aclk_100: mout_aclk_100 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_100";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 16 1>;
+		};
+
+		mout_aclk_160: mout_aclk_160 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_160";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 20 1>;
+		};
+
+		mout_aclk_133: mout_aclk_133 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_aclk_133";
+			clocks = <&mout_mpll>, <&sclk_apll>;
+			reg-info = <0xc210 24 1>;
+		};
+
+		aclk_200: aclk_200 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_200";
+			clocks = <&mout_aclk_200>;
+			reg-info = <0xc510 0 3>;
+		};
+
+		aclk_100: aclk_100 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_100";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc510 4 3>;
+		};
+
+		aclk_160: aclk_160 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_160";
+			clocks = <&mout_aclk_160>;
+			reg-info = <0xc510 8 3>;
+		};
+
+		aclk_133: aclk_133 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "aclk_133";
+			clocks = <&mout_aclk_133>;
+			reg-info = <0xc510 12 3>;
+		};
+
+		uart0: uart0 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart0";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 0>;
+		};
+
+		uart1: uart1 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart1";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 1>;
+		};
+
+		uart2: uart2 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart2";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 2>;
+		};
+
+		uart3: uart3 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart3";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 3>;
+		};
+
+		uart4: uart4 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart4";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 4>;
+		};
+
+		uart5: uart5 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "uart5";
+			clocks = <&mout_aclk_100>;
+			reg-info = <0xc94c 5>;
+		};
+
+		mout_uart0: mout_uart0 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart0";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 0 4>;
+		};
+
+		mout_uart1: mout_uart1 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart1";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 4 4>;
+		};
+
+		mout_uart2: mout_uart2 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart2";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 8 4>;
+		};
+
+		mout_uart3: mout_uart3 {
+			compatible = "samsung,clock-mux";
+			#clock-cells = <0>;
+			clock-output-names = "mout_uart3";
+			clocks = <&xxti>, <&xusbxti>, <&sclk_hdmi24m>,
+				 <&sclk_usbphy0>, <&sclk_usbphy1>,
+				 <&sclk_hdmiphy>, <&mout_mpll>, <&mout_epll>,
+				 <&mout_vpll>;
+			reg-info = <0xc250 12 4>;
+		};
+
+		dout_uart0: dout_uart0 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart0";
+			clocks = <&mout_uart0>;
+			reg-info = <0xc550 0 4>;
+		};
+
+		dout_uart1: dout_uart1 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart1";
+			clocks = <&mout_uart1>;
+			reg-info = <0xc550 4 4>;
+		};
+
+		dout_uart2: dout_uart2 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart2";
+			clocks = <&mout_uart2>;
+			reg-info = <0xc550 8 4>;
+		};
+
+		dout_uart3: dout_uart3 {
+			compatible = "samsung,clock-div";
+			#clock-cells = <0>;
+			clock-output-names = "dout_uart3";
+			clocks = <&mout_uart3>;
+			reg-info = <0xc550 12 4>;
+		};
+
+		sclk_uart0: sclk_uart0 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart0";
+			clocks = <&dout_uart0>;
+			reg-info = <0xc350 0>;
+		};
+
+		sclk_uart1: sclk_uart1 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart1";
+			clocks = <&dout_uart1>;
+			reg-info = <0xc350 4>;
+		};
+
+		sclk_uart2: sclk_uart2 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart2";
+			clocks = <&dout_uart2>;
+			reg-info = <0xc350 8>;
+		};
+
+		sclk_uart3: sclk_uart3 {
+			compatible = "samsung,clock-gate";
+			#clock-cells = <0>;
+			clock-output-names = "sclk_uart3";
+			clocks = <&dout_uart3>;
+			reg-info = <0xc350 12>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index a26c3dd..1c923d3 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -20,6 +20,7 @@
  */
 
 /include/ "skeleton.dtsi"
+/include/ "exynos4-clock.dtsi"
 
 / {
 	interrupt-parent = <&gic>;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 4/5] ARM: dts: list the clock providers for serial ports
  2012-10-07 17:10 ` Thomas Abraham
@ 2012-10-07 17:10   ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

Add the list of clock providers in the serial port device nodes.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4.dtsi |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 1c923d3..eb1cdda 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -98,6 +98,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
 		interrupts = <0 52 0>;
+		clocks = <&uart0>, <&sclk_uart0>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -105,6 +107,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
 		interrupts = <0 53 0>;
+		clocks = <&uart1>, <&sclk_uart1>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -112,6 +116,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
 		interrupts = <0 54 0>;
+		clocks = <&uart2>, <&sclk_uart2>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -119,6 +125,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
 		interrupts = <0 55 0>;
+		clocks = <&uart3>, <&sclk_uart3>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 4/5] ARM: dts: list the clock providers for serial ports
@ 2012-10-07 17:10   ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

Add the list of clock providers in the serial port device nodes.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/boot/dts/exynos4.dtsi |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 1c923d3..eb1cdda 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -98,6 +98,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
 		interrupts = <0 52 0>;
+		clocks = <&uart0>, <&sclk_uart0>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -105,6 +107,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
 		interrupts = <0 53 0>;
+		clocks = <&uart1>, <&sclk_uart1>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -112,6 +116,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
 		interrupts = <0 54 0>;
+		clocks = <&uart2>, <&sclk_uart2>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
@@ -119,6 +125,8 @@
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
 		interrupts = <0 55 0>;
+		clocks = <&uart3>, <&sclk_uart3>;
+		clock-names = "uart", "clk_uart_baud0";
 		status = "disabled";
 	};
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
  2012-10-07 17:10 ` Thomas Abraham
@ 2012-10-07 17:10   ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki,
	mturquette, mturquette

Remove Samsung specific clock support in Exynos4 and migrate to using
common clock framework.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/Kconfig               |    1 +
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.c       | 1603 ----------------------------
 arch/arm/mach-exynos/clock-exynos4.h       |   35 -
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
 arch/arm/mach-exynos/common.c              |   22 +-
 arch/arm/mach-exynos/common.h              |    3 +
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 arch/arm/mach-exynos/mct.c                 |   11 +-
 arch/arm/plat-samsung/Kconfig              |    4 +-
 17 files changed, 18 insertions(+), 2051 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 4372075..3c80eba 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -15,6 +15,7 @@ config ARCH_EXYNOS4
 	bool "SAMSUNG EXYNOS4"
 	default y
 	select HAVE_SMP
+	select COMMON_CLK
 	select MIGHT_HAVE_CACHE_L2X0
 	help
 	  Samsung EXYNOS4 SoCs based systems
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024..ad66c9f4 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,10 +13,7 @@ obj-				:=
 # Core
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= common.o
-obj-$(CONFIG_ARCH_EXYNOS4)	+= clock-exynos4.o
 obj-$(CONFIG_ARCH_EXYNOS5)	+= clock-exynos5.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
 
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644
index 6a45c9a..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ /dev/null
@@ -1,1603 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
-	SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TV),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
-	SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
-	SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
-}
-
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos4_clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources = &clk_src_apll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &exynos4_clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources = &clk_src_epll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
-	.clk	= {
-		.name		= "mout_mpll",
-	},
-	.sources = &clk_src_mpll,
-
-	/* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
-	[0] = &exynos4_clk_mout_apll.clk,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
-	.sources	= exynos4_clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-	},
-	.sources = &exynos4_clkset_moutcore,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &exynos4_clk_moutcore.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
-	.sources	= exynos4_clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-	},
-	.sources = &exynos4_clkset_mout_corebus,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.parent		= &exynos4_clk_sclk_dmc.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.parent		= &exynos4_clk_aclk_cored.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &exynos4_clk_aclk_acp.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
-	.sources	= exynos4_clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
-	.sources	= exynos4_clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos4_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_vpllsrc,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
-	[0] = &exynos4_clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
-	.sources	= exynos4_clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources = &exynos4_clkset_sclk_vpll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "jpeg",
-		.id		= 0,
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "tsi",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dwmmc",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "onenand",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "nfcon",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "dac",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "mixer",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "vp",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hdmi",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "dacphy",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_dac_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 23),
-	}, {
-		.name		= "slimbus",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "spdif",
-		.devname	= "samsung-spdif",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(tv, 2),
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(jpeg, 3),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(rot, 4),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc0, 5),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc1, 6),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc2, 7),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc3, 8),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd0, 10),
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}
-};
-
-static struct clk exynos4_init_clocks_on[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk exynos4_clk_pdma0 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.0",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.1",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.2",
-	.enable		= exynos4_clk_ip_image_ctrl,
-	.ctrlbit	= ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
-	.name		= "fimd",
-	.devname	= "exynos4-fb.0",
-	.enable		= exynos4_clk_ip_lcd0_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &exynos4_clk_sclk_hdmi27m,
-	[3] = &exynos4_clk_sclk_usbphy0,
-	[4] = &exynos4_clk_sclk_usbphy1,
-	[5] = &exynos4_clk_sclk_hdmiphy,
-	[6] = &exynos4_clk_mout_mpll.clk,
-	[7] = &exynos4_clk_mout_epll.clk,
-	[8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
-	.sources	= exynos4_clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
-	.sources	= exynos4_clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
-	.sources	= exynos4_clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
-	.sources	= exynos4_clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources = &exynos4_clkset_mout_mfc0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
-	.sources	= exynos4_clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources = &exynos4_clkset_mout_mfc1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
-	[0] = &exynos4_clk_mout_mfc0.clk,
-	[1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
-	.sources	= exynos4_clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
-	[0] = &exynos4_clk_sclk_vpll.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
-	.sources	= exynos4_clkset_sclk_dac_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
-	.clk		= {
-		.name		= "sclk_dac",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_sclk_dac,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
-	.clk		= {
-		.name		= "sclk_pixel",
-		.parent		= &exynos4_clk_sclk_vpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
-	[0] = &exynos4_clk_sclk_pixel.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
-	.sources	= exynos4_clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
-	.clk		= {
-		.name		= "sclk_hdmi",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_sclk_hdmi,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
-	[0] = &exynos4_clk_sclk_dac.clk,
-	[1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
-	.sources	= exynos4_clkset_sclk_mixer_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
-	.clk	= {
-		.name		= "sclk_mixer",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_sclk_mixer,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
-	&exynos4_clk_sclk_dac,
-	&exynos4_clk_sclk_pixel,
-	&exynos4_clk_sclk_hdmi,
-	&exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
-	.clk	= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
-	.clk	= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
-	.clk	= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
-	.clk	= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_pwm",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.2",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.3",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.0",
-			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &exynos4_clkset_mout_mfc,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dwmmc",
-			.parent		= &exynos4_clk_dout_mmc4.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.0",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.1",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.2",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.3",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_dout_mmc0.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_dout_mmc1.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_dout_mmc2.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_dout_mmc3.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos4_clk_mdout_spi0.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos4_clk_mdout_spi1.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos4_clk_mdout_spi2.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
-	&exynos4_clk_mout_apll,
-	&exynos4_clk_sclk_apll,
-	&exynos4_clk_mout_epll,
-	&exynos4_clk_mout_mpll,
-	&exynos4_clk_moutcore,
-	&exynos4_clk_coreclk,
-	&exynos4_clk_armclk,
-	&exynos4_clk_aclk_corem0,
-	&exynos4_clk_aclk_cores,
-	&exynos4_clk_aclk_corem1,
-	&exynos4_clk_periphclk,
-	&exynos4_clk_mout_corebus,
-	&exynos4_clk_sclk_dmc,
-	&exynos4_clk_aclk_cored,
-	&exynos4_clk_aclk_corep,
-	&exynos4_clk_aclk_acp,
-	&exynos4_clk_pclk_acp,
-	&exynos4_clk_vpllsrc,
-	&exynos4_clk_sclk_vpll,
-	&exynos4_clk_aclk_200,
-	&exynos4_clk_aclk_100,
-	&exynos4_clk_aclk_160,
-	&exynos4_clk_aclk_133,
-	&exynos4_clk_dout_mmc0,
-	&exynos4_clk_dout_mmc1,
-	&exynos4_clk_dout_mmc2,
-	&exynos4_clk_dout_mmc3,
-	&exynos4_clk_dout_mmc4,
-	&exynos4_clk_mout_mfc0,
-	&exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
-	&exynos4_clk_pdma0,
-	&exynos4_clk_pdma1,
-	&exynos4_clk_mdma1,
-	&exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
-	&exynos4_clk_sclk_uart0,
-	&exynos4_clk_sclk_uart1,
-	&exynos4_clk_sclk_uart2,
-	&exynos4_clk_sclk_uart3,
-	&exynos4_clk_sclk_mmc0,
-	&exynos4_clk_sclk_mmc1,
-	&exynos4_clk_sclk_mmc2,
-	&exynos4_clk_sclk_mmc3,
-	&exynos4_clk_sclk_spi0,
-	&exynos4_clk_sclk_spi1,
-	&exynos4_clk_sclk_spi2,
-	&exynos4_clk_mdout_spi0,
-	&exynos4_clk_mdout_spi1,
-	&exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
-	CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
-	CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
-	CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
-	CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-	CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-	CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-	CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-	CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
-	CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
-	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-	CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-	CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-	CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
-	if (soc_is_exynos4210())
-		return s5p_get_pll45xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
-	else
-		return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-	.get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_vpll_div[][8] = {
-	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
-	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
-};
-
-static unsigned long exynos4_vpll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int vpll_con0, vpll_con1 = 0;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
-	vpll_con0 &= ~(0x1 << 27 |					\
-			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
-			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
-			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
-	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
-			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
-			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
-		if (exynos4_vpll_div[i][0] == rate) {
-			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
-	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
-	/* Wait for VPLL lock */
-	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
-		continue;
-
-	clk->rate = rate;
-	return 0;
-}
-
-static struct clk_ops exynos4_vpll_ops = {
-	.get_rate = exynos4_vpll_get_rate,
-	.set_rate = exynos4_vpll_set_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll = 0;
-	unsigned long mpll = 0;
-	unsigned long epll = 0;
-	unsigned long vpll = 0;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	if (soc_is_exynos4210()) {
-		apll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-		mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
-					pll_4508);
-		epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
-	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-		apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
-		mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
-		epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1));
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1));
-	} else {
-		/* nothing */
-	}
-
-	clk_fout_apll.ops = &exynos4_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.ops = &exynos4_vpll_ops;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&exynos4_clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&exynos4_clk_aclk_133.clk);
-
-	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrcs); ptr++)
-		s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
-	&exynos4_clk_sclk_hdmi27m,
-	&exynos4_clk_sclk_hdmiphy,
-	&exynos4_clk_sclk_usbphy0,
-	&exynos4_clk_sclk_usbphy1,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-	return 0;
-}
-
-static void exynos4_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-}
-
-#else
-#define exynos4_clock_suspend NULL
-#define exynos4_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4_clock_syscore_ops = {
-	.suspend	= exynos4_clock_suspend,
-	.resume		= exynos4_clock_resume,
-};
-
-void __init exynos4_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
-		s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
-		s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
-		s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
-	s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
-	s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
-		s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
-	s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
-	register_syscore_ops(&exynos4_clock_syscore_ops);
-	s3c24xx_register_clock(&dummy_apb_pclk);
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644
index bd12d5f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for exynos4 clock support
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_CLOCK_H
-#define __ASM_ARCH_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644
index fed4c26..0000000
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
-	/* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
-	[0] = &exynos4210_clk_mout_g2d0.clk,
-	[1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
-	.sources	= exynos4210_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_mout_corebus,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4210_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sataphy",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd1, 11),
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
-	return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
-	.suspend	= exynos4210_clock_suspend,
-	.resume		= exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
-	int ptr;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
-	exynos4_clk_mout_mpll.reg_src.shift = 8;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644
index 8fba0b5..0000000
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4212 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
-	.sources	= clk_src_mpll_user_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
-	.clk = {
-		.name		= "mout_mpll_user",
-	},
-	.sources	= &clk_src_mpll_user,
-	.reg_src	= { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
-	[0] = &exynos4x12_clk_mout_g2d0.clk,
-	[1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
-	.sources	= exynos4x12_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4x12_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (7 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME2,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.0",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.1",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 23),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
-	return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
-	.suspend	= exynos4212_clock_suspend,
-	.resume		= exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
-	int ptr;
-
-	/* usbphy1 is removed */
-	exynos4_clkset_group_list[4] = NULL;
-
-	/* mout_mpll_user is used */
-	exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
-	exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
-	exynos4_clk_mout_mpll.reg_src.shift = 12;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 715b690..fea1542 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -60,7 +60,6 @@ static const char name_exynos5250[] = "EXYNOS5250";
 
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
-static void exynos4_init_clocks(int xtal);
 static void exynos5_init_clocks(int xtal);
 static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 static int exynos_init(void);
@@ -70,7 +69,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4210_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4210,
@@ -78,7 +76,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4212_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4212,
@@ -86,7 +83,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4412_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4412,
@@ -368,31 +364,17 @@ static void __init exynos5_map_io(void)
 	s3c_i2c2_setname("s3c2440-i2c");
 }
 
-static void __init exynos4_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-
-	if (soc_is_exynos4210())
-		exynos4210_register_clocks();
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		exynos4212_register_clocks();
-
-	exynos4_register_clocks();
-	exynos4_setup_clocks();
-}
-
 static void __init exynos5_init_clocks(int xtal)
 {
 	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
 
+#ifndef CONFIG_COMMON_CLK
 	s3c24xx_register_baseclocks(xtal);
 	s5p_register_clocks(xtal);
 
 	exynos5_register_clocks();
 	exynos5_setup_clocks();
+#endif
 }
 
 #define COMBINER_ENABLE_SET	0x0
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index dac146d..7a4e0ea 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -22,6 +22,9 @@ void exynos4_restart(char mode, const char *cmd);
 void exynos5_restart(char mode, const char *cmd);
 void exynos_init_late(void);
 
+void exynos4210_clk_init(void);
+void exynos4x12_clk_init(void);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 3f37a5e..583c6a7 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -179,7 +179,6 @@ static void __init armlex4210_smsc911x_init(void)
 static void __init armlex4210_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(armlex4210_uartcfgs,
 			   ARRAY_SIZE(armlex4210_uartcfgs));
 }
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index e58d786..8f6687b 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -83,7 +83,6 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
 static void __init exynos4_dt_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos4_dt_machine_init(void)
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 480cd78f..9b7aa9d 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1338,7 +1338,6 @@ static struct platform_device *nuri_devices[] __initdata = {
 static void __init nuri_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 67b50bb..0d6b877 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -756,7 +756,6 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index 7a265d1..d1a7668 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -326,7 +326,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 static void __init smdk4x12_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index c15d223..ead65a2 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -376,7 +376,6 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 98d3ace..bd4d1f0 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -1100,7 +1100,6 @@ static struct platform_device *universal_devices[] __initdata = {
 static void __init universal_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..cc3805a 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -30,6 +30,8 @@
 #include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+
 #define TICK_BASE_CNT	1
 
 enum {
@@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 static void __init exynos4_timer_resources(void)
 {
 	struct clk *mct_clk;
-	mct_clk = clk_get(NULL, "xtal");
+	mct_clk = clk_get(NULL, "fin_pll");
 
 	clk_rate = clk_get_rate(mct_clk);
 
@@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
+#ifdef CONFIG_COMMON_CLK
+	if (soc_is_exynos4210())
+		exynos4210_clk_init();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4x12_clk_init();
+#endif
+
 	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
 		mct_int_type = MCT_INT_SPI;
 	else
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9c3b90c..35b4cb8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -26,7 +26,7 @@ config PLAT_S5P
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_GPIOLIB_4BIT
 	select PLAT_SAMSUNG
-	select SAMSUNG_CLKSRC
+	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_IRQ_VIC_TIMER
 	help
 	  Base platform code for Samsung's S5P series SoC.
@@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
 	  used by newer systems such as the S3C64XX.
 
 config S5P_CLOCK
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+	def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) && !COMMON_CLK)
 	help
 	  Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
@ 2012-10-07 17:10   ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-07 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

Remove Samsung specific clock support in Exynos4 and migrate to using
common clock framework.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos/Kconfig               |    1 +
 arch/arm/mach-exynos/Makefile              |    3 -
 arch/arm/mach-exynos/clock-exynos4.c       | 1603 ----------------------------
 arch/arm/mach-exynos/clock-exynos4.h       |   35 -
 arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
 arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
 arch/arm/mach-exynos/common.c              |   22 +-
 arch/arm/mach-exynos/common.h              |    3 +
 arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
 arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
 arch/arm/mach-exynos/mach-nuri.c           |    1 -
 arch/arm/mach-exynos/mach-origen.c         |    1 -
 arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
 arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
 arch/arm/mach-exynos/mach-universal_c210.c |    1 -
 arch/arm/mach-exynos/mct.c                 |   11 +-
 arch/arm/plat-samsung/Kconfig              |    4 +-
 17 files changed, 18 insertions(+), 2051 deletions(-)
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
 delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 4372075..3c80eba 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -15,6 +15,7 @@ config ARCH_EXYNOS4
 	bool "SAMSUNG EXYNOS4"
 	default y
 	select HAVE_SMP
+	select COMMON_CLK
 	select MIGHT_HAVE_CACHE_L2X0
 	help
 	  Samsung EXYNOS4 SoCs based systems
diff --git a/arch/arm/mach-exynos/Makefile b/arch/arm/mach-exynos/Makefile
index 9b58024..ad66c9f4 100644
--- a/arch/arm/mach-exynos/Makefile
+++ b/arch/arm/mach-exynos/Makefile
@@ -13,10 +13,7 @@ obj-				:=
 # Core
 
 obj-$(CONFIG_ARCH_EXYNOS)	+= common.o
-obj-$(CONFIG_ARCH_EXYNOS4)	+= clock-exynos4.o
 obj-$(CONFIG_ARCH_EXYNOS5)	+= clock-exynos5.o
-obj-$(CONFIG_CPU_EXYNOS4210)	+= clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212)	+= clock-exynos4212.o
 
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644
index 6a45c9a..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ /dev/null
@@ -1,1603 +0,0 @@
-/*
- * Copyright (c) 2010-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
-	SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
-	SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TV),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
-	SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
-	SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
-	SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
-	SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
-	SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
-	SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
-	SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
-	SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
-	SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
-	SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
-	SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.rate		= 27000000,
-};
-
-static struct clk exynos4_clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-};
-
-static struct clk dummy_apb_pclk = {
-	.name		= "apb_pclk",
-	.id		= -1,
-};
-
-static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, clk, enable);
-}
-
-static int exynos4_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-static int exynos4_clk_dac_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos4_clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-	},
-	.sources = &clk_src_apll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.parent		= &exynos4_clk_mout_apll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-	},
-	.sources = &clk_src_epll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
-	.clk	= {
-		.name		= "mout_mpll",
-	},
-	.sources = &clk_src_mpll,
-
-	/* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
-	[0] = &exynos4_clk_mout_apll.clk,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
-	.sources	= exynos4_clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-	},
-	.sources = &exynos4_clkset_moutcore,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.parent		= &exynos4_clk_moutcore.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.parent		= &exynos4_clk_coreclk.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
-	.sources	= exynos4_clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-	},
-	.sources = &exynos4_clkset_mout_corebus,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.parent		= &exynos4_clk_sclk_dmc.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.parent		= &exynos4_clk_aclk_cored.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.parent		= &exynos4_clk_mout_corebus.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.parent		= &exynos4_clk_aclk_acp.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
-	.sources	= exynos4_clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-	},
-	.sources = &exynos4_clkset_aclk,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
-	.sources	= exynos4_clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.enable		= exynos4_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_vpllsrc,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
-	[0] = &exynos4_clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
-	.sources	= exynos4_clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-	},
-	.sources = &exynos4_clkset_sclk_vpll,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.devname	= "s5p-mipi-csis.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "jpeg",
-		.id		= 0,
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.0",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.1",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.2",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.devname	= "exynos4-fimc.3",
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "tsi",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "dwmmc",
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "onenand",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "nfcon",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "dac",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "mixer",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "vp",
-		.devname	= "s5p-mixer",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hdmi",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "hdmiphy",
-		.devname	= "exynos4-hdmi",
-		.enable		= exynos4_clk_hdmiphy_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "dacphy",
-		.devname	= "s5p-sdo",
-		.enable		= exynos4_clk_dac_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "adc",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "keypad",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "rtc",
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.enable		= exynos4_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.devname	= "exynos4210-spi.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.devname	= "samsung-i2s.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 22),
-	}, {
-		.name		= "pcm",
-		.devname	= "samsung-pcm.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 23),
-	}, {
-		.name		= "slimbus",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 25),
-	}, {
-		.name		= "spdif",
-		.devname	= "samsung-spdif",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 26),
-	}, {
-		.name		= "ac97",
-		.devname	= "samsung-ac97",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "mfc",
-		.devname	= "s5p-mfc",
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.0",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.1",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.2",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.3",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.4",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.5",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.6",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-i2c.7",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "i2c",
-		.devname	= "s3c2440-hdmiphy-i2c",
-		.parent		= &exynos4_clk_aclk_100.clk,
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_r, 1),
-		.enable		= exynos4_clk_ip_mfc_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(tv, 2),
-		.enable		= exynos4_clk_ip_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(jpeg, 3),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(rot, 4),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc0, 5),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc1, 6),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc2, 7),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimc3, 8),
-		.enable		= exynos4_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd0, 10),
-		.enable		= exynos4_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}
-};
-
-static struct clk exynos4_init_clocks_on[] = {
-	{
-		.name		= "uart",
-		.devname	= "s5pv210-uart.0",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.1",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.2",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.3",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.4",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.devname	= "s5pv210-uart.5",
-		.enable		= exynos4_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk exynos4_clk_pdma0 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.0",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.1",
-	.enable		= exynos4_clk_ip_fsys_ctrl,
-	.ctrlbit	= (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
-	.name		= "dma",
-	.devname	= "dma-pl330.2",
-	.enable		= exynos4_clk_ip_image_ctrl,
-	.ctrlbit	= ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
-	.name		= "fimd",
-	.devname	= "exynos4-fb.0",
-	.enable		= exynos4_clk_ip_lcd0_ctrl,
-	.ctrlbit	= (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &exynos4_clk_sclk_hdmi27m,
-	[3] = &exynos4_clk_sclk_usbphy0,
-	[4] = &exynos4_clk_sclk_usbphy1,
-	[5] = &exynos4_clk_sclk_hdmiphy,
-	[6] = &exynos4_clk_mout_mpll.clk,
-	[7] = &exynos4_clk_mout_epll.clk,
-	[8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
-	.sources	= exynos4_clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
-	.sources	= exynos4_clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
-	.sources	= exynos4_clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
-	[0] = &exynos4_clk_mout_mpll.clk,
-	[1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
-	.sources	= exynos4_clkset_mout_mfc0_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
-	.clk	= {
-		.name		= "mout_mfc0",
-	},
-	.sources = &exynos4_clkset_mout_mfc0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
-	[0] = &exynos4_clk_mout_epll.clk,
-	[1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
-	.sources	= exynos4_clkset_mout_mfc1_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
-	.clk	= {
-		.name		= "mout_mfc1",
-	},
-	.sources = &exynos4_clkset_mout_mfc1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
-	[0] = &exynos4_clk_mout_mfc0.clk,
-	[1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
-	.sources	= exynos4_clkset_mout_mfc_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
-	[0] = &exynos4_clk_sclk_vpll.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
-	.sources	= exynos4_clkset_sclk_dac_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
-	.clk		= {
-		.name		= "sclk_dac",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_sclk_dac,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
-	.clk		= {
-		.name		= "sclk_pixel",
-		.parent		= &exynos4_clk_sclk_vpll.clk,
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
-	[0] = &exynos4_clk_sclk_pixel.clk,
-	[1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
-	.sources	= exynos4_clkset_sclk_hdmi_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
-	.clk		= {
-		.name		= "sclk_hdmi",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_sclk_hdmi,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
-	[0] = &exynos4_clk_sclk_dac.clk,
-	[1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
-	.sources	= exynos4_clkset_sclk_mixer_list,
-	.nr_sources	= ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
-	.clk	= {
-		.name		= "sclk_mixer",
-		.enable		= exynos4_clksrc_mask_tv_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_sclk_mixer,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
-	&exynos4_clk_sclk_dac,
-	&exynos4_clk_sclk_pixel,
-	&exynos4_clk_sclk_hdmi,
-	&exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
-	.clk	= {
-		.name		= "dout_mmc0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
-	.clk	= {
-		.name		= "dout_mmc1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
-	.clk	= {
-		.name		= "dout_mmc2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
-	.clk	= {
-		.name		= "dout_mmc3",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_pwm",
-			.enable		= exynos4_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_csis",
-			.devname	= "s5p-mipi-csis.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_cam1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.0",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.1",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.2",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimc",
-			.devname	= "exynos4-fimc.3",
-			.enable		= exynos4_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.0",
-			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_mfc",
-			.devname	= "s5p-mfc",
-		},
-		.sources = &exynos4_clkset_mout_mfc,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_dwmmc",
-			.parent		= &exynos4_clk_dout_mmc4.clk,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.0",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.1",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.2",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
-	.clk	= {
-		.name		= "uclk1",
-		.devname	= "exynos4210-uart.3",
-		.enable		= exynos4_clksrc_mask_peril0_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.0",
-		.parent		= &exynos4_clk_dout_mmc0.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.1",
-		.parent		= &exynos4_clk_dout_mmc1.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 4),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.2",
-		.parent		= &exynos4_clk_dout_mmc2.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
-	.clk	= {
-		.name		= "sclk_mmc",
-		.devname	= "exynos4-sdhci.3",
-		.parent		= &exynos4_clk_dout_mmc3.clk,
-		.enable		= exynos4_clksrc_mask_fsys_ctrl,
-		.ctrlbit	= (1 << 12),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.0",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.1",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
-	.clk	= {
-		.name		= "mdout_spi",
-		.devname	= "exynos4210-spi.2",
-	},
-	.sources = &exynos4_clkset_group,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.0",
-		.parent		= &exynos4_clk_mdout_spi0.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 16),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.1",
-		.parent		= &exynos4_clk_mdout_spi1.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 20),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
-	.clk	= {
-		.name		= "sclk_spi",
-		.devname	= "exynos4210-spi.2",
-		.parent		= &exynos4_clk_mdout_spi2.clk,
-		.enable		= exynos4_clksrc_mask_peril1_ctrl,
-		.ctrlbit	= (1 << 24),
-	},
-	.reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
-	&exynos4_clk_mout_apll,
-	&exynos4_clk_sclk_apll,
-	&exynos4_clk_mout_epll,
-	&exynos4_clk_mout_mpll,
-	&exynos4_clk_moutcore,
-	&exynos4_clk_coreclk,
-	&exynos4_clk_armclk,
-	&exynos4_clk_aclk_corem0,
-	&exynos4_clk_aclk_cores,
-	&exynos4_clk_aclk_corem1,
-	&exynos4_clk_periphclk,
-	&exynos4_clk_mout_corebus,
-	&exynos4_clk_sclk_dmc,
-	&exynos4_clk_aclk_cored,
-	&exynos4_clk_aclk_corep,
-	&exynos4_clk_aclk_acp,
-	&exynos4_clk_pclk_acp,
-	&exynos4_clk_vpllsrc,
-	&exynos4_clk_sclk_vpll,
-	&exynos4_clk_aclk_200,
-	&exynos4_clk_aclk_100,
-	&exynos4_clk_aclk_160,
-	&exynos4_clk_aclk_133,
-	&exynos4_clk_dout_mmc0,
-	&exynos4_clk_dout_mmc1,
-	&exynos4_clk_dout_mmc2,
-	&exynos4_clk_dout_mmc3,
-	&exynos4_clk_dout_mmc4,
-	&exynos4_clk_mout_mfc0,
-	&exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
-	&exynos4_clk_pdma0,
-	&exynos4_clk_pdma1,
-	&exynos4_clk_mdma1,
-	&exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
-	&exynos4_clk_sclk_uart0,
-	&exynos4_clk_sclk_uart1,
-	&exynos4_clk_sclk_uart2,
-	&exynos4_clk_sclk_uart3,
-	&exynos4_clk_sclk_mmc0,
-	&exynos4_clk_sclk_mmc1,
-	&exynos4_clk_sclk_mmc2,
-	&exynos4_clk_sclk_mmc3,
-	&exynos4_clk_sclk_spi0,
-	&exynos4_clk_sclk_spi1,
-	&exynos4_clk_sclk_spi2,
-	&exynos4_clk_mdout_spi0,
-	&exynos4_clk_mdout_spi1,
-	&exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
-	CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
-	CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
-	CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
-	CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-	CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-	CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-	CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-	CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
-	CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
-	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
-	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
-	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-	CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-	CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-	CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-static int xtal_rate;
-
-static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
-{
-	if (soc_is_exynos4210())
-		return s5p_get_pll45xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
-	else
-		return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-	.get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_vpll_div[][8] = {
-	{  54000000, 3, 53, 3, 1024, 0, 17, 0 },
-	{ 108000000, 3, 53, 2, 1024, 0, 17, 0 },
-};
-
-static unsigned long exynos4_vpll_get_rate(struct clk *clk)
-{
-	return clk->rate;
-}
-
-static int exynos4_vpll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned int vpll_con0, vpll_con1 = 0;
-	unsigned int i;
-
-	/* Return if nothing changed */
-	if (clk->rate == rate)
-		return 0;
-
-	vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
-	vpll_con0 &= ~(0x1 << 27 |					\
-			PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |	\
-			PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |	\
-			PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-	vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
-	vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |	\
-			PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT |	\
-			PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
-
-	for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
-		if (exynos4_vpll_div[i][0] == rate) {
-			vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
-			vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
-			vpll_con0 |= exynos4_vpll_div[i][7] << 27;
-			break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(exynos4_vpll_div)) {
-		printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-				__func__);
-		return -EINVAL;
-	}
-
-	__raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
-	__raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
-	/* Wait for VPLL lock */
-	while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
-		continue;
-
-	clk->rate = rate;
-	return 0;
-}
-
-static struct clk_ops exynos4_vpll_ops = {
-	.get_rate = exynos4_vpll_get_rate,
-	.set_rate = exynos4_vpll_set_rate,
-};
-
-void __init_or_cpufreq exynos4_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll = 0;
-	unsigned long mpll = 0;
-	unsigned long epll = 0;
-	unsigned long vpll = 0;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	if (soc_is_exynos4210()) {
-		apll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_APLL_CON0),
-					pll_4508);
-		mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
-					pll_4508);
-		epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
-	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-		apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
-		mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
-		epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-					__raw_readl(EXYNOS4_EPLL_CON1));
-
-		vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-		vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-					__raw_readl(EXYNOS4_VPLL_CON1));
-	} else {
-		/* nothing */
-	}
-
-	clk_fout_apll.ops = &exynos4_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.ops = &exynos4_vpll_ops;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&exynos4_clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&exynos4_clk_aclk_133.clk);
-
-	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrcs); ptr++)
-		s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
-	&exynos4_clk_sclk_hdmi27m,
-	&exynos4_clk_sclk_hdmiphy,
-	&exynos4_clk_sclk_usbphy0,
-	&exynos4_clk_sclk_usbphy1,
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-	return 0;
-}
-
-static void exynos4_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4_clock_save, ARRAY_SIZE(exynos4_clock_save));
-}
-
-#else
-#define exynos4_clock_suspend NULL
-#define exynos4_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4_clock_syscore_ops = {
-	.suspend	= exynos4_clock_suspend,
-	.resume		= exynos4_clock_resume,
-};
-
-void __init exynos4_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
-		s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
-		s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
-		s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
-	s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
-	s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
-	s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
-	for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
-		s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
-	s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-	clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
-	register_syscore_ops(&exynos4_clock_syscore_ops);
-	s3c24xx_register_clock(&dummy_apb_pclk);
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644
index bd12d5f..0000000
--- a/arch/arm/mach-exynos/clock-exynos4.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Header file for exynos4 clock support
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_CLOCK_H
-#define __ASM_ARCH_CLOCK_H __FILE__
-
-#include <linux/clk.h>
-
-extern struct clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-extern int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644
index fed4c26..0000000
--- a/arch/arm/mach-exynos/clock-exynos4210.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4210 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
-	SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
-	/* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
-	[0] = &exynos4210_clk_mout_g2d0.clk,
-	[1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
-	.sources	= exynos4210_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= exynos4_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &exynos4_clkset_mout_corebus,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.devname	= "exynos4-fb.1",
-			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos4_clkset_group,
-		.reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4210_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "sataphy",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.parent		= &exynos4_clk_aclk_133.clk,
-		.enable		= exynos4_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "fimd",
-		.devname	= "exynos4-fb.1",
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(fimd1, 11),
-		.enable		= exynos4_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
-	return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
-	.suspend	= exynos4210_clock_suspend,
-	.resume		= exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
-	int ptr;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
-	exynos4_clk_mout_mpll.reg_src.shift = 8;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644
index 8fba0b5..0000000
--- a/arch/arm/mach-exynos/clock-exynos4212.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * EXYNOS4212 - Clock support
- *
- * 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/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/syscore_ops.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-#include <plat/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/sysmmu.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
-	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
-	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
-	[0] = &clk_fin_mpll,
-	[1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
-	.sources	= clk_src_mpll_user_list,
-	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
-	.clk = {
-		.name		= "mout_mpll_user",
-	},
-	.sources	= &clk_src_mpll_user,
-	.reg_src	= { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-	},
-	.sources = &exynos4_clkset_mout_g2d0,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-	},
-	.sources = &exynos4_clkset_mout_g2d1,
-	.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
-	[0] = &exynos4x12_clk_mout_g2d0.clk,
-	[1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
-	.sources	= exynos4x12_clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "sclk_fimg2d",
-		},
-		.sources = &exynos4x12_clkset_mout_g2d,
-		.reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
-		.reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
-	},
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(2d, 14),
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 24),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (7 << 8),
-	}, {
-		.name		= SYSMMU_CLOCK_NAME2,
-		.devname	= SYSMMU_CLOCK_DEVNAME(isp, 9),
-		.enable		= exynos4212_clk_ip_isp1_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.0",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "flite",
-		.devname	= "exynos-fimc-lite.1",
-		.enable		= exynos4212_clk_ip_isp0_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimg2d",
-		.enable		= exynos4_clk_ip_dmc_ctrl,
-		.ctrlbit	= (1 << 23),
-	},
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
-	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
-	return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
-	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
-	.suspend	= exynos4212_clock_suspend,
-	.resume		= exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
-	int ptr;
-
-	/* usbphy1 is removed */
-	exynos4_clkset_group_list[4] = NULL;
-
-	/* mout_mpll_user is used */
-	exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
-	exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
-	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
-	exynos4_clk_mout_mpll.reg_src.shift = 12;
-	exynos4_clk_mout_mpll.reg_src.size = 1;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	register_syscore_ops(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 715b690..fea1542 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -60,7 +60,6 @@ static const char name_exynos5250[] = "EXYNOS5250";
 
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
-static void exynos4_init_clocks(int xtal);
 static void exynos5_init_clocks(int xtal);
 static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 static int exynos_init(void);
@@ -70,7 +69,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4210_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4210,
@@ -78,7 +76,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4212_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4212,
@@ -86,7 +83,6 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.idcode		= EXYNOS4412_CPU_ID,
 		.idmask		= EXYNOS4_CPU_MASK,
 		.map_io		= exynos4_map_io,
-		.init_clocks	= exynos4_init_clocks,
 		.init_uarts	= exynos_init_uarts,
 		.init		= exynos_init,
 		.name		= name_exynos4412,
@@ -368,31 +364,17 @@ static void __init exynos5_map_io(void)
 	s3c_i2c2_setname("s3c2440-i2c");
 }
 
-static void __init exynos4_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-
-	if (soc_is_exynos4210())
-		exynos4210_register_clocks();
-	else if (soc_is_exynos4212() || soc_is_exynos4412())
-		exynos4212_register_clocks();
-
-	exynos4_register_clocks();
-	exynos4_setup_clocks();
-}
-
 static void __init exynos5_init_clocks(int xtal)
 {
 	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
 
+#ifndef CONFIG_COMMON_CLK
 	s3c24xx_register_baseclocks(xtal);
 	s5p_register_clocks(xtal);
 
 	exynos5_register_clocks();
 	exynos5_setup_clocks();
+#endif
 }
 
 #define COMBINER_ENABLE_SET	0x0
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index dac146d..7a4e0ea 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -22,6 +22,9 @@ void exynos4_restart(char mode, const char *cmd);
 void exynos5_restart(char mode, const char *cmd);
 void exynos_init_late(void);
 
+void exynos4210_clk_init(void);
+void exynos4x12_clk_init(void);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 3f37a5e..583c6a7 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -179,7 +179,6 @@ static void __init armlex4210_smsc911x_init(void)
 static void __init armlex4210_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(armlex4210_uartcfgs,
 			   ARRAY_SIZE(armlex4210_uartcfgs));
 }
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index e58d786..8f6687b 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -83,7 +83,6 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
 static void __init exynos4_dt_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos4_dt_machine_init(void)
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 480cd78f..9b7aa9d 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -1338,7 +1338,6 @@ static struct platform_device *nuri_devices[] __initdata = {
 static void __init nuri_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 67b50bb..0d6b877 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -756,7 +756,6 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index 7a265d1..d1a7668 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -326,7 +326,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 static void __init smdk4x12_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index c15d223..ead65a2 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -376,7 +376,6 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 98d3ace..bd4d1f0 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -1100,7 +1100,6 @@ static struct platform_device *universal_devices[] __initdata = {
 static void __init universal_map_io(void)
 {
 	exynos_init_io(NULL, 0);
-	s3c24xx_init_clocks(clk_xusbxti.rate);
 	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
 	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index b601fb8..cc3805a 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -30,6 +30,8 @@
 #include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+
 #define TICK_BASE_CNT	1
 
 enum {
@@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 static void __init exynos4_timer_resources(void)
 {
 	struct clk *mct_clk;
-	mct_clk = clk_get(NULL, "xtal");
+	mct_clk = clk_get(NULL, "fin_pll");
 
 	clk_rate = clk_get_rate(mct_clk);
 
@@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
 
 static void __init exynos4_timer_init(void)
 {
+#ifdef CONFIG_COMMON_CLK
+	if (soc_is_exynos4210())
+		exynos4210_clk_init();
+	else if (soc_is_exynos4212() || soc_is_exynos4412())
+		exynos4x12_clk_init();
+#endif
+
 	if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
 		mct_int_type = MCT_INT_SPI;
 	else
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9c3b90c..35b4cb8 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -26,7 +26,7 @@ config PLAT_S5P
 	select S5P_GPIO_DRVSTR
 	select SAMSUNG_GPIOLIB_4BIT
 	select PLAT_SAMSUNG
-	select SAMSUNG_CLKSRC
+	select SAMSUNG_CLKSRC if !COMMON_CLK
 	select SAMSUNG_IRQ_VIC_TIMER
 	help
 	  Base platform code for Samsung's S5P series SoC.
@@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
 	  used by newer systems such as the S3C64XX.
 
 config S5P_CLOCK
-	def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+	def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) && !COMMON_CLK)
 	help
 	  Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
 
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-10-08  7:54     ` Tomasz Figa
  -1 siblings, 0 replies; 36+ messages in thread
From: Tomasz Figa @ 2012-10-08  7:54 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: linux-arm-kernel, linux-samsung-soc, devicetree-discuss,
	kgene.kim, sylvester.nawrocki, mturquette, mturquette

Hi Thomas,

The whole series looks much better now. Although there is still one more 
thing from my comments to previous version unresolved, see the inline 
comment.

On Monday 08 of October 2012 02:10:52 Thomas Abraham wrote:
> For legacy Exynos4 platforms, the available clocks are statically
> listed and then registered using the common clock framework. On device
> tree enabled exynos platfotms, the device tree is searched and all
> clock nodes found are registered. Support for Exynos4210 and
> Exynos4x12 platforms is included.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  drivers/clk/samsung/Makefile      |    1 +
>  drivers/clk/samsung/clk-exynos4.c |  647
> +++++++++++++++++++++++++++++++++++++ 2 files changed, 648
> insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/clk-exynos4.c
> 
[snip]
> +			EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
> +	GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
> +	GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
> +	GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),

You cannot register more than one clock with the same platform name 
(sclk_fimc). Shouldn't these names be appended with an index, just like 
with div_fimc{0,1,2,3}?

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
@ 2012-10-08  7:54     ` Tomasz Figa
  0 siblings, 0 replies; 36+ messages in thread
From: Tomasz Figa @ 2012-10-08  7:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

The whole series looks much better now. Although there is still one more 
thing from my comments to previous version unresolved, see the inline 
comment.

On Monday 08 of October 2012 02:10:52 Thomas Abraham wrote:
> For legacy Exynos4 platforms, the available clocks are statically
> listed and then registered using the common clock framework. On device
> tree enabled exynos platfotms, the device tree is searched and all
> clock nodes found are registered. Support for Exynos4210 and
> Exynos4x12 platforms is included.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  drivers/clk/samsung/Makefile      |    1 +
>  drivers/clk/samsung/clk-exynos4.c |  647
> +++++++++++++++++++++++++++++++++++++ 2 files changed, 648
> insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/clk-exynos4.c
> 
[snip]
> +			EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
> +	GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
> +	GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
> +	GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
> +	GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
> +			EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),

You cannot register more than one clock with the same platform name 
(sclk_fimc). Shouldn't these names be appended with an index, just like 
with div_fimc{0,1,2,3}?

Best regards,
-- 
Tomasz Figa
Samsung Poland R&D Center

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-10-22 15:55     ` Sylwester Nawrocki
  -1 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2012-10-22 15:55 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: linux-arm-kernel, linux-samsung-soc, devicetree-discuss,
	kgene.kim, t.figa, sylvester.nawrocki, mturquette, mturquette,
	Kyungmin Park, Myungjoo Ham, Marek Szyprowski

Hi Thomas,

On 10/07/2012 07:10 PM, Thomas Abraham wrote:
> All Samsung platforms include several types of clocks including fixed-rate,
> mux, divider and gate clock types. There are typically hundreds of such clocks
> on each of the Samsung platforms. To enable Samsung platforms to register these
> clocks using the common clock framework, a bunch of utility functions are
> introduced here which simplify the clock registration process.
> 
> In addition to the basic types of clock supported by common clock framework,
> a Samsung specific representation of the PLL clocks is also introduced.
> 
> Both legacy and device tree based Samsung platforms are supported. On legacy
> platforms, the clocks are statically instantiated and registered with common
> clock framework. On device tree enabled platforms, the device tree is
> searched and all clock nodes found are registered. It is also possible to
> register statically instantiated clocks on device tree enabled platforms.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>

Thanks for the patch. I'm trying to use this series on an Exynos4412 
SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
support), was it ?

I have a few comments, please see below.

> ---
>  drivers/clk/Makefile         |    1 +
>  drivers/clk/samsung/Makefile |    5 +
>  drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>  4 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/Makefile
>  create mode 100644 drivers/clk/samsung/clk.c
>  create mode 100644 drivers/clk/samsung/clk.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71a25b9..95644e3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -19,6 +19,7 @@ endif
>  obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
>  obj-$(CONFIG_ARCH_U8500)	+= ux500/
>  obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
> +obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
>  
>  # Chip specific
>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> new file mode 100644
> index 0000000..3f926b0
> --- /dev/null
> +++ b/drivers/clk/samsung/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Samsung Clock specific Makefile
> +#
> +
> +obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> new file mode 100644
> index 0000000..f5e269a
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.c
> @@ -0,0 +1,414 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 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 includes utility functions to register clocks to common
> + * clock framework for Samsung platforms. This includes an implementation
> + * of Samsung 'pll type' clock to represent the implementation of the
> + * pll found on Samsung platforms. In addition to that, utility functions
> + * to register mux, div, gate and fixed rate types of clocks are included.
> +*/
> +
> +#include <linux/of.h>
> +#include "clk.h"
> +
> +#define MAX_PARENT_CLKS		16
> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
> +
> +static DEFINE_SPINLOCK(lock);
> +static void __iomem *reg_base;
> +static void __iomem *reg_fin_pll;
> +
> +void __init samsung_clk_set_ctrl_base(void __iomem *base)
> +{
> +	reg_base = base;
> +}
> +
> +void __init samsung_clk_set_finpll_reg(void __iomem *reg)
> +{
> +	reg_fin_pll = reg;
> +}
> +
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
> +				unsigned long parent_rate)
> +{
> +	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +	if (clk_pll->get_rate)
> +		return to_clk_pll(hw)->get_rate(parent_rate);
> +
> +	return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
> +				unsigned long *prate)
> +{
> +	return samsung_pll_clock_recalc_rate(hw, *prate);
> +}
> +
> +/* set the clock output rate of the pll */
> +static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
> +				unsigned long prate)
> +{
> +	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +	if (clk_pll->set_rate)
> +		return to_clk_pll(hw)->set_rate(drate);
> +
> +	return 0;
> +}
> +
> +/* clock operations for samsung pll clock type */
> +static const struct clk_ops samsung_pll_clock_ops = {
> +	.recalc_rate = samsung_pll_clock_recalc_rate,
> +	.round_rate = samsung_pll_clock_round_rate,
> +	.set_rate = samsung_pll_clock_set_rate,
> +};
> +
> +/* register a samsung pll type clock */
> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
> +				struct device_node *np,
> +				int (*set_rate)(unsigned long rate),
> +				unsigned long (*get_rate)(unsigned long rate))
> +{
> +	struct samsung_pll_clock *clk_pll;
> +	struct clk *clk;
> +	struct clk_init_data init;
> +	int ret;
> +
> +	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> +	if (!clk_pll) {
> +		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
> +		return;
> +	}
> +
> +	init.name = name;
> +	init.ops = &samsung_pll_clock_ops;
> +	init.flags = CLK_GET_RATE_NOCACHE;
> +	init.parent_names = pnames;
> +	init.num_parents = 1;
> +
> +	clk_pll->set_rate = set_rate;
> +	clk_pll->get_rate = get_rate;
> +	clk_pll->hw.init = &init;
> +
> +	/* register the clock */
> +	clk = clk_register(NULL, &clk_pll->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register pll clock %s\n", __func__,
> +				name);
> +		kfree(clk_pll);
> +		return;
> +	}
> +
> +#ifdef CONFIG_OF
> +	if (np)
> +		of_clk_add_provider(np, of_clk_src_simple_get, clk);
> +#endif

Is it really required to do clk_register() and of_clk_add_provider() for 
each single clock ? This seems more heavy than it could be. Looking at
drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
whole group of clocks. Also, couldn't we statically define most of the 
clocks and still register them so they can be used with platforms using 
FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
/imx28.dtsi), where a clock is specified at consumer device node by
a phandle to the clock controller node and a clock index ?

Besides that, what bothers me with in the current approach is the 
clock consumers being defined through one big data structure together 
with the actual clocks. Not all clock objects are going to have 
consumers, some resources are waisted by using flat tables of those 
big data structure objects. Perhaps we could use two tables, one for the
platform clocks and one for the consumers ? These common clock driver
is intended to cover all Samsung SoC, I would expect all samsung 
sub-archs getting converted to use it eventually, with as many of them 
as possible then reworked to support device tree. It's a lot of work 
and is going to take some time, but it would be good to have it planned 
in advance. That said I'm not sure the common samsung clock driver in 
non-dt variant would be really a temporary thing.

> +	/*
> +	 * Register a clock lookup for the pll-type clock even if this
> +	 * has been instantiated from device tree. This helps to do
> +	 * clk_get() lookup on this clock for pruposes of displaying its
> +	 * clock speed at boot time.
> +	 */
> +	ret = clk_register_clkdev(clk, name, NULL);
> +	if (ret)
> +		pr_err("%s: failed to register clock lookup for %s", __func__,
> +				name);
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung pll type clock instantiated from device tree */
> +void __init samsung_of_clk_register_pll(struct device_node *np)
> +{
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
> +}
> +#endif
> +
> +/*
> + * Allow platform specific implementations to attach set_rate and get_rate
> + * callbacks for the pll type clock. Typical calling sequence..
> + *
> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
> + */
> +void __init samsung_pll_clk_set_cb(struct clk *clk,
> +			int (*set_rate)(unsigned long rate),
> +			unsigned long (*get_rate)(unsigned long rate))
> +{
> +	struct samsung_pll_clock *clk_pll;
> +	struct clk_hw *hw = __clk_get_hw(clk);
> +
> +	clk_pll = to_clk_pll(hw);
> +	clk_pll->set_rate = set_rate;
> +	clk_pll->get_rate = get_rate;
> +}
> +
> +/* register a list of fixed clocks (used only for non-dt platforms) */
> +void __init samsung_clk_register_fixed_rate(
> +		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
> +				clk_list->flags, clk_list->fixed_rate);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n", __func__,
> +				clk_list->name);
> +			continue;
> +		}
> +
> +		/*
> +		 * Register a lookup which will help in clk_get() and
> +		 * printing the clock rate during clock initialization.
> +		 */
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("clock: failed to register clock lookup for %s",
> +				clk_list->name);
> +	}
> +}
> +
> +/* register a list of mux clocks */
> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_mux(NULL, clk_list->name,
> +			clk_list->parent_names, clk_list->num_parents,
> +			clk_list->flags, clk_list->reg, clk_list->shift,
> +			clk_list->width, clk_list->mux_flags, &lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n", __func__,
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung mux type clock instantiated from device tree */
> +void __init samsung_of_clk_register_mux(struct device_node *np)
> +{
> +	struct samsung_mux_clock mux_clk;
> +	const char *clk_name = np->name;
> +	const char *parent_names[MAX_PARENT_CLKS];
> +	u32 reg_info[3];
> +	int idx = 0;
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	do {
> +		/* get names of all parent clocks */
> +		parent_names[idx] = of_clk_get_parent_name(np, idx);
> +		idx++;
> +	} while (parent_names[idx-1]);
> +
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	mux_clk.name = clk_name;
> +	mux_clk.parent_names = parent_names;
> +	mux_clk.num_parents = idx - 1;
> +	mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	mux_clk.shift = reg_info[1];
> +	mux_clk.width = reg_info[2];
> +	mux_clk.dev_name = NULL;
> +	mux_clk.flags = 0;
> +	mux_clk.mux_flags = 0;
> +	mux_clk.alias = NULL;
> +	mux_clk.np = np;
> +
> +	if (!strcmp(mux_clk.name, "fin_pll"))
> +		mux_clk.reg = reg_fin_pll;
> +
> +	samsung_clk_register_mux(&mux_clk, 1);
> +}
> +#endif
> +
> +/* register a list of div clocks */
> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_divider(NULL, clk_list->name,
> +			clk_list->parent_name, clk_list->flags, clk_list->reg,
> +			clk_list->shift, clk_list->width, clk_list->div_flags,
> +			&lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("clock: failed to register clock %s\n",
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung div type clock instantiated from device tree */
> +void __init samsung_of_clk_register_div(struct device_node *np)
> +{
> +	struct samsung_div_clock clk_div;
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +	u32 reg_info[3];
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	clk_div.name = clk_name;
> +	clk_div.parent_name = parent_name;
> +	clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	clk_div.shift = reg_info[1];
> +	clk_div.width = reg_info[2];
> +	clk_div.dev_name = NULL;
> +	clk_div.flags = 0;
> +	clk_div.div_flags = 0;
> +	clk_div.alias = NULL;
> +	clk_div.np = np;
> +
> +	samsung_clk_register_div(&clk_div, 1);
> +}
> +#endif
> +
> +/* register a list of gate clocks */
> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_gate(NULL, clk_list->name,
> +			clk_list->parent_name, clk_list->flags, clk_list->reg,
> +			clk_list->bit_idx, clk_list->gate_flags, &lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("clock: failed to register clock %s\n",
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung gate type clock instantiated from device tree */
> +void __init samsung_of_clk_register_gate(struct device_node *np)
> +{
> +	struct samsung_gate_clock clk_gate;
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +	u32 reg_info[2];
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	clk_gate.name = clk_name;
> +	clk_gate.parent_name = parent_name;
> +	clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	clk_gate.bit_idx = reg_info[1];
> +	clk_gate.dev_name = NULL;
> +	clk_gate.flags = 0;
> +	clk_gate.gate_flags = 0;

Some clocks need CLK_SET_RATE_PARENT for the drivers to work
as before. So far it is not set for any mux, div nor gate clock.

> +	clk_gate.alias = NULL;
> +	clk_gate.np = np;
> +
> +	samsung_clk_register_gate(&clk_gate, 1);
> +}
> +#endif
> +

--

Thanks,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-22 15:55     ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2012-10-22 15:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

On 10/07/2012 07:10 PM, Thomas Abraham wrote:
> All Samsung platforms include several types of clocks including fixed-rate,
> mux, divider and gate clock types. There are typically hundreds of such clocks
> on each of the Samsung platforms. To enable Samsung platforms to register these
> clocks using the common clock framework, a bunch of utility functions are
> introduced here which simplify the clock registration process.
> 
> In addition to the basic types of clock supported by common clock framework,
> a Samsung specific representation of the PLL clocks is also introduced.
> 
> Both legacy and device tree based Samsung platforms are supported. On legacy
> platforms, the clocks are statically instantiated and registered with common
> clock framework. On device tree enabled platforms, the device tree is
> searched and all clock nodes found are registered. It is also possible to
> register statically instantiated clocks on device tree enabled platforms.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>

Thanks for the patch. I'm trying to use this series on an Exynos4412 
SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
support), was it ?

I have a few comments, please see below.

> ---
>  drivers/clk/Makefile         |    1 +
>  drivers/clk/samsung/Makefile |    5 +
>  drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>  4 files changed, 632 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/Makefile
>  create mode 100644 drivers/clk/samsung/clk.c
>  create mode 100644 drivers/clk/samsung/clk.h
> 
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 71a25b9..95644e3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -19,6 +19,7 @@ endif
>  obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
>  obj-$(CONFIG_ARCH_U8500)	+= ux500/
>  obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
> +obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
>  
>  # Chip specific
>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> new file mode 100644
> index 0000000..3f926b0
> --- /dev/null
> +++ b/drivers/clk/samsung/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Samsung Clock specific Makefile
> +#
> +
> +obj-$(CONFIG_PLAT_SAMSUNG)	+= clk.o
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> new file mode 100644
> index 0000000..f5e269a
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.c
> @@ -0,0 +1,414 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 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 includes utility functions to register clocks to common
> + * clock framework for Samsung platforms. This includes an implementation
> + * of Samsung 'pll type' clock to represent the implementation of the
> + * pll found on Samsung platforms. In addition to that, utility functions
> + * to register mux, div, gate and fixed rate types of clocks are included.
> +*/
> +
> +#include <linux/of.h>
> +#include "clk.h"
> +
> +#define MAX_PARENT_CLKS		16
> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
> +
> +static DEFINE_SPINLOCK(lock);
> +static void __iomem *reg_base;
> +static void __iomem *reg_fin_pll;
> +
> +void __init samsung_clk_set_ctrl_base(void __iomem *base)
> +{
> +	reg_base = base;
> +}
> +
> +void __init samsung_clk_set_finpll_reg(void __iomem *reg)
> +{
> +	reg_fin_pll = reg;
> +}
> +
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
> +				unsigned long parent_rate)
> +{
> +	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +	if (clk_pll->get_rate)
> +		return to_clk_pll(hw)->get_rate(parent_rate);
> +
> +	return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
> +				unsigned long *prate)
> +{
> +	return samsung_pll_clock_recalc_rate(hw, *prate);
> +}
> +
> +/* set the clock output rate of the pll */
> +static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
> +				unsigned long prate)
> +{
> +	struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +	if (clk_pll->set_rate)
> +		return to_clk_pll(hw)->set_rate(drate);
> +
> +	return 0;
> +}
> +
> +/* clock operations for samsung pll clock type */
> +static const struct clk_ops samsung_pll_clock_ops = {
> +	.recalc_rate = samsung_pll_clock_recalc_rate,
> +	.round_rate = samsung_pll_clock_round_rate,
> +	.set_rate = samsung_pll_clock_set_rate,
> +};
> +
> +/* register a samsung pll type clock */
> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
> +				struct device_node *np,
> +				int (*set_rate)(unsigned long rate),
> +				unsigned long (*get_rate)(unsigned long rate))
> +{
> +	struct samsung_pll_clock *clk_pll;
> +	struct clk *clk;
> +	struct clk_init_data init;
> +	int ret;
> +
> +	clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> +	if (!clk_pll) {
> +		pr_err("%s: could not allocate pll clk %s\n", __func__, name);
> +		return;
> +	}
> +
> +	init.name = name;
> +	init.ops = &samsung_pll_clock_ops;
> +	init.flags = CLK_GET_RATE_NOCACHE;
> +	init.parent_names = pnames;
> +	init.num_parents = 1;
> +
> +	clk_pll->set_rate = set_rate;
> +	clk_pll->get_rate = get_rate;
> +	clk_pll->hw.init = &init;
> +
> +	/* register the clock */
> +	clk = clk_register(NULL, &clk_pll->hw);
> +	if (IS_ERR(clk)) {
> +		pr_err("%s: failed to register pll clock %s\n", __func__,
> +				name);
> +		kfree(clk_pll);
> +		return;
> +	}
> +
> +#ifdef CONFIG_OF
> +	if (np)
> +		of_clk_add_provider(np, of_clk_src_simple_get, clk);
> +#endif

Is it really required to do clk_register() and of_clk_add_provider() for 
each single clock ? This seems more heavy than it could be. Looking at
drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
whole group of clocks. Also, couldn't we statically define most of the 
clocks and still register them so they can be used with platforms using 
FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
/imx28.dtsi), where a clock is specified at consumer device node by
a phandle to the clock controller node and a clock index ?

Besides that, what bothers me with in the current approach is the 
clock consumers being defined through one big data structure together 
with the actual clocks. Not all clock objects are going to have 
consumers, some resources are waisted by using flat tables of those 
big data structure objects. Perhaps we could use two tables, one for the
platform clocks and one for the consumers ? These common clock driver
is intended to cover all Samsung SoC, I would expect all samsung 
sub-archs getting converted to use it eventually, with as many of them 
as possible then reworked to support device tree. It's a lot of work 
and is going to take some time, but it would be good to have it planned 
in advance. That said I'm not sure the common samsung clock driver in 
non-dt variant would be really a temporary thing.

> +	/*
> +	 * Register a clock lookup for the pll-type clock even if this
> +	 * has been instantiated from device tree. This helps to do
> +	 * clk_get() lookup on this clock for pruposes of displaying its
> +	 * clock speed at boot time.
> +	 */
> +	ret = clk_register_clkdev(clk, name, NULL);
> +	if (ret)
> +		pr_err("%s: failed to register clock lookup for %s", __func__,
> +				name);
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung pll type clock instantiated from device tree */
> +void __init samsung_of_clk_register_pll(struct device_node *np)
> +{
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
> +}
> +#endif
> +
> +/*
> + * Allow platform specific implementations to attach set_rate and get_rate
> + * callbacks for the pll type clock. Typical calling sequence..
> + *
> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
> + */
> +void __init samsung_pll_clk_set_cb(struct clk *clk,
> +			int (*set_rate)(unsigned long rate),
> +			unsigned long (*get_rate)(unsigned long rate))
> +{
> +	struct samsung_pll_clock *clk_pll;
> +	struct clk_hw *hw = __clk_get_hw(clk);
> +
> +	clk_pll = to_clk_pll(hw);
> +	clk_pll->set_rate = set_rate;
> +	clk_pll->get_rate = get_rate;
> +}
> +
> +/* register a list of fixed clocks (used only for non-dt platforms) */
> +void __init samsung_clk_register_fixed_rate(
> +		struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
> +				clk_list->flags, clk_list->fixed_rate);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n", __func__,
> +				clk_list->name);
> +			continue;
> +		}
> +
> +		/*
> +		 * Register a lookup which will help in clk_get() and
> +		 * printing the clock rate during clock initialization.
> +		 */
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("clock: failed to register clock lookup for %s",
> +				clk_list->name);
> +	}
> +}
> +
> +/* register a list of mux clocks */
> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_mux(NULL, clk_list->name,
> +			clk_list->parent_names, clk_list->num_parents,
> +			clk_list->flags, clk_list->reg, clk_list->shift,
> +			clk_list->width, clk_list->mux_flags, &lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("%s: failed to register clock %s\n", __func__,
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung mux type clock instantiated from device tree */
> +void __init samsung_of_clk_register_mux(struct device_node *np)
> +{
> +	struct samsung_mux_clock mux_clk;
> +	const char *clk_name = np->name;
> +	const char *parent_names[MAX_PARENT_CLKS];
> +	u32 reg_info[3];
> +	int idx = 0;
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	do {
> +		/* get names of all parent clocks */
> +		parent_names[idx] = of_clk_get_parent_name(np, idx);
> +		idx++;
> +	} while (parent_names[idx-1]);
> +
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	mux_clk.name = clk_name;
> +	mux_clk.parent_names = parent_names;
> +	mux_clk.num_parents = idx - 1;
> +	mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	mux_clk.shift = reg_info[1];
> +	mux_clk.width = reg_info[2];
> +	mux_clk.dev_name = NULL;
> +	mux_clk.flags = 0;
> +	mux_clk.mux_flags = 0;
> +	mux_clk.alias = NULL;
> +	mux_clk.np = np;
> +
> +	if (!strcmp(mux_clk.name, "fin_pll"))
> +		mux_clk.reg = reg_fin_pll;
> +
> +	samsung_clk_register_mux(&mux_clk, 1);
> +}
> +#endif
> +
> +/* register a list of div clocks */
> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_divider(NULL, clk_list->name,
> +			clk_list->parent_name, clk_list->flags, clk_list->reg,
> +			clk_list->shift, clk_list->width, clk_list->div_flags,
> +			&lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("clock: failed to register clock %s\n",
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung div type clock instantiated from device tree */
> +void __init samsung_of_clk_register_div(struct device_node *np)
> +{
> +	struct samsung_div_clock clk_div;
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +	u32 reg_info[3];
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	clk_div.name = clk_name;
> +	clk_div.parent_name = parent_name;
> +	clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	clk_div.shift = reg_info[1];
> +	clk_div.width = reg_info[2];
> +	clk_div.dev_name = NULL;
> +	clk_div.flags = 0;
> +	clk_div.div_flags = 0;
> +	clk_div.alias = NULL;
> +	clk_div.np = np;
> +
> +	samsung_clk_register_div(&clk_div, 1);
> +}
> +#endif
> +
> +/* register a list of gate clocks */
> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
> +						unsigned int nr_clk)
> +{
> +	struct clk *clk;
> +	unsigned int idx, ret;
> +
> +	for (idx = 0; idx < nr_clk; idx++, clk_list++) {
> +		clk = clk_register_gate(NULL, clk_list->name,
> +			clk_list->parent_name, clk_list->flags, clk_list->reg,
> +			clk_list->bit_idx, clk_list->gate_flags, &lock);
> +		if (IS_ERR(clk)) {
> +			pr_err("clock: failed to register clock %s\n",
> +				clk_list->name);
> +			continue;
> +		}
> +
> +#ifdef CONFIG_OF
> +		if (clk_list->np)
> +			of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
> +							clk);
> +#endif
> +
> +		ret = clk_register_clkdev(clk, clk_list->name,
> +						clk_list->dev_name);
> +		if (ret)
> +			pr_err("%s: failed to register clock lookup for %s",
> +					__func__, clk_list->name);
> +
> +		if (clk_list->alias) {
> +			ret = clk_register_clkdev(clk, clk_list->alias,
> +						clk_list->dev_name);
> +			if (ret)
> +				pr_err("%s: failed to register lookup %s\n",
> +					__func__, clk_list->alias);
> +		}
> +	}
> +}
> +
> +#ifdef CONFIG_OF
> +/* register a samsung gate type clock instantiated from device tree */
> +void __init samsung_of_clk_register_gate(struct device_node *np)
> +{
> +	struct samsung_gate_clock clk_gate;
> +	const char *clk_name = np->name;
> +	const char *parent_name;
> +	u32 reg_info[2];
> +
> +	of_property_read_string(np, "clock-output-names", &clk_name);
> +	parent_name = of_clk_get_parent_name(np, 0);
> +	if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
> +		pr_err("%s: invalid register info in node\n", __func__);
> +
> +	clk_gate.name = clk_name;
> +	clk_gate.parent_name = parent_name;
> +	clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
> +	clk_gate.bit_idx = reg_info[1];
> +	clk_gate.dev_name = NULL;
> +	clk_gate.flags = 0;
> +	clk_gate.gate_flags = 0;

Some clocks need CLK_SET_RATE_PARENT for the drivers to work
as before. So far it is not set for any mux, div nor gate clock.

> +	clk_gate.alias = NULL;
> +	clk_gate.np = np;
> +
> +	samsung_clk_register_gate(&clk_gate, 1);
> +}
> +#endif
> +

--

Thanks,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-22 15:55     ` Sylwester Nawrocki
@ 2012-10-29 10:09       ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-29 10:09 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-arm-kernel, linux-samsung-soc, devicetree-discuss,
	kgene.kim, t.figa, sylvester.nawrocki, mturquette, mturquette,
	Kyungmin Park, Myungjoo Ham, Marek Szyprowski

Hi Sylwester,

Thanks for your comments. As usual, your comments are very helpful.

On 22 October 2012 21:25, Sylwester Nawrocki <s.nawrocki@samsung.com> wrote:
> Hi Thomas,
>
> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>> All Samsung platforms include several types of clocks including fixed-rate,
>> mux, divider and gate clock types. There are typically hundreds of such clocks
>> on each of the Samsung platforms. To enable Samsung platforms to register these
>> clocks using the common clock framework, a bunch of utility functions are
>> introduced here which simplify the clock registration process.
>>
>> In addition to the basic types of clock supported by common clock framework,
>> a Samsung specific representation of the PLL clocks is also introduced.
>>
>> Both legacy and device tree based Samsung platforms are supported. On legacy
>> platforms, the clocks are statically instantiated and registered with common
>> clock framework. On device tree enabled platforms, the device tree is
>> searched and all clock nodes found are registered. It is also possible to
>> register statically instantiated clocks on device tree enabled platforms.
>>
>> Cc: Mike Turquette <mturquette@ti.com>
>> Cc: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>
> Thanks for the patch. I'm trying to use this series on an Exynos4412
> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
> support), was it ?

No, it has not been tested on any Exynos4x12 based board. I have
tested it only for Exynos4210 based origen board.

>
> I have a few comments, please see below.
>
>> ---
>>  drivers/clk/Makefile         |    1 +
>>  drivers/clk/samsung/Makefile |    5 +
>>  drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>  drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>  4 files changed, 632 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/clk/samsung/Makefile
>>  create mode 100644 drivers/clk/samsung/clk.c
>>  create mode 100644 drivers/clk/samsung/clk.h
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 71a25b9..95644e3 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -19,6 +19,7 @@ endif
>>  obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
>>  obj-$(CONFIG_ARCH_U8500)     += ux500/
>>  obj-$(CONFIG_ARCH_VT8500)    += clk-vt8500.o
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += samsung/
>>
>>  # Chip specific
>>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..3f926b0
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += clk.o
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..f5e269a
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,414 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 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 includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an implementation
>> + * of Samsung 'pll type' clock to represent the implementation of the
>> + * pll found on Samsung platforms. In addition to that, utility functions
>> + * to register mux, div, gate and fixed rate types of clocks are included.
>> +*/
>> +
>> +#include <linux/of.h>
>> +#include "clk.h"
>> +
>> +#define MAX_PARENT_CLKS              16
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +static void __iomem *reg_base;
>> +static void __iomem *reg_fin_pll;
>> +
>> +void __init samsung_clk_set_ctrl_base(void __iomem *base)
>> +{
>> +     reg_base = base;
>> +}
>> +
>> +void __init samsung_clk_set_finpll_reg(void __iomem *reg)
>> +{
>> +     reg_fin_pll = reg;
>> +}
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
>> +                             unsigned long parent_rate)
>> +{
>> +     struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->get_rate)
>> +             return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long *prate)
>> +{
>> +     return samsung_pll_clock_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long prate)
>> +{
>> +     struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->set_rate)
>> +             return to_clk_pll(hw)->set_rate(drate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_pll_clock_ops = {
>> +     .recalc_rate = samsung_pll_clock_recalc_rate,
>> +     .round_rate = samsung_pll_clock_round_rate,
>> +     .set_rate = samsung_pll_clock_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>> +                             struct device_node *np,
>> +                             int (*set_rate)(unsigned long rate),
>> +                             unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_pll_clock *clk_pll;
>> +     struct clk *clk;
>> +     struct clk_init_data init;
>> +     int ret;
>> +
>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> +     if (!clk_pll) {
>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> +             return;
>> +     }
>> +
>> +     init.name = name;
>> +     init.ops = &samsung_pll_clock_ops;
>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> +     init.parent_names = pnames;
>> +     init.num_parents = 1;
>> +
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +     clk_pll->hw.init = &init;
>> +
>> +     /* register the clock */
>> +     clk = clk_register(NULL, &clk_pll->hw);
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>> +                             name);
>> +             kfree(clk_pll);
>> +             return;
>> +     }
>> +
>> +#ifdef CONFIG_OF
>> +     if (np)
>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>> +#endif
>
> Is it really required to do clk_register() and of_clk_add_provider() for
> each single clock ? This seems more heavy than it could be. Looking at

of_clk_add_provider call for every clock instance is not really
required but it does allow platform code to lookup the clock and
retrieve/display the clock speed. That was the intention to add a
lookup for all the clocks.

> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
> whole group of clocks. Also, couldn't we statically define most of the
> clocks and still register them so they can be used with platforms using
> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
> /imx28.dtsi), where a clock is specified at consumer device node by
> a phandle to the clock controller node and a clock index ?

We could do it that way. I was tempted to list out all the clocks in
device tree and then register them so that there is no static
definition of the clocks needed. You seem to prefer not to do that. I
am fine with either way, static or device tree based registration.

>
> Besides that, what bothers me with in the current approach is the
> clock consumers being defined through one big data structure together
> with the actual clocks. Not all clock objects are going to have
> consumers, some resources are waisted by using flat tables of those
> big data structure objects. Perhaps we could use two tables, one for the
> platform clocks and one for the consumers ? These common clock driver
> is intended to cover all Samsung SoC, I would expect all samsung
> sub-archs getting converted to use it eventually, with as many of them
> as possible then reworked to support device tree. It's a lot of work
> and is going to take some time, but it would be good to have it planned
> in advance. That said I'm not sure the common samsung clock driver in
> non-dt variant would be really a temporary thing.

Non-dt support in Samsung common clock driver will be maintained. But
for existing Exynos4 non-dt platforms, it should be possible to
convert them to completely device tree based platforms.

>
>> +     /*
>> +      * Register a clock lookup for the pll-type clock even if this
>> +      * has been instantiated from device tree. This helps to do
>> +      * clk_get() lookup on this clock for pruposes of displaying its
>> +      * clock speed at boot time.
>> +      */
>> +     ret = clk_register_clkdev(clk, name, NULL);
>> +     if (ret)
>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>> +                             name);
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung pll type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_pll(struct device_node *np)
>> +{
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
>> +}
>> +#endif
>> +
>> +/*
>> + * Allow platform specific implementations to attach set_rate and get_rate
>> + * callbacks for the pll type clock. Typical calling sequence..
>> + *
>> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
>> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
>> + */
>> +void __init samsung_pll_clk_set_cb(struct clk *clk,
>> +                     int (*set_rate)(unsigned long rate),
>> +                     unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_pll_clock *clk_pll;
>> +     struct clk_hw *hw = __clk_get_hw(clk);
>> +
>> +     clk_pll = to_clk_pll(hw);
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +}
>> +
>> +/* register a list of fixed clocks (used only for non-dt platforms) */
>> +void __init samsung_clk_register_fixed_rate(
>> +             struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
>> +                             clk_list->flags, clk_list->fixed_rate);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("%s: failed to register clock %s\n", __func__,
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             /*
>> +              * Register a lookup which will help in clk_get() and
>> +              * printing the clock rate during clock initialization.
>> +              */
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +     }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_mux(NULL, clk_list->name,
>> +                     clk_list->parent_names, clk_list->num_parents,
>> +                     clk_list->flags, clk_list->reg, clk_list->shift,
>> +                     clk_list->width, clk_list->mux_flags, &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("%s: failed to register clock %s\n", __func__,
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung mux type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_mux(struct device_node *np)
>> +{
>> +     struct samsung_mux_clock mux_clk;
>> +     const char *clk_name = np->name;
>> +     const char *parent_names[MAX_PARENT_CLKS];
>> +     u32 reg_info[3];
>> +     int idx = 0;
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     do {
>> +             /* get names of all parent clocks */
>> +             parent_names[idx] = of_clk_get_parent_name(np, idx);
>> +             idx++;
>> +     } while (parent_names[idx-1]);
>> +
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     mux_clk.name = clk_name;
>> +     mux_clk.parent_names = parent_names;
>> +     mux_clk.num_parents = idx - 1;
>> +     mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     mux_clk.shift = reg_info[1];
>> +     mux_clk.width = reg_info[2];
>> +     mux_clk.dev_name = NULL;
>> +     mux_clk.flags = 0;
>> +     mux_clk.mux_flags = 0;
>> +     mux_clk.alias = NULL;
>> +     mux_clk.np = np;
>> +
>> +     if (!strcmp(mux_clk.name, "fin_pll"))
>> +             mux_clk.reg = reg_fin_pll;
>> +
>> +     samsung_clk_register_mux(&mux_clk, 1);
>> +}
>> +#endif
>> +
>> +/* register a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_divider(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->shift, clk_list->width, clk_list->div_flags,
>> +                     &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung div type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_div(struct device_node *np)
>> +{
>> +     struct samsung_div_clock clk_div;
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +     u32 reg_info[3];
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     clk_div.name = clk_name;
>> +     clk_div.parent_name = parent_name;
>> +     clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     clk_div.shift = reg_info[1];
>> +     clk_div.width = reg_info[2];
>> +     clk_div.dev_name = NULL;
>> +     clk_div.flags = 0;
>> +     clk_div.div_flags = 0;
>> +     clk_div.alias = NULL;
>> +     clk_div.np = np;
>> +
>> +     samsung_clk_register_div(&clk_div, 1);
>> +}
>> +#endif
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_gate(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->bit_idx, clk_list->gate_flags, &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung gate type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>> +{
>> +     struct samsung_gate_clock clk_gate;
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +     u32 reg_info[2];
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     clk_gate.name = clk_name;
>> +     clk_gate.parent_name = parent_name;
>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     clk_gate.bit_idx = reg_info[1];
>> +     clk_gate.dev_name = NULL;
>> +     clk_gate.flags = 0;
>> +     clk_gate.gate_flags = 0;
>
> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
> as before. So far it is not set for any mux, div nor gate clock.

Ok. I will fix this.

So about the static vs device tree based clock registration, what
would you suggest?

Thanks,
Thomas.


>
>> +     clk_gate.alias = NULL;
>> +     clk_gate.np = np;
>> +
>> +     samsung_clk_register_gate(&clk_gate, 1);
>> +}
>> +#endif
>> +
>
> --
>
> Thanks,
> Sylwester
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-29 10:09       ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-10-29 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sylwester,

Thanks for your comments. As usual, your comments are very helpful.

On 22 October 2012 21:25, Sylwester Nawrocki <s.nawrocki@samsung.com> wrote:
> Hi Thomas,
>
> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>> All Samsung platforms include several types of clocks including fixed-rate,
>> mux, divider and gate clock types. There are typically hundreds of such clocks
>> on each of the Samsung platforms. To enable Samsung platforms to register these
>> clocks using the common clock framework, a bunch of utility functions are
>> introduced here which simplify the clock registration process.
>>
>> In addition to the basic types of clock supported by common clock framework,
>> a Samsung specific representation of the PLL clocks is also introduced.
>>
>> Both legacy and device tree based Samsung platforms are supported. On legacy
>> platforms, the clocks are statically instantiated and registered with common
>> clock framework. On device tree enabled platforms, the device tree is
>> searched and all clock nodes found are registered. It is also possible to
>> register statically instantiated clocks on device tree enabled platforms.
>>
>> Cc: Mike Turquette <mturquette@ti.com>
>> Cc: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>
> Thanks for the patch. I'm trying to use this series on an Exynos4412
> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
> support), was it ?

No, it has not been tested on any Exynos4x12 based board. I have
tested it only for Exynos4210 based origen board.

>
> I have a few comments, please see below.
>
>> ---
>>  drivers/clk/Makefile         |    1 +
>>  drivers/clk/samsung/Makefile |    5 +
>>  drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>  drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>  4 files changed, 632 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/clk/samsung/Makefile
>>  create mode 100644 drivers/clk/samsung/clk.c
>>  create mode 100644 drivers/clk/samsung/clk.h
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 71a25b9..95644e3 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -19,6 +19,7 @@ endif
>>  obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
>>  obj-$(CONFIG_ARCH_U8500)     += ux500/
>>  obj-$(CONFIG_ARCH_VT8500)    += clk-vt8500.o
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += samsung/
>>
>>  # Chip specific
>>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..3f926b0
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += clk.o
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..f5e269a
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,414 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 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 includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an implementation
>> + * of Samsung 'pll type' clock to represent the implementation of the
>> + * pll found on Samsung platforms. In addition to that, utility functions
>> + * to register mux, div, gate and fixed rate types of clocks are included.
>> +*/
>> +
>> +#include <linux/of.h>
>> +#include "clk.h"
>> +
>> +#define MAX_PARENT_CLKS              16
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_pll_clock, hw)
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +static void __iomem *reg_base;
>> +static void __iomem *reg_fin_pll;
>> +
>> +void __init samsung_clk_set_ctrl_base(void __iomem *base)
>> +{
>> +     reg_base = base;
>> +}
>> +
>> +void __init samsung_clk_set_finpll_reg(void __iomem *reg)
>> +{
>> +     reg_fin_pll = reg;
>> +}
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
>> +                             unsigned long parent_rate)
>> +{
>> +     struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->get_rate)
>> +             return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long *prate)
>> +{
>> +     return samsung_pll_clock_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_pll_clock_set_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long prate)
>> +{
>> +     struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->set_rate)
>> +             return to_clk_pll(hw)->set_rate(drate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_pll_clock_ops = {
>> +     .recalc_rate = samsung_pll_clock_recalc_rate,
>> +     .round_rate = samsung_pll_clock_round_rate,
>> +     .set_rate = samsung_pll_clock_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>> +                             struct device_node *np,
>> +                             int (*set_rate)(unsigned long rate),
>> +                             unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_pll_clock *clk_pll;
>> +     struct clk *clk;
>> +     struct clk_init_data init;
>> +     int ret;
>> +
>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> +     if (!clk_pll) {
>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> +             return;
>> +     }
>> +
>> +     init.name = name;
>> +     init.ops = &samsung_pll_clock_ops;
>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> +     init.parent_names = pnames;
>> +     init.num_parents = 1;
>> +
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +     clk_pll->hw.init = &init;
>> +
>> +     /* register the clock */
>> +     clk = clk_register(NULL, &clk_pll->hw);
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>> +                             name);
>> +             kfree(clk_pll);
>> +             return;
>> +     }
>> +
>> +#ifdef CONFIG_OF
>> +     if (np)
>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>> +#endif
>
> Is it really required to do clk_register() and of_clk_add_provider() for
> each single clock ? This seems more heavy than it could be. Looking at

of_clk_add_provider call for every clock instance is not really
required but it does allow platform code to lookup the clock and
retrieve/display the clock speed. That was the intention to add a
lookup for all the clocks.

> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
> whole group of clocks. Also, couldn't we statically define most of the
> clocks and still register them so they can be used with platforms using
> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
> /imx28.dtsi), where a clock is specified at consumer device node by
> a phandle to the clock controller node and a clock index ?

We could do it that way. I was tempted to list out all the clocks in
device tree and then register them so that there is no static
definition of the clocks needed. You seem to prefer not to do that. I
am fine with either way, static or device tree based registration.

>
> Besides that, what bothers me with in the current approach is the
> clock consumers being defined through one big data structure together
> with the actual clocks. Not all clock objects are going to have
> consumers, some resources are waisted by using flat tables of those
> big data structure objects. Perhaps we could use two tables, one for the
> platform clocks and one for the consumers ? These common clock driver
> is intended to cover all Samsung SoC, I would expect all samsung
> sub-archs getting converted to use it eventually, with as many of them
> as possible then reworked to support device tree. It's a lot of work
> and is going to take some time, but it would be good to have it planned
> in advance. That said I'm not sure the common samsung clock driver in
> non-dt variant would be really a temporary thing.

Non-dt support in Samsung common clock driver will be maintained. But
for existing Exynos4 non-dt platforms, it should be possible to
convert them to completely device tree based platforms.

>
>> +     /*
>> +      * Register a clock lookup for the pll-type clock even if this
>> +      * has been instantiated from device tree. This helps to do
>> +      * clk_get() lookup on this clock for pruposes of displaying its
>> +      * clock speed at boot time.
>> +      */
>> +     ret = clk_register_clkdev(clk, name, NULL);
>> +     if (ret)
>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>> +                             name);
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung pll type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_pll(struct device_node *np)
>> +{
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     samsung_clk_register_pll(clk_name, &parent_name, np, NULL, NULL);
>> +}
>> +#endif
>> +
>> +/*
>> + * Allow platform specific implementations to attach set_rate and get_rate
>> + * callbacks for the pll type clock. Typical calling sequence..
>> + *
>> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
>> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
>> + */
>> +void __init samsung_pll_clk_set_cb(struct clk *clk,
>> +                     int (*set_rate)(unsigned long rate),
>> +                     unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_pll_clock *clk_pll;
>> +     struct clk_hw *hw = __clk_get_hw(clk);
>> +
>> +     clk_pll = to_clk_pll(hw);
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +}
>> +
>> +/* register a list of fixed clocks (used only for non-dt platforms) */
>> +void __init samsung_clk_register_fixed_rate(
>> +             struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_fixed_rate(NULL, clk_list->name, NULL,
>> +                             clk_list->flags, clk_list->fixed_rate);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("%s: failed to register clock %s\n", __func__,
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             /*
>> +              * Register a lookup which will help in clk_get() and
>> +              * printing the clock rate during clock initialization.
>> +              */
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +     }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_mux(NULL, clk_list->name,
>> +                     clk_list->parent_names, clk_list->num_parents,
>> +                     clk_list->flags, clk_list->reg, clk_list->shift,
>> +                     clk_list->width, clk_list->mux_flags, &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("%s: failed to register clock %s\n", __func__,
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung mux type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_mux(struct device_node *np)
>> +{
>> +     struct samsung_mux_clock mux_clk;
>> +     const char *clk_name = np->name;
>> +     const char *parent_names[MAX_PARENT_CLKS];
>> +     u32 reg_info[3];
>> +     int idx = 0;
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     do {
>> +             /* get names of all parent clocks */
>> +             parent_names[idx] = of_clk_get_parent_name(np, idx);
>> +             idx++;
>> +     } while (parent_names[idx-1]);
>> +
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     mux_clk.name = clk_name;
>> +     mux_clk.parent_names = parent_names;
>> +     mux_clk.num_parents = idx - 1;
>> +     mux_clk.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     mux_clk.shift = reg_info[1];
>> +     mux_clk.width = reg_info[2];
>> +     mux_clk.dev_name = NULL;
>> +     mux_clk.flags = 0;
>> +     mux_clk.mux_flags = 0;
>> +     mux_clk.alias = NULL;
>> +     mux_clk.np = np;
>> +
>> +     if (!strcmp(mux_clk.name, "fin_pll"))
>> +             mux_clk.reg = reg_fin_pll;
>> +
>> +     samsung_clk_register_mux(&mux_clk, 1);
>> +}
>> +#endif
>> +
>> +/* register a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_divider(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->shift, clk_list->width, clk_list->div_flags,
>> +                     &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung div type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_div(struct device_node *np)
>> +{
>> +     struct samsung_div_clock clk_div;
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +     u32 reg_info[3];
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 3))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     clk_div.name = clk_name;
>> +     clk_div.parent_name = parent_name;
>> +     clk_div.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     clk_div.shift = reg_info[1];
>> +     clk_div.width = reg_info[2];
>> +     clk_div.dev_name = NULL;
>> +     clk_div.flags = 0;
>> +     clk_div.div_flags = 0;
>> +     clk_div.alias = NULL;
>> +     clk_div.np = np;
>> +
>> +     samsung_clk_register_div(&clk_div, 1);
>> +}
>> +#endif
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_gate(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->bit_idx, clk_list->gate_flags, &lock);
>> +             if (IS_ERR(clk)) {
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +#ifdef CONFIG_OF
>> +             if (clk_list->np)
>> +                     of_clk_add_provider(clk_list->np, of_clk_src_simple_get,
>> +                                                     clk);
>> +#endif
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("%s: failed to register clock lookup for %s",
>> +                                     __func__, clk_list->name);
>> +
>> +             if (clk_list->alias) {
>> +                     ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +                     if (ret)
>> +                             pr_err("%s: failed to register lookup %s\n",
>> +                                     __func__, clk_list->alias);
>> +             }
>> +     }
>> +}
>> +
>> +#ifdef CONFIG_OF
>> +/* register a samsung gate type clock instantiated from device tree */
>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>> +{
>> +     struct samsung_gate_clock clk_gate;
>> +     const char *clk_name = np->name;
>> +     const char *parent_name;
>> +     u32 reg_info[2];
>> +
>> +     of_property_read_string(np, "clock-output-names", &clk_name);
>> +     parent_name = of_clk_get_parent_name(np, 0);
>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>> +             pr_err("%s: invalid register info in node\n", __func__);
>> +
>> +     clk_gate.name = clk_name;
>> +     clk_gate.parent_name = parent_name;
>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>> +     clk_gate.bit_idx = reg_info[1];
>> +     clk_gate.dev_name = NULL;
>> +     clk_gate.flags = 0;
>> +     clk_gate.gate_flags = 0;
>
> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
> as before. So far it is not set for any mux, div nor gate clock.

Ok. I will fix this.

So about the static vs device tree based clock registration, what
would you suggest?

Thanks,
Thomas.


>
>> +     clk_gate.alias = NULL;
>> +     clk_gate.np = np;
>> +
>> +     samsung_clk_register_gate(&clk_gate, 1);
>> +}
>> +#endif
>> +
>
> --
>
> Thanks,
> Sylwester
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-10-30 16:30     ` Mike Turquette
  -1 siblings, 0 replies; 36+ messages in thread
From: Mike Turquette @ 2012-10-30 16:30 UTC (permalink / raw)
  To: Thomas Abraham, linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, kgene.kim, t.figa, sylvester.nawrocki

Hi Thomas,

Quoting Thomas Abraham (2012-10-07 10:10:51)
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
> +                               unsigned long parent_rate)
> +{
> +       struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +       if (clk_pll->get_rate)
> +               return to_clk_pll(hw)->get_rate(parent_rate);

Why the extra indirection?  Does your samsung_pll_clock abstract several
different PLL implementations (with separate clock ops)?  If so, why not
make a unique struct for each PLL type?

> +
> +       return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
> +                               unsigned long *prate)
> +{
> +       return samsung_pll_clock_recalc_rate(hw, *prate);

Why is round_rate not supported?  How is returning the recalculated rate
the right thing here?

> +/*
> + * Allow platform specific implementations to attach set_rate and get_rate
> + * callbacks for the pll type clock. Typical calling sequence..
> + *
> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
> + */
> +void __init samsung_pll_clk_set_cb(struct clk *clk,
> +                       int (*set_rate)(unsigned long rate),
> +                       unsigned long (*get_rate)(unsigned long rate))
> +{
> +       struct samsung_pll_clock *clk_pll;
> +       struct clk_hw *hw = __clk_get_hw(clk);
> +
> +       clk_pll = to_clk_pll(hw);
> +       clk_pll->set_rate = set_rate;
> +       clk_pll->get_rate = get_rate;
> +}

This answers my questions above having different PLL types.  Why not
just make seprate clk_hw structs for each PLL type instead of the extra
layer of abstraction + runtime assignment of clk ops?

Regards,
Mike

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-30 16:30     ` Mike Turquette
  0 siblings, 0 replies; 36+ messages in thread
From: Mike Turquette @ 2012-10-30 16:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

Quoting Thomas Abraham (2012-10-07 10:10:51)
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
> +                               unsigned long parent_rate)
> +{
> +       struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
> +
> +       if (clk_pll->get_rate)
> +               return to_clk_pll(hw)->get_rate(parent_rate);

Why the extra indirection?  Does your samsung_pll_clock abstract several
different PLL implementations (with separate clock ops)?  If so, why not
make a unique struct for each PLL type?

> +
> +       return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
> +                               unsigned long *prate)
> +{
> +       return samsung_pll_clock_recalc_rate(hw, *prate);

Why is round_rate not supported?  How is returning the recalculated rate
the right thing here?

> +/*
> + * Allow platform specific implementations to attach set_rate and get_rate
> + * callbacks for the pll type clock. Typical calling sequence..
> + *
> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
> + */
> +void __init samsung_pll_clk_set_cb(struct clk *clk,
> +                       int (*set_rate)(unsigned long rate),
> +                       unsigned long (*get_rate)(unsigned long rate))
> +{
> +       struct samsung_pll_clock *clk_pll;
> +       struct clk_hw *hw = __clk_get_hw(clk);
> +
> +       clk_pll = to_clk_pll(hw);
> +       clk_pll->set_rate = set_rate;
> +       clk_pll->get_rate = get_rate;
> +}

This answers my questions above having different PLL types.  Why not
just make seprate clk_hw structs for each PLL type instead of the extra
layer of abstraction + runtime assignment of clk ops?

Regards,
Mike

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-29 10:09       ` Thomas Abraham
@ 2012-10-30 23:10         ` Sylwester Nawrocki
  -1 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2012-10-30 23:10 UTC (permalink / raw)
  To: Thomas Abraham
  Cc: Sylwester Nawrocki, linux-arm-kernel, linux-samsung-soc,
	devicetree-discuss, kgene.kim, t.figa, mturquette, mturquette,
	Kyungmin Park, Myungjoo Ham, Marek Szyprowski

Hi Thomas,

On 10/29/2012 11:09 AM, Thomas Abraham wrote:
> Hi Sylwester,
> 
> Thanks for your comments. As usual, your comments are very helpful.

Thanks.
> On 22 October 2012 21:25, Sylwester Nawrocki<s.nawrocki@samsung.com>  wrote:
>> Hi Thomas,
>>
>> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>>> All Samsung platforms include several types of clocks including fixed-rate,
>>> mux, divider and gate clock types. There are typically hundreds of such clocks
>>> on each of the Samsung platforms. To enable Samsung platforms to register these
>>> clocks using the common clock framework, a bunch of utility functions are
>>> introduced here which simplify the clock registration process.
>>>
>>> In addition to the basic types of clock supported by common clock framework,
>>> a Samsung specific representation of the PLL clocks is also introduced.
>>>
>>> Both legacy and device tree based Samsung platforms are supported. On legacy
>>> platforms, the clocks are statically instantiated and registered with common
>>> clock framework. On device tree enabled platforms, the device tree is
>>> searched and all clock nodes found are registered. It is also possible to
>>> register statically instantiated clocks on device tree enabled platforms.
>>>
>>> Cc: Mike Turquette<mturquette@ti.com>
>>> Cc: Kukjin Kim<kgene.kim@samsung.com>
>>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>>
>> Thanks for the patch. I'm trying to use this series on an Exynos4412
>> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
>> support), was it ?
> 
> No, it has not been tested on any Exynos4x12 based board. I have
> tested it only for Exynos4210 based origen board.

OK, thanks. I've had some issues with the root clocks on Exynos4412 
and I put this on a back burner for a while. I plan to get back to 
this, possibly after ELCE/LinuxCon.

>>> ---
>>>   drivers/clk/Makefile         |    1 +
>>>   drivers/clk/samsung/Makefile |    5 +
>>>   drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>>   drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>>   4 files changed, 632 insertions(+), 0 deletions(-)
>>>   create mode 100644 drivers/clk/samsung/Makefile
>>>   create mode 100644 drivers/clk/samsung/clk.c
>>>   create mode 100644 drivers/clk/samsung/clk.h
...
>>> +/* register a samsung pll type clock */
>>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>>> +                             struct device_node *np,
>>> +                             int (*set_rate)(unsigned long rate),
>>> +                             unsigned long (*get_rate)(unsigned long rate))
>>> +{
>>> +     struct samsung_pll_clock *clk_pll;
>>> +     struct clk *clk;
>>> +     struct clk_init_data init;
>>> +     int ret;
>>> +
>>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>>> +     if (!clk_pll) {
>>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>>> +             return;
>>> +     }
>>> +
>>> +     init.name = name;
>>> +     init.ops =&samsung_pll_clock_ops;
>>> +     init.flags = CLK_GET_RATE_NOCACHE;
>>> +     init.parent_names = pnames;
>>> +     init.num_parents = 1;
>>> +
>>> +     clk_pll->set_rate = set_rate;
>>> +     clk_pll->get_rate = get_rate;
>>> +     clk_pll->hw.init =&init;
>>> +
>>> +     /* register the clock */
>>> +     clk = clk_register(NULL,&clk_pll->hw);
>>> +     if (IS_ERR(clk)) {
>>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>>> +                             name);
>>> +             kfree(clk_pll);
>>> +             return;
>>> +     }
>>> +
>>> +#ifdef CONFIG_OF
>>> +     if (np)
>>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>>> +#endif
>>
>> Is it really required to do clk_register() and of_clk_add_provider() for
>> each single clock ? This seems more heavy than it could be. Looking at
> 
> of_clk_add_provider call for every clock instance is not really
> required but it does allow platform code to lookup the clock and
> retrieve/display the clock speed. That was the intention to add a
> lookup for all the clocks.

Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
It's probably not a big deal to look up the clocks root node and
then use of_clk_get() function to find required clock ?

>> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
>> whole group of clocks. Also, couldn't we statically define most of the
>> clocks and still register them so they can be used with platforms using
>> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
>> /imx28.dtsi), where a clock is specified at consumer device node by
>> a phandle to the clock controller node and a clock index ?
> 
> We could do it that way. I was tempted to list out all the clocks in
> device tree and then register them so that there is no static
> definition of the clocks needed. You seem to prefer not to do that. I
> am fine with either way, static or device tree based registration.

Ok, it's also worth noting that clk_get() would have been more expensive
when there would be a need to iterate over large number of clock providers.
Indexed look up might be a better alternative.

Exynos SoCs have fairly complex clock tree structure, I personally do find
it harder to understand from a bit bulky description in form of a device
tree node list. Comparing to the original Samsung clock API there is now 
more clock objects, since, e.g. single struct clk_clksrc is now represented 
by mux, div and gate clock group, which makes things slightly more 
complicated, i.e. there is even more clocks to be listed.

>> Besides that, what bothers me with in the current approach is the
>> clock consumers being defined through one big data structure together
>> with the actual clocks. Not all clock objects are going to have
>> consumers, some resources are waisted by using flat tables of those
>> big data structure objects. Perhaps we could use two tables, one for the
>> platform clocks and one for the consumers ? These common clock driver
>> is intended to cover all Samsung SoC, I would expect all samsung
>> sub-archs getting converted to use it eventually, with as many of them
>> as possible then reworked to support device tree. It's a lot of work
>> and is going to take some time, but it would be good to have it planned
>> in advance. That said I'm not sure the common samsung clock driver in
>> non-dt variant would be really a temporary thing.
> 
> Non-dt support in Samsung common clock driver will be maintained. But
> for existing Exynos4 non-dt platforms, it should be possible to
> convert them to completely device tree based platforms.

OK, let's then focus on device tree support for exynos4+ SoCs. I hope we 
could have the clocks statically defined and still freely accessible in 
the device tree.

>>> +     /*
>>> +      * Register a clock lookup for the pll-type clock even if this
>>> +      * has been instantiated from device tree. This helps to do
>>> +      * clk_get() lookup on this clock for pruposes of displaying its
>>> +      * clock speed at boot time.
>>> +      */
>>> +     ret = clk_register_clkdev(clk, name, NULL);
>>> +     if (ret)
>>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>>> +                             name);
>>> +}
...
>>> +
>>> +#ifdef CONFIG_OF
>>> +/* register a samsung gate type clock instantiated from device tree */
>>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>>> +{
>>> +     struct samsung_gate_clock clk_gate;
>>> +     const char *clk_name = np->name;
>>> +     const char *parent_name;
>>> +     u32 reg_info[2];
>>> +
>>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>>> +     parent_name = of_clk_get_parent_name(np, 0);
>>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>>> +             pr_err("%s: invalid register info in node\n", __func__);
>>> +
>>> +     clk_gate.name = clk_name;
>>> +     clk_gate.parent_name = parent_name;
>>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>>> +     clk_gate.bit_idx = reg_info[1];
>>> +     clk_gate.dev_name = NULL;
>>> +     clk_gate.flags = 0;
>>> +     clk_gate.gate_flags = 0;
>>
>> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>> as before. So far it is not set for any mux, div nor gate clock.
> 
> Ok. I will fix this.
> 
> So about the static vs device tree based clock registration, what
> would you suggest?

Defining the clocks statically has my preference, it would be nice to 
hear more opinions on that though. I think on a heavily utilised SoC 
the list of clock nodes could have grown significantly. And with 
preprocessor support at the dt compiler (not sure if it is already 
there) indexed clock definitions could be made more explicit.

These are roughly our conclusions from discussing this patch series
with Tomasz F.

--
Thanks,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-30 23:10         ` Sylwester Nawrocki
  0 siblings, 0 replies; 36+ messages in thread
From: Sylwester Nawrocki @ 2012-10-30 23:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

On 10/29/2012 11:09 AM, Thomas Abraham wrote:
> Hi Sylwester,
> 
> Thanks for your comments. As usual, your comments are very helpful.

Thanks.
> On 22 October 2012 21:25, Sylwester Nawrocki<s.nawrocki@samsung.com>  wrote:
>> Hi Thomas,
>>
>> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>>> All Samsung platforms include several types of clocks including fixed-rate,
>>> mux, divider and gate clock types. There are typically hundreds of such clocks
>>> on each of the Samsung platforms. To enable Samsung platforms to register these
>>> clocks using the common clock framework, a bunch of utility functions are
>>> introduced here which simplify the clock registration process.
>>>
>>> In addition to the basic types of clock supported by common clock framework,
>>> a Samsung specific representation of the PLL clocks is also introduced.
>>>
>>> Both legacy and device tree based Samsung platforms are supported. On legacy
>>> platforms, the clocks are statically instantiated and registered with common
>>> clock framework. On device tree enabled platforms, the device tree is
>>> searched and all clock nodes found are registered. It is also possible to
>>> register statically instantiated clocks on device tree enabled platforms.
>>>
>>> Cc: Mike Turquette<mturquette@ti.com>
>>> Cc: Kukjin Kim<kgene.kim@samsung.com>
>>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>>
>> Thanks for the patch. I'm trying to use this series on an Exynos4412
>> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
>> support), was it ?
> 
> No, it has not been tested on any Exynos4x12 based board. I have
> tested it only for Exynos4210 based origen board.

OK, thanks. I've had some issues with the root clocks on Exynos4412 
and I put this on a back burner for a while. I plan to get back to 
this, possibly after ELCE/LinuxCon.

>>> ---
>>>   drivers/clk/Makefile         |    1 +
>>>   drivers/clk/samsung/Makefile |    5 +
>>>   drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>>   drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>>   4 files changed, 632 insertions(+), 0 deletions(-)
>>>   create mode 100644 drivers/clk/samsung/Makefile
>>>   create mode 100644 drivers/clk/samsung/clk.c
>>>   create mode 100644 drivers/clk/samsung/clk.h
...
>>> +/* register a samsung pll type clock */
>>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>>> +                             struct device_node *np,
>>> +                             int (*set_rate)(unsigned long rate),
>>> +                             unsigned long (*get_rate)(unsigned long rate))
>>> +{
>>> +     struct samsung_pll_clock *clk_pll;
>>> +     struct clk *clk;
>>> +     struct clk_init_data init;
>>> +     int ret;
>>> +
>>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>>> +     if (!clk_pll) {
>>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>>> +             return;
>>> +     }
>>> +
>>> +     init.name = name;
>>> +     init.ops =&samsung_pll_clock_ops;
>>> +     init.flags = CLK_GET_RATE_NOCACHE;
>>> +     init.parent_names = pnames;
>>> +     init.num_parents = 1;
>>> +
>>> +     clk_pll->set_rate = set_rate;
>>> +     clk_pll->get_rate = get_rate;
>>> +     clk_pll->hw.init =&init;
>>> +
>>> +     /* register the clock */
>>> +     clk = clk_register(NULL,&clk_pll->hw);
>>> +     if (IS_ERR(clk)) {
>>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>>> +                             name);
>>> +             kfree(clk_pll);
>>> +             return;
>>> +     }
>>> +
>>> +#ifdef CONFIG_OF
>>> +     if (np)
>>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>>> +#endif
>>
>> Is it really required to do clk_register() and of_clk_add_provider() for
>> each single clock ? This seems more heavy than it could be. Looking at
> 
> of_clk_add_provider call for every clock instance is not really
> required but it does allow platform code to lookup the clock and
> retrieve/display the clock speed. That was the intention to add a
> lookup for all the clocks.

Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
It's probably not a big deal to look up the clocks root node and
then use of_clk_get() function to find required clock ?

>> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
>> whole group of clocks. Also, couldn't we statically define most of the
>> clocks and still register them so they can be used with platforms using
>> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
>> /imx28.dtsi), where a clock is specified at consumer device node by
>> a phandle to the clock controller node and a clock index ?
> 
> We could do it that way. I was tempted to list out all the clocks in
> device tree and then register them so that there is no static
> definition of the clocks needed. You seem to prefer not to do that. I
> am fine with either way, static or device tree based registration.

Ok, it's also worth noting that clk_get() would have been more expensive
when there would be a need to iterate over large number of clock providers.
Indexed look up might be a better alternative.

Exynos SoCs have fairly complex clock tree structure, I personally do find
it harder to understand from a bit bulky description in form of a device
tree node list. Comparing to the original Samsung clock API there is now 
more clock objects, since, e.g. single struct clk_clksrc is now represented 
by mux, div and gate clock group, which makes things slightly more 
complicated, i.e. there is even more clocks to be listed.

>> Besides that, what bothers me with in the current approach is the
>> clock consumers being defined through one big data structure together
>> with the actual clocks. Not all clock objects are going to have
>> consumers, some resources are waisted by using flat tables of those
>> big data structure objects. Perhaps we could use two tables, one for the
>> platform clocks and one for the consumers ? These common clock driver
>> is intended to cover all Samsung SoC, I would expect all samsung
>> sub-archs getting converted to use it eventually, with as many of them
>> as possible then reworked to support device tree. It's a lot of work
>> and is going to take some time, but it would be good to have it planned
>> in advance. That said I'm not sure the common samsung clock driver in
>> non-dt variant would be really a temporary thing.
> 
> Non-dt support in Samsung common clock driver will be maintained. But
> for existing Exynos4 non-dt platforms, it should be possible to
> convert them to completely device tree based platforms.

OK, let's then focus on device tree support for exynos4+ SoCs. I hope we 
could have the clocks statically defined and still freely accessible in 
the device tree.

>>> +     /*
>>> +      * Register a clock lookup for the pll-type clock even if this
>>> +      * has been instantiated from device tree. This helps to do
>>> +      * clk_get() lookup on this clock for pruposes of displaying its
>>> +      * clock speed at boot time.
>>> +      */
>>> +     ret = clk_register_clkdev(clk, name, NULL);
>>> +     if (ret)
>>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>>> +                             name);
>>> +}
...
>>> +
>>> +#ifdef CONFIG_OF
>>> +/* register a samsung gate type clock instantiated from device tree */
>>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>>> +{
>>> +     struct samsung_gate_clock clk_gate;
>>> +     const char *clk_name = np->name;
>>> +     const char *parent_name;
>>> +     u32 reg_info[2];
>>> +
>>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>>> +     parent_name = of_clk_get_parent_name(np, 0);
>>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>>> +             pr_err("%s: invalid register info in node\n", __func__);
>>> +
>>> +     clk_gate.name = clk_name;
>>> +     clk_gate.parent_name = parent_name;
>>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>>> +     clk_gate.bit_idx = reg_info[1];
>>> +     clk_gate.dev_name = NULL;
>>> +     clk_gate.flags = 0;
>>> +     clk_gate.gate_flags = 0;
>>
>> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>> as before. So far it is not set for any mux, div nor gate clock.
> 
> Ok. I will fix this.
> 
> So about the static vs device tree based clock registration, what
> would you suggest?

Defining the clocks statically has my preference, it would be nice to 
hear more opinions on that though. I think on a heavily utilised SoC 
the list of clock nodes could have grown significantly. And with 
preprocessor support at the dt compiler (not sure if it is already 
there) indexed clock definitions could be made more explicit.

These are roughly our conclusions from discussing this patch series
with Tomasz F.

--
Thanks,
Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-30 23:10         ` Sylwester Nawrocki
@ 2012-10-30 23:32           ` Tomasz Figa
  -1 siblings, 0 replies; 36+ messages in thread
From: Tomasz Figa @ 2012-10-30 23:32 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: Thomas Abraham, Sylwester Nawrocki, linux-arm-kernel,
	linux-samsung-soc, devicetree-discuss, kgene.kim, t.figa,
	mturquette, mturquette, Kyungmin Park, Myungjoo Ham,
	Marek Szyprowski

Hi Thomas, Sylwester,

On Wednesday 31 of October 2012 00:10:24 Sylwester Nawrocki wrote:
> >>> +/* register a samsung pll type clock */
> >>> +void __init samsung_clk_register_pll(const char *name, const char
> >>> **pnames, +                             struct device_node *np,
> >>> +                             int (*set_rate)(unsigned long rate),
> >>> +                             unsigned long (*get_rate)(unsigned long
> >>> rate)) +{
> >>> +     struct samsung_pll_clock *clk_pll;
> >>> +     struct clk *clk;
> >>> +     struct clk_init_data init;
> >>> +     int ret;
> >>> +
> >>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> >>> +     if (!clk_pll) {
> >>> +             pr_err("%s: could not allocate pll clk %s\n", __func__,
> >>> name); +             return;
> >>> +     }
> >>> +
> >>> +     init.name = name;
> >>> +     init.ops =&samsung_pll_clock_ops;
> >>> +     init.flags = CLK_GET_RATE_NOCACHE;
> >>> +     init.parent_names = pnames;
> >>> +     init.num_parents = 1;
> >>> +
> >>> +     clk_pll->set_rate = set_rate;
> >>> +     clk_pll->get_rate = get_rate;
> >>> +     clk_pll->hw.init =&init;
> >>> +
> >>> +     /* register the clock */
> >>> +     clk = clk_register(NULL,&clk_pll->hw);
> >>> +     if (IS_ERR(clk)) {
> >>> +             pr_err("%s: failed to register pll clock %s\n",
> >>> __func__,
> >>> +                             name);
> >>> +             kfree(clk_pll);
> >>> +             return;
> >>> +     }
> >>> +
> >>> +#ifdef CONFIG_OF
> >>> +     if (np)
> >>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
> >>> +#endif
> >> 
> >> Is it really required to do clk_register() and of_clk_add_provider()
> >> for
> >> each single clock ? This seems more heavy than it could be. Looking at
> > 
> > of_clk_add_provider call for every clock instance is not really
> > required but it does allow platform code to lookup the clock and
> > retrieve/display the clock speed. That was the intention to add a
> > lookup for all the clocks.

I'm not really sure if displaying clock speed is really a good 
justification for increasing the list of system clocks almost by a factor 
of three. This will make clock lookup a bit heavy.

You might display speed of several most important clocks directly from the 
samsung clk driver using internal data, without the need of involving 
generic clock lookup for this purpose.

> 
> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
> It's probably not a big deal to look up the clocks root node and
> then use of_clk_get() function to find required clock ?

I believe that the intention was for it to work on non-DT platforms as 
well. However I might have misunderstood your suggestion, could you 
elaborate?

> >> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider
> >> for
> >> whole group of clocks. Also, couldn't we statically define most of the
> >> clocks and still register them so they can be used with platforms
> >> using
> >> FDT ? Something along the lines of imx28 implementation
> >> (arch/arm/boot/dts /imx28.dtsi), where a clock is specified at
> >> consumer device node by a phandle to the clock controller node and a
> >> clock index ?
> > 
> > We could do it that way. I was tempted to list out all the clocks in
> > device tree and then register them so that there is no static
> > definition of the clocks needed. You seem to prefer not to do that. I
> > am fine with either way, static or device tree based registration.
> 
> Ok, it's also worth noting that clk_get() would have been more expensive
> when there would be a need to iterate over large number of clock
> providers. Indexed look up might be a better alternative.

I'm definitely for indexed lookup. With the ability to define constants in 
device tree sources the main drawback of this solution being less readable 
now disappeared and everything left are advantages.

> Exynos SoCs have fairly complex clock tree structure, I personally do
> find it harder to understand from a bit bulky description in form of a
> device tree node list. Comparing to the original Samsung clock API there
> is now more clock objects, since, e.g. single struct clk_clksrc is now
> represented by mux, div and gate clock group, which makes things
> slightly more complicated, i.e. there is even more clocks to be listed.

If it's about readability I tend to disagree. I find device tree much more 
readable as a way of describing hardware than hardcoded data structures, 
often using complex macros to keep the definitions short.

> >> Besides that, what bothers me with in the current approach is the
> >> clock consumers being defined through one big data structure together
> >> with the actual clocks. Not all clock objects are going to have
> >> consumers, some resources are waisted by using flat tables of those
> >> big data structure objects. Perhaps we could use two tables, one for
> >> the
> >> platform clocks and one for the consumers ? These common clock driver
> >> is intended to cover all Samsung SoC, I would expect all samsung
> >> sub-archs getting converted to use it eventually, with as many of them
> >> as possible then reworked to support device tree. It's a lot of work
> >> and is going to take some time, but it would be good to have it
> >> planned
> >> in advance. That said I'm not sure the common samsung clock driver in
> >> non-dt variant would be really a temporary thing.
> > 
> > Non-dt support in Samsung common clock driver will be maintained. But
> > for existing Exynos4 non-dt platforms, it should be possible to
> > convert them to completely device tree based platforms.
> 
> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
> could have the clocks statically defined and still freely accessible in
> the device tree.

Using the approach with indexed clocks inside a single provider would allow 
to reuse the same internal SoC-specific data for both DT and non-DT 
variants, without any data duplication. This is definitely an advantage.

> >>> +
> >>> +#ifdef CONFIG_OF
> >>> +/* register a samsung gate type clock instantiated from device tree
> >>> */
> >>> +void __init samsung_of_clk_register_gate(struct device_node *np)
> >>> +{
> >>> +     struct samsung_gate_clock clk_gate;
> >>> +     const char *clk_name = np->name;
> >>> +     const char *parent_name;
> >>> +     u32 reg_info[2];
> >>> +
> >>> +     of_property_read_string(np, "clock-output-names",&clk_name);
> >>> +     parent_name = of_clk_get_parent_name(np, 0);
> >>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
> >>> +             pr_err("%s: invalid register info in node\n",
> >>> __func__);
> >>> +
> >>> +     clk_gate.name = clk_name;
> >>> +     clk_gate.parent_name = parent_name;
> >>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
> >>> +     clk_gate.bit_idx = reg_info[1];
> >>> +     clk_gate.dev_name = NULL;
> >>> +     clk_gate.flags = 0;
> >>> +     clk_gate.gate_flags = 0;
> >> 
> >> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
> >> as before. So far it is not set for any mux, div nor gate clock.
> > 
> > Ok. I will fix this.
> > 
> > So about the static vs device tree based clock registration, what
> > would you suggest?
> 
> Defining the clocks statically has my preference, it would be nice to
> hear more opinions on that though. I think on a heavily utilised SoC
> the list of clock nodes could have grown significantly. And with
> preprocessor support at the dt compiler (not sure if it is already
> there) indexed clock definitions could be made more explicit.
> 
> These are roughly our conclusions from discussing this patch series
> with Tomasz F.

Yes, as I said, I'm definitely for the single clock provider approach (aka 
imx-like approach).

Best regards,
Tomasz Figa

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-10-30 23:32           ` Tomasz Figa
  0 siblings, 0 replies; 36+ messages in thread
From: Tomasz Figa @ 2012-10-30 23:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas, Sylwester,

On Wednesday 31 of October 2012 00:10:24 Sylwester Nawrocki wrote:
> >>> +/* register a samsung pll type clock */
> >>> +void __init samsung_clk_register_pll(const char *name, const char
> >>> **pnames, +                             struct device_node *np,
> >>> +                             int (*set_rate)(unsigned long rate),
> >>> +                             unsigned long (*get_rate)(unsigned long
> >>> rate)) +{
> >>> +     struct samsung_pll_clock *clk_pll;
> >>> +     struct clk *clk;
> >>> +     struct clk_init_data init;
> >>> +     int ret;
> >>> +
> >>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> >>> +     if (!clk_pll) {
> >>> +             pr_err("%s: could not allocate pll clk %s\n", __func__,
> >>> name); +             return;
> >>> +     }
> >>> +
> >>> +     init.name = name;
> >>> +     init.ops =&samsung_pll_clock_ops;
> >>> +     init.flags = CLK_GET_RATE_NOCACHE;
> >>> +     init.parent_names = pnames;
> >>> +     init.num_parents = 1;
> >>> +
> >>> +     clk_pll->set_rate = set_rate;
> >>> +     clk_pll->get_rate = get_rate;
> >>> +     clk_pll->hw.init =&init;
> >>> +
> >>> +     /* register the clock */
> >>> +     clk = clk_register(NULL,&clk_pll->hw);
> >>> +     if (IS_ERR(clk)) {
> >>> +             pr_err("%s: failed to register pll clock %s\n",
> >>> __func__,
> >>> +                             name);
> >>> +             kfree(clk_pll);
> >>> +             return;
> >>> +     }
> >>> +
> >>> +#ifdef CONFIG_OF
> >>> +     if (np)
> >>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
> >>> +#endif
> >> 
> >> Is it really required to do clk_register() and of_clk_add_provider()
> >> for
> >> each single clock ? This seems more heavy than it could be. Looking at
> > 
> > of_clk_add_provider call for every clock instance is not really
> > required but it does allow platform code to lookup the clock and
> > retrieve/display the clock speed. That was the intention to add a
> > lookup for all the clocks.

I'm not really sure if displaying clock speed is really a good 
justification for increasing the list of system clocks almost by a factor 
of three. This will make clock lookup a bit heavy.

You might display speed of several most important clocks directly from the 
samsung clk driver using internal data, without the need of involving 
generic clock lookup for this purpose.

> 
> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
> It's probably not a big deal to look up the clocks root node and
> then use of_clk_get() function to find required clock ?

I believe that the intention was for it to work on non-DT platforms as 
well. However I might have misunderstood your suggestion, could you 
elaborate?

> >> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider
> >> for
> >> whole group of clocks. Also, couldn't we statically define most of the
> >> clocks and still register them so they can be used with platforms
> >> using
> >> FDT ? Something along the lines of imx28 implementation
> >> (arch/arm/boot/dts /imx28.dtsi), where a clock is specified at
> >> consumer device node by a phandle to the clock controller node and a
> >> clock index ?
> > 
> > We could do it that way. I was tempted to list out all the clocks in
> > device tree and then register them so that there is no static
> > definition of the clocks needed. You seem to prefer not to do that. I
> > am fine with either way, static or device tree based registration.
> 
> Ok, it's also worth noting that clk_get() would have been more expensive
> when there would be a need to iterate over large number of clock
> providers. Indexed look up might be a better alternative.

I'm definitely for indexed lookup. With the ability to define constants in 
device tree sources the main drawback of this solution being less readable 
now disappeared and everything left are advantages.

> Exynos SoCs have fairly complex clock tree structure, I personally do
> find it harder to understand from a bit bulky description in form of a
> device tree node list. Comparing to the original Samsung clock API there
> is now more clock objects, since, e.g. single struct clk_clksrc is now
> represented by mux, div and gate clock group, which makes things
> slightly more complicated, i.e. there is even more clocks to be listed.

If it's about readability I tend to disagree. I find device tree much more 
readable as a way of describing hardware than hardcoded data structures, 
often using complex macros to keep the definitions short.

> >> Besides that, what bothers me with in the current approach is the
> >> clock consumers being defined through one big data structure together
> >> with the actual clocks. Not all clock objects are going to have
> >> consumers, some resources are waisted by using flat tables of those
> >> big data structure objects. Perhaps we could use two tables, one for
> >> the
> >> platform clocks and one for the consumers ? These common clock driver
> >> is intended to cover all Samsung SoC, I would expect all samsung
> >> sub-archs getting converted to use it eventually, with as many of them
> >> as possible then reworked to support device tree. It's a lot of work
> >> and is going to take some time, but it would be good to have it
> >> planned
> >> in advance. That said I'm not sure the common samsung clock driver in
> >> non-dt variant would be really a temporary thing.
> > 
> > Non-dt support in Samsung common clock driver will be maintained. But
> > for existing Exynos4 non-dt platforms, it should be possible to
> > convert them to completely device tree based platforms.
> 
> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
> could have the clocks statically defined and still freely accessible in
> the device tree.

Using the approach with indexed clocks inside a single provider would allow 
to reuse the same internal SoC-specific data for both DT and non-DT 
variants, without any data duplication. This is definitely an advantage.

> >>> +
> >>> +#ifdef CONFIG_OF
> >>> +/* register a samsung gate type clock instantiated from device tree
> >>> */
> >>> +void __init samsung_of_clk_register_gate(struct device_node *np)
> >>> +{
> >>> +     struct samsung_gate_clock clk_gate;
> >>> +     const char *clk_name = np->name;
> >>> +     const char *parent_name;
> >>> +     u32 reg_info[2];
> >>> +
> >>> +     of_property_read_string(np, "clock-output-names",&clk_name);
> >>> +     parent_name = of_clk_get_parent_name(np, 0);
> >>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
> >>> +             pr_err("%s: invalid register info in node\n",
> >>> __func__);
> >>> +
> >>> +     clk_gate.name = clk_name;
> >>> +     clk_gate.parent_name = parent_name;
> >>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
> >>> +     clk_gate.bit_idx = reg_info[1];
> >>> +     clk_gate.dev_name = NULL;
> >>> +     clk_gate.flags = 0;
> >>> +     clk_gate.gate_flags = 0;
> >> 
> >> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
> >> as before. So far it is not set for any mux, div nor gate clock.
> > 
> > Ok. I will fix this.
> > 
> > So about the static vs device tree based clock registration, what
> > would you suggest?
> 
> Defining the clocks statically has my preference, it would be nice to
> hear more opinions on that though. I think on a heavily utilised SoC
> the list of clock nodes could have grown significantly. And with
> preprocessor support at the dt compiler (not sure if it is already
> there) indexed clock definitions could be made more explicit.
> 
> These are roughly our conclusions from discussing this patch series
> with Tomasz F.

Yes, as I said, I'm definitely for the single clock provider approach (aka 
imx-like approach).

Best regards,
Tomasz Figa

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-30 16:30     ` Mike Turquette
@ 2012-11-05  7:22       ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:22 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-arm-kernel, linux-samsung-soc, devicetree-discuss,
	kgene.kim, t.figa, sylvester.nawrocki

Hi Mike,

Thanks for your review.

On 30 October 2012 22:00, Mike Turquette <mturquette@ti.com> wrote:
> Hi Thomas,
>
> Quoting Thomas Abraham (2012-10-07 10:10:51)
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
>> +                               unsigned long parent_rate)
>> +{
>> +       struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +       if (clk_pll->get_rate)
>> +               return to_clk_pll(hw)->get_rate(parent_rate);
>
> Why the extra indirection?  Does your samsung_pll_clock abstract several
> different PLL implementations (with separate clock ops)?  If so, why not
> make a unique struct for each PLL type?

Yes, it abstracts several PLL types. There are multiple PLL types used
by Samsung SoC's and this clock type was supposed to abstract all the
types of PLL's. But yes, you are right. It is better to have a unique
implementation for each type of PLL. That way, multiple user's of a
PLL type need not be worried about setting up runtime callbacks for
clock operations.

>
>> +
>> +       return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
>> +                               unsigned long *prate)
>> +{
>> +       return samsung_pll_clock_recalc_rate(hw, *prate);
>
> Why is round_rate not supported?  How is returning the recalculated rate
> the right thing here?

The PLL does not include a divider for the rounding operation. So the
output of the PLL clock type is not something that can be divided
down. The parent clock of the PLL clock type is usually a low
frequency oscillator. Hence, the round rate operation has not been
implemented for the PLL clock type.

>
>> +/*
>> + * Allow platform specific implementations to attach set_rate and get_rate
>> + * callbacks for the pll type clock. Typical calling sequence..
>> + *
>> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
>> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
>> + */
>> +void __init samsung_pll_clk_set_cb(struct clk *clk,
>> +                       int (*set_rate)(unsigned long rate),
>> +                       unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +       struct samsung_pll_clock *clk_pll;
>> +       struct clk_hw *hw = __clk_get_hw(clk);
>> +
>> +       clk_pll = to_clk_pll(hw);
>> +       clk_pll->set_rate = set_rate;
>> +       clk_pll->get_rate = get_rate;
>> +}
>
> This answers my questions above having different PLL types.  Why not
> just make seprate clk_hw structs for each PLL type instead of the extra
> layer of abstraction + runtime assignment of clk ops?

Ok. I will redo this in the next version of this patch.

Thanks,
Thomas.

>
> Regards,
> Mike

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-11-05  7:22       ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

Thanks for your review.

On 30 October 2012 22:00, Mike Turquette <mturquette@ti.com> wrote:
> Hi Thomas,
>
> Quoting Thomas Abraham (2012-10-07 10:10:51)
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_pll_clock_recalc_rate(struct clk_hw *hw,
>> +                               unsigned long parent_rate)
>> +{
>> +       struct samsung_pll_clock *clk_pll = to_clk_pll(hw);
>> +
>> +       if (clk_pll->get_rate)
>> +               return to_clk_pll(hw)->get_rate(parent_rate);
>
> Why the extra indirection?  Does your samsung_pll_clock abstract several
> different PLL implementations (with separate clock ops)?  If so, why not
> make a unique struct for each PLL type?

Yes, it abstracts several PLL types. There are multiple PLL types used
by Samsung SoC's and this clock type was supposed to abstract all the
types of PLL's. But yes, you are right. It is better to have a unique
implementation for each type of PLL. That way, multiple user's of a
PLL type need not be worried about setting up runtime callbacks for
clock operations.

>
>> +
>> +       return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_pll_clock_round_rate(struct clk_hw *hw, unsigned long drate,
>> +                               unsigned long *prate)
>> +{
>> +       return samsung_pll_clock_recalc_rate(hw, *prate);
>
> Why is round_rate not supported?  How is returning the recalculated rate
> the right thing here?

The PLL does not include a divider for the rounding operation. So the
output of the PLL clock type is not something that can be divided
down. The parent clock of the PLL clock type is usually a low
frequency oscillator. Hence, the round rate operation has not been
implemented for the PLL clock type.

>
>> +/*
>> + * Allow platform specific implementations to attach set_rate and get_rate
>> + * callbacks for the pll type clock. Typical calling sequence..
>> + *
>> + * struct clk *clk = clk_get(NULL, "pll-clk-name");
>> + * samsung_pll_clk_set_cb(clk, pll_set_rate, pll_get_rate);
>> + */
>> +void __init samsung_pll_clk_set_cb(struct clk *clk,
>> +                       int (*set_rate)(unsigned long rate),
>> +                       unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +       struct samsung_pll_clock *clk_pll;
>> +       struct clk_hw *hw = __clk_get_hw(clk);
>> +
>> +       clk_pll = to_clk_pll(hw);
>> +       clk_pll->set_rate = set_rate;
>> +       clk_pll->get_rate = get_rate;
>> +}
>
> This answers my questions above having different PLL types.  Why not
> just make seprate clk_hw structs for each PLL type instead of the extra
> layer of abstraction + runtime assignment of clk ops?

Ok. I will redo this in the next version of this patch.

Thanks,
Thomas.

>
> Regards,
> Mike

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-30 23:10         ` Sylwester Nawrocki
@ 2012-11-05  7:36           ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:36 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: Sylwester Nawrocki, linux-arm-kernel, linux-samsung-soc,
	devicetree-discuss, kgene.kim, t.figa, mturquette, mturquette,
	Kyungmin Park, Myungjoo Ham, Marek Szyprowski

Hi Sylwester,

On 31 October 2012 04:40, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hi Thomas,
>
> On 10/29/2012 11:09 AM, Thomas Abraham wrote:
>> Hi Sylwester,
>>
>> Thanks for your comments. As usual, your comments are very helpful.
>
> Thanks.
>> On 22 October 2012 21:25, Sylwester Nawrocki<s.nawrocki@samsung.com>  wrote:
>>> Hi Thomas,
>>>
>>> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>>>> All Samsung platforms include several types of clocks including fixed-rate,
>>>> mux, divider and gate clock types. There are typically hundreds of such clocks
>>>> on each of the Samsung platforms. To enable Samsung platforms to register these
>>>> clocks using the common clock framework, a bunch of utility functions are
>>>> introduced here which simplify the clock registration process.
>>>>
>>>> In addition to the basic types of clock supported by common clock framework,
>>>> a Samsung specific representation of the PLL clocks is also introduced.
>>>>
>>>> Both legacy and device tree based Samsung platforms are supported. On legacy
>>>> platforms, the clocks are statically instantiated and registered with common
>>>> clock framework. On device tree enabled platforms, the device tree is
>>>> searched and all clock nodes found are registered. It is also possible to
>>>> register statically instantiated clocks on device tree enabled platforms.
>>>>
>>>> Cc: Mike Turquette<mturquette@ti.com>
>>>> Cc: Kukjin Kim<kgene.kim@samsung.com>
>>>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>>>
>>> Thanks for the patch. I'm trying to use this series on an Exynos4412
>>> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
>>> support), was it ?
>>
>> No, it has not been tested on any Exynos4x12 based board. I have
>> tested it only for Exynos4210 based origen board.
>
> OK, thanks. I've had some issues with the root clocks on Exynos4412
> and I put this on a back burner for a while. I plan to get back to
> this, possibly after ELCE/LinuxCon.

Ok.

>
>>>> ---
>>>>   drivers/clk/Makefile         |    1 +
>>>>   drivers/clk/samsung/Makefile |    5 +
>>>>   drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>>>   drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>>>   4 files changed, 632 insertions(+), 0 deletions(-)
>>>>   create mode 100644 drivers/clk/samsung/Makefile
>>>>   create mode 100644 drivers/clk/samsung/clk.c
>>>>   create mode 100644 drivers/clk/samsung/clk.h
> ...
>>>> +/* register a samsung pll type clock */
>>>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>>>> +                             struct device_node *np,
>>>> +                             int (*set_rate)(unsigned long rate),
>>>> +                             unsigned long (*get_rate)(unsigned long rate))
>>>> +{
>>>> +     struct samsung_pll_clock *clk_pll;
>>>> +     struct clk *clk;
>>>> +     struct clk_init_data init;
>>>> +     int ret;
>>>> +
>>>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>>>> +     if (!clk_pll) {
>>>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>>>> +             return;
>>>> +     }
>>>> +
>>>> +     init.name = name;
>>>> +     init.ops =&samsung_pll_clock_ops;
>>>> +     init.flags = CLK_GET_RATE_NOCACHE;
>>>> +     init.parent_names = pnames;
>>>> +     init.num_parents = 1;
>>>> +
>>>> +     clk_pll->set_rate = set_rate;
>>>> +     clk_pll->get_rate = get_rate;
>>>> +     clk_pll->hw.init =&init;
>>>> +
>>>> +     /* register the clock */
>>>> +     clk = clk_register(NULL,&clk_pll->hw);
>>>> +     if (IS_ERR(clk)) {
>>>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>>>> +                             name);
>>>> +             kfree(clk_pll);
>>>> +             return;
>>>> +     }
>>>> +
>>>> +#ifdef CONFIG_OF
>>>> +     if (np)
>>>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>>>> +#endif
>>>
>>> Is it really required to do clk_register() and of_clk_add_provider() for
>>> each single clock ? This seems more heavy than it could be. Looking at
>>
>> of_clk_add_provider call for every clock instance is not really
>> required but it does allow platform code to lookup the clock and
>> retrieve/display the clock speed. That was the intention to add a
>> lookup for all the clocks.
>
> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
> It's probably not a big deal to look up the clocks root node and
> then use of_clk_get() function to find required clock ?

Yes, I was referring to calling clk_get() with NULL 'dev' argument.
Usually, at boot, the clock frequency of some of the system clocks
(such as aclk_200) are displayed. So all the clocks were registered
using clk_register allowing clock frequency of any the clock to be
retrieved using clk_get.

Your suggestion to use of_clk_get assumes the clock implementation
follows the imx style, which was not way used in this patch series.
And then there is this problem of supporting non-dt platforms as well.

>
>>> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
>>> whole group of clocks. Also, couldn't we statically define most of the
>>> clocks and still register them so they can be used with platforms using
>>> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
>>> /imx28.dtsi), where a clock is specified at consumer device node by
>>> a phandle to the clock controller node and a clock index ?
>>
>> We could do it that way. I was tempted to list out all the clocks in
>> device tree and then register them so that there is no static
>> definition of the clocks needed. You seem to prefer not to do that. I
>> am fine with either way, static or device tree based registration.
>
> Ok, it's also worth noting that clk_get() would have been more expensive
> when there would be a need to iterate over large number of clock providers.
> Indexed look up might be a better alternative.

Yes, true.

>
> Exynos SoCs have fairly complex clock tree structure, I personally do find
> it harder to understand from a bit bulky description in form of a device
> tree node list. Comparing to the original Samsung clock API there is now
> more clock objects, since, e.g. single struct clk_clksrc is now represented
> by mux, div and gate clock group, which makes things slightly more
> complicated, i.e. there is even more clocks to be listed.
>

Ok.

>>> Besides that, what bothers me with in the current approach is the
>>> clock consumers being defined through one big data structure together
>>> with the actual clocks. Not all clock objects are going to have
>>> consumers, some resources are waisted by using flat tables of those
>>> big data structure objects. Perhaps we could use two tables, one for the
>>> platform clocks and one for the consumers ? These common clock driver
>>> is intended to cover all Samsung SoC, I would expect all samsung
>>> sub-archs getting converted to use it eventually, with as many of them
>>> as possible then reworked to support device tree. It's a lot of work
>>> and is going to take some time, but it would be good to have it planned
>>> in advance. That said I'm not sure the common samsung clock driver in
>>> non-dt variant would be really a temporary thing.
>>
>> Non-dt support in Samsung common clock driver will be maintained. But
>> for existing Exynos4 non-dt platforms, it should be possible to
>> convert them to completely device tree based platforms.
>
> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
> could have the clocks statically defined and still freely accessible in
> the device tree.

Ok. I will implement it as you mentioned.

>
>>>> +     /*
>>>> +      * Register a clock lookup for the pll-type clock even if this
>>>> +      * has been instantiated from device tree. This helps to do
>>>> +      * clk_get() lookup on this clock for pruposes of displaying its
>>>> +      * clock speed at boot time.
>>>> +      */
>>>> +     ret = clk_register_clkdev(clk, name, NULL);
>>>> +     if (ret)
>>>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>>>> +                             name);
>>>> +}
> ...
>>>> +
>>>> +#ifdef CONFIG_OF
>>>> +/* register a samsung gate type clock instantiated from device tree */
>>>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>>>> +{
>>>> +     struct samsung_gate_clock clk_gate;
>>>> +     const char *clk_name = np->name;
>>>> +     const char *parent_name;
>>>> +     u32 reg_info[2];
>>>> +
>>>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>>>> +     parent_name = of_clk_get_parent_name(np, 0);
>>>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>>>> +             pr_err("%s: invalid register info in node\n", __func__);
>>>> +
>>>> +     clk_gate.name = clk_name;
>>>> +     clk_gate.parent_name = parent_name;
>>>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>>>> +     clk_gate.bit_idx = reg_info[1];
>>>> +     clk_gate.dev_name = NULL;
>>>> +     clk_gate.flags = 0;
>>>> +     clk_gate.gate_flags = 0;
>>>
>>> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>>> as before. So far it is not set for any mux, div nor gate clock.
>>
>> Ok. I will fix this.
>>
>> So about the static vs device tree based clock registration, what
>> would you suggest?
>
> Defining the clocks statically has my preference, it would be nice to
> hear more opinions on that though. I think on a heavily utilised SoC
> the list of clock nodes could have grown significantly. And with
> preprocessor support at the dt compiler (not sure if it is already
> there) indexed clock definitions could be made more explicit.
>
> These are roughly our conclusions from discussing this patch series
> with Tomasz F.

Ok. Thanks for your comments. I will redo this patch series and post them.

Thanks,
Thomas.

>
> --
> Thanks,
> Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-11-05  7:36           ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sylwester,

On 31 October 2012 04:40, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hi Thomas,
>
> On 10/29/2012 11:09 AM, Thomas Abraham wrote:
>> Hi Sylwester,
>>
>> Thanks for your comments. As usual, your comments are very helpful.
>
> Thanks.
>> On 22 October 2012 21:25, Sylwester Nawrocki<s.nawrocki@samsung.com>  wrote:
>>> Hi Thomas,
>>>
>>> On 10/07/2012 07:10 PM, Thomas Abraham wrote:
>>>> All Samsung platforms include several types of clocks including fixed-rate,
>>>> mux, divider and gate clock types. There are typically hundreds of such clocks
>>>> on each of the Samsung platforms. To enable Samsung platforms to register these
>>>> clocks using the common clock framework, a bunch of utility functions are
>>>> introduced here which simplify the clock registration process.
>>>>
>>>> In addition to the basic types of clock supported by common clock framework,
>>>> a Samsung specific representation of the PLL clocks is also introduced.
>>>>
>>>> Both legacy and device tree based Samsung platforms are supported. On legacy
>>>> platforms, the clocks are statically instantiated and registered with common
>>>> clock framework. On device tree enabled platforms, the device tree is
>>>> searched and all clock nodes found are registered. It is also possible to
>>>> register statically instantiated clocks on device tree enabled platforms.
>>>>
>>>> Cc: Mike Turquette<mturquette@ti.com>
>>>> Cc: Kukjin Kim<kgene.kim@samsung.com>
>>>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>>>
>>> Thanks for the patch. I'm trying to use this series on an Exynos4412
>>> SoC based board. I think it wasn't tested with Exynos4x12 (with FDT
>>> support), was it ?
>>
>> No, it has not been tested on any Exynos4x12 based board. I have
>> tested it only for Exynos4210 based origen board.
>
> OK, thanks. I've had some issues with the root clocks on Exynos4412
> and I put this on a back burner for a while. I plan to get back to
> this, possibly after ELCE/LinuxCon.

Ok.

>
>>>> ---
>>>>   drivers/clk/Makefile         |    1 +
>>>>   drivers/clk/samsung/Makefile |    5 +
>>>>   drivers/clk/samsung/clk.c    |  414 ++++++++++++++++++++++++++++++++++++++++++
>>>>   drivers/clk/samsung/clk.h    |  212 +++++++++++++++++++++
>>>>   4 files changed, 632 insertions(+), 0 deletions(-)
>>>>   create mode 100644 drivers/clk/samsung/Makefile
>>>>   create mode 100644 drivers/clk/samsung/clk.c
>>>>   create mode 100644 drivers/clk/samsung/clk.h
> ...
>>>> +/* register a samsung pll type clock */
>>>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>>>> +                             struct device_node *np,
>>>> +                             int (*set_rate)(unsigned long rate),
>>>> +                             unsigned long (*get_rate)(unsigned long rate))
>>>> +{
>>>> +     struct samsung_pll_clock *clk_pll;
>>>> +     struct clk *clk;
>>>> +     struct clk_init_data init;
>>>> +     int ret;
>>>> +
>>>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>>>> +     if (!clk_pll) {
>>>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>>>> +             return;
>>>> +     }
>>>> +
>>>> +     init.name = name;
>>>> +     init.ops =&samsung_pll_clock_ops;
>>>> +     init.flags = CLK_GET_RATE_NOCACHE;
>>>> +     init.parent_names = pnames;
>>>> +     init.num_parents = 1;
>>>> +
>>>> +     clk_pll->set_rate = set_rate;
>>>> +     clk_pll->get_rate = get_rate;
>>>> +     clk_pll->hw.init =&init;
>>>> +
>>>> +     /* register the clock */
>>>> +     clk = clk_register(NULL,&clk_pll->hw);
>>>> +     if (IS_ERR(clk)) {
>>>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>>>> +                             name);
>>>> +             kfree(clk_pll);
>>>> +             return;
>>>> +     }
>>>> +
>>>> +#ifdef CONFIG_OF
>>>> +     if (np)
>>>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>>>> +#endif
>>>
>>> Is it really required to do clk_register() and of_clk_add_provider() for
>>> each single clock ? This seems more heavy than it could be. Looking at
>>
>> of_clk_add_provider call for every clock instance is not really
>> required but it does allow platform code to lookup the clock and
>> retrieve/display the clock speed. That was the intention to add a
>> lookup for all the clocks.
>
> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
> It's probably not a big deal to look up the clocks root node and
> then use of_clk_get() function to find required clock ?

Yes, I was referring to calling clk_get() with NULL 'dev' argument.
Usually, at boot, the clock frequency of some of the system clocks
(such as aclk_200) are displayed. So all the clocks were registered
using clk_register allowing clock frequency of any the clock to be
retrieved using clk_get.

Your suggestion to use of_clk_get assumes the clock implementation
follows the imx style, which was not way used in this patch series.
And then there is this problem of supporting non-dt platforms as well.

>
>>> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider for
>>> whole group of clocks. Also, couldn't we statically define most of the
>>> clocks and still register them so they can be used with platforms using
>>> FDT ? Something along the lines of imx28 implementation (arch/arm/boot/dts
>>> /imx28.dtsi), where a clock is specified at consumer device node by
>>> a phandle to the clock controller node and a clock index ?
>>
>> We could do it that way. I was tempted to list out all the clocks in
>> device tree and then register them so that there is no static
>> definition of the clocks needed. You seem to prefer not to do that. I
>> am fine with either way, static or device tree based registration.
>
> Ok, it's also worth noting that clk_get() would have been more expensive
> when there would be a need to iterate over large number of clock providers.
> Indexed look up might be a better alternative.

Yes, true.

>
> Exynos SoCs have fairly complex clock tree structure, I personally do find
> it harder to understand from a bit bulky description in form of a device
> tree node list. Comparing to the original Samsung clock API there is now
> more clock objects, since, e.g. single struct clk_clksrc is now represented
> by mux, div and gate clock group, which makes things slightly more
> complicated, i.e. there is even more clocks to be listed.
>

Ok.

>>> Besides that, what bothers me with in the current approach is the
>>> clock consumers being defined through one big data structure together
>>> with the actual clocks. Not all clock objects are going to have
>>> consumers, some resources are waisted by using flat tables of those
>>> big data structure objects. Perhaps we could use two tables, one for the
>>> platform clocks and one for the consumers ? These common clock driver
>>> is intended to cover all Samsung SoC, I would expect all samsung
>>> sub-archs getting converted to use it eventually, with as many of them
>>> as possible then reworked to support device tree. It's a lot of work
>>> and is going to take some time, but it would be good to have it planned
>>> in advance. That said I'm not sure the common samsung clock driver in
>>> non-dt variant would be really a temporary thing.
>>
>> Non-dt support in Samsung common clock driver will be maintained. But
>> for existing Exynos4 non-dt platforms, it should be possible to
>> convert them to completely device tree based platforms.
>
> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
> could have the clocks statically defined and still freely accessible in
> the device tree.

Ok. I will implement it as you mentioned.

>
>>>> +     /*
>>>> +      * Register a clock lookup for the pll-type clock even if this
>>>> +      * has been instantiated from device tree. This helps to do
>>>> +      * clk_get() lookup on this clock for pruposes of displaying its
>>>> +      * clock speed at boot time.
>>>> +      */
>>>> +     ret = clk_register_clkdev(clk, name, NULL);
>>>> +     if (ret)
>>>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>>>> +                             name);
>>>> +}
> ...
>>>> +
>>>> +#ifdef CONFIG_OF
>>>> +/* register a samsung gate type clock instantiated from device tree */
>>>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>>>> +{
>>>> +     struct samsung_gate_clock clk_gate;
>>>> +     const char *clk_name = np->name;
>>>> +     const char *parent_name;
>>>> +     u32 reg_info[2];
>>>> +
>>>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>>>> +     parent_name = of_clk_get_parent_name(np, 0);
>>>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>>>> +             pr_err("%s: invalid register info in node\n", __func__);
>>>> +
>>>> +     clk_gate.name = clk_name;
>>>> +     clk_gate.parent_name = parent_name;
>>>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>>>> +     clk_gate.bit_idx = reg_info[1];
>>>> +     clk_gate.dev_name = NULL;
>>>> +     clk_gate.flags = 0;
>>>> +     clk_gate.gate_flags = 0;
>>>
>>> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>>> as before. So far it is not set for any mux, div nor gate clock.
>>
>> Ok. I will fix this.
>>
>> So about the static vs device tree based clock registration, what
>> would you suggest?
>
> Defining the clocks statically has my preference, it would be nice to
> hear more opinions on that though. I think on a heavily utilised SoC
> the list of clock nodes could have grown significantly. And with
> preprocessor support at the dt compiler (not sure if it is already
> there) indexed clock definitions could be made more explicit.
>
> These are roughly our conclusions from discussing this patch series
> with Tomasz F.

Ok. Thanks for your comments. I will redo this patch series and post them.

Thanks,
Thomas.

>
> --
> Thanks,
> Sylwester

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
  2012-10-30 23:32           ` Tomasz Figa
@ 2012-11-05  7:41             ` Thomas Abraham
  -1 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:41 UTC (permalink / raw)
  To: Tomasz Figa
  Cc: Sylwester Nawrocki, Sylwester Nawrocki, linux-arm-kernel,
	linux-samsung-soc, devicetree-discuss, kgene.kim, t.figa,
	mturquette, mturquette, Kyungmin Park, Myungjoo Ham,
	Marek Szyprowski

Hi Tomasz,

On 31 October 2012 05:02, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Thomas, Sylwester,
>
> On Wednesday 31 of October 2012 00:10:24 Sylwester Nawrocki wrote:
>> >>> +/* register a samsung pll type clock */
>> >>> +void __init samsung_clk_register_pll(const char *name, const char
>> >>> **pnames, +                             struct device_node *np,
>> >>> +                             int (*set_rate)(unsigned long rate),
>> >>> +                             unsigned long (*get_rate)(unsigned long
>> >>> rate)) +{
>> >>> +     struct samsung_pll_clock *clk_pll;
>> >>> +     struct clk *clk;
>> >>> +     struct clk_init_data init;
>> >>> +     int ret;
>> >>> +
>> >>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> >>> +     if (!clk_pll) {
>> >>> +             pr_err("%s: could not allocate pll clk %s\n", __func__,
>> >>> name); +             return;
>> >>> +     }
>> >>> +
>> >>> +     init.name = name;
>> >>> +     init.ops =&samsung_pll_clock_ops;
>> >>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> >>> +     init.parent_names = pnames;
>> >>> +     init.num_parents = 1;
>> >>> +
>> >>> +     clk_pll->set_rate = set_rate;
>> >>> +     clk_pll->get_rate = get_rate;
>> >>> +     clk_pll->hw.init =&init;
>> >>> +
>> >>> +     /* register the clock */
>> >>> +     clk = clk_register(NULL,&clk_pll->hw);
>> >>> +     if (IS_ERR(clk)) {
>> >>> +             pr_err("%s: failed to register pll clock %s\n",
>> >>> __func__,
>> >>> +                             name);
>> >>> +             kfree(clk_pll);
>> >>> +             return;
>> >>> +     }
>> >>> +
>> >>> +#ifdef CONFIG_OF
>> >>> +     if (np)
>> >>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>> >>> +#endif
>> >>
>> >> Is it really required to do clk_register() and of_clk_add_provider()
>> >> for
>> >> each single clock ? This seems more heavy than it could be. Looking at
>> >
>> > of_clk_add_provider call for every clock instance is not really
>> > required but it does allow platform code to lookup the clock and
>> > retrieve/display the clock speed. That was the intention to add a
>> > lookup for all the clocks.
>
> I'm not really sure if displaying clock speed is really a good
> justification for increasing the list of system clocks almost by a factor
> of three. This will make clock lookup a bit heavy.
>
> You might display speed of several most important clocks directly from the
> samsung clk driver using internal data, without the need of involving
> generic clock lookup for this purpose.

Ok. But that would mean that we implment the clk_get_rate() function
for such clocks again. For example, to get the rate of the aclk_200
clock, its parent clock would have to be divided and then displayed.
But it was easier to just use the clk_get api. But yes I agree, this
is not a compelling reason to register all the clocks.

>
>>
>> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
>> It's probably not a big deal to look up the clocks root node and
>> then use of_clk_get() function to find required clock ?
>
> I believe that the intention was for it to work on non-DT platforms as
> well. However I might have misunderstood your suggestion, could you
> elaborate?
>
>> >> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider
>> >> for
>> >> whole group of clocks. Also, couldn't we statically define most of the
>> >> clocks and still register them so they can be used with platforms
>> >> using
>> >> FDT ? Something along the lines of imx28 implementation
>> >> (arch/arm/boot/dts /imx28.dtsi), where a clock is specified at
>> >> consumer device node by a phandle to the clock controller node and a
>> >> clock index ?
>> >
>> > We could do it that way. I was tempted to list out all the clocks in
>> > device tree and then register them so that there is no static
>> > definition of the clocks needed. You seem to prefer not to do that. I
>> > am fine with either way, static or device tree based registration.
>>
>> Ok, it's also worth noting that clk_get() would have been more expensive
>> when there would be a need to iterate over large number of clock
>> providers. Indexed look up might be a better alternative.
>
> I'm definitely for indexed lookup. With the ability to define constants in
> device tree sources the main drawback of this solution being less readable
> now disappeared and everything left are advantages.

Ok.

>
>> Exynos SoCs have fairly complex clock tree structure, I personally do
>> find it harder to understand from a bit bulky description in form of a
>> device tree node list. Comparing to the original Samsung clock API there
>> is now more clock objects, since, e.g. single struct clk_clksrc is now
>> represented by mux, div and gate clock group, which makes things
>> slightly more complicated, i.e. there is even more clocks to be listed.
>
> If it's about readability I tend to disagree. I find device tree much more
> readable as a way of describing hardware than hardcoded data structures,
> often using complex macros to keep the definitions short.
>
>> >> Besides that, what bothers me with in the current approach is the
>> >> clock consumers being defined through one big data structure together
>> >> with the actual clocks. Not all clock objects are going to have
>> >> consumers, some resources are waisted by using flat tables of those
>> >> big data structure objects. Perhaps we could use two tables, one for
>> >> the
>> >> platform clocks and one for the consumers ? These common clock driver
>> >> is intended to cover all Samsung SoC, I would expect all samsung
>> >> sub-archs getting converted to use it eventually, with as many of them
>> >> as possible then reworked to support device tree. It's a lot of work
>> >> and is going to take some time, but it would be good to have it
>> >> planned
>> >> in advance. That said I'm not sure the common samsung clock driver in
>> >> non-dt variant would be really a temporary thing.
>> >
>> > Non-dt support in Samsung common clock driver will be maintained. But
>> > for existing Exynos4 non-dt platforms, it should be possible to
>> > convert them to completely device tree based platforms.
>>
>> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
>> could have the clocks statically defined and still freely accessible in
>> the device tree.
>
> Using the approach with indexed clocks inside a single provider would allow
> to reuse the same internal SoC-specific data for both DT and non-DT
> variants, without any data duplication. This is definitely an advantage.

Ok.

>
>> >>> +
>> >>> +#ifdef CONFIG_OF
>> >>> +/* register a samsung gate type clock instantiated from device tree
>> >>> */
>> >>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>> >>> +{
>> >>> +     struct samsung_gate_clock clk_gate;
>> >>> +     const char *clk_name = np->name;
>> >>> +     const char *parent_name;
>> >>> +     u32 reg_info[2];
>> >>> +
>> >>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>> >>> +     parent_name = of_clk_get_parent_name(np, 0);
>> >>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>> >>> +             pr_err("%s: invalid register info in node\n",
>> >>> __func__);
>> >>> +
>> >>> +     clk_gate.name = clk_name;
>> >>> +     clk_gate.parent_name = parent_name;
>> >>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>> >>> +     clk_gate.bit_idx = reg_info[1];
>> >>> +     clk_gate.dev_name = NULL;
>> >>> +     clk_gate.flags = 0;
>> >>> +     clk_gate.gate_flags = 0;
>> >>
>> >> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>> >> as before. So far it is not set for any mux, div nor gate clock.
>> >
>> > Ok. I will fix this.
>> >
>> > So about the static vs device tree based clock registration, what
>> > would you suggest?
>>
>> Defining the clocks statically has my preference, it would be nice to
>> hear more opinions on that though. I think on a heavily utilised SoC
>> the list of clock nodes could have grown significantly. And with
>> preprocessor support at the dt compiler (not sure if it is already
>> there) indexed clock definitions could be made more explicit.
>>
>> These are roughly our conclusions from discussing this patch series
>> with Tomasz F.
>
> Yes, as I said, I'm definitely for the single clock provider approach (aka
> imx-like approach).

Ok. Thanks for your comments. I will redo this patch series.

Thanks,
Thomas.

>
> Best regards,
> Tomasz Figa
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms
@ 2012-11-05  7:41             ` Thomas Abraham
  0 siblings, 0 replies; 36+ messages in thread
From: Thomas Abraham @ 2012-11-05  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Tomasz,

On 31 October 2012 05:02, Tomasz Figa <tomasz.figa@gmail.com> wrote:
> Hi Thomas, Sylwester,
>
> On Wednesday 31 of October 2012 00:10:24 Sylwester Nawrocki wrote:
>> >>> +/* register a samsung pll type clock */
>> >>> +void __init samsung_clk_register_pll(const char *name, const char
>> >>> **pnames, +                             struct device_node *np,
>> >>> +                             int (*set_rate)(unsigned long rate),
>> >>> +                             unsigned long (*get_rate)(unsigned long
>> >>> rate)) +{
>> >>> +     struct samsung_pll_clock *clk_pll;
>> >>> +     struct clk *clk;
>> >>> +     struct clk_init_data init;
>> >>> +     int ret;
>> >>> +
>> >>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> >>> +     if (!clk_pll) {
>> >>> +             pr_err("%s: could not allocate pll clk %s\n", __func__,
>> >>> name); +             return;
>> >>> +     }
>> >>> +
>> >>> +     init.name = name;
>> >>> +     init.ops =&samsung_pll_clock_ops;
>> >>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> >>> +     init.parent_names = pnames;
>> >>> +     init.num_parents = 1;
>> >>> +
>> >>> +     clk_pll->set_rate = set_rate;
>> >>> +     clk_pll->get_rate = get_rate;
>> >>> +     clk_pll->hw.init =&init;
>> >>> +
>> >>> +     /* register the clock */
>> >>> +     clk = clk_register(NULL,&clk_pll->hw);
>> >>> +     if (IS_ERR(clk)) {
>> >>> +             pr_err("%s: failed to register pll clock %s\n",
>> >>> __func__,
>> >>> +                             name);
>> >>> +             kfree(clk_pll);
>> >>> +             return;
>> >>> +     }
>> >>> +
>> >>> +#ifdef CONFIG_OF
>> >>> +     if (np)
>> >>> +             of_clk_add_provider(np, of_clk_src_simple_get, clk);
>> >>> +#endif
>> >>
>> >> Is it really required to do clk_register() and of_clk_add_provider()
>> >> for
>> >> each single clock ? This seems more heavy than it could be. Looking at
>> >
>> > of_clk_add_provider call for every clock instance is not really
>> > required but it does allow platform code to lookup the clock and
>> > retrieve/display the clock speed. That was the intention to add a
>> > lookup for all the clocks.
>
> I'm not really sure if displaying clock speed is really a good
> justification for increasing the list of system clocks almost by a factor
> of three. This will make clock lookup a bit heavy.
>
> You might display speed of several most important clocks directly from the
> samsung clk driver using internal data, without the need of involving
> generic clock lookup for this purpose.

Ok. But that would mean that we implment the clk_get_rate() function
for such clocks again. For example, to get the rate of the aclk_200
clock, its parent clock would have to be divided and then displayed.
But it was easier to just use the clk_get api. But yes I agree, this
is not a compelling reason to register all the clocks.

>
>>
>> Hmm, do you mean calling clk_get() with NULL 'dev' argument ?
>> It's probably not a big deal to look up the clocks root node and
>> then use of_clk_get() function to find required clock ?
>
> I believe that the intention was for it to work on non-DT platforms as
> well. However I might have misunderstood your suggestion, could you
> elaborate?
>
>> >> drivers/clk/mxs/clk-imx28.c, it registers only single clock provider
>> >> for
>> >> whole group of clocks. Also, couldn't we statically define most of the
>> >> clocks and still register them so they can be used with platforms
>> >> using
>> >> FDT ? Something along the lines of imx28 implementation
>> >> (arch/arm/boot/dts /imx28.dtsi), where a clock is specified at
>> >> consumer device node by a phandle to the clock controller node and a
>> >> clock index ?
>> >
>> > We could do it that way. I was tempted to list out all the clocks in
>> > device tree and then register them so that there is no static
>> > definition of the clocks needed. You seem to prefer not to do that. I
>> > am fine with either way, static or device tree based registration.
>>
>> Ok, it's also worth noting that clk_get() would have been more expensive
>> when there would be a need to iterate over large number of clock
>> providers. Indexed look up might be a better alternative.
>
> I'm definitely for indexed lookup. With the ability to define constants in
> device tree sources the main drawback of this solution being less readable
> now disappeared and everything left are advantages.

Ok.

>
>> Exynos SoCs have fairly complex clock tree structure, I personally do
>> find it harder to understand from a bit bulky description in form of a
>> device tree node list. Comparing to the original Samsung clock API there
>> is now more clock objects, since, e.g. single struct clk_clksrc is now
>> represented by mux, div and gate clock group, which makes things
>> slightly more complicated, i.e. there is even more clocks to be listed.
>
> If it's about readability I tend to disagree. I find device tree much more
> readable as a way of describing hardware than hardcoded data structures,
> often using complex macros to keep the definitions short.
>
>> >> Besides that, what bothers me with in the current approach is the
>> >> clock consumers being defined through one big data structure together
>> >> with the actual clocks. Not all clock objects are going to have
>> >> consumers, some resources are waisted by using flat tables of those
>> >> big data structure objects. Perhaps we could use two tables, one for
>> >> the
>> >> platform clocks and one for the consumers ? These common clock driver
>> >> is intended to cover all Samsung SoC, I would expect all samsung
>> >> sub-archs getting converted to use it eventually, with as many of them
>> >> as possible then reworked to support device tree. It's a lot of work
>> >> and is going to take some time, but it would be good to have it
>> >> planned
>> >> in advance. That said I'm not sure the common samsung clock driver in
>> >> non-dt variant would be really a temporary thing.
>> >
>> > Non-dt support in Samsung common clock driver will be maintained. But
>> > for existing Exynos4 non-dt platforms, it should be possible to
>> > convert them to completely device tree based platforms.
>>
>> OK, let's then focus on device tree support for exynos4+ SoCs. I hope we
>> could have the clocks statically defined and still freely accessible in
>> the device tree.
>
> Using the approach with indexed clocks inside a single provider would allow
> to reuse the same internal SoC-specific data for both DT and non-DT
> variants, without any data duplication. This is definitely an advantage.

Ok.

>
>> >>> +
>> >>> +#ifdef CONFIG_OF
>> >>> +/* register a samsung gate type clock instantiated from device tree
>> >>> */
>> >>> +void __init samsung_of_clk_register_gate(struct device_node *np)
>> >>> +{
>> >>> +     struct samsung_gate_clock clk_gate;
>> >>> +     const char *clk_name = np->name;
>> >>> +     const char *parent_name;
>> >>> +     u32 reg_info[2];
>> >>> +
>> >>> +     of_property_read_string(np, "clock-output-names",&clk_name);
>> >>> +     parent_name = of_clk_get_parent_name(np, 0);
>> >>> +     if (of_property_read_u32_array(np, "reg-info", reg_info, 2))
>> >>> +             pr_err("%s: invalid register info in node\n",
>> >>> __func__);
>> >>> +
>> >>> +     clk_gate.name = clk_name;
>> >>> +     clk_gate.parent_name = parent_name;
>> >>> +     clk_gate.reg = (void __iomem *)(reg_base + reg_info[0]);
>> >>> +     clk_gate.bit_idx = reg_info[1];
>> >>> +     clk_gate.dev_name = NULL;
>> >>> +     clk_gate.flags = 0;
>> >>> +     clk_gate.gate_flags = 0;
>> >>
>> >> Some clocks need CLK_SET_RATE_PARENT for the drivers to work
>> >> as before. So far it is not set for any mux, div nor gate clock.
>> >
>> > Ok. I will fix this.
>> >
>> > So about the static vs device tree based clock registration, what
>> > would you suggest?
>>
>> Defining the clocks statically has my preference, it would be nice to
>> hear more opinions on that though. I think on a heavily utilised SoC
>> the list of clock nodes could have grown significantly. And with
>> preprocessor support at the dt compiler (not sure if it is already
>> there) indexed clock definitions could be made more explicit.
>>
>> These are roughly our conclusions from discussing this patch series
>> with Tomasz F.
>
> Yes, as I said, I'm definitely for the single clock provider approach (aka
> imx-like approach).

Ok. Thanks for your comments. I will redo this patch series.

Thanks,
Thomas.

>
> Best regards,
> Tomasz Figa
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-11-14  5:14     ` Kukjin Kim
  -1 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:14 UTC (permalink / raw)
  To: 'Thomas Abraham', linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, t.figa, sylvester.nawrocki, mturquette, mturquette

Thomas Abraham wrote:
> 
> For legacy Exynos4 platforms, the available clocks are statically
> listed and then registered using the common clock framework. On device
> tree enabled exynos platfotms, the device tree is searched and all
> clock nodes found are registered. Support for Exynos4210 and
> Exynos4x12 platforms is included.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  drivers/clk/samsung/Makefile      |    1 +
>  drivers/clk/samsung/clk-exynos4.c |  647
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 648 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/clk-exynos4.c

[...]

> +
> +/* base address of io remapped clock controller register space */
> +static	void __iomem *clk_base;
> +

I didn't look at the full details. BTW, you know, clock naming is very
important and there are some comments about that below...

> +static const char *pll_parent_names[] __initdata = { "fin_pll" };

Why is this only 'xxx_parent_names'? not just 'xxx_parents' like others?

> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
> +static const char *mout_apll_parents[] __initdata = { "fin_pll",
> "fout_apll", };

According to original naming, how about clk_src_apll here?

+static const char *clk_src_apll[] __initdata = { "fin_pll", "fout_apll", };

> +static const char *mout_mpll_parents[] __initdata = { "fin_pll",

clk_src_mpll?

> "fout_mpll", };
> +static const char *mout_epll_parents[] __initdata = { "fin_pll",

clk_src_epll?

> "fout_epll", };
> +
> +static const char *sclk_ampll_parents[] __initdata = {

clk_src_aclk?

> +		"mout_mpll", "sclk_apll", };
> +
> +static const char *sclk_evpll_parents[] __initdata = {



> +		"mout_epll", "mout_vpll", };
> +
> +static const char *mout_core_parents[] __initdata = {

clk_src_core?

Hmm... most of the 'sources' is from out of MUX so mout is not required?...

> +		"mout_apll", "mout_mpll", };
> +
> +static const char *mout_mfc_parents[] __initdata = {
> +		"mout_mfc0", "mout_mfc1", };

Should be following?

+static const char *clk_src_mfc0[] __initdata = {"mout_mpll", "sclk_apll",
};
+static const char *clk_src_mfc1[] __initdata = {"mout_epll", "sclk_vpll",
};

> +
> +static const char *mout_dac_parents[] __initdata = {
> +		"mout_vpll", "sclk_hdmiphy", };

sclk_vpll?

+static const char *clk_src_sclk_dac[] __initdata = {"sclk_vpll",
"sclk_hdmiphy", };


> +
> +static const char *mout_hdmi_parents[] __initdata = {

clk_src_sclk_hdmi?

> +		"sclk_pixel", "sclk_hdmiphy", };
> +
> +static const char *mout_mixer_parents[] __initdata = {

clk_src_sclk_mixer?

> +		"sclk_dac", "sclk_hdmi", };
> +
> +static const char *group1_parents[] __initdata = {

According to original clock-exynos4.c, just 'group_parents' not
'group1_parents'?

> +		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",

Should be 'sclk_hdmi27m' instead of 'sclk_hdmi24m'
+		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",

> +		"none", "sclk_hdmiphy", "mout_mpll", "mout_epll",

Missed 'sclk_usbphy1'?
+		"sclk_usbphy1", "sclk_hdmiphy", "mout_mpll", "mout_epll",

> +		"mout_vpll" };
> +
> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
> +	FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
> +	FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),

Well, above clock rate depends on board and it means it is not a fixed
value.

> +	FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
> +	FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
> +	FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),

Missed sclk_hdmi27m?
+	FRATE_CLK(NULL, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),

> +};
> +
> +static struct samsung_mux_clock exynos4_mux_clks[] = {

[...]

> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {

[...]

> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {

[...]

> +	clk = clk_get(NULL, "fout_apll");
> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_apll);

+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_apll_get_rate);

> +	clk = clk_get(NULL, "fout_mpll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_mpll_get_rate);

> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_mpll);


> +	clk = clk_get(NULL, "fout_epll");
> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_epll);

+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_epll_get_rate);

> +	clk = clk_get(NULL, "fout_vpll");
> +	samsung_pll_clk_set_cb(clk, exynos4210_vpll_set_rate,
> +				exynos4210_get_rate_mpll);

mpll? Should be vpll?

+				exynos4210_vpll_get_rate); ???

[...]

> +	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_apll);

+		NULL, exynos4210_apll_get_rate);

> +	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_mpll);

+		NULL, exynos4210_mpll_get_rate);

> +	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_epll);

+		NULL, exynos4210_epll_get_rate);

> +	samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
> +		NULL, exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);


+		NULL, exynos4210_vpll_set_rate, exynos4210_vpll_get_rate);

[...]

> +static unsigned long exynos4x12_get_rate_apll(unsigned long xtal_rate)

exynos4x12_apll_get_rate()

> +{
> +	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
> +}
> +
> +static unsigned long exynos4x12_get_rate_mpll(unsigned long xtal_rate)

exynos4x12_mpll_get_rate()

> +{
> +	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
> +}
> +
> +static unsigned long exynos4x12_get_rate_epll(unsigned long xtal_rate)

exynos4x12_epll_get_rate()

> +{
> +	return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
> +		__raw_readl(EXYNOS4_EPLL_CON1));
> +}
> +
> +static unsigned long exynos4x12_get_rate_vpll(unsigned long vpllsrc_rate)

exynos4x12_vpll_get_rate()

> +{
> +	return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
> +		__raw_readl(EXYNOS4_VPLL_CON1));
> +}
> +
> +/* Exynos4x12 specific clock registeration */
> +void __init exynos4x12_clk_init(void)
> +{
> +	exynos4_clk_init();
> +
> +	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_apll);

+		NULL, exynos4x12_apll_get_rate);

> +	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_mpll);

+		NULL, exynos4x12_mpll_get_rate);

> +	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_epll);

+		NULL, exynos4x12_epll_get_rate);

> +	samsung_clk_register_pll("fout_vpll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_vpll);

+		NULL, exynos4x12_vpll_get_rate);

> +
> +	samsung_clk_register_mux(exynos4x12_mux_clks,
> +			ARRAY_SIZE(exynos4x12_mux_clks));
> +
> +	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",

pr_info("EXYNOS4X12:...

> +		_get_rate("fout_apll"), _get_rate("fout_mpll"),
> +		_get_rate("fout_epll"), _get_rate("fout_vpll"));
> +
> +	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"

pr_info("EXYNOS4X12:...

> +		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
> +		_get_rate("aclk_200"), _get_rate("aclk_100"),
> +		_get_rate("aclk_160"), _get_rate("aclk_133"));
> +}
> --
> 1.7.5.4


Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework
@ 2012-11-14  5:14     ` Kukjin Kim
  0 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:14 UTC (permalink / raw)
  To: linux-arm-kernel

Thomas Abraham wrote:
> 
> For legacy Exynos4 platforms, the available clocks are statically
> listed and then registered using the common clock framework. On device
> tree enabled exynos platfotms, the device tree is searched and all
> clock nodes found are registered. Support for Exynos4210 and
> Exynos4x12 platforms is included.
> 
> Cc: Mike Turquette <mturquette@ti.com>
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  drivers/clk/samsung/Makefile      |    1 +
>  drivers/clk/samsung/clk-exynos4.c |  647
> +++++++++++++++++++++++++++++++++++++
>  2 files changed, 648 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/samsung/clk-exynos4.c

[...]

> +
> +/* base address of io remapped clock controller register space */
> +static	void __iomem *clk_base;
> +

I didn't look at the full details. BTW, you know, clock naming is very
important and there are some comments about that below...

> +static const char *pll_parent_names[] __initdata = { "fin_pll" };

Why is this only 'xxx_parent_names'? not just 'xxx_parents' like others?

> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
> +static const char *mout_apll_parents[] __initdata = { "fin_pll",
> "fout_apll", };

According to original naming, how about clk_src_apll here?

+static const char *clk_src_apll[] __initdata = { "fin_pll", "fout_apll", };

> +static const char *mout_mpll_parents[] __initdata = { "fin_pll",

clk_src_mpll?

> "fout_mpll", };
> +static const char *mout_epll_parents[] __initdata = { "fin_pll",

clk_src_epll?

> "fout_epll", };
> +
> +static const char *sclk_ampll_parents[] __initdata = {

clk_src_aclk?

> +		"mout_mpll", "sclk_apll", };
> +
> +static const char *sclk_evpll_parents[] __initdata = {



> +		"mout_epll", "mout_vpll", };
> +
> +static const char *mout_core_parents[] __initdata = {

clk_src_core?

Hmm... most of the 'sources' is from out of MUX so mout is not required?...

> +		"mout_apll", "mout_mpll", };
> +
> +static const char *mout_mfc_parents[] __initdata = {
> +		"mout_mfc0", "mout_mfc1", };

Should be following?

+static const char *clk_src_mfc0[] __initdata = {"mout_mpll", "sclk_apll",
};
+static const char *clk_src_mfc1[] __initdata = {"mout_epll", "sclk_vpll",
};

> +
> +static const char *mout_dac_parents[] __initdata = {
> +		"mout_vpll", "sclk_hdmiphy", };

sclk_vpll?

+static const char *clk_src_sclk_dac[] __initdata = {"sclk_vpll",
"sclk_hdmiphy", };


> +
> +static const char *mout_hdmi_parents[] __initdata = {

clk_src_sclk_hdmi?

> +		"sclk_pixel", "sclk_hdmiphy", };
> +
> +static const char *mout_mixer_parents[] __initdata = {

clk_src_sclk_mixer?

> +		"sclk_dac", "sclk_hdmi", };
> +
> +static const char *group1_parents[] __initdata = {

According to original clock-exynos4.c, just 'group_parents' not
'group1_parents'?

> +		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",

Should be 'sclk_hdmi27m' instead of 'sclk_hdmi24m'
+		"xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",

> +		"none", "sclk_hdmiphy", "mout_mpll", "mout_epll",

Missed 'sclk_usbphy1'?
+		"sclk_usbphy1", "sclk_hdmiphy", "mout_mpll", "mout_epll",

> +		"mout_vpll" };
> +
> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
> +	FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
> +	FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),

Well, above clock rate depends on board and it means it is not a fixed
value.

> +	FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
> +	FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
> +	FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),

Missed sclk_hdmi27m?
+	FRATE_CLK(NULL, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),

> +};
> +
> +static struct samsung_mux_clock exynos4_mux_clks[] = {

[...]

> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {

[...]

> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {

[...]

> +	clk = clk_get(NULL, "fout_apll");
> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_apll);

+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_apll_get_rate);

> +	clk = clk_get(NULL, "fout_mpll");
+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_mpll_get_rate);

> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_mpll);


> +	clk = clk_get(NULL, "fout_epll");
> +	samsung_pll_clk_set_cb(clk, NULL, exynos4210_get_rate_epll);

+	samsung_pll_clk_set_cb(clk, NULL, exynos4210_epll_get_rate);

> +	clk = clk_get(NULL, "fout_vpll");
> +	samsung_pll_clk_set_cb(clk, exynos4210_vpll_set_rate,
> +				exynos4210_get_rate_mpll);

mpll? Should be vpll?

+				exynos4210_vpll_get_rate); ???

[...]

> +	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_apll);

+		NULL, exynos4210_apll_get_rate);

> +	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_mpll);

+		NULL, exynos4210_mpll_get_rate);

> +	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
> +		NULL, exynos4210_get_rate_epll);

+		NULL, exynos4210_epll_get_rate);

> +	samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
> +		NULL, exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);


+		NULL, exynos4210_vpll_set_rate, exynos4210_vpll_get_rate);

[...]

> +static unsigned long exynos4x12_get_rate_apll(unsigned long xtal_rate)

exynos4x12_apll_get_rate()

> +{
> +	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
> +}
> +
> +static unsigned long exynos4x12_get_rate_mpll(unsigned long xtal_rate)

exynos4x12_mpll_get_rate()

> +{
> +	return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
> +}
> +
> +static unsigned long exynos4x12_get_rate_epll(unsigned long xtal_rate)

exynos4x12_epll_get_rate()

> +{
> +	return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
> +		__raw_readl(EXYNOS4_EPLL_CON1));
> +}
> +
> +static unsigned long exynos4x12_get_rate_vpll(unsigned long vpllsrc_rate)

exynos4x12_vpll_get_rate()

> +{
> +	return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
> +		__raw_readl(EXYNOS4_VPLL_CON1));
> +}
> +
> +/* Exynos4x12 specific clock registeration */
> +void __init exynos4x12_clk_init(void)
> +{
> +	exynos4_clk_init();
> +
> +	samsung_clk_register_pll("fout_apll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_apll);

+		NULL, exynos4x12_apll_get_rate);

> +	samsung_clk_register_pll("fout_mpll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_mpll);

+		NULL, exynos4x12_mpll_get_rate);

> +	samsung_clk_register_pll("fout_epll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_epll);

+		NULL, exynos4x12_epll_get_rate);

> +	samsung_clk_register_pll("fout_vpll", pll_parent_names, NULL,
> +		NULL, exynos4x12_get_rate_vpll);

+		NULL, exynos4x12_vpll_get_rate);

> +
> +	samsung_clk_register_mux(exynos4x12_mux_clks,
> +			ARRAY_SIZE(exynos4x12_mux_clks));
> +
> +	pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",

pr_info("EXYNOS4X12:...

> +		_get_rate("fout_apll"), _get_rate("fout_mpll"),
> +		_get_rate("fout_epll"), _get_rate("fout_vpll"));
> +
> +	pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"

pr_info("EXYNOS4X12:...

> +		"         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
> +		_get_rate("aclk_200"), _get_rate("aclk_100"),
> +		_get_rate("aclk_160"), _get_rate("aclk_133"));
> +}
> --
> 1.7.5.4


Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-11-14  5:25     ` Kukjin Kim
  -1 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:25 UTC (permalink / raw)
  To: 'Thomas Abraham', linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, t.figa, sylvester.nawrocki, mturquette, mturquette

Thomas Abraham wrote:
> 
> Remove Samsung specific clock support in Exynos4 and migrate to using
> common clock framework.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  arch/arm/mach-exynos/Kconfig               |    1 +
>  arch/arm/mach-exynos/Makefile              |    3 -
>  arch/arm/mach-exynos/clock-exynos4.c       | 1603
-------------------------
> ---
>  arch/arm/mach-exynos/clock-exynos4.h       |   35 -
>  arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
>  arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
>  arch/arm/mach-exynos/common.c              |   22 +-
>  arch/arm/mach-exynos/common.h              |    3 +
>  arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
>  arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
>  arch/arm/mach-exynos/mach-nuri.c           |    1 -
>  arch/arm/mach-exynos/mach-origen.c         |    1 -
>  arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
>  arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
>  arch/arm/mach-exynos/mach-universal_c210.c |    1 -
>  arch/arm/mach-exynos/mct.c                 |   11 +-
>  arch/arm/plat-samsung/Kconfig              |    4 +-
>  17 files changed, 18 insertions(+), 2051 deletions(-)
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

I think, would be better to us if we could keep this clock stuff with common
clock for a moment, e.g. 3.8. In addition, the clock stuff is still updating
at this moment so we need some time to move on common clock framework
entirely. Of course, I have no objection to support common clock on new SoC
such as exynos5440 :-)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
@ 2012-11-14  5:25     ` Kukjin Kim
  0 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:25 UTC (permalink / raw)
  To: linux-arm-kernel

Thomas Abraham wrote:
> 
> Remove Samsung specific clock support in Exynos4 and migrate to using
> common clock framework.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
>  arch/arm/mach-exynos/Kconfig               |    1 +
>  arch/arm/mach-exynos/Makefile              |    3 -
>  arch/arm/mach-exynos/clock-exynos4.c       | 1603
-------------------------
> ---
>  arch/arm/mach-exynos/clock-exynos4.h       |   35 -
>  arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
>  arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
>  arch/arm/mach-exynos/common.c              |   22 +-
>  arch/arm/mach-exynos/common.h              |    3 +
>  arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
>  arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
>  arch/arm/mach-exynos/mach-nuri.c           |    1 -
>  arch/arm/mach-exynos/mach-origen.c         |    1 -
>  arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
>  arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
>  arch/arm/mach-exynos/mach-universal_c210.c |    1 -
>  arch/arm/mach-exynos/mct.c                 |   11 +-
>  arch/arm/plat-samsung/Kconfig              |    4 +-
>  17 files changed, 18 insertions(+), 2051 deletions(-)
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.c
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
>  delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c

I think, would be better to us if we could keep this clock stuff with common
clock for a moment, e.g. 3.8. In addition, the clock stuff is still updating
at this moment so we need some time to move on common clock framework
entirely. Of course, I have no objection to support common clock on new SoC
such as exynos5440 :-)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* RE: [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
  2012-10-07 17:10   ` Thomas Abraham
@ 2012-11-14  5:26     ` Kukjin Kim
  -1 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:26 UTC (permalink / raw)
  To: 'Kukjin Kim', 'Thomas Abraham',
	linux-arm-kernel, linux-samsung-soc
  Cc: devicetree-discuss, t.figa, sylvester.nawrocki, mturquette, mturquette

Kukjin Kim wrote:

> Thomas Abraham wrote:
> >
> > Remove Samsung specific clock support in Exynos4 and migrate to using
> > common clock framework.
> >
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> > ---
> >  arch/arm/mach-exynos/Kconfig               |    1 +
> >  arch/arm/mach-exynos/Makefile              |    3 -
> >  arch/arm/mach-exynos/clock-exynos4.c       | 1603
-----------------------
> --
> > ---
> >  arch/arm/mach-exynos/clock-exynos4.h       |   35 -
> >  arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
> >  arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
> >  arch/arm/mach-exynos/common.c              |   22 +-
> >  arch/arm/mach-exynos/common.h              |    3 +
> >  arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
> >  arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
> >  arch/arm/mach-exynos/mach-nuri.c           |    1 -
> >  arch/arm/mach-exynos/mach-origen.c         |    1 -
> >  arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
> >  arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
> >  arch/arm/mach-exynos/mach-universal_c210.c |    1 -
> >  arch/arm/mach-exynos/mct.c                 |   11 +-
> >  arch/arm/plat-samsung/Kconfig              |    4 +-
> >  17 files changed, 18 insertions(+), 2051 deletions(-)  delete mode
> > 100644 arch/arm/mach-exynos/clock-exynos4.c
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
> 
> I think, would be better to us if we could keep this clock stuff with
> common clock for a moment, e.g. 3.8. In addition, the clock stuff is still
> updating at this moment so we need some time to move on common clock
> framework entirely. Of course, I have no objection to support common clock
> on new SoC such as exynos5440 :-)
> 
Oops, I'm resending because of e-mail client problem.

> Thanks.
> 
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer, SW Solution
> Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework
@ 2012-11-14  5:26     ` Kukjin Kim
  0 siblings, 0 replies; 36+ messages in thread
From: Kukjin Kim @ 2012-11-14  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

Kukjin Kim wrote:

> Thomas Abraham wrote:
> >
> > Remove Samsung specific clock support in Exynos4 and migrate to using
> > common clock framework.
> >
> > Cc: Kukjin Kim <kgene.kim@samsung.com>
> > Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> > ---
> >  arch/arm/mach-exynos/Kconfig               |    1 +
> >  arch/arm/mach-exynos/Makefile              |    3 -
> >  arch/arm/mach-exynos/clock-exynos4.c       | 1603
-----------------------
> --
> > ---
> >  arch/arm/mach-exynos/clock-exynos4.h       |   35 -
> >  arch/arm/mach-exynos/clock-exynos4210.c    |  188 ----
> >  arch/arm/mach-exynos/clock-exynos4212.c    |  192 ----
> >  arch/arm/mach-exynos/common.c              |   22 +-
> >  arch/arm/mach-exynos/common.h              |    3 +
> >  arch/arm/mach-exynos/mach-armlex4210.c     |    1 -
> >  arch/arm/mach-exynos/mach-exynos4-dt.c     |    1 -
> >  arch/arm/mach-exynos/mach-nuri.c           |    1 -
> >  arch/arm/mach-exynos/mach-origen.c         |    1 -
> >  arch/arm/mach-exynos/mach-smdk4x12.c       |    1 -
> >  arch/arm/mach-exynos/mach-smdkv310.c       |    1 -
> >  arch/arm/mach-exynos/mach-universal_c210.c |    1 -
> >  arch/arm/mach-exynos/mct.c                 |   11 +-
> >  arch/arm/plat-samsung/Kconfig              |    4 +-
> >  17 files changed, 18 insertions(+), 2051 deletions(-)  delete mode
> > 100644 arch/arm/mach-exynos/clock-exynos4.c
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4.h
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4210.c
> >  delete mode 100644 arch/arm/mach-exynos/clock-exynos4212.c
> 
> I think, would be better to us if we could keep this clock stuff with
> common clock for a moment, e.g. 3.8. In addition, the clock stuff is still
> updating at this moment so we need some time to move on common clock
> framework entirely. Of course, I have no objection to support common clock
> on new SoC such as exynos5440 :-)
> 
Oops, I'm resending because of e-mail client problem.

> Thanks.
> 
> Best regards,
> Kgene.
> --
> Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer, SW Solution
> Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2012-11-14  5:26 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-07 17:10 [PATCH v2 0/5] clk: exynos4: migrate to common clock framework Thomas Abraham
2012-10-07 17:10 ` Thomas Abraham
2012-10-07 17:10 ` [PATCH v2 1/5] clk: samsung: add common clock framework support for Samsung platforms Thomas Abraham
2012-10-07 17:10   ` Thomas Abraham
2012-10-22 15:55   ` Sylwester Nawrocki
2012-10-22 15:55     ` Sylwester Nawrocki
2012-10-29 10:09     ` Thomas Abraham
2012-10-29 10:09       ` Thomas Abraham
2012-10-30 23:10       ` Sylwester Nawrocki
2012-10-30 23:10         ` Sylwester Nawrocki
2012-10-30 23:32         ` Tomasz Figa
2012-10-30 23:32           ` Tomasz Figa
2012-11-05  7:41           ` Thomas Abraham
2012-11-05  7:41             ` Thomas Abraham
2012-11-05  7:36         ` Thomas Abraham
2012-11-05  7:36           ` Thomas Abraham
2012-10-30 16:30   ` Mike Turquette
2012-10-30 16:30     ` Mike Turquette
2012-11-05  7:22     ` Thomas Abraham
2012-11-05  7:22       ` Thomas Abraham
2012-10-07 17:10 ` [PATCH v2 2/5] clk: exynos4: register clocks using common clock framework Thomas Abraham
2012-10-07 17:10   ` Thomas Abraham
2012-10-08  7:54   ` Tomasz Figa
2012-10-08  7:54     ` Tomasz Figa
2012-11-14  5:14   ` Kukjin Kim
2012-11-14  5:14     ` Kukjin Kim
2012-10-07 17:10 ` [PATCH v2 3/5] ARM: dts: Add Exynos4210 clock nodes Thomas Abraham
2012-10-07 17:10   ` Thomas Abraham
2012-10-07 17:10 ` [PATCH v2 4/5] ARM: dts: list the clock providers for serial ports Thomas Abraham
2012-10-07 17:10   ` Thomas Abraham
2012-10-07 17:10 ` [PATCH v2 5/5] ARM: Exynos4: Migrate clock support to common clock framework Thomas Abraham
2012-10-07 17:10   ` Thomas Abraham
2012-11-14  5:25   ` Kukjin Kim
2012-11-14  5:25     ` Kukjin Kim
2012-11-14  5:26   ` Kukjin Kim
2012-11-14  5:26     ` Kukjin Kim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.